Fix tube flicker and review fixes

- The bit-banged WS2812 update disables interrupts (about 30 us per
  pixel), which made the lit tube stay on longer and flash. neoShow()
  now only sends when the pixels changed (fixed colour was resent every
  second) and waits for the dark gap between tubes; the bit-bang strip
  has no headroom pixels. This also fixed digits that seemed to hang.
- 4 WS2812 on this board, one per tube (not 8)
- Saving the firmware URL in the web UI no longer starts an HTTP
  update; never update from an empty URL
- Restart once after the first switch from AP mode to WiFi, so
  ArduinoOTA and MQTT start on the real network
- Optional web UI password (WEB_USER/WEB_PASSWORD in secrets.h);
  /getConfiguration returns the stored WiFi and MQTT passwords
- Cathode protect: random mode now starts at a random tube (the +-1
  start digits were swapped and then overwritten)
- Apply the unused gamma table to wheel colours
- LOOP_DIAG (off by default): main-loop stalls in /getCurrentInfos,
  which now also reports uptime and free heap

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
mangavalkandClaude Opus 5.5 committed 2026-10-25 22:18:39 +01:00
1 parent e5d1757035
commit 5fbae6247c
7 files changed
+189 -80

No files matched your search

@@ -36,6 +36,16 @@ const int PWMrefresh = 11000;
const int PWM_min = 1000;
const int PWM_max = 10000;
volatile boolean displayBlank = true; //true while the ISR outputs an all-off word (gap between tubes)
// Wait (at most one tube slot) until the tubes are dark. Used before work that blocks interrupts for a
// few hundred microseconds (the bit-banged WS2812 update): if the ISR is delayed in the dark gap, only the
// gap gets longer. Delayed while a tube is lit, that tube would stay on longer and flash brighter.
void displayWaitBlank() {
uint32_t started = micros();
while (!displayBlank && ((micros() - started) < 3000)) {}
}
// Shift one 16-bit word into both 595s and latch it. Also called from main code via clearTubes(),
// so the caller must keep the ISR out (see clearTubes()).
static inline void IRAM_ATTR write595(uint16_t w) {
@@ -139,6 +149,7 @@ void IRAM_ATTR writeDisplay() { //timer1 ISR, single-shot: must re-arm timer1
if (w) w |= 1 << anodeBits[pos];
}
write595(w);
displayBlank = (w == 0);
timer1_write(timer);
}