172 lines
4.4 KiB
C
172 lines
4.4 KiB
C
/* IDF */
|
|
#include "esp_log.h"
|
|
#include "esp_system.h"
|
|
|
|
/* FreeRTOS */
|
|
#include "freertos/FreeRTOS.h"
|
|
#include "freertos/task.h"
|
|
|
|
/* IDF drivers */
|
|
#include "driver/gpio.h"
|
|
#include "driver/spi_master.h"
|
|
|
|
/* Private */
|
|
#include "st7789_lcd.h"
|
|
|
|
#define LCD_GPIO_RST 4
|
|
#define LCD_GPIO_DC 2
|
|
#define LCD_GPIO_MOSI 23
|
|
#define LCD_GPIO_SCK 18
|
|
#define LCD_GPIO_BL 5
|
|
|
|
#define LCD_SPI_HOST SPI3_HOST
|
|
#define LCD_SPI_MAX_SIZE 4096
|
|
#define LCD_SPI_MHZ 10
|
|
|
|
#define APP_LOG_TAG "LCD_IMPL"
|
|
|
|
static void lcd_impl_spi_pre_cb(spi_transaction_t *txn) {
|
|
int dc = (int)txn->user;
|
|
|
|
gpio_set_level(LCD_GPIO_DC, dc);
|
|
}
|
|
|
|
spi_device_handle_t lcd_impl_init(void) {
|
|
gpio_set_direction(LCD_GPIO_BL, GPIO_MODE_OUTPUT);
|
|
gpio_set_direction(LCD_GPIO_DC, GPIO_MODE_OUTPUT);
|
|
gpio_set_direction(LCD_GPIO_RST, GPIO_MODE_OUTPUT);
|
|
|
|
gpio_set_level(LCD_GPIO_BL, 0);
|
|
gpio_set_level(LCD_GPIO_RST, 1);
|
|
gpio_set_level(LCD_GPIO_DC, 0);
|
|
|
|
gpio_set_pull_mode(LCD_GPIO_MOSI, GPIO_PULLUP_ONLY);
|
|
gpio_set_pull_mode(LCD_GPIO_SCK, GPIO_PULLUP_ONLY);
|
|
|
|
esp_err_t err;
|
|
spi_device_handle_t spi_handle;
|
|
spi_bus_config_t bus_cfg = {
|
|
.mosi_io_num = LCD_GPIO_MOSI,
|
|
.sclk_io_num = LCD_GPIO_SCK,
|
|
.miso_io_num = -1,
|
|
.quadhd_io_num = -1,
|
|
.quadwp_io_num = -1,
|
|
.max_transfer_sz = LCD_SPI_MAX_SIZE,
|
|
};
|
|
|
|
spi_device_interface_config_t if_cfg = {
|
|
.clock_speed_hz = LCD_SPI_MHZ * 1000 * 1000,
|
|
.mode = 3,
|
|
.spics_io_num = -1,
|
|
.queue_size = 1,
|
|
.pre_cb = lcd_impl_spi_pre_cb,
|
|
};
|
|
|
|
err = spi_bus_initialize(LCD_SPI_HOST, &bus_cfg, SPI_DMA_CH_AUTO);
|
|
if (err != ESP_OK) {
|
|
ESP_LOGE(APP_LOG_TAG, "SPI bus initialization failed");
|
|
return NULL;
|
|
}
|
|
|
|
err = spi_bus_add_device(LCD_SPI_HOST, &if_cfg, &spi_handle);
|
|
if (err != ESP_OK) {
|
|
ESP_LOGE(APP_LOG_TAG, "SPI add device failed");
|
|
return NULL;
|
|
}
|
|
|
|
return spi_handle;
|
|
}
|
|
|
|
st7789_lcd_ret_t lcd_impl_reset(void *pdev) {
|
|
/* Hardware reset is necessary if CS not used !! */
|
|
|
|
ESP_LOGI(APP_LOG_TAG, "LCD reset!");
|
|
|
|
gpio_set_level(LCD_GPIO_RST, 0U);
|
|
vTaskDelay(pdMS_TO_TICKS(10));
|
|
gpio_set_level(LCD_GPIO_RST, 1U);
|
|
vTaskDelay(pdMS_TO_TICKS(100));
|
|
|
|
return ST7789_SUCCESS;
|
|
}
|
|
|
|
st7789_lcd_ret_t lcd_impl_delay(void *pdev, uint32_t msec) {
|
|
vTaskDelay(pdMS_TO_TICKS(msec));
|
|
|
|
return ST7789_SUCCESS;
|
|
}
|
|
|
|
st7789_lcd_ret_t lcd_impl_write_command(void *pdev, uint8_t *command, uint32_t len) {
|
|
ESP_LOGD(APP_LOG_TAG, "Write CMD: %d bytes, 0x%02x...", len, command[0]);
|
|
|
|
esp_err_t ret;
|
|
|
|
spi_device_handle_t handle = pdev;
|
|
|
|
spi_transaction_t txn = {
|
|
.length = 0x08,
|
|
.tx_buffer = command,
|
|
.user = (void *)0U,
|
|
};
|
|
|
|
ret = spi_device_polling_transmit(handle, &txn);
|
|
if (ret != ESP_OK) {
|
|
ESP_LOGE(APP_LOG_TAG, "CMD transmit failed phase 1");
|
|
return ST7789_FAIL;
|
|
}
|
|
|
|
/* This command has parameters */
|
|
if (len > 1) {
|
|
txn.length = (len - 1) * 8;
|
|
txn.tx_buffer = &command[1];
|
|
txn.user = (void *)1U;
|
|
|
|
gpio_set_level(LCD_GPIO_DC, 1U);
|
|
ret = spi_device_polling_transmit(handle, &txn);
|
|
if (ret != ESP_OK) {
|
|
ESP_LOGE(APP_LOG_TAG, "CMD transmit failed phase 2");
|
|
return ST7789_FAIL;
|
|
}
|
|
}
|
|
|
|
return ST7789_SUCCESS;
|
|
}
|
|
|
|
st7789_lcd_ret_t lcd_impl_write_data(void *pdev, uint8_t *data, uint32_t len) {
|
|
ESP_LOGD(APP_LOG_TAG, "Write DATA: %d bytes", len);
|
|
|
|
esp_err_t ret;
|
|
spi_device_handle_t handle = pdev;
|
|
|
|
spi_transaction_t txn;
|
|
uint32_t d_ptr = 0U;
|
|
|
|
txn.user = (void *)1U;
|
|
|
|
while (len > LCD_SPI_MAX_SIZE) {
|
|
txn.tx_buffer = &data[d_ptr];
|
|
txn.length = LCD_SPI_MAX_SIZE * 8;
|
|
|
|
ret = spi_device_polling_transmit(handle, &txn);
|
|
if (ret != ESP_OK) {
|
|
ESP_LOGE(APP_LOG_TAG, "DATA transmit failed phase 1");
|
|
return ST7789_FAIL;
|
|
}
|
|
|
|
len -= LCD_SPI_MAX_SIZE;
|
|
d_ptr += LCD_SPI_MAX_SIZE;
|
|
}
|
|
|
|
if (len > 0) {
|
|
txn.tx_buffer = &data[d_ptr];
|
|
txn.length = len * 8;
|
|
|
|
ret = spi_device_polling_transmit(handle, &txn);
|
|
if (ret != ESP_OK) {
|
|
ESP_LOGE(APP_LOG_TAG, "DATA transmit failed phase 2");
|
|
return ST7789_FAIL;
|
|
}
|
|
}
|
|
|
|
return ST7789_SUCCESS;
|
|
} |