You are here : Main projects | ZM1042 Nixie Tube Clock | 2. Conception and construction



ZM1042 Nixie Tube Clock
July 2014

2.  Conception and construction

This page will briefly outline the construction of the clock itself, and in particular its DV high-voltage power supply. The source code of the clock, given whole, can be found at the bottom of the page. As already mentioned in the introduction, I will not write a full explanation for the code, but for aspects pertaining to RTC timekeeping, the reader is invited to check the relevant RLB clock page.

2.1   Case construction

[Back to top]

The case is mostly made of wood with aluminium and steel ornaments. The eagle-like front emblem is made of hand-cut aluminium plates fixed against a 5mm thick sanded PVC support, which allows for a nice glowing effect when the backlight is on. The interior of the clock is painted with matte black to avoid parasitic reflections. The base of the clock is covered with rubber plates for great stability.

Here are a few selected pictures during the construction of the clock. You can find more on this photo album.

2.2   DC high-voltage power supply circuit

[Back to top]

The HV circuit supplies power to the nixie tubes at a relatively high voltage (around 200V). Here a direct-drive design was used. While multiplexed displays are often used in digital clocks due to the fact they demand much less microcontroller outputs to function, direct-drive circuits have a number of advantages, viz. they are simpler to build, the tubes don't flicker, no voltage overshoot is demanded (which can, sometimes, increase their lifetime).

The design used here, a switching power supply based on the MAX1771 chip is based on Mike Harrison's Nixie power supply, which is shown below for convenience. Mike's webpage contains good explanations on the circuit's functioning and helpful advice on how to build it.

Figure 2. — Schematic of the HV direct-drive nixie power supply used on this clock.
[Image credits: Mike Harrison]

Here are a few pictures of the construction of this circuit.

2.3   Complete source code

[Back to top]

The source code of this clock is pretty lengthy due to its many features, but apart from the nixie digit impression subroutines (which are now written for a direct-drive system, not multiplexed), many functions closely resemble the source codes of my previous IN-18 and RLB clocks. The reader is thus invited to check these pages if anything unclear with this source code.

Figure 2.2 — Annotated photograph of the front panel of the clock, comprising all the inputs relevant to the code.

The many switches and inputs that the clock has are labelled in fig. 2.2 above. The nixie switch turns the nixies on and off using by sending the right binary value to one specific pin of the MAX1771 chip. The backlightning of the front emblem is similarly controlled, with a simple transistor this time. The mode selector switch allows to chose what quantity to display on the nixies : time, date, or the alarm. The nixie pair selector switch determines whether the left, middle, or right pair of nixies have to be modified (i.e. for time mode, hours, minutes, or seconds). Then, the rightmost switch, which is a 12-position continuously rotating switch, allows the user to increase or decrease the value. The full source code can be downloaded from the link on the right.

/*
 * Program for the Hazardous Physics ZM1042 nixie tube clock. K155ID1-based, no multiplexing.
 * All clock functions by Chris Gerekos.
 * Music playing (Wave library + code for playing + SD card errors check) by Adafruit, http://learn.adafruit.com/adafruit-wave-shield-audio-shield-for-arduino/
 * Last updated 01/04/2014.
 */
 
 
 
// SN74141 : Truth Table
//D C B A #
//L,L,L,L 0
//L,L,L,H 1
//L,L,H,L 2
//L,L,H,H 3
//L,H,L,L 4
//L,H,L,H 5
//L,H,H,L 6
//L,H,H,H 7
//H,L,L,L 8
//H,L,L,H 9


#include <EEPROM.h>
#include <FatReader.h>
#include <SdReader.h>
#include <avr/pgmspace.h>
#include "WaveUtil.h"
#include "WaveHC.h"
#include <Wire.h>
#include "RTClib.h"

RTC_DS1307 RTC;   // Real time clock.
SdReader card;    // This object holds the information for the card.
FatVolume vol;    // This holds the information for the partition on the card.
FatReader root;   // This holds the information for the filesystem on the card.
FatReader f;      // This holds the information for the file we're play.
WaveHC wave;      // This is the only wave (audio) object, since we will only play one at a time.

#define DEBOUNCE 5  // button debouncer

volatile byte pressed, justpressed, justreleased;


