feat: add support for inverted data transfer in SPI communication

This commit is contained in:
GW_MC
2026-01-29 14:29:19 +08:00
parent f433abb9ec
commit 6b0dcafd8b
2 changed files with 37 additions and 3 deletions

View File

@@ -191,7 +191,7 @@ esp_err_t EPDHandler::dangerous_epd_write_data_without_lock_(const uint8_t data)
return err; 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); ESP_LOGI(TAG, "transfer_spi_data: waiting to send %zu bytes of data", length);
SemaphoreGuard transaction_guard(spi_transaction_mutex_); 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 offset = 0;
size_t remaining = length; size_t remaining = length;
gpio_set_level(PIN_DC, 1); // Data mode 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) { while (remaining > 0) {
size_t transfer_size = (remaining < DMA_TRANSFER_CHUNK_SIZE) ? remaining : DMA_TRANSFER_CHUNK_SIZE; 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 = {}; spi_transaction_t t = {};
t.length = transfer_size * 8; // Length in bits 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); esp_err_t ret = spi_device_polling_transmit(spi_, &t);
if (ret != ESP_OK) { 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", ESP_LOGE(TAG, "Current free DMA-capable memory size: %u bytes",
heap_caps_get_free_size(MALLOC_CAP_DMA)); 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; 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); ESP_LOGI(TAG, "transfer_spi_data: completed sending %zu bytes of data", length);
return ESP_OK; return ESP_OK;
} }

View File

@@ -15,7 +15,7 @@ public:
esp_err_t epd_write_cmd(const uint8_t cmd, uint32_t transaction_id); 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_data(const uint8_t data, uint32_t transaction_id);
esp_err_t epd_write_cmd_with_data(const uint8_t cmd, std::vector<uint8_t>& data, uint32_t transaction_id); esp_err_t epd_write_cmd_with_data(const uint8_t cmd, std::vector<uint8_t>& 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; bool is_busy(void) const;
void wait_for_idle(void) const; void wait_for_idle(void) const;