[net.micro.atari16] Xbtimer usage example

bammi@cwruecmp.UUCP (Jwahar R. Bammi) (07/21/86)

Here is the Xbtimer sample program promised in an earlier message.
Packed in shar format.
-----
#!/bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #!/bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	xbtimer.c
# This archive created: Mon Jul 21 01:22:10 1986
# By:	Jwahar R. Bammi ()
export PATH; PATH=/bin:$PATH
echo shar: extracting "'xbtimer.c'" '(4181 characters)'
if test -f 'xbtimer.c'
then
	echo shar: over-writing existing file "'xbtimer.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'xbtimer.c'
X#include <osbind.h>
X#include <stdio.h>
X
X#define VOID int
X
X
X/*
X * Xbtimer.c
X *	Sample code that demonstrates the use of TIMER A on the 68901 MFP
X *	Also demonstrates  how to take over the process terminate interrupt.
X *
X *	WHAT:
X *
X *	The program begins by installing the address of the function
X *	'terminate' into the exception vector 0x102 (Process terminate
X *	exception, saving its old pointer. It then starts up Timer A on
X *	the MFP, configured to interrupt the function 'count' at 48Hz. The
X *	main loop continuously displays the value of a counter, that the
X *	function 'count' increments. On hitting CTRL-C, the 'terminate' function
X *	is called to handle the termination. It stops Timer A, then
X *	restores the origonal process terminate vector and
X *	returns (to the default system Interrupt Service Routine).
X *
X *	HOW:
X *	The timers on the MFP are controlled by a 2.4576 Mhz xtal (Yes the
X *	Atari Internals book is once again wrong!). Using
X *	timer 'a' in the delay mode with a prescale set at 200 (ie. by
X *	setting the timer 'a' control register to 7)
X *	gives you a 12288 Hz counter (2457600/200). Using a count
X *	of 256 (ie. by loading the timer 'a' data register with 0)
X *	you get an interrupt frequency of 48 Hz (12288/256). For other
X *	values for the control & data registers see the 68901 manual
X *	available for free by calling Motorola, or see the Atari Internals
X *	book.
X *
X *	The timer interrupt is handled by the function 'count'. This function
X *	increments the long counter, then clears Bit 5 of the ISRA (In
X *	Service Register A), and then returns from the exception by doing
X *	an RTE. NOTES: In the ST the 68901 always operates in the
X *	Software End of Interrupt Mode (ie. bit 3 of the Vector Register VR
X *	is always set). In this mode the ISR bit of the ISRA is automatically
X *	set when an interrupt occurs and the processor requests the interrupt
X *	vector. (The ISR bit corresponding to the Timer A interrupt is bit 5
X *	of the ISRA). As long as the bit is set, that interrupt and any other
X *	interrupts of lower priority cannot occur. Once the bit is cleared
X *	the same interrupt or any lower priority interrupts can once again
X *	occur. This is why it is important to clear BIT 5 of the ISRA before
X *	performing the RTE. The address of the ISRA register is 0xfffA0F
X *
X *
X *	Compile and link with gemstart.o, osbind.o, gemlib,  libf
X *
X *
X *	Author:
X *		Comments/Questions etc to
X *		Jwahar R. Bammi
X *		.....!decvax!cwruecmp!bammi
X *		bammi@case.CSNET
X *		bammi%case@csnet-relay.ARPA
X *
X */
X
X/* Static globals */
X
X/* Internal software ticks counter */
Xlong counter = 0L;
X
X/* Saved Process terminate vector */
XVOID (*t_handle)();
X
X/* My process terminate handler */
XVOID terminate()
X{
X	VOID count();
X
X	/* Shut of Timer - by writing 0 to the control register of Timer A */
X	Xbtimer(0, 0, 0, count);
X	/* Clear bit 5 of ISRA just in case it was set */
X	asm("bclr.b #5,$fffa0f");
X
X	/* Restore the old process terminate vector */
X	Setexc(0x0102, t_handle);
X
X	/*
X	 * by doing an RTS here we return to the systems default
X	 * Interrupt service routine that dispatched the ^C interrupt
X	 * to this routine. It will take care of doing the RTE
X	 */
X
X	/*
X	 * Note that we could have done an unlk R4 to restore the stack frame
X	 * and then jumped to the origonal handler too. (saved in t_handle)
X	 *
X	 */
X}
X
X/* MFP Timer A interrupt handler */
XVOID count()
X{
X	/* Increment counter */
X	counter++;
X
X	/* Restore stack frame */
X	asm("unlk R14");
X
X	/* clear bit 5 of ISRA on the MFP */
X	asm("bclr.b #5,$fffa0f");
X
X	/* Return from exception */
X	asm("rte");
X}
X	
X
X/* Main */
Xmain()
X{
X	char *save_ssp;		/* Saved System Stack Pointer */
X	
X	/* Get into Supervisor mode */
X	save_ssp = Super(0L);
X
X	/* Get current Process Terminate vector */
X	t_handle = Setexc(0x0102, -1L);
X
X	/* Set up our own Process Terminate Handler */
X	Setexc(0x0102, terminate);
X
X	/* Start the timer */
X	Xbtimer(0, 7, 0, count);
X
X	/* Get out of Supervisor mode */
X	Super(save_ssp);
X
X	/* Continuously display counter */
X
X	while(1 == 1)
X	{
X		char buf[12];
X
X		sprintf(buf,"%09ld\r",counter);
X		Cconws(buf);
X	}
X
X	/* If it gets here .. */
X	Cconws("\r\nHeh! How did I end up here?\r\n");
X}
SHAR_EOF
if test 4181 -ne "`wc -c 'xbtimer.c'`"
then
	echo shar: error transmitting "'xbtimer.c'" '(should have been 4181 characters)'
fi
#	End of shell archive
exit 0


-- 
					Jwahar R. Bammi
			       Usenet:  .....!decvax!cwruecmp!bammi
			        CSnet:  bammi@case
				 Arpa:  bammi%case@csnet-relay
			   CompuServe:  71515,155