// This handy function will return the number of bytes currently free in RAM, great for debugging!   
int freeRam(void)
{
  extern int  __bss_end; 
  extern int  *__brkval; 
  int free_memory; 
  if((int)__brkval == 0)  free_memory = ((int)&free_memory) - ((int)&__bss_end); 
  else  free_memory = ((int)&free_memory) - ((int)__brkval); 
  return free_memory; 
} 

void sdErrorCheck(void)
{
  if (!card.errorCode()) return;
  putstring("\n\rSD I/O error: ");
  Serial.print(card.errorCode(), HEX);
  putstring(", ");
  Serial.println(card.errorData(), HEX);
  while(1);
}

//Read the EEPROM just at switch-on.
int ClockHourSet = word(EEPROM.read(31), EEPROM.read(30));  //Reconstruction the integer form the two bytes saved on the EEPROM.
int ClockMinSet = word(EEPROM.read(33), EEPROM.read(32));   
int ClockSecSet = word(EEPROM.read(35), EEPROM.read(34));   
int ClockDaySet = word(EEPROM.read(37), EEPROM.read(36));  
int ClockMonthSet = word(EEPROM.read(39), EEPROM.read(38));  
int ClockYearSet = word(EEPROM.read(311), EEPROM.read(310));
int AlmHours = word(EEPROM.read(213), EEPROM.read(212));
int AlmMins = word(EEPROM.read(215), EEPROM.read(214));

//Naming a few inputs-related pins:
byte BlueLED = A0;
byte EagleLightSwitch = A1;
byte MainButton = A2;
byte ModeSwitchL = A3;
byte ModeSwitchR = A5;
byte SleepSwitch = A4;
byte NixieSHDN = A6;
byte EagleLight = 9;
byte Set2 = A14;
byte Set3 = A9;
byte Set1 = A10;
byte Scroll1 = A15;
byte Scroll2 = A12;
byte Scroll3 = A13;
byte AlmSend = 16;
byte AlmReceive = 17;

//Naming other stuff
byte Mode;      // 1: Time, 2: Date, 3: Alarm
byte LastMode=1;
byte Set;       // 1: Left, 2: Middle, 3: Right
byte BlueLEDState;
byte MainButtonPressed;
byte AlmArmed = EEPROM.read(316);
byte AlmPlaying;
int CycleState[3];
int LastCycleState[3];
byte change;
int Increase;   //Can be -1, 0, 1.

//Naming all the pins going to the K155ID1.
byte leftleftA = 26;
byte leftleftB = 24;
byte leftleftD = 28;
byte leftleftC = 30;
byte leftrightA = 42;
byte leftrightB = 40;
byte leftrightC = 46;
byte leftrightD = 44;

byte middlerightA = 27;
byte middlerightB = 25;
byte middlerightC = 31;
byte middlerightD = 29;
byte middleleftA = 35;
byte middleleftB = 33;
byte middleleftC = 39;
byte middleleftD = 37;

byte rightrightA = 43;
byte rightrightB = 41;
byte rightrightC = 47;
byte rightrightD = 45;
byte rightleftA = 34;
byte rightleftB = 32;
byte rightleftC = 38;
byte rightleftD = 36;


