Public Access
el512: refresh health counters and quiet warnings
The panel driver counts ring refills, the largest gap between refills, frame swaps, swap timeouts and I2S TX FIFO underruns (takeStats()). The ESPHome component checks them every 10 s and logs a warning only when the ESP32 side of the signal had a problem, plus a debug summary per minute. Measured with Wi-Fi on: ~4600 refills/s, max gap < 0.4 ms (lead 1.7 ms), no underruns or timeouts, so remaining blinks come from the signal being disturbed on the wires (Wi-Fi transmit bursts), not from the refresh. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
963590cdfe
commit
f3212ea969
4 files changed
+80
-1
No files matched your search
@@ -1,6 +1,7 @@
|
||||
#include "el512_display.h"
|
||||
|
||||
#include <esp_heap_caps.h>
|
||||
#include <esp_private/esp_clk.h>
|
||||
|
||||
#include "esphome/core/hal.h"
|
||||
#include "esphome/core/log.h"
|
||||
@@ -22,7 +23,10 @@ void EL512Display::setup() {
|
||||
}
|
||||
|
||||
void EL512Display::loop() {
|
||||
if (this->still_alive_page_ == nullptr || this->panel_ == nullptr || !this->panel_->running())
|
||||
if (this->panel_ == nullptr || !this->panel_->running())
|
||||
return;
|
||||
this->check_refresh_health_();
|
||||
if (this->still_alive_page_ == nullptr)
|
||||
return;
|
||||
const bool active = this->is_still_alive_playing();
|
||||
const uint32_t now = millis();
|
||||
@@ -44,6 +48,37 @@ void EL512Display::loop() {
|
||||
this->update();
|
||||
}
|
||||
|
||||
// Refresh health, checked every 10 s: warn when the ESP32 side of the video
|
||||
// signal had a problem (DMA FIFO underrun, a refill later than the ring's lead,
|
||||
// or a frame swap that timed out); otherwise a debug summary once a minute.
|
||||
// No warnings while the panel misbehaves means the signal left the ESP32
|
||||
// intact and was disturbed on the wires (e.g. by Wi-Fi transmit bursts).
|
||||
void EL512Display::check_refresh_health_() {
|
||||
const uint32_t now = millis();
|
||||
if (this->health_checked_ == 0) {
|
||||
// Skip the start-up period (the FIFO is empty once while the DMA starts).
|
||||
this->panel_->takeStats();
|
||||
this->health_checked_ = now;
|
||||
return;
|
||||
}
|
||||
if (now - this->health_checked_ < 10000)
|
||||
return;
|
||||
const uint32_t period_ms = now - this->health_checked_;
|
||||
this->health_checked_ = now;
|
||||
const auto s = this->panel_->takeStats();
|
||||
const float max_gap_us = s.maxGapCycles / (float) (esp_clk_cpu_freq() / 1000000);
|
||||
const float lead_us = 1e6f * EL512Panel::RING_LINES * EL512Panel::CLOCKS_PER_ROW / EL512Panel::PIXEL_CLOCK_HZ;
|
||||
if (s.underruns > 0 || s.showTimeouts > 0 || max_gap_us > lead_us * 0.75f) {
|
||||
ESP_LOGW(TAG, "Refresh problem in the last %us: %u FIFO underruns, %u swap timeouts, max refill gap %.0f us",
|
||||
(unsigned) (period_ms / 1000), (unsigned) s.underruns, (unsigned) s.showTimeouts, max_gap_us);
|
||||
}
|
||||
if (now - this->health_logged_ >= 60000) {
|
||||
this->health_logged_ = now;
|
||||
ESP_LOGD(TAG, "Refresh OK: %.0f refills/s, max gap %.0f us, %u swaps", s.refills * 1000.0f / period_ms,
|
||||
max_gap_us, (unsigned) s.swaps);
|
||||
}
|
||||
}
|
||||
|
||||
void EL512Display::play_still_alive() {
|
||||
if (this->still_alive_page_ == nullptr)
|
||||
return;
|
||||
|
||||
Reference in new issue
Block a user