; 100W Solar Charger ; 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 ;Program Configuration Register 1 __CONFIG _CONFIG1, _CP_ALL & _CCP1_RB3 & _DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_ON & _MCLR_ON & _PWRTE_ON & _WDT_OFF & _INTRC_IO ;Program Configuration Register 2 __CONFIG _CONFIG2, _IESO_OFF & _FCMEN_OFF ; 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 ; All Banks RAM ; Interrupt store registers W_TMP equ H'70' ; storage of w before interrupt STATUS_TMP equ H'71' ; status storage before interrupt ; start at memory 0 org 0 goto SETUP org 4 goto INTERRUPT ; position the lookup table at start to avoid a 256 bit boundary TEMP_CONV ; convert A/D values to deg C based on thermistor R=Ae**(B/T) where (T is in K ie deg C plus 273) ; A =0.01058 and B is 4100 addwf PCL,f ; add value to program counter ; 60 deg C max retlw D'60' ; 60deg C for A/D D49 (8-bit) retlw D'59' ; deg C for A/D D50(8-bit) retlw D'58' ; deg C for A/D D51(8-bit) retlw D'58' ; deg C for A/D D52(8-bit) retlw D'57' ; deg C for A/D D53(8-bit) retlw D'57' ; deg C for A/D D54(8-bit) retlw D'56' ; deg C for A/D D55(8-bit) retlw D'56' ; deg C for A/D D56(8-bit) retlw D'55' ; deg C for A/D D57(8-bit) retlw D'54' ; deg C for A/D D58(8-bit) retlw D'54' ; 54 deg C for A/D D59(8-bit) retlw D'53' ; deg C for A/D D60(8-bit) retlw D'53' ; deg C for A/D D61(8-bit) retlw D'52' ; deg C for A/D D62(8-bit) retlw D'52' ; deg C for A/D D63(8-bit) retlw D'51' ; deg C for A/D D64(8-bit) retlw D'50' ; deg C for A/D D65(8-bit) retlw D'50' ; deg C for A/D D66(8-bit) retlw D'50' ; deg C for A/D D67(8-bit) retlw D'49' ; deg C for A/D D68(8-bit) retlw D'49' ; deg C for A/D D69(8-bit) retlw D'48' ; 48 deg C for A/D D70(8-bit) retlw D'48' ; deg C for A/D D71(8-bit) retlw D'47' ; deg C for A/D D72(8-bit) retlw D'47' ; deg C for A/D D73(8-bit) retlw D'46' ; deg C for A/D D74(8-bit) retlw D'46' ; deg C for A/D D75(8-bit) retlw D'45' ; deg C for A/D D76(8-bit) retlw D'45' ; deg C for A/D D77(8-bit) retlw D'44' ; deg C for A/D D78(8-bit) retlw D'44' ; deg C for A/D D79(8-bit) retlw D'43' ; deg C for A/D D80(8-bit) retlw D'43' ; deg C for A/D D81(8-bit) retlw D'43' ; deg C for A/D D82(8-bit) retlw D'42' ; deg C for A/D D83(8-bit) retlw D'42' ; deg C for A/D D84(8-bit) retlw D'41' ; deg C for A/D D85(8-bit) retlw D'41' ; deg C for A/D D86(8-bit) retlw D'40' ; deg C for A/D D87(8-bit) retlw D'40' ; deg C for A/D D88(8-bit) retlw D'40' ; 40 deg C for A/D D89(8-bit) retlw D'39' ; deg C for A/D D90(8-bit) retlw D'39' ; deg C for A/D D91(8-bit) retlw D'38' ; deg C for A/D D92(8-bit) retlw D'38' ; deg C for A/D D93(8-bit) retlw D'38' ; deg C for A/D D94(8-bit) retlw D'37' ; deg C for A/D D95(8-bit) retlw D'37' ; deg C for A/D D96(8-bit) retlw D'36' ; deg C for A/D D97(8-bit) retlw D'36' ; deg C for A/D D98(8-bit) retlw D'36' ; deg C for A/D D99(8-bit) retlw D'35' ; deg C for A/D D100(8-bit) retlw D'35' ; deg C for A/D D101(8-bit) retlw D'34' ; deg C for A/D D102(8-bit) retlw D'34' ; deg C for A/D D103(8-bit) retlw D'34' ; deg C for A/D D104(8-bit) retlw D'33' ; deg C for A/D D105(8-bit) retlw D'33' ; deg C for A/D D106(8-bit) retlw D'33' ; deg C for A/D D107(8-bit) retlw D'32' ; deg C for A/D D108(8-bit) retlw D'32' ; 32 deg C for A/D D109(8-bit) retlw D'32' ; deg C for A/D D110(8-bit) retlw D'31' ; deg C for A/D D111(8-bit) retlw D'31' ; deg C for A/D D112(8-bit) retlw D'30' ; deg C for A/D D113(8-bit) retlw D'30' ; deg C for A/D D114(8-bit) retlw D'30' ; deg C for A/D D115(8-bit) retlw D'29' ; deg C for A/D D116(8-bit) retlw D'29' ; deg C for A/D D117(8-bit) retlw D'29' ; deg C for A/D D118(8-bit) retlw D'28' ; deg C for A/D D119(8-bit) retlw D'28' ; deg C for A/D D120(8-bit) retlw D'28' ; deg C for A/D D121(8-bit) retlw D'27' ; deg C for A/D D122(8-bit) retlw D'27' ; deg C for A/D D123(8-bit) retlw D'27' ; deg C for A/D D124(8-bit) retlw D'26' ; deg C for A/D D125(8-bit) retlw D'26' ; deg C for A/D D126(8-bit) retlw D'26' ; deg C for A/D D127(8-bit) retlw D'25' ; deg C for A/D D128(8-bit) retlw D'25' ; deg C for A/D D129(8-bit) retlw D'24' ; deg C for A/D D130(8-bit) retlw D'24' ; deg C for A/D D131(8-bit) retlw D'24' ; deg C for A/D D132(8-bit) retlw D'24' ; deg C for A/D D133(8-bit) retlw D'23' ; deg C for A/D D134(8-bit) retlw D'23' ; deg C for A/D D135(8-bit) retlw D'23' ; deg C for A/D D136(8-bit) retlw D'22' ; deg C for A/D D137(8-bit) retlw D'22' ; deg C for A/D D138(8-bit) retlw D'22' ; deg C for A/D D139(8-bit) retlw D'21' ; deg C for A/D D140(8-bit) retlw D'21' ; deg C for A/D D141(8-bit) retlw D'21' ; deg C for A/D D142(8-bit) retlw D'20' ; deg C for A/D D143(8-bit) retlw D'20' ; deg C for A/D D144(8-bit) retlw D'20' ; deg C for A/D D145(8-bit) retlw D'19' ; deg C for A/D D146(8-bit) retlw D'19' ; deg C for A/D D147(8-bit) retlw D'19' ; deg C for A/D D148(8-bit) retlw D'18' ; deg C for A/D D149(8-bit) retlw D'18' ; deg C for A/D D150(8-bit) retlw D'18' ; deg C for A/D D151(8-bit) retlw D'17' ; deg C for A/D D152(8-bit) retlw D'17' ; deg C for A/D D153(8-bit) retlw D'17' ; deg C for A/D D154(8-bit) retlw D'16' ; deg C for A/D D155(8-bit) retlw D'16' ; deg C for A/D D156(8-bit) retlw D'16' ; deg C for A/D D157(8-bit) retlw D'15' ; deg C for A/D D158(8-bit) retlw D'15' ; deg C for A/D D159(8-bit) retlw D'15' ; deg C for A/D D160(8-bit) retlw D'14' ; deg C for A/D D161(8-bit) retlw D'14' ; deg C for A/D D162(8-bit) retlw D'14' ; deg C for A/D D163(8-bit) retlw D'13' ; deg C for A/D D164(8-bit) retlw D'13' ; deg C for A/D D165(8-bit) retlw D'13' ; deg C for A/D D166(8-bit) retlw D'12' ; deg C for A/D D167(8-bit) retlw D'12' ; deg C for A/D D168(8-bit) retlw D'12' ; deg C for A/D D169(8-bit) retlw D'11' ; deg C for A/D D170(8-bit) retlw D'11' ; deg C for A/D D171(8-bit) retlw D'11' ; deg C for A/D D172(8-bit) retlw D'10' ; deg C for A/D D173(8-bit) retlw D'10' ; deg C for A/D D174(8-bit) retlw D'10' ; deg C for A/D D175(8-bit) retlw D'9' ; deg C for A/D D176(8-bit) retlw D'9' ; deg C for A/D D177(8-bit) retlw D'8' ; deg C for A/D D178(8-bit) retlw D'8' ; 8 deg C for A/D D179(8-bit) retlw D'8' ; deg C for A/D D180(8-bit) retlw D'7' ; deg C for A/D D181(8-bit) retlw D'7' ; deg C for A/D D182(8-bit) retlw D'7' ; deg C for A/D D183(8-bit) retlw D'6' ; deg C for A/D D184(8-bit) retlw D'6' ; deg C for A/D D185(8-bit) retlw D'6' ; deg C for A/D D186(8-bit) retlw D'5' ; deg C for A/D D187(8-bit) retlw D'5' ; deg C for A/D D188(8-bit) retlw D'4' ; 4 deg C for A/D D189(8-bit) retlw D'4' ; deg C for A/D D190(8-bit) retlw D'4' ; deg C for A/D D191(8-bit) retlw D'3' ; deg C for A/D D192(8-bit) retlw D'3' ; deg C for A/D D193(8-bit) retlw D'2' ; deg C for A/D D194(8-bit) retlw D'2' ; deg C for A/D D195(8-bit) retlw D'2' ; deg C for A/D D196(8-bit) retlw D'1' ; deg C for A/D D197(8-bit) retlw D'1' ; deg C for A/D D198(8-bit) retlw D'0' ; deg C for A/D D199(8-bit) ; 0 deg C min retlw D'0' ; 0 deg C for A/D D200(8-bit) ;********************************************************************************************** SETUP clrf PORTB ; outputs low clrf PORTA ; set inputs/outputs bsf STATUS,RP0 ; select memory bank 1 movlw B'00000111' ; comparators off movwf CMCON movlw B'00010011' ; port B outputs/ inputs set movwf TRISB ; port B data direction register movlw B'00111111' ; outputs (0) and inputs (1) movwf TRISA ; port A data direction register movlw B'00000111' ; settings (pullups enabled, TMR0/256) movwf OPTION_REG ; analog inputs, A/D movlw B'00011111' ; AN0 to AN4 are analog inputs movwf ANSEL ; movlw B'10000000' ; * 4MHz operation right justified A/D result, Vdd to Vss A/D movlw B'11000000' ; ** 8MHz operation right justified A/D result, Vdd to Vss A/D movwf ADCON1 bcf STATUS,RP0 ; select memory bank 0 movlw B'01000000' ; Fosc, channel 0 etc movwf ADCON0 bsf ADCON0,ADON ; A/D on bsf STATUS,RP0 ; select memory bank 1 ; movlw B'01101000' ; * 4MHz operation movlw B'01111000' ; ** 8MHz operation 8MHz movwf OSCCON ; bcf STATUS,RP0 ; select memory bank 0 ; timer 1 ; movlw B'00100001' ; * 4MHz operation timer 1 prescaler /4, fosc/4 movlw B'00110001' ; ** 8MHz operation timer 1 prescaler /8, fosc/4 movwf T1CON bsf T1CON,0 ; timer 1 on bsf STATUS,RP0 ; select memory bank 1 ; movlw H'1F' ; * 4MHz operation 31.24kHz pwm rate 7-bit resolution movlw H'3F' ; ** 8MHz operation 31.24kHz pwm rate 8-bit resolution movwf PR2 ; PWM period register bcf STATUS,RP0 ; memory bank 0 ; 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 ; load SLA preset values ; battery voltage reduced to 0.3125 so 14.4V becomes 4.50V and D920 (H398) with A/D conversion (10-bit) movlw H'03' movwf CUT_M ; cutout SLA voltage high byte 14.4V movlw H'98' movwf CUT_L ; cutout SLA voltage low byte movlw H'03' movwf FLOAT_H ; float SLA voltage high byte 13.5V movlw H'5F' movwf FLOAT_L ; float SLA voltage low byte movlw H'03' movwf EQ_HI ; Equalsiation voltage high byte (14.4V x 10%)= 15.84V movlw H'F4' movwf EQ_LO ; Equalisation voltage low byte 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 ;******************************************************* CYCLE ; beginining of normal running loop ; sensors checked periodically decfsz SENSOR_COUNT,f goto CHARGE_MODE decfsz SENSOR_COUNT1,f goto CHARGE_MODE ; when both zero ; movlw D'4' ; * 4MHz operation movlw D'8' ; ** 8MHz operation movwf SENSOR_COUNT1 ; set period to about 500ms SENSORS ; equalisation input btfss PORTB,4 ; equalisation input selection goto LOW_IN btfss EQ_LEVEL,4 ; input store goto HI_IN ; if portB,4 is high and EQ_LEVEL,4 is also high set EQ_FLAG,0 (no equalisation) clrf EQ_FLAG bsf EQ_FLAG,0 ; no equalisation when flag is set (PORTB,4 is high) goto CH_1AD LOW_IN btfss EQ_LEVEL,4 goto CH_1AD ; if portB,4 and EQ_LEVEL,4 both low ignore ; 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 ; level change from H/L indicates equalisation required ; flash LEDS bcf INTCON,GIE ; stop interrupt bcf PORTA,7 ; Bulk LED off bcf PORTB,7 ; Float LED off bcf PORTA,6 ; Absorption LED off bsf PORTB,6 ; equalisation LED on call DELAY bcf PORTB,6 ; Equalisation LED off call DELAY bsf PORTB,6 ; Equalisation LED on call DELAY bcf PORTB,6 ; Equalisation LED off call DELAY bsf INTCON,GIE ; interrupt starts again goto CH_1AD 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) bsf EQ_LEVEL,4 ; store portB,4 level bsf EQ_FLAG,0 ; no equalisation ; Channel 1 A/D value(mV/deg C Compensation) ; compensation calculated as (Comp/50) x 255 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' ; reduce from 10-bit to 8-bit rrf ADRESH,f ; move right ls byte rrf DIGITAL,f ; ls byte moved right rrf ADRESH,f ; move right ls byte rrf DIGITAL,f ; ls byte moved right ; write compensation value movf DIGITAL,w ; 8-bit byte movwf COMP ; mV/deg C SLA compensation ; Channel 4 A/D value (thermistor (temperature)) CH_4AD ; set analog input address bsf ADCON0,5 bcf ADCON0,4 bcf ADCON0,3 ; A/D No.4 call DEL_AD ; convert to digital ls bits in 'DIGITAL' ; change from 10-bit to 8-bit rrf ADRESH,f ; move right ls byte rrf DIGITAL,f ; ls byte moved right rrf ADRESH,f ; move right ls byte rrf DIGITAL,f ; ls byte moved right ; check for thermistor out of circuit movf DIGITAL,w sublw D'250' ; >250 bcf INTCON,GIE ; stop interrupt clrf THERMISTOR ; clear value btfsc STATUS,C goto CK_ZRO bsf THERMISTOR,0 ; set bit 0 when out of circuit goto BY_ZRO ; check for zero degrees or less CK_ZRO movf DIGITAL,w sublw D'199' ; >199 movlw D'199' ; keep at 0 degrees btfss STATUS,C movwf DIGITAL ; keep at 0 degrees C so compensation plateaus below 0 degrees C ; check for thermistor short circuit movlw D'04' subwf DIGITAL,w ; if less than 4 btfss STATUS,C bsf THERMISTOR,1 ; set when short circuit 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 ; find compensation requirement with temperature difference from 20 deg C ; multiplied by D100 and divided by D8000 to calculate mV/deg C for cutout and float voltages ; this is added (for <20 deg C) or subtracted (for >20deg C) from cutoff and float Voltages. ; take away 20 deg C clrf NEGATIVE ; subtract flag movlw D'20' ; 20 deg C subwf TEMPERATURE,w ; btfss STATUS,C ; if negative then less than 20 deg C bsf NEGATIVE,7 ; (temperature - 20) x 100 movwf AARGB0 ; if negative then subtract from 20 btfss NEGATIVE,7 goto CONTINUE1 movf TEMPERATURE,w sublw D'20' ; temperature from 20 movwf AARGB0 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 ; take compensation value from equalisation voltage and place in EQ_LO_COMP, EQ_HI_COMP CHECK_EQ movf AARGB3,w ; result subwf EQ_LO,w movwf EQ_LO_COMP movf EQ_HI,w ; ms btfss STATUS,C decf EQ_HI,w ; decrease if carry movwf EQ_HI_COMP btfss EQ_HI_COMP,7 ; if bit 7 set then over so clear goto CHECK_FLOAT clrf EQ_HI_COMP clrf EQ_LO_COMP goto CHECK_FLOAT 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 ; check if over 1024 btfss CUT_COMP_M,2 ; if bit set over so set at 1023 goto CHECK_EQ_PLUS movlw B'00000011' ; set at 1023 movwf CUT_COMP_M movlw H'FF' movwf CUT_COMP_L CHECK_EQ_PLUS movf EQ_HI,w movwf EQ_HI_COMP movf AARGB3,w ; result addwf EQ_LO,w movwf EQ_LO_COMP btfsc STATUS,C incf EQ_HI_COMP,f ; increase if carry ; check if over 1024 btfss EQ_HI_COMP,2 ; if bit set over so set at 1023 goto CHECK_FLOAT movlw B'00000011' ; set at 1023 movwf EQ_HI_COMP movlw H'FF' movwf EQ_LO_COMP ; Float calculations CHECK_FLOAT btfsc NEGATIVE,7 ; if set add value goto ADD_COMP2 ; take compensation value from float V and place in FLOAT_COMP_M/LS movf AARGB3,w ; result subwf FLOAT_L,w movwf FLOAT_COMP_L movf FLOAT_H,w ; ms float V btfss STATUS,C decf FLOAT_H,w ; decrease if carry 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 ; check if over 1024 btfss FLOAT_COMP_M,2 ; if bit set over so set at 1023 goto CH_0AD movlw B'00000011' ; set at 1023 movwf FLOAT_COMP_M movlw H'FF' movwf FLOAT_COMP_L ; Battery voltage, Channel 0 A/D ; voltage at AN2 is 0.3125 of actual measured due to divider ; so 15V is reduced to 4.6875V and results in D960 from A/D converter (10-bit value) ; this divider value sets the other cutoff, float and compensation calculations CH_0AD ; set analog input address bcf ADCON0,5 bcf ADCON0,4 bcf ADCON0,3 ; call DEL_AD movf DIGITAL,w movwf BATT_LO ; battery voltage ls byte movf ADRESH,w ; ms byte movwf BATT_HI ; battery voltage ms byte ; check if below 12.45V or about 75% of capacity ; A/D is (D796, H31C). Reset to main Bulk when voltage drops to below 12.45V movf BATT_HI,w ; high byte of battery voltage sublw H'3' ; take from movwf DIGITAL ; store movf BATT_LO,w ; low byte sublw H'1C' ; 12.45V btfss STATUS,C decf DIGITAL,f ; decrease if required btfsc DIGITAL,7 ; if set then >12.45V goto BY_BULK_SET clrf CHARGE_STATE ; below 12.45V so set for bulk/main charging clrf BULK_TIMER clrf BULK_TIMER_END ; bulk timer ended flag ; end of switched sensors BY_BULK_SET bsf CHRG_RATE,0 ; charge rate flag set to show new values available ; Charge Control CHARGE_MODE ; if THERMISTOR,1 is set (ie a short circuit) btfss THERMISTOR,1 ; short circuit thermistor goto CHK_ZRO_BIT bsf CHARGE_FLAG,0 ; set charge flag so no charge goto NO_CHARGE CHK_ZRO_BIT btfss THERMISTOR,0 ; thermistor out goto CHK_BATT bsf CHARGE_FLAG,0 ; set charge flag so no charge goto NO_CHARGE CHK_BATT ; battery voltage: if low then apply bursts till >10.5V (D671, H29F) ; check if below 10.5V. 10.5V = 29F ;(for testing set values to test at 33F for 13V) movf BATT_HI,w ; high byte of battery voltage sublw H'2' ; take from 10.5V (H29F) movwf DIGITAL ; store movf BATT_LO,w ; low byte sublw H'9F' ; 10.5V (H29F) btfss STATUS,C decf DIGITAL,f ; decrease if required btfss DIGITAL,7 ; if set then >10.5V goto BURST ; burst charge till voltage is above 10.5V clrf BURST_FLG ; burst flag off (no burst) ; if battery above 15V (usually when an O/C cell) then show Batt. LED ; first check if Equalisation running btfss EQ_FLAG,1 ; when set equalisation is running so bypass since >15V during eq goto BATT15 bsf PORTB,2 ; equalisation and >15V output. High on equalisation goto MODE_CHARGE 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 ; if above 12V (3.75V after division (H2FF)) set RB2 low BATT12 movf BATT_HI,w ; high byte of battery voltage sublw H'2' ; take from 12V movwf DIGITAL ; store movf BATT_LO,w ; low byte sublw H'FF' ; 12V btfss STATUS,C decf DIGITAL,f ; decrease if required btfss DIGITAL,7 ; if set then >12V goto BATT11.5 bcf PORTB,2 ; output low at <15V and >12V goto MODE_CHARGE ; if below 11.5V (3.59V after division (H2DF)) set RB2 high BATT11.5 movf BATT_HI,w ; high byte of battery voltage sublw H'2' ; take from 11.5V movwf DIGITAL ; store movf BATT_LO,w ; low byte sublw H'DF' ; 11.5V btfss STATUS,C decf DIGITAL,f ; decrease if required btfss DIGITAL,7 ; if set then >11.5V bsf PORTB,2 ; set when <11.5V MODE_CHARGE bcf BATT_IND,0 ; Batt.indicator LED off ; charge mode ; measure solar cell voltage ; AN2 ; solar cell voltage is divided by a factor of 0.176 ; set analog input address bcf ADCON0,5 bsf ADCON0,4 bcf ADCON0,3 ; call DEL_AD movf DIGITAL,w movwf CELL_LO ; solar cell voltage ls byte movf ADRESH,w ; ms byte movwf CELL_HI ; solar cell voltage ms byte ; 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 ; charge; check charge status. Bulk charge or absorption/ float (trickle) clrf CHARGE_FLAG ; charging flag movf CHARGE_STATE,w ; 0 Bulk, 1 float btfsc STATUS,Z goto CHARGE_FULL goto CHARGE_ABSORP_FLOAT NO_CHARGE bsf CHARGE_FLAG,0 ; no charge flag clrf CCPR1L ; charge off clrf FIRST movlw D'5' ; 5 x 0.262ms movwf PERIOD ; check if 4-hour timer is set movf HOUR3,w ; if zero then not yet set btfss STATUS,Z goto CYCLE ; not set bcf STATUS,GIE ; stop interrupt ; set timer movlw H'FF' ; 256 counts for 4 hours ; ** test timer, remark out for normal 4 hours ; movlw H'1' ; ** about 56 seconds timer. For use as a shorter test period ; ** movwf HOUR3 ; set 4 hour timer clrf HOUR2 bsf STATUS,GIE ; allow interrupt goto CYCLE CHARGE_FULL; (CHARGE_STATE = 0) main bulk charge 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 ; end of bulk charge 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 ABS_TME ; absorption timer set clrf CCPR1L clrf HOUR1 ; 14 seconds counter movlw H'FF' ; 256 counts for 1 hour ; ** test timer, remark out for normal 1hour ; movlw H'4' ; ** about 42-56 seconds timer. For use as a shorter test period ; ** movwf HOUR0 ; set absorption period @ 1 hour BY_SET movlw D'5' ; 5 x 0.262ms movwf PERIOD goto CHARGE_ABSORP_FLOAT ; 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 ; measure solar cell current ; AN3 CH_3AD ; solar cell current (1V=2.21A) ; set analog input address bcf ADCON0,5 bsf ADCON0,4 bsf ADCON0,3 ; call DEL_AD movf DIGITAL,w movwf CELL_I_LO ; solar cell current ls byte movf ADRESH,w ; ms byte movwf CELL_I_HI ; solar cell current ms byte ; AN2 CH_2AD ; solar cell voltage is divided by a factor of 0.176 ; set analog input address bcf ADCON0,5 bsf ADCON0,4 bcf ADCON0,3 ; call DEL_AD movf DIGITAL,w movwf CELL_LO ; solar cell voltage ls byte movf ADRESH,w ; ms byte movwf CELL_HI ; solar cell voltage ms byte ; multiply CELL_HI, CELL_LO by CELL_I_HI, CELL_I_LO check for maximum ; 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 TRANSFER ; transfer values ; new power is larger than last, transfer to POWERH,POWERL ; transfer CCPR1L into CCPR1_STORE movf AARGB0,w movwf POWERH movf AARGB1,w movwf POWERL movf CCPR1L,w movwf CCPR1_STORE 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 ; Measure battery Voltage ; set analog input address bcf ADCON0,5 bcf ADCON0,4 bcf ADCON0,3 ; call DEL_AD movf DIGITAL,w movwf BATT_LO ; battery voltage ls byte movf ADRESH,w ; ms byte movwf BATT_HI ; battery voltage ms byte ; if battery voltage is D1023 (H3FF) then over in value movf BATT_HI,w ; ms byte xorlw H'03' ; 3 btfss STATUS,Z goto TEST_BATT3 ; not equal movf BATT_LO,w xorlw H'FF' btfsc STATUS,Z goto NO_CHARGE ; battery voltage high so end charge TEST_BATT3 ; alter CHARGE_CONT to adjust the drive to maintain float V ; set values to 8-bit ; battery rrf BATT_HI,w movwf VALUE1 rrf BATT_LO,w ; get value difference movwf VALUE2 rrf VALUE1,w rrf VALUE2,f ; check hour timer. If still timing then absorption. if timer ended (hour0=0) then float movf HOUR0,w btfsc STATUS,Z goto FLOAT_VALUES ; check Equalisation or Absorption btfsc EQ_LEVEL,4 ; when low run equalisation unless already run (EQ_FLAG,0 set) goto ABSORPTION_VALUES btfsc EQ_FLAG,0 ; if flag is set equalisation has already run so bypass to absorption goto ABSORPTION_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 ; compare battery with compensated cutoff V movf BATT_HI,w ; high byte of battery voltage subwf EQ_HI_COMP,w ; take from compensated equalisation Voltage movwf DIGITAL ; store movf BATT_LO,w ; low byte subwf EQ_LO_COMP,w ; take from compensated V btfss STATUS,C decf DIGITAL,f ; decrease if required btfss DIGITAL,7 ; if set then battery voltage is over cut voltage goto PWM_CONTROL ; control power goto DECREASE_CHARGE 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 ; compare battery with compensated cutoff V movf BATT_HI,w ; high byte of battery voltage subwf CUT_COMP_M,w ; take from compensated cut V movwf DIGITAL ; store movf BATT_LO,w ; low byte subwf CUT_COMP_L,w ; take from compensated cut V btfss STATUS,C decf DIGITAL,f ; decrease if required btfss DIGITAL,7 ; if set then battery voltage is over cut voltage goto PWM_CONTROL ; control power goto DECREASE_CHARGE 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 ; compare battery with float V movf BATT_HI,w ; high byte of battery voltage subwf FLOAT_COMP_M,w ; take from compensated float movwf DIGITAL ; store movf BATT_LO,w ; low byte subwf FLOAT_COMP_L,w ; take from compensated float V btfss STATUS,C decf DIGITAL,f ; decrease if required btfsc DIGITAL,7 ; if set then battery voltage is over cut voltage goto DECREASE_CHARGE ; 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 ; control of PWM other than for full power PWM_CONTROL movf CCPR1L,w subwf CCPR1_STORE,w btfss STATUS,C ; if over max power point PWM value go to FULL POWER mode goto FULL_POWER_RUN btfsc STATUS,Z goto FULL_POWER_RUN incf CCPR1L,w sublw D'64' btfss STATUS,C goto FULL_POWER_RUN incf CCPR1L,f 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 movf VALUE2,w ; subtracted value subwf CCPR1L,w btfss STATUS,C ; if negative set at 0 clrw movwf CCPR1L ; reduce charge goto CYCLE CLEAR_CHRG clrf CCPR1L goto CYCLE 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 pulses of current till voltage >10.5V movf FLASHER,w ; flasher counter (0-255 count) andlw B'00001111' ; ; only burst is on for 1 in 16 (6.25% on duty cycle) at a 4.2s rate btfss STATUS,Z goto BURST_OFF ; Burst on bsf PORTA,7 ; Bulk LED on movlw D'64' movwf CCPR1L ; set full charge goto CYCLE 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 bcf PIR1,TMR1IF ; clear flag FLASH1 ; flasher rate (increases every 0.262ms) incf FLASHER,f ; flasher ; rate for power calculation during charging movf PERIOD,w ; period for charging power cycle btfss STATUS,Z decf PERIOD,f ; decrease if not 0 ; flash NTC Thermistor LED(PORTB,5)if required ; check thermistor btfss THERMISTOR,0 ; when set, thermistor is out of circuit goto CK_THERM1 ; 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 NC thermistor LED movf FLASHER,w andlw B'00001111' ; flash 262ms on each 2 seconds btfsc STATUS,Z ; goto SET_OUT bcf PORTB,5 ; NTC thermistor LED off goto CHECK_END SET_OUT bsf PORTB,5 ; NTC thermistor LED on goto CHECK_END 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 main or trickle btfss CHARGE_STATE,0 ; clear then main Bulk goto MAIN_LED ; if HOUR0 is clear then float. Otherwise absorption movf HOUR0,w btfsc STATUS,Z goto FLOAT ; ; Absorption or Equalisation btfss EQ_FLAG,1 ; when set Equalisation in process goto ABSORPTION EQUALISATION bcf PORTB,5 ; NTC thermistor LED off bcf PORTA,7 ; Bulk LED off bcf PORTB,7 ; Float LED off bcf PORTA,6 ; Absorption LED off bsf PORTB,6 ; Equalisation LED on goto CHECK_END ABSORPTION bcf PORTB,5 ; NTC thermistor LED off bcf PORTA,7 ; Bulk LED off bcf PORTB,7 ; Float LED off bcf PORTB,6 ; Equalisation LED off bsf PORTA,6 ; Absorption LED on goto CHECK_END ; FLOAT bcf PORTB,5 ; NTC thermistor LED off bcf PORTA,7 ; Bulk LED off bsf PORTB,7 ; Float LED on bcf PORTA,6 ; Absorption LED off bcf PORTB,6 ; Equalisation LED off goto CHECK_END ; MAIN_LED ;(main Bulk) bcf PORTB,5 ; NTC thermistor LED off bsf PORTA,7 ; Bulk LED on bcf PORTA,6 ; Absorption LED off bcf PORTB,7 ; Float LED off bcf PORTB,6 ; Equalisation LED off goto CHECK_END ; OFF_CHRG ; charge LEDs off bcf PORTA,7 ; Bulk LED off BURST_IND ; for burst indication bcf PORTA,6 ; Absorption LED off bcf PORTB,7 ; Float LED off bcf PORTB,6 ; Equalisation LED off ; flash Equalisation LED once run btfss EQ_FLAG,2 ; equalisation run flag goto HOUR_TIMER movf FLASHER,w andlw B'00001111' ; flash 262ms on each 2 seconds btfss STATUS,Z goto OFF_TIMER bsf PORTB,6 ; equalisation LED flashes goto OFF_TIMER ; bypass hour timer when charge is off CHECK_END ; flash Equalisation LED once run btfss EQ_FLAG,2 ; equalisation run flag goto HOUR_TIMER movf FLASHER,w andlw B'00001111' ; flash 262ms on each 2 seconds btfss STATUS,Z goto HOUR_TIMER bsf PORTB,6 ; equalisation LED flashes ; 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 movf HOUR0,w ; starts at 255 so 256 x 14s = 1 hour btfss STATUS,Z ; check if zero decf HOUR0,f ; no decrease if already 0 ; decrease bulk timer (used to check if bulk charge < 1 minute BULK_TIME movf BULK_TIMER,w btfss STATUS,Z decfsz BULK_TIMER,f ; decrease til zero goto OFF_TIMER bsf BULK_TIMER_END,0; bulk timer ended flag ; solar panel 4-hour off timer OFF_TIMER ; off timer is included if RB0 is low btfsc PORTB,0 goto RECLAIM incf HOUR2,f ; seconds movf HOUR2,w sublw D'208' ; 56 seconds btfsc STATUS,C goto RECLAIM clrf HOUR2 ; cleared when 56-seconds reached movf HOUR3,w ; starts at 255 so 256 x 56s = 4 hour btfsc STATUS,Z ; check if zero goto RECLAIM ; no decrease if already 0 decfsz HOUR3,f ; goto RECLAIM clrf CHARGE_STATE ; set to Bulk charge after 4 hours off clrf BULK_TIMER clrf BULK_TIMER_END ; bulk timer ended flag 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 for A/D acquisition DEL_AD ; movlw D'50' ; * 4MHz operation movlw D'100' ; ** 8MHz operation movwf DELCNT DEL1 decfsz DELCNT,f goto DEL1 bsf ADCON0,2 ; GO/DONE bit start conversion WAIT_CONV1 btfsc ADCON0,2 ; conversion complete when cleared ~11 cycles goto WAIT_CONV1 bsf STATUS,RP0 ; select memory bank 1 movf ADRESL,w ; ls bits bcf STATUS,RP0 ; select memory bank 0 movwf DIGITAL return ; delay general purpose debounce switch 500ms DELAY ; movlw D'2' ; * 4MHz operation movlw D'4' ; ** 8MHz operation number of delay cycles DELAY_1 movwf DELCNT 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 EIGHTEIGHT CLRF AARGB1 ; clear partial product UMUL0808L MOVLW H'08' MOVWF LOOPCOUNT MOVF AARGB0,W 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 .HEX :020000040000FA :020000009E2838 :080008001D2B82073C343B3440 :100010003A343A343934393438343834373436347D :100020003634353435343434343433343234323491 :10003000323431343134303430342F342F342E34A0 :100040002E342D342D342C342C342B342B342B34AF :100050002A342A34293429342834283428342734BB :1000600027342634263426342534253424342434C5 :1000700024342334233422342234223421342134CE :1000800021342034203420341F341F341E341E34D5 :100090001E341D341D341D341C341C341C341B34DC :1000A0001B341B341A341A341A34193419341834E2 :1000B00018341834183417341734173416341634E7 :1000C00016341534153415341434143414341334EC :1000D00013341334123412341234113411341134F1 :1000E0001034103410340F340F340F340E340E34F7 :1000F0000E340D340D340D340C340C340C340B34FC :100100000B340B340A340A340A3409340934083401 :100110000834083407340734073406340634063408 :100120000534053404340434043403340334023411 :100130000234023401340134003400348601850174 :10014000831607309C00133086003F30850007304F :1001500081001F309B00C0309F00831240309F0001 :100160001F14831678308F008312313090001014E2 :1001700083163F3092008312950117129712920155 :1001800012150C30970086018501AC010130B600D4 :10019000B700BC01BD010530C100C201A101C3010E :1001A000C401AA01BE01B401B501D201D101C90146 :1001B0004914CE01CF01D001D301D4010330A200F4 :1001C0009830A3000330A4005F30A5000330CB00BB :1001D000F430CA0083160C1483120C100B178B1703 :1001E000B60BD129B70BD1290830B700061EFD2860 :1001F0004E1E1229C901491417294E1E1729B6236C :10020000061A1729CE01C9018B138513861305130E :100210000617B6230613B6230617B6230613B6230E :100220008B171729B623061E17294E1649149F123D :100230001F129F15AA239E0CA00C9E0CA00C200838 :10024000A6009F161F129F11AA239E0CA00C9E0CA5 :10025000A00C2008FA3C8B13AC01031831292C1494 :100260003A292008C73CC730031CA00004302002F4 :10027000031CAC148B172008C73CC830031CA0001B :100280003130A002031CA00120080520AB00B10101 :1002900014302B02031CB117EA00B11F52292B089E :1002A000143CEA002608EE00B0256908E8006A0858 :1002B000E900EA016430EC00ED01EE01D1236808A9 :1002C000EA006708E9006608E8006508E700EE0153 :1002D000ED011F30EC004030EB003824B11B8729C2 :1002E00067082302AE002208031C2203AD00AD1FE5 :1002F0007B29AD01AE0167084A02CC004B08031C04 :100300004B03CD00CD1FA129CD01CC01A12922088D :10031000AD0067082307AE000318AD0A2D1D942910 :100320000330AD00FF30AE004B08CD0067084A0730 :10033000CC000318CD0A4D1DA1290330CD00FF309C :10034000CC00B11BAF2967082502B0002408031CAC :100350002403AF00AF1FBC29AF01B001BC292408A2 :10036000AF0067082507B0000318AF0A2F1DBC298E :100370000330AF00FF30B0009F121F129F11AA235D :100380002008A8001E08A7002708033CA000280892 :100390001C3C031CA003A01BD029BC01D301D40129 :1003A0003E14AC1CD5293D14202A2C1CD9293D14FF :1003B000202A2708023CA00028089F3C031CA00319 :1003C000A01F0E2BD001C91CE7290615082A2708F3 :1003D000033CA0002808BF3C031CA003A01FF42975 :1003E0003D144F140615202A2708023CA0002808B7 :1003F000FF3C031CA003A01FFF290611082A2708A1 :10040000023CA0002808DF3C031CA003A01F061527 :100410004F109F121F169F11AA232008B8001E0814 :10042000B9003908013CA0003808B03C031CA00307 :10043000A01F202AD101BD013C0803192E2A952AAC :100440003D149501A1010530C1005108031DF0289C :100450008313FF30D100D2018317F02827082D0223 :10046000A00028082E02031CA003A01F432A541832 :100470003C2AB401D401402A9501B501FF30B400F3 :100480000530C100952A3C08031D4B2A5308031D63 :100490004B2AE530D3004108031DF0282108031D35 :1004A000582AC301C4019501C323C201FF30A10032 :1004B0009F121F169F15AA232008BA001E08BB0012 :1004C0009F121F169F11AA232008B8001E08B9000A :1004D000390CA000380CBF00200CBF0C3B0CA00056 :1004E0003A0CC000200CC00C3F08EA004008EE00A7 :1004F000B0256A084302A00069084402031CA00357 :10050000A01F882A6A08C3006908C4001508C20031 :100510001508403C031C8F2A950ACC23F0284C3048 :10052000C100A10142089500F0280130BC00D401AF :100530009F121F129F11AA232008A8001E08A700BF :100540002708033A031DA82A2808FF3A0319202A7E :10055000270CC500280CC600450CC60C340803192E :10056000D72A4E1AC62A4918C62AC9144D0CC700E4 :100570004C0CC800470CC80C27084D02A0002808E6 :100580004C02031CA003A01FF42A002BC9102D0C41 :10059000C7002E0CC800470CC80C27082D02A0006D :1005A00028082E02031CA003A01FF42A002B4914C4 :1005B000C9184915C9102F0CC700300CC800470CCA :1005C000C80C27082F02A00028083002031CA00333 :1005D000A01B002B8618F42A42081502031CF42ADB :1005E000BC01D301D401F02815084202031C432AA0 :1005F0000319432A150A403C031C432A950AF02894 :100600004808C6024608033C031C0C2B460815028A :10061000031C03019500F0289501F02850140513E0 :10062000861306132A080F39031D1A2B851740302D :100630009500F02885139501F028F000030EF100D5 :10064000831203130C10AA0A4108031DC1032C1CBA :10065000352B85130513861306132A080F39031942 :10066000332B8612802B8616802BAC1C432B8513D4 :100670000513861306132A0807390319412B86121E :10068000802B8616802B4F1C502B051386130613C8 :100690002A08073903194E2B8513802B8517802BC9 :1006A0003D08031D742B5018752B3C1C6E2B340811 :1006B0000319682BC91C622B861285138613051338 :1006C0000617802B86128513861306130517802BB9 :1006D00086128513861705130613802B861285173D :1006E000051386130613802B851305138613061333 :1006F000491D872B2A080F39031D952B0617952BAB :10070000491D872B2A080F39031D872B0617B50AA9 :100710003508343C0318902BB5013408031DB4038D :100720005308031DD30B952B54140618A52BD20A7E :100730005208D03C0318A52BD20151080319A52B50 :10074000D10BA52BBC01D301D401710E8300F00E97 :10075000700E09006430A900A90BAC2B1F151F19DE :10076000AF2B83161E088312A00008000430A900D6 :10077000FF30B200FF30B300B30BBC2BB20BBA2B6F :10078000A90BB82B08000830B200FF30B300B30B40 :10079000C72BB20BC52B08003A30B300B30BCE2BDE :1007A0000800E701E601E5016A08DD006908DE00EE :1007B0006808DF000830EF00EC0C0318F52BEF0B96 :1007C000DC2BEF00ED0C0318F32BEF0BE22BEF000B :1007D000EE0C0318F12BEF0BE82BEA01E901E8011D :1007E000003403102F2C0310192C0310042CEC0CD4 :1007F000031C042C5F08E8075E0803185E0FE90776 :100800005D0803185D0FEA07EA0CE90CE80CE70C39 :10081000EF0BF72B0830EF00ED0C031C192C5F08D1 :10082000E8075E0803185E0FE9075D0803185D0F0F :10083000EA07EA0CE90CE80CE70CE60CEF0B0C2CD1 :100840000830EF00EE0C031C2F2C5F08E8075E0851 :1008500003185E0FE9075D0803185D0FEA07EA0C4D :10086000E90CE80CE70CE60CE50CEF0B222C080079 :10087000E401E301E201E1013E240800E0016A0D28 :10088000E10D6B08E1026C08031C6C0FE2026D08BD :10089000031C6D0FE3026E08031C6E0FE4020301DC :1008A000031C0130E002EA0D0730EF006A0DE10D94 :1008B000E20DE30DE40DE00D6B086A1C712CE10202 :1008C0006C08031C6C0FE2026D08031C6D0FE30241 :1008D0006E08031C6E0FE4020301031C0130E002EA :1008E000822CE1076C0803186C0FE2076D080318EF :1008F0006D0FE3076E0803186E0FE407030103187A :100900000130E007EA0DEF0B562C690DE10DE20D09 :10091000E30DE40DE00D6B086A1CA02CE1026C08ED :10092000031C6C0FE2026D08031C6D0FE3026E08DE :10093000031C6E0FE4020301031C0130E002B12C22 :10094000E1076C0803186C0FE2076D0803186D0FC0 :10095000E3076E0803186E0FE40703010318013064 :10096000E007E90D0730EF00690DE10DE20DE30D41 :10097000E40DE00D6B08691CCF2CE1026C08031C30 :100980006C0FE2026D08031C6D0FE3026E08031C7E :100990006E0FE4020301031C0130E002E02CE107CA :1009A0006C0803186C0FE2076D0803186D0FE3075E :1009B0006E0803186E0FE407030103180130E00707 :1009C000E90DEF0BB42C680DE10DE20DE30DE40D24 :1009D000E00D6B08691CFE2CE1026C08031C6C0F17 :1009E000E2026D08031C6D0FE3026E08031C6E0F1C :1009F000E4020301031C0130E0020F2DE1076C0843 :100A000003186C0FE2076D0803186D0FE3076E08FB :100A100003186E0FE407030103180130E007E80D27 :100A20000730EF00680DE10DE20DE30DE40DE00D80 :100A30006B08681C2D2DE1026C08031C6C0FE20290 :100A40006D08031C6D0FE3026E08031C6E0FE402B9 :100A50000301031C0130E0023E2DE1076C0803187E :100A60006C0FE2076D0803186D0FE3076E0803189B :100A70006E0FE407030103180130E007E80DEF0BE8 :100A8000122D670DE10DE20DE30DE40DE00D6B0895 :100A9000681C5C2DE1026C08031C6C0FE2026D08FF :100AA000031C6D0FE3026E08031C6E0FE4020301CA :100AB000031C0130E0026D2DE1076C0803186C0F78 :100AC000E2076D0803186D0FE3076E0803186E0F39 :100AD000E407030103180130E007E70D0730EF00DA :100AE000670DE10DE20DE30DE40DE00D6B08671CF1 :100AF0008B2DE1026C08031C6C0FE2026D08031CD5 :100B00006D0FE3026E08031C6E0FE4020301031C69 :100B10000130E0029C2DE1076C0803186C0FE2071E :100B20006D0803186D0FE3076E0803186E0FE407D6 :100B3000030103180130E007E70DEF0B702D671874 :100B4000AF2D6B08E1076C0803186C0FE2076D0806 :100B500003186D0FE3076E0803186E0FE407080013 :100B6000E9010830EF006A08EE0C0318BB2DEF0B0B :100B7000B42DEA0100340310C02DEE0C0318EA076F :0A0B8000EA0CE90CEF0BBD2D080094 :02400E00700F31 :02401000FC3F73 :00000001FF