void setup(){
  Serial.begin(9600);
  Wire.begin();
  RTC.begin();
  //Following line sets the RTC to the date & time this sketch was compiled:
  //RTC.adjust(DateTime(__DATE__, __TIME__));

  putstring("Free RAM: ");        // This can help with debugging, running out of RAM is bad.
  Serial.println(freeRam());      // If this is under 150 bytes it may spell trouble!

  //Set the output pins for the DAC control. This pins are defined in the library.
  pinMode(2,OUTPUT);
  pinMode(3,OUTPUT);
  pinMode(4,OUTPUT);
  pinMode(5,OUTPUT);
  pinMode(13,OUTPUT); //LED
  pinMode(AlmSend, OUTPUT);
  pinMode(AlmReceive, INPUT_PULLUP);

  if (!card.init()) {                    // Play with 8 MHz spi (default faster!)  
    putstring_nl("Card init. failed!");  // Something went wrong, lets print out why.
    sdErrorCheck();
    while(1);                            // Then 'halt' - do nothing!
  }

  //Enable optimize read - some cards may timeout. Disable if you're having problems
  card.partialBlockRead(true);

  //Now we will look for a FAT partition!
  uint8_t part;
  for (part = 0; part < 5; part++) {     // We have up to 5 slots to look in
    if (vol.init(card, part)) 
      break;                             // We found one, lets bail.
  }
  if (part == 5) {                       // If we ended up not finding one  :(
    putstring_nl("No valid FAT partition!");
    sdErrorCheck();                      // Something went wrong, lets print out why
    while(1);                            // Then 'halt' - do nothing!
  }

  // Lets tell the user about what we found
  putstring("Using partition ");
  Serial.print(part, DEC);
  putstring(", type is FAT");
  Serial.println(vol.fatType(),DEC);      // FAT16 or FAT32?

  //Try to open the root directory
  if (!root.openRoot(vol)) {
    putstring_nl("Can't open root dir!"); // Something went wrong,
    while(1);                             // Then 'halt' - do nothing!
  }

  putstring_nl("Ready!");

  TCCR2A = 0;
  TCCR2B = 1<<CS22 | 1<<CS21 | 1<<CS20;
  TIMSK2 |= 1<<TOIE2;   //Timer2 Overflow Interrupt Enable

  //REMINDER: All inputs have their pull-up resistor activated, so pressing the buttons/switch makes the pin go LOW.

  //Pin modes for the lower panel.
  pinMode(BlueLED, OUTPUT);
  pinMode(EagleLightSwitch, INPUT_PULLUP);
  pinMode(MainButton, INPUT_PULLUP);
  pinMode(ModeSwitchL, INPUT_PULLUP);
  pinMode(ModeSwitchR, INPUT_PULLUP);
  pinMode(SleepSwitch, INPUT_PULLUP);
  pinMode(NixieSHDN, OUTPUT);
  pinMode(EagleLight, OUTPUT);

  //Pin modes for the upper panel.
  pinMode(Set1, INPUT_PULLUP);
  pinMode(Set2, INPUT_PULLUP);
  pinMode(Set3, INPUT_PULLUP);
  pinMode(Scroll1, INPUT_PULLUP);
  pinMode(Scroll2, INPUT_PULLUP);
  pinMode(Scroll3, INPUT_PULLUP);

  //Pin modes for the K155ID1 chips
  for(byte i=24; i<=47; i++) pinMode(i,OUTPUT);

}



SIGNAL(TIMER2_OVF_vect) {
  check_switches();
}

void check_switches()
{
  static byte previousstate;
  static byte currentstate;
  
    currentstate = digitalRead(17);   // read the button
    
    if (currentstate == previousstate) {
      if ((pressed == LOW) && (currentstate == LOW)) {
          // just pressed
          justpressed = 1;
      }
      else if ((pressed == HIGH) && (currentstate == HIGH)) {
          // just released
          justreleased = 1;
      }
      pressed = !currentstate;  // remember, digital HIGH means NOT pressed
    }
    previousstate = currentstate;   // keep a running tally of the buttons
}

