Arduino Shield NCS314 NIXIE Tubes Clock IN-14
Build your Nixie Tubes display easy.
Devices & Components
Arduino Mega 2560 Rev3
Arduino Uno Rev3
Shield Nixie Tubes IN-14 NCS314 Arduino for Nixie Tubes Clock etc.
Power Supply 12V 1A
Shield Nixie Tubes Clock IN-12 NCS312 for xUSSR Nixie Tubes
Acrylic Case for SHIELD NCS314
Software & Tools
Arduino IDE
Project description
Code
Prog NIXIE Clock Tubes Shield NCS314
Prog NIXIE Clock Tubes Shield NCS314
Untitled file
c_cpp
1const String FirmwareVersion="010000"; 2//Format _X.XX__ 3//NIXIE CLOCK SHIELD NCS314 by GRA & AFCH (fominalec@gmail.com) 4//25.05.2016 5 6#include <SPI.h> 7#include <Wire.h> 8#include <ClickButton.h> 9#include <Time.h> 10#include <Tone.h> 11#include <EEPROM.h> 12 13const byte LEpin=7; //pin Latch Enabled data accepted while HI level 14const byte DHVpin=5; // off/on MAX1771 Driver Hight Voltage(DHV) 110-220V 15const byte RedLedPin=9; //MCU WDM output for red LEDs 9-g 16const byte GreenLedPin=6; //MCU WDM output for green LEDs 6-b 17const byte BlueLedPin=3; //MCU WDM output for blue LEDs 3-r 18const byte pinSet=A0; 19const byte pinUp=A2; 20const byte pinDown=A1; 21const byte pinBuzzer=2; 22const byte pinUpperDots=12; //HIGH value light a dots 23const byte pinLowerDots=8; //HIGH value light a dots 24const word fpsLimit=16666; // 1/60*1.000.000 //limit maximum refresh rate on 60 fps 25 26String stringToDisplay="000000";// Conten of this string will be displayed on tubes (must be 6 chars length) 27int menuPosition=0; // 0 - time 28 // 1 - date 29 // 2 - alarm 30 // 3 - 12/24 hours mode 31 32byte blinkMask=B00000000; //bit mask for blinkin digits (1 - blink, 0 - constant light) 33 34//-------------------------0-------1----------2----------3---------4--------5---------6---------7---------8---------9----- 35//byte lowBytesArray[]={B11111110,B11111101,B11111011,B11110111,B11101111,B11011111,B10111111,B01111111,B11111111,B11111111}; 36//byte highBytesArray[]={B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111110,B11111101}; 37 38byte dotPattern=B00000000; //bit mask for separeting dots 39 //B00000000 - turn off up and down dots 40 //B1100000 - turn off all dots 41 42#define DS1307_ADDRESS 0x68 43byte zero = 0x00; //workaround for issue #527 44int RTC_hours, RTC_minutes, RTC_seconds, RTC_day, RTC_month, RTC_year, RTC_day_of_week; 45 46//-- ------------0--------1--------2-------3--------4--------5--------6--------7--------8--------9--------10-------11-------12-------13-------14 47// names: Time, Date, Alarm, 12/24 hours, mintues, seconds, day, month, year, hour, minute, second alarm01 hour_format 48// 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 49int parent[15]={ 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4}; 50int firstChild[15]={4, 7, 10, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 51int lastChild[15]={ 6, 9, 13, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 52int value[15]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24}; 53int maxValue[15]={ 0, 0, 0, 0, 23, 59, 59, 31, 12, 99, 23, 59, 59, 1, 24}; 54int minValue[15]={ 0, 0, 0, 12, 00, 00, 00, 1, 1, 00, 00, 00, 00, 0, 12}; 55byte blinkPattern[15]={ 56 B00000000, 57 B00000000, 58 B00000000, 59 B00000000, 60 B00000011, 61 B00001100, 62 B00110000, 63 B00000011, 64 B00001100, 65 B00110000, 66 B00000011, 67 B00001100, 68 B00110000, 69 B11000000, 70 B00001100}; 71#define TimeIndex 0 72#define DateIndex 1 73#define AlarmIndex 2 74#define hModeIndex 3 75#define TimeHoursIndex 4 76#define TimeMintuesIndex 5 77#define TimeSecondsIndex 6 78#define DateDayIndex 7 79#define DateMonthIndex 8 80#define DateYearIndex 9 81#define AlarmHourIndex 10 82#define AlarmMinuteIndex 11 83#define AlarmSecondIndex 12 84#define Alarm01 13 85#define hModeValueIndex 14 86 87bool editMode=false; 88 89long downTime=0; 90long upTime=0; 91const long settingDelay=150; 92bool BlinkUp=false; 93bool BlinkDown=false; 94unsigned long enteringEditModeTime=0; 95bool RGBLedsOn=true; 96byte RGBLEDsEEPROMAddress=0; 97byte HourFormatEEPROMAddress=1; 98byte AlarmTimeEEPROMAddress=2;//3,4,5 99byte AlarmArmedEEPROMAddress=6; 100 101//buttons pins declarations 102ClickButton setButton(pinSet, LOW, CLICKBTN_PULLUP); 103ClickButton upButton(pinUp, LOW, CLICKBTN_PULLUP); 104ClickButton downButton(pinDown, LOW, CLICKBTN_PULLUP); 105/////////////////// 106 107Tone tone1; 108#define isdigit(n) (n >= '0' && n <= '9') 109//char *song = "MissionImp:d=16,o=6,b=95:32d,32d#,32d,32d#,32d,32d#,32d,32d#,32d,32d,32d#,32e,32f,32f#,32g,g,8p,g,8p,a#,p,c7,p,g,8p,g,8p,f,p,f#,p,g,8p,g,8p,a#,p,c7,p,g,8p,g,8p,f,p,f#,p,a#,g,2d,32p,a#,g,2c#,32p,a#,g,2c,a#5,8c,2p,32p,a#5,g5,2f#,32p,a#5,g5,2f,32p,a#5,g5,2e,d#,8d"; 110char *song = "PinkPanther:d=4,o=5,b=160:8d#,8e,2p,8f#,8g,2p,8d#,8e,16p,8f#,8g,16p,8c6,8b,16p,8d#,8e,16p,8b,2a#,2p,16a,16g,16e,16d,2e"; 111//char *song="VanessaMae:d=4,o=6,b=70:32c7,32b,16c7,32g,32p,32g,32p,32d#,32p,32d#,32p,32c,32p,32c,32p,32c7,32b,16c7,32g#,32p,32g#,32p,32f,32p,16f,32c,32p,32c,32p,32c7,32b,16c7,32g,32p,32g,32p,32d#,32p,32d#,32p,32c,32p,32c,32p,32g,32f,32d#,32d,32c,32d,32d#,32c,32d#,32f,16g,8p,16d7,32c7,32d7,32a#,32d7,32a,32d7,32g,32d7,32d7,32p,32d7,32p,32d7,32p,16d7,32c7,32d7,32a#,32d7,32a,32d7,32g,32d7,32d7,32p,32d7,32p,32d7,32p,32g,32f,32d#,32d,32c,32d,32d#,32c,32d#,32f,16c"; 112//char *song="DasBoot:d=4,o=5,b=100:d#.4,8d4,8c4,8d4,8d#4,8g4,a#.4,8a4,8g4,8a4,8a#4,8d,2f.,p,f.4,8e4,8d4,8e4,8f4,8a4,c.,8b4,8a4,8b4,8c,8e,2g.,2p"; 113//char *song="Scatman:d=4,o=5,b=200:8b,16b,32p,8b,16b,32p,8b,2d6,16p,16c#.6,16p.,8d6,16p,16c#6,8b,16p,8f#,2p.,16c#6,8p,16d.6,16p.,16c#6,16b,8p,8f#,2p,32p,2d6,16p,16c#6,8p,16d.6,16p.,16c#6,16a.,16p.,8e,2p.,16c#6,8p,16d.6,16p.,16c#6,16b,8p,8b,16b,32p,8b,16b,32p,8b,2d6,16p,16c#.6,16p.,8d6,16p,16c#6,8b,16p,8f#,2p.,16c#6,8p,16d.6,16p.,16c#6,16b,8p,8f#,2p,32p,2d6,16p,16c#6,8p,16d.6,16p.,16c#6,16a.,16p.,8e,2p.,16c#6,8p,16d.6,16p.,16c#6,16a,8p,8e,2p,32p,16f#.6,16p.,16b.,16p."; 114//char *song="Popcorn:d=4,o=5,b=160:8c6,8a#,8c6,8g,8d#,8g,c,8c6,8a#,8c6,8g,8d#,8g,c,8c6,8d6,8d#6,16c6,8d#6,16c6,8d#6,8d6,16a#,8d6,16a#,8d6,8c6,8a#,8g,8a#,c6"; 115//char *song="WeWishYou:d=4,o=5,b=200:d,g,8g,8a,8g,8f#,e,e,e,a,8a,8b,8a,8g,f#,d,d,b,8b,8c6,8b,8a,g,e,d,e,a,f#,2g,d,g,8g,8a,8g,8f#,e,e,e,a,8a,8b,8a,8g,f#,d,d,b,8b,8c6,8b,8a,g,e,d,e,a,f#,1g,d,g,g,g,2f#,f#,g,f#,e,2d,a,b,8a,8a,8g,8g,d6,d,d,e,a,f#,2g"; 116#define OCTAVE_OFFSET 0 117char *p; 118 119int notes[] = { 0, 120NOTE_C4, NOTE_CS4, NOTE_D4, NOTE_DS4, NOTE_E4, NOTE_F4, NOTE_FS4, NOTE_G4, NOTE_GS4, NOTE_A4, NOTE_AS4, NOTE_B4, 121NOTE_C5, NOTE_CS5, NOTE_D5, NOTE_DS5, NOTE_E5, NOTE_F5, NOTE_FS5, NOTE_G5, NOTE_GS5, NOTE_A5, NOTE_AS5, NOTE_B5, 122NOTE_C6, NOTE_CS6, NOTE_D6, NOTE_DS6, NOTE_E6, NOTE_F6, NOTE_FS6, NOTE_G6, NOTE_GS6, NOTE_A6, NOTE_AS6, NOTE_B6, 123NOTE_C7, NOTE_CS7, NOTE_D7, NOTE_DS7, NOTE_E7, NOTE_F7, NOTE_FS7, NOTE_G7, NOTE_GS7, NOTE_A7, NOTE_AS7, NOTE_B7 124}; 125 126int fireforks[]={0,0,1,//1 127 -1,0,0,//2 128 0,1,0,//3 129 0,0,-1,//4 130 1,0,0,//5 131 0,-1,0}; //array with RGB rules (0 - do nothing, -1 - decrese, +1 - increse 132 133void setRTCDateTime(byte h, byte m, byte s, byte d, byte mon, byte y, byte w=1); 134 135int functionDownButton=0; 136int functionUpButton=0; 137 138/******************************************************************************************************* 139Init Programm 140*******************************************************************************************************/ 141void setup() 142{ 143 digitalWrite(DHVpin, LOW); // off MAX1771 Driver Hight Voltage(DHV) 110-220V 144 145 Wire.begin(); 146 //setRTCDateTime(23,40,00,25,7,15,1); 147 148 Serial.begin(115200); 149 Serial.println(""); 150 151 if (EEPROM.read(HourFormatEEPROMAddress)!=12) value[hModeValueIndex]=24; else value[hModeValueIndex]=12; 152 if (EEPROM.read(RGBLEDsEEPROMAddress)!=0) RGBLedsOn=true; else RGBLedsOn=false; 153 if (EEPROM.read(AlarmTimeEEPROMAddress)==255) value[AlarmHourIndex]=0; else value[AlarmHourIndex]=EEPROM.read(AlarmTimeEEPROMAddress); 154 if (EEPROM.read(AlarmTimeEEPROMAddress+1)==255) value[AlarmMinuteIndex]=0; else value[AlarmMinuteIndex]=EEPROM.read(AlarmTimeEEPROMAddress+1); 155 if (EEPROM.read(AlarmTimeEEPROMAddress+2)==255) value[AlarmSecondIndex]=0; else value[AlarmSecondIndex]=EEPROM.read(AlarmTimeEEPROMAddress+2); 156 if (EEPROM.read(AlarmArmedEEPROMAddress)==255) value[Alarm01]=0; else value[Alarm01]=EEPROM.read(AlarmArmedEEPROMAddress); 157 158 tone1.begin(pinBuzzer); 159 song=parseSong(song); 160 161 pinMode(LEpin, OUTPUT); 162 pinMode(DHVpin, OUTPUT); 163 164 pinMode(RedLedPin, OUTPUT); 165 pinMode(GreenLedPin, OUTPUT); 166 pinMode(BlueLedPin, OUTPUT); 167 168 169 // SPI setup 170 171 SPI.begin(); // 172 SPI.setDataMode (SPI_MODE3); // Mode 3 SPI 173 SPI.setClockDivider(SPI_CLOCK_DIV128); // SCK = 16MHz/128= 125kHz 174 175 //buttons pins inits 176 pinMode(pinSet, INPUT_PULLUP); 177 pinMode(pinUp, INPUT_PULLUP); 178 pinMode(pinDown, INPUT_PULLUP); 179 //////////////////////////// 180 pinMode(pinBuzzer, OUTPUT); 181 182 //buttons objects inits 183 setButton.debounceTime = 20; // Debounce timer in ms 184 setButton.multiclickTime = 30; // Time limit for multi clicks 185 setButton.longClickTime = 2000; // time until "held-down clicks" register 186 187 upButton.debounceTime = 20; // Debounce timer in ms 188 upButton.multiclickTime = 30; // Time limit for multi clicks 189 upButton.longClickTime = 2000; // time until "held-down clicks" register 190 191 downButton.debounceTime = 20; // Debounce timer in ms 192 downButton.multiclickTime = 30; // Time limit for multi clicks 193 downButton.longClickTime = 2000; // time until "held-down clicks" register 194 195 // 196 digitalWrite(DHVpin, HIGH); // on MAX1771 Driver Hight Voltage(DHV) 110-220V 197 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 198 //doTest(); 199 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 200 getRTCTime(); 201 setTime(RTC_hours, RTC_minutes, RTC_seconds, RTC_day, RTC_month, RTC_year); 202 digitalWrite(DHVpin, LOW); // off MAX1771 Driver Hight Voltage(DHV) 110-220V 203 setRTCDateTime(RTC_hours,RTC_minutes,RTC_seconds,RTC_day,RTC_month,RTC_year,1); //���������� ������ ��� ��������� ����� � RTC ����� ��������� ����� ���������� 204 digitalWrite(DHVpin, HIGH); // on MAX1771 Driver Hight Voltage(DHV) 110-220V 205 //p=song; 206} 207 208void rotateLeft(uint8_t &bits) 209{ 210 uint8_t high_bit = bits & (1 << 7) ? 1 : 0; 211 bits = (bits << 1) | high_bit; 212} 213 214int rotator=0; //index in array with RGB "rules" (increse by one on each 255 cycles) 215int cycle=0; //cycles counter 216int RedLight=255; 217int GreenLight=0; 218int BlueLight=0; 219unsigned long prevTime=0; // time of lase tube was lit 220unsigned long prevTime4FireWorks=0; //time of last RGB changed 221//int minuteL=0; //������� ����� ����� 222 223/*************************************************************************************************************** 224MAIN Programm 225***************************************************************************************************************/ 226void loop() { 227 228 p=playmusic(p); 229 230 if ((millis()-prevTime4FireWorks)>5) 231 { 232 rotateFireWorks(); //change color (by 1 step) 233 prevTime4FireWorks=millis(); 234 } 235 236 doIndication(); 237 238 setButton.Update(); 239 upButton.Update(); 240 downButton.Update(); 241 if (editMode==false) 242 { 243 blinkMask=B00000000; 244 245 } else if ((millis()-enteringEditModeTime)>60000) 246 { 247 editMode=false; 248 menuPosition=firstChild[menuPosition]; 249 blinkMask=blinkPattern[menuPosition]; 250 } 251 if (setButton.clicks>0) //short click 252 { 253 p=0; //shut off music ))) 254 tone1.play(1000,100); 255 enteringEditModeTime=millis(); 256 menuPosition=menuPosition+1; 257 if (menuPosition==hModeIndex+1) menuPosition=TimeIndex; 258 Serial.print(F("menuPosition=")); 259 Serial.println(menuPosition); 260 Serial.print(F("value=")); 261 Serial.println(value[menuPosition]); 262 263 blinkMask=blinkPattern[menuPosition]; 264 if ((parent[menuPosition-1]!=0) and (lastChild[parent[menuPosition-1]-1]==(menuPosition-1))) 265 { 266 if ((parent[menuPosition-1]-1==1) && (!isValidDate())) 267 { 268 menuPosition=DateDayIndex; 269 return; 270 } 271 editMode=false; 272 menuPosition=parent[menuPosition-1]-1; 273 if (menuPosition==TimeIndex) setTime(value[TimeHoursIndex], value[TimeMintuesIndex], value[TimeSecondsIndex], day(), month(), year()); 274 if (menuPosition==DateIndex) setTime(hour(), minute(), second(),value[DateDayIndex], value[DateMonthIndex], 2000+value[DateYearIndex]); 275 if (menuPosition==AlarmIndex) {EEPROM.write(AlarmTimeEEPROMAddress,value[AlarmHourIndex]); EEPROM.write(AlarmTimeEEPROMAddress+1,value[AlarmMinuteIndex]); EEPROM.write(AlarmTimeEEPROMAddress+2,value[AlarmSecondIndex]); EEPROM.write(AlarmArmedEEPROMAddress, value[Alarm01]);}; 276 if (menuPosition==hModeIndex) EEPROM.write(HourFormatEEPROMAddress, value[hModeValueIndex]); 277 digitalWrite(DHVpin, LOW); // off MAX1771 Driver Hight Voltage(DHV) 110-220V 278 setRTCDateTime(hour(),minute(),second(),day(),month(),year()%1000,1); 279 digitalWrite(DHVpin, HIGH); // on MAX1771 Driver Hight Voltage(DHV) 110-220V 280 } 281 value[menuPosition]=extractDigits(blinkMask); 282 } 283 if (setButton.clicks<0) //long click 284 { 285 tone1.play(1000,100); 286 if (!editMode) 287 { 288 enteringEditModeTime=millis(); 289 if (menuPosition==TimeIndex) stringToDisplay=PreZero(hour())+PreZero(minute())+PreZero(second()); //temporary enabled 24 hour format while settings 290 } 291 menuPosition=firstChild[menuPosition]; 292 if (menuPosition==AlarmHourIndex) {value[Alarm01]=1; /*digitalWrite(pinUpperDots, HIGH);*/dotPattern=B10000000;} 293 editMode=!editMode; 294 blinkMask=blinkPattern[menuPosition]; 295 value[menuPosition]=extractDigits(blinkMask); 296 } 297 298 if (upButton.clicks != 0) functionUpButton = upButton.clicks; 299 300 if (upButton.clicks>0) 301 { 302 p=0; //shut off music ))) 303 tone1.play(1000,100); 304 incrementValue(); 305 } 306 307 if (functionUpButton == -1 && upButton.depressed == true) 308 { 309 BlinkUp=false; 310 if (editMode==true) 311 { 312 if ( (millis() - upTime) > settingDelay) 313 { 314 upTime = millis();// + settingDelay; 315 incrementValue(); 316 } 317 } 318 } else BlinkUp=true; 319 320 if (downButton.clicks != 0) functionDownButton = downButton.clicks; 321 322 if (downButton.clicks>0) 323 { 324 p=0; //shut off music ))) 325 tone1.play(1000,100); 326 dicrementValue(); 327 } 328 329 if (functionDownButton == -1 && downButton.depressed == true) 330 { 331 BlinkDown=false; 332 if (editMode==true) 333 { 334 if ( (millis() - downTime) > settingDelay) 335 { 336 downTime = millis();// + settingDelay; 337 dicrementValue(); 338 } 339 } 340 } else BlinkDown=true; 341 342 if (!editMode) 343 { 344 if (upButton.clicks<0) 345 { 346 tone1.play(1000,100); 347 RGBLedsOn=true; 348 EEPROM.write(RGBLEDsEEPROMAddress,1); 349 Serial.println("RGB=on"); 350 } 351 if (downButton.clicks<0) 352 { 353 tone1.play(1000,100); 354 RGBLedsOn=false; 355 EEPROM.write(RGBLEDsEEPROMAddress,0); 356 Serial.println("RGB=off"); 357 } 358 } 359 360 361 static bool updateDateTime=false; 362 switch (menuPosition) 363 { 364 case TimeIndex: //time mode 365 stringToDisplay=updateDisplayString(); 366 doDotBlink(); 367 checkAlarmTime(); 368 break; 369 case DateIndex: //date mode 370 stringToDisplay=PreZero(day())+PreZero(month())+PreZero(year()%1000); 371 dotPattern=B01000000;//turn on lower dots 372 /*digitalWrite(pinUpperDots, LOW); 373 digitalWrite(pinLowerDots, HIGH);*/ 374 checkAlarmTime(); 375 break; 376 case AlarmIndex: //alarm mode 377 stringToDisplay=PreZero(value[AlarmHourIndex])+PreZero(value[AlarmMinuteIndex])+PreZero(value[AlarmSecondIndex]); 378 if (value[Alarm01]==1) /*digitalWrite(pinUpperDots, HIGH);*/ dotPattern=B10000000; //turn on upper dots 379 else 380 { 381 /*digitalWrite(pinUpperDots, LOW); 382 digitalWrite(pinLowerDots, LOW);*/ 383 dotPattern=B00000000; //turn off upper dots 384 } 385 checkAlarmTime(); 386 break; 387 case hModeIndex: //12/24 hours mode 388 stringToDisplay="00"+String(value[hModeValueIndex])+"00"; 389 dotPattern=B00000000;//turn off all dots 390 /*digitalWrite(pinUpperDots, LOW); 391 digitalWrite(pinLowerDots, LOW);*/ 392 checkAlarmTime(); 393 break; 394 } 395} 396 397String PreZero(int digit) 398{ 399 if (digit<10) return String("0")+String(digit); 400 else return String(digit); 401} 402 403void rotateFireWorks() 404{ 405 if (!RGBLedsOn) 406 { 407 analogWrite(RedLedPin,0 ); 408 analogWrite(GreenLedPin,0); 409 analogWrite(BlueLedPin,0); 410 return; 411 } 412 RedLight=RedLight+fireforks[rotator*3]; 413 GreenLight=GreenLight+fireforks[rotator*3+1]; 414 BlueLight=BlueLight+fireforks[rotator*3+2]; 415 analogWrite(RedLedPin,RedLight ); 416 analogWrite(GreenLedPin,GreenLight); 417 analogWrite(BlueLedPin,BlueLight); 418 cycle=cycle+1; 419 if (cycle==255) 420 { 421 rotator=rotator+1; 422 cycle=0; 423 } 424 if (rotator>5) rotator=0; 425} 426 427 428void doIndication() 429{ 430 431 //static byte b=B00000001; 432 433 static unsigned long lastTimeInterval1Started; 434 if ((micros()-lastTimeInterval1Started)<fpsLimit) return; 435 //if (menuPosition==TimeIndex) doDotBlink(); 436 lastTimeInterval1Started=micros(); 437 438 digitalWrite(LEpin, HIGH); // allow data input (Transparent mode) 439 440 /* 441 SPI.transfer((b|dotPattern) & doEditBlink()); // anode 442 SPI.transfer(highBytesArray[stringToDisplay.substring(curTube,curTube+1).toInt()]); 443 SPI.transfer(lowBytesArray[stringToDisplay.substring(curTube,curTube+1).toInt()]); 444 */ 445 446 // 0 1 2 3 4 5 6 7 8 9 447 //long mass1[10]={B1111111111111110, B1111111111111101, B1111111111111011, B1111111111110111, B1111111111101111, B1111111111011111, B1111111110111111, B1111111101111111, B1111111011111111, B1111110111111111}; 448 //long mass2[10]={B1111111111111110, B1111110111111111, B1111111011111111, B1111111101111111, B1111111110111111, B1111111111011111, B1111111111101111, B1111111111110111, B1111111111111011, B1111111111111101}; // used only shiled ver 1.0 //for some hardware bug in wiring 449 450 // 0 1 2 3 4 5 6 7 8 9 451 word mass1[10]={65534, 65533, 65531, 65527, 65519, 65503, 65471, 65407, 65279, 65023}; 452 word mass2[10]={65534, 65023, 65279, 65407, 65471, 65503, 65519, 65527, 65531, 65533}; // used only shiled ver 1.0 //for some hardware bug in wiring 453 454 unsigned long long Var64=0; 455 unsigned long long tmpVar64=0; 456 457 long digits=stringToDisplay.toInt(); 458 459 Var64=~Var64; 460 tmpVar64=~tmpVar64; 461 462 Var64=Var64&((mass2[digits%10]|doEditBlink(5))<<6); 463 Var64=Var64<<48; 464 digits=digits/10; 465 466 tmpVar64=(mass1[digits%10]|doEditBlink(4))<<6; 467 Var64|=(tmpVar64<<38); 468 digits=digits/10; 469 470 tmpVar64=(mass2[digits%10]|doEditBlink(3))<<6; 471 Var64|=(tmpVar64<<28); 472 digits=digits/10; 473 474 tmpVar64=(mass1[digits%10]|doEditBlink(2))<<6; 475 Var64|=(tmpVar64<<18); 476 digits=digits/10; 477 478 tmpVar64=(mass2[digits%10]|doEditBlink(1))<<6; 479 Var64|=(tmpVar64<<8); 480 digits=digits/10; 481 482 tmpVar64=(mass1[digits%10]|doEditBlink(0))<<6>>2; 483 Var64|=tmpVar64; 484 485 Var64=(Var64>>4); 486 487 unsigned int iTmp=0; 488 489 iTmp=Var64>>56; 490 SPI.transfer(iTmp); 491 iTmp=Var64>>48; 492 SPI.transfer(iTmp); 493 iTmp=Var64>>40; 494 SPI.transfer(iTmp); 495 iTmp=Var64>>32; 496 SPI.transfer(iTmp); 497 iTmp=Var64>>24; 498 SPI.transfer(iTmp); 499 iTmp=Var64>>16; 500 SPI.transfer(iTmp); 501 iTmp=Var64>>8; 502 SPI.transfer(iTmp); 503 iTmp=Var64; 504 SPI.transfer(iTmp); 505 506 digitalWrite(LEpin, LOW); // latching data 507} 508 509byte CheckButtonsState() 510{ 511 static boolean buttonsWasChecked; 512 static unsigned long startBuzzTime; 513 static unsigned long lastTimeButtonsPressed; 514 if ((digitalRead(pinSet)==0)||(digitalRead(pinUp)==0)||(digitalRead(pinDown)==0)) 515 { 516 if (buttonsWasChecked==false) startBuzzTime=millis(); 517 buttonsWasChecked=true; 518 } else buttonsWasChecked=false; 519 if (millis()-startBuzzTime<30) 520 { 521 digitalWrite(pinBuzzer, HIGH); 522 } else 523 { 524 digitalWrite(pinBuzzer, LOW); 525 } 526} 527 528String updateDisplayString() 529{ 530 static unsigned long lastTimeStringWasUpdated; 531 if ((millis()-lastTimeStringWasUpdated)>1000) 532 { 533 //Serial.println("doDotBlink"); 534 //doDotBlink(); 535 lastTimeStringWasUpdated=millis(); 536 if (value[hModeValueIndex]==24) return PreZero(hour())+PreZero(minute())+PreZero(second()); 537 else return PreZero(hourFormat12())+PreZero(minute())+PreZero(second()); 538 539 } 540 return stringToDisplay; 541} 542 543void doTest() 544{ 545 Serial.print(F("Firmware version: ")); 546 Serial.println(FirmwareVersion.substring(1,2)+"."+FirmwareVersion.substring(2,4)); 547 Serial.println(F("Start Test")); 548 int adc=analogRead(A3); 549 float Uinput=4.6*(5.0*adc)/1024.0+0.7; 550 Serial.print(F("U input=")); 551 Serial.print(Uinput); 552 553 p=song; 554 parseSong(p); 555 556 analogWrite(RedLedPin,255); 557 delay(1000); 558 analogWrite(RedLedPin,0); 559 analogWrite(GreenLedPin,255); 560 delay(1000); 561 analogWrite(GreenLedPin,0); 562 analogWrite(BlueLedPin,255); 563 delay(1000); 564 //while(1); 565 566 String testStringArray[12]={"000000","111111","222222","333333","444444","555555","666666","777777","888888","999999","",""}; 567 568 if (Uinput<10) testStringArray[10]="000"+String(int(Uinput*100)); else testStringArray[10]="00"+String(int(Uinput*100)); 569 testStringArray[11]=FirmwareVersion; 570 571 int dlay=500; 572 bool test=1; 573 byte strIndex=0; 574 unsigned long startOfTest=millis(); 575 for (int i=0; i<12; i++) 576 { 577 if ((millis()-startOfTest)>dlay) 578 { 579 startOfTest=millis(); 580 strIndex=strIndex+1; 581 if (strIndex==10) dlay=3000; 582 if (strIndex==12) test=0; 583 584 switch (strIndex) 585 { 586 /* 587 case 10: SPI.transfer((b|B01000000)&B11111100); 588 break; 589 case 11: SPI.transfer((b|B01000000)&B11001110); 590 break; 591 */ 592 //default: SPI.transfer(b|B11000000); 593 default: stringToDisplay=testStringArray[strIndex]; 594 } 595 } 596 597 delayMicroseconds(2000); 598 }; 599 600 Serial.println(F("Stop Test")); 601 602} 603 604void doDotBlink() 605{ 606 static unsigned long lastTimeBlink=millis(); 607 static bool dotState=0; 608 if ((millis()-lastTimeBlink)>1000) 609 { 610 lastTimeBlink=millis(); 611 dotState=!dotState; 612 if (dotState) 613 { 614 dotPattern=B11000000; 615 /*digitalWrite(pinUpperDots, HIGH); 616 digitalWrite(pinLowerDots, HIGH);*/ 617 } 618 else 619 { 620 dotPattern=B00000000; 621 /*digitalWrite(pinUpperDots, LOW); 622 digitalWrite(pinLowerDots, LOW);*/ 623 } 624 } 625} 626 627void setRTCDateTime(byte h, byte m, byte s, byte d, byte mon, byte y, byte w) 628{ 629 Wire.beginTransmission(DS1307_ADDRESS); 630 Wire.write(zero); //stop Oscillator 631 632 Wire.write(decToBcd(s)); 633 Wire.write(decToBcd(m)); 634 Wire.write(decToBcd(h)); 635 Wire.write(decToBcd(w)); 636 Wire.write(decToBcd(d)); 637 Wire.write(decToBcd(mon)); 638 Wire.write(decToBcd(y)); 639 640 Wire.write(zero); //start 641 642 Wire.endTransmission(); 643 644} 645 646byte decToBcd(byte val){ 647// Convert normal decimal numbers to binary coded decimal 648 return ( (val/10*16) + (val%10) ); 649} 650 651byte bcdToDec(byte val) { 652// Convert binary coded decimal to normal decimal numbers 653 return ( (val/16*10) + (val%16) ); 654} 655 656void getRTCTime() 657{ 658 Wire.beginTransmission(DS1307_ADDRESS); 659 Wire.write(zero); 660 Wire.endTransmission(); 661 662 Wire.requestFrom(DS1307_ADDRESS, 7); 663 664 RTC_seconds = bcdToDec(Wire.read()); 665 RTC_minutes = bcdToDec(Wire.read()); 666 RTC_hours = bcdToDec(Wire.read() & 0b111111); //24 hour time 667 RTC_day_of_week = bcdToDec(Wire.read()); //0-6 -> sunday - Saturday 668 RTC_day = bcdToDec(Wire.read()); 669 RTC_month = bcdToDec(Wire.read()); 670 RTC_year = bcdToDec(Wire.read()); 671} 672 673word doEditBlink(int pos) 674{ 675 if (!BlinkUp) return 0; 676 if (!BlinkDown) return 0; 677 678 int lowBit=blinkMask>>pos; 679 lowBit=lowBit&B00000001; 680 681 static unsigned long lastTimeEditBlink=millis(); 682 static bool blinkState=false; 683 word mask=0; 684 static int tmp=0;//blinkMask; 685 if ((millis()-lastTimeEditBlink)>300) 686 { 687 lastTimeEditBlink=millis(); 688 blinkState=!blinkState; 689 /*Serial.print("blinkpattern= "); 690 Serial.println(blinkPattern[menuPosition]); 691 if (((blinkPattern[menuPosition]>>8)&1==1) && blinkState==true) digitalWrite(pinLowerDots, HIGH); 692 else digitalWrite(pinLowerDots, LOW); 693 if (((blinkPattern[menuPosition]>>7)&1==1) && blinkState==true) digitalWrite(pinUpperDots, HIGH); 694 else digitalWrite(pinUpperDots, LOW); 695 */ 696 if (blinkState) tmp= 0; 697 else tmp=blinkMask; 698 } 699 if (((dotPattern&~tmp)>>6)&1==1) digitalWrite(pinLowerDots, HIGH); 700 else digitalWrite(pinLowerDots, LOW); 701 if (((dotPattern&~tmp)>>7)&1==1) digitalWrite(pinUpperDots, HIGH); 702 else digitalWrite(pinUpperDots, LOW); 703 704 if ((blinkState==true) && (lowBit==1)) mask=0xFFFF;//mask=B11111111; 705 return mask; 706} 707 708int extractDigits(byte b) 709{ 710 String tmp="1"; 711 /*Serial.print("blink pattern= "); 712 Serial.println(b); 713 Serial.print("stringToDisplay= "); 714 Serial.println(stringToDisplay);*/ 715 if (b==B00000011) 716 { 717 tmp=stringToDisplay.substring(0,2); 718 /*Serial.print("stringToDisplay1= "); 719 Serial.println(stringToDisplay);*/ 720 } 721 if (b==B00001100) 722 { 723 tmp=stringToDisplay.substring(2,4); 724 /*Serial.print("stringToDisplay2= "); 725 Serial.println(stringToDisplay);*/ 726 } 727 if (b==B00110000) 728 { 729 tmp=stringToDisplay.substring(4); 730 /*Serial.print("stringToDisplay3= "); 731 Serial.println(stringToDisplay);*/ 732 } 733 /*Serial.print("stringToDisplay4= "); 734 Serial.println(stringToDisplay);*/ 735 return tmp.toInt(); 736} 737 738void injectDigits(byte b, int value) 739{ 740 if (b==B00000011) stringToDisplay=PreZero(value)+stringToDisplay.substring(2); 741 if (b==B00001100) stringToDisplay=stringToDisplay.substring(0,2)+PreZero(value)+stringToDisplay.substring(4); 742 if (b==B00110000) stringToDisplay=stringToDisplay.substring(0,4)+PreZero(value); 743} 744 745bool isValidDate() 746{ 747 int days[12]={31,28,31,30,31,30,31,31,30,31,30,31}; 748 if (value[DateYearIndex]%4==0) days[1]=29; 749 if (value[DateDayIndex]>days[value[DateMonthIndex]-1]) return false; 750 else return true; 751 752} 753 754byte default_dur = 4; 755byte default_oct = 6; 756int bpm = 63; 757int num; 758long wholenote; 759long duration; 760byte note; 761byte scale; 762char* parseSong(char *p) 763{ 764 // Absolutely no error checking in here 765 // format: d=N,o=N,b=NNN: 766 // find the start (skip name, etc) 767 768 while(*p != ':') p++; // ignore name 769 p++; // skip ':' 770 771 // get default duration 772 if(*p == 'd') 773 { 774 p++; p++; // skip "d=" 775 num = 0; 776 while(isdigit(*p)) 777 { 778 num = (num * 10) + (*p++ - '0'); 779 } 780 if(num > 0) default_dur = num; 781 p++; // skip comma 782 } 783 784 // get default octave 785 if(*p == 'o') 786 { 787 p++; p++; // skip "o=" 788 num = *p++ - '0'; 789 if(num >= 3 && num <=7) default_oct = num; 790 p++; // skip comma 791 } 792 793 // get BPM 794 if(*p == 'b') 795 { 796 p++; p++; // skip "b=" 797 num = 0; 798 while(isdigit(*p)) 799 { 800 num = (num * 10) + (*p++ - '0'); 801 } 802 bpm = num; 803 p++; // skip colon 804 } 805 806 // BPM usually expresses the number of quarter notes per minute 807 wholenote = (60 * 1000L / bpm) * 4; // this is the time for whole note (in milliseconds) 808 return p; 809} 810 811 // now begin note loop 812 static unsigned long lastTimeNotePlaying=0; 813 char* playmusic(char *p) 814 { 815 if(*p==0) 816 { 817 return p; 818 } 819 if (millis()-lastTimeNotePlaying>duration) 820 lastTimeNotePlaying=millis(); 821 else return p; 822 // first, get note duration, if available 823 num = 0; 824 while(isdigit(*p)) 825 { 826 num = (num * 10) + (*p++ - '0'); 827 } 828 829 if(num) duration = wholenote / num; 830 else duration = wholenote / default_dur; // we will need to check if we are a dotted note after 831 832 // now get the note 833 note = 0; 834 835 switch(*p) 836 { 837 case 'c': 838 note = 1; 839 break; 840 case 'd': 841 note = 3; 842 break; 843 case 'e': 844 note = 5; 845 break; 846 case 'f': 847 note = 6; 848 break; 849 case 'g': 850 note = 8; 851 break; 852 case 'a': 853 note = 10; 854 break; 855 case 'b': 856 note = 12; 857 break; 858 case 'p': 859 default: 860 note = 0; 861 } 862 p++; 863 864 // now, get optional '#' sharp 865 if(*p == '#') 866 { 867 note++; 868 p++; 869 } 870 871 // now, get optional '.' dotted note 872 if(*p == '.') 873 { 874 duration += duration/2; 875 p++; 876 } 877 878 // now, get scale 879 if(isdigit(*p)) 880 { 881 scale = *p - '0'; 882 p++; 883 } 884 else 885 { 886 scale = default_oct; 887 } 888 889 scale += OCTAVE_OFFSET; 890 891 if(*p == ',') 892 p++; // skip comma for next note (or we may be at the end) 893 894 // now play the note 895 896 if(note) 897 { 898 tone1.play(notes[(scale - 4) * 12 + note], duration); 899 if (millis()-lastTimeNotePlaying>duration) 900 lastTimeNotePlaying=millis(); 901 else return p; 902 tone1.stop(); 903 } 904 else 905 { 906 return p; 907 } 908 Serial.println(F("Incorrect Song Format!")); 909 return 0; //error 910 } 911 912 913void incrementValue() 914 { 915 enteringEditModeTime=millis(); 916 if (editMode==true) 917 { 918 if(menuPosition!=hModeValueIndex) // 12/24 hour mode menu position 919 value[menuPosition]=value[menuPosition]+1; else value[menuPosition]=value[menuPosition]+12; 920 if (value[menuPosition]>maxValue[menuPosition]) value[menuPosition]=minValue[menuPosition]; 921 if (menuPosition==Alarm01) 922 { 923 if (value[menuPosition]==1) /*digitalWrite(pinUpperDots, HIGH);*/dotPattern=B10000000;//turn on all dots 924 /*else digitalWrite(pinUpperDots, LOW); */ dotPattern=B00000000; //turn off all dots 925 } 926 injectDigits(blinkMask, value[menuPosition]); 927 } 928 } 929 930void dicrementValue() 931{ 932 enteringEditModeTime=millis(); 933 if (editMode==true) 934 { 935 if (menuPosition!=hModeValueIndex) value[menuPosition]=value[menuPosition]-1; else value[menuPosition]=value[menuPosition]-12; 936 if (value[menuPosition]<minValue[menuPosition]) value[menuPosition]=maxValue[menuPosition]; 937 if (menuPosition==Alarm01) 938 { 939 if (value[menuPosition]==1) /*digitalWrite(pinUpperDots, HIGH);*/ dotPattern=B10000000;//turn on upper dots �������� ������� ����� 940 else /*digitalWrite(pinUpperDots, LOW);*/ dotPattern=B00000000; //turn off upper dots 941 } 942 injectDigits(blinkMask, value[menuPosition]); 943 } 944} 945 946bool Alarm1SecondBlock=false; 947unsigned long lastTimeAlarmTriggired=0; 948void checkAlarmTime() 949{ 950 if (value[Alarm01]==0) return; 951 if ((Alarm1SecondBlock==true) && ((millis()-lastTimeAlarmTriggired)>1000)) Alarm1SecondBlock=false; 952 if (Alarm1SecondBlock==true) return; 953 if ((hour()==value[AlarmHourIndex]) && (minute()==value[AlarmMinuteIndex]) && (second()==value[AlarmSecondIndex])) 954 { 955 lastTimeAlarmTriggired=millis(); 956 Alarm1SecondBlock=true; 957 Serial.println(F("Wake up, Neo!")); 958 p=song; 959 } 960} 961 962
Downloadable files
Scheme Nixie Tubes Clock IN-14 SHIELD NCS314 v2.0
Scheme Nixie Tubes Clock IN-14 SHIELD NCS314 v2.0

Scheme Nixie Tubes Clock IN-14 SHIELD NCS314 v1.2
Scheme Nixie Tubes Clock IN-14 SHIELD NCS314 v1.2

Scheme Nixie Tubes Clock IN-12 SHIELD NCS312 v1.2
Scheme Nixie Tubes Clock IN-12 SHIELD NCS312 v1.2

Scheme Nixie Tubes Clock IN-14 SHIELD NCS314 v2.0
Scheme Nixie Tubes Clock IN-14 SHIELD NCS314 v2.0

Scheme Nixie Tubes Clock IN-14 SHIELD NCS314 v1.2
Scheme Nixie Tubes Clock IN-14 SHIELD NCS314 v1.2

Scheme Nixie Tubes Clock IN-12 SHIELD NCS312 v1.2
Scheme Nixie Tubes Clock IN-12 SHIELD NCS312 v1.2

Comments
Only logged in users can leave comments