title "4-digit Serial Nixie Clock" ;#define Debug ; ; This Application uses TMR0 to Increment time with the interrupt ; and display time with a latched time interrupt handler ; ; Hardware Notes: ; This application runs on a 16F84A executing at 3.57 MHz ; _MCLR is tied through a 10K Resistor to Vcc and PWRT is Enabled ; Port B is used as a general purpose data output bus. The data are ; sent out in 40-bit chunks, made up of 5 8-bit registers. Separate ; functions build the data block so that multiplexing is done in ; software as opposed to hardware. Only one nixie's cathode is tied ; low at a time in this manner... Also, since I had a screwey layout ; for the tube cathodes for nixies 2 and 4, this allows a more ; natural lookup table operation for the nixies. ; 07/17/05 ; LIST R=DEC, P=16F84A INCLUDE "p16f84a.inc" ; Registers CBLOCK 0x020 ;;registers! _w, _status, _pclath ; Context Register Save Values DigitA ; DigitB ; DigitC ; DigitD ; second ; minute ; hour ; SRA; SRB; SRC; SRD; SRE; keys ; temp_w; second_flag; bres_hi; bres_mid; bres_lo; index; serial_count; display_out; A_const; show_timer; which_tube; ENDC PAGE __CONFIG _CP_OFF & _PWRTE_ON & _WDT_OFF & _XT_OSC ; Mainline of Timer org 0 movlw 2 ; Setup the Count goto Mainline org 4 Int ; Interrupt Handler movwf _w ; Save Context Registers movf STATUS, w ; - Assume TMR0 is the only enabled movwf _status; movf PCLATH, w movwf _pclath clrf PCLATH ;Roman Black's 1-sec interrupter tstf bres_mid; test if mid = 0 skpnz ;nz = no underflow needed decf bres_hi,f; z, no underflow so dec msb decfsz bres_mid,f; dec mid byte = subtract 256 goto IntEnd; tstf bres_hi; test hi byte skpz ; z = high and mid one second! goto IntEnd; ;from here to IntEnd is code for when you reach 1 second movlw 0x06 ;testing speed: ;movlw 0x01 movwf bres_hi movlw 0xD3 movwf bres_mid movlw 0xD3 addwf bres_lo,f skpnc ;no overflow incf bres_mid,f ;add 256 (absorbing error!) movlw 0x01; movwf second_flag; IntEnd decfsz show_timer; goto skip_timer; bsf second_flag,2; movlw 0x02; movwf show_timer; skip_timer movf _pclath, w movwf PCLATH bcf INTCON, T0IF ; Reset the Interrupt Flag bcf STATUS, RP0 movf _status, w ; Restore the Context Registers movwf STATUS swapf _w, f swapf _w, w retfie _bin2bcd ;eeprom binary to decimal hack movwf EEADR; bsf STATUS, RP0 ; Bank 1 bsf EECON1, RD ; EE Read bcf STATUS, RP0 ; Bank 0 movf EEDATA, w; return; _bcd2serAC addwf PCL,f retlw b'11111111'; 1 retlw b'01111111'; 2 retlw b'10111111'; 3 retlw b'11011111'; 4 retlw b'11101111'; 5 retlw b'11110111'; 6 retlw b'11111011'; 7 retlw b'11111101'; 8 retlw b'11111110'; 9 Seconds incf second, f movlw 0x3C subwf second, w btfss STATUS, C ;seconds overflow? goto Display; Clear_seconds movlw 0x00 ; movwf second ; Minutes incf minute, f movlw 0x3C subwf minute, w btfss STATUS, C ;minutes underflow? goto Display; Clear_minutes movlw 0x00 movwf minute; Hours incf hour, f movlw 0x0D subwf hour, w btfsc STATUS, C goto Clear_hours goto Display Clear_hours movlw 0x01; movwf hour; goto Display Display movlw 0x00; movwf second_flag; return; Make_time_regs movfw minute; call _bin2bcd; movwf DigitA; swapf DigitA,w; movwf DigitB; movlw 0x0F; andwf DigitA,f; andwf DigitB,f; movfw hour; call _bin2bcd; movwf DigitC; swapf DigitC,w; movwf DigitD; movlw 0x0F; andwf DigitC,f; andwf DigitD,f; return Delay ;delays by amount in w movf temp_w, w ; subroutine, not goto! Delay_loop decfsz temp_w,f goto Delay_loop return Mainline movlw 0x3A ; Clock starts at movwf second ; 12:00:58 AM, 01/03/05 movlw 0x05 movwf minute movlw 0x03 ; movwf hour movlw 0x06 movwf bres_hi movlw 0xD3 +1 movwf bres_mid movlw 0xD3 movwf bres_lo ;loads 866k plus 1 256 into ;the 24 bit register movlw 0x07; movwf DigitA; movwf DigitB; movwf DigitC; movwf DigitD; movwf index; movlw 0x00; movwf which_tube; movwf second_flag; movlw 0xFF; movwf SRA; movwf SRB; movwf SRC; movwf SRD; movwf SRE; movlw 0x02; movwf show_timer; movlw 0x01; movwf A_const; movlw 0x07; movwf temp_w; movwf serial_count; movlw b'01010101' movwf display_out; bcf STATUS, RP1 bsf STATUS, RP0 ; Goto Bank 1 to set Port Direction movlw 0x00; movwf TRISB ; PORTB is Output movlw 0x1F; movwf TRISA ; PORTA is input movlw 0x0C0 ; 0x0C0 - Minimum Timer Delay movwf OPTION_REG bcf STATUS, RP0 ; Go back to Bank 0 clrf TMR0 ; Start the Timer from Scratch movlw 0x03; movwf PORTA; movlw 0xFF; movwf PORTB; movlw b'10100000' ;movlw (1 << GIE) + (1 << T0IE) movwf INTCON ; Enable Interrupts Loop ; Loop Here btfsc second_flag, 0; second flag set call Seconds; btfsc second_flag, 2; display flag set call Show_time; call Make_time_regs; movf PORTA, w; xorwf keys, w; andlw 0x03 ;only check the button pins btfsc STATUS,Z ;test, if Z=0, no buttons goto Loop ;no, loop again xorwf keys,f movlw 0xFF; ; movlw 0x04; movwf temp_w; call Delay Debounce ;movlw 0xA0 movlw 0xFF; ; movlw 0x04; movwf temp_w; call Delay movf PORTA, w; movwf keys; test_hours btfsc keys, 0 ;hours goto test_minutes; call Hours; goto Loop; test_minutes btfsc keys, 1 ;minutes goto Loop; call Minutes; goto Loop; org 0x0200 Show_time bcf second_flag,2; incf which_tube; movfw which_tube; sublw 0x04; btfss STATUS, Z; goto test_continue; movlw 0x00; movwf which_tube; test_continue btfss which_tube,1; goto test_1_2; call Build_NixieD; btfss which_tube,0; call Build_NixieC; call serial_output; return; test_1_2 call Build_NixieB; btfss which_tube,0; call Build_NixieA; call serial_output; return; Build_NixieA movfw DigitA; subwf A_const,w; btfsc STATUS,C; goto skip_A; movfw A_const; subwf DigitA,w; call _bcd2serAC; movwf SRA; movlw 0xFF; movwf SRB; movwf SRC; movwf SRD; movwf SRE; return; skip_A movfw DigitA; addlw 0x07; call _bcd2serAC; movwf SRB; movlw 0xFF; movwf SRA; movwf SRC; movwf SRD; movwf SRE; return; Build_NixieB movfw DigitB; sublw 0x07; btfsc STATUS,C; goto skip_B; movfw DigitB; sublw 0x07; call _bcd2serAC; movwf SRB; movlw 0xFF; movwf SRA; movwf SRC; movwf SRD; movwf SRE; return; skip_B movfw DigitB; sublw 0x03; btfsc STATUS,C; goto skip_B2; ;leq 3 movfw DigitB; ;greater than 3 addlw 0x01; call _bcd2serAC; movwf SRC; movlw 0xFF; movwf SRA; movwf SRB; movwf SRD; movwf SRE; return; skip_B2 movfw DigitB; addlw 0x03; call _bcd2serAC; movwf SRB; movlw 0xFF; movwf SRA; movwf SRC; movwf SRD; movwf SRE; return; Build_NixieC movfw DigitC; sublw 0x05; btfsc STATUS,C; goto skip_C; movlw 0x05; subwf DigitC,w; call _bcd2serAC; movwf SRC; movlw 0xFF; movwf SRA; movwf SRB; movwf SRD; movwf SRE; return; skip_C movfw DigitC; addlw 0x03; call _bcd2serAC; movwf SRD; movlw 0xFF; movwf SRA; movwf SRB; movwf SRC; movwf SRE; return; Build_NixieD movfw DigitD; addlw 0x06; call _bcd2serAC; movwf SRE; movlw 0xFF; movwf SRA; movwf SRB; movwf SRC; movwf SRD; return; serial_output movlw 0x07; movwf index; bcf PORTB,3; movlw 0xF7; movwf PORTB; register_director movlw 0x08; movwf serial_count; decf index; movfw index; sublw 0x01; btfss STATUS, Z; goto test_SRE; goto end_loop; test_SRE movfw index; sublw 0x02; btfss STATUS, Z goto test_SRD movfw SRE; movwf display_out; goto ones_zeros test_SRD movfw index; sublw 0x03; btfss STATUS, Z goto test_SRC movfw SRD; movwf display_out; goto ones_zeros test_SRC movfw index; sublw 0x04; btfss STATUS, Z goto test_SRB movfw SRC; movwf display_out; goto ones_zeros test_SRB movfw index; sublw 0x05; btfss STATUS, Z goto test_SRA movfw SRB; movwf display_out; goto ones_zeros test_SRA movfw SRA; movwf display_out; ones_zeros btfsc display_out, 0; lowest bit set goto one_out; zero_out bcf PORTB,1; ;clock bcf PORTB,2; (just the data bit);data nop nop bsf PORTB,1; rrf display_out,f; goto serial_loop one_out bcf PORTB,1; bsf PORTB,2; nop nop bsf PORTB,1; rrf display_out,f; serial_loop decfsz serial_count; goto ones_zeros; goto register_director; end_loop bsf PORTB,3; ;latch movlw 0x0F; movwf temp_w; call Delay; bcf PORTB,3; return; org 0x02100 ;EEProm address de 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007, 0x008 de 0x009, 0x010, 0x011, 0x012, 0x013, 0x014, 0x015, 0x016, 0x017 de 0x018, 0x019, 0x020, 0x021, 0x022, 0x023, 0x024, 0x025, 0x026 de 0x027, 0x028, 0x029, 0x030, 0x031, 0x032, 0x033, 0x034, 0x035 de 0x036, 0x037, 0x038, 0x039, 0x040, 0x041, 0x042, 0x043, 0x044 de 0x045, 0x046, 0x047, 0x048, 0x049, 0x050, 0x051, 0x052, 0x053 de 0x054, 0x055, 0x056, 0x057, 0x058, 0x059; end