void DisplaySetK155ID1( int LL, int LR, int ML, int MR, int RL, int RR , int del)
{
  int a,b,c,d;
  
  // Set defaults.
  a=0;b=0;c=0;d=0; // will display a zero.
  
  // Load the a,b,c,d.. to send to the K156ID1 controlling the leftmost tube.
  switch( LL )
  {
    case 0: a=0;b=0;c=0;d=0;break;
    case 1: a=0;b=0;c=0;d=1;break;
    case 2: a=0;b=0;c=1;d=0;break;
    case 3: a=0;b=0;c=1;d=1;break;
    case 4: a=0;b=1;c=0;d=0;break;
    case 5: a=0;b=1;c=0;d=1;break;
    case 6: a=0;b=1;c=1;d=0;break;
    case 7: a=0;b=1;c=1;d=1;break;
    case 8: a=1;b=0;c=0;d=0;break;
    case 9: a=1;b=0;c=0;d=1;break;
    default: a=1;b=1;c=1;d=1;
    break;
  }  
  // Write to output pins.
  digitalWrite(leftleftA, a);
  digitalWrite(leftleftB, b);
  digitalWrite(leftleftC, c);
  digitalWrite(leftleftD, d);
  
  delay(del);

// Load the a,b,c,d.. to send to the K155ID1 controlling the left-right tube.
  switch( LR )
  {
    case 0: a=0;b=0;c=0;d=0;break;
    case 1: a=0;b=0;c=0;d=1;break;
    case 2: a=0;b=0;c=1;d=0;break;
    case 3: a=0;b=0;c=1;d=1;break;
    case 4: a=0;b=1;c=0;d=0;break;
    case 5: a=0;b=1;c=0;d=1;break;
    case 6: a=0;b=1;c=1;d=0;break;
    case 7: a=0;b=1;c=1;d=1;break;
    case 8: a=1;b=0;c=0;d=0;break;
    case 9: a=1;b=0;c=0;d=1;break;
    default: a=1;b=1;c=1;d=1;
    break;
  }  
  // Write to output pins.
  digitalWrite(leftrightA, a);
  digitalWrite(leftrightB, b);
  digitalWrite(leftrightC, c);
  digitalWrite(leftrightD, d);
  
  delay(del);
  
  // Load the a,b,c,d.. to send to the K155ID1 controlling the middle-left tube.
  switch( ML )
  {
    case 0: a=0;b=0;c=0;d=0;break;
    case 1: a=0;b=0;c=0;d=1;break;
    case 2: a=0;b=0;c=1;d=0;break;
    case 3: a=0;b=0;c=1;d=1;break;
    case 4: a=0;b=1;c=0;d=0;break;
    case 5: a=0;b=1;c=0;d=1;break;
    case 6: a=0;b=1;c=1;d=0;break;
    case 7: a=0;b=1;c=1;d=1;break;
    case 8: a=1;b=0;c=0;d=0;break;
    case 9: a=1;b=0;c=0;d=1;break;
    default: a=1;b=1;c=1;d=1;
    break;
  }  
  // Write to output pins.
  digitalWrite(middleleftA, a);
  digitalWrite(middleleftB, b);
  digitalWrite(middleleftC, c);
  digitalWrite(middleleftD, d);
  
  // Load the a,b,c,d.. to send to the K155ID1 controlling the middle-left tube.
  switch( MR )
  {
    case 0: a=0;b=0;c=0;d=0;break;
    case 1: a=0;b=0;c=0;d=1;break;
    case 2: a=0;b=0;c=1;d=0;break;
    case 3: a=0;b=0;c=1;d=1;break;
    case 4: a=0;b=1;c=0;d=0;break;
    case 5: a=0;b=1;c=0;d=1;break;
    case 6: a=0;b=1;c=1;d=0;break;
    case 7: a=0;b=1;c=1;d=1;break;
    case 9: a=1;b=0;c=0;d=0;break;  //Wiring mistake ;)
    case 8: a=1;b=0;c=0;d=1;break;
    default: a=1;b=1;c=1;d=1;
    break;
  }  
  // Write to output pins.
  digitalWrite(middlerightA, a);
  digitalWrite(middlerightB, b);
  digitalWrite(middlerightC, c);
  digitalWrite(middlerightD, d);
  
  delay(del);
  
  // Load the a,b,c,d.. to send to the K155ID1 controlling the right-left tube.
  switch( RL )
  {
    case 0: a=0;b=0;c=0;d=0;break;
    case 1: a=0;b=0;c=0;d=1;break;
    case 2: a=0;b=0;c=1;d=0;break;
    case 3: a=0;b=0;c=1;d=1;break;
    case 4: a=0;b=1;c=0;d=0;break;
    case 5: a=0;b=1;c=0;d=1;break;
    case 6: a=0;b=1;c=1;d=0;break;
    case 7: a=0;b=1;c=1;d=1;break;
    case 8: a=1;b=0;c=0;d=0;break;
    case 9: a=1;b=0;c=0;d=1;break;
    default: a=1;b=1;c=1;d=1;
    break;
  }  
  // Write to output pins.
  digitalWrite(rightleftA, a);
  digitalWrite(rightleftB, b);
  digitalWrite(rightleftC, c);
  digitalWrite(rightleftD, d);
  
  delay(del);
  
  // Load the a,b,c,d.. to send to the K155ID1 controlling the rightmost tube.
  switch( RR )
  {
    case 0: a=0;b=0;c=0;d=0;break;
    case 1: a=0;b=0;c=0;d=1;break;
    case 2: a=0;b=0;c=1;d=0;break;
    case 3: a=0;b=0;c=1;d=1;break;
    case 4: a=0;b=1;c=0;d=0;break;
    case 5: a=0;b=1;c=0;d=1;break;
    case 6: a=0;b=1;c=1;d=0;break;
    case 7: a=0;b=1;c=1;d=1;break;
    case 8: a=1;b=0;c=0;d=0;break;
    case 9: a=1;b=0;c=0;d=1;break;
    default: a=1;b=1;c=1;d=1;
    break;
  }  
  // Write to output pins.
  digitalWrite(rightrightA, a);
  digitalWrite(rightrightB, b);
  digitalWrite(rightrightC, c);
  digitalWrite(rightrightD, d);
  
  delay(del);
}



