Skip to content

Instantly share code, notes, and snippets.

@jaymcgavren
Last active December 21, 2025 00:26
Show Gist options
  • Select an option

  • Save jaymcgavren/777f1fc796be941bee818cbd6327b8cd to your computer and use it in GitHub Desktop.

Select an option

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)
; 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