;************************************************************************** ;Earl's Mods 7/2005 Nixie Tube driven from PORT A and Port B ; CLOCK.ASM ; ; Displays time on a single Nixie display. The timing source ; 4 MHz crystal. ; *** Chime signal on RA3 *** ; A Nixie display is attached as follows: ; ; RB0 0 ; RB1 1 ; RB2 2 ; RB3 3 ; RB4 4 ; RB5 5 ; RB6 6 ; RB7 Switch ; RA0 7 ; RA1 8 ; RA2 9 ; RA3 Chime output ; ; Each output is connected via a resistor to a transistor base. ; The common anode ; is connected to high plus voltage through resistor. ; Holding botton down during power up runs a Nixie Test program ; ; The time is displayed digit by digit over a four second period ; every 10 seconds and the display is blank otherwise. ; ; A normally open switch is connected from RB7 to GND via a 470 ohm ; resistor; no pull-up resistor is needed as an internal weak pull-up ; is enabled by the program. To set the clock press the switch when ; the appropriate digit is displayed; the digit can then be incremented ; by pressing the switch repeatedly. If the switch is open for about ; 2 seconds the clock display is restarted allowing another digit to be ; changed. It is up to the user to put in sensible times as no checking ; is done by the program. ; ;************************************************************************** processor 16f84a include __config _XT_OSC & _WDT_OFF & _PWRTE_ON ERRORLEVEL -302 ; suppress bank selection messages #DEFINE _3_58MHZ ; choose clock speed ;#DEFINE _4_00MHZ PCL EQU 2 ; registers are defined here to make this STATUS EQU 3 ; program self contained. PORTA EQU 5 PORTB EQU 6 INTCON EQU 0BH TRISA EQU 85H TRISB EQU 86H OPTREG EQU 81H C EQU 0 ; bits in STATUS Z EQU 2 RP0 EQU 5 T0IF EQU 2 ; bit in INTCON #IFDEF _3_58MHZ ; number of ticks per second for 3.58 MHz: TCK0 EQU .109 ; nominal TCK1 EQU .111 ; every 10 secs TCK2 EQU .113 ; every min TCK3 EQU .115 ; every 10 mins TCK4 EQU .114 ; every hour TCK5 EQU .110 ; every 10 hours TCK6 EQU .111 ; every 24 hours #ENDIF #IFDEF _4_00MHZ ; as above but for 4 MHz TCK0 EQU .122 TCK1 EQU .123 TCK2 EQU .121 TCK3 EQU .123 TCK4 EQU .124 TCK5 EQU .125 TCK6 EQU .125 #ENDIF CBLOCK 0CH ; define variables required TICKS ; decremented every tick (9.15 ms or 8.19 ms) SEGS ; one bit per segment SEC SEC10 MIN MIN10 HOUR HOUR10 FRAME ; used to decide when to display time HHMM ; one bit per digit displayed COUNT ; scratch register DIGIT ; last digit displayed CHIME ; Number of chimes needed ENDC ;*********************************; ; Initialization ; ;*********************************; ORG 0 INIT CLRF SEC CLRF SEC10 CLRF MIN CLRF MIN10 CLRF HOUR movlw D'1' movwf HOUR10 CLRF FRAME CLRF PORTA CLRF PORTB CLRF CHIME BSF STATUS,RP0 ; select register bank 1 CLRF TRISA MOVLW 80H MOVWF TRISB ; only RB7 is an input MOVLW 4 MOVWF OPTREG ; assign prescaler (1:32) to TMR0 BCF STATUS,RP0 ; reselect bank 0 BTFSS PORTB,7 ; switch open? GOTO TEST ; no, go to test mode ;*********************************; ; Main Program ; ;*********************************; MAIN CALL CLOCK ; real-time clock algo called every second CALL SHOW ; display the time MOVF CHIME,F ; check if chimes needed BZ WAIT ; No Chime now BSF PORTA,3 ; Chime on DECF CHIME,F WAIT BTFSS INTCON,T0IF ; wait for TMR0 to roll over GOTO WAIT CLRF INTCON CALL CHKSW ; check for button press MOVF TICKS,W XORLW D'20' ;Check for 20 ticks BTFSS STATUS,Z GOTO J1 CLRF PORTB ;Turn off Display at 100/120 ticks CLRF PORTA J1 DECFSZ TICKS,F GOTO WAIT GOTO MAIN ; get here every second ;*********************************; ; Convert digit to segment form ; ;*********************************; SEGTAB ANDLW 0FH ADDWF PCL,F DT .1,.2,.4,.8,.16,.32,.64,00,00,00,00 ; 0 to 6 Port B SEGTABA ANDLW 0FH ADDWF PCL,F DT 00,00,00,00,0,0,0,.1,.2,.4,0 ; 7 to 9 Port A ;*********************************; ; Real-time clock algorithm ; ;*********************************; CLOCK MOVLW TCK0 ; increment digits as appropriate MOVWF TICKS ; and define number of ticks per INCF SEC,F ; second for next second MOVF SEC,W SUBLW 9 BTFSC STATUS,C RETURN MOVLW TCK1 ;per 10 sec MOVWF TICKS CLRF SEC ;clear seconds, add 10 seconds INCF SEC10,F MOVF SEC10,W SUBLW 5 ;check for a 6 BTFSC STATUS,C RETURN MOVLW TCK2 ;per min MOVWF TICKS CLRF SEC10 ;clear 10sec, add 1 minute INCF MIN,F MOVF MIN,W SUBLW 9 ;check for 10 BTFSC STATUS,C RETURN MOVLW TCK3 ;per 10 minutes MOVWF TICKS CLRF MIN ;clear minute, add 10 minute INCF MIN10,F MOVF MIN10,W SUBLW 5 BTFSC STATUS,C RETURN MOVLW TCK4 ;each hour MOVWF TICKS CLRF MIN10 ;clear 10 minute add to hour MOVF HOUR10,W ;check for over 10 SUBLW 0 BTFSC STATUS,C GOTO INCHR ; less than 10 INCF HOUR,F ; 10 ->11 or 11--> 12 MOVF HOUR,W SUBLW 2 ;check for 12 BTFSC STATUS,C goto SETCHIME MOVLW TCK6 ;deal with 12 + 1 hour MOVWF TICKS ;each 12 hour movlw D'1' movwf HOUR ; 1 o'clock CLRF HOUR10 goto SETCHIME INCHR INCF HOUR,F ;Add to single digit hour MOVF HOUR,W SUBLW 9 ; did it go from 9 to 10 ? BTFSC STATUS,C goto SETCHIME ; no, it's less than 10 MOVLW TCK5 ;deal with 9 to 10 carry MOVWF TICKS ;each 10 hour CLRF HOUR INCF HOUR10,F GOTO SETCHIME SETCHIME MOVF HOUR,W ;On hour change set chimes MOVWF CHIME MOVF HOUR10,F BZ J2 MOVLW D'10' ADDWF CHIME,F J2 RETURN ;*********************************; ; Displays the time digit by digit; ;*********************************; SHOW CLRF HHMM INCF FRAME,F ; increment place in frame MOVF FRAME,W SUBLW D'06' ; Display cycle time BTFSS STATUS,C CLRF FRAME MOVF FRAME,W XORLW 1 BTFSC STATUS,Z GOTO DHOUR10 ; display 10s of hours when frame is 1 XORLW 1^2 BTFSC STATUS,Z GOTO DHOUR ; display hour when frame is 2 XORLW 2^3 BTFSC STATUS,Z GOTO DMIN10 ; display 10s of mins when frame is 3 XORLW 3^4 BTFSC STATUS,Z GOTO DMIN ; display mins when frame is 4 MOVLW H'00' ; otherwise blank display MOVWF PORTB MOVLW H'00' MOVWF PORTA RETURN DHOUR10 BSF HHMM,3 MOVF HOUR10,W BTFSS STATUS,Z ;check for leading zero GOTO DISPLAY RETURN ;skip display of zero DHOUR BSF HHMM,2 MOVF HOUR,W GOTO DISPLAY DMIN10 BSF HHMM,1 MOVF MIN10,W GOTO DISPLAY DMIN BSF HHMM,0 MOVF MIN,W ; falls through to DISPLAY ;*********************************; ; Displays digit in W ; ;*********************************; DISPLAY MOVWF DIGIT ; save number to be displayed in DIGIT CALL SEGTAB ; convert to segment form MOVWF PORTB ; and display 0-6 MOVF DIGIT,W CALL SEGTABA MOVWF PORTA ; and display 7-9 RETURN ;*********************************; ; Checks for a switch press and ; ; updates digit if displayed ; ;*********************************; CHKSW BTFSC PORTB,7 ; switch closed? RETURN ; no MOVF HHMM,F BTFSC STATUS,Z ; digit displayed? RETURN ; no INCDIG INCF DIGIT,F ; DIGIT is the currently displayed number MOVF DIGIT,W SUBLW 9 BTFSS STATUS,C CLRF DIGIT MOVF DIGIT,W CALL DISPLAY CALL DELAY ; wait for switch to settle CHKSW0 BTFSS PORTB,7 ; switch open? GOTO CHKSW0 ; no CALL DELAY BTFSS PORTB,7 ; still open? GOTO CHKSW0 ; no MOVLW D'20' MOVWF COUNT CHKSW1 BTFSS PORTB,7 ; switch open? GOTO INCDIG ; no CALL DELAY DECFSZ COUNT,F GOTO CHKSW1 MOVF DIGIT,W ; switch was open for around 2 secs CLRF FRAME CLRF SEC10 CLRF SEC BTFSC HHMM,3 ; update correct digit MOVWF HOUR10 BTFSC HHMM,2 MOVWF HOUR BTFSC HHMM,1 MOVWF MIN10 BTFSC HHMM,0 MOVWF MIN GOTO MAIN ; restart the program ;*********************************; ; Delay used by switch routine ; ;*********************************; DELAY MOVLW D'12' ; roughly 100ms delay MOVWF TICKS DEL1 BTFSS INTCON,T0IF ; wait for TMR0 to roll over GOTO DEL1 CLRF INTCON DECFSZ TICKS,F GOTO DEL1 RETURN TEST CLRF COUNT ;exercise Nixie by cycling through MOVF COUNT,W ;all numbers CALL DISPLAY CALL DELAY CALL DELAY ;1 second delay INCF COUNT,F MOVF COUNT,W XORLW D'10' ;Test for 10 BTFSS STATUS,Z GOTO TEST+1 GOTO TEST ;Reset COUNT to 0 END