;
; K8LH Crazy-8 Hi-Rez 8-channel (PORTB) Servo Algorithm
;
; 1 usec steps, 600-2400 usecs range, using prescaler setting
; of 1, 2, or 4 with a 4, 8, or 16-MHz clock, respectively.
;
;
; unsigned char n = 0;
; unsigned int Servo [] = { 1500, 1500, 1500, 1500, 1500,
; 1500, 1500, 1500, 20000 };
; unsigned char Channel = 1;
;
; void interrupt() // special event interrupts
; { pir1.CCP1IF = 0; // clear CCP1 interrupt flag
; portb = Channel; // output new Servo pulse
; ccpr1 = Servo[n++]; // update "match" period value
; Servo[8] -= CCPR1; // adj end-of-period off time
; Channel <<= 1; // prep for next channel
; if(n = 9) // if end of 20-msec period
; { n = 0; // reset array index
; Servo[8] = 20000; // reset the 20 msec period
; Channel = 1; // reset Shadow to '00000001'
; }
; }
;
org 0x004
radix dec
v_interrupt
movwf W_ISR ; save main program context |B?
swapf STATUS,W ; |B?
movwf S_ISR ; save STATUS reg |B?
clrf STATUS ; force bank 0 |B0
movf FSR,W ; |B0
movwf F_ISR ; save FSR |B0
;
; clear the CCP1 interrupt flag and output new servo pulse
;
bcf PIR1,CCP1IF ; clear CCP1 interrupt flag |B0
movf Channel,W ; get channel output bit |B0
movwf PORTB ; output new Servo pulse |B0
;
; put current Servo Servo[n] "on-time" into the CCPR1L:CCPR1H
; compare registers for next "special event" match interrupt
; and subtract the "on-time" from Servo[8] "period"
;
clrc ; clr carry |B0
rlf n,W ; n index (0..8) * 2 |B0
addlw Servo ; add @Servo[0] base address |B0
movwf FSR ; setup indirect address |B0
movf INDF,W ; Servo[n] pulse lo, 600..2400 |B0
movwf CCPR1L ; set new CCP compare time lo |B0
subwf Servo+16,F ; adjust Servo[8] Period lo |B0
incf FSR,F ; |B0
movf INDF,W ; Servo[n] pulse hi, 600..2400 |B0
movwf CCPR1H ; set new CCP compare time hi |B0
skpc ; borrow? no, skip, else |B0
incf INDF,W ; increment sutrahend |B0
subwf Servo+17,F ; adjust Servo[8] Period hi |B0
;
; increment Servo mask and 'n' index for next interrupt cycle
;
clrc ; |B0
rlf Channel,F ; shift channel output bit |B0
incf n,F ; inc n |B0
movf n,W ; |B0
xorlw 9 ; all 9 intervals? |B0
bnz ISR_XIT ; no, branch, else |B0
;
; reset Channel, 'n' index, and Servo[8] 'period' variables
;
clrf n ; reset index to 0 |B0
movlw low 20000 ; reset Period to 20000 usecs |B0
movwf Servo+16 ; |B0
movlw high 20000 ; |B0
movwf Servo+17 ; |B0
bsf Channel,0 ; reset channel to '00000001' |B0
;
; restore main program context
;
ISR_XIT
movf F_ISR,W ; |B0
movwf FSR ; restore FSR |B0
swapf S_ISR,W ; |B0
movwf STATUS ; restore STATUS |B?
swapf W_ISR,F ; don't screw up STATUS |B?
swapf W_ISR,W ; restore W-reg |B?
retfie ; return from interrupt |B?
;