void loop(){
  
  digitalWrite(AlmSend, HIGH);
  
  // TIME CALCULATION /////////////////////////////////
/////////////////////////////////////////////////////

  DateTime now = RTC.now();

  unsigned long time = now.unixtime() - 1401000000; 
  time += (long) ClockSecSet + 60* (long) ClockMinSet + 3600* (long) ClockHourSet + 86400* (long) ClockDaySet;    //time in seconds, based on offset

  // Convert time to days,hours,mins,seconds
  long days  = time / 86400;    time -= days  * 86400; 
  long hours = time / 3600;   time -= hours * 3600; 
  long minutes  = time / 60;    time -= minutes  * 60; 
  long seconds  = time; 

  // Get the high and low order values for hours,min,seconds. 
  byte lowerHours = hours % 10;
  byte upperHours = hours - lowerHours;
  byte lowerMins = minutes % 10;
  byte upperMins = minutes - lowerMins;
  byte lowerSeconds = seconds % 10;
  byte upperSeconds = seconds - lowerSeconds;
  if( upperSeconds >= 10 )   upperSeconds = upperSeconds / 10;
  if( upperMins >= 10 )      upperMins = upperMins / 10;
  if( upperHours >= 10 )     upperHours = upperHours / 10;

// DATE CALCULATION /////////////////////////////////
/////////////////////////////////////////////////////

  int Day = days;
  int Month = ClockMonthSet;
  int Year = abs(ClockYearSet%100);

  //Number of days in a month:
  byte February;
  if(Year%4==0) February=29;
  else February=28;
  byte MonthArray[13] = {0,31,February,31,30,31,30,31,31,30,31,30,31};  //we'll skip the first entry, so we can use the array's index directly.

  //Defining Month incrementation.
  for(byte i=1;i<13;i++){
    if(Month==i){
      if(Day>MonthArray[i]){	//If "Day" exceeds the number of days in the present month, it is resetted to 1 and we step into the next month.
        Day -= MonthArray[i];
        Month++;
      }
      if(Day<1){	//Similarly if "Day" is to become 0.
        if(i-1==0) i=13;	//Before January comes December.
        Day += MonthArray[i-1];
        Month--;
      }
    }
  }
  
  //Defining years incrementation.
  if(Month>=13){
   Year++;
   Month=Month-12;
  }
  if(Month<=0){
   Year--;
   Month=Month+12;
  }

  // Splitting date. 
  byte lowerYears = Year % 10;
  byte upperYears = Year - lowerYears;
  byte lowerMonths = Month % 10;
  byte upperMonths = Month - lowerMonths;
  byte lowerDays = Day % 10;
  byte upperDays = Day - lowerDays;
  if( upperDays >= 10 ) upperDays = upperDays / 10;
  if( upperMonths >= 10 ) upperMonths = upperMonths / 10; 
  if( upperYears >= 10 ) upperYears = upperYears / 10;
  
  // ALARM //////////////////////////////////
  ///////////////////////////////////////////
  if(AlmHours>23)  AlmHours=AlmHours-24;  //After 23:00 comes 00:00
  if(AlmHours<0)  AlmHours=AlmHours+23;   //vice-versa
  if(AlmMins>59)  AlmMins=AlmMins-60;   //same thing
  if(AlmMins<0)  AlmMins=AlmMins+59;
  
   // Splitting.    
  byte lowerAlmHours = AlmHours % 10;
  byte upperAlmHours = AlmHours - lowerAlmHours;
  byte lowerAlmMins = AlmMins % 10;
  byte upperAlmMins = AlmMins - lowerAlmMins;
  if( upperAlmMins >= 10 )      upperAlmMins = upperAlmMins / 10;
  if( upperAlmHours >= 10 )     upperAlmHours = upperAlmHours / 10;
  

  // LOWER PANEL INPUTS /////////////////////
  ///////////////////////////////////////////

  //Nixies and eagle lightning:
  if(digitalRead(SleepSwitch)==LOW){          // CLOCK IS AWAKE.
    digitalWrite(NixieSHDN, LOW);             // Enable HV power supply.
    if(digitalRead(EagleLightSwitch)==LOW){
      digitalWrite(EagleLight,HIGH);          // Turn on eagle lights
    }
    else  digitalWrite(EagleLight,LOW);       // Turn off eagle lights.
  }
  else if(wave.isplaying==false){             // EVERYTHING GOES DOWN.
    digitalWrite(NixieSHDN, HIGH);            // Disable HV supply.
    digitalWrite(EagleLight,LOW);             // Turn off eagle lights.
  }

  //Mode selection with the three-states switch:
  byte Left = digitalRead(ModeSwitchL);
  byte Right = digitalRead(ModeSwitchR);
  if(Left==LOW && Right==HIGH)   Mode=1;  //Switch tilts left ==> time mode.
  if(Left==HIGH && Right==HIGH)  Mode=2;  //Switch is upright ==> date mode.
  if(Left==HIGH && Right==LOW)   Mode=3;  //Switch tilts right ==> alarm mode.
  //Cool-looking "string transition" between modes.
  if(Mode != LastMode){
    DisplaySetK155ID1(10,10,10,10,10,10, 50);
    if(Mode==1)  DisplaySetK155ID1(upperHours, lowerHours, upperMins, lowerMins, upperSeconds, lowerSeconds, 50);
    if(Mode==2)  DisplaySetK155ID1(upperDays, lowerDays, upperMonths, lowerMonths, upperYears, lowerYears, 50);
    if(Mode==3)  DisplaySetK155ID1(AlmArmed, 10, upperAlmHours, lowerAlmHours, upperAlmMins, lowerAlmMins, 50);
    LastMode = Mode;
  }
  
  //Alarm triggering:
  if(AlmArmed==true && AlmHours==hours && AlmMins==minutes && seconds==0){
    digitalWrite(AlmSend,LOW);
    delay(1000);
    AlmPlaying = true;
    digitalWrite(NixieSHDN,LOW);
  }
  
  if(AlmPlaying==true && digitalRead(MainButton)==LOW){
    AlmPlaying==false;
    wave.stop();
  }
  
  if (justpressed) {  //play or stop alarm when 17 is "triggered"
    justpressed=0;
    if(AlmPlaying==true)  playfile("SONG.WAV");    
  }
  


  //Blue LED blinking:
  if(now.second()%2 == 0)  digitalWrite(BlueLED, HIGH);        //Blinks with a period of 2sec (1sec on, 1sec off).
  else digitalWrite(BlueLED, LOW);            


  // UPPER PANEL INPUTS /////////////////////
  ///////////////////////////////////////////

  //Set selector switch:
  if(digitalRead(Set1)==LOW)  Set=1;
  if(digitalRead(Set2)==LOW)  Set=2;
  if(digitalRead(Set3)==LOW)  Set=3;

  //Scroll switch for modification:
  if(digitalRead(Scroll1)==LOW){
    CycleState[0]=0;
    CycleState[1]=1;
    CycleState[2]=1;
  }
  else if(digitalRead(Scroll2)==LOW){
    CycleState[0]=1;
    CycleState[1]=0;
    CycleState[2]=1;
  }
  else{
    CycleState[0]=1;
    CycleState[1]=1;
    CycleState[2]=0;
  }
  
  //Pushbutton reading.
  byte MainInput = digitalRead(MainButton);
  if(MainInput==0)  MainButtonPressed = true;
  // Checking for changes in the array
  if(MainInput==0 && digitalRead(SleepSwitch)==LOW){  //Allow modification only when button is pressed and nixies on
    for (int j=0; j<=2; j++){   
      if(LastCycleState[j] != CycleState[j])  change=true;
    }
    
    if(change==true){
      if(CycleState[0]==0){
        if(LastCycleState[1]==0)  Increase = 1;
        if(LastCycleState[2]==0)  Increase = -1;
      }
      if(CycleState[1]==0){
        if(LastCycleState[2]==0)  Increase = 1;
        if(LastCycleState[0]==0)  Increase = -1;
      }
      if(CycleState[2]==0){
        if(LastCycleState[0]==0)  Increase = 1;
        if(LastCycleState[1]==0)  Increase = -1;
      }
      delay(25);
    
      if(Mode==1){
        if(Set==1)  ClockHourSet = ClockHourSet+Increase;
        if(Set==2)  ClockMinSet = ClockMinSet+Increase;
        if(Set==3)  ClockSecSet = ClockSecSet+Increase;
      }
      if(Mode==2){
        if(Set==1)  ClockDaySet = ClockDaySet+Increase;
        if(Set==2)  ClockMonthSet = ClockMonthSet+Increase;
        if(Set==3)  ClockYearSet = ClockYearSet+Increase;
      }
      if(Mode==3){
        if(Set==2)  AlmHours = AlmHours + Increase;
        if(Set==3)  AlmMins = AlmMins + Increase;
      }
  
      Increase=0;
      for(int j=0; j<=2; j++)     LastCycleState[j] = CycleState[j];
      //Reinitialazing arrays.
    }
  }
  
  if(MainButtonPressed==true && MainInput==1){  //Saving when button is released
    byte lowCHS = lowByte(ClockHourSet);        //Split the 2-bytes integer into the respecting "high" and "low" parts in order to save them on the EEPROM.
    byte highCHS = highByte(ClockHourSet);
    byte lowCMS = lowByte(ClockMinSet);
    byte highCMS = highByte(ClockMinSet);
    byte lowCSS = lowByte(ClockSecSet);
    byte highCSS = highByte(ClockSecSet);
    byte lowCDS = lowByte(ClockDaySet);
    byte highCDS = highByte(ClockDaySet);
    byte lowCOS = lowByte(ClockMonthSet);
    byte highCOS = highByte(ClockMonthSet);
    byte lowCYS = lowByte(ClockYearSet);
    byte highCYS = highByte(ClockYearSet);
    byte lowAH = lowByte(AlmHours);
    byte highAH = highByte(AlmHours);
    byte lowAM = lowByte(AlmMins);
    byte highAM = highByte(AlmMins);
    
    EEPROM.write(30, lowCHS);  EEPROM.write(31, highCHS); //Saving
    EEPROM.write(32, lowCMS);  EEPROM.write(33, highCMS);
    EEPROM.write(34, lowCSS);  EEPROM.write(35, highCSS);
    EEPROM.write(36, lowCDS);  EEPROM.write(37, highCDS);
    EEPROM.write(38, lowCOS);  EEPROM.write(39, highCOS);
    EEPROM.write(310, lowCYS);  EEPROM.write(311, highCYS);
    EEPROM.write(212, lowAH);  EEPROM.write(213, highAH);
    EEPROM.write(214, lowAM);  EEPROM.write(215, highAM);
    
    MainButtonPressed=false;
    
    MainInput = digitalRead(MainButton);
    if(MainInput==0)  MainButtonPressed = true;
    if(Mode==3 && digitalRead(SleepSwitch)==LOW){ //Releasing the button also changes the alarm arming.
        if(AlmArmed==false)  AlmArmed=true;
        else  AlmArmed=false;
        MainButtonPressed=false;
        EEPROM.write(316, AlmArmed);
    }
  }
    
  
// SHOWTIME!! ///////////////////////////////////////
/////////////////////////////////////////////////////

  if(Mode==1){
    //Display time on the tubes.
    DisplaySetK155ID1(upperHours, lowerHours, upperMins, lowerMins, upperSeconds, lowerSeconds, 0);
    
    //Cleaning cathodes every 10 minutes.
    if(lowerMins==0 && upperSeconds==0 && lowerSeconds==5){
      for(int j=-1; j<11; j++){
        DisplaySetK155ID1(j,j,j,j,j,j, 50);
        delay(100);
      }
    }
  }
  
  if(Mode==2){
    DisplaySetK155ID1(upperDays, lowerDays, upperMonths, lowerMonths, upperYears, lowerYears, 0);
  }
  
  if(Mode==3){
    DisplaySetK155ID1(AlmArmed, 10, upperAlmHours, lowerAlmHours, upperAlmMins, lowerAlmMins, 0);
  }
  
}



// Plays a full file from beginning to end with no pause.
void playcomplete(char *name) {    // Call our helper to find and play this name.
  playfile(name);
  while (wave.isplaying) {
  }        // Do nothing while its playing.
}                                  // Now its done playing.



void playfile(char *name) {
  //See if the wave object is currently doing something
  if (wave.isplaying) {
    wave.stop();      // Already playing something, so stop it!
  }
  //Look in the root directory and open the file
  if (!f.open(root, name)) {
    putstring("Couldn't open file "); 
    Serial.print(name);
    return;
  }
  //OK read the file and turn it into a wave object.
  if (!wave.create(f)) {
    putstring_nl("Not a valid WAV");
    return;
  }

  //OK time to play! Start playback.
  wave.play();
}