Skip to content

Commit 6371018

Browse files
committed
Finish alarm; night-off and day-off; un-off (briefly light dark tubes); timer interval mode. (All untested)
1 parent 01b4fbe commit 6371018

File tree

2 files changed

+88
-47
lines changed

2 files changed

+88
-47
lines changed

README.md

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@ _In these instructions, **Select** is the main pushbutton, and **Adjust** can be
1414

1515
| Function | Looks like | Notes |
1616
| --- | --- | --- |
17-
| **Time** | `12 34 56` | The time of day. You can choose 12h or 24h format in Options. When setting, it's in 24h format (so you can tell AM from PM) and the seconds will reset to :00 when you save. The clock keeps time during power outages, and its timekeeping is corrected for temperature changes. |
17+
| **Time** | `12 34 56` | The time of day. You can choose 12h or 24h format in Options. When setting, it's in 24h format (so you can tell AM from PM) and the seconds will reset to :00 when you save. The clock keeps time during power outages and compensates for temperature effects. |
1818
| **Date** | `_2 _4 _0`<br/>(for&nbsp;Sun&nbsp;2/4) | You can choose month/date or date/month format in the options menu (2). Setting is done in three stages: first year, then month, then date.<br/>Weekdays are: 0=Sun, 1=Mon, 2=Tue, 3=Wed, 4=Thu, 5=Fri, 6=Sat |
19-
| **Timer** | `__ __ _0` | A countdown timer, in hours, minutes, and seconds; or `0` when stopped. Can be set to the minute, up to 18 hours. Begins running as soon as you set it, and will continue to run in the background if you change to a different function. To cancel while running, hold **Select**. When timer runs out, press **Select** to silence the beeper. If power is lost, the timer will reset to `0`. |
20-
| **Day counter** | `_1 23 __` | Shows the number of days until/since a date you specify. The target date is set the same way as **Date.** |
19+
| **Alarm** | `_7 00 1_` | Shows alarm time (always in 24hr format) and on/off status on 5th tube (1=on, 0=off) and by display brightness (bright=on, dim=off). Use **Adjust** to switch on/off. Hold **Select** to set time (same way as **Time**). When alarm sounds, press **Select** to snooze, or hold for 1sec (followed by a short beep) to silence the alarm for the day. Options menu lets you restrict the alarm to your workweek or weekend only. In a power outage, the alarm will remain set, but it will not sound if power is disconnected at alarm time. |
20+
| **Timer** | `__ __ _0` | A countdown timer, in hours, minutes, and seconds; or `0` when stopped. Can be set to the minute, up to 18 hours. Begins running as soon as you set it, and will continue to run in the background if you change to a different function. To cancel while running, hold **Select**. When timer runs out, press **Select** to silence. If power is lost, the timer will reset to `0`. |
21+
| **Day counter** | `_1 23 __` | Shows the number of days until/since a date you specify. Set the same way as **Date.** |
2122
| **Thermometer** | `__ 38 25` | Shows the temperature of the onboard DS3231 chip (e.g. 38.25°C – I think). May not be very useful as it tends to read higher than ambient temperature and its tolerance is low. |
2223
| **Cleaner** | `88 88 88` | Cycles all the digits on all the tubes. A quick and dirty anti-cathode-poisoning mode, until automatic digit cycling is implemented. |
23-
| **Alarm** | `_7 00 1_` | _Not yet implemented._<br/>Shows alarm time and status. Use **Adjust** to switch on/off; status is shown on 5th tube (1=on, 0=off) and by display brightness (bright=on, dim=off). Hold **Select** to set the time the same way as **Time**. When alarm sounds, press **Select** to snooze, or hold for 1sec (followed by a short beep) to silence the alarm for the day. Options menu lets you restrict the alarm to your workweek or weekend only. In a power outage, the alarm will remain set, but it will not sound if power is disconnected at alarm time. |
2424

2525
### Options Menu
2626

@@ -31,30 +31,30 @@ _In these instructions, **Select** is the main pushbutton, and **Adjust** can be
3131

