Landzo_K60Z_WebServer/src/lcd_impl.c

106 lines
3.0 KiB
C

/* Drivers */
#include "fsl_clock.h"
#include "fsl_common.h"
#include "fsl_dmamux.h"
#include "fsl_edma.h"
#include "fsl_gpio.h"
/* Board */
#include "peripherals.h"
#include "pin_mux.h"
/* LCD panel */
#include "epd-spi/panel/lcd_generic_ssd1289.h"
/* Private header */
#include "lcd_impl.h"
#define IMPL_LCD_DMA_INSTANCE DMA0
#define IMPL_LCD_DMAMUX_INSTANCE DMAMUX0
#define IMPL_LCD_DMA_CHANNEL 0
#define IMPL_LCD_DMA_REQUEST 63 /* Always On Request */
#define IMPL_LCD_COMMAND_BASE ((uint16_t *)0x70000000)
#define IMPL_LCD_DATA_BASE ((uint16_t *)0x78000000)
static void epd_impl_edma_callback(edma_handle_t *handle, void *userData, bool transferDone, uint32_t tcds) {
lcd_impl_t *impl = userData;
BaseType_t xHigherPriorityTaskWoken;
xSemaphoreGiveFromISR(impl->dma_semphr, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
epd_ret_t epd_impl_init(void *handle) {
lcd_impl_t *impl = handle;
impl->dma_semphr = xSemaphoreCreateBinary();
if (impl->dma_semphr == NULL) {
return EPD_FAIL;
}
/* Async flush */
xSemaphoreGive(impl->dma_semphr);
DMAMUX_SetSource(IMPL_LCD_DMAMUX_INSTANCE, IMPL_LCD_DMA_CHANNEL, IMPL_LCD_DMA_REQUEST);
DMAMUX_EnableChannel(IMPL_LCD_DMAMUX_INSTANCE, IMPL_LCD_DMA_CHANNEL);
EDMA_CreateHandle(&impl->dma_handle, IMPL_LCD_DMA_INSTANCE, IMPL_LCD_DMA_CHANNEL);
EDMA_SetCallback(&impl->dma_handle, epd_impl_edma_callback, impl);
return EPD_OK;
}
epd_ret_t epd_impl_write_command(void *handle, uint8_t *command, uint32_t len) {
uint32_t param_len = (len - 1) / 2;
*IMPL_LCD_COMMAND_BASE = command[0];
for (uint32_t i = 0; i < param_len; i++) {
uint16_t le_param = (command[2 * i + 1] << 8) | command[2 * i + 2];
*IMPL_LCD_DATA_BASE = le_param;
}
return EPD_OK;
}
epd_ret_t epd_impl_write_data(void *handle, uint8_t *data, uint32_t len) {
lcd_impl_t *impl = handle;
uint32_t data_len = (len / 2);
edma_transfer_config_t cfg = {
.srcAddr = (uint32_t)data,
.srcTransferSize = kEDMA_TransferSize2Bytes,
.srcOffset = 2U,
.destAddr = (uint32_t)IMPL_LCD_DATA_BASE,
.destTransferSize = kEDMA_TransferSize2Bytes,
.destOffset = 0U, /* Destination is not self-incrementing */
.majorLoopCounts = data_len,
.minorLoopBytes = 2,
};
/* Wait for DMA transfer complete. */
if (xSemaphoreTake(impl->dma_semphr, portMAX_DELAY) != pdPASS) {
return EPD_FAIL;
}
EDMA_SubmitTransfer(&impl->dma_handle, &cfg);
EDMA_StartTransfer(&impl->dma_handle);
return EPD_OK;
}
epd_ret_t epd_impl_reset(void *handle) {
GPIO_WritePinOutput(BOARD_INITPINS_TFT_RESET_GPIO, BOARD_INITPINS_TFT_RESET_PIN, 0U);
vTaskDelay(pdMS_TO_TICKS(20));
GPIO_WritePinOutput(BOARD_INITPINS_TFT_RESET_GPIO, BOARD_INITPINS_TFT_RESET_PIN, 1U);
vTaskDelay(pdMS_TO_TICKS(20));
return EPD_OK;
}
epd_ret_t epd_impl_delay(void *handle, uint32_t msec) {
vTaskDelay(pdMS_TO_TICKS(msec));
return EPD_OK;
}