Last active
December 21, 2025 00:26
-
-
Save jaymcgavren/777f1fc796be941bee818cbd6327b8cd to your computer and use it in GitHub Desktop.
Linwood Whaley's assembly code for his Nixie tube clock in the HeatSync Labs front window (shared with permission)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ; 4-nixie-2-K155ID1-up-down-asm-source | |
| ; this program will use a PIC16F887 microcontroller, two K155ID1 | |
| ; driver chips and MPSA42/MPSA92 transistors to control four | |
| ; nixie tubes. MAXIM DS1302 RTC chip | |
| ; 20MHz resonator for 200nS instruction cycle | |
| ; | |
| ; pin 1 RE3: reset pin | |
| ; pins 2-5 RA0/3: outputs to anode control transistors | |
| ; pin 8 RE0: input/output (I/O of DS1302) | |
| ; pins 11 and 32 power | |
| ; pins 12 and 31 ground | |
| ; pins 13-14 RA6/7: 20MHz resonator | |
| ; pin 17 RC2: output (CE of DS1302) | |
| ; pin 16 RC1: output (SCLK of DS1302) | |
| ; pins 19/22 RD0/3: outputs--low nybble to K155ID1 | |
| ; pins 27/30 RD4/7: outputs--high nybble to K155ID1 | |
| ; pins 38/40 RB5/7: inputs--switches | |
| ; | |
| ; | |
| ; | |
| ; Option register: Timer 0 internal clock - low to high transition; | |
| ; Prescaler assigned to timer 0; Prescaler set to 1 : 16 | |
| ; Pull-ups disabled --1000 0011-- | |
| ; | |
| ; | |
| ; start date: August 19, 2019 | |
| ; last worked on: May 27, 2021 | |
| ; added comments: May 9, 2023 | |
| list R=DEC | |
| list p=16f887 | |
| #include p16f887.inc | |
| ; CONFIG1 | |
| ; __config 0xE0F2 | |
| __CONFIG _CONFIG1, _FOSC_HS & _WDTE_OFF & _PWRTE_OFF & _MCLRE_ON & _CP_OFF & _CPD_OFF & _BOREN_OFF & _IESO_OFF & _FCMEN_OFF & _LVP_OFF | |
| ; CONFIG2 | |
| ; __config 0xFFFF | |
| __CONFIG _CONFIG2, _BOR4V_BOR40V & _WRT_OFF | |
| ;**************************************************************************** | |
| ; VARIABLES | |
| ;**************************************************************************** | |
| cblock 0x20 | |
| clk.reg:7, clk.val:7 | |
| reg.address ; 0x2E | |
| time.valu ; 0x2F | |
| fsr.offset ; 0x31 | |
| i ; 0x32 | |
| wp.bit ; 0x33 | |
| cnt | |
| count | |
| new.num | |
| old.num | |
| k | |
| read.min.address | |
| temp.min.address | |
| read.hrs.address | |
| temp.hrs.address | |
| minutes.byte | |
| hours.byte | |
| temp.time | |
| minutes | |
| temp.minutes | |
| temp.bcd.minutes | |
| hours | |
| temp.hours | |
| temp.bcd.hours | |
| endc | |
| #define RTC.enable PORTC, 2 ; connected to CE pin of DS1302 | |
| #define clockBit PORTC, 1 ; connected to SCLK pin of DS1302 | |
| #define comm.data PORTE, 0 ; connected to I/O pin of DS1302 | |
| #define low.minutes.anode PORTA, 0 ; anode control low minutes | |
| #define high.minutes.anode PORTA, 1 ; anode control high minutes | |
| #define low.hours.anode PORTA, 2 ; anode control low hours | |
| #define high.hours.anode PORTA, 3 ; anode control high hours | |
| #define time.up.button PORTB, 7 ; time up | |
| #define time.down.button PORTB, 6 ; time down | |
| #define next.button PORTB, 5 ; start time change - next - | |
| org 0 | |
| goto START | |
| ;**************************************************************************** | |
| ;**************************************************************************** | |
| ; SUBROUTINES | |
| ;**************************************************************************** | |
| ;**************************************************************************** | |
| ;**************************************************************************** | |
| ; RTC module | |
| ; Read the minutes | |
| ;**************************************************************************** | |
| ReadMinutesSetup ; sets up RTC module to enable us | |
| banksel TRISE ; to read the minutes | |
| movlw 0x00 | |
| movwf TRISE ; make PORTE,0 into an output | |
| banksel PORTE | |
| movlw 8 | |
| movwf count ; set counter to 8 -full byte- | |
| clrf PORTE | |
| movf read.min.address, w ; move the read minutes address into the | |
| movwf temp.min.address ; temporary address variable | |
| bsf RTC.enable ; enable RTC module - drive CE pin high | |
| nop | |
| command_output_mins | |
| bcf clockBit ; set the clock low | |
| nop ; nops for timing | |
| nop | |
| nop ; move first bit(LSB) into RTC module | |
| movwf PORTE ; by moving min.address into PORTE | |
| bsf clockBit ; and bringing the clock high | |
| nop | |
| rrf temp.min.address, w ; bring in next bit of minutes address | |
| movwf temp.min.address ; move into temp. address variable and w | |
| decfsz count, f ; do until all eight bits been written | |
| goto command_output_mins | |
| ReadTheMinutes | |
| banksel TRISE | |
| movlw 0x01 | |
| movwf TRISE ; make PORTE,0 into an input | |
| banksel PORTE | |
| movlw 8 | |
| movwf count ; reset the counter to 8 | |
| clrf PORTE | |
| clrf minutes.byte ; minutes.byte = 0000 0000 | |
| bcf STATUS, C ; clear carry flag | |
| read_mins | |
| bcf clockBit ; clock low will read bit(as per RTC data) | |
| nop ; into PORTE, 0(comm.data) | |
| nop ; nops for timing | |
| bsf clockBit ; clock high -- end read | |
| btfsc comm.data ; test the bit read from the RTC | |
| bsf STATUS, C ; if a 1 set carry flag to a 1 | |
| nop ; if zero skip - carry has a zero | |
| rrf minutes.byte, f ; rotate to bring carry into bit 7 | |
| decfsz count, f ; have all eight bits been read | |
| goto read_mins ; no, read another bit | |
| bcf RTC.enable ; disable RTC module | |
| bcf clockBit ; clock low | |
| return | |
| ;**************************************************************************** | |
| ; RTC module | |
| ; Read the hours | |
| ;**************************************************************************** | |
| ReadHoursSetup ; set up RTC to read the hours | |
| banksel TRISE ; move to bank 1 | |
| movlw 0x00 | |
| movwf TRISE ; make PORTE,0 into an output | |
| banksel PORTE ; move to bank 0 | |
| movlw 8 | |
| movwf count ; reset the counter to 8 | |
| clrf PORTE | |
| movf read.hrs.address, w ; move the read hours address into the | |
| movwf temp.hrs.address ; temporary address variable | |
| bsf RTC.enable ; enable RTC module - drive CE pin high | |
| nop | |
| command_output_hrs | |
| bcf clockBit | |
| nop ; nops for timing | |
| nop | |
| nop ; move first bit(LSB) into RTC module | |
| movwf PORTE ; by moving hrs.address into PORTE | |
| bsf clockBit ; and bringing the clock high | |
| nop | |
| rrf temp.hrs.address, w ; bring in next bit of hours address | |
| movwf temp.hrs.address ; move into temp. hours variable and w | |
| decfsz count, f ; do until all eight bits been written | |
| goto command_output_hrs | |
| ReadtheHours | |
| banksel TRISE | |
| movlw 0x01 | |
| movwf TRISE ; make PORTE,0 into an input | |
| banksel PORTE | |
| clrf PORTE | |
| movlw 8 | |
| movwf count | |
| clrf hours.byte ; hours.byte = 0000 0000 | |
| bcf STATUS, C ; clear carry flag | |
| read_hrs | |
| bcf clockBit ; clock low will read bit(as per RTC data) | |
| nop ; into PORTE, 0(comm.data) | |
| nop ; nops for timing | |
| bsf clockBit ; clock high -- end read | |
| btfsc comm.data ; test the bit read from the RTC | |
| bsf STATUS, C ; if a 1 set carry flag to a 1 | |
| nop ; if zero skip - carry has a zero | |
| rrf hours.byte, f ; rotate to bring carry into bit 7 | |
| decfsz count, f ; have all eight bits been read | |
| goto read_hrs ; no, read another bit | |
| bcf RTC.enable | |
| bcf clockBit | |
| return | |
| ;**************************************************************************** | |
| ; Changing the time (while displaying the change) | |
| ; for RTC reset | |
| ;**************************************************************************** | |
| ChangeTimeSubroutine | |
| clrf PORTA ; turn off all anodes | |
| movf hours.byte, w ; move current RTC hours | |
| movwf temp.bcd.hours ; into temporary variable | |
| movf minutes.byte, w ; move current RTC minutes | |
| movwf temp.bcd.minutes ; into temporary variable | |
| call TestHighHours | |
| call TestHighMinutes | |
| call hoursON | |
| ChangeHours | |
| btfss time.up.button ; test for button press | |
| call IncHours | |
| btfss time.down.button ; test for button press | |
| call DecHours | |
| btfsc next.button ; test for button press | |
| goto ChangeHours | |
| call bounceNext | |
| call minutesON | |
| ChangeMinutes | |
| btfss time.up.button ; test for button press | |
| call IncMinutes | |
| btfss time.down.button ; test for button press | |
| call DecMinutes | |
| btfsc next.button ; test for button press | |
| goto ChangeMinutes | |
| call bounceNext | |
| return | |
| ;**************************************************************************** | |
| TestHighHours ; change hours in BCD | |
| btfsc temp.bcd.hours, 4 ; into temp.hours in binary(decimal) | |
| goto AddTen ; if high nybble is a 0; then low nybble | |
| movf temp.bcd.hours, w ; is maxxed at 9 so no problem | |
| movwf temp.hours | |
| movwf hours | |
| return | |
| AddTen | |
| movf temp.bcd.hours, w | |
| iorlw 15 << 4 ; turns high nybble into zeros | |
| xorlw 15 << 4 | |
| movwf temp.hours | |
| movlw 0x0a ; move ten(10)into w add 10 to low nybble | |
| addwf temp.hours, f ; temp.hours now in binary(decimal) | |
| movf temp.bcd.hours, w | |
| movwf hours | |
| return | |
| ;**************************************************************************** | |
| TestHighMinutes ; we want to count in decimal(binary) | |
| TestMover49 ; but display it as bcd for Nixies | |
| movlw 0xb0 | |
| addwf temp.bcd.minutes, w | |
| btfsc STATUS, C | |
| goto Mover50 | |
| TestMover39 ; 0100 0001 = 41 displayed on Nixies | |
| movlw 0xc0 ; 1100 0000 | |
| addwf temp.bcd.minutes, w ; C = 1 0000 0000 | |
| btfsc STATUS, C ; C is the carry bit from add overflow | |
| goto Mover40 ; so do this instruction | |
| TestMover29 | |
| movlw 0xd0 | |
| addwf temp.bcd.minutes, w | |
| btfsc STATUS, C | |
| goto Mover30 | |
| TestMover19 | |
| movlw 0xe0 | |
| addwf temp.bcd.minutes, w | |
| btfsc STATUS, C | |
| goto Mover20 | |
| TestMover9 | |
| movlw 0xf0 | |
| addwf temp.bcd.minutes, w | |
| btfsc STATUS, C | |
| goto Mover10 | |
| Mover0 | |
| movf temp.bcd.minutes, w | |
| movwf minutes | |
| return | |
| Mover49 | |
| movf temp.bcd.minutes, w | |
| iorlw 15 << 4 ; turns high nybble into zeros | |
| xorlw 15 << 4 | |
| movwf temp.minutes | |
| movlw 0x32 | |
| addwf temp.minutes, f | |
| movf temp.bcd.minutes, w | |
| movwf minutes | |
| return | |
| Mover39 | |
| movf temp.bcd.minutes, w ; 0100 0001 = 41 in bcd | |
| iorlw 15 << 4 ; turns high nybble into zeros | |
| xorlw 15 << 4 ; 0000 0001 | |
| movwf temp.minutes | |
| movlw 0x28 ; 0010 1000 | |
| addwf temp.minutes, f ; 0010 1001 = 41 in binary | |
| movf temp.bcd.minutes, w | |
| movwf minutes | |
| return | |
| Mover29 | |
| movf temp.bcd.minutes, w | |
| iorlw 15 << 4 ; turns high nybble into zeros | |
| xorlw 15 << 4 | |
| movwf temp.minutes | |
| movlw 0x1e | |
| addwf temp.minutes, f | |
| movf temp.bcd.minutes, w | |
| movwf minutes | |
| return | |
| Mover19 | |
| movf temp.bcd.minutes, w | |
| iorlw 15 << 4 ; turns high nybble into zeros | |
| xorlw 15 << 4 | |
| movwf temp.minutes | |
| movlw 0x14 | |
| addwf temp.minutes, f | |
| movf temp.bcd.minutes, w | |
| movwf minutes | |
| return | |
| Mover9 | |
| movf temp.bcd.minutes, w | |
| iorlw 15 << 4 ; turns high nybble into zeros | |
| xorlw 15 << 4 | |
| movwf temp.minutes | |
| movlw 0x0a | |
| addwf temp.minutes, f | |
| movf temp.bcd.minutes, w | |
| movwf minutes | |
| return | |
| ;**************************************************************************** | |
| IncHours | |
| ;call bounceUp | |
| incf temp.hours, f | |
| call HoursUpdate | |
| call Delay100mS | |
| call Delay100mS | |
| btfss time.up.button | |
| goto IncHours | |
| btfss time.down.button | |
| goto DecHours | |
| return | |
| ;**************************************************************************** | |
| IncMinutes | |
| ;call bounceUp | |
| incf temp.minutes, f | |
| call MinutesUpdate | |
| call Delay100mS | |
| call Delay100mS | |
| btfss time.up.button | |
| goto IncMinutes | |
| btfss time.down.button | |
| goto IncMinutes | |
| return | |
| ;**************************************************************************** | |
| DecHours | |
| call HoursDownUpdate | |
| call Delay100mS | |
| call Delay100mS | |
| btfss time.down.button | |
| goto DecHours | |
| btfss time.up.button | |
| goto IncHours | |
| return | |
| ;**************************************************************************** | |
| DecMinutes | |
| call MinutesDownUpdate | |
| call Delay100mS | |
| call Delay100mS | |
| btfss time.down.button | |
| goto DecMinutes | |
| btfss time.up.button | |
| goto IncMinutes | |
| return | |
| ;**************************************************************************** | |
| hoursON | |
| bcf high.minutes.anode | |
| bcf low.minutes.anode | |
| movf hours, w | |
| movwf PORTD | |
| bsf high.hours.anode | |
| bsf low.hours.anode | |
| return | |
| ;**************************************************************************** | |
| minutesON | |
| bcf high.hours.anode | |
| bcf low.hours.anode | |
| movf minutes, w | |
| movwf PORTD | |
| bsf high.minutes.anode | |
| bsf low.minutes.anode | |
| return | |
| ;**************************************************************************** | |
| MinutesUpdate | |
| call hoursON | |
| call Delay10mS | |
| call Delay10mS | |
| Test59 ; 0011 1011 = 59 | |
| movlw 0xC4 ; 1100 0100 | |
| addwf temp.minutes, w ; 1111 1111 | |
| btfsc STATUS, C ; no overflow Carry = 0 | |
| goto Over59 ; skip this instruction | |
| Test49 | |
| movlw 0xCE | |
| addwf temp.minutes, w | |
| btfsc STATUS, C | |
| goto Over49 | |
| Test39 ; 0010 1000 = 40 in temp.minutes | |
| movlw 0xD8 ; 1101 1000 | |
| addwf temp.minutes, w ; 0000 0000 | |
| btfsc STATUS, C ; overflow Carry = 1 | |
| goto Over39 ; do this instruction | |
| Test29 | |
| movlw 0xE2 | |
| addwf temp.minutes, w | |
| btfsc STATUS, C | |
| goto Over29 | |
| Test19 ; 0000 1100 = 12 in temp.minutes | |
| movlw 0xEC ; 1110 1100 | |
| addwf temp.minutes, w ; 1111 1000 | |
| btfsc STATUS, C ; no overflow Carry = 0 | |
| goto Over19 ; skip this instruction | |
| Test9 | |
| movlw 0xF6 | |
| addwf temp.minutes, w | |
| btfsc STATUS, C | |
| goto Over9 | |
| movf temp.minutes, w | |
| movwf minutes | |
| call minutesON | |
| return | |
| Over59 | |
| clrf temp.minutes | |
| clrf minutes | |
| call minutesON | |
| return | |
| Over49 ; 0011 0010 = 50 in temp.minutes | |
| movlw 0x1E ; 0001 1110 = 30 in binary | |
| addwf temp.minutes, w ; 0101 0000 = to display 50 on Nixies | |
| movwf minutes | |
| call minutesON | |
| return | |
| Over39 ; 0011 0000 = 48 in temp.minutes | |
| movlw 0x18 ; 0001 1000 = 24 in binary | |
| addwf temp.minutes, w ; 0100 1000 = into w register move to | |
| movwf minutes ; minutes not changing temp.minutes | |
| call minutesON ; to display 48 on Nixies | |
| return | |
| Over29 ; 0010 0000 = 32 in temp.minutes | |
| movlw 0x12 ; 0001 0010 = 18 in binary | |
| addwf temp.minutes, w ; 0011 0010 = to display 32 on Nixies | |
| movwf minutes | |
| call minutesON | |
| return | |
| Over19 | |
| movlw 0x0C | |
| addwf temp.minutes, w ; add off-set so nixies | |
| movwf minutes ; display proper time | |
| call minutesON | |
| return | |
| Over9 | |
| movlw 0x06 ; add off-set so nixies | |
| addwf temp.minutes, w ; display proper time | |
| movwf minutes | |
| call minutesON | |
| return | |
| ;**************************************************************************** | |
| HoursUpdate | |
| call minutesON | |
| call Delay10mS | |
| call Delay10mS | |
| TestOver12 | |
| movlw 0xF3 | |
| addwf temp.hours, w | |
| btfsc STATUS, C | |
| goto Over12Test | |
| TestOver9 | |
| movlw 0xF6 | |
| addwf temp.hours, w | |
| btfsc STATUS, C | |
| goto Over9Test | |
| movf temp.hours, w | |
| movwf hours | |
| call hoursON | |
| return | |
| Over12Test | |
| movlw 0x01 | |
| movwf temp.hours | |
| movwf hours | |
| call hoursON | |
| return | |
| Over9Test | |
| movlw 0x06 | |
| addwf temp.hours, w | |
| movwf hours | |
| call hoursON | |
| return | |
| ;**************************************************************************** | |
| HoursDownUpdate | |
| call minutesON | |
| call Delay10mS | |
| call Delay10mS | |
| TestHourOne | |
| movlw 0xff | |
| addwf temp.hours, w ; test if temp.hours.byte = 1 | |
| btfsc STATUS, Z | |
| goto HoursOne | |
| TestHour10orUnder | |
| movlw 0xf5 | |
| addwf temp.hours, w | |
| btfss STATUS, C | |
| goto Hours9orUnder | |
| Hours11orOver | |
| decf temp.hours, f | |
| movlw 0x06 | |
| addwf temp.hours, w | |
| movwf hours | |
| call hoursON | |
| return | |
| Hours9orUnder | |
| decf temp.hours, f | |
| movf temp.hours, w | |
| movwf hours | |
| call hoursON | |
| return | |
| HoursOne | |
| movlw 0x0c ; 12 | |
| movwf temp.hours | |
| movlw 0x06 ; 10 | |
| addwf temp.hours, w ; change decimal 12 to bcd 0001 0010 | |
| movwf hours | |
| call hoursON | |
| return | |
| ;**************************************************************************** | |
| MinutesDownUpdate | |
| call hoursON | |
| call Delay10mS | |
| call Delay10mS | |
| TestForZero | |
| movlw 0x00 | |
| addwf temp.minutes, w | |
| btfsc STATUS, Z | |
| goto Zero | |
| Test10orUnder | |
| movlw 0xf5 | |
| addwf temp.minutes, w | |
| btfss STATUS, C | |
| goto Under11 | |
| Test20orUnder | |
| movlw 0xeb | |
| addwf temp.minutes, w | |
| btfss STATUS, C | |
| goto Under21 | |
| Test30orUnder | |
| movlw 0xe1 | |
| addwf temp.minutes, w | |
| btfss STATUS, C | |
| goto Under31 | |
| Test40orUnder | |
| movlw 0xd7 | |
| addwf temp.minutes, w | |
| btfss STATUS, C | |
| goto Under41 | |
| Test50orUnder | |
| movlw 0xcd | |
| addwf temp.minutes, w | |
| btfss STATUS, C | |
| goto Under51 | |
| goto Over50 | |
| ;**************************************************************************** | |
| Zero | |
| movlw 59 | |
| movwf temp.minutes | |
| movlw 0x1e | |
| addwf temp.minutes, w | |
| movwf minutes | |
| call minutesON | |
| return | |
| Under11 | |
| decf temp.minutes, f | |
| movf temp.minutes, w | |
| movwf minutes | |
| call minutesON | |
| return | |
| Under21 | |
| decf temp.minutes, f | |
| movlw 0x06 | |
| addwf temp.minutes, w | |
| movwf minutes | |
| call minutesON | |
| return | |
| Under31 | |
| decf temp.minutes, f | |
| movlw 0x0c | |
| addwf temp.minutes, w | |
| movwf minutes | |
| call minutesON | |
| return | |
| Under41 | |
| decf temp.minutes, f | |
| movlw 0x12 | |
| addwf temp.minutes, w | |
| movwf minutes | |
| call minutesON | |
| return | |
| Under51 | |
| decf temp.minutes, f | |
| movlw 0x18 | |
| addwf temp.minutes, w | |
| movwf minutes | |
| call minutesON | |
| return | |
| Over50 | |
| decf temp.minutes, f | |
| movlw 0x1e | |
| addwf temp.minutes, w | |
| movwf minutes | |
| call minutesON | |
| return | |
| ;**************************************************************************** | |
| ; RTC module | |
| ; Write new time into RTC | |
| ;**************************************************************************** | |
| ClearRtcWP ; next 34 instructions = bcf control, 7 | |
| clear_rtc_wp ; clear the write protect bit to allow | |
| banksel TRISE ; writing to the clock module (DS1302) | |
| movlw 0x00 | |
| movwf TRISE ; make PORTE,0 into an output | |
| banksel PORTE | |
| clrf PORTE ; using porte,0 as data transfer bit | |
| movlw 0x08 | |
| movwf count | |
| movlw 0x8E ; 1000 1110 the write protect register address | |
| movwf reg.address | |
| bsf RTC.enable ; turn on control logic of RTC module | |
| nop | |
| write_protect | |
| nop | |
| nop ; nops for timing | |
| nop | |
| movwf PORTE ; only PORT E bit 0 is input/output | |
| call delay2usec ; move address one bit at a time | |
| bsf clockBit ; into RTC module | |
| call delay2usec | |
| bcf clockBit | |
| rrf reg.address, w ; next address bit-rotate one bit to the right | |
| movwf reg.address | |
| decfsz count, f ; do until all eight bits written | |
| goto write_protect ; into RTC | |
| Setwriteprotectbit0 | |
| movlw 8 | |
| movwf count | |
| setto0 | |
| clrf PORTE ; fill write protect register with zeros | |
| call delay2usec ; to clear it | |
| bsf clockBit | |
| call delay2usec | |
| bcf clockBit | |
| decfsz count, f | |
| goto setto0 | |
| bcf RTC.enable ; turn off control logic of RTC module | |
| return | |
| ;**************************************************************************** | |
| InitiateWrite | |
| movf fsr.offset, w | |
| addlw clk.reg ; get correct write address | |
| movwf FSR ; move adderss into FSR - move contents of | |
| movf INDF, w ; register pointed to by FSR into W | |
| movwf reg.address ; move into working variable | |
| movlw 8 | |
| movwf count | |
| movf reg.address, w | |
| bsf RTC.enable ; turn on control logic of RTC module - CE - | |
| commandwrite | |
| nop | |
| nop ; nops for timing | |
| nop | |
| movwf PORTE | |
| call delay2usec | |
| bsf clockBit ; move in the address | |
| call delay2usec ; one bit at a time | |
| bcf clockBit | |
| rrf reg.address, w | |
| movwf reg.address | |
| decfsz count, f | |
| goto commandwrite | |
| WriteRegister | |
| movf fsr.offset, w | |
| addlw clk.val ; get correct value address | |
| movwf FSR ; move address into FSR - move contents of | |
| movf INDF, w ; the register pointed to by FSR into W | |
| movwf time.valu ; move into working variable | |
| movlw 8 | |
| movwf count | |
| movf time.valu, w | |
| writetime | |
| movwf PORTE ; move in value one bit at a time | |
| call delay2usec | |
| bsf clockBit ; clocking and | |
| call delay2usec ; delays are | |
| bcf clockBit ; to set the bit | |
| rrf time.valu, w ; bring in next bit -- need new value | |
| movwf time.valu ; in W and in time.valu | |
| decfsz count, f | |
| goto writetime | |
| bcf RTC.enable ; enable RTC off | |
| call delay2usec | |
| incf fsr.offset, f ; increment offset to get the next register | |
| movlw 0x07 ; and its value. | |
| subwf fsr.offset, w ; check to see if all seven time and date | |
| btfss STATUS, Z ; bytes have been written | |
| goto InitiateWrite | |
| return | |
| ;**************************************************************************** | |
| SetRtcWP ; Set the write protect bit to disallow | |
| clrf PORTE ; writing/reading with clock module | |
| movlw 0x08 ; using porta, 0 as data transfer bit | |
| movwf count | |
| movlw 0x8E ; 1000 1110 the write protect register address | |
| movwf reg.address | |
| bsf RTC.enable ; turn on control logic of RTC module | |
| nop | |
| protect_address | |
| nop | |
| nop ; nops for timing | |
| nop | |
| movwf PORTE | |
| call delay2usec ; move address one bit at a time | |
| bsf clockBit ; into RTC module | |
| call delay2usec | |
| bcf clockBit | |
| rrf reg.address, w | |
| movwf reg.address | |
| decfsz count, f | |
| goto protect_address | |
| writeprotectbitTo1 | |
| movlw 8 | |
| movwf count | |
| movlw 0x80 ; 1000 0000 | |
| movwf wp.bit | |
| setto1 | |
| nop | |
| nop | |
| movwf PORTE ; move first digit into WP register | |
| call delay2usec | |
| bsf clockBit | |
| call delay2usec | |
| bcf clockBit | |
| rrf wp.bit, w | |
| movwf wp.bit | |
| decfsz count, f | |
| goto setto1 | |
| bcf RTC.enable ; turn off control logic of RTC module | |
| return | |
| ;**************************************************************************** | |
| ; Roll Display | |
| ;**************************************************************************** | |
| NixieRoll | |
| clrf k | |
| movf new.num, w ; make old.num the | |
| movwf old.num ; same as new.num | |
| clrf PORTA ; turn off any anodes that may be on | |
| up | |
| movlw 9 | |
| movwf cnt | |
| nixieup | |
| movf k,w ; display k in all | |
| movwf PORTD ; four tubes | |
| bsf high.hours.anode | |
| bsf low.hours.anode | |
| call Delay10mS | |
| bcf high.hours.anode | |
| bcf low.hours.anode | |
| call Delay1mS | |
| bsf high.minutes.anode | |
| bsf low.minutes.anode | |
| call Delay10mS | |
| bcf high.minutes.anode | |
| bcf low.minutes.anode | |
| call Delay1mS | |
| decfsz cnt, f | |
| goto nixieup | |
| movlw 17 ; 0001 0001 -- 1,1 | |
| addwf k, f | |
| movlw 170 ; 1010 1010 -- 10,10 | |
| subwf k, w | |
| btfss STATUS, Z ; if digit is 10 skip | |
| goto up | |
| movlw 136 ; move eight into k 1000 1000 -- 8,8 | |
| movwf k | |
| down | |
| movlw 9 | |
| movwf cnt | |
| nixiedown | |
| movf k, w | |
| movwf PORTD ; display k | |
| bsf high.hours.anode | |
| bsf low.hours.anode | |
| call Delay10mS | |
| bcf high.hours.anode | |
| bcf low.hours.anode | |
| call Delay1mS | |
| bsf high.minutes.anode | |
| bsf low.minutes.anode | |
| call Delay10mS | |
| bcf high.minutes.anode | |
| bcf low.minutes.anode | |
| call Delay1mS | |
| decfsz cnt, f | |
| goto nixiedown | |
| movlw 17 ; subtract one from k 0001 0001 -- 1,1 | |
| subwf k, f | |
| btfss STATUS, Z ; if zero skip | |
| goto down | |
| clrf PORTD | |
| movlw 9 | |
| movwf cnt | |
| displayzero | |
| bsf high.hours.anode ; display the zeros | |
| bsf low.hours.anode | |
| call Delay10mS | |
| bcf high.hours.anode | |
| bcf low.hours.anode | |
| call Delay1mS | |
| bsf high.minutes.anode ; display the zeros | |
| bsf low.minutes.anode | |
| call Delay10mS | |
| bcf high.minutes.anode | |
| bcf low.minutes.anode | |
| call Delay1mS | |
| decfsz cnt, f | |
| goto displayzero | |
| return | |
| ;**************************************************************************** | |
| ; Delays | |
| ;**************************************************************************** | |
| delay2usec ; 1.8uS delay plus return | |
| movlw 2 | |
| movwf i | |
| usec2 ; 2uS = 10 instruction cycles | |
| nop | |
| decfsz i, f | |
| goto usec2 | |
| return | |
| ;**************************************************************************** | |
| delay5usec ; 5uS delay plus return | |
| movlw 4 | |
| movwf i | |
| usec5 ; 5uS delay = 25 instruction cycles | |
| nop | |
| nop | |
| nop | |
| decfsz i, f | |
| goto usec5 | |
| return | |
| ;**************************************************************************** | |
| delay10usec ;10uS delay plus return | |
| movlw 8 | |
| movwf i | |
| usec10 ; 10uS delay = 50 instruction cycles | |
| nop | |
| nop | |
| nop | |
| decfsz i, f | |
| goto usec10 | |
| return | |
| ;**************************************************************************** | |
| Delay100uS | |
| bcf INTCON, T0IF ; clear timer 0 overflow flag | |
| movlw 225 | |
| movwf TMR0 | |
| check1 | |
| btfss INTCON, T0IF | |
| goto check1 | |
| bcf INTCON, T0IF | |
| return | |
| ;**************************************************************************** | |
| Delay500uS | |
| bcf INTCON, T0IF | |
| movlw 100 | |
| movwf TMR0 | |
| check5 | |
| btfss INTCON, T0IF | |
| goto check5 | |
| bcf INTCON, T0IF | |
| return | |
| ;**************************************************************************** | |
| Delay1mS | |
| movlw 0xFD ; 1.0038mS with these numbers | |
| movwf TMR1H | |
| movlw 0x8E | |
| movwf TMR1L | |
| bcf PIR1, TMR1IF ; clear tmr 1 overflow flag | |
| bsf T1CON, TMR1ON ; turn timer 1 on | |
| Tmr1FlagCheck1 | |
| btfss PIR1, TMR1IF ; check for overflow | |
| goto Tmr1FlagCheck1 | |
| bcf T1CON, TMR1ON ; turn timer 1 off | |
| return | |
| ;**************************************************************************** | |
| Delay10mS | |
| movlw 0xE7 ; 10.0038mS with these numbers | |
| movwf TMR1H | |
| movlw 0x95 | |
| movwf TMR1L | |
| bcf PIR1, TMR1IF ; clear tmr 1 overflow flag | |
| bsf T1CON, TMR1ON ; turn timer 1 on | |
| Tmr1FlagCheck10 | |
| btfss PIR1, TMR1IF ; check for overflow | |
| goto Tmr1FlagCheck10 | |
| bcf T1CON, TMR1ON ; turn timer 1 off | |
| return | |
| ;**************************************************************************** | |
| Delay100mS | |
| movlw 0x0B ; 100.0038mS with these numbers | |
| movwf TMR1H | |
| movlw 0xDB | |
| movwf TMR1L | |
| bcf PIR1, TMR1IF ; clear tmr 1 overflow flag | |
| bsf T1CON, TMR1ON ; turn timer 1 on | |
| Tmr1FlagCheck100 | |
| btfss PIR1, TMR1IF ; check for overflow | |
| goto Tmr1FlagCheck100 | |
| bcf T1CON, TMR1ON ; turn timer 1 off | |
| return | |
| ;**************************************************************************** | |
| bounceUp | |
| call Delay10mS | |
| btfss time.up.button | |
| goto bounceUp | |
| return | |
| ;**************************************************************************** | |
| bounceNext | |
| call Delay10mS | |
| btfss next.button | |
| goto bounceNext | |
| return | |
| ;**************************************************************************** | |
| ; Time and Date Information | |
| ;**************************************************************************** | |
| SetNewTime | |
| clrf PORTA ;turn off all nixies | |
| movlw 0x00 ; 0000 000 clear clock hold, 0 for seconds | |
| movwf clk.val | |
| movf minutes, w ; 0XXX XXXX-- minutes | |
| movwf clk.val + 1 | |
| movlw 0x80 ; put in 12 hr mode | |
| iorwf hours, w | |
| movwf clk.val + 2 | |
| movlw 0x00 | |
| movwf clk.val + 3 ; no need for | |
| movlw 0x00 | |
| movwf clk.val + 4 ; date, month, | |
| movlw 0x00 | |
| movwf clk.val + 5 ; day or | |
| movlw 0x00 | |
| movwf clk.val + 6 ; year | |
| call ClearRtcWP | |
| clrf fsr.offset | |
| call InitiateWrite | |
| call SetRtcWP ; set write protect bit | |
| return | |
| ;**************************************************************************** | |
| ; End subroutines | |
| ;**************************************************************************** | |
| START | |
| ;**************************************************************************** | |
| ; Initialization | |
| ; of Microcontroller | |
| ;**************************************************************************** | |
| banksel PORTA ; move into bank 0 | |
| clrf PORTA | |
| clrf PORTB | |
| clrf PORTC ; clear all ports | |
| clrf PORTD | |
| clrf PORTE | |
| movlw 0x30 | |
| movwf T1CON ; timer 1 off; 1:8 prescaler -0011 0000- | |
| movlw 0x83 ; address of read minutes register | |
| movwf read.min.address | |
| movlw 0x85 ; address of read hours register | |
| movwf read.hrs.address | |
| movlw 0x80 ; address of write seconds register | |
| movwf clk.reg | |
| movlw 0x82 ; address of write minutes register | |
| movwf clk.reg + 1 | |
| movlw 0x84 ; address of write hours register | |
| movwf clk.reg + 2 | |
| movlw 0x86 ; address of write date register | |
| movwf clk.reg + 3 | |
| movlw 0x88 ; address of write month register | |
| movwf clk.reg + 4 | |
| movlw 0x8A ; address of write day register | |
| movwf clk.reg + 5 | |
| movlw 0x8C ; address of write year register | |
| movwf clk.reg + 6 | |
| movlw 0x00 | |
| movwf old.num | |
| banksel TRISA ; move into bank 1 | |
| movlw 0x83 ; 1000 0011 | |
| movwf OPTION_REG | |
| movlw 0x00 | |
| movwf TRISA ; make PORTA outputs | |
| movlw 0xff | |
| movwf TRISB ; make PORTB inputs | |
| movlw 0x00 | |
| movwf WPUB ; disable pull-ups on all PortB pins | |
| movlw 0x00 | |
| movwf TRISC ; make outputs | |
| movlw 0x00 | |
| movwf TRISD ; make outputs | |
| movlw 0x00 | |
| movwf TRISE ; make outputs | |
| banksel ANSEL ; move into bank 3 | |
| movlw 0x00 | |
| movwf ANSEL ; turn off A/D and make | |
| movwf ANSELH ; ports A and B digital I/O | |
| banksel PORTA ; finish in bank 0 | |
| ;**************************************************************************** | |
| ; MAIN CODE | |
| ; (LOOP) | |
| ;**************************************************************************** | |
| DisplayMinutes | |
| call ReadMinutesSetup ; read minutes register in RTC | |
| bcf minutes.byte, 7 | |
| movf minutes.byte, w | |
| movwf PORTD | |
| bsf high.minutes.anode | |
| bsf low.minutes.anode | |
| call Delay10mS ; change delay if other nixies or resistors | |
| movf minutes.byte, w | |
| iorlw 15 << 4 ; turns high nybble into zeros | |
| xorlw 15 << 4 | |
| movwf new.num | |
| movf old.num, w ; check to see if new.num and | |
| subwf new.num, w ; old.num are the same - they | |
| btfss STATUS, Z ; will be after first roll | |
| call NixieRoll ; so only one roll | |
| bcf high.minutes.anode | |
| bcf low.minutes.anode | |
| call Delay1mS ; change delay if other nixies or resistors | |
| ;**************************************************************************** | |
| DisplayHours | |
| call ReadHoursSetup ; read hours register in RTC | |
| bcf hours.byte, 7 ; make bit 5, 6 and 7 low | |
| bcf hours.byte, 6 ; so hour nixie tube will | |
| bcf hours.byte, 5 ; only show one or zero | |
| movf hours.byte, w | |
| movwf PORTD | |
| btfsc hours.byte, 4 ; blank leading zero | |
| bsf high.hours.anode | |
| bsf low.hours.anode | |
| call Delay10mS ; change delay if other nixies or resistors | |
| bcf high.hours.anode | |
| bcf low.hours.anode | |
| call Delay1mS ; change delay if other nixies or resistors | |
| ;**************************************************************************** | |
| btfsc next.button ; change time? | |
| goto DisplayMinutes | |
| bounce | |
| call Delay10mS | |
| btfss next.button ; wait for button release | |
| goto bounce | |
| call ChangeTimeSubroutine | |
| call SetNewTime | |
| goto DisplayMinutes | |
| ;**************************************************************************** | |
| ;**************************************************************************** | |
| ;**************************************************************************** | |
| end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment