;************************************************************************** ; Jon's Mods 12/2006 for B7971 alphanumeric nixie tube ; Earl's Mods 7/2005 for standard nixie tube driven by Port A and Port B ; Original program was David Tait's CLOCK.ASM ; ; Displays time on a single B7971 Nixie display. ; Timing Source: 4 MHz crystal ; A B7971 Nixie display is attached as follows: ; ; PIN SEGMENT B7971 PIN # ; RB0 1 8 ; RB1 2 5 ; RB2 3 6 ; RB3 4 9 ; RB4 5 14 ; RB5 6 15 ; RB6 7 12 (SEE NOTE 1)\ ; RB7 8 7 } Both active = pin 1, 10 on ; RA0 11 16 (SEE NOTE 1)/ ; RA1 9 3 (SEE NOTE 2)\ ; RA2 14 4 (SEE NOTE 2)/ Both active = pin 17 on ; ; RA3 Chime Output ; RA4 Switch Input ; ; * Note 1: ; RB6 and RA0 feed into logic gate system, RB6 feeds segment 7 via NOR ; and RA0 feeds segment 11 via NOR. When both RB6 and RA0 are active, segment 10/13 on. ; ; * Note 2: ; RA1 and RA2 feed into logic gate system, RA1 feeds segment 9 via NOR ; and RA2 feeds segment 14 via NOR. When both RA1 and RA2 are active, segment 12 on. ; ; Each output is connected via a resistor to a transistor base. ; The common anode is connected to high voltage (200-300V) through a resistor. ; Holding button 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 RA4 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 16f84 include __config _XT_OSC & _WDT_OFF & _PWRTE_ON ERRORLEVEL -302 ; suppress bank selection messages 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 ; Below are ticks for 4 MHz crystal TCK0 EQU .122 TCK1 EQU .123 TCK2 EQU .121 TCK3 EQU .123 TCK4 EQU .124 TCK5 EQU .125 TCK6 EQU .125 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 TRISB ; all of port B are outputs MOVLW 10H MOVWF TRISA ; only RA4 is an input MOVLW 4 MOVWF OPTREG ; assign prescaler (1:32) to TMR0 BCF STATUS,RP0 ; reselect bank 0 BTFSS PORTA,4 ; switch on RA4 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 RA3 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 0xFC,0x02,0xD1,0xB1,0x67,0x96,0x9E,0x80,0xFF,0xF1,0x00 ; Port B lookup table SEGTABA ANDLW 0FH ADDWF PCL,F DT 00h,01h,01h,04h,00h,02h,02h,05h,00h,06h,00h ; Port A lookup table ;*********************************; ; 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 ; call bit allocation table MOVWF PORTB ; and display bits for port B MOVF DIGIT,W CALL SEGTABA ; call bit allocation table MOVWF PORTA ; and display bits for port A RETURN ;*********************************; ; Checks for a switch press and ; ; updates digit if displayed ; ;*********************************; CHKSW BTFSC PORTA,4 ; switch closed on RA4? 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 PORTA,4 ; switch open? GOTO CHKSW0 ; no CALL DELAY BTFSS PORTA,4 ; still open? GOTO CHKSW0 ; no MOVLW D'20' MOVWF COUNT CHKSW1 BTFSS PORTA,4 ; 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