'This is a nixie clock driver 'Assumed is an ATMega8 - should work with an S2334 or similar but untested 'Author: Neil Barnes 'Date: 30/01/2004 'This software is released under GPL conditions - see www.gnu.org for details 'clock speed is 8000KHz 'each of four output tubes is directly driven via a 74141 binary-decimal driver 'chip; sending a code between 10 and 15 will blank the output 'the output tubes are wired with four bits each 'minutes PD4-7 'min tens PD0-3 'hours PC0-3 'hours tens PB0-3 'there are two switches on PB4 and PB5 which will be used to set the time 'since there are no indicators other than the four nixies available, 'the clock will display in 24 hour format only 'CODE STARTS HERE 'declare subroutines Declare Sub Showtime(byval Lhs As Byte , Byval Rhs As Byte) Declare Sub Settime 'global variables Dim Ticks As Byte '20 ticks per second Dim Seconds As Byte 'time Dim Minutes As Byte 'time Dim Hours As Byte 'time from interrupt routine Dim Oldseconds As Byte 'time currently displayed Dim Oldminutes As Byte Dim Oldhours As Byte Dim Acc1 As Byte Dim Acc2 As Byte Dim Acc3 As Byte 'temporary output routine variables Dim Xfade As Byte 'temporary use by main loop to handle Dim Temp As Integer 'the crossfade between digits Dim Count As Integer 'on-going tick count, used to time debounce Dim Switch1 As Bit 'switch temporary store Dim Switch2 As Bit Dim Oldswitch1 As Bit Dim Oldswitch2 As Bit 'variables for set time routine Dim Hrs As Byte Dim Mins As Byte Dim Lasttick As Byte Dim Flash As Byte 'set direction port B 'output on 0-3, input on 4,5 Ddrb = $0f 'set direction port C 'output on 0-3 Ddrc = $0f 'set direction port D 'output on all pins Ddrd = $ff 'preset the time to midnight Ticks = 0 Seconds = 0 Minutes = 0 Hours = 0 Oldseconds = 0 Oldminutes = 0 Oldhours = 0 Oldswitch1 = 1 'now we set up the clock to tick nicely 'the system clock is 8000kHz 'we set timer 1 to divide by 50000 which gives us 20 ticks per second 'after a divide by eight prescale Config Timer1 = Timer , Prescale = 8 'set up the interrupt vector Enable Interrupts Enable Oc1a 'set default count time - 50000 Ocr1ah = $c3 Ocr1al = $50 Tccr1b.wgm12 = 1 On Oc1a Ticktock 'loop forever - this is where the button scanning will probably go 'initial display Call Showtime(hours , Minutes) Do 'check to see if seconds have changed If Oldseconds <> Seconds Then 'yup, display time ' crossfade Xfade = 15 Xfd: Call Showtime(oldhours , Oldminutes) Temp = Xfade Waitms Temp Call Showtime(hours , Minutes) Temp = 15 - Xfade Temp = Temp Waitms Temp Decr Xfade If Xfade <> 0 Then Goto Xfd Oldseconds = Seconds Oldminutes = Minutes Oldhours = Hours End If 'now we think about the switches 'we only care here about switch one. if it's pressed for more than one 'second then we change mode to set the time 'when we start, the switches are pulled high and we have a 1 in 'switch and oldswitch to reflect this 'if we have a 0 on the pin, the switch is pushed 'remember count is updated by the interrupt routine If Pinb.5 = 0 Then Waitms 30 If Pinb.5 = 0 Then Call Settime End If End If Loop '''''''''''''''''''''''''''''''''''''''''' 'the interrupt service vector lives here ' 'it's entered 20 times per second ' 'updates ticks, seconds, minutes, hours 'we do not display in the interrupt process ' '''''''''''''''''''''''''''''''''''''''''' Ticktock: 'add one to tick count and update time if required '20 ticks per second Incr Ticks Incr Count 'we have to work round not being able to evaluate expressions in 'if-then-else constructs If Ticks = 20 Then Ticks = 0 End If If Ticks = 0 Then 'update seconds Incr Seconds If Seconds = 60 Then Seconds = 0 Incr Minutes If Minutes = 60 Then Minutes = 0 Incr Hours If Hours = 24 Then Hours = 0 End If End If End If End If Return 'end of interrupt routine '''''''''''''''''''''''''''''''''''''''''''''''''''''' ' 'Display two digits on the nixies ' 'note that on the hardware for which this is written, 'the first and third digits from the left can only 'display 0-2 and 0-5 respectively ' 'your mileage may vary ' 'if either parameter is 0xff, than that pair of 'digits is blanked ' '''''''''''''''''''''''''''''''''''''''''''''''''''''' Sub Showtime(lhs As Byte , Rhs As Byte): 'display is not in logical order: 'digits are in order: 'PC0-3 PD0-3 PB0-3 PD4-7 'start with minutes display Acc1 = Rhs Mod 10 Acc1 = Acc1 * 16 'minutes tens Acc2 = Rhs / 10 Acc2 = Acc2 And &B00001111 'hours Acc3 = Lhs / 10 Acc3 = Acc3 And &B00001111 'merge with minutes Acc1 = Acc1 + Acc3 Acc3 = Lhs Mod 10 'we need to blank channels as required If Rhs = 255 Then Acc1 = Acc1 Or &B11110000 Acc2 = Acc2 Or &B00001111 End If If Lhs = 255 Then Acc1 = Acc1 Or &B00001111 Acc3 = Acc3 Or &B00001111 End If 'now output them Portd = Acc1 Portc = Acc3 Portb = Acc2 Return End Sub Sub Settime 'settime is used to set the time 'it is entered when switch1 has been pressed for more than half a second. ' 'the hours digits flash ' 'after its release, pressing switch2 will advance the hours 0-23 ' 'pressing and releasing switch one then sets the hours and causes the minutes 'display to flash ' 'the minutes digits are advanced by pressing switch 2 ' 'a third use of switch1 transfers the time to the actual time locations 'and resets the seconds counter, then returns Hrs = Hours Mins = Minutes 'we work with local copies in case time is incremented 'by interrupt tick during our manipulation Call Showtime(hrs , 255) While Pinb.5 = 0 Waitms 30 'and debounce delay Wend 'wait for button to be released While Pinb.5 = 1 'now we wait until switch1 is pressed again Call Showtime(hrs , 255) If Pinb.4 = 0 Then 'switch 2 pressed? Waitms 30 'debounce If Pinb.4 = 0 Then Incr Hrs If Hrs = 24 Then 'cycle to zero Hrs = 0 End If While Pinb.4 = 0 Wend 'wait till switch 2 is released Waitms 30 End If End If Wend While Pinb.5 = 0 'switch 2 is released, wait till pressed Waitms 30 Wend 'now a similar trick to set the minutes While Pinb.5 = 1 Call Showtime(255 , Mins) If Pinb.4 = 0 Then Waitms 30 If Pinb.4 = 0 Then Incr Mins If Mins = 60 Then Mins = 0 End If While Pinb.4 = 0 Wend Waitms 30 End If End If Wend Waitms 30 While Pinb.5 = 0 'switch 2 is released, wait till pressed Waitms 30 Wend 'now update the real time stores Seconds = 0 Minutes = Mins Hours = Hrs Call Showtime(hours , Minutes) Return End Sub