;******************************************************************
;
; clock 4-MHz, TMR2 prescaler 16, PR2=156, 2496-usec PWM period
;
EADR equ h'60' ; EPROM address / 2 [0..7]
DutyLo equ h'61'
DutyHi equ h'62'
SArray equ h'68' ; 8-bytes [68h..6Fh]
;
; save main program context
;
ISRPROC movwf W_ISR ; save W-reg |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
bcf PIR1,TMR2IF ; clear TMR2 interrupt flag |B0
;
; EEPROM address counter / servo counter maintenance
;
incf EADR,f ; increment counter |B0
bcf EADR,3 ; force 0..7 |B0
;
; set eeprom address lines on RB0:RB2 during minimum 96-usec
; window at beginning of interrupt where PWM output is low
;
movf PORTB,W ; |B0
andlw b'11111000' ; |B0
iorwf EADR,W ; |B0
movwf PORTB ; set EPROM address lines |B0
;
; set Servo PWM output. duty cycle set in 8-usec steps
;
movf EADR,W ; [0..7] |B0
addlw SArray ; add index to array address |B0
movwf FSR ; setup indirect address |B0
clrf DutyHi ; |B0
movf INDF,W ; user ServoPWM value [000..250] |B0
addlw d'50' ; add minimum 0.4-msec on-time |B0
skpnc ; |B0
incf DutyHi,f ; |B0
sublw low d'312' ; 2496-usec period /8-usecs |B0
movwf DutyLo ; |B0
movf DutyHi,W ; |B0
skpc ; borrow? |B0
incf DutyHi,W ; |B0
sublw high d'312' ; |B0
movwf DutyHi ; |B0
rrf DutyHi,f ; |B0
rrf DutyLo,W ; |B0
movwf CCPR1L ; set 000..150 (16-usec ticks) |B0
bcf CCP1CON,DC1B1 ; |B0
skpnc ; |B0
bsf CCP1CON,DC1B1 ; |B0
;
; restore main program context
;
ISR_X 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?