DEBOUNCE EQU 16 MIN_SEC EQU 17 ; MIN/seconds timer ; ; PORT pin definitions ; ; Port A: s ; bit0 led to flash ; bit 1-3 unsed i/o ; ; define the RAM locations of DATA PAGE 1 (timers) ; NB to use these RAM locations (variables) the correct bits of the ; FSR must be set (5&6). ; setup 5 timers. Each will store BCD time values and be decremented to- ; wards zero. NB if these timers are moved the code that works on that ; must be updated. ; ; Timers placed in Data Page 1 stmr1 equ 30 mtmr1 equ 31 stmr2 equ 32 mtmr2 equ 33 stmr3 equ 34 mtmr3 equ 35 stmr4 equ 36 mtmr4 equ 37 stmr1Val equ 38 mtmr1Val equ 39 stmr2Val equ 3A mtmr2Val equ 3B stmr3Val equ 3C mtmr3Val equ 3D stmr4Val equ 3E mtmr4Val equ 3F ; ; ; ; **************************************************************************** org 0 START goto initialise ; this routine runs a test on the leds ; all the relevent leds are lit up for 2 secs. ; test_hardware movlw D'1' ; flash every two for 2 secs movwf min_sec ; ; norm_time bcf genFlag, 0 ; put in real time bcf genFlag, 1 ; time_loop ; call update_display ; bsf status, PA1 ; goto page 2 ; call service_keys bsf status, PA0 ; goto page 1 call update_timers ; wait and update timers (Realtime) bcf status, PA0 iorlw 0 ; btfss status, Z ; goto GPtime ; ; movf genFlag, w ; see if in atm ; andlw B'00000011' ; xorlw B'00000001' ; btfsc status, z ; skip if not retrn goto time_loop GPtime ; code sequence to call general purpose timers ; Pre: only called after a second interval has past bsf status, PA0 ; goto page 1 call servTmr ; service the gen purpose timers call TmrAct bcf status, PA0 ; reset page flags call ChangeState goto retrn on ; Level 2 routine. ; set led on, by setting it low, set in flag and at port. ; Pre: ; Post: bsf genflag, LEDON bcf port_a, led retlw 0 ; ChangeState ; Level 2 routine ; routine to change the state of the led. this is only entered if the ; min_sec timer has reached zero. ; ; Pre: ; POst: ; ; reset value for blinks the led ever 2 secs movlw D'01' ; 2 secs movwf min_sec ; check the led status on/off? movf genflag, w andlw B'00100000' btfsc status, z ; if ledon is on goto on ; turn it on bsf port_a, led ; turn it off bcf genflag, ledon retlw 0 ;************************************************************************; ; This routine set up ports A, B, C and the internal ; real time clock counter. ; Level 1 routine ; Pre: ; Post: Timers have been setup. ; Ports have been setup ; The prescaler is set ; initialise clrf FSR movlw B'00001111' ; make active high movwf port_a movlw B'00000000' ; set port A as outputs tris port_a ; movlw B'11111111' ; set levels high movwf port_b movlw B'00000000' ; set portB as output tris port_b ; movlw B'00000000' ; set levels low movwf port_c movlw B'00000000' ; set port C as output tris port_c ; ; OPTION REG setup ; bits 7,6,5,4,3,2,1,0 ; 6,7 not avail ; 5 rt source o = int, 1, edge on rtcc pin ; 4 rtcc edge l->H '0', H-->L '1' ; 3 prescaler assignment 0 rtcc, 1 wdt ; 1,2,3 ratio of prescaler '100' = 1:32 ; 000 -> scale 1:2 ; 111 -> scale 1:256 ; NB if scale used for wdt, then ratio is 1/2 of the rtcc scale ; movlw B'00000100' ; set up prescaler (1:32) movlw B'00000000' ; for testing option ; movlw MTICKS ; rtcc = 5msecs ; init the rtcc with a value MTICKS, so that when it times out it is ; almost exactly 5msecs. movwf rtcc clrf mstmr clrf stmr clrf mtmr movlw 12H ; make hours = 12 movwf htmr clrf genFlag bsf status, PA0 call initTmr movlw stmr1 ; set W = timer1 ; call setTimer ; testing movlw 5 bsf fsr, DataP1 movwf stmr1 bcf fsr, DataP1 bsf timeFlag, timer1 ; activate timer bcf status, PA0 goto test_hardware ; ; ; ************************************************************************* ; ; TIMER MODULE ; ; ************************************************************************* ; All routines related to timer update are located at address ; 200 and above. ; org 200 ; ; This routine is called on every loop. update_timers ; ; Pre: ; Post: returns 1 in W if a 1 second interval has past clrwdt timerLoop ; the timer loop is currently set to time out every 5ms. NB it must be ; less than 18 ms or the watchdog may time out. nop ; allow time for rtcc = 0 to be available movf rtcc, w ; is rtcc =0 btfss status, z ; if 0 then skip goto timerLoop ; else loop ; setup real time counter again to count out the next 5ms movlw MTICKS ; rtcc = 5ms or 4ms movwf rtcc incf mstmr ; inc 5 ms ; btfsc genFlag, key_hit ; no key hit, then skip ; goto chk_de_bounce ; else debounce ; ; check to see if a second has rolled around. IE 200 x 5ms = 1 sec ; or 250 x 4ms = 1sec movf mstmr, 0 ; get mstmr in W xorlw NumRollOver ; if enough to equal 1 sec then skip btfss status, z retlw 0 ; return as not a second interval ; ; inc seconds count clrf MSTMR ; CLEAR ms-TMR movf min_sec, w ; get min_sec timer andlw B'00001111' ; mask minutes btfss status, z ; zero then skip decf min_sec movlw stmr ; load fsr with s_tmr movwf fsr call inc_60 ; inc secs iorlw 0 ; btfss status, z ; retlw 1 ; only a sec passed ; ; inc minutes count swapf min_sec movf min_sec, w ; get min_sec in w andlw B'00001111' ; mask seconds btfss status, z ; skip is not set decf min_sec ; else dec swapf min_sec ; swap back ; call chk_silnc_tim ; silence on? movlw mtmr ; inc mins movwf fsr ; call inc_60 iorlw 0 ; do an operation btfss status, z ; if 0 then skip retlw 1 ; ; ;inc hour count ; Level ? ; Increment the hour count. movlw htmr ; get htmr in fsr movwf fsr call inc_hr ; inc_60 ; inc the register pointed to by the FSR modulo 60. NB BCD is used. ; Pre: The Fsr is a timer register that is desired to be incremented by 1 ; modulo 60. ; Post: inc has occurred. If the result is 1 a inc was normal. If the ; result is 0, then the tmr overflowed (=60) incf f0 ; inc and get in w movf f0, 0 andlw B'00001111' ; mask high bits xorlw B'00001010' ; = 10 them make it 0 btfss status, z ; normal condition, return 1 (okay), unit digit incremented retlw 1 ; else ret non zero movlw B'11110000' ; zero lsb andwf f0 swapf f0 ; swap indirect incf f0 movf f0,0 ; get in w swapf f0 ; swap f0 back xorlw D'6' btfss status,z ; normal condition, return 1, tens digit incremented retlw 1 ; mod 60 overflow, return 0. clrf f0 retlw 0 ; inc_hr ; FSR is pointing to the timer. ; i don't think that the hour timer is BCD. ; pre: ; post: incf f0 ; inc hour timer movf f0, w ; chk_13 movf f0, w ; get in w xorlw 12h ; see if 13 btfss status, z ; yes then skip nop retlw 1 ; flags that a second interval has past ; set_1_hr movlw B'00000001' ; SET TO 1 MOVWF f0 ; The general purpose timers are not affected if their value is zero. ; InitTmr ; Initialise timers ; Timers can run for 255 minutes or over 4 hours. ; Procedure to initialise the general purpose timers system. This will be ; by constants in the first place, but later from the NV RAM. ; Pre: Data page is 0 ; Post: Data page is 0 ; Initialise the backup of the timer values. (this will eventually ; come from the NVRAM) ; ; Set all timers to zero in the first instance. ; ; set data page to 1 bsf FSR, dataP1 clrf timeFlag ; move in address of first timer and then increment the addr, clearing ; each timer as we step through the timers. Currently this is the ; first 8 bytes of data page 1 movlw stmr1 ClrLoop movwf fsr bsf FSR, dataP1 ; maintain data page clrf f0 ; clears seconds part of timer incf fsr, same ; inc so to clear minutes part clrf f0 ; clears mins part ; test to see all timers are clear movf fsr, W xorlw mtmr4 andlw b'00001111' ; ensure high nibble is clear btfss STATUS, Z ; = --> skip goto ClrLoop ; install some setup values movlw 10 movwf stmr1Val movlw 1 movwf stmr2Val movwf stmr3Val movwf stmr4Val movwf mtmr2Val movlw 2 movwf mtmr3Val movlw 10 movwf mtmr4Val ; reset data page to 0 bcf FSR, DataP1 retlw 0 SetTimer ; This procedure sets the timer to it's backup value ; ; Pre: W is the timer (the address of the seconds part of the tmr) ; Data Page is 0 ; Post: The timer is set to the corresponding timer setup values ; Data page is 0 ; the offset to the setup values is currently 8 bytes higher than the ; timer variable locations ; set to the timer data page bsf FSR, dataP1 ; firstly transfer the seconds values ; calculate timer using the offset in W movwf temp ; Save timer address movlw OFFSET addwf temp, w ; calculate reg of the initial value movwf FSR ; save this address in FSR bsf FSR, dataP1 ; maintain data page ; get timer (secs) value movf f0, W ; get setup value movwf tmp2 ; save value, then get back timer address movf temp, W ; get timer address again movwf fsr bsf FSR, dataP1 ; maintain data page movf tmp2, W movwf f0 ; Now transfer the minutes value movlw OFFSET+1 addwf temp, w ; calculate reg of the initial value movwf FSR ; save this address in FSR bsf FSR, dataP1 ; maintain data page ; get timer (mins) value movf f0, W movwf tmp2 ; save value, then get back timer address incf temp, same movf temp, W movwf fsr bsf FSR, dataP1 movf tmp2, W movwf f0 bcf FSR, dataP1 ; reset data page pointer retlw 0 ; ??? ServTmr ; Services the timers, decrementing the active timers ; Pre: Must called from main loop, as there are calls in this routine ; Data Page is 0 ; Post: Data Page is 0 ; testing ; bcf port_a, 2 ; set to data page 1 bsf FSR, dataP1 ; get timer address in working register movlw stmr1 ; check to see timer active btfsc timeFlag, timer1 ; if it is decrement it call timerDec ; if the value returned in w is 1, then the timer is finished ; so set it's flag xorlw d'1' btfsc status, z ; bsf timeFlag, tmr1end ; movlw stmr2 btfsc timeFlag, timer2 call timerDec ; if the value returned in w is 1, then the timer is finished ; so set it's flag xorlw d'1' btfsc status, z ; bsf timeFlag, tmr2end ; movlw stmr3 btfsc timeFlag, timer3 call timerDec ; if the value returned in w is 1, then the timer is finished ; so set it's flag xorlw d'1' btfsc status, z ; bsf timeFlag, tmr3end ; movlw stmr4 btfsc timeFlag, timer4 call timerDec ; if the value returned in w is 1, then the timer is finished ; so set it's flag xorlw d'1' btfsc status, z ; bsf timeFlag, tmr4end ; bcf FSR, dataP1 retlw 0 timerDec ; Pre: W = stmr1 | stmr2 | stmr3 | stmr4 (addresses) ; the seconds are never 0, either counting down, or ; reset to 60 ; post: ; ; testing ; bcf port_a, 2 movwf fsr bsf FSR, dataP1 ; ensure that data page remains ok decf f0, same ; dec seconds, then ; ************************************************************************ ; ************************************************************************ ; This is where I have found the timer not to progress. It will light the ; LED on port A if the Xorlw is for 3 or 4 as it counts down, but it never ; gets to the stage where comparsion (via XOR) with 1 or 2, lights the LED. ; I take this to mean that, it never gets to the value of 1 or 2. ; movf f0, w ; xorlw 4 ; btfsc status, z ; bcf Port_A, 1 ; xorlw 3 ; btfsc status, z ; bcf Port_A, 0 ; xorlw 2 ; btfsc status, z ; bcf Port_A, 2 btfss status, z ; if zero dec minutes retlw 0 ZeroSecs ; The seconds have zeroed, so if no mins left end, else dec mins ; and set seconds to 60 ; Pre: FSR is the ADDR of the seconds part of the timer ; Data page is 1 ; Post: Data page is 1 ; retlw 1 if the timer is finished ; testing bcf Port_a, 0 incf FSR, same ; so to move to mins part movf f0, w andlw B'11111111' ; test for zero btfss status, z ; skip if 0 goto decNow ; else dec the minutes now ; testing bcf Port_A, 2 bcf FSR, dataP1 retlw 1 ; return from timerDec, noting ; that the tmr is finished decNow ; Pre: accessed by a goto from ZeroSecs ; Post: decf f0, same ; dec minutes decf FSR, same ; access seconds address movlw 60 movwf f0 ; set seconds ;testing bcf Port_a, 1 bcf FSR, dataP1 ; retlw 0 ; return from timerDec TmrAct ; Take initial action if a timer is finished. ; Pre: The finshed flag for the timer is set ; Post: The finshed flag is cleared ; testing ; bcf port_a, 2 init1 btfsc timeFlag, tmr1end goto TmrAct1 init2 btfsc timeFlag, tmr2end goto TmrAct2 init3 btfsc timeFlag, tmr3end goto TmrAct3 init4 btfsc timeFlag, tmr4end goto TmrAct4 retlw 0 ; return from TmrAct routine ; TmrAct1 bcf timeFlag, tmr1end ; clear the ended flag bcf timeFlag, timer1 ; stop timer decrementing ; testing ; bcf Port_A, 2 movlw stmr2 call setTimer bsf timeFlag, timer2 ; activate timer2 bcf port_A, 0 goto init2 TmrAct2 bcf timeFlag, tmr2end ; clear the ended flag bcf timeFlag, timer2 ; stop timer decrementing movlw stmr3 call setTimer bsf timeFlag, timer3 ; activate timer3 bsf Port_A, 0 ; turn off previous led bcf Port_A, 1 ; turn on led goto init3 TmrAct3 bcf timeFlag, tmr3end ; clear the ended flag bcf timeFlag, timer3 ; stop timer decrementing movlw stmr4 call setTimer bsf timeFlag, timer4 ; activate timer4 bsf Port_A, 1 ; turn off previous led bcf Port_A, 2 ; turn on led goto init4 TmrAct4 bcf timeFlag, tmr4end ; clear the ended flag bcf timeFlag, timer4 ; stop timer decrementing bsf Port_A, 2 ; turn off previous led bcf Port_A, 3 bsf status, PA0 bsf status, PA1 goto sys_reset retlw 0 ; return from TmrAct routine ; ; ; ************************************************************************** org PIC57 sys_reset goto start ; end