; ; File Name :'ISR.asm" ; Title :8515 Interrupt Handlers ; Date : ; Version : ; Support telephone :765 287 1987 David B. VanHorn ; Support fax :765 287 1989 ; Support Email :dvanhorn@cedar.net ; Target MCU :AT90S8515 ; ; DESCRIPTION ; All interrupt handlers reside here ; ;***************************************************************************; ; M O D I F I C A T I O N H I S T O R Y ; ; ; rev. date who why ; ---- -------- --- ------------------------------------------ ; 0.01 98.07.29 dvh Creation ; 0.02 98.08.20 dvh Added Timer 1 int for servo control, a little cleanup ; and better documentation elsewhere ; 0.03 98.08.21 dvh Added support in TIM0_OVF for a FRAME_DELAY ; variable used in SERVO.ASM. ; Converted Frame_Delay to SRAM from register ; 0.04 98.08.23 dvh Regularized to XL,XH notation instead of R26.R27 etc ; ;*************************************************************************** ;Fixed jump vectors ; ;$000 rjmp INIT_Machine ;Restart vector, points to the beginning of the code. ;$001 rjmp EXT_INT0 ;IRQ 0 ;$002 rjmp EXT_INT1 ;IRQ 1 ;$003 rjmp TIM1_CAPT ;Timer 1 capture ;$004 rjmp TIM1_COMPA ;Timer 1 compare A ;$005 rjmp TIM1_COMPB ;Timer 1 compare B ;$006 rjmp TIM1_OVF ;Timer 1 overflow ;$007 rjmp TIM0_OVF ;Timer 0 overflow ;$008 rjmp SPI_Handler ;Serial transfer complete ;$009 rjmp UART_RXC ;Uart RX complete ;$00A rjmp UART_DRE ;Uart data register empty ;$00B rjmp UART_TXC ;Uart TX complete ;$00C rjmp ANA_COMP ;Analog comparator ; ;************************************************************** ; ;All my ISRs use TTEMP and TTEMP2 to maximize speed. You could push ;TEMP, and pop it back.. ; ;Each int vector has, at minimum, code that turns off that int. ;This is a "belts and suspenders" method that protects me from ;any ints I forgot to turn off, or accidentally enabled. ; ;If you decide to use one of the disabled ints, enable it in the ;code when appropriate, and replace these "turn-off" handlers ;with whatever it is you want done. ; ;Each ISR saves SREG to TTEMP2, which is dedicated to this purpose. ;I could have pushed and popped it, but push and pop take two cycles, ;and in and out only take one. If you get squeezed for registers, then ;you can always do the pushpop dance. It's an extra 500nS at 8MHz ; ;MAKE ABSOLUTELY SURE YOU DO NOT USE "TEMP" IN ANY ISR! (unless you push and pop it!) ; ; ;************************************************************** ; ;Unused at this point. ; ; EXT_INT0: in TTEMP2,SREG ;Saves the status register INT0_OFF: in TTEMP,GIMSK ;If done, then turn off the int! andi TTEMP,$BF ; out GIMSK,TTEMP ; INT0_EXIT: out SREG,TTEMP2 ;restore the status register reti ; ;*************************************************************** ; ; EXT_INT1: in TTEMP2,SREG ;Saves the status register INT1_OFF: in TTEMP,GIMSK ;Get the int enables andi TTEMP,$7F ;Mask off INT1 out GIMSK,TTEMP ;Send it ldi TTEMP,$80 ; out GIFR,TTEMP ;Manual clear INT1_EXIT: out SREG,TTEMP2 ;restore the status register reti ; ; ;*************************************************************** ; ; TIM1_CAPT: ; in TTEMP2,SREG ;Saves the status register TIM1_OFF: in TTEMP,TIMSK ;Shut off this int andi TTEMP,$F7 ; out TIMSK,TTEMP ; TIM1_EXIT: out SREG,TTEMP2 ;restore the status register reti ; ; ;*************************************************************** ; ; ; TIM1_COMPA: ; in TTEMP2,SREG ;Saves the status register TC1A_OFF: in TTEMP,TIMSK ; andi TTEMP,$BF ; out TIMSK,TTEMP ; TC1A_EXIT: out SREG,TTEMP2 ;restore the status register reti ; ; ;*************************************************************** ; ; TIM1_COMPB: in TTEMP2,SREG ;Saves the status register TC1B_OFF: in TTEMP,TIMSK ; andi TTEMP,$DF ; out TIMSK,TTEMP ; TC1B_EXIT: out SREG,TTEMP2 ;restore the status register reti ; ; ;*************************************************************** ; ;Timer 1 gives us servo output timings from 1mS to 2mS, and allows ;the CPU to go do other things, rather than sitting there spinning ;NOPS. It's a 16 bit counter, so I start it with a base value of 1mS, ;plus the servo width control byte (SERVO_X) We then have 1-2mS pulses, ;with full 8 bit resolution (4uS) ; ;Each servo out is activated sequentially in the main code. The activation ;code loads a value into Timer1, and sets the prescaler to /8, and sets the ;desired servo bit high. This int occurs when the servo's time expires, and ;we just shut off the output, and stop the timer. (Fast eh? :) ; TIM1_OVF: in TTEMP2,SREG ;Saves the status register ;************************************************** ;Support for the R/C servo driver in SERVO.ASM ;************************************************** ;No matter who was running, shut off all servo outputs ldi TTEMP,$00 ; out PORTC,TTEMP ; in TTEMP,TCCR1B ;Get the timer control register andi TTEMP,$F8 ;Set the prescaler to "off" out TCCR1B,TTEMP ;Make it so. ;This test could instead mask and look for a particular ;bit to reduce the number of active servos. lds TTEMP,Servo_Control ; ;To make the servos run from 1 to 8, enable this lsl TTEMP ;Set next servo to run brcc Servo_TB ;If no carry then done, else ldi TTEMP,$01 ;start over on servo 1(0) ;To make the servos run from 8 to 1, enable this ;lsr TTEMP ;Set next servo to run ;brcc Servo_TB ;If no carry then done, else ;ldi TTEMP,$80 ;start over on servo 1(0) ;If there was a ROL without carry, then I wouldn't have needed ;to test for carry and reload like that. can't use LSL Servo_TB: sts Servo_Control,TTEMP ;Set the next active servo bit on. TIM1O_EXIT: out SREG,TTEMP2 ;restore the status register reti ; ; ;*************************************************************** ; ; Main 1mS Opsys tick ; TIM0_OVF: in TTEMP2,SREG ;Saves the status register ;************************************************** ;Reload timer 0 now to preserve accuracy ;************************************************** ldi TTEMP,T0DIV ;Reload early, avoid the latency out TCNT0,TTEMP ; ;************************************************** ;Support for the stepper motor handler ;************************************************** T0_Step:lds TTEMP,Step_Time ;Get delay timer from SRAM and TTEMP,TTEMP ;Is it zero? breq T0_Dog ;leave it alone if so dec TTEMP ;Otherwise dec sts Step_Time,TTEMP ;and store ;************************************************** ;Support for the timed watchdog handler ;************************************************** T0_Dog: lds TTEMP,Dog_Food ;Get delay timer from SRAM and TTEMP,TTEMP ;Is it zero? breq T0_Char ;leave it alone if so dec TTEMP ;Otherwise dec sts Dog_Food,TTEMP ;and store ;************************************************** ;Support for the timed charachter wait ;************************************************** T0_Char:lds TTEMP,Char_Time ;Get delay timer from SRAM and TTEMP,TTEMP ;Is it zero? breq T0_RC ;leave it alone if so dec TTEMP ;Otherwise dec sts Char_Time,TTEMP ;and store ;************************************************** ;Support for the R/C servo driver in SERVO.ASM ;************************************************** T0_RC: lds TTEMP,Frame_Delay;Get delay timer from SRAM and TTEMP,TTEMP ;Is it zero? breq T0_SER ;leave it alone if so dec TTEMP ;Otherwise dec sts Frame_Delay,TTEMP;and store ;************************************************** ;Support for the inter-char delay feature in SERIAL.ASM ;************************************************** T0_SER: lds TTEMP,Char_Delay ; and TTEMP,TTEMP ; breq TIM0_EXIT ;If already zero, nevermind dec TTEMP ;else dec, and if NOW zero sts Char_Delay,TTEMP ; brne TIM0_EXIT ; ;re-enable UART DRE INT. in TTEMP,UCR ; ori TTEMP,$20 ; out UCR,TTEMP ; ;************************************************** ;All done, seeya! ;************************************************** TIM0_EXIT: out SREG,TTEMP2 ;restore the status register reti ;Bye! ; ;*************************************************************** ; ;SPI is unused at this point ; SPI_Handler: ; in TTEMP2,SREG ;Saves the status register SPI_OFF: ldi TTEMP,$3F ;Disable int, disable SPI out SPCR,TTEMP ; SPI_EXIT: out SREG,TTEMP2 ;restore the status register reti ; ; ;*************************************************************** ; ;Take a char and put it in the Serial input buffer. ; UART_RXC: ; in TTEMP2,SREG ;Saves the status register push TEMP ;Have to use TEMP because Store_Serin uses temp ;************************************************** ;Loading incoming UART data into the serial input buffer ;************************************************** in TEMP,UDR ;Get the char rcall Store_Serin ;Store it in the serial in buffer (USES TEMP) UART_RXC_Exit: pop TEMP ; out sreg,TTEMP2 ;restore the status register reti ; ; ;*************************************************************** ; ;Ready to transmit the next byte ; UART_DRE: ; in TTEMP2,SREG ;Saves the status register push YL push YH push ZL push ZH push TEMP ;It's used in SEROUT_Check rcall SEROUT_Check ;Anything to say? brne UART_DRE_TX ;If non-zero, then let it continue in TTEMP,UCR ; andi TTEMP,$DF ;Turn off DRE, I'm DONE out UCR,TTEMP ; rjmp UART_DRE_EXIT ; UART_DRE_TX: lds TTEMP,(Serial_OUT_BUF+1);Load a byte to temp from SERIAL_OUT_BUF ; ; Time------------> ; S L X X X X X M S S ; T S X X X X X S P T ; A B X X X X X B C P ;1 0 0 0 0 0 0 0 0 0 1 (Line state) ; ;Comment both of the following out for 8N1 andi TTEMP,$7F ;7 bit Space parity ;ori TTEMP,$80 ;7 bit Mark parity out UDR,TTEMP ;Load uart from TEMP ldi TTEMP,SER_DLY ;Stupid inter-char delay sts Char_Delay,TTEMP ; ;disable Uart_DRE_int. in TTEMP,UCR ;Get the UCR andi TTEMP,$DF ;Shut off DRE ints till the T0OV int re-enables them out UCR,TTEMP ;Output it to the UCR ldi ZL,low(SERIAL_OUT_BUF) ; ldi ZH,high(SERIAL_OUT_BUF); lds YL,(SERIAL_OUT_TAIL) ; lds YH,(SERIAL_OUT_TAIL+1) ; push TEMP ; rcall Kill_Head ;Kill the sent byte pop TEMP ; sts (SERIAL_OUT_TAIL),YL ; sts (SERIAL_OUT_TAIL+1),YH ; UART_DRE_EXIT: pop TEMP pop ZH ; pop ZL ; pop YH ; pop YL ; out SREG,TTEMP2 ;restore the status register reti ; ; ;*************************************************************** ; ;Uart TXC is unused at this point ; UART_TXC: in TTEMP2,SREG ;Saves the status register UTXC_OFF: in TTEMP,UCR ; andi TTEMP,$BF ;Disable the TXC int. out UCR,TTEMP ; UTXC_EXIT: out SREG,TTEMP2 ;restore the status register reti ; ; ;*************************************************************** ; ;Analog comparator is unused at this point. ; ANA_COMP: in TTEMP2,SREG ;Saves the status register ANAC_OFF: ldi TTEMP,$83 ;Shut off power to the comparator out ACSR,TTEMP ;and the comparator ints ANAC_EXIT: out SREG,TTEMP2 ;restore the status register reti ; ;*************************************************************** ;