Tasmota/lib/lib_display/UDisplay/uDisplay_dma.cpp
2025-10-12 17:15:02 +02:00

133 lines
3.1 KiB
C++

#include "uDisplay.h"
#include "uDisplay_config.h"
#ifdef ESP32
// ===== DMA Initialization and Control =====
// ESP 32 DMA section , derived from TFT_eSPI
bool uDisplay::initDMA(int32_t ctrl_cs) {
if (DMA_Enabled) return false;
esp_err_t ret;
spi_bus_config_t buscfg = {
.mosi_io_num = spi_mosi,
.miso_io_num = -1,
.sclk_io_num = spi_clk,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
.max_transfer_sz = width() * height() * 2 + 8, // TFT screen size
.flags = 0,
.intr_flags = 0
};
spi_device_interface_config_t devcfg = {
.command_bits = 0,
.address_bits = 0,
.dummy_bits = 0,
.mode = SPI_MODE3,
.duty_cycle_pos = 0,
.cs_ena_pretrans = 0,
.cs_ena_posttrans = 0,
.clock_speed_hz = spi_speed*1000000,
.input_delay_ns = 0,
.spics_io_num = ctrl_cs,
.flags = SPI_DEVICE_NO_DUMMY, //0,
.queue_size = 1,
.pre_cb = 0, //dc_callback, //Callback to handle D/C line
.post_cb = 0
};
ret = spi_bus_initialize(spi_host, &buscfg, 1);
ESP_ERROR_CHECK(ret);
ret = spi_bus_add_device(spi_host, &devcfg, &dmaHAL);
ESP_ERROR_CHECK(ret);
DMA_Enabled = true;
spiBusyCheck = 0;
return true;
}
void uDisplay::deInitDMA(void) {
if (!DMA_Enabled) return;
spi_bus_remove_device(dmaHAL);
spi_bus_free(spi_host);
DMA_Enabled = false;
}
bool uDisplay::dmaBusy(void) {
if (!DMA_Enabled || !spiBusyCheck) return false;
spi_transaction_t *rtrans;
esp_err_t ret;
uint8_t checks = spiBusyCheck;
for (int i = 0; i < checks; ++i) {
ret = spi_device_get_trans_result(dmaHAL, &rtrans, 0);
if (ret == ESP_OK) spiBusyCheck--;
}
//Serial.print("spiBusyCheck=");Serial.println(spiBusyCheck);
if (spiBusyCheck == 0) return false;
return true;
}
void uDisplay::dmaWait(void) {
if (!DMA_Enabled || !spiBusyCheck) return;
spi_transaction_t *rtrans;
esp_err_t ret;
for (int i = 0; i < spiBusyCheck; ++i) {
ret = spi_device_get_trans_result(dmaHAL, &rtrans, portMAX_DELAY);
assert(ret == ESP_OK);
}
spiBusyCheck = 0;
}
// ===== DMA Data Transfer Functions =====
void uDisplay::pushPixelsDMA(uint16_t* image, uint32_t len) {
if ((len == 0) || (!DMA_Enabled)) return;
dmaWait();
esp_err_t ret;
memset(&trans, 0, sizeof(spi_transaction_t));
trans.user = (void *)1;
trans.tx_buffer = image; //finally send the line data
trans.length = len * 16; //Data length, in bits
trans.flags = 0; //SPI_TRANS_USE_TXDATA flag
ret = spi_device_queue_trans(dmaHAL, &trans, portMAX_DELAY);
assert(ret == ESP_OK);
spiBusyCheck++;
if (!lvgl_param.async_dma) {
dmaWait();
}
}
void uDisplay::pushPixels3DMA(uint8_t* image, uint32_t len) {
if ((len == 0) || (!DMA_Enabled)) return;
dmaWait();
esp_err_t ret;
memset(&trans, 0, sizeof(spi_transaction_t));
trans.user = (void *)1;
trans.tx_buffer = image; //finally send the line data
trans.length = len * 24; //Data length, in bits
trans.flags = 0; //SPI_TRANS_USE_TXDATA flag
ret = spi_device_queue_trans(dmaHAL, &trans, portMAX_DELAY);
assert(ret == ESP_OK);
spiBusyCheck++;
if (!lvgl_param.async_dma) {
dmaWait();
}
}
#endif // ESP32