[comp.sys.apple2] heartbeat interrupts

acmfiu@serss0.fiu.edu (ACMFIU) (01/13/91)

I have the following inline asm function to handle HeartBeat interrupts. my
main purpose for using it is to catch keypresses and pause control of the
program in progess. Then, I just wait for another keypress. Also, if the
user presses oa-period, then the program should immediately end, regardless
of where it is.

However, when i oa-period 3/4 times, the computer crashes. can anyone
suggest a better (i.e. WORKING) solution to my problem.


asm void
check_key (void)
{
  dcl 0
 count: dcw 10
  dcw 0xa55a

  phb
  phk
  plb
  php
  rep #0x30
  lda #10
  sta count

  sep #0x20
  lda >0xe0c000
  bpl end
  cmp #0xae
  bne wait
  lda >0xe0c025
  and #0x80
  beq wait
  rep #0x20
  lda >0xe0c010
  jsl raise_signal
  bra end
 wait: lda >0xe0c010
 rdkey:  lda >0xe0c000
  bpl rdkey
  lda >0xe0c010
 end: rep #0x20
  plp
  plb
  dcb 0x6b
}

void
raise_signal (void)
{
        raise (SIGTERM);
}

void
bye (int sig)
{
	fclose (global_file);

	DelHeartBeat (check_key);
	exit (1);
}

int
main (int argc, char **argv)
{
	signal (SIGTERM, bye);
	SetHeartBeat (check_key);

	<blah>
}

-----------------------

albert chin ... acmfiu@fiu.edu

AABENSON@MTUS5.BITNET (01/13/91)

Well, I'm assuming you're using Orca or APW C?  Why not make a tool call to
SetVector (I think that's the name) to patch "keyboard interrupts," and then
make another call to IntSource to enable "Keyboard Interrupts."  I put this
in quotation marks, because there isn't such a thing, but it is simulated
by the firmware by using the Heartbeat Queue and VBL interrupts.

- Andrew.  (aabenson@balance.cs.mtu.edu     or     aabenson@mtu.edu)

acmfiu@serss0.fiu.edu (ACMFIU) (01/18/91)

Awhile back I posted a message concerning HeartBeat interrupts. I wanted to,
when a key was pressed, pause my program and, if oa-period was pressed,
terminate the program. Thanks to Tim Meekins and Jawaid Bazyar for their
responses. I have come up with the following code, although their remains to
be one bug.

int
main (void)
{
	char *kybdvector;
	<blah>

	EMStartup (blah);
	kybdvector = GetVector (kybdIntHnd);
	SetVector (kybdIntHnd, check_key);

	<blah>

	bye ();
}

void
bye (void)
{
	SetVector (kybdIntHnd, kybdvector);
	EMShutDown ();
	Close (0);		/* close all files */
	exit (1);
}

asm void
check_key (void)
{
		rep	#$30			/* just to make sure */
		php
		phb
		phk
		plb
		jsl	incbusyflag

		lda	$e0c000
		bpl	end
		cmp	#"."
		bne	wait
		lda	$<wherever oa status is>
		cmp	#<is oa key pressed>
		bne	wait

		pha				/* space for result */
		pushlong #bye
		_SchAddTask
		pla				/* i KNOW it worked */
		bra	end

	wait	pha
		pushlong #pause
		_SchAddTask
		pla

	end	plb
		plp
		jsl	decbusyflag
		rtl
}

asm void
pause (void)
{
		lda	$e0c000
	wait	lda	$e0c010
		bpl	wait
		lda	$e0c000
		rtl
}

What I basically do is startup the Event Manager which automatically makes
keyboard interrupts available (ala IntSource) and then I modify the interrupt
handler that the Event Manger uses for the keyboard interrupts to my own.
When I run my program, pressing any key appropriately causes the program to
pause, then I press the key again and it resumes execution. The problem comes
with oa-period. When I press it, the program ends and I'm back in the shell.
however, when I run it again, NO key I press does anything. It's like the
keyboard interrupts were disabled. If I press "AAAAAAAAAAAAAAA", they will
appear on the command line AFTER the program is finished executing.

My question is, how in the world do keyboard interrupts get disabled from
the above code (the above code is not 100% correct but you should get the 
idea). Since I get the keyboard interrupt vector used by the Event Manager
and restore it before I EMShutDown(), how does it get corrupted?

I also used the above code without the Event Manager. Using the Misc Tool
Set you can do it via:
	IntSource (kybdEnable);
	kybdvector = GetVector (kybdIntHnd);
	SetVector (kybdIntHnd, check_key);
	<foo>
	SetVector (kybdIntHnd, kybdvector);
	exit (0);

Any ideas?

albert