Files
LCD/main/lcd_reg.c

161 lines
3.5 KiB
C

#include "lcd_reg.h"
#include "driver/gpio.h"
#include "driver/spi_master.h"
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include "freertos/task.h"
#define LCD_SPI_HOST SPI2_HOST
#define LCD_PIN_BL 1
#define LCD_PIN_CS 8
#define LCD_PIN_DC 9
#define LCD_PIN_RES 10
#define LCD_PIN_SDA 11
#define LCD_PIN_SCL 12
#define LCD_CMD_SWRESET 0x01
#define LCD_CMD_SLPOUT 0x11
#define LCD_CMD_COLMOD 0x3A
#define LCD_CMD_MADCTL 0x36
#define LCD_CMD_CASET 0x2A
#define LCD_CMD_RASET 0x2B
#define LCD_CMD_RAMWR 0x2C
#define LCD_CMD_INVON 0x21
#define LCD_CMD_DISPON 0x29
static spi_device_handle_t lcd_spi;
static SemaphoreHandle_t lcd_mutex;
/* Timing */
void lcd_delay_ms(uint32_t ms)
{
vTaskDelay(pdMS_TO_TICKS(ms));
}
/* Low-level bus and command helpers */
static void lcd_spi_write(const void *data, uint32_t length)
{
spi_transaction_t transaction = {
.length = length * 8,
.tx_buffer = data,
};
spi_device_polling_transmit(lcd_spi, &transaction);
}
static void lcd_write(uint8_t dc_level, uint16_t value, uint8_t length)
{
uint8_t bytes[2] = {
(uint8_t)(value >> 8),
(uint8_t)value,
};
const uint8_t *data = length == 1 ? &bytes[1] : bytes;
gpio_set_level(LCD_PIN_DC, dc_level);
lcd_spi_write(data, length);
}
void lcd_set_window(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1)
{
lcd_write(0, LCD_CMD_CASET, 1);
lcd_write(1, x0, 2);
lcd_write(1, x1, 2);
lcd_write(0, LCD_CMD_RASET, 1);
lcd_write(1, y0, 2);
lcd_write(1, y1, 2);
lcd_write(0, LCD_CMD_RAMWR, 1);
}
void lcd_write_pixels(const void *data, uint32_t length)
{
gpio_set_level(LCD_PIN_DC, 1);
lcd_spi_write(data, length);
}
/* Initialization */
static void lcd_gpio_init(void)
{
gpio_config_t gpio_config_data = {
.pin_bit_mask = (1ULL << LCD_PIN_BL) | (1ULL << LCD_PIN_DC) | (1ULL << LCD_PIN_RES),
.mode = GPIO_MODE_OUTPUT,
.pull_up_en = GPIO_PULLUP_DISABLE,
.pull_down_en = GPIO_PULLDOWN_DISABLE,
.intr_type = GPIO_INTR_DISABLE,
};
gpio_config(&gpio_config_data);
gpio_set_level(LCD_PIN_BL, 1);
gpio_set_level(LCD_PIN_DC, 0);
gpio_set_level(LCD_PIN_RES, 1);
}
static void lcd_spi_init(void)
{
spi_bus_config_t bus_config = {
.mosi_io_num = LCD_PIN_SDA,
.miso_io_num = -1,
.sclk_io_num = LCD_PIN_SCL,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
.max_transfer_sz = LCD_WIDTH * 40 * 2,
};
spi_bus_initialize(LCD_SPI_HOST, &bus_config, SPI_DMA_CH_AUTO);
spi_device_interface_config_t device_config = {
.clock_speed_hz = 40000000,
.mode = 0,
.spics_io_num = LCD_PIN_CS,
.queue_size = 8,
};
spi_bus_add_device(LCD_SPI_HOST, &device_config, &lcd_spi);
}
static void lcd_reset(void)
{
gpio_set_level(LCD_PIN_RES, 1);
lcd_delay_ms(20);
gpio_set_level(LCD_PIN_RES, 0);
lcd_delay_ms(20);
gpio_set_level(LCD_PIN_RES, 1);
lcd_delay_ms(120);
}
static void lcd_controller_init(void)
{
lcd_write(0, LCD_CMD_SWRESET, 1);
lcd_delay_ms(150);
lcd_write(0, LCD_CMD_SLPOUT, 1);
lcd_delay_ms(120);
lcd_write(0, LCD_CMD_COLMOD, 1);
lcd_write(1, 0x05, 1);
lcd_write(0, LCD_CMD_MADCTL, 1);
lcd_write(1, 0x60, 1);
lcd_write(0, LCD_CMD_INVON, 1);
lcd_write(0, LCD_CMD_DISPON, 1);
lcd_delay_ms(120);
}
void lcd_reg_init(void)
{
lcd_mutex = xSemaphoreCreateMutex();
lcd_gpio_init();
lcd_spi_init();
lcd_reset();
lcd_controller_init();
}