Files
AutoFilm-ESP32/components/hal_display/hal_display_lcd2004.c

191 lines
3.7 KiB
C

#include "hal_display.h"
#include <string.h>
#include "driver/i2c_master.h"
#include "esp_rom_sys.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#define LCD_ADDR 0x27
#define LCD_COLS 20
#define LCD_ROWS 4
#define PIN_SDA 21
#define PIN_SCL 22
#define LCD_RS 0x01
#define LCD_EN 0x04
#define LCD_BL 0x08
static const char *TAG = "display";
static i2c_master_bus_handle_t s_bus;
static i2c_master_dev_handle_t s_dev;
static bool s_inited;
static const uint8_t s_thermo[8] = {
0b00100,
0b01100,
0b00100,
0b01100,
0b00100,
0b01110,
0b01110,
0b01110,
};
static const uint8_t s_row_off[4] = {0x00, 0x40, 0x14, 0x54};
static void i2c_write(uint8_t b)
{
if (s_dev == NULL) {
return;
}
i2c_master_transmit(s_dev, &b, 1, 50);
}
static void pulse(uint8_t data)
{
i2c_write((uint8_t)(data | LCD_EN | LCD_BL));
esp_rom_delay_us(1);
i2c_write((uint8_t)((data & (uint8_t)~LCD_EN) | LCD_BL));
esp_rom_delay_us(50);
}
static void write4(uint8_t nibble, uint8_t rs)
{
uint8_t data = (uint8_t)((nibble & 0xF0) | rs | LCD_BL);
i2c_write(data);
pulse(data);
}
static void send(uint8_t value, uint8_t rs)
{
write4(value, rs);
write4((uint8_t)(value << 4), rs);
}
static void cmd(uint8_t c)
{
send(c, 0);
if (c == 0x01 || c == 0x02) {
vTaskDelay(pdMS_TO_TICKS(2));
}
}
static void data_byte(uint8_t d)
{
send(d, LCD_RS);
}
static void set_ddram(uint8_t addr)
{
cmd((uint8_t)(0x80 | addr));
}
void hal_display_init(void)
{
if (s_inited) {
return;
}
i2c_master_bus_config_t bus_cfg = {
.i2c_port = I2C_NUM_0,
.sda_io_num = PIN_SDA,
.scl_io_num = PIN_SCL,
.clk_source = I2C_CLK_SRC_DEFAULT,
.glitch_ignore_cnt = 7,
.flags = {
.enable_internal_pullup = true,
},
};
if (i2c_new_master_bus(&bus_cfg, &s_bus) != ESP_OK) {
ESP_LOGE(TAG, "i2c bus failed");
return;
}
i2c_device_config_t dev_cfg = {
.dev_addr_length = I2C_ADDR_BIT_LEN_7,
.device_address = LCD_ADDR,
.scl_speed_hz = 100000,
};
if (i2c_master_bus_add_device(s_bus, &dev_cfg, &s_dev) != ESP_OK) {
ESP_LOGE(TAG, "i2c device failed");
return;
}
vTaskDelay(pdMS_TO_TICKS(50));
write4(0x30, 0);
vTaskDelay(pdMS_TO_TICKS(5));
write4(0x30, 0);
esp_rom_delay_us(150);
write4(0x30, 0);
write4(0x20, 0);
cmd(0x28); /* 4-bit, 2 line */
cmd(0x08);
cmd(0x01);
cmd(0x06);
cmd(0x0C);
cmd(0x40); /* CGRAM 0 */
for (int i = 0; i < 8; i++) {
data_byte(s_thermo[i]);
}
cmd(0x01);
s_inited = true;
ESP_LOGI(TAG, "init LCD 20x4 addr=0x27 sda=21 scl=22 IDF I2C");
}
void hal_display_clear(void)
{
if (!s_inited) {
return;
}
cmd(0x01);
}
void hal_display_text(int col, int row, const char *s)
{
if (!s_inited || s == NULL) {
return;
}
if (row < 0 || row >= LCD_ROWS) {
return;
}
if (col < 0) {
col = 0;
}
if (col >= LCD_COLS) {
return;
}
set_ddram((uint8_t)(s_row_off[row] + col));
int room = LCD_COLS - col;
int n = 0;
while (s[n] != '\0' && n < room) {
data_byte((uint8_t)s[n]);
n++;
}
}
void hal_display_glyph_thermo(int col, int row)
{
if (!s_inited) {
return;
}
if (row < 0 || row >= LCD_ROWS || col < 0 || col >= LCD_COLS) {
return;
}
set_ddram((uint8_t)(s_row_off[row] + col));
data_byte(0);
}
void hal_display_flush(void)
{
}
void hal_display_softkey(int slot, int slots, const char *label)
{
(void)slot;
(void)slots;
(void)label;
}