;********************************************************************** ; * ; Filename: timer.asm * ; Date: * ; File Version: * ; * ; Author: el@jap.hu * ; Company: http://jap.hu/ * ;********************************************************************** ;NOTES ; ;********************************************************************** ;HISTORY ; ; 000-20010602 ; 001-20010603 working clock and timer, no display/keyboard/setting ; 002-20010603 keyboard handler OK ; 003-20010604 fully functional except output ctl ; 004-20010604 implementation done, write EEPROM routines ; 005-20010604 uses internal EEPROM to store on/off time ; 006-20010605 timing adjustment ; 007-20010706 bugfix: clear days at timer ON ; ;********************************************************************** list p=16f84 __CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _HS_OSC #include dcnt EQU 0x0c ; digit counter keys equ 0x0d ; keyboard state temp equ 0x0e ; BCD temp temp2 w_save equ 0x10 ; itr save s_save equ 0x11 ; itr save f_save equ 0x12 ; itr save porta_shadow equ 0x13 ; porta mask for itr flags equ 0x14 digits EQU 0x15 ; 7-segment display digits ; CLOCK msec equ 0x20 ; tens of milliseconds sec equ 0x21 ; seconds min equ 0x22 ; minutes hour equ 0x23 ; hours day equ 0x24 ; days (max 32) ; START smin equ 0x25 shour equ 0x26 sday equ 0x27 ; INTERVAL imin equ 0x28 ihour equ 0x29 ; don't change order of bytes between min-ihour! ; STOP omin equ 0x2a ohour equ 0x2b r1 equ 0x2c ; register 1 r2 equ 0x2e ; register 2 mode equ 0x30 prevkeys equ 0x31 keyidle equ 0x32 keypress equ 0x33 dlycnt1 equ 0x34 dlycnt2 equ 0x35 ; CONSTANTS ; FLAGS ch_min equ 0 ; minutes changed in_iv equ 1 ; check (ohour, omin) stop condition al_ena equ 2 ; check (sday, shour, sday) start condition ch_sec equ 3 ; seconds changed ch_eep equ 4 ; permament data changed ; KEYS KMODE equ 7 KENA equ 6 KSTART equ 5 KSTOP equ 4 KDAY equ 6 KHOUR equ 5 KMIN equ 4 krdelay equ .20 krrate equ .20-3 ; CLOCK msinc_iv equ .10000 msdiv equ .100 ; ms divider ; clkinc_iv = prescaler * 256 usec @ 4MHz clkinc_iv equ .4 * .256 msinc_step equ .65536-msinc_iv ; DISPLAY LMINUS equ B'10000000' LC equ B'01110010' LE equ B'11110010' LF equ B'11100010' LL equ B'01110000' LO equ B'01111110' LN equ B'10101000' ; PORTS PARELAY equ 2 ; EEPROM DATA ORG 0x2100 de .22, .7, 0, 4, 0 vectors ORG 0 goto main nop nop nop movwf w_save swapf STATUS, W movwf s_save movf FSR, W movwf f_save bcf INTCON, T0IF call interrupt movf f_save, W movwf FSR swapf s_save, W movwf STATUS swapf w_save swapf w_save, W retfie segtable bcf PCLATH, 0 ; on page 0 addwf PCL, F dt B'01111110', B'00001100' ; 01 dt B'10110110', B'10011110' ; 23 dt B'11001100', B'11011010' ; 45 dt B'11111010', B'00001110' ; 67 dt B'11111110', B'11011110' ; 89 dt B'11101110', B'11111000' ; Ab dt B'01110010', B'10111100' ; Cd dt B'11110010', B'11100010' ; EF print_dec movwf temp clrf temp+1 pr_dec11 movlw d'10' subwf temp, W bnc pr_dec1 movwf temp incf temp+1, F goto pr_dec11 pr_dec1 movf temp+1, W call print_chr movf temp, W print_chr call segtable movwf INDF incf FSR, F return led_mpx incf dcnt, F clrf PORTB movlw 0x09 subwf dcnt, W bnz next_row ; readout keys movf PORTB, W movwf keys ; reset clrf dcnt movlw 3 iorwf porta_shadow, W movwf PORTA movlw 1 iorwf porta_shadow, W movwf PORTA movlw 0 tris PORTB goto display next_row movlw 8 subwf dcnt, W bnz notkeys movlw 0xff ; row 8:keyboard tris PORTB notkeys ; clock movf porta_shadow, W movwf PORTA movlw 1 iorwf porta_shadow, W movwf PORTA display movlw digits addwf dcnt, W movwf FSR movf INDF, W xorlw 0xff movwf PORTB movf porta_shadow, W btfsc INDF, 0 movwf PORTA return time_adj ; r1+= clkinc_iv movlw low clkinc_iv addwf r1, F btfsc STATUS, C incf r1+1, F movlw high clkinc_iv addwf r1+1, F ; r2 = r1 + msinc_step movf r1+1, W movwf r2+1 movlw low msinc_step addwf r1, W movwf r2 btfsc STATUS, C incf r2+1, F movlw high msinc_step addwf r2+1, F ; if (!overflow) return btfss STATUS, C return ; r1 = r2 movf r2, W movwf r1 movf r2+1, W movwf r1+1 incf msec,F ; msec++; movf msec,W ; ACCU = msec; sublw msdiv ; if ((ACCU-XD) != 0) btfss STATUS,Z ; return; return ; else { clrf msec ; msec = 0; incf sec,F ; sec++; bsf flags, ch_sec ; ch_sec = 1; movf sec,W ; ACCU = sec; sublw 0x3c ; if ((ACCU-60) != 0) btfss STATUS,Z ; return; return ; else { clrf sec ; sec = 0; incf min,F ; min++; bsf flags, ch_min ; ch_min = 1; movf min,W ; ACCU = min; sublw 0x3c ; if ((ACCU-60) != 0) btfss STATUS,Z ; return; return ; else { clrf min ; min = 0; incf hour,F ; hour++; movf hour,W ; ACCU = hour; sublw 0x18 ; if ((ACCU-24) != 0) btfss STATUS,Z ; return; return ; else { clrf hour ; hour = 0; incf day, F movf day, W sublw 0x20 btfsc STATUS, Z clrf day return time_cmp ; compare time btfss flags, ch_min return ; no change in minutes bcf flags, ch_min btfss flags, in_iv goto skip_t1 ; interval end check movf ohour, W subwf hour, W btfss STATUS, Z goto skip_t1 movf omin, W subwf min, W btfsc STATUS, Z bcf flags, in_iv skip_t1 ; interval start check btfss flags, al_ena return ; interval start check movf sday, W btfss STATUS, Z subwf day, W btfss STATUS, Z return movf shour, W subwf hour, W btfss STATUS, Z return movf smin, W subwf min, W btfss STATUS, Z return time_start ; start condition bsf flags, in_iv clrf day ; recalc stop condition from (imin, ihour) movf ihour, W addwf hour, W movwf ohour movf imin, W addwf min, W movwf omin movlw .60 subwf omin, W btfss STATUS, C goto skip_t2 movwf omin incf ohour, F skip_t2 movlw .24 subwf ohour, W btfsc STATUS, C movwf ohour return main MOVLW 0 MOVWF PORTA movwf porta_shadow movlw 0 MOVWF PORTB movlw 0 TRIS PORTA MOVLW 0 TRIS PORTB ; init display clrf dcnt ; init clock clrf r1 clrf r1+1 clrf msec ; msec = 0; clrf sec ; sec = 0; clrf min ; min = 0; clrf hour ; hour = 0; clrf day clrf omin clrf ohour clrf flags call eep_read ; init mode clrf mode ; init keys clrf keyidle clrf keypress movlw 0xff movwf prevkeys movwf keys ; init interrupts clrwdt ; changing default presc. assignment movlw 0x01 ; prescaler 1:4 assigned to TMR0 OPTION ; T0CS selects internal CLK movlw (1<