3232
| Option | Settings |
3333
| --- | --- |
34-
| **Timekeeping and display** | |
34+
| | **Timekeeping and display** |
3535
| 1. Time format | 1 = 12-hour<br/>2 = 24-hour<br/>(time-of-day display only; setting times is always done in 24h) |
3636
| 2. Date format | 1 = month/date<br/>2 = date/month |
3737
| 3. Display date during time? | 0 = never<br/>1 = date instead of seconds<br/>2 = full date (as above) every minute at :30 seconds |
3838
| 4. Leading zero in hour, date, and month? | 0 = no<br/>1 = yes |
3939
| 5. Digit fade | _Not yet implemented._<br/>0–50 (in hundredths of a second) |
4040
| 6. Auto DST | Add 1h for daylight saving time between these dates (at 2am):<br/>0 = off<br/>1 = second Sunday in March to first Sunday in November (US/CA)<br/>2 = last Sunday in March to last Sunday in October (UK/EU)<br/>3 = first Sunday in April to last Sunday in October (MX)<br/>4 = last Sunday in September to first Sunday in April (NZ)<br/>5 = first Sunday in October to first Sunday in April (AU)<br/>6 = third Sunday in October to third Sunday in February (BZ) |
41-
| **Alarms and sounds** | |
42-
| 7. Alarm days | 0 = every day<br/>1 = workweek only (per workdays setting below)<br/>2 = weekend only |
41+
| | **Alarms and sounds** |
42+
| 7. Alarm days | 0 = every day<br/>1 = work week only (per settings below)<br/>2 = weekend only |
4343
| 8. Alarm snooze | 0–60 minutes. 0 disables snooze. |
4444
| 9. Alarm tone pitch | _Not yet implemented._<br/>[Note number on a piano keyboard](https://en.wikipedia.org/wiki/Piano_key_frequencies), from 49 (A4) to 88 (C8). Some are louder than others. |
45-
| 10. Timer interval mode | _Not yet implemented._<br/>What happens when the timer reaches 0.<br/>0 = stop and sound continuously<br/>1 = restart and sound a single tone (interval timer) |
45+
| 10. Timer interval mode | What happens when the timer reaches 0.<br/>0 = stop and sound continuously<br/>1 = restart and sound a single tone (interval timer) |
4646
| 11. Timer tone pitch | _Not yet implemented._<br/>Set the same way as the alarm tone pitch, above. |
4747
| 12. Hourly strike | _Not yet implemented._<br/>0 = off<br/>1 = double tone<br/>2 = pips<br/>3 = strike the hour<br/>4 = ship's bell<br/>(Clocks without radio/timer control only. Will not sound during day-off or night-off.) |
4848
| 13. Hourly strike pitch | _Not yet implemented._<br/>Set the same way as the alarm tone pitch, above. |
49-
| **Night-off and day-off** | |
50-
| 14. Night-off | _Not yet implemented._<br/>To save tube life and/or preserve your sleep, dim or shut off tubes nightly when you're not around or sleeping.<br/>0 = none (tubes fully on at night)<br/>1 = dim tubes at night<br/>2 = shut off tubes at night<br/>When off, you can press **Select** to light the tubes briefly. |
51-
| 15. Night starts at | _Not yet implemented._<br/>Time of day. |
52-
| 16. Night ends at | _Not yet implemented._<br/>Time of day. Set to 0:00 to use the alarm time. At this time (whether night-off/alarm is enabled or not), all tubes will briefly cycle through all digits at full brightness to help prevent [cathode poisoning](http://www.tube-tester.com/sites/nixie/different/cathode%20poisoning/cathode-poisoning.htm). |
53-
| 17. Day-off | _Not yet implemented._<br/>To further save tube life, shut off tubes during the day when you're not around.<br/>0 = none (tubes fully on during the day)<br/>1 = clock at work (shut off all day on weekends)<br/>2 = clock at home (shut off during work hours)<br/>When off, you can press **Select** to light the tubes briefly. |
49+
| | **Night-off and day-off** |
50+
| 14. Night-off | To save tube life and/or preserve your sleep, dim or shut off tubes nightly when you're not around or sleeping.<br/>0 = none (tubes fully on at night)<br/>1 = dim tubes at night<br/>2 = shut off tubes at night<br/>When off, you can press **Select** to illuminate the tubes briefly. |
51+
| 15. Night starts at | Time of day. |
52+
| 16. Night ends at | Time of day. Set to 0:00 to use the alarm time. At this time (whether night-off/alarm is enabled or not), all tubes will briefly cycle through all digits at full brightness to help prevent [cathode poisoning](http://www.tube-tester.com/sites/nixie/different/cathode%20poisoning/cathode-poisoning.htm) _(not yet implemented)_. |
53+
| 17. Day-off | To further save tube life, shut off tubes during the day when you're not around.<br/>0 = none (tubes fully on during the day)<br/>1 = clock at work (shut off all day on weekends)<br/>2 = clock at home (shut off during work hours)<br/>When off, you can press **Select** to illuminuate the tubes briefly. |
5454
| 18. First day of work week | 0–6 (Sunday–Saturday) |
5555
| 19. Last day of work week | 0–6 (Sunday–Saturday) |
56-
| 20. Work starts at | _Not yet implemented._<br/>Time of day. |
57-
| 21. Work ends at | _Not yet implemented._<br/>Time of day. |
56+
| 20. Work starts at | Time of day. |
57+
| 21. Work ends at | Time of day. |
5858

5959
### Factory Reset
6060

sixtube_lm/sixtube_lm.ino

Lines changed: 73 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ const byte alarmRadio = 0;
8080
// When timer is running, output will stay on until timer runs down.
8181
const byte alarmDur = 1;
8282

83+
const byte unoffDur = 10; //when display is dim/off, a press will light the tubes for this many seconds
84+
8385
const byte displaySize = 6; //number of tubes
8486

8587
// How long (in ms) are the button hold durations?
@@ -163,7 +165,9 @@ word soundRemain = 0; //alarm/timer sound timeout counter, seconds
163165
word snoozeRemain = 0; //snooze timeout counter, seconds
164166
word timerInitial = 0; //timer original setting, seconds - up to 18 hours (64,800 seconds - fits just inside a word)
165167
word timerRemain = 0; //timer actual counter
168+
word unoffRemain = 0; //un-off (briefly turn on tubes during full night-off or day-off) timeout counter, seconds
166169
byte displayNext[6] = {15,15,15,15,15,15}; //Internal representation of display. Blank to start. Change this to change tubes.
170+
byte displayDim = 2; //dim per display or function: 2=normal, 1=dim, 0=off
167171

168172

169173
////////// Main code control //////////
@@ -308,6 +312,14 @@ void ctrlEvt(byte ctrl, byte evt){
308312
return;
309313
}
310314

315+
//Is it a press for an un-off?
316+
if(displayDim==0 && evt==1) {
317+
unoffRemain = unoffDur;
318+
updateDisplay();
319+
btnStop();
320+
return;
321+
}
322+
311323
if(fn < fnOpts) { //normal fn running/setting (not in options menu)
312324

313325
if(evt==3 && ctrl==mainSel) { //mainSel long hold: enter options menu
@@ -643,7 +655,14 @@ void checkRTC(bool force){
643655
//If timer has time on it, decrement and trigger beeper if we reach zero
644656
if(timerRemain>0) {
645657
timerRemain--;
646-
if(timerRemain<=0) { fnSetPg = 0; fn = fnIsTimer; inputLast = pollLast; soundRemain = alarmDur*60; } //TODO radio mode
658+
if(timerRemain<=0) { //timer has elasped
659+
if(readEEPROM(25,false)) { //interval timer: sound for 1sec and restart; don't change to timer fn
660+
soundRemain = 1; timerRemain = timerInitial;
661+
} else {
662+
fnSetPg = 0; fn = fnIsTimer; inputLast = pollLast; soundRemain = alarmDur*60;
663+
}
664+
//TODO radio mode
665+
} //end timer elapsed
647666
}
648667
//If beeper has time on it, decrement and sound the beeper for 1/2 second
649668
if(soundRemain>0) {
@@ -658,6 +677,9 @@ void checkRTC(bool force){
658677
snoozeRemain--;
659678
if(snoozeRemain<=0 && readEEPROM(2,false)) { fnSetPg = 0; fn = fnIsTime; soundRemain = alarmDur*60; }
660679
}
680+
if(unoffRemain>0) {
681+
unoffRemain--; //updateDisplay will naturally put it back to off state if applicable
682+
}
661683
} //end natural second
662684

663685
//Finally, whether natural tick or not, if we're not setting anything, update the display
@@ -729,6 +751,7 @@ void updateDisplay(){
729751
//Run as needed to update display when the value being shown on it has changed
730752
//This formats the new value and puts it in displayNext[] for cycleDisplay() to pick up
731753
if(fnSetPg) { //setting value, for either fn or option
754+
displayDim = 2;
732755
blankDisplay(4, 5);
733756
if(fnSetValMax==1439) { //Time of day (0-1439 mins, 0:00–23:59): show hrs/mins
734757
editDisplay(fnSetVal/60, 0, 1, readEEPROM(19,false)); //hours with leading zero
@@ -740,12 +763,24 @@ void updateDisplay(){
740763
} else editDisplay(fnSetVal, 0, 3, false); //some other type of value
741764
}
742765
else if(fn >= fnOpts){ //options menu, but not setting a value
766+
displayDim = 2;
743767
editDisplay(fn-fnOpts+1,0,1,0); //display option number (1-index) on hour tubes
744768
blankDisplay(2,5);
745769
} else { //fn running
770+
//Set displayDim per night-off and day-off settings - fnIsAlarm may override this
771+
word todmins = tod.hour()*60+tod.minute();
772+
if(unoffDur > 0) {
773+
displayDim = 2;
774+
} else if(readEEPROM(27,false) && (todmins>=readEEPROM(28,true) || todmins<(readEEPROM(30,true)==0?readEEPROM(0,true):readEEPROM(30,true)))) { //night-off
775+
displayDim = (readEEPROM(27,false)==1?1:0); //dim or off
776+
} else if(readEEPROM(32,false)==1 && toddow<readEEPROM(33,false) && toddow>readEEPROM(34,false)) { //day-off all day on weekends
777+
displayDim = 0;
778+
} else if(readEEPROM(32,false)==2 && toddow>=readEEPROM(33,false) && toddow<=readEEPROM(34,false) && todmins>=readEEPROM(35,true) && todmins<readEEPROM(37,true)) { //day-off during office hours
779+
displayDim = 0;
780+
} else displayDim = 2;
746781
switch(fn){
747782
case fnIsTime:
748-
byte hr; hr = tod.hour();
783+
byte hr; hr = tod.hour();
749784
if(readEEPROM(16,false)==1) hr = (hr==0?12:(hr>12?hr-12:hr));
750785
editDisplay(hr, 0, 1, readEEPROM(19,false));
751786
editDisplay(tod.minute(), 2, 3, true);
@@ -770,10 +805,12 @@ void updateDisplay(){
770805
blankDisplay(4,5);
771806
break;
772807
case fnIsAlarm: //alarm
773-
//TODO this isn't a real display
774-
editDisplay(0,0,1,readEEPROM(19,false)); //hrs
775-
editDisplay(0,2,3,true); //mins
776-
editDisplay(0,4,5,false); //status
808+
word almTime; almTime = readEEPROM(0,true);
809+
editDisplay(almTime/60, 0, 1, readEEPROM(19,false)); //hours with leading zero
810+
editDisplay(almTime%60, 2, 3, true);
811+
editDisplay(readEEPROM(2,false),4,4,false); //status 1/0
812+
displayDim = (readEEPROM(2,false)?2:1); //status bright/dim
813+
blankDisplay(5,5);
777814
break;
778815
case fnIsTimer: //timer - display time left.
779816
//Relative unit positioning: when t <1h, display min/sec in place of hr/min on 4-tube displays
@@ -850,43 +887,47 @@ void initOutputs() {
850887
}
851888

852889
void cycleDisplay(){
853-
bool dim = 0;//(opts[2]>0?true:false); //Under normal circumstances, dim constantly if the time is right
854-
if(fnSetPg>0) { //but if we're setting, dim for every other 500ms since we started setting
890+
//Other display code decides whether we should dim per function or time of day
891+
bool dim = (displayDim==1?1:0);
892+
//But if we're setting, decide here to dim for every other 500ms since we started setting
893+
if(fnSetPg>0) {
855894
if(setStartLast==0) setStartLast = millis();
856895
dim = 1-(((millis()-setStartLast)/500)%2);
857896
} else {
858897
if(setStartLast>0) setStartLast=0;
859898
}
860899

861-
//Anode channel 0: tubes #2 (min x10) and #5 (sec x1)
862-
setCathodes(displayLast[2],displayLast[5]); //Via d2b decoder chip, set cathodes to old digits
863-
digitalWrite(anodes[0], HIGH); //Turn on tubes
864-
delay(displayLastFade[0]/(dim?4:1)); //Display for fade-out cycles
865-
setCathodes(displayNext[2],displayNext[5]); //Switch cathodes to new digits
866-
delay(displayNextFade[0]/(dim?4:1)); //Display for fade-in cycles
867-
digitalWrite(anodes[0], LOW); //Turn off tubes
900+
if(displayDim !== 0) { //if other display code says to shut off entirely, skip this part
901+
//Anode channel 0: tubes #2 (min x10) and #5 (sec x1)
902+
setCathodes(displayLast[2],displayLast[5]); //Via d2b decoder chip, set cathodes to old digits
903+
digitalWrite(anodes[0], HIGH); //Turn on tubes
904+
delay(displayLastFade[0]/(dim?4:1)); //Display for fade-out cycles
905+
setCathodes(displayNext[2],displayNext[5]); //Switch cathodes to new digits
906+
delay(displayNextFade[0]/(dim?4:1)); //Display for fade-in cycles
907+
digitalWrite(anodes[0], LOW); //Turn off tubes
868908

869-
if(dim) delay(fadeMax/1.5);
909+
if(dim) delay(fadeMax/1.5);
870910

871-
//Anode channel 1: tubes #4 (sec x10) and #1 (hour x1)
872-
setCathodes(displayLast[4],displayLast[1]);
873-
digitalWrite(anodes[1], HIGH);
874-
delay(displayLastFade[1]/(dim?4:1));
875-
setCathodes(displayNext[4],displayNext[1]);
876-
delay(displayNextFade[1]/(dim?4:1));
877-
digitalWrite(anodes[1], LOW);
911+
//Anode channel 1: tubes #4 (sec x10) and #1 (hour x1)
912+
setCathodes(displayLast[4],displayLast[1]);
913+
digitalWrite(anodes[1], HIGH);
914+
delay(displayLastFade[1]/(dim?4:1));
915+
setCathodes(displayNext[4],displayNext[1]);
916+
delay(displayNextFade[1]/(dim?4:1));
917+
digitalWrite(anodes[1], LOW);
878918

879-
if(dim) delay(fadeMax/1.5);
919+
if(dim) delay(fadeMax/1.5);
880920

881-
//Anode channel 2: tubes #0 (hour x10) and #3 (min x1)
882-
setCathodes(displayLast[0],displayLast[3]);
883-
digitalWrite(anodes[2], HIGH);
884-
delay(displayLastFade[2]/(dim?4:1));
885-
setCathodes(displayNext[0],displayNext[3]);
886-
delay(displayNextFade[2]/(dim?4:1));
887-
digitalWrite(anodes[2], LOW);
921+
//Anode channel 2: tubes #0 (hour x10) and #3 (min x1)
922+
setCathodes(displayLast[0],displayLast[3]);
923+
digitalWrite(anodes[2], HIGH);
924+
delay(displayLastFade[2]/(dim?4:1));
925+
setCathodes(displayNext[0],displayNext[3]);
926+
delay(displayNextFade[2]/(dim?4:1));
927+
digitalWrite(anodes[2], LOW);
888928

889-
if(dim) delay(fadeMax*0.75);
929+
if(dim) delay(fadeMax*0.75);
930+
} //end if displayDim !== 0
890931

891932
// Loop thru and update all the arrays, and fades.
892933
for( byte i = 0 ; i < 6 ; i ++ ) {

0 commit comments

Comments
 (0)