Code:
MODE btfss REPEAT,1 ; bit 1 a '1' for on (on/off flag)
goto SET_1 ; was off so turn on
btfsc REPEAT,3 ; speedo on/off flag
goto BYSPD
btfss REPEAT,2 ; speedometer or alarm set mode
goto SET_2 ; repeat1 status same, repeat2 =1
BYSPD bcf REPEAT,1 ; if set then clear on/off flag
bcf REPEAT,2 ; clear speedometer flag
bcf INTCON,INTE ; clear interrupt enable for RB0
clrf PULSE_CNT ; clear pulse counter
clrf TIME_CNT1 ; clear time counter 1
clrf TIME_CNT2 ; clear time counter 2
goto WAIT
SET_2 bsf REPEAT,2 ; set speedometer flag
goto NO_SET1
SET_1 bsf REPEAT,1 ; if clear then set on/off flag
NO_SET1 bsf INTCON,INTE ; set interrupt enable for RB0
goto WAIT
UP movf DISP1,w ; display1 to w register
xorlw 0x05 ; compare with decimal'5'
btfss STATUS,Z ; skip next instruction if Disp <9 decimal
goto UP_1 ; increase display1
; check for maximum on display
movf DISP2,w ; look at display 2
xorlw 0x05 ; compare with a 5
btfss STATUS,Z ; is it 5 then check DISP3
goto DISP_UP
movf DISP3,w ; look at disp3
xorlw 0x02 ; compare with a 1
btfsc STATUS,Z ; is it a 2
goto WAIT ; maximum of 255 on display so stop counting up
; digit overflow
DISP_UP clrf DISP1 ; Disp value cleared as it was beyond BCD range (0-9)
movf DISP2,w ; display2 value to w
xorlw 0x09 ; compare with decimal'9' (H'9')
btfss STATUS,Z ; skip next instruction if Disp <9 decimal
goto UP_2 ; increase display2
clrf DISP2 ; Disp value cleared as it was beyond BCD range (0-9)
goto UP_3 ; increase display3
UP_1 movlw 0x05 ; a 5 in the display (count by 5's)
movwf DISP1 ; display1 increased
goto WAIT
UP_2 incf DISP2,f ; display2 increased
goto WAIT
UP_3 incf DISP3,f ; display3 increased
goto WAIT
DOWN movf DISP1,w ; display1 to w register
xorlw 0x00 ; compare with decimal'0' to see if was zero
btfss STATUS,Z ; skip next instruction if Disp 0 decimal
goto DN_1 ; decrease display1
; check for display minimum
movf DISP2,w ; look at display 2
xorlw 0x00 ; compare with 0
btfss STATUS,Z ;
goto DISP_DN ; not 0 so can count down
movf DISP3,w ; look at display 3
xorlw 0x00 ; compare with 0
btfsc STATUS,Z
goto WAIT ; do not decrease beyond 000
DISP_DN movlw H'05' ; place a 5 in display1
movwf DISP1 ; disp1 = 5
movf DISP2,w ; display2 value to w
xorlw 0x00 ; compare with decimal'0' to see if 0
btfss STATUS,Z ; skip next instruction if Disp 0 decimal
goto DN_2 ; decrease display2
movlw H'09' ; Disp value = 9
movwf DISP2
goto DN_3 ; decrease display3
DN_1 clrf DISP1 ; display1 decreased to 0
goto WAIT
DN_2 decf DISP2,f ; display2 decreased
goto WAIT
DN_3 decf DISP3,f ; display3 decreased
; wait period (delay plus EEPROM write time)
; delay loop plus apply tone to piezo alarm as switch press acknowledgement
WAIT bsf INTCON,GIE ; allow global interrupts
movlw D'100' ; set delay period for repeat of value 2 delay (sets key
; acknowledge tone frequency)
movwf VALUE_1 ; VALUE_1 = w
movlw D'50' ; set delay period value 2 (also sets key acknowledge tone period)
LOOP_1 movwf VALUE_2 ; VALUE_2 = w
LOOP_2 decfsz VALUE_2,f ; decrease VALUE_2, skip if zero
goto LOOP_2
btfsc PORTA,3 ; alarm output check if high or low
goto CLR_T
bsf PORTA,3 ; alarm out high
DEC_V1 decfsz VALUE_1,f ; decrease VALUE_1, skip if zero
goto LOOP_1
bsf PORTA,3 ; alarm out high
goto DELTME ; delay time
CLR_T bcf PORTA,3 ; alarm out low
goto DEC_V1
; more delay time
DELTME movlw D'50' ; set delay period
movwf VALUE_1 ; VALUE_1 = w
movlw D'255' ; set delay period value 2
LP_1 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
; EEPROM write. Store new display values in EEPROM
EPWRT movlw EEPROM1 ; address for EEPROM1
movwf EEADR ; address to write
movf DISP1,w ; display1 data to w
call EWRITE ; EEPROM write sequence
movlw EEPROM2 ; address for EEPROM2
movwf EEADR ; address for write
movf DISP2,w
call EWRITE
movlw EEPROM3 ; address for EEPROM3
movwf EEADR ; address for write
movf DISP3,w
call EWRITE
movlw EEPROM4 ; address for EEPROM4
movwf EEADR ; address to write to
movf REPEAT,w ; repeat values (bit 0 is alarm repeat, bit 1 is on/off)
call EWRITE
; when a new speed setting is selected recalculate speed equivalent value
bcf INTCON,GIE ; disable interrupts
call SPDEQIV ; recalculate speed equivalent value
bsf INTCON,GIE ; enable interrupts
goto CLOSED ; out from EEPROM write
; subroutine to write to EEPROM
EWRITE bcf FLAG_1,6 ; EEPROM write repeat flag
movwf TEMP_2 ; store w in temporary storage
EWRIT movf TEMP_2,w ; place value in w (used for read data sequence)
movwf EEDATA ; data register
bcf INTCON,GIE ; disable interrupts
bsf STATUS,RP0 ; select bank 1
bsf EECON1,WREN ; enable write
movlw 0x55 ; place 55H in w for write sequence
movwf EECON2 ; write 55H to EECON2
movlw 0xAA ; AAH to w
movwf EECON2 ; write AA to EECON2
bsf EECON1,WR ; set WR bit and begin write sequence
bsf INTCON,GIE ; enable interrupts
bcf EECON1,WREN ; clear WREN bit
WRITE btfsc EECON1,WR ; skip if write complete WR=0 when write complete
goto WRITE ; not written yet
bcf EECON1,EEIF ; clear write interrupt flag
; read EEPROM DATA and check if written correctly
bsf STATUS,RP0 ; select memory bank 1
bsf EECON1,RD ; read EEPROM
RD_AGN nop
btfsc EECON1,RD ; skip if RD low (read complete)
goto RD_AGN ; wait for low RD
bcf STATUS,RP0 ; select bank 0
movf EEDATA,w ; EEPROM value in w
subwf EEDATA,w ; compare read value with value stored
btfsc STATUS,z ; skip if not the same
return ; value correctly written
btfsc FLAG_1,6 ; write repeat bit, skip if clear and rewrite
return
bsf FLAG_1,6 ; set repeat flag rewrite once only
goto EWRIT ; rewrite as not written correctly
; wait for switch to open (must test for closed switch when RA0, RA1 and RA2 are low
; because switch will appear open at RA4 when switch pull down via RA0-RA2 is high)
CLOSED bcf FLAG_1,1 ; clear flag that indicates switch closed
call ON ; check for closed switch
call ON ; do three times to return to original switch closure
call ON ;
call ON ; do again just in case missed an interrupt during call
call ON ; do again just in case missed one interrupt during call
btfsc FLAG_1,1 ; was switch closed
goto CLOSED ; yes go to check again
goto SWITCH ; switch open so out
; subroutine to wait for switch to reopen
ON bcf INTCON,T0IE ; prevent multiplex update
bcf FLAG_1,0 ; clear flag that indicates update interrupt for display
RE_CHK btfsc PORTA,4 ; check if switch closed
goto OPEN
bsf FLAG_1,1 ; switch closed so set flag
bsf INTCON,T0IE ; allow multiplex interrupt
goto RE_CHK ; closed so check till open
OPEN bcf FLAG_1,0 ; clear multiplex update flag wait for next multiplex update
bsf INTCON,T0IE ; allow multiplex update
FLG_TST btfss FLAG_1,0 ; is flag set indicating a new interrupt for multiplexing
goto FLG_TST ; wait
return
; calibrate routine
CALIBRT btfss REPEAT,1 ; is on/off flag on
goto WAIT ; no calibration allowed when speed alarm unit is off
btfsc REPEAT,2 ; is speedometer on
goto WAIT ; no calibration if speedometer mode
bcf INTCON,GIE ; disable interrupts
clrf PULSE_CNT ; clear pulse counter
clrf TIME_CNT1 ; clear time counter 1
clrf TIME_CNT2 ; clear time counter 2
bsf FLAG_1,7 ; calibrate flag set
bcf INTCON,T0IF ; clear timer interrupt flag
bcf INTCON,INTF ; clear interrupt flag
bsf INTCON,GIE ; allow interrupts
FLG1_CK btfsc FLAG_1,7 ; wait for end of calibrate, skip if end
goto FLG1_CK ; recheck flag 1 bit 7 (cleared at end of calibration)
; store new calibration count numbers in EEPROM
movlw EEPROM5 ; address for EEPROM5
movwf EEADR ; address to write
movf TIME_CNT3,w ; counter 3 to w
call EWRITE ; EEPROM write sequence
movlw EEPROM6 ; address for EEPROM6
movwf EEADR ; address to write
movf TIME_CNT4,w ; counter 4 to w
call EWRITE ; EEPROM write sequence
goto SWITCH ; check for a new closed switch
; Subroutine to convert from 8-bit binary to 2-digit BCD (packed)
; Binary value is in BIN_0
; Result in BCD is in BCD_0 & BCD_1.
; BCD_0 is MSB, BCD_1 is LSB
BCD bcf STATUS,c ; clear carry bit
movlw D'8'
movwf CNT_8 ; 8 in count
clrf BCD_0
clrf BCD_1 ; set BCD registers to 0
LOOPBCD rlf BIN_0,f ; shift left binary registers
rlf BCD_1,f ; MSB shift left
rlf BCD_0,f ; LSB shift left BCD registers
decfsz CNT_8,f ; reduce count value return when 0
goto DECADJ ; continue decimal adjust
return ; completed decimal to BCD operation
; subroutine decimal adjust
DECADJ movlw BCD_1 ; BCD LSB address
movwf FSR ; pointer for BCD1
call ADJBCD ; subroutine to adjust BCD
movlw BCD_0 ; BCD MS address
movwf FSR ; pointer for BCD0
call ADJBCD
goto LOOPBCD
; subroutine adjust BCD
ADJBCD movlw 0x03 ; w has 03
addwf INDF,w ; add 03 to BCDx register (x is 0-1)
movwf TEMP ; store w
btfsc TEMP,3 ; test if >7
movwf INDF ; save as LS digit
movlw 0x30 ; 3 for MSbyte
addwf INDF,w ; add 30 to BCDx register
movwf TEMP ; store w in temp
btfsc TEMP,7 ; test if >7
movwf INDF ; save as MS digit
return ; end subroutine
end
Bookmarks