diff --git a/CHANGELOG.md b/CHANGELOG.md
index 59a4bad14..6172e26d8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,12 @@
### Builds after release 0.12.0
+#### Build 2104210
+
+- Added `tb` to JSON state, allowing setting the timebase (set tb=0 to start e.g. wipe effect from the beginning). Receive only.
+- Slightly raised Solid mode refresh rate to work with LEDs (TM1814) that require refresh rates of at least 2fps
+- Added sunrise and sunset calculation to the backup JSON time source
+
#### Build 2104151
- `NUM_STRIPS` no longer required with compile-time strip defaults
diff --git a/usermods/PIR_sensor_switch/usermod_PIR_sensor_switch.h b/usermods/PIR_sensor_switch/usermod_PIR_sensor_switch.h
index 73216684b..bd92b9d94 100644
--- a/usermods/PIR_sensor_switch/usermod_PIR_sensor_switch.h
+++ b/usermods/PIR_sensor_switch/usermod_PIR_sensor_switch.h
@@ -372,7 +372,7 @@ after (SEGENV.data);
- // initialize start of the TV-Colors
- if (SEGENV.call == 0) {
- tvSimulator->pixelNum = ((uint8_t)random(18)) * numTVPixels / 18; // Begin at random movie (18 in total)
+ uint8_t colorSpeed = map(SEGMENT.speed, 0, UINT8_MAX, 1, 20);
+ uint8_t colorIntensity = map(SEGMENT.intensity, 0, UINT8_MAX, 10, 30);
+
+ i = SEGMENT.speed << 8 | SEGMENT.intensity;
+ if (i != tvSimulator->sliderValues) {
+ tvSimulator->sliderValues = i;
+ SEGENV.aux1 = 0;
}
- // Read next 16-bit (5/6/5) color
- hi = pgm_read_byte(&tv_colors[tvSimulator->pixelNum * 2 ]);
- lo = pgm_read_byte(&tv_colors[tvSimulator->pixelNum * 2 + 1]);
+ #ifndef WLED_DISABLE_FX_HIGH_FLASH_USE
+ /*
+ * this code uses the real color data from tv_colos.h
+ */
- // Expand to 24-bit (8/8/8)
- r8 = (hi & 0xF8) | (hi >> 5);
- g8 = ((hi << 5) & 0xff) | ((lo & 0xE0) >> 3) | ((hi & 0x06) >> 1);
- b8 = ((lo << 3) & 0xff) | ((lo & 0x1F) >> 2);
+ // initialize start of the TV-Colors
+ if (SEGENV.aux1 == 0) {
+ tvSimulator->pixelNum = ((uint8_t)random8(18)) * numTVPixels / 18; // Begin at random movie (18 in total)
+ SEGENV.aux1 = 1;
+ }
+
+ // Read next 16-bit (5/6/5) color
+ hi = pgm_read_byte(&tv_colors[tvSimulator->pixelNum * 2 ]);
+ lo = pgm_read_byte(&tv_colors[tvSimulator->pixelNum * 2 + 1]);
+
+ // Expand to 24-bit (8/8/8)
+ r8 = (hi & 0xF8) | (hi >> 5);
+ g8 = ((hi << 5) & 0xff) | ((lo & 0xE0) >> 3) | ((hi & 0x06) >> 1);
+ b8 = ((lo << 3) & 0xff) | ((lo & 0x1F) >> 2);
- // Apply gamma correction, further expand to 16/16/16
- nr = (uint8_t)gamma8(r8) * 257; // New R/G/B
- ng = (uint8_t)gamma8(g8) * 257;
- nb = (uint8_t)gamma8(b8) * 257;
+ // Apply gamma correction, further expand to 16/16/16
+ nr = (uint8_t)gamma8(r8) * 257; // New R/G/B
+ ng = (uint8_t)gamma8(g8) * 257;
+ nb = (uint8_t)gamma8(b8) * 257;
+ #else
+ /*
+ * this code calculates the color to be used and save 18k of flash memory
+ */
+
+ // create a new sceene
+ if (((millis() - tvSimulator->sceeneStart) >= tvSimulator->sceeneDuration) || SEGENV.aux1 == 0) {
+ tvSimulator->sceeneStart = millis(); // remember the start of the new sceene
+ tvSimulator->sceeneDuration = random16(60* 250* colorSpeed, 60* 750 * colorSpeed); // duration of a "movie sceene" which has similar colors (5 to 15 minutes with max speed slider)
+ tvSimulator->sceeneColorHue = random16( 0, 768); // random start color-tone for the sceene
+ tvSimulator->sceeneColorSat = random8 ( 100, 130 + colorIntensity); // random start color-saturation for the sceene
+ tvSimulator->sceeneColorBri = random8 ( 200, 240); // random start color-brightness for the sceene
+ SEGENV.aux1 = 1;
+ SEGENV.aux0 = 0;
+ }
+
+ // slightly change the color-tone in this sceene
+ if ( SEGENV.aux0 == 0) {
+ // hue change in both directions
+ j = random8(4 * colorIntensity);
+ hue = (random8() < 128) ? ((j < tvSimulator->sceeneColorHue) ? tvSimulator->sceeneColorHue - j : 767 - tvSimulator->sceeneColorHue - j) : // negative
+ ((j + tvSimulator->sceeneColorHue) < 767 ? tvSimulator->sceeneColorHue + j : tvSimulator->sceeneColorHue + j - 767) ; // positive
+
+ // saturation
+ j = random8(2 * colorIntensity);
+ sat = (tvSimulator->sceeneColorSat - j) < 0 ? 0 : tvSimulator->sceeneColorSat - j;
+
+ // brightness
+ j = random8(100);
+ bri = (tvSimulator->sceeneColorBri - j) < 0 ? 0 : tvSimulator->sceeneColorBri - j;
+
+ // calculate R,G,B from HSV
+ // Source: https://blog.adafruit.com/2012/03/14/constant-brightness-hsb-to-rgb-algorithm/
+ { // just to create a local scope for the variables
+ uint8_t temp[5], n = (hue >> 8) % 3;
+ uint8_t x = ((((hue & 255) * sat) >> 8) * bri) >> 8;
+ uint8_t s = ( (256 - sat) * bri) >> 8;
+ temp[0] = temp[3] = s;
+ temp[1] = temp[4] = x + s;
+ temp[2] = bri - x;
+ tvSimulator->actualColorR = temp[n + 2];
+ tvSimulator->actualColorG = temp[n + 1];
+ tvSimulator->actualColorB = temp[n ];
+ }
+ }
+ // Apply gamma correction, further expand to 16/16/16
+ nr = (uint8_t)gamma8(tvSimulator->actualColorR) * 257; // New R/G/B
+ ng = (uint8_t)gamma8(tvSimulator->actualColorG) * 257;
+ nb = (uint8_t)gamma8(tvSimulator->actualColorB) * 257;
+ #endif
if (SEGENV.aux0 == 0) { // initialize next iteration
SEGENV.aux0 = 1;
- // increase color-index for next loop
- tvSimulator->pixelNum++;
- if (tvSimulator->pixelNum >= numTVPixels) tvSimulator->pixelNum = 0;
+ #ifndef WLED_DISABLE_FX_HIGH_FLASH_USE
+ // increase color-index for next loop
+ tvSimulator->pixelNum++;
+ if (tvSimulator->pixelNum >= numTVPixels) tvSimulator->pixelNum = 0;
+ #endif
// randomize total duration and fade duration for the actual color
- tvSimulator->totalTime = random(250, 2500); // Semi-random pixel-to-pixel time
- tvSimulator->fadeTime = random(0, tvSimulator->totalTime); // Pixel-to-pixel transition time
- if (random(10) < 3) tvSimulator->fadeTime = 0; // Force scene cut 30% of time
+ tvSimulator->totalTime = random16(250, 2500); // Semi-random pixel-to-pixel time
+ tvSimulator->fadeTime = random16(0, tvSimulator->totalTime); // Pixel-to-pixel transition time
+ if (random8(10) < 3) tvSimulator->fadeTime = 0; // Force scene cut 30% of time
tvSimulator->startTime = millis();
} // end of initialization
@@ -3894,7 +3966,6 @@ uint16_t WS2812FX::mode_tv_simulator(void) {
}
return FRAMETIME;
- #endif
}
/*
diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp
index a679cbc6d..de53d8cc0 100644
--- a/wled00/FX_fcn.cpp
+++ b/wled00/FX_fcn.cpp
@@ -43,7 +43,7 @@
19, 18, 17, 16, 15, 20, 21, 22, 23, 24, 29, 28, 27, 26, 25]}
*/
-//factory defaults LED setup (for multistrip boards)
+//factory defaults LED setup
//#define PIXEL_COUNTS 30, 30, 30, 30
//#define DATA_PINS 16, 1, 3, 4
//#define DEFAULT_LED_TYPE TYPE_WS2812_RGB
diff --git a/wled00/bus_wrapper.h b/wled00/bus_wrapper.h
index a71d951f5..a5e34c7f3 100644
--- a/wled00/bus_wrapper.h
+++ b/wled00/bus_wrapper.h
@@ -28,7 +28,7 @@
#define I_8266_U1_400_3 10
#define I_8266_DM_400_3 11
#define I_8266_BB_400_3 12
-//TM1418 (RGBW)
+//TM1814 (RGBW)
#define I_8266_U0_TM1_4 13
#define I_8266_U1_TM1_4 14
#define I_8266_DM_TM1_4 15
@@ -68,7 +68,7 @@
#define I_32_R7_400_3 44
#define I_32_I0_400_3 45
#define I_32_I1_400_3 46
-//TM1418 (RGBW)
+//TM1814 (RGBW)
#define I_32_R0_TM1_4 47
#define I_32_R1_TM1_4 48
#define I_32_R2_TM1_4 49
@@ -117,7 +117,7 @@
#define B_8266_U1_400_3 NeoPixelBrightnessBus //3 chan, esp8266, gpio2
#define B_8266_DM_400_3 NeoPixelBrightnessBus //3 chan, esp8266, gpio3
#define B_8266_BB_400_3 NeoPixelBrightnessBus //3 chan, esp8266, bb (any pin)
-//TM1418 (RGBW)
+//TM1814 (RGBW)
#define B_8266_U0_TM1_4 NeoPixelBrightnessBus
#define B_8266_U1_TM1_4 NeoPixelBrightnessBus
#define B_8266_DM_TM1_4 NeoPixelBrightnessBus
@@ -159,7 +159,7 @@
#define B_32_R7_400_3 NeoPixelBrightnessBus
#define B_32_I0_400_3 NeoPixelBrightnessBus
#define B_32_I1_400_3 NeoPixelBrightnessBus
-//TM1418 (RGBW)
+//TM1814 (RGBW)
#define B_32_R0_TM1_4 NeoPixelBrightnessBus
#define B_32_R1_TM1_4 NeoPixelBrightnessBus
#define B_32_R2_TM1_4 NeoPixelBrightnessBus
@@ -198,6 +198,14 @@
//handles pointer type conversion for all possible bus types
class PolyBus {
public:
+ // Begin & initialize the PixelSettings for TM1814 strips.
+ template
+ static void beginTM1814(void* busPtr) {
+ T tm1814_strip = static_cast(busPtr);
+ tm1814_strip->Begin();
+ // Max current for each LED (22.5 mA).
+ tm1814_strip->SetPixelSettings(NeoTm1814Settings(/*R*/225, /*G*/225, /*B*/225, /*W*/225));
+ }
static void begin(void* busPtr, uint8_t busType, uint8_t* pins) {
switch (busType) {
case I_NONE: break;
@@ -214,10 +222,10 @@ class PolyBus {
case I_8266_U1_400_3: (static_cast(busPtr))->Begin(); break;
case I_8266_DM_400_3: (static_cast(busPtr))->Begin(); break;
case I_8266_BB_400_3: (static_cast(busPtr))->Begin(); break;
- case I_8266_U0_TM1_4: (static_cast(busPtr))->Begin(); break;
- case I_8266_U1_TM1_4: (static_cast(busPtr))->Begin(); break;
- case I_8266_DM_TM1_4: (static_cast(busPtr))->Begin(); break;
- case I_8266_BB_TM1_4: (static_cast(busPtr))->Begin(); break;
+ case I_8266_U0_TM1_4: beginTM1814(busPtr); break;
+ case I_8266_U1_TM1_4: beginTM1814(busPtr); break;
+ case I_8266_DM_TM1_4: beginTM1814(busPtr); break;
+ case I_8266_BB_TM1_4: beginTM1814(busPtr); break;
case I_HS_DOT_3: (static_cast(busPtr))->Begin(); break;
case I_HS_DOT_4: (static_cast(busPtr))->Begin(); break;
case I_HS_LPD_3: (static_cast(busPtr))->Begin(); break;
@@ -255,16 +263,16 @@ class PolyBus {
case I_32_R7_400_3: (static_cast(busPtr))->Begin(); break;
case I_32_I0_400_3: (static_cast(busPtr))->Begin(); break;
case I_32_I1_400_3: (static_cast(busPtr))->Begin(); break;
- case I_32_R0_TM1_4: (static_cast(busPtr))->Begin(); break;
- case I_32_R1_TM1_4: (static_cast(busPtr))->Begin(); break;
- case I_32_R2_TM1_4: (static_cast(busPtr))->Begin(); break;
- case I_32_R3_TM1_4: (static_cast(busPtr))->Begin(); break;
- case I_32_R4_TM1_4: (static_cast(busPtr))->Begin(); break;
- case I_32_R5_TM1_4: (static_cast(busPtr))->Begin(); break;
- case I_32_R6_TM1_4: (static_cast(busPtr))->Begin(); break;
- case I_32_R7_TM1_4: (static_cast(busPtr))->Begin(); break;
- case I_32_I0_TM1_4: (static_cast(busPtr))->Begin(); break;
- case I_32_I1_TM1_4: (static_cast(busPtr))->Begin(); break;
+ case I_32_R0_TM1_4: beginTM1814(busPtr); break;
+ case I_32_R1_TM1_4: beginTM1814(busPtr); break;
+ case I_32_R2_TM1_4: beginTM1814(busPtr); break;
+ case I_32_R3_TM1_4: beginTM1814(busPtr); break;
+ case I_32_R4_TM1_4: beginTM1814(busPtr); break;
+ case I_32_R5_TM1_4: beginTM1814(busPtr); break;
+ case I_32_R6_TM1_4: beginTM1814(busPtr); break;
+ case I_32_R7_TM1_4: beginTM1814(busPtr); break;
+ case I_32_I0_TM1_4: beginTM1814(busPtr); break;
+ case I_32_I1_TM1_4: beginTM1814(busPtr); break;
// ESP32 can (and should, to avoid inadvertantly driving the chip select signal) specify the pins used for SPI, but only in begin()
case I_HS_DOT_3: (static_cast(busPtr))->Begin(pins[1], -1, pins[0], -1); break;
case I_HS_DOT_4: (static_cast(busPtr))->Begin(pins[1], -1, pins[0], -1); break;
@@ -878,6 +886,8 @@ class PolyBus {
return (rgbwOverride ? I_8266_U0_NEO_4 : I_8266_U0_NEO_3) + offset;
case TYPE_WS2811_400KHZ:
return I_8266_U0_400_3 + offset;
+ case TYPE_TM1814:
+ return I_8266_U0_TM1_4 + offset;
}
#else //ESP32
uint8_t offset = num; //RMT bus # == bus index in BusManager
@@ -890,6 +900,8 @@ class PolyBus {
return (rgbwOverride ? I_32_R0_NEO_4 : I_32_R0_NEO_3) + offset;
case TYPE_WS2811_400KHZ:
return I_32_R0_400_3 + offset;
+ case TYPE_TM1814:
+ return I_32_R0_TM1_4 + offset;
}
#endif
}
diff --git a/wled00/json.cpp b/wled00/json.cpp
index d9ba64b46..7ab3b321d 100644
--- a/wled00/json.cpp
+++ b/wled00/json.cpp
@@ -214,6 +214,9 @@ bool deserializeState(JsonObject root)
jsonTransitionOnce = true;
}
strip.setTransition(transitionDelayTemp);
+
+ tr = root[F("tb")] | -1;
+ if (tr >= 0) strip.timebase = ((uint32_t)tr) - millis();
int cy = root[F("pl")] | -2;
if (cy > -2) presetCyclingEnabled = (cy >= 0);
@@ -235,9 +238,16 @@ bool deserializeState(JsonObject root)
receiveNotifications = udpn["recv"] | receiveNotifications;
bool noNotification = udpn[F("nn")]; //send no notification just for this request
- unsigned long timein = root[F("time")] | UINT32_MAX;
+ unsigned long timein = root[F("time")] | UINT32_MAX; //backup time source if NTP not synced
if (timein != UINT32_MAX) {
- if (millis() - ntpLastSyncTime > 50000000L) setTime(timein);
+ time_t prev = now();
+ if (millis() - ntpLastSyncTime > 50000000L) {
+ setTime(timein);
+ if (abs(now() - prev) > 60L) {
+ updateLocalTime();
+ calculateSunriseAndSunset();
+ }
+ }
if (presetsModifiedTime == 0) presetsModifiedTime = timein;
}
diff --git a/wled00/ntp.cpp b/wled00/ntp.cpp
index d2ecd9b71..3a3d8310e 100644
--- a/wled00/ntp.cpp
+++ b/wled00/ntp.cpp
@@ -330,7 +330,7 @@ int getSunriseUTC(int year, int month, int day, float lat, float lon, bool sunse
float M = (0.9856f * t) - 3.289f;
//4. calculate the Sun's true longitude
- float L = fmod_t(M + (1.916f * sin_t(DEG_TO_RAD*M)) + (0.020f * sin_t(2*DEG_TO_RAD*M)) + 282.634f, 360.0f);
+ float L = fmod_t(M + (1.916f * sin_t(DEG_TO_RAD*M)) + (0.02f * sin_t(2*DEG_TO_RAD*M)) + 282.634f, 360.0f);
//5a. calculate the Sun's right ascension
float RA = fmod_t(RAD_TO_DEG*atan_t(0.91764f * tan_t(DEG_TO_RAD*L)), 360.0f);
diff --git a/wled00/wled.h b/wled00/wled.h
index 4da987fad..0ec6dd4a4 100644
--- a/wled00/wled.h
+++ b/wled00/wled.h
@@ -8,7 +8,7 @@
*/
// version code in format yymmddb (b = daily build)
-#define VERSION 2104191
+#define VERSION 2104210
//uncomment this if you have a "my_config.h" file you'd like to use
//#define WLED_USE_MY_CONFIG