diff --git a/main/display/epd_handler.cpp b/main/display/epd_handler.cpp index ca14465..e161e23 100644 --- a/main/display/epd_handler.cpp +++ b/main/display/epd_handler.cpp @@ -191,7 +191,7 @@ esp_err_t EPDHandler::dangerous_epd_write_data_without_lock_(const uint8_t data) return err; } -esp_err_t EPDHandler::transfer_spi_data(const uint8_t* data, const size_t& length, uint32_t transaction_id) { +esp_err_t EPDHandler::transfer_spi_data(const uint8_t* data, const size_t& length, uint32_t transaction_id, bool inverted) { ESP_LOGI(TAG, "transfer_spi_data: waiting to send %zu bytes of data", length); SemaphoreGuard transaction_guard(spi_transaction_mutex_); @@ -212,12 +212,37 @@ esp_err_t EPDHandler::transfer_spi_data(const uint8_t* data, const size_t& lengt size_t offset = 0; size_t remaining = length; gpio_set_level(PIN_DC, 1); // Data mode + + // Allocate a temporary buffer for inverted data (only if inverted) + uint8_t* temp_transfer_buffer = nullptr; + if (inverted) { + temp_transfer_buffer = (uint8_t*)heap_caps_malloc(DMA_TRANSFER_CHUNK_SIZE, MALLOC_CAP_DMA); + if (temp_transfer_buffer == nullptr) { + ESP_LOGE(TAG, "Failed to allocate memory for inverted data transfer buffer"); + ESP_LOGI(TAG, "Current free heap size: %u bytes", esp_get_free_heap_size()); + ESP_LOGI(TAG, "Current free DMA-capable memory size: %u bytes", + heap_caps_get_free_size(MALLOC_CAP_DMA)); + return ESP_ERR_NO_MEM; + } + } + while (remaining > 0) { size_t transfer_size = (remaining < DMA_TRANSFER_CHUNK_SIZE) ? remaining : DMA_TRANSFER_CHUNK_SIZE; + const uint8_t* transfer_buffer = nullptr; + if (inverted) { + // Invert only the current chunk into the temporary buffer + for (size_t i = 0; i < transfer_size; ++i) { + temp_transfer_buffer[i] = ~data[offset + i]; + } + transfer_buffer = temp_transfer_buffer; + } else { + transfer_buffer = data + offset; + } + spi_transaction_t t = {}; t.length = transfer_size * 8; // Length in bits - t.tx_buffer = data + offset; + t.tx_buffer = transfer_buffer; esp_err_t ret = spi_device_polling_transmit(spi_, &t); if (ret != ESP_OK) { @@ -227,6 +252,10 @@ esp_err_t EPDHandler::transfer_spi_data(const uint8_t* data, const size_t& lengt ESP_LOGE(TAG, "Current free DMA-capable memory size: %u bytes", heap_caps_get_free_size(MALLOC_CAP_DMA)); } + if (inverted && temp_transfer_buffer != nullptr) { + // Free the temporary inverted buffer + heap_caps_free(temp_transfer_buffer); + } return ret; } @@ -240,6 +269,11 @@ esp_err_t EPDHandler::transfer_spi_data(const uint8_t* data, const size_t& lengt } } + if (inverted && temp_transfer_buffer != nullptr) { + // Free the temporary inverted buffer + heap_caps_free(temp_transfer_buffer); + } + ESP_LOGI(TAG, "transfer_spi_data: completed sending %zu bytes of data", length); return ESP_OK; } diff --git a/main/display/epd_handler.h b/main/display/epd_handler.h index 0a32e5e..23a8ef4 100644 --- a/main/display/epd_handler.h +++ b/main/display/epd_handler.h @@ -15,7 +15,7 @@ public: esp_err_t epd_write_cmd(const uint8_t cmd, uint32_t transaction_id); esp_err_t epd_write_data(const uint8_t data, uint32_t transaction_id); esp_err_t epd_write_cmd_with_data(const uint8_t cmd, std::vector& data, uint32_t transaction_id); - esp_err_t transfer_spi_data(const uint8_t* data, const size_t& length, uint32_t transaction_id); + esp_err_t transfer_spi_data(const uint8_t* data, const size_t& length, uint32_t transaction_id, bool inverted = false); bool is_busy(void) const; void wait_for_idle(void) const;