Add generic SystemWaitIfBusy() to fix WS2812 led flicker

Add generic SystemWaitIfBusy() to fix WS2812 led flicker
This commit is contained in:
Theo Arends 2023-05-24 16:21:59 +02:00
parent 4be618fe7b
commit fc67cca8b4
5 changed files with 48 additions and 19 deletions

View File

@ -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

View File

@ -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
*

View File

@ -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());

View File

@ -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;
}
@ -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;

View File

@ -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++) {