#include #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "user_board.h" #include "app_lib_epd_impl.h" #define MAXIMUM_XFER_SIZE 4000 #define MAX_BUSY_POLL_COUNT 10 static void _spi_pre_transfere_callback(spi_transaction_t *txn) { gpio_set_level(BOARD_EPD_DC_PIN, (int)txn->user); } void app_lib_epd_impl_init(app_lib_epd_impl_t *impl) { gpio_config_t io_config = { .intr_type = GPIO_INTR_DISABLE, .mode = GPIO_MODE_OUTPUT_OD, .pin_bit_mask = (1 << BOARD_EPD_RES_PIN), .pull_up_en = GPIO_PULLUP_ENABLE, .pull_down_en = GPIO_PULLDOWN_DISABLE }; gpio_config(&io_config); io_config.pin_bit_mask = (1 << BOARD_EPD_DC_PIN); io_config.pull_up_en = GPIO_PULLUP_DISABLE; io_config.mode = GPIO_MODE_OUTPUT; gpio_config(&io_config); io_config.pin_bit_mask = (1 << BOARD_EPD_BUSY_PIN); io_config.mode = GPIO_MODE_INPUT; gpio_config(&io_config); spi_bus_config_t bus_cfg = { .mosi_io_num = BOARD_EPD_SPI_MOSI_PIN, .sclk_io_num = BOARD_EPD_SPI_SCK_PIN, .miso_io_num = -1, .quadhd_io_num = -1, .quadwp_io_num = -1, .max_transfer_sz = MAXIMUM_XFER_SIZE }; spi_device_interface_config_t interface_config = { .clock_speed_hz = 16 * 1000 * 1000, .mode = 0, .spics_io_num = BOARD_EPD_SPI_CS_PIN, .queue_size = 7, .pre_cb = _spi_pre_transfere_callback, .flags = SPI_DEVICE_HALFDUPLEX, }; ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &bus_cfg, SPI_DMA_CH_AUTO)); ESP_ERROR_CHECK(spi_bus_add_device(SPI2_HOST, &interface_config, &impl->spi_handle)); } gd_epd_042_ret_t app_lib_epd_impl_reset(app_lib_epd_impl_t *impl) { gpio_set_level(BOARD_EPD_RES_PIN, 1); vTaskDelay(10); gpio_set_level(BOARD_EPD_RES_PIN, 0); vTaskDelay(10); gpio_set_level(BOARD_EPD_RES_PIN, 1); vTaskDelay(10); gpio_set_level(BOARD_EPD_RES_PIN, 0); vTaskDelay(10); gpio_set_level(BOARD_EPD_RES_PIN, 1); vTaskDelay(10); gpio_set_level(BOARD_EPD_RES_PIN, 0); vTaskDelay(10); gpio_set_level(BOARD_EPD_RES_PIN, 1); vTaskDelay(10); return EPD_OK; } gd_epd_042_ret_t app_lib_epd_delay_ms(app_lib_epd_impl_t *impl, uint32_t ms) { vTaskDelay(pdMS_TO_TICKS(ms)); return EPD_OK; } gd_epd_042_ret_t app_lib_epd_impl_write_cmd(app_lib_epd_impl_t *impl, uint8_t *cmd, uint8_t len) { esp_err_t ret; spi_transaction_t txn = { .length = 8, .tx_buffer = cmd, .user = (void *)0 }; ret = spi_device_polling_transmit(impl->spi_handle, &txn); if(ret != ESP_OK) return EPD_ERR; if(len > 1) { txn.length = 8 * (len - 1); txn.tx_buffer = &cmd[1]; txn.user = (void *)1; ret = spi_device_polling_transmit(impl->spi_handle, &txn); if(ret != ESP_OK) return EPD_ERR; } return EPD_OK; } gd_epd_042_ret_t app_lib_epd_impl_write_data(app_lib_epd_impl_t *impl, uint8_t *data, uint32_t len) { esp_err_t ret; uint8_t *dma_buffer = heap_caps_malloc(MAXIMUM_XFER_SIZE, MALLOC_CAP_DMA); if(dma_buffer == NULL) return EPD_ERR; uint8_t has_partial = (len % MAXIMUM_XFER_SIZE ? 1 : 0); uint32_t txn_count = len / MAXIMUM_XFER_SIZE + has_partial; spi_transaction_t txn = { .length = 8 * len, .tx_buffer = data, .user = (void *)1 }; for(uint32_t i = 0; i < txn_count; i++) { uint16_t txn_bytes = MAXIMUM_XFER_SIZE; if(i == (txn_count - 1) && has_partial) { txn_bytes = len % MAXIMUM_XFER_SIZE; } memcpy(dma_buffer, &data[i * MAXIMUM_XFER_SIZE], txn_bytes); txn.length = 8 * txn_bytes; txn.tx_buffer = dma_buffer; ret = spi_device_polling_transmit(impl->spi_handle, &txn); if(ret != ESP_OK) return EPD_ERR; } free(dma_buffer); return EPD_OK; } gd_epd_042_ret_t app_lib_epd_impl_poll_busy(app_lib_epd_impl_t *impl) { uint8_t count = MAX_BUSY_POLL_COUNT; while(gpio_get_level(BOARD_EPD_BUSY_PIN) == 0) { vTaskDelay(10); if(count == 0) { return EPD_ERR; } count--; } return EPD_OK; }