Skip to content

Commit f5fb731

Browse files
committed
Finish modularizing with h/cpp files - wip
1 parent ec210c7 commit f5fb731

14 files changed

+199
-76
lines changed

arduino-nixie/arduino-nixie.h

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
1-
// Universal digital clock codebase for Arduino - https://github.com/clockspot/arduino-clock
2-
// Sketch by Luke McKenzie (luke@theclockspot.com)
3-
// Written to support RLB Designs’ Universal Nixie Driver Board
4-
// Inspired by original sketch by Robin Birtles (rlb-designs.com) and Chris Gerekos
1+
#ifndef ARDUINO_CLOCK_H
2+
#define ARDUINO_CLOCK_H
53

64
////////// Hardware configuration //////////
75
//Include the config file that matches your hardware setup. If needed, duplicate an existing one.
86

97
#include "configs/led-iot.h"
108
//#include "configs/undb-v9-relay.h"
119

12-
10+
////////////////////////////////////////////
1311

1412

1513
//Unique IDs for the functions - see also fnScroll
@@ -23,7 +21,7 @@
2321

2422
void setup();
2523
void loop();
26-
void ctrlEvt(byte ctrl, byte evt, byte evtLast);
24+
void ctrlEvt(byte ctrl, byte evt, byte evtLast, bool velocity=0);
2725
void fnScroll(byte dir);
2826
void fnOptScroll(byte dir);
2927
void goToFn(byte thefn, byte thefnPg=0);
@@ -78,4 +76,7 @@ byte getSignalPattern();
7876
void quickBeep(int pitch);
7977
void quickBeepPattern(int source, int pattern);
8078
void updateBacklight();
81-
void cycleBacklight();
79+
void cycleBacklight();
80+
byte getVersionPart(byte part);
81+
82+
#endif //ARDUINO_CLOCK_H

arduino-nixie/arduino-nixie.ino

Lines changed: 33 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// Written to support RLB Designs’ Universal Nixie Driver Board
44
// Inspired by original sketch by Robin Birtles (rlb-designs.com) and Chris Gerekos
55

6+
#include <arduino.h>
67
#include "arduino-nixie.h";
78

89
////////// Software version //////////
@@ -15,22 +16,18 @@ const bool vDev = 1;
1516

1617
// These modules are used per the available hardware and features enabled in the config file.
1718
// The disp and rtc options are mutually exclusive and define the same functions.
18-
// Because the Arduino IDE preprocessor seems to #include without regard to #if blocks (see https://forum.arduino.cc/index.php?topic=134226.0), I don't have #ifdef blocks around these header file inclusions. Instead I simply include them all, and have #ifdef blocks around the corresponding cpp code so only the included code is compiled. It's dumb, but it works.
19+
// Because the Arduino IDE preprocessor seems to #include without regard to #if blocks (see https://forum.arduino.cc/index.php?topic=134226.0), I don't have #ifdef blocks around these header file inclusions. Instead I simply include them all, and have #ifdef blocks around the corresponding cpp code so only the specified code is compiled. It's dumb, but it works.
1920

2021
#if ENABLE_DATE_RISESET //this probably doesn't work, per the above, but ¯\_(ツ)_/¯
2122
#include <Dusk2Dawn.h> //DM Kishi - unlicensed - install in your Arduino IDE if needed - test without
2223
#endif
23-
#include "storage.h"; //supports both AVR EEPROM and SAMD flash
24-
#include "dispNixie.cpp" //for a SN74141-multiplexed nixie array
25-
#include "dispMAX7219.cpp" //for a SPI MAX7219 8x8 LED array
26-
27-
#include "rtcDS3231.h" //for an I2C DS3231 RTC module
28-
#include "rtcMillis.h" //for a fake RTC based on millis
29-
30-
#define INPUT
31-
#include "input.cpp"; //for Sel/Alt/Up/Dn - uses rtc functions
32-
#define NETWORK
33-
#include "network.cpp" //for 33 IoT WiFiNINA - uses display, rtc, and storage functions
24+
#include "storage.h"; //for persistent storage - supports both AVR EEPROM and SAMD flash
25+
#include "dispNixie.h" //if DISP_NIXIE is defined in config - for a SN74141-multiplexed nixie array
26+
#include "dispMAX7219.h" //if DISP_MAX7219 is defined in config - for a SPI MAX7219 8x8 LED array
27+
#include "rtcDS3231.h" //if RTC_DS3231 is defined in config – for an I2C DS3231 RTC module
28+
#include "rtcMillis.h" //if RTC_MILLIS is defined in config – for a fake RTC based on millis
29+
#include "input.h"; //for Sel/Alt/Up/Dn - supports buttons, rotary control, and Nano 33 IoT IMU
30+
#include "network.h" //if not AVR – enables WiFi/web-based config/NTP sync on Nano 33 IoT WiFiNINA
3431

