1+ #pragma once
2+
3+ #include " wled.h"
4+
5+ class UsermodCronixie : public Usermod {
6+ private:
7+ unsigned long lastTime = 0 ;
8+ char cronixieDisplay[7 ] = " HHMMSS" ;
9+ byte _digitOut[6 ] = {10 ,10 ,10 ,10 ,10 ,10 };
10+ byte dP[6 ] = {255 , 255 , 255 , 255 , 255 , 255 };
11+
12+ // set your config variables to their boot default value (this can also be done in readFromConfig() or a constructor if you prefer)
13+ bool backlight = true ;
14+
15+ public:
16+ void initCronixie ()
17+ {
18+ if (dP[0 ] == 255 ) // if dP[0] is 255, cronixie is not yet init'ed
19+ {
20+ setCronixie ();
21+ strip.getSegment (0 ).grouping = 10 ; // 10 LEDs per digit
22+ }
23+ }
24+
25+ void setup () {
26+
27+ }
28+
29+ void loop () {
30+ if (!toki.isTick ()) return ;
31+ initCronixie ();
32+ _overlayCronixie ();
33+ strip.trigger ();
34+ }
35+
36+ byte getSameCodeLength (char code, int index, char const cronixieDisplay[])
37+ {
38+ byte counter = 0 ;
39+
40+ for (int i = index+1 ; i < 6 ; i++)
41+ {
42+ if (cronixieDisplay[i] == code)
43+ {
44+ counter++;
45+ } else {
46+ return counter;
47+ }
48+ }
49+ return counter;
50+ }
51+
52+ void setCronixie ()
53+ {
54+ /*
55+ * digit purpose index
56+ * 0-9 | 0-9 (incl. random)
57+ * 10 | blank
58+ * 11 | blank, bg off
59+ * 12 | test upw.
60+ * 13 | test dnw.
61+ * 14 | binary AM/PM
62+ * 15 | BB upper +50 for no trailing 0
63+ * 16 | BBB
64+ * 17 | BBBB
65+ * 18 | BBBBB
66+ * 19 | BBBBBB
67+ * 20 | H
68+ * 21 | HH
69+ * 22 | HHH
70+ * 23 | HHHH
71+ * 24 | M
72+ * 25 | MM
73+ * 26 | MMM
74+ * 27 | MMMM
75+ * 28 | MMMMM
76+ * 29 | MMMMMM
77+ * 30 | S
78+ * 31 | SS
79+ * 32 | SSS
80+ * 33 | SSSS
81+ * 34 | SSSSS
82+ * 35 | SSSSSS
83+ * 36 | Y
84+ * 37 | YY
85+ * 38 | YYYY
86+ * 39 | I
87+ * 40 | II
88+ * 41 | W
89+ * 42 | WW
90+ * 43 | D
91+ * 44 | DD
92+ * 45 | DDD
93+ * 46 | V
94+ * 47 | VV
95+ * 48 | VVV
96+ * 49 | VVVV
97+ * 50 | VVVVV
98+ * 51 | VVVVVV
99+ * 52 | v
100+ * 53 | vv
101+ * 54 | vvv
102+ * 55 | vvvv
103+ * 56 | vvvvv
104+ * 57 | vvvvvv
105+ */
106+
107+ // H HourLower | HH - Hour 24. | AH - Hour 12. | HHH Hour of Month | HHHH Hour of Year
108+ // M MinuteUpper | MM Minute of Hour | MMM Minute of 12h | MMMM Minute of Day | MMMMM Minute of Month | MMMMMM Minute of Year
109+ // S SecondUpper | SS Second of Minute | SSS Second of 10 Minute | SSSS Second of Hour | SSSSS Second of Day | SSSSSS Second of Week
110+ // B AM/PM | BB 0-6/6-12/12-18/18-24 | BBB 0-3... | BBBB 0-1.5... | BBBBB 0-1 | BBBBBB 0-0.5
111+
112+ // Y YearLower | YY - Year LU | YYYY - Std.
113+ // I MonthLower | II - Month of Year
114+ // W Week of Month | WW Week of Year
115+ // D Day of Week | DD Day Of Month | DDD Day Of Year
116+
117+ DEBUG_PRINT (" cset " );
118+ DEBUG_PRINTLN (cronixieDisplay);
119+
120+ for (int i = 0 ; i < 6 ; i++)
121+ {
122+ dP[i] = 10 ;
123+ switch (cronixieDisplay[i])
124+ {
125+ case ' _' : dP[i] = 10 ; break ;
126+ case ' -' : dP[i] = 11 ; break ;
127+ case ' r' : dP[i] = random (1 ,7 ); break ; // random btw. 1-6
128+ case ' R' : dP[i] = random (0 ,10 ); break ; // random btw. 0-9
129+ // case 't': break; //Test upw.
130+ // case 'T': break; //Test dnw.
131+ case ' b' : dP[i] = 14 + getSameCodeLength (' b' ,i,cronixieDisplay); i = i+dP[i]-14 ; break ;
132+ case ' B' : dP[i] = 14 + getSameCodeLength (' B' ,i,cronixieDisplay); i = i+dP[i]-14 ; break ;
133+ case ' h' : dP[i] = 70 + getSameCodeLength (' h' ,i,cronixieDisplay); i = i+dP[i]-70 ; break ;
134+ case ' H' : dP[i] = 20 + getSameCodeLength (' H' ,i,cronixieDisplay); i = i+dP[i]-20 ; break ;
135+ case ' A' : dP[i] = 108 ; i++; break ;
136+ case ' a' : dP[i] = 58 ; i++; break ;
137+ case ' m' : dP[i] = 74 + getSameCodeLength (' m' ,i,cronixieDisplay); i = i+dP[i]-74 ; break ;
138+ case ' M' : dP[i] = 24 + getSameCodeLength (' M' ,i,cronixieDisplay); i = i+dP[i]-24 ; break ;
139+ case ' s' : dP[i] = 80 + getSameCodeLength (' s' ,i,cronixieDisplay); i = i+dP[i]-80 ; break ; // refresh more often bc. of secs
140+ case ' S' : dP[i] = 30 + getSameCodeLength (' S' ,i,cronixieDisplay); i = i+dP[i]-30 ; break ;
141+ case ' Y' : dP[i] = 36 + getSameCodeLength (' Y' ,i,cronixieDisplay); i = i+dP[i]-36 ; break ;
142+ case ' y' : dP[i] = 86 + getSameCodeLength (' y' ,i,cronixieDisplay); i = i+dP[i]-86 ; break ;
143+ case ' I' : dP[i] = 39 + getSameCodeLength (' I' ,i,cronixieDisplay); i = i+dP[i]-39 ; break ; // Month. Don't ask me why month and minute both start with M.
144+ case ' i' : dP[i] = 89 + getSameCodeLength (' i' ,i,cronixieDisplay); i = i+dP[i]-89 ; break ;
145+ // case 'W': break;
146+ // case 'w': break;
147+ case ' D' : dP[i] = 43 + getSameCodeLength (' D' ,i,cronixieDisplay); i = i+dP[i]-43 ; break ;
148+ case ' d' : dP[i] = 93 + getSameCodeLength (' d' ,i,cronixieDisplay); i = i+dP[i]-93 ; break ;
149+ case ' 0' : dP[i] = 0 ; break ;
150+ case ' 1' : dP[i] = 1 ; break ;
151+ case ' 2' : dP[i] = 2 ; break ;
152+ case ' 3' : dP[i] = 3 ; break ;
153+ case ' 4' : dP[i] = 4 ; break ;
154+ case ' 5' : dP[i] = 5 ; break ;
155+ case ' 6' : dP[i] = 6 ; break ;
156+ case ' 7' : dP[i] = 7 ; break ;
157+ case ' 8' : dP[i] = 8 ; break ;
158+ case ' 9' : dP[i] = 9 ; break ;
159+ // case 'V': break; //user var0
160+ // case 'v': break; //user var1
161+ }
162+ }
163+ DEBUG_PRINT (" result " );
164+ for (int i = 0 ; i < 5 ; i++)
165+ {
166+ DEBUG_PRINT ((int )dP[i]);
167+ DEBUG_PRINT (" " );
168+ }
169+ DEBUG_PRINTLN ((int )dP[5 ]);
170+
171+ _overlayCronixie (); // refresh
172+ }
173+
174+ void _overlayCronixie ()
175+ {
176+ byte h = hour (localTime);
177+ byte h0 = h;
178+ byte m = minute (localTime);
179+ byte s = second (localTime);
180+ byte d = day (localTime);
181+ byte mi = month (localTime);
182+ int y = year (localTime);
183+ // this has to be changed in time for 22nd century
184+ y -= 2000 ; if (y<0 ) y += 30 ; // makes countdown work
185+
186+ if (useAMPM && !countdownMode)
187+ {
188+ if (h>12 ) h-=12 ;
189+ else if (h==0 ) h+=12 ;
190+ }
191+ for (int i = 0 ; i < 6 ; i++)
192+ {
193+ if (dP[i] < 12 ) _digitOut[i] = dP[i];
194+ else {
195+ if (dP[i] < 65 )
196+ {
197+ switch (dP[i])
198+ {
199+ case 21 : _digitOut[i] = h/10 ; _digitOut[i+1 ] = h- _digitOut[i]*10 ; i++; break ; // HH
200+ case 25 : _digitOut[i] = m/10 ; _digitOut[i+1 ] = m- _digitOut[i]*10 ; i++; break ; // MM
201+ case 31 : _digitOut[i] = s/10 ; _digitOut[i+1 ] = s- _digitOut[i]*10 ; i++; break ; // SS
202+
203+ case 20 : _digitOut[i] = h- (h/10 )*10 ; break ; // H
204+ case 24 : _digitOut[i] = m/10 ; break ; // M
205+ case 30 : _digitOut[i] = s/10 ; break ; // S
206+
207+ case 43 : _digitOut[i] = weekday (localTime); _digitOut[i]--; if (_digitOut[i]<1 ) _digitOut[i]= 7 ; break ; // D
208+ case 44 : _digitOut[i] = d/10 ; _digitOut[i+1 ] = d- _digitOut[i]*10 ; i++; break ; // DD
209+ case 40 : _digitOut[i] = mi/10 ; _digitOut[i+1 ] = mi- _digitOut[i]*10 ; i++; break ; // II
210+ case 37 : _digitOut[i] = y/10 ; _digitOut[i+1 ] = y- _digitOut[i]*10 ; i++; break ; // YY
211+ case 39 : _digitOut[i] = 2 ; _digitOut[i+1 ] = 0 ; _digitOut[i+2 ] = y/10 ; _digitOut[i+3 ] = y- _digitOut[i+2 ]*10 ; i+=3 ; break ; // YYYY
212+
213+ // case 16: _digitOut[i+2] = ((h0/3)&1)?1:0; i++; //BBB (BBBB NI)
214+ // case 15: _digitOut[i+1] = (h0>17 || (h0>5 && h0<12))?1:0; i++; //BB
215+ case 14 : _digitOut[i] = (h0>11 )?1 :0 ; break ; // B
216+ }
217+ } else
218+ {
219+ switch (dP[i])
220+ {
221+ case 71 : _digitOut[i] = h/10 ; _digitOut[i+1 ] = h- _digitOut[i]*10 ; if (_digitOut[i] == 0 ) _digitOut[i]=10 ; i++; break ; // hh
222+ case 75 : _digitOut[i] = m/10 ; _digitOut[i+1 ] = m- _digitOut[i]*10 ; if (_digitOut[i] == 0 ) _digitOut[i]=10 ; i++; break ; // mm
223+ case 81 : _digitOut[i] = s/10 ; _digitOut[i+1 ] = s- _digitOut[i]*10 ; if (_digitOut[i] == 0 ) _digitOut[i]=10 ; i++; break ; // ss
224+ // case 66: _digitOut[i+2] = ((h0/3)&1)?1:10; i++; //bbb (bbbb NI)
225+ // case 65: _digitOut[i+1] = (h0>17 || (h0>5 && h0<12))?1:10; i++; //bb
226+ case 64 : _digitOut[i] = (h0>11 )?1 :10 ; break ; // b
227+
228+ case 93 : _digitOut[i] = weekday (localTime); _digitOut[i]--; if (_digitOut[i]<1 ) _digitOut[i]= 7 ; break ; // d
229+ case 94 : _digitOut[i] = d/10 ; _digitOut[i+1 ] = d- _digitOut[i]*10 ; if (_digitOut[i] == 0 ) _digitOut[i]=10 ; i++; break ; // dd
230+ case 90 : _digitOut[i] = mi/10 ; _digitOut[i+1 ] = mi- _digitOut[i]*10 ; if (_digitOut[i] == 0 ) _digitOut[i]=10 ; i++; break ; // ii
231+ case 87 : _digitOut[i] = y/10 ; _digitOut[i+1 ] = y- _digitOut[i]*10 ; i++; break ; // yy
232+ case 89 : _digitOut[i] = 2 ; _digitOut[i+1 ] = 0 ; _digitOut[i+2 ] = y/10 ; _digitOut[i+3 ] = y- _digitOut[i+2 ]*10 ; i+=3 ; break ; // yyyy
233+ }
234+ }
235+ }
236+ }
237+ }
238+
239+ void handleOverlayDraw ()
240+ {
241+ byte offsets[] = {5 , 0 , 6 , 1 , 7 , 2 , 8 , 3 , 9 , 4 };
242+
243+ for (uint16_t i = 0 ; i < 6 ; i++)
244+ {
245+ byte o = 10 *i;
246+ byte excl = 10 ;
247+ if (_digitOut[i] < 10 ) excl = offsets[_digitOut[i]];
248+ excl += o;
249+
250+ if (backlight && _digitOut[i] <11 )
251+ {
252+ uint32_t col = strip.gamma32 (strip.getSegment (0 ).colors [1 ]);
253+ for (uint16_t j=o; j< o+10 ; j++) {
254+ if (j != excl) strip.setPixelColor (j, col);
255+ }
256+ } else
257+ {
258+ for (uint16_t j=o; j< o+10 ; j++) {
259+ if (j != excl) strip.setPixelColor (j, 0 );
260+ }
261+ }
262+ }
263+ }
264+
265+ void addToJsonState (JsonObject& root)
266+ {
267+ root[" nx" ] = cronixieDisplay;
268+ }
269+
270+ void readFromJsonState (JsonObject& root)
271+ {
272+ if (root[" nx" ].is <const char *>()) {
273+ strncpy (cronixieDisplay, root[" nx" ], 6 );
274+ }
275+ }
276+
277+ void addToConfig (JsonObject& root)
278+ {
279+ JsonObject top = root.createNestedObject (F (" Cronixie" ));
280+ top[" backlight" ] = backlight;
281+ }
282+
283+ bool readFromConfig (JsonObject& root)
284+ {
285+ // default settings values could be set here (or below using the 3-argument getJsonValue()) instead of in the class definition or constructor
286+ // setting them inside readFromConfig() is slightly more robust, handling the rare but plausible use case of single value being missing after boot (e.g. if the cfg.json was manually edited and a value was removed)
287+
288+ JsonObject top = root[F (" Cronixie" )];
289+
290+ bool configComplete = !top.isNull ();
291+
292+ configComplete &= getJsonValue (top[" backlight" ], backlight);
293+
294+ return configComplete;
295+ }
296+
297+ uint16_t getId ()
298+ {
299+ return USERMOD_ID_CRONIXIE;
300+ }
301+ };
0 commit comments