**************************************************************************
* RTI Multitasking Example with TOI     EEL-4744          EMS & AAA *
* Combines RTI Multitasking example with earlier TOI example
**************************************************************************
********************************************************
* MultiTasking using Real-Time Interrupt
*		Port B	Port C
* Process#1:	  $0F	  $00
* Process#2:	  $00	  $F0
* Switching between Processes will occur
* 	EVERY 8.192 msecs (=16k=16384=$4000 E-cycles)
* Also REVERSE ALL PORTC BITS EVERY 262.14 MILLISECONDS (TOF)
* USE TIMER OVERFLOW AS TIME BASE & Extend the Timer with a 16-bit Extension
* USE 8.0 MHZ CRYSTAL FOR 68HCll CLOCK
*****************************************************************************************************************
* SYMBOL DEFINITIONS
********************************************************
* 68HCll REGISTERS
REGS	EQU	$1000	;Base Address of Internal Registers
PORTC	EQU	$03	;I/O PORT C REGISTER
PORTB	EQU	$04	;Output-only PORT B REGISTER
DDRC	EQU	$07	;DATA DIRECTION REGISTER C
TMSK2	EQU	$24	;TIMER MASK REGISTER
TFLG2	EQU	$25	;TIMER FLAG REGISTER
PACTL	EQU	$26	;PULSE ACCUMULATOR CONTROL REG
* I/O Patterns
IOPAT	EQU	$FF	;I/O PATTERN, 0=IN 1=OUT
OUTPAT1	EQU	$0F	;OUTPUT Pattern for PORTB
OUTPAT2	EQU	$F0	;OUTPUT Pattern for PORTC
* MASKS
BIT7	EQU	%10000000
INV7	EQU	%01111111	
BIT6	EQU	%01000000
INV6	EQU	%10111111
BIT1	EQU	%00000010
BIT0	EQU	%00000001
* Others
StSize	EQU	$40
*
********************************************************
* DATA SECTION
********************************************************
	ORG	$0001
PID	RMB	1	;Process ID
SP1	RMB	2	;Stack Pointer for Process#1
SP2	RMB	2	;Stack Pointer for Process#2
	ORG	$0010
TCNTEXT	FDB	$0000	
	ORG	$0100
Stack1	RMB	StSize	;Stack for Process#1
Stack2	RMB	StSize	;Stack for Process#2
*
	ORG	$FFDE	;TOI INTERRUPT VECTOR
     	FDB	TOISR
     	ORG 	$FFF0	;RTI INTERRUPT VECTOR
     	FDB     RTISR
********************************************************
* MAIN PROGRAM
********************************************************
     	ORG 	$B600
*-----------------------------------------------------
* INITIALIZATION
*-----------------------------------------------------
	LDX	#REGS
*
* INITIALIZE TIMER SPEED & TIMER OVERFLOW INTERRUPT 
* (Note: This MUST occur within 64 E-clocks of reset)
	BSET	TMSK2,X BIT1	;PR1:PR0=10 FOR 262.1 msec; 11 for 524.3 ms
	BCLR	TMSK2,X BIT0	;PR1:PRO=01 FOR 131.1 msec; 00 for 32.77 ms
	BSET	TMSK2,X BIT7	;..ENABLE TOI INTERRUPT
*
* Initialize TCNT Extension
        LDY     #0
	STY	TCNTEXT
*
* INITIALIZE PORT C, SET UP PORTC INs AND OUTs
     	LDAA 	#IOPAT
	STAA 	DDRC,X  ;ALL OUTPUTS
*
* INITIALIZE REAL TIME INTERRUPT, SET INTERRUPT RATE TO 8.19 msec
*     RTR1:RTR0 = 01
	BCLR	PACTL,X BIT1
	BSET	PACTL,X BIT0
*
*   ENABLE RTI INTERRUPT
	BSET	TMSK2,X BIT6	;..ENABLE RTI INTERRUPT
*
* Initialize Stack Pointers for each Process
	LDX	#Stack1+StSize-1
	STX	SP1
	LDX	#Stack2+StSize-1
	STX	SP2
*
* Assume the Previous PID was 2, Initialize Stack for Process#2
	LDS	SP2
*
*     Initialize the Return Point
	LDX	#PS2
	PSHX
