part 3
Code:
; routine to convert speedo memory to speed 1, 2 & 3 display memory
	
	sublw	0xFF		; compare with maximum value (255km/h)
	btfsc	STATUS,Z	; is it at maximum
	goto	LIMIT		; maximum of 255 on display 

; convert speedo to BCD place in Speed 3,Speed 2 and Speed1	

	movf	SPEEDO,w	; look at speedo value
	movwf	BIN_0		; to binary register
	call	BCD		; convert to BCD
	movf	BCD_0,w		; ms digit
	movwf	SPEED3		; display MSD
	movf	BCD_1,w		; LS Digits
	andlw	0x0F		; mask bits 7-4
	movwf	SPEED1		; ls digit
	swapf	BCD_1,w		; look at ms nibble
	andlw	0x0F
	movwf	SPEED2		; middle digit
	goto	CK_SPD

LIMIT	movlw	0x08		; place 8 in speed1-3 memory so display -
	movwf	SPEED1		; - shows 888 for overrange speedometer
	movwf	SPEED2
	movwf	SPEED3
	
; check speed against alarm setting

CK_SPD	movf	SPEED_EQV,w	; speed equivalent value to w 
	btfsc	REPEAT,4	; skip if alarm threshold low
	addlw	0x01		; increase speed equiv by hysteresis value
	subwf	PULSE_CNT,w	; subtract speed equivalent from pulse counter	
	btfsc	STATUS,c	; if positive or zero (c=1) then sound overspeed alarm	
	goto 	SETALM
	
; add hysteresis (addition of 1 to pulse counter gives 1km/h hysteresis)

	movf	PULSE_CNT,w	; pulse counter value
	btfss	REPEAT,4	; skip if alarm threshold high
	addlw	0x01		; increase by factor for hysteresis (on to off alarm speed)
	movwf	PULSE_CNT
	movf	SPEED_EQV,w
	subwf	PULSE_CNT,w	; subtract speed equivalent from new pulse counter value
	btfsc	STATUS,c	; if positive or zero (c=1) then leave set alarm on
	goto	ALM_CL		; continue alarm
	goto	CLRALM		; clear alarm as below overspeed 
	
INC_CT1 incfsz	TIME_CNT1,f	; increase counter 1 skip if overflowed
	goto 	ALARM
	incf	TIME_CNT2,f	; increase counter 2 when counter 1 overflows
	goto 	ALARM

; calibrate time counters

CALBRAT	incfsz	TIME_CNT1,f	; increase counter 1 skip if overflowed
	goto	CMP_PLS
	incfsz	TIME_CNT2,f	; increase counter 2 on overflow skip if overflowed
	goto	CMP_PLS		; not overrange so compare pulse count with speed equiv
	bsf	ERR_FLG,0	; error flag set as counter 2 has overranged
	bcf	FLAG_1,7	; calibrate off flag
	goto	C_ALM
CMP_PLS	movf	PULSE_CNT,w	; pulse counter to w
	xorwf	SPEED_EQV,w	; compare pulse counter with speed equivalent (display value)	
	btfss	STATUS,Z	; skip if equal
	goto 	C_ALM
	
; store time counters TIME_CNT1 & 2 into TIME_CNT3 & 4 and into EEPROM5 & 6 - new calibration 

	movf	TIME_CNT1,w	; time counter 1 to w
	movwf	TIME_CNT3	; time counter 3 = 1
	movf	TIME_CNT2,w	; time counter 2 to w
	movwf	TIME_CNT4	; time counter 2 = 4
	bcf	FLAG_1,7	; calibrate flag clear, calibrate off
	
; clear alarm
	
CLRALM	clrf	PULSE_CNT	; clear pulse counter for recount
	clrf	TIME_CNT1	; clear time counter 1
	clrf	TIME_CNT2	; clear time counter 2 	
C_ALM	bcf	FLAG_1,5	; overspeed flag
	bcf	FLAG_1,4	; clear alarm off flag
	bsf	PORTA,3		; alarm output high 
	goto	ALARM		; continue program

; set alarm

SETALM	clrf	PULSE_CNT	; clear pulse counter for recount
	clrf	TIME_CNT1	; clear time counter 1
	clrf	TIME_CNT2	; clear time counter 2 	
	btfsc	FLAG_1,5	; is overspeed flag set. Skip if not
	goto	ALARM		; set so skip setting alarm again, wait till cleared
	bsf	FLAG_1,5	; overspeed flag
	bsf	FLAG_1,2	; set alarm tone flag
	bsf	FLAG_1,4	; set alarm off flag
	clrf	FLAG_2		; alarm tone period
	bcf	FLAG_1,3	; clear on off flag
	clrf	FLAG_3		; alarm tone sequence

; alarm tone routine generates a beep beep tone for over-speed 	

ALM_CL	clrf	PULSE_CNT
	clrf	TIME_CNT1	; clear time counter 1
	clrf	TIME_CNT2	; clear time counter 2 	
ALARM	btfss	FLAG_1,4	; alarm off flag
	goto	SENSOR		; alarm not required 
	incf	FLAG_2,f	; alarm tone period
	btfss	FLAG_1,2	; skip if alarm tone required	
	goto	RDFLG_2		; no alarm go to check sensor interrupt
	btfsc	FLAG_1,3	; alternate on and off flag for tone 
	goto	SET_OUT		; if flag set then stop tone on RA3 output
	btfsc	PORTA,3		; is alarm out low 
	goto	SET_OUT
	bsf	PORTA,3		; alarm out pin high 
	goto	CNT_SEQ
SET_OUT	bcf	PORTA,3		; alarm out pin low 
CNT_SEQ	bcf 	FLAG_1,3
	btfss	FLAG_3,0	; read alarm tone sequence (bit 0 low then alarm tone)
	goto	RDFLG_2	
	bsf	FLAG_1,3	; no tone
	bsf	PORTA,3		; alarm output high
	btfss	FLAG_3,1	; check count
	goto 	RDFLG_2
	bcf	FLAG_1,2	; alarm off
	bcf	PORTA,3		; alarm out low 
	goto 	SENSOR	
RDFLG_2	movf	FLAG_2,w	; read alarm tone period counter
	sublw	0xFE		; alarm tone on-time (FE = max) (00 = min)
	btfss	STATUS,C	; skip if less than on-time
	goto	SET_FLG
	goto 	SENSOR	
SET_FLG incf	FLAG_3,f	; next sequence
	clrf	FLAG_2		; start period count
	btfss	FLAG_3,7	; look at bit for repeat tone period, 7 is longest interval, 6 half the period etc
	goto	SENSOR		; if bit set then repeat alarm
	btfss	REPEAT,0	; skip if repeat flag set
	goto	SENSOR
	bsf	FLAG_1,2	; allow alarm again
	clrf	FLAG_3		; clear repeat bit 
	goto	SENSOR

; speed sensor update

SPEED	bcf	INTCON,INTF	; clear INT flag
	incfsz	PULSE_CNT,f	; increase pulse counter value for each speed sensor input
	goto	RECLAIM
	movlw	0xFF		; max value
	movwf	PULSE_CNT	; place max count in pulse counter do not allow overrange	
	
; end of interrupt reclaim w and status 

RECLAIM	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