feat(display): Implement singleton pattern for EInkDisplayHandler and enhance buffer allocation checks
This commit is contained in:
@@ -13,22 +13,31 @@
|
||||
#define MINIMUM_POWER_ON_DELAY_MS 100
|
||||
#define PARTIAL_REFRESH_THRESHOLD 5 // Full refresh every N partial refreshes
|
||||
|
||||
static uint8_t* DRAW_BUFFER; // 1 bit per pixel
|
||||
static uint8_t* OLD_DRAW_BUFFER; // 1 bit per pixel
|
||||
static uint8_t* black_data;
|
||||
static uint8_t* white_data;
|
||||
// Static flag to prevent multiple instances (these buffers are large, only one display allowed)
|
||||
static bool display_instance_exists = false;
|
||||
|
||||
EInkDisplayHandler::EInkDisplayHandler() {
|
||||
black_data = static_cast<uint8_t*>(heap_caps_malloc(DISPLAY_BUFFER_SIZE, MALLOC_CAP_SPIRAM));
|
||||
white_data = static_cast<uint8_t*>(heap_caps_malloc(DISPLAY_BUFFER_SIZE, MALLOC_CAP_SPIRAM));
|
||||
DRAW_BUFFER = static_cast<uint8_t*>(heap_caps_malloc(DISPLAY_BUFFER_SIZE, MALLOC_CAP_SPIRAM));
|
||||
OLD_DRAW_BUFFER = static_cast<uint8_t*>(heap_caps_malloc(DISPLAY_BUFFER_SIZE, MALLOC_CAP_SPIRAM));
|
||||
memset(black_data, 0xFF, DISPLAY_BUFFER_SIZE); // eink uses 1 for black
|
||||
memset(white_data, 0x00, DISPLAY_BUFFER_SIZE);
|
||||
memset(DRAW_BUFFER, 0x00, DISPLAY_BUFFER_SIZE); // start with all white (0 = white in e-ink)
|
||||
memset(OLD_DRAW_BUFFER, 0x00, DISPLAY_BUFFER_SIZE); // start with all white (0 = white in e-ink)
|
||||
draw_buffer_ = DRAW_BUFFER;
|
||||
old_buffer_ = OLD_DRAW_BUFFER;
|
||||
if (display_instance_exists) {
|
||||
ESP_LOGE(TAG, "Only one EInkDisplayHandler instance allowed!");
|
||||
return;
|
||||
}
|
||||
display_instance_exists = true;
|
||||
|
||||
black_data_ = static_cast<uint8_t*>(heap_caps_malloc(DISPLAY_BUFFER_SIZE, MALLOC_CAP_SPIRAM));
|
||||
white_data_ = static_cast<uint8_t*>(heap_caps_malloc(DISPLAY_BUFFER_SIZE, MALLOC_CAP_SPIRAM));
|
||||
draw_buffer_ = static_cast<uint8_t*>(heap_caps_malloc(DISPLAY_BUFFER_SIZE, MALLOC_CAP_SPIRAM));
|
||||
old_buffer_ = static_cast<uint8_t*>(heap_caps_malloc(DISPLAY_BUFFER_SIZE, MALLOC_CAP_SPIRAM));
|
||||
|
||||
// Check for allocation failures
|
||||
if (!black_data_ || !white_data_ || !draw_buffer_ || !old_buffer_) {
|
||||
ESP_LOGE(TAG, "Failed to allocate display buffers!");
|
||||
return;
|
||||
}
|
||||
|
||||
memset(black_data_, 0xFF, DISPLAY_BUFFER_SIZE); // eink uses 1 for black
|
||||
memset(white_data_, 0x00, DISPLAY_BUFFER_SIZE);
|
||||
memset(draw_buffer_, 0x00, DISPLAY_BUFFER_SIZE); // start with all white (0 = white in e-ink)
|
||||
memset(old_buffer_, 0x00, DISPLAY_BUFFER_SIZE); // start with all white (0 = white in e-ink)
|
||||
|
||||
refresh_mutex_ = xSemaphoreCreateMutex();
|
||||
if (refresh_mutex_ == nullptr) {
|
||||
@@ -46,18 +55,23 @@ EInkDisplayHandler::~EInkDisplayHandler() {
|
||||
if (tp_io_handle_ != nullptr) {
|
||||
esp_lcd_panel_io_del(tp_io_handle_);
|
||||
}
|
||||
if (black_data != nullptr) {
|
||||
heap_caps_free(black_data);
|
||||
if (black_data_ != nullptr) {
|
||||
heap_caps_free(black_data_);
|
||||
black_data_ = nullptr;
|
||||
}
|
||||
if (white_data != nullptr) {
|
||||
heap_caps_free(white_data);
|
||||
if (white_data_ != nullptr) {
|
||||
heap_caps_free(white_data_);
|
||||
white_data_ = nullptr;
|
||||
}
|
||||
if (DRAW_BUFFER != nullptr) {
|
||||
heap_caps_free(DRAW_BUFFER);
|
||||
if (draw_buffer_ != nullptr) {
|
||||
heap_caps_free(draw_buffer_);
|
||||
draw_buffer_ = nullptr;
|
||||
}
|
||||
if (OLD_DRAW_BUFFER != nullptr) {
|
||||
heap_caps_free(OLD_DRAW_BUFFER);
|
||||
if (old_buffer_ != nullptr) {
|
||||
heap_caps_free(old_buffer_);
|
||||
old_buffer_ = nullptr;
|
||||
}
|
||||
display_instance_exists = false;
|
||||
}
|
||||
|
||||
esp_err_t EInkDisplayHandler::deep_sleep_display(void) {
|
||||
@@ -185,7 +199,7 @@ esp_err_t EInkDisplayHandler::full_write(const uint8_t* framebuffer, const bool
|
||||
ESP_LOGE(TAG, "Failed to send old data command: %s", esp_err_to_name(err));
|
||||
return err;
|
||||
}
|
||||
err = epd_handler_.transfer_spi_data(white_basemap ? black_data : white_data, DISPLAY_BUFFER_SIZE, transaction_guard.transaction_id()); // Send all white data (0xFF)
|
||||
err = epd_handler_.transfer_spi_data(white_basemap ? black_data_ : white_data_, DISPLAY_BUFFER_SIZE, transaction_guard.transaction_id()); // Send all white data (0xFF)
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to send all white data for old data: %s", esp_err_to_name(err));
|
||||
return err;
|
||||
@@ -449,7 +463,7 @@ esp_err_t EInkDisplayHandler::partial_refresh(const uint8_t* incoming_partial_fr
|
||||
esp_err_t EInkDisplayHandler::clear_display(void) {
|
||||
ESP_LOGV(TAG, "Clearing display to all white...");
|
||||
|
||||
esp_err_t err = full_write(white_data, false);
|
||||
esp_err_t err = full_write(white_data_, false);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to clear display: %s", esp_err_to_name(err));
|
||||
return err;
|
||||
|
||||
Reference in New Issue
Block a user