Files
capacitance-lcd-driver/main/lcd_reg.c
2026-06-17 17:28:22 +08:00

176 lines
4.0 KiB
C

#include "lcd_reg.h"
#include "driver/gpio.h"
#include "driver/spi_master.h"
#include "freertos/FreeRTOS.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 void lcd_delay_ms(uint32_t ms)
{
vTaskDelay(pdMS_TO_TICKS(ms));
}
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_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_command(uint8_t command)
{
gpio_set_level(LCD_PIN_DC, 0);
lcd_spi_write(&command, 1);
}
static void lcd_write_data8(uint8_t data)
{
gpio_set_level(LCD_PIN_DC, 1);
lcd_spi_write(&data, 1);
}
static void lcd_write_data16(uint16_t data)
{
uint8_t bytes[2] = {
(uint8_t)(data >> 8),
(uint8_t)data,
};
gpio_set_level(LCD_PIN_DC, 1);
lcd_spi_write(bytes, sizeof(bytes));
}
static void lcd_set_window(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1)
{
lcd_write_command(LCD_CMD_CASET);
lcd_write_data16(x0);
lcd_write_data16(x1);
lcd_write_command(LCD_CMD_RASET);
lcd_write_data16(y0);
lcd_write_data16(y1);
lcd_write_command(LCD_CMD_RAMWR);
}
void lcd_reg_init(void)
{
lcd_gpio_init();
lcd_spi_init();
lcd_reset();
lcd_write_command(LCD_CMD_SWRESET);
lcd_delay_ms(150);
lcd_write_command(LCD_CMD_SLPOUT);
lcd_delay_ms(120);
lcd_write_command(LCD_CMD_COLMOD);
lcd_write_data8(0x05);
lcd_write_command(LCD_CMD_MADCTL);
lcd_write_data8(0x60);
lcd_write_command(LCD_CMD_INVON);
lcd_write_command(LCD_CMD_DISPON);
lcd_delay_ms(120);
}
void lcd_reg_draw_image(const uint16_t *image)
{
enum { LINES_PER_TRANSFER = 20 };
static uint16_t line_buffer[LCD_WIDTH * LINES_PER_TRANSFER];
lcd_set_window(0, 0, LCD_WIDTH - 1, LCD_HEIGHT - 1);
gpio_set_level(LCD_PIN_DC, 1);
for (uint32_t y = 0; y < LCD_HEIGHT; y += LINES_PER_TRANSFER) {
uint32_t lines = LINES_PER_TRANSFER;
if ((y + lines) > LCD_HEIGHT) {
lines = LCD_HEIGHT - y;
}
uint32_t pixels = LCD_WIDTH * lines;
for (uint32_t i = 0; i < pixels; i++) {
uint16_t color = image[(y * LCD_WIDTH) + i];
line_buffer[i] = (uint16_t)((color >> 8) | (color << 8));
}
lcd_spi_write(line_buffer, pixels * 2);
}
}