From fc67cca8b42265c909b2d84ec6e906d511e6f7b1 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 24 May 2023 16:21:59 +0200 Subject: [PATCH] Add generic SystemWaitIfBusy() to fix WS2812 led flicker Add generic SystemWaitIfBusy() to fix WS2812 led flicker --- tasmota/tasmota.ino | 1 + tasmota/tasmota_support/support.ino | 25 +++++++++++++++++++ .../xdrv_52_3_berry_leds.ino | 17 +++++++------ tasmota/tasmota_xlgt_light/xlgt_01_ws2812.ino | 17 ++++++++----- .../tasmota_xsns_sensor/xsns_02_analog.ino | 7 ++---- 5 files changed, 48 insertions(+), 19 deletions(-) diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index 8958e121c..56434faea 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -310,6 +310,7 @@ struct TasmotaGlobal_t { bool no_autoexec; // Disable autoexec uint8_t user_globals[3]; // User set global temp/hum/press + uint8_t busy_time; // Time in ms to allow executing of time critical functions uint8_t init_state; // Tasmota init state uint8_t heartbeat_inverted; // Heartbeat pulse inverted flag uint8_t spi_enabled; // SPI configured diff --git a/tasmota/tasmota_support/support.ino b/tasmota/tasmota_support/support.ino index fbeae1688..e7bad295e 100755 --- a/tasmota/tasmota_support/support.ino +++ b/tasmota/tasmota_support/support.ino @@ -2210,6 +2210,31 @@ bool TimeReachedUsec(uint32_t timer) return (passed >= 0); } +void SystemSetBusy(uint32_t busy) { +/* + TasmotaGlobal.busy_time = millis(); + SetNextTimeInterval(TasmotaGlobal.busy_time, busy +1); + if (!TasmotaGlobal.busy_time) { + TasmotaGlobal.busy_time++; + } +*/ + TasmotaGlobal.busy_time = busy; +} + +void SystemWaitIfBusy(void) { + if (TasmotaGlobal.busy_time) { +/* + // Calls to millis() interrupt RMT and defeats our goal + if (!TimeReached(TasmotaGlobal.busy_time)) { + delay(1); + } +*/ + delay(TasmotaGlobal.busy_time); + + TasmotaGlobal.busy_time = 0; + } +} + /*********************************************************************************************\ * Syslog * diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_leds.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_leds.ino index 3d6b8f86b..f8327c68b 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_leds.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_leds.ino @@ -39,15 +39,15 @@ typedef NeoPixelBus neopixel_sk6812_gr /*********************************************************************************************\ * Native functions mapped to Berry functions - * + * * import unishox - * - * + * + * \*********************************************************************************************/ extern "C" { // # Native commands - // # 00 : ctor + // # 00 : ctor // # 01 : begin void -> void // # 02 : show void -> void // # 03 : CanShow void -> bool @@ -88,7 +88,7 @@ extern "C" { int32_t argc = be_top(vm); // Get the number of arguments if (argc >= 2 && be_isint(vm, 2)) { int32_t cmd = be_toint(vm, 2); - + if (0 == cmd) { // 00 : ctor (leds:int, gpio:int) -> void if (!(argc >= 6 && be_isint(vm, 3) && be_isint(vm, 4) && be_isint(vm, 5) && be_isint(vm, 6))) { be_raise(vm, "value_error", "bad arguments for neopixelbus:ctor"); @@ -136,6 +136,7 @@ extern "C" { case 2: // # 02 : show void -> void if (s_ws2812_grb) s_ws2812_grb->Show(); if (s_sk6812_grbw) s_sk6812_grbw->Show(); + SystemSetBusy(4); break; case 3: // # 03 : CanShow void -> bool if (s_ws2812_grb) be_pushbool(vm, s_ws2812_grb->CanShow()); @@ -154,7 +155,7 @@ extern "C" { uint8_t * pixels; if (s_ws2812_grb) pixels = s_ws2812_grb->Pixels(); if (s_sk6812_grbw) pixels = s_sk6812_grbw->Pixels(); - + be_pushcomptr(vm, pixels); } break; @@ -196,11 +197,11 @@ extern "C" { if (s_ws2812_grb) { RgbColor rgb = s_ws2812_grb->GetPixelColor(idx); - be_pushint(vm, (rgb.R << 16) | (rgb.G << 8) | rgb.B); + be_pushint(vm, (rgb.R << 16) | (rgb.G << 8) | rgb.B); } if (s_sk6812_grbw) { RgbwColor rgbw = s_sk6812_grbw->GetPixelColor(idx); - be_pushint(vm, (rgbw.W << 24) | (rgb.R << 16) | (rgb.G << 8) | rgb.B); + be_pushint(vm, (rgbw.W << 24) | (rgb.R << 16) | (rgb.G << 8) | rgb.B); } } break; diff --git a/tasmota/tasmota_xlgt_light/xlgt_01_ws2812.ino b/tasmota/tasmota_xlgt_light/xlgt_01_ws2812.ino index c0f7ff7e5..8dd87f738 100644 --- a/tasmota/tasmota_xlgt_light/xlgt_01_ws2812.ino +++ b/tasmota/tasmota_xlgt_light/xlgt_01_ws2812.ino @@ -212,6 +212,11 @@ long wsmap(long x, long in_min, long in_max, long out_min, long out_max) { return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; } +void Ws2812LibStripShow(void) { + strip->Show(); + SystemSetBusy(Settings->light_pixels >> 2); // 256 / 64 = 4 +} + void Ws2812StripShow(void) { #if (USE_WS2812_CTYPE > NEO_3LED) @@ -232,7 +237,7 @@ void Ws2812StripShow(void) strip->SetPixelColor(i, c); } } - strip->Show(); + Ws2812LibStripShow(); } int mod(int a, int b) @@ -549,7 +554,7 @@ void Ws2812DDP(void) void Ws2812Clear(void) { strip->ClearTo(0); - strip->Show(); + Ws2812LibStripShow(); Ws2812.show_next = 1; } @@ -575,7 +580,7 @@ void Ws2812SetColor(uint32_t led, uint8_t red, uint8_t green, uint8_t blue, uint } if (!Ws2812.suspend_update) { - strip->Show(); + Ws2812LibStripShow(); Ws2812.show_next = 1; } } @@ -616,7 +621,7 @@ void Ws2812ForceSuspend (void) void Ws2812ForceUpdate (void) { Ws2812.suspend_update = false; - strip->Show(); + Ws2812LibStripShow(); Ws2812.show_next = 1; } @@ -634,7 +639,7 @@ bool Ws2812SetChannels(void) void Ws2812ShowScheme(void) { uint32_t scheme = Settings->light_scheme - Ws2812.scheme_offset; - + #ifdef USE_NETWORK_LIGHT_SCHEMES if ((scheme != 9) && (ddp_udp_up)) { ddp_udp.stop(); @@ -797,7 +802,7 @@ size_t Ws2812StripGetPixelSize(void) { // return true if strip was dirty and an actual refresh was triggered bool Ws2812StripRefresh(void) { if (strip->IsDirty()) { - strip->Show(); + Ws2812LibStripShow(); return true; } else { return false; diff --git a/tasmota/tasmota_xsns_sensor/xsns_02_analog.ino b/tasmota/tasmota_xsns_sensor/xsns_02_analog.ino index 12292d0b0..4351b12aa 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_02_analog.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_02_analog.ino @@ -317,11 +317,8 @@ uint16_t AdcRead(uint32_t pin, uint32_t factor) { // factor 3 = 8 samples // factor 4 = 16 samples // factor 5 = 32 samples -#ifdef USE_LIGHT - if ((XLGT_01 == TasmotaGlobal.light_driver) && LightPower()) { - delay(5); // analogRead() interferes with DMA/RMT so wait for a decent amount of time - } -#endif // USE_LIGHT + SystemWaitIfBusy(); + uint32_t samples = 1 << factor; uint32_t analog = 0; for (uint32_t i = 0; i < samples; i++) {