191 lines
3.7 KiB
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;
|
|
}
|