pls i hve a source code for a digital alarm clock bt its for pic16c54a and i want to desiogn a digital alarm clock using pic 16f84a so here is my source code, i need an assembly language guru to help me do this pls. below is the source code
[; *********************************************
; * PIC Egg Timer Give-Away *
; * *
; * Author: John Day *
; * Sr. Field Applications Engineer *
; * Northeast Region *
; * *
; * Revision: 1.2 *
; * Date September 22, 1994 *
; * Part: PIC16C54-LP/P or PIC16LC54A/P *
; * Fuses: OSC: LP *
; * WDT: OFF *
; * PuT: OFF *
; * CP: OFF *
; *********************************************
;
; This program is intended to run on a 32 Khz watch crystal and connects
; to four multiplexed seven segment displays. It displays the current
; time, alarm time and egg count down timers. There are switches that
; allow the user to set the alarm, timer and clock functions.
LIST F=INHX8M,P=16C54
INCLUDE "c:\pictools\picstarc\p16C5X.inc"
__FUSES _CP_OFF&_WDT_OFF&_LP_OSC
ORG 07h
; ****************************************
; * Static RAM Register File Definitions *
; ****************************************
INDADDR EQU 0 ; Indirect address register
DISPSEGS_A EQU 07h ; Current Display A segment bit pattern
DISPSEGS_B EQU 08h ; Current Display B segment bit pattern
DISPSEGS_C EQU 09h ; Current Display C segment bit pattern
DISPSEGS_D EQU 0Ah ; Current Display D segment bit pattern
CLK_SEC EQU 0Bh ; Clock second counter (0-59)
CLK_MIN_LD EQU 0Ch ; Clock minute low digit counter (0-9)
CLK_MIN_HD EQU 0Dh ; Clock minute high digit counter (0-5)
CLK_HOUR_LD EQU 0Eh ; Clock hour low digit counter (0-9)
CLK_HOUR_HD EQU 0Fh ; Clock hour high digit counter (0-2)
ALM_MIN_LD EQU 10h ; Alarm minute low digit counter (0-9)
ALM_MIN_HD EQU 11h ; Alarm minute high digit counter (0-5)
ALM_HOUR_LD EQU 12h ; Alarm hour lor digit counter (0-9)
ALM_HOUR_HD EQU 13h ; Alarm hour high digit counter (0-2)
TMR_SEC_LD EQU 14h ; Timer second low digit counter (0-9)
TMR_SEC_HD EQU 15h ; Timer second high digit counter (0-5)
TMR_MIN_LD EQU 16h ; Timer hour low digit counter (0-9)
TMR_MIN_HD EQU 17h ; Timer hour high digit counter (0-2)
KEYPAT EQU 18h ; Currently pressed key bits
FLAGS EQU 19h ; Status of alarms, display on, etc.
PREVTMR0 EQU 1Ah ; Used to determine which TMR0 bits changed
PREVSCAN EQU 1Bh ; Store Common Cathode display scan state
TEMP EQU 1Ch ; Temporary storage
DISPONCNT EQU 1Dh ; Time the displays have been on
MODE_COUNT EQU 1Eh ; Current mode state
ALARMCNT EQU 1Fh ; Time the alarm has been sounding
; ****************************************
; * Flag and state bit definitions *
; ****************************************
#define SECBIT TEMP,7 ; Bit to spawn 1/4 second count
#define SCANBIT TMR0,0 ; Bit to spawn display MUX
#define MODEKEY KEYPAT,4 ; Bit for MODEKEY pressed
#define UPKEY KEYPAT,6 ; Bit for UPKEY pressed
#define DOWNKEY KEYPAT,5 ; Bit for DOWNKEY pressed
#define MODEKEYCHG TEMP,4 ; Bit for delta MODEKEY
#define TIMENOW FLAGS,7 ; Flag to indicate 1 second passed
#define ALARMNOW FLAGS,3 ; Flag to indicate wakeup alarm
#define EGGNOW FLAGS,4 ; Flag to indicate egg timer alarm
#define ALARMOK STATUS,PA0 ; Flag to enable wakeup alarm
#define EGGOK STATUS,PA1 ; Flag to enable timer alarm
#define BUZZEROUT PORTB,7 ; Pin for pulsing the buzzer
#define DISPON DISPONCNT,4 ; Bit to turn on LED displays
; *************************************************
; * Various Constants used throughout the program *
; *************************************************
TMR0 EQU 1 ; Location of the TMR0 register
SEC_MAX EQU .60 ; Maximum value for second counter
MIN_LD_MAX EQU .10 ; Maximum value for low digit of minute
MIN_HD_MAX EQU .6 ; Maximum value for high digit of minute
HOUR_LD_MAX EQU .4 ; Maximum value for low digit of hour
HOUR_HD_MAX EQU .2 ; Maximum value for high digit of hour
OPTION_SETUP EQU b'00000011' ; TMR0 - internal, /16 prescale
BUZINITVAL EQU 7 ;
INIT_MODE_COUNT EQU 8 ; Digit counts to move to hour digits
ALARMCYCCNT EQU .40 ; Alarm for 10 seconds (ALARMCYCCNT/4)
ORG 01FFh ; The PIC5X reset vector is at end of memory
reset_vector
GOTO init ; Jump to the initialization code
ORG 0
; ****************************************
; * Current mode look-up table *
; ****************************************
mode_timer
ANDLW 3 ; Mask off upper bits just in case..
ADDWF PC ; Jump to one of 4 look-up entries
RETLW TMR_SEC_LD ; Return the address of the 99 min timer RAM
RETLW ALM_MIN_LD ; Return the address of the alarm RAM
RETLW CLK_MIN_LD ; Return the address of the clock RAM
RETLW CLK_MIN_LD ; Return the address of the clock RAM
; ****************************************
; * Buzz the buzzer for 1/8 second *
; ****************************************
buzz_now
CLRF PORTB ; Shut off the segments
buzz_now_dispon
CLRF TEMP ; Buzz for 256 pulses
loop_buz
BSF BUZZEROUT ; Send out pulse
BCF BUZZEROUT ; Clear out the pulse
DECFSZ TEMP ; Decriment counter and skip when done
GOTO loop_buz ; Go back and send another pulse
RETLW 0 ; We are done so come back!
; ****************************************
; * Mux drive the next LED display digit *
; ****************************************
task_scan ; (19 (next_scan) + 2 = 21 cycles - must be called every 11 cy)
BTFSC SCANBIT ; Synch up with 3.9 mS timer bit
GOTO task_scan ; Jump back until bit is clear
next_scan ; (15 + 2 call + 2 return = 19 cycles)
RLF PREVSCAN,W ; Move to the next digit select into C
BTFSS PREVSCAN,1 ; 0 Check if display A was on before
MOVF DISPSEGS_C,W ; Place display B value into W
BTFSS PREVSCAN,0 ; 1 Check if display B was on before
MOVF DISPSEGS_B,W ; Place display C value into W
BTFSS PREVSCAN,3 ; 2 Check if display C was on before
MOVF DISPSEGS_A,W ; Place display D value into W
BTFSS PREVSCAN,2 ; 3 Check if display D was on before
MOVF DISPSEGS_D,W ; Place display A value into W
CLRF PORTB ; Turn off all segments
RLF PREVSCAN ; Move to the next digit
RLF PORTA ; Move port to the next digit
MOVWF PORTB ; Place next segment value on PORTB
MOVF PREVSCAN,W ; Restore the port in case it is wrong
MOVWF PORTA ; Restore the port
RETLW 0 ; Display is updated - now return
; **********************************************
; * Move new digit display info out to display *
; **********************************************
disp_value
MOVWF FSR ; Place W into FSR for indirect addressing
CALL task_scan ; Scan the next LED digit.
MOVF INDADDR,W ; Place display value into W
CALL led_lookup ; Look up seven segment value
MOVWF DISPSEGS_A ; Move value out to display register A
INCF FSR ; Go to next display value
CALL task_scan ; Scan the next LED digit.
MOVF INDADDR,W ; Place display value into W
CALL led_lookup ; Look up seven segment value
MOVWF DISPSEGS_B ; Move value out to display register B
INCF FSR ; Go to next display value
CALL task_scan ; Scan the next LED digit.
MOVF INDADDR,W ; Place display value into W
CALL led_lookup ; Look up seven segment value
MOVWF DISPSEGS_C ; Move value out to display register C
INCF FSR ; Go to next display value
CALL task_scan ; Scan the next LED digit.
MOVF INDADDR,W ; Place display value into W
BTFSC STATUS,Z ; ZBLANK - Check for a zero
COMF INDADDR,W ; ZBLANK - Clear digit with FF if leading 0
CALL led_lookup ; Look up seven segment value
MOVWF DISPSEGS_D ; Move value out to display register D
CALL task_scan ; Scan the next LED digit.
RETLW 0
; ****************************************
; * Convert display value into segments *
; ****************************************
led_lookup
ANDLW 0Fh ; Strip off upper digits
ADDWF PC ; Jump into the correct location
RETLW b'00111111' ; Bit pattern for a Zero
RETLW b'00000110' ; Bit pattern for a One
RETLW b'01011011' ; Bit pattern for a Two
RETLW b'01001111' ; Bit pattern for a Three
RETLW b'01100110' ; Bit pattern for a Four
RETLW b'01101101' ; Bit pattern for a Five
RETLW b'01111101' ; Bit pattern for a Six
RETLW b'00000111' ; Bit pattern for a Seven
RETLW b'01111111' ; Bit pattern for a Eight
RETLW b'01101111' ; Bit pattern for a Nine
RETLW 0 ; Turn display off - ILLEGAL VALUE
RETLW 0 ; Turn display off - ILLEGAL VALUE
RETLW 0 ; Turn display off - ILLEGAL VALUE
RETLW 0 ; Turn display off - ILLEGAL VALUE
RETLW 0 ; Turn display off - ILLEGAL VALUE
RETLW 0 ; Turn display off - ILLEGAL VALUE
; ************************************************************************
; * Convert display value into single segment ON for manufacturing diags *
; ************************************************************************
mfg_led_lookup
ANDLW 07h ; Strip off upper digits
ADDWF PC ; Jump into the correct location
RETLW b'00000001' ; Bit pattern for segment A on only
RETLW b'00000010' ; Bit pattern for segment B on only
RETLW b'00000100' ; Bit pattern for segment C on only
RETLW b'00001000' ; Bit pattern for segment D on only
RETLW b'00010000' ; Bit pattern for segment E on only
RETLW b'00100000' ; Bit pattern for segment F on only
RETLW b'01000000' ; Bit pattern for segment G on only
RETLW b'01111111' ; Bit pattern for all segments on
; ***********************************************************
; * Wake-up and turn on the displays *
; ***********************************************************
turnon_scan
BSF DISPON ; Set display ON bit
MOVLW b'11101110' ; Place digit 0 scan pattern in W
XORWF PREVSCAN,W ; See if this is the current scan
BTFSC STATUS,Z ; Skip if this is not the current scan
RETLW 0 ; Legal scan value - we are done!
MOVLW b'11011101' ; Place digit 1 scan pattern in W
XORWF PREVSCAN,W ; See if this is the current scan
BTFSC STATUS,Z ; Skip if this is not the current scan
RETLW 0 ; Legal scan value - we are done!
MOVLW b'10111011' ; Place digit 2 scan pattern in W
XORWF PREVSCAN,W ; See if this is the current scan
BTFSC STATUS,Z ; Skip if this is not the current scan
RETLW 0 ; Legal scan value - we are done!
MOVLW b'01110111' ; Place digit 3 scan pattern in W
XORWF PREVSCAN,W ; See if this is the current scan
BTFSC STATUS,Z ; Skip if this is not the current scan
RETLW 0 ; Legal scan value - we are done!
MOVLW 0EEh ; Move digit 0 scan value into W
MOVWF PREVSCAN ; Move it into scan pattern register
; ****************************************
; * Scan for pressed keys *
; ****************************************
scan_keys
CLRF PORTB ; Turn off all of the segments
MOVLW 0FFh ; Place FF into W
MOVWF PORTA ; Make PORT A all ones
MOVLW b'01110000' ; Place 70 into W
TRIS PORTB ; Make RB4,5,6 inputs others outputs
MOVF PORTB,W ; Place keyscan value into W
XORWF KEYPAT,W ; Place Delta key press into W
MOVWF TEMP ; Place Delta key press into TEMP
XORWF KEYPAT,F ; Update KEYPAT reg to buttons pressed
CLRW ; Place 0 into W
TRIS PORTB ; Make PORT B outputs
MOVF PREVSCAN,W ; Place previous scan value into W
MOVWF PORTA ; Turn on the scan
RETLW 0
; ****************************************
; * Check if alarm or timer is expired *
; ****************************************
check_time
CALL task_scan ; Scan the next LED digit.
BSF ALARMNOW ; Set the alarm bit
BSF EGGNOW ; Set the Egg timer alarm bit
MOVF ALM_MIN_LD,W ; Place alarm minute counter into W
SUBWF CLK_MIN_LD,W ; CLK_MIN_LD - W -> W
BTFSS STATUS,Z ; Skip if they are equal
BCF ALARMNOW ; They are not equal so clear alarm bit
MOVF ALM_MIN_HD,W ; Place alarm minute counter into W
SUBWF CLK_MIN_HD,W ; CLK_MIN_HD - W -> W
BTFSS STATUS,Z ; Skip if they are equal
BCF ALARMNOW ; They are not equal so clear alarm bit
CALL task_scan ; Scan the next LED digit.
MOVF ALM_HOUR_LD,W ; Place alarm hour counter into W
SUBWF CLK_HOUR_LD,W ; CLK_HOUR_LD - W -> W
BTFSS STATUS,Z ; Skip if they are equal
BCF ALARMNOW ; They are not equal so clear alarm bit
MOVF ALM_HOUR_HD,W ; Place alarm hour counter into W
SUBWF CLK_HOUR_HD,W ; CLK_HOUR_LD - W -> W
BTFSS STATUS,Z ; Skip if they are equal
BCF ALARMNOW ; They are not equal so clear alarm bit
CALL task_scan ; Scan the next LED digit.
MOVF TMR_SEC_LD,W ; Set the Z bit to check for zero
BTFSS STATUS,Z ; Skip if this digit is zero
BCF EGGNOW ; Timer is not zero so clear egg alarm bit
MOVF TMR_SEC_HD,W ; Set the Z bit to check for zero
BTFSS STATUS,Z ; Skip if this digit is zero
BCF EGGNOW ; Timer is not zero so clear egg alarm bit
MOVF TMR_MIN_LD,W ; Set the Z bit to check for zero
BTFSS STATUS,Z ; Skip if this digit is zero
BCF EGGNOW ; Timer is not zero so clear egg alarm bit
CALL task_scan ; Scan the next LED digit.
MOVF TMR_MIN_HD,W ; Set the Z bit to check for zero
BTFSS STATUS,Z ; Skip if this digit is zero
BCF EGGNOW ; Timer is not zero so clear egg alarm bit
BTFSS EGGNOW ; Skip if we are still at EGG Time
BSF EGGOK ; If we are not at EGG time, re-set egg alarm
BTFSS ALARMNOW ; Skip if we are still at Alarm time
BSF ALARMOK ; If we are not at Alarm time, re-set alarm
CALL task_scan ; Scan the next LED digit.
RETLW 0
; ****************************************
; * Incriment the clock, timer or alarm *
; ****************************************
inc_time
MOVWF FSR ; Add one to clock second counter
CALL task_scan ; Scan the next LED digit.
INCF INDADDR ; Add one to minute lower digit
MOVLW SEC_MAX ; Place second max value into w
SUBWF INDADDR,W ; CLOCK_SEC - SEC_MAX -> W
BTFSS STATUS,C ; Skip if there is an overflow
RETLW 0 ; We are done so let's get out of here!
CLRF CLK_SEC ; Clear CLK_second counter
INCF FSR ; Move to the next digit
INCF INDADDR ; Add 1 to minute LOW digit
GOTO skip_min_fsr ; Jump to the next digit
inc_min_ld
MOVWF FSR
INCF INDADDR ; Add 1 to minute LOW digit
skip_min_fsr
CALL task_scan ; Scan the next LED digit.
MOVLW MIN_LD_MAX ; Place minute lower digit max value into W
SUBWF INDADDR,W ; CLK_MIN_LD - MIN_LD_MAX -> W
BTFSS STATUS,C ; Skip if there is an overflow
RETLW 0 ; We are done so let's get out of here!
CLRF INDADDR ; Clear CLK minute low digit
INCF FSR ; Move to the minute high digit
INCF INDADDR ; Add one to minute high digit
inc_min_hd
CALL task_scan ; Scan the next LED digit.
MOVLW MIN_HD_MAX ; Place minute high digit max value into W
SUBWF INDADDR,W ; CLK_MIN_HD - MIN_HD_MAX -> W
BTFSS STATUS,C ; Skip if there is an overflow
RETLW 0 ; We are done so let's get out of here!
CLRF INDADDR ; Clear CLK minute high digit
INCF FSR ; Move to the hour low digit
INCF INDADDR ; Add one to hour low digit
GOTO skip_hour_fsr ; Jump to the next digit
inc_hour_ld
MOVWF FSR
INCF FSR
INCF FSR
INCF INDADDR ; Add 1 to minute LOW digit
skip_hour_fsr
CALL task_scan ; Scan the next LED digit.
MOVLW MIN_LD_MAX ; Place hour lower digit max value into W
SUBWF INDADDR,W ; CLK_HOUR_LD - HOUR_LD_MAX -> W
BTFSS STATUS,C ; Skip if there is an overflow
GOTO check_inc ; We need to check for overflow
CLRF INDADDR ; Clear CLK hour low digit
INCF FSR ; Move to the hour high digit
INCF INDADDR ; Add one to hour high digit
GOTO inc_hour_hd
check_inc
INCF FSR ; Move to hour high digit
inc_hour_hd
CALL task_scan ; Scan the next LED digit.
MOVLW HOUR_HD_MAX ; Place hour high digit max value into W
BTFSC FLAGS,1
GOTO off_mode1
BTFSC FLAGS,0
MOVLW MIN_LD_MAX-1
off_mode1
SUBWF INDADDR,W ; CLK_HOUR_HD - HOUR_HD_MAX -> W
BTFSS STATUS,C ; Skip if there is an overflow
RETLW 0 ; We are done so let's get out of here!
DECF FSR ; Move to the hour low digit
CALL task_scan ; Scan the next LED digit.
MOVLW HOUR_LD_MAX ; Place hour high digit max value into W
BTFSC FLAGS,1
GOTO off_mode2
BTFSC FLAGS,0
MOVLW 0 ; Clear W
off_mode2
SUBWF INDADDR,W ; CLK_HOUR_HD - HOUR_HD_MAX -> W
BTFSS STATUS,C ; Skip if there is an overflow
RETLW 0 ; We are done so let's get out of here!
CALL task_scan ; Scan the next LED digit.
CLRF INDADDR ; Clear hour high digit
BTFSC FLAGS,1
GOTO off_mode3
BTFSS FLAGS,0
off_mode3
NOP
INCF FSR ; Move to the hour high digit
CLRF INDADDR ; Clear one hour low digit
CALL task_scan
RETLW 0 ; We are done so let's get out of here!
dec_hour_ld
GOTO dec_hour_ld_vect ; ran out of CALL space....
; ****************************************
; * Decriment the clock, alarm or timer *
; ****************************************
dec_time
dec_min_ld
MOVWF FSR ; Set up pointer for indirect address
CALL task_scan ; Scan the next LED digit.
DECF INDADDR,F ; Subtract one from CLK_MIN_LD
COMF INDADDR,W ; Set the Z bit to check for zero
BTFSS STATUS,Z ; Skip if CLK_MIN_LD is zero
RETLW 0 ; We are done... Let's get out of here
MOVLW MIN_LD_MAX - 1 ; Place minute lower digit max value into W
MOVWF INDADDR ; MIN_LD_MAX -> CLK_MIN_LD
dec_min_hd
CALL task_scan ; Scan the next LED digit.
INCF FSR ; Move the pointer to Min HIGH DIGIT
DECF INDADDR,F ; Subtract one from CLK_MIN_HD
COMF INDADDR,W ; Set the Z bit to check for zero
BTFSS STATUS,Z ; Skip if CLK_MIN_LD is zero
RETLW 0 ; We are done... Let's get out of here
MOVLW MIN_HD_MAX - 1 ; Place minute lower digit max value into W
MOVWF INDADDR ; MIN_HD_MAX -> CLK_MIN_HD
CALL task_scan ; Scan the next LED digit.
INCF FSR ; Move the pointer to Hour LOW DIGIT
GOTO skip_dhour_fsr ; Jump to the next digit
dec_hour_ld_vect
MOVWF FSR
INCF FSR
INCF FSR
CALL task_scan ; Scan the next LED digit.
skip_dhour_fsr
DECF INDADDR,F ; Subtract one from CLK_HOUR_LD
COMF INDADDR,W ; Set the Z bit to check for zero
BTFSS STATUS,Z ; Skip if CLK_MIN_LD is zero
GOTO check_hour
MOVLW MIN_LD_MAX - 1 ; Place minute lower digit max value into W
MOVWF INDADDR ; MIN_LD_MAX -> CLK_HOUR_LD
INCF FSR ; Move the pointer to Hour HIGH DIGIT
DECF INDADDR,F ; Subtract one from CLK_HOUR_HD
GOTO dec_hour_hd
check_hour
INCF FSR ; Point to hour high digit
dec_hour_hd
CALL task_scan ; Scan the next LED digit.
COMF INDADDR,W
BTFSS STATUS,Z
RETLW 0
CALL task_scan ; Scan the next LED digit.
DECF FSR
MOVLW .9 ; Reset digit to 9
SUBWF INDADDR,W
BTFSS STATUS,Z ; Skip if CLK_MIN_LD is zero
RETLW 0 ; We are done... Let's get out of here
CALL task_scan ; Scan the next LED digit.
INCF FSR
MOVLW HOUR_HD_MAX ; Place minute lower digit max value into W
BTFSS FLAGS,1 ; Skip if CLOCK or ALARM mode
MOVLW .9 ; Reset digit to 9
MOVWF INDADDR ; HOUR_HD_MAX -> CLK_HOUR_HD
MOVLW HOUR_LD_MAX - 1 ; Place minute lower digit max value into W
BTFSS FLAGS,1 ; Skip if CLOCK or ALARM mode
MOVLW .9 ; Reset digit to 9
DECF FSR ; Move the pointer to Min LOW DIGIT
MOVWF INDADDR ; HOUR_LD_MAX -> CLK_HOUR_LD
CALL task_scan ; Scan the next LED digit.
RETLW 0 ; We are done... Let's get out of here
; ****************************************
; * Main loop calls all tasks as needed *
; ****************************************
main_loop
CALL task_scan ; Scan the next LED digit.
MOVF TMR0,W ; Place current TMR0 value into W
XORWF PREVTMR0,W ; Lets see which bits have changed...
MOVWF TEMP ; All changed bits are placed in temp for test
XORWF PREVTMR0,F ; Update Previous TMR0 value.
BTFSS SECBIT ; Skip if it is not time to increment second
GOTO main_loop ; Go back to main loop if 250 mS not passed
MOVLW b'00100000' ; Bits 6 and 5 of FLAGS used as divide by 4
ADDWF FLAGS,F ; Add one to bit 5
BTFSS TIMENOW ; Check bit 7 - if four adds occur, skip
GOTO skip_timer ; One second has not passed - skip timers
CALL task_scan ; Scan the next LED digit.
BCF TIMENOW ; Clear out second passed flag
MOVLW CLK_SEC ; Place pointer to increment clock
CALL inc_time ; Increment the clock
CALL check_time ; Check for alarm or timer conditions
BTFSC EGGNOW ; Do NOT decrease timer if zero
GOTO skip_timer ; Jump out if egg timer is zero
BTFSC UPKEY ; Skip if UP key is NOT pressed
GOTO skip_timer ; Jump out if UP key is pressed
BTFSC DOWNKEY ; Skip if DOWN key is NOT pressed
GOTO skip_timer ; Jump out if DOWN key is pressed
MOVLW TMR_SEC_LD ; Place pointer to decrement timer
CALL dec_time ; Decrement countdown timer
MOVLW ALARMCYCCNT ; Place the number of alarm beeps into W
MOVWF ALARMCNT ; Move beep count to ALARMCNT
skip_timer
BTFSS ALARMOK ; Skip if this is the first pass into alarm
GOTO skip_wakeup ; Second pass - do not re-init ALARMCNT
BTFSS ALARMNOW ; Skip if this is alarm pass
GOTO skip_wakeup ; Countdown timer - do not re-init ALARMCNT
MOVLW ALARMCYCCNT ; Place the number of alarm beeps into W
MOVWF ALARMCNT ; Move beep count to ALARMCNT
BCF ALARMOK ; Clear flag for second pass
skip_wakeup
CALL task_scan ; Scan the next LED digit.
BTFSC ALARMNOW ; Skip if alarm clock is not set
GOTO send_alarm ; Blast out a beep
BTFSC EGGNOW ; Skip if countdown timer is not alarming
GOTO send_alarm ; Blast out a beep
GOTO skip_alarm ; Skip beeping and continue
send_alarm
MOVF ALARMCNT,W ; Place ALARMCNT into W
BTFSC STATUS,Z ; Skip if not zero
GOTO skip_alarm ; We are done beeping - skip and continue
DECFSZ ALARMCNT,F ; Decriment beep count and skip when zero
CALL buzz_now ; Blast out the beep!!!
skip_alarm
BTFSS FLAGS,5 ; Skip if it is time to scan the keys 1/2 sec
goto finish_update ; Jump to finish updates - don't scan
CALL scan_keys ; Scan the keys and load value into KEYPAT
CALL task_scan ; Scan the next LED digit.
BTFSS MODEKEY ; Skip if the MODEKEY is pressed
GOTO same_mode ; Not pressed so it is the same mode...
BTFSS MODEKEYCHG ; Skip if the is pressing edge
GOTO same_mode ; Button is held so it is the same mode...
INCF FLAGS ; Advance the mode by incrimenting bits 0,1
BCF FLAGS,2 ; Force mode to wrap-around by clearing bit 2
CALL turnon_scan ; Mode button pressed - must turn on LEDs
same_mode
call task_scan ; Scan the next LED digit.
BTFSC UPKEY ; Skip if the UP key is not pressed
GOTO serve_up_key ; UP key is pressed - jump to serve it!
BTFSC DOWNKEY ; Skip if the DOWN key is not pressed
GOTO serve_down_key ; DOWN key is pressed - jump to serve it!
MOVLW INIT_MODE_COUNT ; UP and DOWN not pressed - re-init mode count
MOVWF MODE_COUNT ; Change back to lower digits for setting
MOVF DISPONCNT,F ; Update Z bit in STATUS reg display on time
BTFSS STATUS,Z ; Skip if displays should be OFF
DECF DISPONCNT ; Decriment display ON counter
BTFSS STATUS,Z ; Skip if displays should be OFF
GOTO finish_update ; Displays are ON - jump to finish updates
BCF FLAGS,0 ; Restore the mode to displays OFF
BCF FLAGS,1 ; Restore the mode to displays OFF
CLRF PORTB ; Clear out segment drives on PORTB
CLRF PORTA ; Clear out common digit drives on PORTA
GOTO finish_update ; Jump to finish updates
serve_up_key
call task_scan ; Scan the next LED digit.
BTFSC FLAGS,0 ; Skip if not in TIMER or CLOCK mode
GOTO no_up_display ; Currently in TIMER or CLOCK - keep mode
BTFSC FLAGS,1 ; Skip if not in ALARM mode
GOTO no_up_display ; Currently in ALARM - keep mode
BSF FLAGS,0 ; Set to CLOCK mode
BSF FLAGS,1 ; Set to CLOCK mode
no_up_display
CLRF ALARMCNT ; A key was pressed, so turn off alarm
call turnon_scan ; Turn on the LEDs
BTFSS MODEKEY ; Skip if MODE is pressed as well
GOTO finish_update ; MODE is not pressed - jump to finish update
MOVF MODE_COUNT,W ; Update STATUS Z bit for mode count
BTFSS STATUS,Z ; Skip if we have counted down to zero
DECF MODE_COUNT ; Decriment the mode count
call task_scan ; Scan the next LED digit.
MOVF MODE_COUNT,W ; Update the Z bit to check for zero
BTFSS STATUS,Z ; Skip if we have incrimented for 7 times
GOTO serve_min_up ; Incriment the minutes digits
DECF FLAGS,W ; Place current mode into W
CALL mode_timer ; Look-up register RAM address for current mode
CALL inc_hour_ld ; Add one hour to the current display
GOTO finish_update ; Jump to finish updates
serve_min_up
call task_scan ; Scan the next LED digit.
DECF FLAGS,W ; Place current mode into W
CALL mode_timer ; Look-up register RAM address for current mode
CALL inc_min_ld ; Add one minute to the current display
GOTO finish_update ; Jump to finish updates
serve_down_key
call task_scan ; Scan the next LED digit.
BTFSC FLAGS,0 ; Skip if not in TIMER or CLOCK mode
GOTO no_dn_display ; Currently in TIMER or CLOCK - keep mode
BTFSC FLAGS,1 ; Skip if not in ALARM mode
GOTO no_dn_display ; Currently in ALARM - keep mode
BSF FLAGS,0 ; Set to CLOCK mode
BSF FLAGS,1 ; Set to CLOCK mode
no_dn_display
CLRF ALARMCNT ; A key was pressed, so turn off alarm
CALL turnon_scan ; Turn on the LEDs
BTFSS MODEKEY ; Skip if MODE is pressed as well
GOTO finish_update ; MODE is not pressed - jump to finish update
MOVF MODE_COUNT,W ; Update STATUS Z bit for mode count
BTFSS STATUS,Z ; Skip if we have counted down to zero
DECF MODE_COUNT ; Decriment the mode count
call task_scan ; Scan the next LED digit.
MOVF MODE_COUNT,W ; Update the Z bit to check for zero
BTFSS STATUS,Z ; Skip if we have incrimented for 7 times
GOTO serve_min_down ; Decriment the minutes digits
DECF FLAGS,W ; Place current mode into W
CALL mode_timer ; Look-up register RAM address for current mode
CALL dec_hour_ld ; Subtract one hour from the current display
GOTO finish_update ; Jump to finish updates
serve_min_down
DECF FLAGS,W ; Place current mode into W
CALL mode_timer ; Look-up register RAM address for current mode
CALL dec_min_ld ; Subtract one minute from the current display
finish_update
call task_scan ; Scan the next LED digit.
BTFSC FLAGS,0 ; Skip if in mode OFF or ALARM
GOTO new_display ; Jump to update LED display registers
BTFSC FLAGS,1 ; Skip if in mode OFF
GOTO new_display ; Jump to update LED display registers
CLRF DISPSEGS_A ; Clear display regs to Shut off LED display
CLRF DISPSEGS_B ; Clear display regs to Shut off LED display
CLRF DISPSEGS_C ; Clear display regs to Shut off LED display
CLRF DISPSEGS_D ; Clear display regs to Shut off LED display
GOTO main_loop ; We are done - go back and do it again!
new_display
DECF FLAGS,W ; Move current mode state into W
CALL mode_timer ; Look-up register address of value to display
CALL disp_value ; Update display registers with new values
GOTO main_loop ; We are done - go back and do it again!
; ****************************************
; * Set up and initialize the processor *
; ****************************************
init
MOVLW OPTION_SETUP ; Place option reg setup into W
OPTION ; Set up OPTION register
MOVLW PORTA ; Place beginning of RAM/Port location into W
MOVWF FSR ; Now initialize FSR with this location
clear_mem
CLRF INDADDR ; Clear the FSR pointed memory location
INCFSZ FSR ; Point to the next location
GOTO clear_mem ; Jump back to clear memory routine
BSF ALM_HOUR_LD,3 ; Place 8:00 into alarm register
INCF CLK_HOUR_LD ; Place 1:00 into clock register
MOVLW 0EEh ; Turn on display A scan line, others off
MOVWF PREVSCAN ;
CLRW
TRIS PORTB ; Make all Port B pins outputs.
TRIS PORTA ; Make all Port A pins outputs.
BSF FLAGS,1 ; Set up current mode to CLOCK, display ON
BSF FLAGS,0
BCF ALARMOK ; Don't want to trigger alarms
BCF EGGOK
BSF DISPON ; Turn on the displays
mfg_checkkey
CALL scan_keys ; Lets see what is pressed
BTFSS UPKEY ; Goto self-test if UP key is pressed at pwr up
GOTO main_loop ; Normal operation - Jump to the main loop
; *****************************************************************
; * Self-test code for manufacturing only - test buttons and LEDs *
; *****************************************************************
mfg_selftest
MOVLW b'01110000' ; Place all key on pattern into W
MOVWF CLK_MIN_HD ; Use CLK_MIN_HD for keystuck ON test
CLRF CLK_HOUR_HD ; Use CLK_HOUR_HD for keystuck OFF test
mfg_display
MOVF CLK_SEC,W ; Current segment display count -> W
CALL mfg_led_lookup ; Look-up the next segment pattern to display
MOVWF PORTB ; Move the pattern to PORT B to display it
mfg_timer
MOVF TMR0,W ; Place current TMR0 value into W
XORWF PREVTMR0,W ; Lets see which bits have changed...
MOVWF TEMP ; All changed bits are placed in temp for test
XORWF PREVTMR0,F ; Update Previous TMR0 value.
BTFSS TEMP,7 ; Skip if it is not time to increment second
GOTO mfg_timer ; It is not time to move to next digit - go back
INCF CLK_SEC ; Move to the next display pattern
mfg_check_digit
BTFSS CLK_SEC,5 ; Skip if we have timed out waiting for button
GOTO mfg_doneclk ; Jump to check for the next button press
mfg_nextdigit
CLRF CLK_SEC ; Clear out timer
CALL buzz_now ; Send out a buzzer beep!
BTFSS PREVSCAN,3 ; Skip if we have NOT tested the last digit
GOTO finish_mfg_test ; Jump to the end after last digit tested
RLF PREVSCAN,W ; Select the next digit through a rotate..
RLF PREVSCAN
MOVF PREVSCAN,W ; Place next digit select into W
MOVWF PORTA ; Update port A to select next digit
mfg_doneclk
CALL scan_keys ; Scan the keys to see what is pressed...
MOVF KEYPAT,W ; Place pattern into W
ANDWF CLK_MIN_HD ; Make shure keys are not stuck ON
IORWF CLK_HOUR_HD ; Make shure each key is pressed at least once
BTFSS PREVSCAN,3 ; Skip if we are NOT at the last digit
BSF KEYPAT,7 ; Set flag bit to indicate we are done!
MOVLW .8 ; Place 8 into W
SUBWF CLK_SEC,W ; CLK_SEC - W => W
BTFSS STATUS,C
CLRF KEYPAT
SWAPF KEYPAT
COMF PREVSCAN,W
ANDWF KEYPAT,W
BTFSS STATUS,Z
GOTO mfg_nextdigit
GOTO mfg_display
finish_mfg_test
MOVF CLK_MIN_HD,F
BTFSS STATUS,Z
GOTO bad_switch
MOVF CLK_HOUR_HD,W
XORLW 070h
BTFSS STATUS,Z
GOTO bad_switch
mfg_cleanup
CLRF CLK_HOUR_HD ; Restore temp registers to zero
CLRF CLK_MIN_HD ; Restore temp registers to zero
GOTO main_loop ; Jump to main loop
bad_switch
COMF CLK_MIN_HD,F
SWAPF CLK_MIN_HD,W
MOVWF KEYPAT
BSF CLK_HOUR_HD,7
SWAPF CLK_HOUR_HD,W
ANDWF KEYPAT
MOVLW 07Fh
MOVWF PORTB
CLRF CLK_MIN_LD
BSF CLK_MIN_LD,5
loop_bad_sw
CALL buzz_now_dispon ; Beep the buzzer constantly for a few secs
DECFSZ CLK_MIN_LD ; Decriment counter and skip when done
GOTO loop_bad_sw ; Not done buzzing - go back and do it again
GOTO mfg_cleanup ; Done buzzing - clean-up and run clock
END
]
thanks alot:sad:
i'll be expecting a rply asap pls