;/*****************************************************************
; * *
; * K8LH Crazy-8 Hi-Rez Hard 8-Channel 74HC4017 Servo Algorithm *
; * *
; *****************************************************************/
;
; static unsigned char Qn = 0;
; static unsigned int Qarray [] = { 1500, 1500, 1500, 1500, 1500,
; 1500, 1500, 1500, 400, 20000 };
; void isr_hi ()
; { if (PIR1bits.CCP1IF == 1) // if CCP1 "compare" interrupt
; { CCPR1H += (Qarray[Qn]/256); // update the "match" value
; CCPR1L += (Qarray[Qn]%256); // for this Qn servo pulse
;
; PORTBbits.CCP1 = 0; // clear CCP1 "CLK" line
; PIR1bits.CCP1IF = 0; // clear CCP1 interrupt flag
;
; Qarray[9] -= Qarray[Qn++]; // adjust end-of-period off time
; // (post increment Qn index)
; if (!(Qn %= 10)) // if end-of-period (Qn == 0)
; { Qarray[9] = 20000; // reset 20.0-msec period and
; PORTAbits.RA0 = 1; // toggle 74HC4017 "CLR" line
; PORTAbits.RA0 = 0; // to force Q0 output sync'
; }
; }
; }
;
org h'0004'
ISR_Vector
;
; save main program context
;
movwf W_ISR ; save W |B?
swapf STATUS,W ; doesn't change STATUS bits |B?
movwf S_ISR ; save STATUS reg |B?
clrf STATUS ; force bank 0 |B0
movf FSR,W ; |B0
movwf F_ISR ; save FSR |B0
;
; Qarray holds ten 16-bit period values, one for each of the
; ten shift register Qn outputs. Eight Qn outputs and periods
; drive Servos. The other two Qn outputs are unused but their
; periods are used to complete the 20-msec Servo period cycle.
;
; Qarray[0] is Q1/Servo 1 "on" time, 600..2400
; Qarray[1] is Q2/Servo 2 "on" time, 600..2400
; Qarray[2] is Q3/Servo 3 "on" time, 600..2400
; Qarray[3] is Q4/Servo 4 "on" time, 600..2400
; Qarray[4] is Q5/Servo 5 "on" time, 600..2400
; Qarray[5] is Q6/Servo 6 "on" time, 600..2400
; Qarray[6] is Q7/Servo 7 "on" time, 600..2400
; Qarray[7] is Q8/Servo 8 "on" time, 600..2400
; Qarray[8] is Q9 unused cycle time, 400 (fixed)
; Qarray[9] is Q0 unused cycle time, 400..14800
;
; add current Qarray[Qn] pulse time to previous CCPR1L:CCPR1H
; register "match" interrupt value
;
setc ; set carry |B0
rlf Qn,W ; Qn index [0..9] * 2 + 1 |B0
addlw Qarray ; add to array base address |B0
movwf FSR ; setup indirect address |B0
movf INDF,W ; Qn pulse hi [600..2400] |B0
addwf CCPR1H,f ; set new CCP compare time hi |B0
decf FSR,f ; |B0
movf INDF,W ; Qn pulse lo [600..2400] |B0
addwf CCPR1L,f ; set new CCP compare time lo |B0
skpnc ; carry? no, skip, else |B0
incf CCPR1H,f ; |B0
;
; clear CCP1 interrupt flag and CCP1 "CLK" output
;
bcf PIR1,CCP1IF ; clear CCP interrupt flag bit |B0
bcf PORTB,CLK ; clear CCP1/RB3 'CLK' pin |B0
;
; subtract current Qarray[Qn] pulse time from Qarray[9] period
;
movf INDF,W ; Qn pulse lo [600..2400] |B0
subwf Qarray+.18,f ; subtract from period lo |B0
incf FSR,f ; |B0
movf INDF,W ; Qn pulse hi [600..2400] |B0
skpc ; borrow? no, skip, else |B0
incfsz INDF,W ; increment subtrahend (in W) |B0
subwf Qarray+.19,f ; subtract from period hi |B0
;
; increment Qn index (0..9) for next Qn pulse interrupt
;
incf Qn,f ; increment Qn index |B0
movf Qn,W ; |B0
xorlw d'10' ; end-of-period (Qn=0)? |B0
bnz ISR_XIT ; no, branch, else |B0
;
; reset the Qn array index and the period value in Qarray[9]
;
clrf Qn ; reset Qn index to 0 |B0
movlw low d'20000' ; reset Period to 20000 usecs |B0
movwf Qarray+.18 ; Qarray[9] |B0
movlw high d'20000' ; |B0
movwf Qarray+.19 ; |B0
bsf PORTA,CLR ; toggle 74HC4017 "CLR" line to |B0
bcf PORTA,CLR ; force Q0 output sync' |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 |B?
retfie ; return from interrupt |B?