3532

3633
////////// Variables and storage //////////
@@ -165,12 +162,11 @@ void setup(){
165162
rtcInit();
166163
initStorage(); //pulls persistent storage data into volatile vars - see storage.cpp
167164
byte changed = initEEPROM(false); //do a soft init to make sure vals in range
168-
initInputs();
169165
initDisplay();
170166
initOutputs(); //depends on some EEPROM settings
171-
delay(100); //prevents the below from firing in the event there's a capacitor stabilizing the input, which can read low falsely
172-
if(readBtn(CTRL_SEL)){ //if Sel is held at startup, show version, and skip init network for now (since wifi connect hangs)
173-
versionShowing = 1; inputCur = CTRL_SEL;
167+
if(initInputs()){ //inits inputs and returns true if CTRL_SEL is held
168+
versionShowing = 1;
169+
//skip network for now, since wifi connect hangs - we'll do it after version is done
174170
} else {
175171
#ifdef NETWORK_SUPPORTED
176172
initNetwork();
@@ -238,7 +234,7 @@ void loop(){
238234

239235
////////// Input handling and value setting //////////
240236

241-
void ctrlEvt(byte ctrl, byte evt, byte evtLast){
237+
void ctrlEvt(byte ctrl, byte evt, byte evtLast, bool velocity){
242238
//Handle control events from inputs, based on current fn and set state.
243239
//evt: 1=press, 2=short hold, 3=long hold, 4=verylong, 5=superlong, 0=release.
244240
//We only handle press evts for up/down ctrls, as that's the only evt encoders generate,
@@ -545,8 +541,8 @@ void ctrlEvt(byte ctrl, byte evt, byte evtLast){
545541
default: break;
546542
} //end switch fn
547543
} //end CTRL_SEL push
548-
if(ctrl==CTRL_UP) doSet(rotVel ? 10 : 1);
549-
if(ctrl==CTRL_DN) doSet(rotVel ? -10 : -1);
544+
if(ctrl==CTRL_UP) doSet(velocity ? 10 : 1);
545+
if(ctrl==CTRL_DN) doSet(velocity ? -10 : -1);
550546
} //end if evt==1
551547
} //end fn setting
552548

@@ -583,8 +579,8 @@ void ctrlEvt(byte ctrl, byte evt, byte evtLast){
583579
clearSet();
584580
}
585581
if(evt==1 && (ctrl==CTRL_UP || ctrl==CTRL_DN)){
586-
if(ctrl==CTRL_UP) doSet(rotVel ? 10 : 1);
587-
if(ctrl==CTRL_DN) doSet(rotVel ? -10 : -1);
582+
if(ctrl==CTRL_UP) doSet(velocity ? 10 : 1);
583+
if(ctrl==CTRL_DN) doSet(velocity ? -10 : -1);
588584
updateDisplay(); //may also make sounds for sampling
589585
}
590586
} //end setting value
@@ -655,8 +651,9 @@ void fnOptScroll(byte dir){
655651
}
656652
}
657653
void goToFn(byte thefn, byte thefnPg){ //A shortcut that also sets inputLast per human activity
658-
fn = thefn; inputLast = millis(); inputLastTODMins = rtcGetHour()*60+rtcGetMinute();
654+
fn = thefn;
659655
fnPg = thefnPg;
656+
setInputLast();
660657
}
661658

662659
void switchAlarmState(byte dir){
@@ -822,17 +819,17 @@ void checkRTC(bool force){
822819
//Things to do every time this is called: timeouts to reset display. These may force a tick.
823820
//Setting timeout: if we're in the settings menu, or we're setting a value
824821
if(fnSetPg || fn>=FN_OPTS){
825-
if((unsigned long)(now-inputLast)>=SETTING_TIMEOUT*1000) { fnSetPg = 0; fn = FN_TOD; force=true; } //Time out after 2 mins
822+
if((unsigned long)(now-getInputLast())>=SETTING_TIMEOUT*1000) { fnSetPg = 0; fn = FN_TOD; force=true; } //Time out after 2 mins
826823
}
827824
//Paged-display function timeout //TODO change FN_CAL to consts? //TODO timeoutPageFn var
828-
else if(fn==FN_CAL && (unsigned long)(now-inputLast)>=FN_PAGE_TIMEOUT*1000) { //3sec per date page
825+
else if(fn==FN_CAL && (unsigned long)(now-getInputLast())>=FN_PAGE_TIMEOUT*1000) { //3sec per date page
829826
// //If a scroll in is going, fast-forward to end - see also ctrlEvt
830827
// if(scrollRemain>0) {
831828
// scrollRemain = 1;
832829
// checkEffects(true);
833830
// }
834831
//Here we just have to increment the page and decide when to reset. updateDisplay() will do the rendering
835-
fnPg++; inputLast+=(FN_PAGE_TIMEOUT*1000); //but leave inputLastTODMins alone so the subsequent page displays will be based on the same TOD
832+
fnPg++; setInputLast(FN_PAGE_TIMEOUT*1000); //but leave inputLastTODMins alone so the subsequent page displays will be based on the same TOD
836833
while(fnPg<fnDatePages && fnPg<200 && ( //skip inapplicable date pages. The 200 is an extra failsafe
837834
(!readEEPROM(10,true) && !readEEPROM(12,true) && //if no lat+long specified, skip weather/rise/set
838835
(fnPg==fnDateWeathernow || fnPg==fnDateWeathernext || fnPg==fnDateSunlast || fnPg==fnDateSunnext))
@@ -843,7 +840,7 @@ void checkRTC(bool force){
843840
//Temporary-display function timeout: if we're *not* in a permanent one (time, or running/signaling timer)
844841
// Stopped/non-signaling timer shouldn't be permanent, but have a much longer timeout, mostly in case someone is waiting to start the chrono in sync with some event, so we'll give that an hour.
845842
else if(fn!=FN_TOD && !(fn==FN_TIMER && (timerState&1 || signalRemain>0))){
846-
if((unsigned long)(now-inputLast)>=(fn==FN_TIMER?3600:FN_TEMP_TIMEOUT)*1000) { fnSetPg = 0; fn = FN_TOD; force=true; }
843+
if((unsigned long)(now-getInputLast())>=(fn==FN_TIMER?3600:FN_TEMP_TIMEOUT)*1000) { fnSetPg = 0; fn = FN_TOD; force=true; }
847844
}
848845

849846
//Temporary value display queue
@@ -1446,9 +1443,9 @@ void updateDisplay(){
14461443
blankDisplay(4,5,true);
14471444
}
14481445
//The sun and weather displays are based on a snapshot of the time of day when the function display was triggered, just in case it's triggered a few seconds before a sun event (sunrise/sunset) and the "prev/now" and "next" displays fall on either side of that event, they'll both display data from before it. If triggered just before midnight, the date could change as well – not such an issue for sun, but might be for weather - TODO create date snapshot also
1449-
else if(fnPg==fnDateSunlast) displaySun(0,rtcGetDate(),inputLastTODMins);
1446+
else if(fnPg==fnDateSunlast) displaySun(0,rtcGetDate(),getInputLastTODMins());
14501447
else if(fnPg==fnDateWeathernow) displayWeather(0);
1451-
else if(fnPg==fnDateSunnext) displaySun(1,rtcGetDate(),inputLastTODMins);
1448+
else if(fnPg==fnDateSunnext) displaySun(1,rtcGetDate(),getInputLastTODMins());
14521449
else if(fnPg==fnDateWeathernext) displayWeather(1);
14531450
break; //end FN_CAL
14541451
//fnIsDayCount removed in favor of paginated calendar
@@ -1902,4 +1899,12 @@ void cycleBacklight() {
19021899
digitalWrite(BACKLIGHT_PIN,(backlightNow?LOW:HIGH)); //LOW = device on
19031900
}
19041901
}
1902+
}
1903+
byte getVersionPart(byte part){
1904+
switch(part){
1905+
case 0: return vMajor; break;
1906+
case 1: return vMinor; break;
1907+
case 2: return vPatch; break;
1908+
case 3: return vDev; break;
1909+
}
19051910
}

arduino-nixie/dispMAX7219.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
#ifdef DISP_MAX7219 //only compile when requested (when included in main file)
2-
#ifndef DISP_MAX7219_SRC //include once only
3-
#define DISP_MAX7219_SRC
1+
#include <arduino.h>
2+
#include "arduino-nixie.h"
43

5-
//#include "Arduino.h" //not necessary, since these get compiled as part of the main sketch
4+
#ifdef DISP_MAX7219 //see arduino-nixie.ino Includes section
5+
6+
#include "dispMAX7219.h"
67
#include <SPI.h> //Arduino - for SPI access to MAX7219
78
#include <LedControl.h> //Eberhard Farle's LedControl library - http://wayoda.github.io/LedControl
89

@@ -134,5 +135,4 @@ void displayBlink(){
134135

135136
//void checkEffects(bool force){}
136137

137-
#endif
138-
#endif
138+
#endif //DISP_MAX7219

arduino-nixie/dispMAX7219.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#ifndef DISP_MAX7219_H
2+
#define DISP_MAX7219_H
3+
4+
//Mutually exclusive with other disp options
5+
6+
void initDisplay();
7+
void sendToMAX7219(byte posStart, byte posEnd);
8+
void cycleDisplay(byte displayDim, byte fnSetPg);
9+
void editDisplay(word n, byte posStart, byte posEnd, bool leadingZeros, bool fade);
10+
void blankDisplay(byte posStart, byte posEnd, byte fade);
11+
void displayBlink();
12+
13+
#endif //DISP_MAX7219_H

arduino-nixie/dispNixie.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
#ifdef DISP_NIXIE //only compile when requested (when included in main file)
2-
#ifndef DISP_NIXIE_SRC //include once only
3-
#define DISP_NIXIE_SRC
1+
#include <arduino.h>
2+
#include "arduino-nixie.h"
43

5-
// Display cycling code derived from http://arduinix.com/Main/Code/ANX-6Tube-Clock-Crossfade.txt
4+
#ifdef DISP_NIXIE //see arduino-nixie.ino Includes section
5+
6+
#include "dispNixie.h"
67

7-
//#include "Arduino.h" //not necessary, since these get compiled as part of the main sketch
8+
// Display cycling code derived from http://arduinix.com/Main/Code/ANX-6Tube-Clock-Crossfade.txt
89

910
//This clock is 2x3 multiplexed: two tubes powered at a time.
1011
//The anode channel determines which two tubes are powered,
@@ -200,5 +201,4 @@ void displayBlink(){
200201
// }
201202
// }
202203

203-
#endif
204-
#endif
204+
#endif //DISP_NIXIE

arduino-nixie/dispNixie.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#ifndef DISP_NIXIE_H
2+
#define DISP_NIXIE_H
3+
4+
//Mutually exclusive with other disp options
5+
6+
void decToBin(bool binVal[], byte i);
7+
void setCathodes(byte decValA, byte decValB);
8+
void initDisplay();
9+
void cycleDisplay(byte displayDim, byte fnSetPg);
10+
void editDisplay(word n, byte posStart, byte posEnd, bool leadingZeros, bool fade);
11+
void blankDisplay(byte posStart, byte posEnd, byte fade);
12+
// void startScroll();
13+
void displayBlink();
14+
// void checkEffects(bool force);
15+
16+
#endif //DISP_NIXIE_H

arduino-nixie/input.cpp

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
1-
#ifdef INPUT //only compile when requested (when included in main file)
2-
#ifndef INPUT_SRC //include once only
3-
#define INPUT_SRC
1+
#include <arduino.h>
2+
#include "arduino-nixie.h"
3+
4+
#include "input.h"
5+
6+
//Needs access to RTC timestamps
7+
#include "rtcDS3231.h"
8+
#include "rtcMillis.h"
49

510
#define HOLDSET_SLOW_RATE 125
611
#define HOLDSET_FAST_RATE 20
@@ -65,7 +70,7 @@ byte inputCurHeld = 0; //Button hold thresholds: 0=none, 1=unused, 2=short, 3=lo
6570
unsigned long inputLast = 0; //When an input last took place, millis()
6671
int inputLastTODMins = 0; //When an input last took place, time of day. Used in paginated functions so they all reflect the time of day when the input happened.
6772

68-
void initInputs(){
73+
bool initInputs(){
6974
//TODO are there no "loose" pins left floating after this? per https://electronics.stackexchange.com/q/37696/151805
7075
#ifdef INPUT_BUTTONS
7176
pinMode(CTRL_SEL, INPUT_PULLUP);
@@ -85,6 +90,10 @@ void initInputs(){
8590
IMU.begin();
8691
//Serial.println(F("IMU initialized"));
8792
#endif
93+
//Check to see if CTRL_SEL is held at init - facilitates version number display and EEPROM hard init
94+
delay(100); //prevents the below from firing in the event there's a capacitor stabilizing the input, which can read low falsely
95+
if(readBtn(CTRL_SEL)){ inputCur = CTRL_SEL; return true; }
96+
else return false;
8897
}
8998

9099
bool readBtn(byte btn){
@@ -190,8 +199,8 @@ void checkRot(){
190199
if((unsigned long)(now-rotLastStep)<=ROT_VEL_START) rotVel = 1; //kick into high velocity setting (x10)
191200
else if((unsigned long)(now-rotLastStep)>=ROT_VEL_STOP) rotVel = 0; //fall into low velocity setting (x1)
192201
rotLastStep = now;
193-
while(rotCurVal>=4) { rotCurVal-=4; ctrlEvt(CTRL_UP,1,inputCurHeld); }
194-
while(rotCurVal<=-4) { rotCurVal+=4; ctrlEvt(CTRL_DN,1,inputCurHeld); }
202+
while(rotCurVal>=4) { rotCurVal-=4; ctrlEvt(CTRL_UP,1,inputCurHeld,rotVel); }
203+
while(rotCurVal<=-4) { rotCurVal+=4; ctrlEvt(CTRL_DN,1,inputCurHeld,rotVel); }
195204
rot.write(rotCurVal);
196205
}
197206
}
@@ -220,5 +229,18 @@ void checkInputs(){
220229
#endif
221230
}
222231

223-
#endif
224-
#endif
232+
void setInputLast(unsigned long increment){
233+
//Called when other code changes the displayed fn, as though the human user had done it
234+
//(which in many cases they did, but indirectly, such as via settings page - but also automatic date display)
235+
//If increment is specified, we just want to move inputLast up a bit
236+
if(increment) inputLast+=increment;
237+
//else we want to set both inputLast and the TODMins snapshot to now
238+
inputLast = millis(); inputLastTODMins = rtcGetTOD();
239+
}
240+
unsigned long getInputLast(){
241+
return inputLast;
242+
}
243+
int getInputLastTODMins(){
244+
//Used to ensure paged displays (e.g. calendar) use the same TOD for all pages
245+
return inputLastTODMins;
246+
}

arduino-nixie/input.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#ifndef INPUT_H
2+
#define INPUT_H
3+
4+
#ifdef INPUT_IMU
5+
//If we don't already have inputs defined for Sel/Alt/Up/Dn, use some bogus ones
6+
#ifndef CTRL_SEL
7+
#define CTRL_SEL 100
8+
#endif
9+
#ifndef CTRL_ALT
10+
#define CTRL_ALT 101
11+
#endif
12+
#ifndef CTRL_UP
13+
#define CTRL_UP 102
14+
#endif
15+
#ifndef CTRL_DN
16+
#define CTRL_DN 103
17+
#endif
18+
#endif
19+
20+
//#ifdef INPUT_IMU
21+
void readIMU();
22+
//#endif
23+
bool initInputs();
24+
bool readBtn(byte btn);
25+
void checkBtn(byte btn);
26+
void inputStop();
27+
//#ifdef INPUT_UPDN_ROTARY
28+
void checkRot();
29+
//#endif
30+
void checkInputs();
31+
void setInputLast(unsigned long increment=0);
32+
unsigned long getInputLast();
33+
int getInputLastTODMins();
34+
35+
#endif //INPUT_H

0 commit comments

Comments
 (0)