Professional Documents
Culture Documents
; upgraded with a supplementary bulk charge restart feature after a 4hr break when
sunlight returns to panel
; Option set when RB0 low
; Supplementary bulk restart anytime power demanded for float charging. Option set
when RB1 low
; Added switch to float mode if bulk charging takes less than 60s. ie if the
battery is fully charged
list P=16F88
#include p16f88.inc
ERRORLEVEL -302
ERRORLEVEL -306
; Bank 0 RAM
DIGITAL equ H'20' ; storage
FIRST equ H'21' ; first run
CUT_M equ H'22' ; cutout voltage high byte
CUT_L equ H'23' ; cutout voltage low byte
FLOAT_H equ H'24' ; float voltage high byte
FLOAT_L equ H'25' ; float voltage low byte
COMP equ H'26' ; compensation (temperature)
BATT_HI equ H'27' ; battery volts high byte
BATT_LO equ H'28' ; battery low byte
DELCNT equ H'29' ; delay counter
FLASHER equ H'2A' ; LED flasher timer
TEMPERATURE equ H'2B' ; temperature reading deg C
THERMISTOR equ H'2C' ; thermistor flag for LED
CUT_COMP_M equ H'2D' ; cutout temp. compensated voltage high byte
CUT_COMP_L equ H'2E' ; cutout temp. compensated voltage low byte
FLOAT_COMP_M equ H'2F' ; float temp. compensated voltage high byte
FLOAT_COMP_L equ H'30' ; float temp. compensated voltage low byte
NEGATIVE equ H'31' ; subtract negative flag
VALUE_1 equ H'32' ; delay counter
VALUE_2 equ H'33' ; delay counter
HOUR0 equ H'34' ; hour counter
HOUR1 equ H'35' ; 14 seconds counter for hour counter (256 x
14s=1hour)
SENSOR_COUNT equ H'36' ; sensor counter for periodic checking
SENSOR_COUNT1 equ H'37' ; sensor counter for periodic checking
CELL_LO equ H'38' ; solar cell voltage ls byte
CELL_HI equ H'39' ; solar cell voltage ms byte
CELL_I_LO equ H'3A' ; solar cell current ls byte
CELL_I_HI equ H'3B' ; solar cell current ms byte
CHARGE_STATE equ H'3C' ; 0 charge, 1 float
CHARGE_FLAG equ H'3D' ; flag for charge
CHRG_RATE equ H'3E' ; charge change rate
CELL_V equ H'3F' ; solar cell voltage 8-bit
CELL_I equ H'40' ; solar cell current 8-bit
PERIOD equ H'41' ; power calculation rate
CCPR1_STORE equ H'42' ; CCPR1L storage value
POWERH equ H'43' ; power ms byte
POWERL equ H'44' ; power ls byte
VALUE1 equ H'45' ; temporary value
VALUE2 equ H'46' ; temporary value
VALUE3 equ H'47' ; temporary value
VALUE4 equ H'48' ; temporary value
EQ_FLAG equ H'49' ; equalisation flag
EQ_LO equ H'4A' ; ls byte EQ battery voltage
EQ_HI equ H'4B' ; ms byte EQ battery voltage
EQ_LO_COMP equ H'4C' ; ls byte temp. compensated EQ battery voltage
EQ_HI_COMP equ H'4D' ; ms byte temp. compensated EQ battery voltage
EQ_LEVEL equ H'4E' ; equalisation input (RB4) level store
BATT_IND equ H'4F' ; battery indicator flag when error
BURST_FLG equ H'50' ; burst flag
HOUR3 equ H'51' ; 4 hour counter
HOUR2 equ H'52' ; 56 seconds counter for hour counter (256 x
56s=1hour)
BULK_TIMER equ H'53' ; bulk charge timer (60s)
BULK_TIMER_END equ H'54' ; bulk timer ended flag
; math routines
TEMP1 equ H'5C'
TEMPB0 equ H'5D'
TEMPB1 equ H'5E'
TEMPB2 equ H'5F'
TEMP equ H'60'
REMB3 equ H'61'
REMB2 equ H'62'
REMB1 equ H'63'
REMB0 equ H'64'
AARGB5 equ H'65'
AARGB4 equ H'66'
AARGB3 equ H'67'
AARGB2 equ H'68'
AARGB1 equ H'69'
AARGB0 equ H'6A' ; most significant byte of argument A
BARGB3 equ H'6B'
BARGB2 equ H'6C'
BARGB1 equ H'6D'
BARGB0 equ H'6E' ; most significant byte of argument B
LOOPCOUNT equ H'6F' ; division counter
; start at memory 0
org 0
goto SETUP
org 4
goto INTERRUPT
;
***********************************************************************************
***********
SETUP
; pwm set
clrf CCPR1L ; duty 0% Mosfet off
bcf CCP1CON,4
bcf CCP1CON,5 ; clear 10-bits
clrf T2CON
bsf T2CON,2 ; enable timer 2
movlw B'00001100' ; set PWM mode
movwf CCP1CON ; enable PWM operation
; initial conditions
INITIAL
clrf PORTB
clrf PORTA
clrf THERMISTOR ; thermistor flags
movlw D'1'
movwf SENSOR_COUNT ; counter ready to zero on next decrement
movwf SENSOR_COUNT1
clrf CHARGE_STATE ; start at main Bulk ( 0 main Bulk, 1 float)
clrf CHARGE_FLAG ; flag for charge
movlw D'5' ; 5 x 0.262ms
movwf PERIOD ; period counter for solar cell power calculations
clrf CCPR1_STORE ; CCPR1L storage
clrf FIRST ; first run
clrf POWERH ; power ms byte
clrf POWERL ; power ls byte
clrf FLASHER ; flash timer
clrf CHRG_RATE ; charge rate flag
clrf HOUR0 ; hour counter
clrf HOUR1 ; 14s counter for hour0 counter
clrf HOUR2 ; 56s counter for 4 hour counter
clrf HOUR3 ; 4- hour timer
clrf EQ_FLAG ; equalisation flag
bsf EQ_FLAG,0 ; equalisation flag.0 Does not run equalisation
when set
clrf EQ_LEVEL ; equalisation input level store
clrf BATT_IND ; no battery error when clear
clrf BURST_FLG ; no burst
clrf BULK_TIMER ; bulk charge timer
clrf BULK_TIMER_END ; bulk timer ended flag
ALLOW_INTERRUPTS
; allow interrupts
bsf STATUS,RP0 ; select memory bank 1
bsf PIE1,TMR1IE ; timer 1 overflow interrupt enable
bcf STATUS,RP0 ; select memory bank 0
bcf PIR1,TMR1IF ; timer 1 interrupt flag
bsf INTCON,PEIE ; enable periperal interrupts
bsf INTCON,GIE ; enable global interrupts
;*******************************************************
SENSORS
; equalisation input
; if portB,4 is low and EQ_LEVEL,4 is high, run delay and check again.
call DELAY
btfsc PORTB,4
goto CH_1AD ; If portB,4 high ignore
; if portB,4 remains low clear EQ_LEVEL,4 and clear EQ_FLAG (level change from h/l)
clrf EQ_LEVEL ; store new portB,4 level
clrf EQ_FLAG ; equalisation flag clear for equalisation
HI_IN
; if portB,4 is high and EQ_LEVEL,4 is low, run delay and check again.
call DELAY
btfss PORTB,4
goto CH_1AD ; portB,4 low so bypass
; If portB,4 is still high, set EQ_LEVEL,4 and set EQ_FLAG,0 (no equalisation)
CH_1AD
; set analog input address
bcf ADCON0,5
bcf ADCON0,4
bsf ADCON0,3 ;
call DEL_AD ; convert to digital ls bits in 'DIGITAL'
BY_ZRO
TEMP_CONV1
bsf INTCON,GIE ; allow interrupt
; convert to temperature
movf DIGITAL,w
sublw D'199' ; take from 199 if negative then >200 so set at 200
movlw D'200' ; ready to load if >200
btfss STATUS,C
movwf DIGITAL
movlw D'49' ; minimum value
subwf DIGITAL,f ; take away 49 from A/D value
btfss STATUS,C ; if minus then >60 deg C so set at 60deg
clrf DIGITAL ; 0 so 60 deg C in lookup table
movf DIGITAL,w
call TEMP_CONV ; convert reading to temperature in deg C
movwf TEMPERATURE ; store value
CONTINUE1
; multiply temperature difference from 20 deg C (in AARGB0) by compensation value
movf COMP,w
movwf BARGB0
call EIGHTEIGHT
; result in AARGB0,AARGB1
; shift result
movf AARGB1,w
movwf AARGB2
movf AARGB0,w
movwf AARGB1
clrf AARGB0
; Multiply by 100
movlw D'100'
movwf BARGB2
clrf BARGB1
clrf BARGB0
call FXM2424U ; multiply
; shift result for division
movf AARGB2,w ; ms of multiplication
movwf AARGB0
movf AARGB3,w ; ls byte
movwf AARGB1
movf AARGB4,w ; ms of multiplication
movwf AARGB2
movf AARGB5,w ; ls byte
movwf AARGB3
; Divide by D8000 = H1F40
clrf BARGB0
clrf BARGB1
movlw H'1F'
movwf BARGB2
movlw H'40'
movwf BARGB3
call FXD3232U ; divide
; cutoff calculations
btfsc NEGATIVE,7 ; if set add value
goto ADD_COMP1
; take compensation value from cutoff V and place in CUT_COMP_M/LS
movf AARGB3,w ; result
subwf CUT_L,w
movwf CUT_COMP_L
movf CUT_M,w ; ms cutout V
btfss STATUS,C
decf CUT_M,w ; decrease if carry
movwf CUT_COMP_M
btfss CUT_COMP_M,7 ; if bit 7 set then over so clear
goto CHECK_EQ
clrf CUT_COMP_M
clrf CUT_COMP_L
ADD_COMP1
movf CUT_M,w
movwf CUT_COMP_M
movf AARGB3,w ; result
addwf CUT_L,w
movwf CUT_COMP_L
btfsc STATUS,C
incf CUT_COMP_M,f ; increase if carry
; Float calculations
CHECK_FLOAT
btfsc NEGATIVE,7 ; if set add value
goto ADD_COMP2
movwf FLOAT_COMP_M
btfss FLOAT_COMP_M,7 ; if bit 7 set then over so clear
goto CH_0AD
clrf FLOAT_COMP_M
clrf FLOAT_COMP_L
goto CH_0AD
ADD_COMP2
movf FLOAT_H,w ; ms float V to w
movwf FLOAT_COMP_M
movf AARGB3,w ; result
addwf FLOAT_L,w
movwf FLOAT_COMP_L
btfsc STATUS,C
incf FLOAT_COMP_M,f ; increase if carry
; Charge Control
CHARGE_MODE
CHK_BATT
; battery voltage: if low then apply bursts till >10.5V (D671, H29F)
; if battery above 15V (usually when an O/C cell) then show Batt. LED
BATT15
movf BATT_HI,w ; high byte of battery voltage
sublw H'3' ; take from 15V
movwf DIGITAL ; store
movf BATT_LO,w ; low byte
sublw H'BF' ; 15V
btfss STATUS,C
decf DIGITAL,f ; decrease if required
btfss DIGITAL,7 ; if set then >15V
goto MODE_CHARGE1 ; <15V
bsf CHARGE_FLAG,0 ; stop charging
bsf BATT_IND,0 ; Batt. indicator LED on (Flash Bulk LED)
bsf PORTB,2 ; >15V output
goto NO_CHARGE ; battery voltage high so end charge
MODE_CHARGE1
; test for low battery
; start charge when solar cell has sufficient voltage. ie about 12V
; check if above 12V D432, H1B0 (solar cell voltage is divided by a factor of
0.176)
movf CELL_HI,w ; high byte of solar call voltage
sublw H'1' ; take from
movwf DIGITAL ; store
movf CELL_LO,w ; low byte
sublw H'B0' ; 12V
btfss STATUS,C
decf DIGITAL,f ; decrease if required
btfss DIGITAL,7 ; if set then >12V
goto NO_CHARGE ; charge off till solar cell ready
clrf HOUR3 ; prevents return to Bulk charge if this is before the
end of 4hr timer
NO_CHARGE
bsf CHARGE_FLAG,0 ; no charge flag
clrf CCPR1L ; charge off
clrf FIRST
movlw D'5' ; 5 x 0.262ms
movwf PERIOD
TEST_BATT2
; compare battery voltage (BATT_HI/LO) with cutout (CUT_COMP_M/L)
movf BATT_HI,w ; high byte of battery voltage
subwf CUT_COMP_M,w ; take from compensated cutout
movwf DIGITAL ; store
movf BATT_LO,w ; low byte
subwf CUT_COMP_L,w ; take from compensated cutout
btfss STATUS,C
decf DIGITAL,f ; decrease if required
btfss DIGITAL,7 ; if set then battery is over cutout voltage
goto FULL_POWER_RUN
btfsc BULK_TIMER_END,0; bulk timer ended flag. If not set, then bulk charge
occurred in <60s
; so clear timer 0 so charging goes to float rather than absorption
goto ABS_TME
clrf HOUR0 ; stop absorption charge
clrf BULK_TIMER_END ; bulk timer ended flag
goto BY_SET ; bypass setting the timer for absorption
; full charge; maintain max power from solar cell during bulk charging
; periodically alter the duty cycle to find power maximum
; store CCPR1L value that provides max power
FULL_POWER_RUN
; set 60s timer for bulk charge
movf CHARGE_STATE,w ; check if bulk
btfss STATUS,Z
goto BY_BULK_TIMER ; absorption or float so bypass bulk timer
movf BULK_TIMER,w ; check if timer running
btfss STATUS,Z
goto BY_BULK_TIMER
movlw D'229' ; 0.262ms x 229 = 60s
movwf BULK_TIMER ; decreased in interrupt to zero and sets bulk timer
ended flag
BY_BULK_TIMER
movf PERIOD,w ; when zero check for maximum power
btfss STATUS,Z ;
goto CYCLE
movf FIRST,w ; first run
btfss STATUS,Z ; when clear
goto CH_3AD
clrf POWERH ; power
clrf POWERL
clrf CCPR1L ; drive cleared
call DELAY2 ; time for current reading to drop
clrf CCPR1_STORE
movlw H'FF'
movwf FIRST ; sets first run
; AN2
CH_2AD
; solar cell voltage is divided by a factor of 0.176
; set at 8-bit
; solar cell voltage
rrf CELL_HI,w ; shift ms byte right and store
movwf DIGITAL
rrf CELL_LO,w ; shift ls byte and store
movwf CELL_V
rrf DIGITAL,w ; shift stored ms byte
rrf CELL_V,f ; shift stored ls byte
; solar cell current
rrf CELL_I_HI,w
movwf DIGITAL
rrf CELL_I_LO,w
movwf CELL_I
rrf DIGITAL,w
rrf CELL_I,f
; multiply
movf CELL_V,w
movwf AARGB0
movf CELL_I,w
movwf BARGB0
call EIGHTEIGHT
; result is in AARGB0,AARGB1
; compare with POWERH,POWERL
movf AARGB0,w ; high byte of power new
subwf POWERH,w ; take from last power value
movwf DIGITAL ; store
movf AARGB1,w ; low byte
subwf POWERL,w ; take from last power value
btfss STATUS,C
decf DIGITAL,f ; decrease if required
btfss DIGITAL,7 ; if set then new power > old power
goto INC_CHRG ; increase PWM
INC_CHRG
; increase charge
movf CCPR1L,w ; check if maximum
sublw D'64'
btfss STATUS,C ; if maximum value end of test cycle
goto MAX ; bypass decrease if 0
incf CCPR1L,f
call DELAY3 ; allow time to change at I and V inputs
goto CYCLE
MAX
; when max power found, set next timer for test period
movlw D'76' ; D76 = 20s (0.262ms per bit)
movwf PERIOD ; next 20s
clrf FIRST ; so runs with first values at start
movf CCPR1_STORE,w
movwf CCPR1L ; set full charge rate at maximum power
goto CYCLE
CHARGE_ABSORP_FLOAT; (CHARGE_STATE = 1)
movlw D'01'
movwf CHARGE_STATE ; absorption/float mode set when coming from full mode
clrf BULK_TIMER_END ; bulk timer ended flag
TEST_BATT3
; alter CHARGE_CONT to adjust the drive to maintain float V
; check hour timer. If still timing then absorption. if timer ended (hour0=0) then
float
movf HOUR0,w
btfsc STATUS,Z
goto FLOAT_VALUES
EQUALISATION_VALUES
bsf EQ_FLAG,1 ; equalisation started flag so LED lights
; equalisation
rrf EQ_HI_COMP,w
movwf VALUE3
rrf EQ_LO_COMP,w ; get value difference
movwf VALUE4
rrf VALUE3,w
rrf VALUE4,f
ABSORPTION_VALUES
bcf EQ_FLAG,1 ; clear so equaliser LEDs off
; absorption
rrf CUT_COMP_M,w
movwf VALUE3
rrf CUT_COMP_L,w ; get value difference
movwf VALUE4
rrf VALUE3,w
rrf VALUE4,f
FLOAT_VALUES
bsf EQ_FLAG,0 ; equalisation no run flag set so no further
equalisation occurs until reset
btfsc EQ_FLAG,1 ; if running flag set set bit 2
bsf EQ_FLAG,2 ; allows EQ LED to flash
bcf EQ_FLAG,1 ; equalisation flag for eq running indicator LED
; float
rrf FLOAT_COMP_M,w
movwf VALUE3
rrf FLOAT_COMP_L,w ; get value difference
movwf VALUE4
rrf VALUE3,w
rrf VALUE4,f
; check RB1 for return to bulk charge after drawing current when in float
btfsc PORTB,1
goto PWM_CONTROL
; compare float control with previous CCPR1 storage during bulk charge
movf CCPR1_STORE,w
subwf CCPR1L,w
btfss STATUS,C
goto PWM_CONTROL ;
clrf CHARGE_STATE ; set for bulk/main charging
clrf BULK_TIMER
clrf BULK_TIMER_END ; bulk timer ended flag
goto CYCLE
; decrease charge
DECREASE_CHARGE
movf VALUE4,w ; absorption/float 8-bit
subwf VALUE2,f ; battery 8-bit
; if >3 switch off charge
movf VALUE2,w
sublw D'3'
btfss STATUS,C
goto CLEAR_CHRG ; over
BURST
bsf BURST_FLG,0 ; set flag
bcf PORTA,6 ; Absorption LED off
bcf PORTB,7 ; Float LED off
bcf PORTB,6 ; Equalisation LED off
BURST_OFF
bcf PORTA,7 ; Bulk LED off
clrf CCPR1L
goto CYCLE
;***************************************************
; INTERRUPT
; start interrupt by saving w and status registers
INTERRUPT
movwf W_TMP ; w to w_tmp storage
swapf STATUS,w ; status to w
movwf STATUS_TMP ; status in status_tmp
bcf STATUS,RP0 ; bank select
bcf STATUS,RP1 ; select memory bank 0
FLASH1
; flasher rate (increases every 0.262ms)
incf FLASHER,f ; flasher
CK_THERM1
btfss THERMISTOR,1 ; when set, thermistor is shorted
goto CHARGE_CONDITION
; charge LEDs off
bcf PORTA,7 ; Bulk LED off
bcf PORTA,6 ; Absorption LED off
bcf PORTB,7 ; Float LED off
bcf PORTB,6 ; Equalisation LED off
; flash thermistor LED
movf FLASHER,w
andlw B'00000111' ; flash 262ms on each 1 second
btfsc STATUS,Z
goto SET_OUT1
bcf PORTB,5 ; NTC thermistor LED off
goto CHECK_END
SET_OUT1
bsf PORTB,5 ; NTC thermistor LED on
goto CHECK_END
CHARGE_CONDITION
; check battery error
btfss BATT_IND,0 ; when set flash Bulk LED
goto CHARGE_STATES
; flash Bulk LED
; charging LEDs off
bcf PORTA,6 ; Absorption LED off
bcf PORTB,7 ; Float LED off
bcf PORTB,6 ; Equalisation LED off
; flash LED
movf FLASHER,w
andlw B'00000111' ; flash 262ms on each 1 second
btfsc STATUS,Z
goto SET_OUT_CHRG
bcf PORTA,7 ; LED off
goto CHECK_END
SET_OUT_CHRG
bsf PORTA,7 ; LED on
goto CHECK_END
CHARGE_STATES
movf CHARGE_FLAG,w ; if zero then charging
btfss STATUS,Z
goto OFF_CHRG
; check burst
btfsc BURST_FLG,0 ; if set burst mode
goto BURST_IND
CHECK_END
; hour timer
HOUR_TIMER
incf HOUR1,f ; seconds
movf HOUR1,w
sublw D'52' ; 14 seconds
btfsc STATUS,C
goto BULK_TIME
clrf HOUR1 ; cleared when 14-seconds reached
RECLAIM
; end of interrupt reclaim w and status
swapf STATUS_TMP,w; status temp storage to w
movwf STATUS ; w to status register
swapf W_TMP,f ; swap upper and lower 4-bits in w_tmp
swapf W_TMP,w ; swap bits and into w register
retfie ; return from interrupt
;**************************************************************
; Subroutines
; delays
DELAY_M
movlw D'255' ; set delay period
movwf VALUE_1 ; VALUE_1 = w
LP_1
movlw D'255' ; set delay period value 2
movwf VALUE_2 ; VALUE_2 = w
LP_2
decfsz VALUE_2,f ; decrease VALUE_2, skip if zero
goto LP_2
decfsz VALUE_1,f ; decrease VALUE_1, skip if zero
goto LP_1
decfsz DELCNT,f
goto DELAY_M
return
DELAY2
; movlw D'4' ; * 4MHz operation set delay period
movlw D'8' ; ** 8MHz operation set delay period
movwf VALUE_1 ; VALUE_1 = w
LP_3
movlw D'255' ; set delay period value 2
movwf VALUE_2 ; VALUE_2 = w
LP_4
decfsz VALUE_2,f ; decrease VALUE_2, skip if zero
goto LP_4
decfsz VALUE_1,f ; decrease VALUE_1, skip if zero
goto LP_3
return
DELAY3
; movlw D'116' ; * 4MHz operation
movlw D'58' ; ** 8MHz operation set delay period value 2 for 50ms max
power calc period
movwf VALUE_2 ; VALUE_2 = w
LP_5
decfsz VALUE_2,f ; decrease VALUE_2, skip if zero
goto LP_5
return
;*********************************
; 24x24 Bit Unsigned Fixed Point Multiply 24x24 -> 48
; Input: 24 bit unsigned fixed point multiplicand in AARGB0,1,2
; 24 bit unsigned fixed point multiplier in BARGB0,1,2
; Use: CALL FXM2424U
; Output: 48 bit unsigned fixed point product in AARGB0
; Result: AARG <-- AARG x BARG
; Max Timing: 9+501+2 = 512 clks
; Min Timing: 9+150 = 159 clks
FXM2424U
CLRF AARGB3 ; clear partial product
CLRF AARGB4
CLRF AARGB5
MOVF AARGB0,W
MOVWF TEMPB0
MOVF AARGB1,W
MOVWF TEMPB1
MOVF AARGB2,W
MOVWF TEMPB2
MOVLW H'08'
MOVWF LOOPCOUNT
LOOPUM2424A
RRF BARGB2,F
BTFSC STATUS,C
GOTO ALUM2424NAP
DECFSZ LOOPCOUNT,F
GOTO LOOPUM2424A
MOVWF LOOPCOUNT
LOOPUM2424B
RRF BARGB1,F
BTFSC STATUS,C
GOTO BLUM2424NAP
DECFSZ LOOPCOUNT,F
GOTO LOOPUM2424B
MOVWF LOOPCOUNT
LOOPUM2424C
RRF BARGB0,F
BTFSC STATUS,C
GOTO CLUM2424NAP
DECFSZ LOOPCOUNT,F
GOTO LOOPUM2424C
CLRF AARGB0
CLRF AARGB1
CLRF AARGB2
RETLW 0x00
CLUM2424NAP
BCF STATUS,C
GOTO CLUM2424NA
BLUM2424NAP
BCF STATUS,C
GOTO BLUM2424NA
ALUM2424NAP
BCF STATUS,C
GOTO ALUM2424NA
ALOOPUM2424
RRF BARGB2,F
BTFSS STATUS,C
GOTO ALUM2424NA
MOVF TEMPB2,W
ADDWF AARGB2,F
MOVF TEMPB1,W
BTFSC STATUS,C
INCFSZ TEMPB1,W
ADDWF AARGB1,F
MOVF TEMPB0,W
BTFSC STATUS,C
INCFSZ TEMPB0,W
ADDWF AARGB0,F
ALUM2424NA
RRF AARGB0,F
RRF AARGB1,F
RRF AARGB2,F
RRF AARGB3,F
DECFSZ LOOPCOUNT,F
GOTO ALOOPUM2424
MOVLW H'08'
MOVWF LOOPCOUNT
BLOOPUM2424
RRF BARGB1,F
BTFSS STATUS,C
GOTO BLUM2424NA
MOVF TEMPB2,W
ADDWF AARGB2,F
MOVF TEMPB1,W
BTFSC STATUS,C
INCFSZ TEMPB1,W
ADDWF AARGB1,F
MOVF TEMPB0,W
BTFSC STATUS,C
INCFSZ TEMPB0,W
ADDWF AARGB0,F
BLUM2424NA
RRF AARGB0,F
RRF AARGB1,F
RRF AARGB2,F
RRF AARGB3,F
RRF AARGB4,F
DECFSZ LOOPCOUNT,F
GOTO BLOOPUM2424
MOVLW H'08'
MOVWF LOOPCOUNT
CLOOPUM2424
RRF BARGB0,F
BTFSS STATUS,C
GOTO CLUM2424NA
MOVF TEMPB2,W
ADDWF AARGB2,F
MOVF TEMPB1,W
BTFSC STATUS,C
INCFSZ TEMPB1,W
ADDWF AARGB1,F
MOVF TEMPB0,W
BTFSC STATUS,C
INCFSZ TEMPB0,W
ADDWF AARGB0,F
CLUM2424NA
RRF AARGB0,F
RRF AARGB1,F
RRF AARGB2,F
RRF AARGB3,F
RRF AARGB4,F
RRF AARGB5,F
DECFSZ LOOPCOUNT,F
GOTO CLOOPUM2424
return
;********************************
; 32/32 Bit Unsigned Fixed Point Divide 32/32 -> 32.32
; Input: 32 bit unsigned fixed point dividend in AARGB0, AARGB1,AARGB2,AARGB3
; 32 bit unsigned fixed point divisor in BARGB0, BARGB1, BARGB2, BARGB3
; Use: CALL FXD3232U
; Output: 32 bit unsigned fixed point quotient in AARGB0, AARGB1,AARGB2,AARGB3
; 32 bit unsigned fixed point remainder in REMB0, REMB1, REMB2, REMB3
; Result: AARG, REM <-- AARG / BARG
; Max Timing: 4+1025+2 = 1031 clks
; Max Timing: 4+981+2 = 987 clks
; PM: 4+359+1 = 364 DM: 13
FXD3232U
CLRF REMB0
CLRF REMB1
CLRF REMB2
CLRF REMB3
call UDIV3232L
return
UDIV3232L
; Max Timing: 24+6*32+31+31+6*32+31+31+6*32+31+31+6*32+31+16 = 1025 clks
; Min Timing: 24+6*31+30+30+6*31+30+30+6*31+30+30+6*31+30+3 = 981 clks
; PM: 359 DM: 13
CLRF TEMP
RLF AARGB0,W
RLF REMB3,F
MOVF BARGB3,W
SUBWF REMB3,F
MOVF BARGB2,W
BTFSS STATUS,C
INCFSZ BARGB2,W
SUBWF REMB2,F
MOVF BARGB1,W
BTFSS STATUS,C
INCFSZ BARGB1,W
SUBWF REMB1,F
MOVF BARGB0,W
BTFSS STATUS,C
INCFSZ BARGB0,W
SUBWF REMB0,F
CLRW
BTFSS STATUS,C
MOVLW H'1'
SUBWF TEMP,F
RLF AARGB0,F
MOVLW H'7'
MOVWF LOOPCOUNT
LOOPU3232A
RLF AARGB0,W
RLF REMB3,F
RLF REMB2,F
RLF REMB1,F
RLF REMB0,F
RLF TEMP,F
MOVF BARGB3,W
BTFSS AARGB0,0
GOTO UADD22LA
SUBWF REMB3,F
MOVF BARGB2,W
BTFSS STATUS,C
INCFSZ BARGB2,W
SUBWF REMB2,F
MOVF BARGB1,W
BTFSS STATUS,C
INCFSZ BARGB1,W
SUBWF REMB1,F
MOVF BARGB0,W
BTFSS STATUS,C
INCFSZ BARGB0,W
SUBWF REMB0,F
CLRW
BTFSS STATUS,C
MOVLW H'1'
SUBWF TEMP,F
GOTO UOK22LA
UADD22LA
ADDWF REMB3,F
MOVF BARGB2,W
BTFSC STATUS,C
INCFSZ BARGB2,W
ADDWF REMB2,F
MOVF BARGB1,W
BTFSC STATUS,C
INCFSZ BARGB1,W
ADDWF REMB1,F
MOVF BARGB0,W
BTFSC STATUS,C
INCFSZ BARGB0,W
ADDWF REMB0,F
CLRW
BTFSC STATUS,C
MOVLW H'1'
ADDWF TEMP,F
UOK22LA
RLF AARGB0,F
DECFSZ LOOPCOUNT,F
GOTO LOOPU3232A
RLF AARGB1,W
RLF REMB3,F
RLF REMB2,F
RLF REMB1,F
RLF REMB0,F
RLF TEMP,F
MOVF BARGB3,W
BTFSS AARGB0,0
GOTO UADD22L8
SUBWF REMB3,F
MOVF BARGB2,W
BTFSS STATUS,C
INCFSZ BARGB2,W
SUBWF REMB2,F
MOVF BARGB1,W
BTFSS STATUS,C
INCFSZ BARGB1,W
SUBWF REMB1,F
MOVF BARGB0,W
BTFSS STATUS,C
INCFSZ BARGB0,W
SUBWF REMB0,F
CLRW
BTFSS STATUS,C
MOVLW H'1'
SUBWF TEMP,F
GOTO UOK22L8
UADD22L8
ADDWF REMB3,F
MOVF BARGB2,W
BTFSC STATUS,C
INCFSZ BARGB2,W
ADDWF REMB2,F
MOVF BARGB1,W
BTFSC STATUS,C
INCFSZ BARGB1,W
ADDWF REMB1,F
MOVF BARGB0,W
BTFSC STATUS,C
INCFSZ BARGB0,W
ADDWF REMB0,F
CLRW
BTFSC STATUS,C
MOVLW H'1'
ADDWF TEMP,F
UOK22L8
RLF AARGB1,F
MOVLW H'7'
MOVWF LOOPCOUNT
LOOPU3232B
RLF AARGB1,W
RLF REMB3,F
RLF REMB2,F
RLF REMB1,F
RLF REMB0,F
RLF TEMP,F
MOVF BARGB3,W
BTFSS AARGB1,0
GOTO UADD22LB
SUBWF REMB3,F
MOVF BARGB2,W
BTFSS STATUS,C
INCFSZ BARGB2,W
SUBWF REMB2,F
MOVF BARGB1,W
BTFSS STATUS,C
INCFSZ BARGB1,W
SUBWF REMB1,F
MOVF BARGB0,W
BTFSS STATUS,C
INCFSZ BARGB0,W
SUBWF REMB0,F
CLRW
BTFSS STATUS,C
MOVLW H'1'
SUBWF TEMP,F
GOTO UOK22LB
UADD22LB
ADDWF REMB3,F
MOVF BARGB2,W
BTFSC STATUS,C
INCFSZ BARGB2,W
ADDWF REMB2,F
MOVF BARGB1,W
BTFSC STATUS,C
INCFSZ BARGB1,W
ADDWF REMB1,F
MOVF BARGB0,W
BTFSC STATUS,C
INCFSZ BARGB0,W
ADDWF REMB0,F
CLRW
BTFSC STATUS,C
MOVLW H'1'
ADDWF TEMP,F
UOK22LB
RLF AARGB1,F
DECFSZ LOOPCOUNT,F
GOTO LOOPU3232B
RLF AARGB2,W
RLF REMB3,F
RLF REMB2,F
RLF REMB1,F
RLF REMB0,F
RLF TEMP,F
MOVF BARGB3,W
BTFSS AARGB1,0
GOTO UADD22L16
SUBWF REMB3,F
MOVF BARGB2,W
BTFSS STATUS,C
INCFSZ BARGB2,W
SUBWF REMB2,F
MOVF BARGB1,W
BTFSS STATUS,C
INCFSZ BARGB1,W
SUBWF REMB1,F
MOVF BARGB0,W
BTFSS STATUS,C
INCFSZ BARGB0,W
SUBWF REMB0,F
CLRW
BTFSS STATUS,C
MOVLW H'1'
SUBWF TEMP,F
GOTO UOK22L16
UADD22L16
ADDWF REMB3,F
MOVF BARGB2,W
BTFSC STATUS,C
INCFSZ BARGB2,W
ADDWF REMB2,F
MOVF BARGB1,W
BTFSC STATUS,C
INCFSZ BARGB1,W
ADDWF REMB1,F
MOVF BARGB0,W
BTFSC STATUS,C
INCFSZ BARGB0,W
ADDWF REMB0,F
CLRW
BTFSC STATUS,C
MOVLW H'1'
ADDWF TEMP,F
UOK22L16
RLF AARGB2,F
MOVLW H'7'
MOVWF LOOPCOUNT
LOOPU3232C
RLF AARGB2,W
RLF REMB3,F
RLF REMB2,F
RLF REMB1,F
RLF REMB0,F
RLF TEMP,F
MOVF BARGB3,W
BTFSS AARGB2,0
GOTO UADD22LC
SUBWF REMB3,F
MOVF BARGB2,W
BTFSS STATUS,C
INCFSZ BARGB2,W
SUBWF REMB2,F
MOVF BARGB1,W
BTFSS STATUS,C
INCFSZ BARGB1,W
SUBWF REMB1,F
MOVF BARGB0,W
BTFSS STATUS,C
INCFSZ BARGB0,W
SUBWF REMB0,F
CLRW
BTFSS STATUS,C
MOVLW H'1'
SUBWF TEMP,F
GOTO UOK22LC
UADD22LC
ADDWF REMB3,F
MOVF BARGB2,W
BTFSC STATUS,C
INCFSZ BARGB2,W
ADDWF REMB2,F
MOVF BARGB1,W
BTFSC STATUS,C
INCFSZ BARGB1,W
ADDWF REMB1,F
MOVF BARGB0,W
BTFSC STATUS,C
INCFSZ BARGB0,W
ADDWF REMB0,F
CLRW
BTFSC STATUS,C
MOVLW H'1'
ADDWF TEMP,F
UOK22LC
RLF AARGB2,F
DECFSZ LOOPCOUNT,F
GOTO LOOPU3232C
RLF AARGB3,W
RLF REMB3,F
RLF REMB2,F
RLF REMB1,F
RLF REMB0,F
RLF TEMP,F
MOVF BARGB3,W
BTFSS AARGB2,0
GOTO UADD22L24
SUBWF REMB3,F
MOVF BARGB2,W
BTFSS STATUS,C
INCFSZ BARGB2,W
SUBWF REMB2,F
MOVF BARGB1,W
BTFSS STATUS,C
INCFSZ BARGB1,W
SUBWF REMB1,F
MOVF BARGB0,W
BTFSS STATUS,C
INCFSZ BARGB0,W
SUBWF REMB0,F
CLRW
BTFSS STATUS,C
MOVLW H'1'
SUBWF TEMP,F
GOTO UOK22L24
UADD22L24
ADDWF REMB3,F
MOVF BARGB2,W
BTFSC STATUS,C
INCFSZ BARGB2,W
ADDWF REMB2,F
MOVF BARGB1,W
BTFSC STATUS,C
INCFSZ BARGB1,W
ADDWF REMB1,F
MOVF BARGB0,W
BTFSC STATUS,C
INCFSZ BARGB0,W
ADDWF REMB0,F
CLRW
BTFSC STATUS,C
MOVLW H'1'
ADDWF TEMP,F
UOK22L24
RLF AARGB3,F
MOVLW H'7'
MOVWF LOOPCOUNT
LOOPU3232D
RLF AARGB3,W
RLF REMB3,F
RLF REMB2,F
RLF REMB1,F
RLF REMB0,F
RLF TEMP,F
MOVF BARGB3,W
BTFSS AARGB3,0
GOTO UADD22LD
SUBWF REMB3,F
MOVF BARGB2,W
BTFSS STATUS,C
INCFSZ BARGB2,W
SUBWF REMB2,F
MOVF BARGB1,W
BTFSS STATUS,C
INCFSZ BARGB1,W
SUBWF REMB1,F
MOVF BARGB0,W
BTFSS STATUS,C
INCFSZ BARGB0,W
SUBWF REMB0,F
CLRW
BTFSS STATUS,C
MOVLW H'1'
SUBWF TEMP,F
GOTO UOK22LD
UADD22LD
ADDWF REMB3,F
MOVF BARGB2,W
BTFSC STATUS,C
INCFSZ BARGB2,W
ADDWF REMB2,F
MOVF BARGB1,W
BTFSC STATUS,C
INCFSZ BARGB1,W
ADDWF REMB1,F
MOVF BARGB0,W
BTFSC STATUS,C
INCFSZ BARGB0,W
ADDWF REMB0,F
CLRW
BTFSC STATUS,C
MOVLW H'1'
ADDWF TEMP,F
UOK22LD
RLF AARGB3,F
DECFSZ LOOPCOUNT, F
GOTO LOOPU3232D
BTFSC AARGB3,0
GOTO UOK22L
MOVF BARGB3,W
ADDWF REMB3,F
MOVF BARGB2,W
BTFSC STATUS,C
INCFSZ BARGB2,W
ADDWF REMB2,F
MOVF BARGB1,W
BTFSC STATUS,C
INCFSZ BARGB1,W
ADDWF REMB1,F
MOVF BARGB0,W
BTFSC STATUS,C
INCFSZ BARGB0,W
ADDWF REMB0,F
UOK22L
RETURN
;******************
; 8 x 8 multiply
LOOPUM0808A
RRF BARGB0, F
BTFSC STATUS,C
GOTO LUM0808NAP
DECFSZ LOOPCOUNT, F
GOTO LOOPUM0808A
CLRF AARGB0
RETLW H'00'
LUM0808NAP
BCF STATUS,C
GOTO LUM0808NA
LOOPUM0808
RRF BARGB0, F
BTFSC STATUS,C
ADDWF AARGB0, F
LUM0808NA RRF AARGB0, F
RRF AARGB1, F
DECFSZ LOOPCOUNT,F
GOTO LOOPUM0808
return
end