Full Version : David Vanhorn's Interrupt Service Routines (ASM)
avr >>ASSMBLER ROUTINES >>David Vanhorn's Interrupt Service Routines (ASM)


Admin5- 04-19-2006
David Vanhorn's ISR.ASM

Interrupt Service Routines

Link: http://members.tripod.com/Stelios_Cellar/A...tarted_code.htm

CODE

;
; 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
;



Forumer™ is Voted #1 Free Forum Hosting provider
Build your own community today with the largest message board hosting company.