*
*     Initialize all the Internal Registers for Process#2
	LDY	#0	;IY
	PSHY
	LDX	#0	;IX
	PSHX
	CLRA		;Accumulator A
	PSHA
	CLRB		;Accumulator B
	PSHB
	ORAA	#BIT6	;CCR with X = 1 (disable)
	PSHA		;     and I = 0 (enable) 
	STS	SP2	;SP ==> SP2
*
* Initialize the Current PID as Process#1
	LDAA	#1
	STAA	PID
	LDS  	SP1
*
* TURN ON INTERRUPT SYSTEM
	CLI
*
*---------------------------------------------------
* Execute Process #1
*----------------------------------------------------
	JMP 	PS1
*
********************************************************
* Real-Time Interrupt Service Routine
********************************************************
	ORG	$B700
*------------------------------------------------------
* INTERRUPT POLLING CHAIN
*------------------------------------------------------
* INTERRUPT FROM REAL TIME INTERRUPT DEVICE?
*
RTISR 	LDX   	#REGS
     	BRCLR 	TFLG2,X BIT6 ENDRTI ;IGNORE ILLEGAL INTERRUPT
*
* CLEAR REAL TIME INTERRUPT FLAG
*
* Do not Use BSET TFLG2,X BIT6 
*      because it is equivalent to LDAA TFLG2, ORAA BIT6, STAA TFLG2
	BCLR	TFLG2,X INV6 
* Above is equivalent to ~ LDAA TFLG2, ANDA BIT6 (=/INV6), STAA TFLG2
*
* Determine the Current PID
	LDAA	PID
	CMPA	#1
	BEQ	SaveP1
	CMPA	#2
	BEQ	SaveP2
	BRA	ENDRTI	;Ignore Illegal PID
SaveP1	STS	SP1	;SP ==> SP1
	BRA	SetP2
SaveP2	STS	SP2	;SP ==> SP2
	BRA	SetP1	
*
* Set Next Process as Process#1
SetP1	LDAA	#1
	STAA	PID
	LDS	SP1	;SP1 ==> SP	
	BRA	ENDRTI
*
* Set Next Process as Process#2
SetP2	LDAA	#2
	STAA	PID
	LDS	SP2	;SP2 ==> SP	
*
* RETURN FROM INTERRUPT
ENDRTI	RTI
*
********************************************************
* Process #1: Clear PORT C and 
*	      Send OUTPAT1 ($0F) to PORT B
********************************************************
	ORG	$B760
PS1	LDX   	#REGS
*
* Clear OUTPUTS of PORT C
LOOP1	CLR 	PORTC,X	;0=LOW
*
* Send OUTPAT1 ($0F) to PORT B
 	LDAA	#OUTPAT1
	STAA	PORTB,X
* Do this routine again (and again, and again)
PS1H	BRA	LOOP1
*
********************************************************
* Process #2: Clear PORT B and 
*	      Send OUTPAT2 ($F0) to PORT C
********************************************************
	ORG	$B7A0
PS2	LDX   	#REGS
*
* Clear OUTPUTS of PORT B
*
LOOP2	CLR 	PORTB,X	;0=LOW
*
* Send OUTPAT2 ($F0) to PORT C
*
 	LDAA	#OUTPAT2
	STAA	PORTC,X   
* Do this routine again (and again, and again)
PS2H	BRA	LOOP2
*
*********************************************************
** Timer Overflow INTERRUPT SERVICE ROUTINE
*********************************************************
	ORG	$B740
*-----------------------------------------------------
*INTERRUPT POLLING CHAIN
*-----------------------------------------------------
* INTERRUPT FROM TIMER OVERFLOW?
*
TOISR	LDX	#REGS
	BRCLR	TFLG2,X BIT7 ENDTOI	;IGNORE ILLEGAL INTERRUPT

*-----------------------------------------------------
* CONTROL PORT C OUTPUTS
*-----------------------------------------------------
* CLEAR TIMER OVERFLOW FLAG
	BCLR	TFLG2,X INV7	;Clear TOI Flag
*
* COMPLEMENT PORT C OUTPUTS
	LDAA	#$AA
	STAA	PORTC,X		;OUTPUT TO PORT C
	LDX	TCNTEXT		;Update the TCNT Extension
	INX
	STX	TCNTEXT		;Save the TCNT Extension
*
* RETURN FROM INTERRUPT
ENDTOI	RTI
