PIC newbie - took ages to program and i still have bugs


Closed Thread
Results 1 to 15 of 15

Hybrid View

  1. #1
    Join Date
    Feb 2003
    Location
    Salt Lake City, Utah USA
    Posts
    517


    Did you find this post helpful? Yes | No

    Default

    >>took ages to program and i still have bugs

    Interesting .... I found your code here with google

    http://www.siliconchip.com.au/cms/at...month=November
    Last edited by paul borgmeier; - 25th September 2007 at 07:29.
    Paul Borgmeier
    Salt Lake City, UT
    USA
    __________________

  2. #2
    Join Date
    Sep 2007
    Posts
    12


    Did you find this post helpful? Yes | No

    Default

    you've got me -

    the code is legit no malware

    the code is available with current kit based speed alert devices but I need to modify it for a personal project. I just Downloaded MPLAB today and ran the first couple of instructions and found a list of errors. I was expecting everything to be in order:

    Heres the code in full:

    part 1:
    Code:
    ; File SPEED254.ASM changes from SPEED.ASM to allow speed readings up to 254km/h
    ; Uses assembly code for PIC16F84 microcontroller
    ; This program is for a car speed alarm. It utilises three 7-segment displays
    ; which show the set speed. The speed setting can be altered with up and down pushbutton 
    ; switches from 0 to 255km/h in 5km/h steps. When the speed of the vehicle reaches the set speed,
    ; the alarm sounds and an LED lights up. The alarm is a short beep beep sound while the LED 
    ; remains lit until the speed is reduced below the alarm speed or the alarm speed is increased 
    ; above the vehicles speed.
    ;
    ; A rotating magnet or magnets installed on the vehicles tail shaft or drive shaft
    ; trigger an inductive (coil) sensor to detect vehicle speed and this signal is detected via
    ; an interrupt in the processor.
    ;
    ; Calibration can be made by setting an alarm speed on the display and then bringing the 
    ; vehicle speed up to the alarm speed as shown on the vehicles speedometer. 
    ; The Calibrate switch is then pressed. The display will show CAL until
    ; calibrated. Display will show Err (error) if too few pulses or none are present while calibrating.  
    ; No calibration allowed in speedometer mode. 
    ;
    ; Each pressing the Mode switch will cycle between alarm speed indication, speedometer
    ; and off which disables the speed alarm. 
    ;
    ; Alarm indication occurs for speedometer and alarm speed modes. 
    ;
    ; Pressing the Up switch at power up will set the speed alarm for either a
    ; repeat warning of overspeed or single alarm. The repeat alarm will produce a tone every 
    ; 10-seconds until the speed goes below the setting or the speed setting is increased above
    ; the speed.
    ; 
    ; When pressing the Up switch at power up, a 'r' on the right display indicates repeat 
    ; alarm and a '-' indicates no-repeat alarm option.
    ;
    ; Pressing the Mode switch at power up will toggle the speed alarm with the speedometer on or off
    ; If the display shows an 'S' then the speedometer function will operate and a '-' indicates that
    ; the speedometer is off.
    ;
    ; Pressing the Down switch at power up will set the speed alarm threshold point either high or
    ; low. The low threshold means that the alarm will sound at the set speed and switch off
    ; when the speed goes 1km/h or less below this speed. The high threshold will set the alarm 
    ; when the speed is 1km/h or more above the set speed and go off for speeds at or below the 
    ; set speed. A high setting will be indicated by an 'H' and a low setting by an 'L'as shown during
    ; power up with the down switch pressed.
    ;  
    ; Processor pin allocations are as follows:
    ; RA0 Output disp1 driving transistor for common anode display
    ; RA1 Output disp2
    ; RA2 Output disp3
    ; RA3 Output for alarm
    ; RA4 Input from switches
    
    ; RB0 Input for wheel sensor (interrupt)
    ; RB1 c segment drive for seven segment LED display
    ; RB2 d segment drive
    ; RB3 e segment drive
    ; RB4 f segment drive
    ; RB5 a segment drive
    ; RB6 b segment drive
    ; RB7 g segment drive
    
    ; CPU configuration
    ; 	
    	list P=16F84
    	#include "p16f84.inc"
    	__config _XT_OSC & _WDT_OFF & _PWRTE_ON
    
    ; Define variables at memory locations
    
    ; EEPROM DATA
    
    EEPROM1		equ	H'00'	; non-volatile storage for display1
    EEPROM2		equ	H'01'	; non-volatile storage for display2
    EEPROM3		equ	H'02'	; non-volatile storage for display3
    EEPROM4		equ	H'03'	; non-volatile storage to toggle repeat alarm feature and mode
    EEPROM5		equ	H'04'	; non-volatile storage of LS byte of calibration number
    EEPROM6		equ	H'05'	; non-volatile storage of MS byte of calibration number
    
    ; RAM
    
    DISP1		equ	H'0C'	; working storage for Display1 value alarm speed mode
    DISP2		equ	H'0D'	; working storage for Display2 value alarm speed mode
    DISP3		equ	H'0E'	; working storage for Display3 value alarm speed mode
    STATUS_TMP 	equ H'0F'	; temp storage for status during interrupt
    W_TMP		equ	H'10'	; temporary storage for w during interrupt
    VALUE_1		equ H'11'	; delay value storage			
    VALUE_2		equ	H'12'	; delay value storage
    FLAG_1		equ	H'13'	; flag, bit 0 = flag for closed switch, bit 1 for interrupt indicator
    						; bit 2 for alarm tone required, bit 3 for tone duty cycle,
    						; bit 4 alarm off, bit 5 overspeed, bit 6 EEPROM 
    						; write repeat number, bit 7 for calibrate flag
    FLAG_2		equ	H'14'	; alarm tone period settable from 00-FE 
    FLAG_3		equ	H'15'	; alarm tone sequence 00000000=on,00000001=off,00000010=on >=00000011 off, 
    						; use a more significant bit to set reocurrence, bit 6 or 7
    REPEAT		equ	H'16'	; bit 0 working store repeat alarm flag stored in EEPROM4, bit 1 on/off flag
    						; bit 1 on/off flag, bit 2 speedo/alarm select flag, bit 3 speedo on/off flag
    						; bit 4 alarm threshold 
    SPEED_EQV	equ	H'17'	; storage for speed equivalent (value of 5 per 5km/h) 160km/h=160
    TEMP_1		equ	H'18'	; temporary working storage
    TEMP_2		equ	H'19'	; temp storage
    TIME_CNT1	equ	H'1A'	; counter for pulse count period
    TIME_CNT2	equ	H'1B'	; counter for pulse count period
    TIME_CNT3	equ	H'1C'	; working lsb calibration number stored in EEPROM5
    TIME_CNT4	equ	H'1D'	; working msd calibration number stored in EEPROM6
    PULSE_CNT	equ	H'1E'   ; counter for speed pulses compared with speed_eqv 
    ERR_FLG		equ	H'1F'	; bit 0 is error flag for counter overrange during calibration
    SPEEDO		equ	H'20'	; latched value for speedometer obtained from PULSE_CNT
    SPEED1		equ	H'21'	; display1 value during speedometer mode
    SPEED2		equ	H'22'	; display2 value during speedometer mode
    SPEED3		equ	H'23'	; display3 value during speedometer mode
    TEMP		equ	H'24'	; temporary register for BCD conversion
    BCD_0		equ	H'25'	; decimal value MSD
    BCD_1		equ	H'26'	; decimal packed BCD LS digits
    BIN_0		equ	H'27'	; binary value for BCD conversion
    CNT_8		equ	H'28'   ; counter for BCD conversion
    TEMP_X		equ	H'29'	; temporary register for speed equivalent calculation
     
    ; preprogram EEPROM DATA
    	
    	ORG     2100
    	DE	0x00, 0x06, 0x00	; preset EEPROM1-EEPROM3 ( initial speed setting is 60)
    		DE	0x03			; set EEPROM4 (repeat alarm on bit 0 and set to on/off bit 1)
    							; bit 2 speedo/set bit to set alarm mode, bit 3 speedo on
    							; bit 4 alarm threshold low
    		DE	0xB3, 0x11		; set calibration EEPROM5 & EEPROM6 (set to 100Hz = 160km/h
    ; calibration calculated out at 1.6s update time 160km/h = 160 pulses counted.
    ; 3.579545MHz/4/2/(256-100+2) = 353.1175us and require 4531Decimal for 1.6 sec or 11B3Hex 
    
    ; Program begins
    
    ; define reset and interrupt vector start addresses
    
    	org	0			  	; start at address 0000h
    	goto	MAIN		; normal service routines from Reset vector
    	org     4			; interrupt vector 0004h, start interrupt routine here
    	goto	INTER		; go to start of interrupt routine, bypass subroutines
    
    ; subroutine to get seven segment display data. (This is placed at front of programm to prevent computed
    ; goto crossing 256 bit boundary. *PCL control only over least significant 8-bits*) 
     
    	SVNSEG	andlw	0x0F; remove most significant bits if present prevents value >16h
    	addwf	PCL,f		; add value of display to program counter
    	retlw 	B'10000000'	; 7-segment code 0 
    	retlw 	B'10111100'	; 7-segment code 1
    	retlw 	B'00010010'	; 7-segment code 2
    	retlw 	B'00011000'	; 7-segment code 3
    	retlw 	B'00101100'	; 7-segment code 4
    	retlw 	B'01001000'	; 7-segment code 5
    	retlw 	B'01000000'	; 7-segment code 6
    	retlw 	B'10011100'	; 7-segment code 7
    	retlw 	B'00000000'	; 7-segment code 8
    	retlw 	B'00001000'	; 7-segment code 9
    
    ;*******************************************************************************************
    - if need be i'll contact the developers website on why their code is ridden with bugs. Thanks for look at it.

  3. #3
    Join Date
    Sep 2007
    Posts
    12


    Did you find this post helpful? Yes | No

    Default

    Part 2
    Code:
    ; INTERRUPT
    ; interrupt from counter used to multiplex display
    ; this sucessively switches on Disp1, Disp2, Disp3 in sequence plus 
    ; blanking leading zeros on display for Disp2 and Disp3 for either 
    ; speedometer or set alarm speed modes
    ; uses internal timer to initiate display update
    ; also updates time period counters which set period of speed pulse counting
    ; checks speed against alarm setting
    ; speed sensor update
    
    ; start interrupt by saving w and status registers before altered by interrupt routine
    
    	INTER	movwf	W_TMP	; w to w_tmp storage
    	swapf	STATUS,w		; status to w
    	movwf	STATUS_TMP		; status in status_tmp  
    
    ; which interrupt (INT or TMRO)
    
    	btfsc	INTCON,T0IF		; TMRO overflow interrupt flag then goto litchk
    	goto	LITCHK			; TMRO overflow so multiplex display
    SENSOR	btfsc	INTCON,INTF	; INT interrupt flag set then goto speed
    	goto	SPEED			; speed sensor signal update 
    	goto	RECLAIM			; end of interrupt reclaim w and status
    
    ; multiplex display routine
    
    LITCHK	btfsc	REPEAT,1	; check if speed alarm unit on or off
    	goto	ALM_BY			; on so skip resetting alarm (alarm bypass)
    
    ; reset alarm function
    
    	clrf	PULSE_CNT	; clear pulse counter so no alarm
    	clrf	TIME_CNT1	; clear time counter 1
    	clrf	TIME_CNT2	; clear time counter 2 	
    ALM_BY	bcf	STATUS,RP0	; select bank 0
    	movlw	D'100'		; speed up multiplex rate for suitable tone in piezo alarm (100
    						; is used in calibration number calculation and for output freq)	
    						; freq is 3.579545MHz/2/4/(256-100+2)/2 = 1.4159kHz
    	addwf	TMR0,f		; add to timer registerand takes 2 cycles to start counting
    	bcf	INTCON,T0IF		; clear TMRO interrupt flag
    	bsf	FLAG_1,0		; indicate another interrupt has occurred
    	btfsc	REPEAT,2	; check if speedometer or alarm speed mode
    	goto 	SPD_LTE		; display update in speedometer mode 
    	btfss	PORTA,0		; skip if display 1 not lit
    	goto	LIT1		; display 1 lit
    	btfss	PORTA,1		; skip if display 2 not lit
    	goto	LIT2		; display 2 lit
    	btfss	PORTA,2		; skip if display 3 not lit				
    	goto	LIT3		; display 3 lit
    	movlw	B'11111110'	; seven segments off
    	movwf	PORTB
    	bcf	PORTA,2			; no displays lit so set disp3 (used if error in output)
    	goto 	LITCHK		; goto check which is lit now
    LIT1	bsf	PORTA,0		; disp1 off
    	movf	DISP3,w		; look at display3
    	xorlw	0x00		; compare display3 with 0
    	btfss	STATUS,Z	; skip if zero
    	goto	NOBLNK		; do not blank display2
    	movf	DISP2,w		; look at display2
    	xorlw	0x00		; compare disp2 with 0
    	btfss	STATUS,Z	; skip if 0
    	goto	NOBLNK		; do not blank disp2
    	movlw	B'11111110'	; 7-segment display off
    	goto	BLANK		; blank disp2 when disp2 and disp3 = 0
    NOBLNK	movf	DISP2,w		; disp2 to w
    	call 	SVNSEG		; goto subroutine to get seven segment code 
    BLANK	btfss	ERR_FLG,0	; calibrate error
    	goto	CAL_M		; mid display
    	movlw	B'10000110'	; set display for 'r' (Err)
    	goto	LIT_r		; light an r
    CAL_M	btfsc	FLAG_1,7	; calibrate flag skip if clear
    	movlw	B'00000100'	; set display to show an A (for CAL) 
    	btfss	REPEAT,1	; is speed alarm unit on or off, 1 is on 0 is off
    	movlw	B'01111110'	; set 'g' segment on display 
    LIT_r	movwf	PORTB		; seven segment value to portB
    	bcf	PORTA,1		; disp2 powered
    	goto	TIMECNT		; end of multiplex
    LIT2	bsf	PORTA,1		; disp2 off
    	movf	DISP3,w		; disp3 to w
    	xorlw	0x00		; compare with 0
    	btfss	STATUS,Z	; skip if zero
    	goto 	SHOW		; show digit on disp3
    	movlw	B'11111110'	; 7-segment display off
    	goto	BLNK		; value to blank display
    SHOW	movf	DISP3,w		; look at display3
    	call	SVNSEG		; get 7-segment value
    BLNK	btfss	ERR_FLG,0	; calibrate error
    	goto	CAL_L		; Left display
    	movlw	B'01000010'	; set display for 'E' (Err)
    	goto	LIT_E		; light an E
    CAL_L	btfsc	FLAG_1,7	; calibrate flag skip if clear
    	movlw	B'11000010'	; set display to show a C (for CAL) 
    	btfss	REPEAT,1	; is speed alarm unit on or off, 1 is on 0 is off
    	movlw	B'01111110'	; set 'g' segment on display 
    LIT_E	movwf	PORTB		; portB has seven-segment code 
    	bcf	PORTA,2		; disp3 powered
    	goto	TIMECNT		; end of multiplex
    LIT3	bsf	PORTA,2		; disp3 off
    	movf	DISP1,w		; disp1 to w
    	call	SVNSEG
    	btfss	ERR_FLG,0	; calibrate error
    	goto	CAL_R		; Right display
    	movlw	B'10000110'	; set display for 'r' (Err)
    	goto	LIT_rr		; light an r
    CAL_R	btfsc	FLAG_1,7	; calibrate flag skip if clear
    	movlw	B'11100010'	; set display to show an L (for CAL) 
    	btfss	REPEAT,1	; is speed alarm unit on or off, 1 is on 0 is off
    	movlw	B'01111110'	; set 'g' segment on display 
    LIT_rr	movwf 	PORTB
    	bcf	PORTA,0		; disp1 powered
    	goto	TIMECNT
    
    ; display update for speedometer mode
    
    SPD_LTE btfss	PORTA,0	; skip if display 1 not lit
    	goto	SPD_LT1		; display 1 lit
    	btfss	PORTA,1		; skip if display 2 not lit
    	goto	SPD_LT2		; display 2 lit
    	btfss	PORTA,2		; skip if display 3 not lit				
    	goto	SPD_LT3		; display 3 lit
    	movlw	B'11111110'	; seven segments off
    	movwf	PORTB
    	bcf	PORTA,2			; no displays lit so set disp3 (used if error in output)
    	goto 	SPD_LTE		; goto check which is lit now
    SPD_LT1	bsf	PORTA,0		; disp1 off
    	movf	SPEED3,w	; look at display3
    	xorlw	0x00		; compare display3 with 0
    	btfss	STATUS,Z	; skip if zero
    	goto	NOBLNK1		; do not blank display2
    	movf	SPEED2,w	; look at display2
    	xorlw	0x00		; compare disp2 with 0
    	btfss	STATUS,Z	; skip if 0
    	goto	NOBLNK1		; do not blank disp2
    	movlw	B'11111110'	; 7-segment display off
    	goto	BLANK1		; blank disp2 when disp2 and disp3 = 0
    NOBLNK1	movf	SPEED2,w	; disp2 to w
    	call 	SVNSEG		; goto subroutine to get seven segment code 
    BLANK1	movwf	PORTB		; seven segment value to portB
    	bcf	PORTA,1		; disp2 powered
    	goto	TIMECNT		; end of multiplex
    SPD_LT2	bsf	PORTA,1		; disp2 off
    	movf	SPEED3,w	; disp3 to w
    	xorlw	0x00		; compare with 0
    	btfss	STATUS,Z	; skip if zero
    	goto 	SHOW1		; show digit on disp3
    	movlw	B'11111110'	; 7-segment display off
    	goto	BLNK1		; value to blank display
    SHOW1	movf	SPEED3,w	; look at display3
    	call	SVNSEG		; get 7-segment value
    BLNK1	movwf	PORTB		; portB has seven-segment code 
    	bcf	PORTA,2		; disp3 powered
    	goto	TIMECNT		; end of multiplex
    SPD_LT3	bsf	PORTA,2		; disp3 off
    	movf	SPEED1,w	; disp1 to w
    	call	SVNSEG
    	movwf 	PORTB
    	bcf	PORTA,0		; disp1 powered
    
    ; update time period counters for speed pulse counter
    
    TIMECNT	btfsc	FLAG_1,7	; calibrate flag skip if clear (no calibrate)
    	goto	CALBRAT		; calibrate switch pressed so do calibration
    	movf	TIME_CNT4,w	; MS Byte of calibration value to w
    	xorwf	TIME_CNT2,w	; compare MS Byte counter with calibration
    	btfss	STATUS,z	; skip if equal
    	goto	INC_CT1		; 
    	movf	TIME_CNT3,w	; LS Byte of calibration value
    	xorwf	TIME_CNT1,w	; compare LS byte counter with calibration
    	btfss	STATUS,z	; skip if equal
    	goto	INC_CT1		; 
    	clrf	TIME_CNT1	; clear timer counter 1
    	clrf	TIME_CNT2	; and timer 2
    	movf	PULSE_CNT,w	; look at pulse counter value
    	movwf	SPEEDO		; speedometer value latched pulse counter value

  4. #4
    Join Date
    Sep 2007
    Posts
    12


    Did you find this post helpful? Yes | No

    Default

    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

  5. #5
    Join Date
    Sep 2007
    Posts
    12


    Did you find this post helpful? Yes | No

    Default part 4

    Code:
    ;********************************************************************************************** 
      
    ; RESET		
    ; Set ports A & B
    
    MAIN	clrf	FLAG_1		; clear flag memory
    	clrf	ERR_FLG		; clear error flag used in calibration
    	clrf	TIME_CNT1	; clear time period counter for speed pulse update
    	clrf	TIME_CNT2	; clear time period counter
    	clrf	PULSE_CNT	; clear speed pulse counter
    	clrf	SPEED1		; clear speedometer display1 
    	clrf	SPEED2		; clear speedometer display2 
    	clrf	SPEED3		; clear speedometer display3 
    	bsf	STATUS,RP0	; select memory bank 1
    	movlw	B'00000001'	; w = 00000001 binary (RB0 input, RB1-RB7 output)
    	movwf	TRISB		; port B data direction register
    	movlw	B'10000000'	; w = 10000000 binary
    	movwf	OPTION_REG	; TMRO prescaler no division, PORTB pullups disabled
    	movlw   B'00010000'	; w = 10000 binary (RA0-RA2, RA3 outputs, RA4 input)
    	movwf   TRISA		; A port data direction register
    	bcf	STATUS,RP0	; select memory bank 0
    	movlw	B'11111110'	; w is all 1's for RB7-RB1, 0 for RB0
    	movwf	PORTB		; portB outputs high
    	movlw	B'00001111'
    	movwf	PORTA		; portA RA0 high, RA1,RA2 outputs high, RA3 high 
    	
    ; get memory in EEPROM1, EEPROM2 & EEPROM3 for speed setting, place in DISP1, DISP2, DISP3
    	
    	movlw	EEPROM1		; address for EEPROM1
    	call	EEREAD		; read EEPROM storage
    	sublw	0x09		; compare with 9
    	btfss	STATUS,C	; skip if positive therefore a 9 or less
    	goto	CLR1		; greater than 9 then clear to 0
    	movf	EEDATA,w	; restore w
    	movwf	DISP1		; EEPROM1 to DISP1
    	goto	EEPRM2
    CLR1	clrf	DISP1		; Disp1 = 0 as disp1 was more than 9 (illegal value)
    	
    EEPRM2	movlw	EEPROM2		; address for EEPROM2
    	call	EEREAD
    	sublw	0x09		; compare with 9
    	btfss	STATUS,C	; skip if positive therefore a 9 or less
    	goto	CLR2
    	movf	EEDATA,w	; restore w
    	movwf	DISP2		; EEPROM2 to DISP2
    	goto	EEPRM3
    CLR2	clrf	DISP2		; disp2 = 0 as disp2 was more than 9 (illegal value)
    
    EEPRM3	movlw	EEPROM3		; address for EEPROM3
    	call	EEREAD
    	sublw	0x01		; compare with 1
    	btfss	STATUS,C	; skip if positive therefore a 1 or less
    	goto	CLR3
    	movf	EEDATA,w	; restore w
    	movwf	DISP3		; EEPROM3 to DISP3
    	goto	EEPRM5
    CLR3	clrf	DISP3		; disp3 = 0 as disp3 was more than 1 (illegal value)
    
    ; get EEPROM5 and EEPROM6 calibration values and place in TIME_CNT3 and TIME_CNT4
    
    EEPRM5	movlw	EEPROM5		; address for EEPROM5
    	call	EEREAD
    	movwf	TIME_CNT3	; store in LS byte calibration register
    	movlw	EEPROM6		; address for EEPROM6
    	call	EEREAD
    	movwf	TIME_CNT4	; store in MS byte calibration register
    
    ; get memory EEPROM4 and place in REPEAT. This is the indicator for
    ; repeat alarm on or off, bit 0. ON/OFF flag, bit 1, bit 2 is speedo, bit 3 is speedo on/off 
    ; bit 4 is alarm threshold high or low
    	
    EEPRM4	movlw	EEPROM4		; address for EEPROM4
    	call	EEREAD
    	movwf	REPEAT		; store in repeat register
    
    ; check for pressed up switch
    	
    	bcf	PORTA,2		; clear RA2 to check if up switch pressed
    	nop
    	nop			; allow time for levels to settle
    	btfsc	PORTA,4		; is up switch pressed
    	goto	CHK_DN		; switch open so check down switch
    	btfsc	REPEAT,0	; test for repeat flag bit 0	
    	goto	CLRREP		; clear repeat off alarm
    	bsf	REPEAT,0	; set repeat for alarm
    	movlw	B'10000110'	; 'r' on display for repeat alarm
    	goto	SWOPEN
    CLRREP	bcf	REPEAT,0	; clear repeat
    	movlw	B'01111110'	; '-' on display for no repeat alarm
    SWOPEN	movwf	TEMP_1
    SWCLSD	bsf	PORTA,0		; display off
    	bsf	PORTB,5		; clear a segment
    	bsf	PORTB,6		; clear b segment
    	bsf	PORTB,3		; e segment
    	bsf	PORTB,4		; f segment
    	bsf	PORTB,7		; g segment
    	bsf	PORTB,2		; clear display at RB	
    	bcf	PORTA,2		; clear RA2 to check if up switch pressed
    	call	DELMO
    	btfsc	PORTA,4		; wait for switch to open
    	goto	MODESTO		; store repeat setting when switch opens
    
    ; multiplex display until switch opens
    
    	bsf	PORTA,2		; RA2 high
    	nop
    	nop
    	nop
    	bcf	PORTA,0		; RA0 low so display 1 lit
    	movf	TEMP_1,w	; retrieve temp storage value
    	movwf	PORTB		; port B a-g segments on again
    	call	DELMO		; more delay time 
    	goto 	SWCLSD		; check for pressed switch
    
    ; check for pressed down switch
    	
    CHK_DN	bsf	PORTA,2		; RA2 high so Disp3 will be off
    	bsf	PORTA,0		; RA0 high so disp1 off
    	nop
    	nop
    	bcf	PORTA,1		; clear RA1 to check if down switch pressed
    	nop
    	nop			; allow time for levels to settle
    	btfsc	PORTA,4		; is down switch pressed
    	goto	CHK_MDE		; switch open so check mode switch
    	btfsc	REPEAT,4	; test for threshold flag bit 4	
    	goto	CLRTRS		; clear threshold flag bit
    	bsf	REPEAT,4	; set threshold high
    	movlw	B'00100100'	; 'H' on display for high threshold
    	goto	DNOPEN
    CLRTRS	bcf	REPEAT,4	; clear threshold flag
    	movlw	B'11100010'	; 'L' on display for low threshold
    DNOPEN	movwf	TEMP_1
    DNCLSD  bsf	PORTB,6		; clear b segment
    	bsf	PORTB,1		; clear c segment
    	bsf	PORTB,3		; e segment
    	bsf	PORTB,4		; f segment
    	bsf	PORTB,7		; g segment
    	bsf	PORTB,2		; d segment	
    	bcf	PORTA,1		; clear RA1 to check if down switch pressed
    	call	DELMO		; more delay time (multiplex)
    	call	DELMO		; more delay time 
    	btfsc	PORTA,4		; wait for switch to open
    	goto	MODESTO		; store repeat setting when switch open
    	
    ; multiplex display until switch opens
    
    	movf	TEMP_1,w
    	movwf	PORTB		; port B a-g segments on again
    	call	DELMO		; more delay time 
    	goto 	DNCLSD		; check for pressed switch

  6. #6
    Join Date
    Sep 2007
    Posts
    12


    Did you find this post helpful? Yes | No

    Default part 5

    Code:
    ; check for pressed Mode switch
    	
    CHK_MDE	bsf	PORTA,1		; RA1 high so disp2 off
    	bsf	PORTA,2		; RA2 high so disp3 off
    	nop
    	nop
    	bcf	PORTA,0		; clear RA0 to check if mode switch pressed
    	nop
    	nop
    	btfsc	PORTA,4		; is mode switch pressed
    	goto	NO_OPEN		; switch open so no change
    	btfss	REPEAT,3	; test for speedo on/off flag bit 3	
    	goto	CLRSPED		; clear speedo on/off 
    	bcf	REPEAT,3	; set speedo
    	movlw	B'01001000'	; 's' on display for speedo
    	movwf	TEMP_1
    	goto	MODEOPN
    CLRSPED	bsf	REPEAT,3	; set speedo on/off flag
    	movlw	B'01111110'	; '-' on display for no speedo
    	movwf	TEMP_1
    	bcf	REPEAT,2	; clear speedometer flag
    MODEOPN	bsf	PORTA,2		; display off
    	bsf	PORTB,5		; clear a segment
    	bsf	PORTB,1		; clear c segment
    	bsf	PORTB,2		; d segment
    	bsf	PORTB,4		; f segment
    	bsf	PORTB,7		; g segment
    	bcf	PORTA,0		; clear RA0 to check if mode switch pressed
    	call	DELMO		; more delay time (multiplex time)
    	call	DELMO		; more delay time 
    	btfsc	PORTA,4		; wait for switch to open
    	goto	MODESTO		; store repeat setting when switch open
    
    ; multiplex display until switch opens
    
    	bsf	PORTA,0		; RA0 high
    	nop
    	nop
    	nop
    	bcf	PORTA,2		; RA2 low so display 1 lit
    	movf	TEMP_1,w
    	movwf	PORTB		; 
    	call	DELMO		; more delay time (multiplex)
    	goto 	MODEOPN
    
    ; delay period for multiplex rate
    
    DELMO	movlw 	D'255'		; delay period
    	movwf	TEMP_2
    SMALR	decfsz	TEMP_2,f	; reduce temp_2
    	goto	SMALR		; temp_2 smaller by 1
    	return			; end delay
    
    ; write new mode option to EEPROM4
    
    MODESTO	movlw	EEPROM4		; address for EEPROM4
    	movwf	EEADR		; address for write
    	movf	REPEAT,w	; flag stored
    	call	EWRITE		; write to EEPROM
    	
    ; calculate speed equivalent value
    
    NO_OPEN	call	SPDEQIV		; calculate speed equivalent
    	goto	INT_SET
    	
    ; subroutine to read EEPROM memory
    
    EEREAD	movwf 	EEADR		; indirect special function register
    	bsf 	STATUS,RP0	; select memory bank 1
    	bsf	EECON1,RD	; read EEPROM
    RD_RD	nop
    	btfsc	EECON1,RD	; skip if RD low (read complete)
    	goto 	RD_RD		; wait for low RD (read RD)	
    	bcf	STATUS,RP0	; select bank 0
    	movf	EEDATA,w	; EEPROM value in w
    	return
    
    ; subroutine to calculate speed equivalent of 8 per 5km/h this value is compared with 
    ; counted pulses from speed sensor.  
    	
    SPDEQIV	bcf	FLAG_1,5	; overspeed flag
    	bcf	FLAG_1,4	; clear alarm off flag
    	clrf	PULSE_CNT	; clear pulse counter
    	clrf	TIME_CNT1	; clear time counter 1
    	clrf	TIME_CNT2	; clear time counter 2 	
    	bsf	PORTA,3		; alarm output high 
    	clrf	SPEED_EQV	; clear speed equivalent store
    
    ; Convert the display readings to a binary speed equivalent value	
    
    	movf	DISP3,w		; look at DISP3 value
    	btfsc	STATUS,z	; check if 0
    	goto 	ZERO
    	xorlw	0x01		; check if a 1
    	btfsc	STATUS,z	; z is 1 if a 1
    	goto	ONE		; 
    	movlw	D'100'		; 100
    	movwf	SPEED_EQV	; 100 in speed equivalent
    ONE	movlw	D'100'
    	addwf	SPEED_EQV,f	; 200 if disp3 was a 2
    ZERO	movf	DISP2,w		; look at display 2
    	movwf	TEMP_X		; place in temporary register
    INC_SE	movlw	D'10'		; 10
    	addwf	SPEED_EQV,f	; increase speed equivalent by 10		
    	decfsz	TEMP_X,f	; reduce disp2 value
    	goto	INC_SE		; do again
    	movf	DISP1,w		; display 1 value
    	addwf	SPEED_EQV,f	; add display 1 value 		 
    	return
    
    	
    ; allow interrupts
    
    INT_SET	btfss	REPEAT,1	; bit 1 on/off flag
    	goto	RB0_INT		; no RB0 interrupt if speed alarm unit in off mode
    	bsf	INTCON,INTE	; set interrupt enable for RB0
    RB0_INT	bsf	INTCON,T0IE	; set interrupt enable for TMR0 
    SWITCH	bsf	INTCON,GIE	; set global interrupt enable for above
    
    ; check if a switch is pressed
    
    	bcf	FLAG_1,0	; clear multiplex update flag
    MULTIP	btfss	FLAG_1,0	; check if multiplex update occured
    	goto	MULTIP		; wait for new multiplex update for display
    	btfsc	PORTA,4		; if a switch is pressed, then bit 4 will be low
    	goto	SWITCH		; no switch pressed so look again
    	
    ; check for Cal switch
    
    	bcf	INTCON,GIE	; clear interrupts
    	bcf	ERR_FLG,0	; clear error flag when any switch pressed
    	movf	PORTA,w		; look at RA0-RA2
    	
    	movwf	TEMP_1		; store in temporary memory
    	iorlw	B'00000111'	; bit 0-2 high
    	movwf	PORTA		; place in port A, displays off
    	
    	movlw	0x1F		; delay period
    	movwf	VALUE_1		; VALUE_1 = w
    DELOOP	decfsz	VALUE_1,f	; decrease VALUE_1, skip if zero
    	goto	DELOOP	
    
    	btfss	PORTA,4		; is the cal switch pressed
    	goto 	CALIBRT		; yes it is the cal switch
    	movf	TEMP_1,w	; retrieve port A bit 0-2
    	movwf	PORTA		; port A bits 0-2 as before
    	nop			; give time for ports to change
    	nop
    	nop
    	btfsc	PORTA,4		; if a switch is pressed, then bit 4 will be low
    	goto	SWITCH		; no switch pressed so look again
    	btfsc	PORTA,0		; is it the mode switch	
    	goto	D_U_CHK
    	goto 	MODE
    D_U_CHK	btfss	REPEAT,1	; is on/off flag on
    	goto	WAIT		; no up down selection allowed when speed alarm unit is off
    	btfsc	PORTA,1		; is it the Down switch
    	goto	U_CHK
    	goto	DOWN
    U_CHK	btfsc	PORTA,2		; is it the UP switch
    	goto	SWITCH		; no switch reading
    	goto 	UP

  7. #7
    Join Date
    Sep 2007
    Posts
    12


    Did you find this post helpful? Yes | No

    Default part 6

    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

Members who have read this thread : 0

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts