Skip to content

Commit a2c8796

Browse files
committed
Replaced native Cronixie support with usermod
1 parent ad301fd commit a2c8796

19 files changed

+363
-382
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@
22

33
### Builds after release 0.12.0
44

5+
#### Build 2203060
6+
7+
- Dynamic hiding of unused color controls in UI (PR #2567)
8+
- Removed native Cronixie support and added Cronixie usermod
9+
- Fixed disabled timed preset expanding calendar
10+
- Fixed Color Order setting shown for analog busses
11+
- Fixed incorrect operator (#2566)
12+
513
#### Build 2203011
614

715
- IR rewrite (PR #2561), supports CCT

platformio.ini

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -335,10 +335,10 @@ build_flags = ${common.build_flags_esp32} -D WLED_RELEASE_NAME=ESP32_Ethernet -D
335335
lib_deps = ${esp32.lib_deps}
336336
board_build.partitions = ${esp32.default_partitions}
337337

338-
# ESP32 ETH build that fits in old 1M app space (disables Blynk, Cronixie, and Hue sync)
338+
# ESP32 ETH build that fits in old 1M app space (disables Blynk and Hue sync)
339339
[env:esp32_eth_ota1mapp]
340340
extends = env:esp32_eth
341-
build_flags = ${common.build_flags_esp32} -D WLED_RELEASE_NAME=ESP32_Ethernet_OTA -D RLYPIN=-1 -D WLED_USE_ETHERNET -D BTNPIN=-1 -D WLED_DISABLE_BLYNK -D WLED_DISABLE_CRONIXIE -D WLED_DISABLE_HUESYNC
341+
build_flags = ${common.build_flags_esp32} -D WLED_RELEASE_NAME=ESP32_Ethernet_OTA -D RLYPIN=-1 -D WLED_USE_ETHERNET -D BTNPIN=-1 -D WLED_DISABLE_BLYNK -D WLED_DISABLE_HUESYNC
342342

343343
[env:esp32s2_saola]
344344
board = esp32-s2-saola-1
@@ -529,7 +529,6 @@ board = esp32dev
529529
530530
upload_speed = 921600
531531
build_flags = ${common.build_flags_esp32} -D WLED_DISABLE_BROWNOUT_DET -D WLED_DISABLE_INFRARED
532-
#-D ELEKSTUBE_DIMMING # if enabled, scale display brightness (does not set backlight, only scales contents)
533532
-D USERMOD_RTC
534533
-D USERMOD_ELEKSTUBE_IPS
535534
-D LEDPIN=12

platformio_override.ini.sample

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ build_flags = ${common.build_flags_esp8266}
2222
; -D WLED_DISABLE_OTA
2323
; -D WLED_DISABLE_ALEXA
2424
; -D WLED_DISABLE_BLYNK
25-
; -D WLED_DISABLE_CRONIXIE
2625
; -D WLED_DISABLE_HUESYNC
2726
; -D WLED_DISABLE_INFRARED
2827
; -D WLED_DISABLE_WEBSOCKETS

readme.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ A fast and feature-rich implementation of an ESP8266/ESP32 webserver to control
2727
- Presets can be used to automatically execute API calls
2828
- Nightlight function (gradually dims down)
2929
- Full OTA software updatability (HTTP + ArduinoOTA), password protectable
30-
- Configurable analog clock + support for the Cronixie kit by Diamex
30+
- Configurable analog clock (Cronixie, 7-segment and EleksTube IPS clock support via usermods)
3131
- Configurable Auto Brightness limit for safer operation
3232
- Filesystem-based config for easier backup of presets and settings
3333

usermods/Cronixie/readme.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Cronixie clock usermod
2+
3+
This usermod supports driving the Cronixie M and L clock kits by Diamex.
4+
5+
## Installation
6+
7+
Compile and upload after adding `-D USERMOD_CRONIXIE` to `build_flags` of your PlatformIO environment.
8+
Make sure the Auto Brightness Limiter is enabled at 420mA (!) and configure 60 WS281x LEDs.
Lines changed: 301 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,301 @@
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+
};

usermods/EleksTube_IPS/usermod_elekstube_ips.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ class ElekstubeIPSUsermod : public Usermod {
1111
static const char _tubeSeg[];
1212
static const char _digitOffset[];
1313

14+
char cronixieDisplay[7] = "HHMMSS";
15+
1416
TFTs tfts;
1517
void updateClockDisplay(TFTs::show_t show=TFTs::yes) {
1618
bool set[6] = {false};
@@ -123,6 +125,7 @@ class ElekstubeIPSUsermod : public Usermod {
123125
*/
124126
void addToJsonState(JsonObject& root)
125127
{
128+
root["nx"] = cronixieDisplay;
126129
root[FPSTR(_digitOffset)] = tfts.digitOffset;
127130
}
128131

@@ -133,6 +136,10 @@ class ElekstubeIPSUsermod : public Usermod {
133136
*/
134137
void readFromJsonState(JsonObject& root)
135138
{
139+
if (root["nx"].is<const char*>()) {
140+
strncpy(cronixieDisplay, root["nx"], 6);
141+
}
142+
136143
uint8_t digitOffsetPrev = tfts.digitOffset;
137144
tfts.digitOffset = root[FPSTR(_digitOffset)] | tfts.digitOffset;
138145
if (tfts.digitOffset > 240) tfts.digitOffset = 240;

0 commit comments

Comments
 (0)