ESP32S2_Cal_Demo/main/app_lib_epd_impl.c

153 lines
4.1 KiB
C

#include <string.h>
#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;
}