Add LCD1602A I2C test with SoftSPI touch and LVGL.
PCF8574 backpack on SDA=GPIO22/SCL=GPIO27, demo/hello/clear/backlight UI, and flashable firmware/cyd package. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
221
src/lcd.cpp
Normal file
221
src/lcd.cpp
Normal file
@@ -0,0 +1,221 @@
|
||||
#include "lcd.h"
|
||||
#include "pins.h"
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <Wire.h>
|
||||
#include <string.h>
|
||||
|
||||
// PCF8574 背包常见接线:P0=RS P1=RW P2=E P3=BL P4..P7=D4..D7
|
||||
static constexpr uint8_t BIT_RS = 0x01;
|
||||
static constexpr uint8_t BIT_RW = 0x02;
|
||||
static constexpr uint8_t BIT_E = 0x04;
|
||||
static constexpr uint8_t BIT_BL = 0x08;
|
||||
|
||||
static constexpr uint8_t CANDIDATE_ADDRS[] = {0x27, 0x3F, 0x26, 0x3E};
|
||||
|
||||
struct DemoMsg {
|
||||
const char *line0;
|
||||
const char *line1;
|
||||
};
|
||||
|
||||
static const DemoMsg DEMOS[] = {
|
||||
{"Hello CYD!", "LCD1602A I2C"},
|
||||
{"SDA=GPIO22", "SCL=GPIO27"},
|
||||
{"Line1 16 chars!", "Line2 ready...."},
|
||||
{"Backlight ON", "Touch UI demo"},
|
||||
};
|
||||
|
||||
static bool g_ok = false;
|
||||
static bool g_bl = true;
|
||||
static uint8_t g_addr = 0;
|
||||
static char g_lines[LCD_ROWS][LCD_COLS + 1];
|
||||
|
||||
static uint8_t bl_mask() { return g_bl ? BIT_BL : 0; }
|
||||
|
||||
static bool i2c_write(uint8_t data) {
|
||||
Wire.beginTransmission(g_addr);
|
||||
Wire.write(data);
|
||||
return Wire.endTransmission() == 0;
|
||||
}
|
||||
|
||||
static void pulse_enable(uint8_t data) {
|
||||
i2c_write((uint8_t)(data | BIT_E));
|
||||
delayMicroseconds(1);
|
||||
i2c_write((uint8_t)(data & (uint8_t)~BIT_E));
|
||||
delayMicroseconds(50);
|
||||
}
|
||||
|
||||
static void write4(uint8_t nibble, uint8_t mode) {
|
||||
const uint8_t data = (uint8_t)((nibble & 0xF0) | mode | bl_mask());
|
||||
i2c_write(data);
|
||||
pulse_enable(data);
|
||||
}
|
||||
|
||||
static void send(uint8_t value, uint8_t mode) {
|
||||
write4((uint8_t)(value & 0xF0), mode);
|
||||
write4((uint8_t)((value << 4) & 0xF0), mode);
|
||||
}
|
||||
|
||||
static void cmd(uint8_t c) {
|
||||
send(c, 0);
|
||||
if (c <= 0x03) {
|
||||
delay(2);
|
||||
}
|
||||
}
|
||||
|
||||
static void data(uint8_t d) { send(d, BIT_RS); }
|
||||
|
||||
static void pad_copy(char *dst, const char *src) {
|
||||
size_t i = 0;
|
||||
if (src) {
|
||||
for (; i < LCD_COLS && src[i]; ++i) {
|
||||
dst[i] = src[i];
|
||||
}
|
||||
}
|
||||
for (; i < LCD_COLS; ++i) {
|
||||
dst[i] = ' ';
|
||||
}
|
||||
dst[LCD_COLS] = '\0';
|
||||
}
|
||||
|
||||
static void write_row(uint8_t row) {
|
||||
if (!g_ok || row >= LCD_ROWS) {
|
||||
return;
|
||||
}
|
||||
cmd((uint8_t)(0x80 | (row == 0 ? 0x00 : 0x40)));
|
||||
for (uint8_t i = 0; i < LCD_COLS; ++i) {
|
||||
data((uint8_t)g_lines[row][i]);
|
||||
}
|
||||
}
|
||||
|
||||
static bool probe_addr(uint8_t addr) {
|
||||
Wire.beginTransmission(addr);
|
||||
return Wire.endTransmission() == 0;
|
||||
}
|
||||
|
||||
static bool hd44780_init() {
|
||||
delay(50);
|
||||
// 强制 8-bit 再切 4-bit(手册上电时序)
|
||||
write4(0x30, 0);
|
||||
delay(5);
|
||||
write4(0x30, 0);
|
||||
delayMicroseconds(150);
|
||||
write4(0x30, 0);
|
||||
delayMicroseconds(150);
|
||||
write4(0x20, 0); // 4-bit
|
||||
delayMicroseconds(150);
|
||||
|
||||
cmd(0x28); // 4-bit, 2 lines, 5x8
|
||||
cmd(0x0C); // display on, cursor off
|
||||
cmd(0x06); // entry mode
|
||||
cmd(0x01); // clear
|
||||
delay(2);
|
||||
return true;
|
||||
}
|
||||
|
||||
void lcd_init() {
|
||||
memset(g_lines, 0, sizeof(g_lines));
|
||||
pad_copy(g_lines[0], "LCD1602A");
|
||||
pad_copy(g_lines[1], "init...");
|
||||
|
||||
Wire.begin(LCD_I2C_SDA_PIN, LCD_I2C_SCL_PIN, (uint32_t)LCD_I2C_FREQ_HZ);
|
||||
delay(20);
|
||||
|
||||
g_ok = false;
|
||||
g_addr = 0;
|
||||
g_bl = true;
|
||||
|
||||
for (uint8_t a : CANDIDATE_ADDRS) {
|
||||
if (probe_addr(a)) {
|
||||
g_addr = a;
|
||||
g_ok = true;
|
||||
Serial.printf("LCD1602A PCF8574 found @ 0x%02X\n", g_addr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!g_ok) {
|
||||
Serial.printf("LCD1602A NOT FOUND (SDA=GPIO%d SCL=GPIO%d). Tried:",
|
||||
LCD_I2C_SDA_PIN, LCD_I2C_SCL_PIN);
|
||||
for (uint8_t a : CANDIDATE_ADDRS) {
|
||||
Serial.printf(" 0x%02X", a);
|
||||
}
|
||||
Serial.println();
|
||||
pad_copy(g_lines[0], "NO I2C LCD");
|
||||
pad_copy(g_lines[1], "check wiring");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!hd44780_init()) {
|
||||
g_ok = false;
|
||||
Serial.println("LCD1602A HD44780 init failed");
|
||||
return;
|
||||
}
|
||||
|
||||
write_row(0);
|
||||
write_row(1);
|
||||
Serial.printf("LCD1602A OK SDA=GPIO%d SCL=GPIO%d addr=0x%02X\n",
|
||||
LCD_I2C_SDA_PIN, LCD_I2C_SCL_PIN, g_addr);
|
||||
}
|
||||
|
||||
bool lcd_ok() { return g_ok; }
|
||||
|
||||
uint8_t lcd_addr() { return g_addr; }
|
||||
|
||||
void lcd_set_backlight(bool on) {
|
||||
g_bl = on;
|
||||
if (!g_ok) {
|
||||
return;
|
||||
}
|
||||
i2c_write(bl_mask());
|
||||
Serial.printf("LCD backlight %s\n", g_bl ? "ON" : "OFF");
|
||||
}
|
||||
|
||||
bool lcd_backlight() { return g_bl; }
|
||||
|
||||
void lcd_clear() {
|
||||
pad_copy(g_lines[0], "");
|
||||
pad_copy(g_lines[1], "");
|
||||
if (!g_ok) {
|
||||
return;
|
||||
}
|
||||
cmd(0x01);
|
||||
delay(2);
|
||||
Serial.println("LCD clear");
|
||||
}
|
||||
|
||||
void lcd_set_line(uint8_t row, const char *text) {
|
||||
if (row >= LCD_ROWS) {
|
||||
return;
|
||||
}
|
||||
pad_copy(g_lines[row], text);
|
||||
write_row(row);
|
||||
Serial.printf("LCD L%u: [%s]\n", (unsigned)row, g_lines[row]);
|
||||
}
|
||||
|
||||
void lcd_get_line(uint8_t row, char *out, size_t out_len) {
|
||||
if (!out || out_len == 0) {
|
||||
return;
|
||||
}
|
||||
if (row >= LCD_ROWS) {
|
||||
out[0] = '\0';
|
||||
return;
|
||||
}
|
||||
strncpy(out, g_lines[row], out_len - 1);
|
||||
out[out_len - 1] = '\0';
|
||||
}
|
||||
|
||||
uint8_t lcd_demo_count() { return (uint8_t)(sizeof(DEMOS) / sizeof(DEMOS[0])); }
|
||||
|
||||
void lcd_demo(uint8_t index) {
|
||||
if (lcd_demo_count() == 0) {
|
||||
return;
|
||||
}
|
||||
index = (uint8_t)(index % lcd_demo_count());
|
||||
g_bl = true;
|
||||
if (g_ok) {
|
||||
i2c_write(bl_mask());
|
||||
}
|
||||
lcd_set_line(0, DEMOS[index].line0);
|
||||
lcd_set_line(1, DEMOS[index].line1);
|
||||
}
|
||||
45
src/main.cpp
Normal file
45
src/main.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
#include <Arduino.h>
|
||||
#include <lvgl.h>
|
||||
|
||||
#include "lcd.h"
|
||||
#include "pins.h"
|
||||
#include "touch.h"
|
||||
#include "ui.h"
|
||||
|
||||
static constexpr uint32_t DRAW_BUF_SIZE =
|
||||
(SCREEN_WIDTH * SCREEN_HEIGHT / 10 * (LV_COLOR_DEPTH / 8));
|
||||
static uint32_t draw_buf[DRAW_BUF_SIZE / 4];
|
||||
|
||||
void setup() {
|
||||
Serial.begin(460800);
|
||||
delay(200);
|
||||
Serial.println();
|
||||
Serial.printf("LVGL %d.%d.%d | LCD1602A I2C\n", lv_version_major(),
|
||||
lv_version_minor(), lv_version_patch());
|
||||
Serial.println("BOOT_OK");
|
||||
|
||||
pinMode(TFT_BL_PIN, OUTPUT);
|
||||
digitalWrite(TFT_BL_PIN, HIGH);
|
||||
|
||||
touch_init();
|
||||
lcd_init();
|
||||
|
||||
lv_init();
|
||||
|
||||
lv_display_t *disp =
|
||||
lv_tft_espi_create(SCREEN_WIDTH, SCREEN_HEIGHT, draw_buf, sizeof(draw_buf));
|
||||
lv_display_set_rotation(disp, LV_DISPLAY_ROTATION_270);
|
||||
|
||||
lv_indev_t *indev = lv_indev_create();
|
||||
lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER);
|
||||
lv_indev_set_read_cb(indev, touch_read_cb);
|
||||
lv_indev_set_display(indev, disp);
|
||||
|
||||
ui_create();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
lv_timer_handler();
|
||||
lv_tick_inc(5);
|
||||
delay(5);
|
||||
}
|
||||
125
src/touch.cpp
Normal file
125
src/touch.cpp
Normal file
@@ -0,0 +1,125 @@
|
||||
#include "touch.h"
|
||||
#include "pins.h"
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
/**
|
||||
* SoftSPI XPT2046
|
||||
* BL↔TR 是矩形主对角线镜像(XY 对调),不是 180°(180° 会搞成 TL↔BR)。
|
||||
* 先按 rot2 得到旧 UI,再做对角修正,反变换喂给 LVGL 270。
|
||||
*/
|
||||
|
||||
int16_t g_dbg_phys_x = -1;
|
||||
int16_t g_dbg_phys_y = -1;
|
||||
int16_t g_dbg_logic_x = -1;
|
||||
int16_t g_dbg_logic_y = -1;
|
||||
bool g_dbg_touch_down = false;
|
||||
|
||||
static void soft_write(uint8_t data) {
|
||||
for (int i = 7; i >= 0; --i) {
|
||||
digitalWrite(CYD_TOUCH_MOSI, (data >> i) & 1);
|
||||
digitalWrite(CYD_TOUCH_CLK, HIGH);
|
||||
delayMicroseconds(2);
|
||||
digitalWrite(CYD_TOUCH_CLK, LOW);
|
||||
delayMicroseconds(2);
|
||||
}
|
||||
}
|
||||
|
||||
static uint16_t soft_read12() {
|
||||
uint16_t v = 0;
|
||||
digitalWrite(CYD_TOUCH_CLK, HIGH);
|
||||
delayMicroseconds(2);
|
||||
digitalWrite(CYD_TOUCH_CLK, LOW);
|
||||
delayMicroseconds(2);
|
||||
for (int i = 0; i < 12; ++i) {
|
||||
digitalWrite(CYD_TOUCH_CLK, HIGH);
|
||||
delayMicroseconds(2);
|
||||
v = (uint16_t)((v << 1) | (digitalRead(CYD_TOUCH_MISO) ? 1u : 0u));
|
||||
digitalWrite(CYD_TOUCH_CLK, LOW);
|
||||
delayMicroseconds(2);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
static uint16_t xpt_read(uint8_t cmd) {
|
||||
digitalWrite(CYD_TOUCH_CS, LOW);
|
||||
soft_write(cmd);
|
||||
uint16_t v = soft_read12();
|
||||
digitalWrite(CYD_TOUCH_CS, HIGH);
|
||||
return v;
|
||||
}
|
||||
|
||||
static int16_t clampi(int32_t v, int32_t lo, int32_t hi) {
|
||||
if (v < lo) {
|
||||
return (int16_t)lo;
|
||||
}
|
||||
if (v > hi) {
|
||||
return (int16_t)hi;
|
||||
}
|
||||
return (int16_t)v;
|
||||
}
|
||||
|
||||
void touch_init() {
|
||||
pinMode(CYD_TOUCH_CS, OUTPUT);
|
||||
pinMode(CYD_TOUCH_CLK, OUTPUT);
|
||||
pinMode(CYD_TOUCH_MOSI, OUTPUT);
|
||||
pinMode(CYD_TOUCH_MISO, INPUT);
|
||||
pinMode(CYD_TOUCH_IRQ, INPUT);
|
||||
digitalWrite(CYD_TOUCH_CS, HIGH);
|
||||
digitalWrite(CYD_TOUCH_CLK, LOW);
|
||||
Serial.println("Touch: SoftSPI + diagonal fix (BL/TR)");
|
||||
}
|
||||
|
||||
void touch_read_cb(lv_indev_t * /*indev*/, lv_indev_data_t *data) {
|
||||
uint16_t adc_x = xpt_read(0x90);
|
||||
uint16_t adc_y = xpt_read(0xD0);
|
||||
adc_x = (uint16_t)((adc_x + xpt_read(0x90)) / 2);
|
||||
adc_y = (uint16_t)((adc_y + xpt_read(0xD0)) / 2);
|
||||
|
||||
const bool irq = (digitalRead(CYD_TOUCH_IRQ) == LOW);
|
||||
const bool in_range =
|
||||
(adc_x > 80 && adc_x < 4000 && adc_y > 80 && adc_y < 4000);
|
||||
|
||||
if (!in_range || (!irq && (adc_x < 200 || adc_y < 200))) {
|
||||
data->state = LV_INDEV_STATE_RELEASED;
|
||||
g_dbg_touch_down = false;
|
||||
return;
|
||||
}
|
||||
|
||||
const int16_t p_x = (int16_t)adc_x;
|
||||
const int16_t p_y = (int16_t)(4095 - adc_y);
|
||||
|
||||
int16_t x = map(p_x, 200, 3700, 1, SCREEN_WIDTH);
|
||||
int16_t y = map(p_y, 240, 3800, 1, SCREEN_HEIGHT);
|
||||
x = clampi(x, 0, SCREEN_WIDTH - 1);
|
||||
y = clampi(y, 0, SCREEN_HEIGHT - 1);
|
||||
|
||||
// 旧 UI(LVGL270):(y, 239-x) — 该空间里 BL↔TR,做主对角线镜像
|
||||
// (ux,uy) -> (uy*(319/239), ux*(239/319))
|
||||
const int32_t old_ux = y;
|
||||
const int32_t old_uy = (SCREEN_WIDTH - 1) - x;
|
||||
int16_t ui_x = clampi((old_uy * (UI_HOR_RES - 1)) / (UI_VER_RES - 1), 0,
|
||||
UI_HOR_RES - 1);
|
||||
int16_t ui_y = clampi((old_ux * (UI_VER_RES - 1)) / (UI_HOR_RES - 1), 0,
|
||||
UI_VER_RES - 1);
|
||||
|
||||
// 反变换喂 LVGL,使最终落在 (ui_x, ui_y)
|
||||
const int16_t feed_x = (int16_t)((SCREEN_WIDTH - 1) - ui_y);
|
||||
const int16_t feed_y = ui_x;
|
||||
|
||||
g_dbg_phys_x = x;
|
||||
g_dbg_phys_y = y;
|
||||
g_dbg_logic_x = ui_x;
|
||||
g_dbg_logic_y = ui_y;
|
||||
g_dbg_touch_down = true;
|
||||
|
||||
static uint32_t last_log = 0;
|
||||
if (millis() - last_log > 80) {
|
||||
last_log = millis();
|
||||
Serial.printf("Touch UI(%d,%d)\n", ui_x, ui_y);
|
||||
}
|
||||
|
||||
data->point.x = feed_x;
|
||||
data->point.y = feed_y;
|
||||
data->state = LV_INDEV_STATE_PRESSED;
|
||||
}
|
||||
184
src/ui.cpp
Normal file
184
src/ui.cpp
Normal file
@@ -0,0 +1,184 @@
|
||||
#include "ui.h"
|
||||
#include "lcd.h"
|
||||
#include "pins.h"
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <lvgl.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static constexpr uint32_t COL_BG = 0x0A1016;
|
||||
static constexpr uint32_t COL_INK = 0xEAF0F6;
|
||||
static constexpr uint32_t COL_MUTED = 0x7A8B9C;
|
||||
static constexpr uint32_t COL_BTN = 0x243140;
|
||||
static constexpr uint32_t COL_ON = 0x1B5E4A;
|
||||
static constexpr uint32_t COL_ACCENT = 0x7CDBFF;
|
||||
static constexpr uint32_t COL_DIM = 0x3A4656;
|
||||
static constexpr uint32_t COL_ERR = 0xC62828;
|
||||
|
||||
static lv_obj_t *lbl_title;
|
||||
static lv_obj_t *lbl_pin;
|
||||
static lv_obj_t *lbl_status;
|
||||
static lv_obj_t *lbl_line0;
|
||||
static lv_obj_t *lbl_line1;
|
||||
static lv_obj_t *btn_demo;
|
||||
static lv_obj_t *lbl_demo;
|
||||
static lv_obj_t *btn_hello;
|
||||
static lv_obj_t *btn_clear;
|
||||
static lv_obj_t *btn_bl;
|
||||
static lv_obj_t *lbl_bl;
|
||||
|
||||
static uint8_t g_demo_idx = 0;
|
||||
|
||||
static void style_btn(lv_obj_t *btn, uint32_t bg) {
|
||||
lv_obj_set_style_radius(btn, 10, 0);
|
||||
lv_obj_set_style_bg_color(btn, lv_color_hex(bg), 0);
|
||||
lv_obj_set_style_bg_opa(btn, LV_OPA_COVER, 0);
|
||||
lv_obj_set_style_shadow_width(btn, 0, 0);
|
||||
lv_obj_set_style_border_width(btn, 0, 0);
|
||||
lv_obj_set_style_pad_all(btn, 0, 0);
|
||||
}
|
||||
|
||||
static lv_obj_t *make_btn(lv_obj_t *parent, const char *txt, int16_t x,
|
||||
int16_t y, int16_t w, int16_t h, lv_event_cb_t cb,
|
||||
lv_obj_t **out_lbl) {
|
||||
lv_obj_t *btn = lv_button_create(parent);
|
||||
lv_obj_set_size(btn, w, h);
|
||||
lv_obj_align(btn, LV_ALIGN_TOP_LEFT, x, y);
|
||||
style_btn(btn, COL_BTN);
|
||||
lv_obj_add_event_cb(btn, cb, LV_EVENT_CLICKED, nullptr);
|
||||
lv_obj_t *lbl = lv_label_create(btn);
|
||||
lv_label_set_text(lbl, txt);
|
||||
lv_obj_set_style_text_color(lbl, lv_color_hex(COL_INK), 0);
|
||||
lv_obj_set_style_text_font(lbl, &lv_font_montserrat_16, 0);
|
||||
lv_obj_center(lbl);
|
||||
if (out_lbl) {
|
||||
*out_lbl = lbl;
|
||||
}
|
||||
return btn;
|
||||
}
|
||||
|
||||
void ui_refresh_lcd() {
|
||||
char l0[LCD_COLS + 1];
|
||||
char l1[LCD_COLS + 1];
|
||||
lcd_get_line(0, l0, sizeof(l0));
|
||||
lcd_get_line(1, l1, sizeof(l1));
|
||||
|
||||
if (lbl_line0) {
|
||||
lv_label_set_text_fmt(lbl_line0, "[%s]", l0);
|
||||
}
|
||||
if (lbl_line1) {
|
||||
lv_label_set_text_fmt(lbl_line1, "[%s]", l1);
|
||||
}
|
||||
|
||||
if (lbl_status) {
|
||||
if (lcd_ok()) {
|
||||
lv_label_set_text_fmt(lbl_status, "OK addr 0x%02X", lcd_addr());
|
||||
lv_obj_set_style_text_color(lbl_status, lv_color_hex(COL_ON), 0);
|
||||
} else {
|
||||
lv_label_set_text(lbl_status, "FAIL no PCF8574");
|
||||
lv_obj_set_style_text_color(lbl_status, lv_color_hex(COL_ERR), 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (lbl_bl) {
|
||||
lv_label_set_text(lbl_bl, lcd_backlight() ? "BL OFF" : "BL ON");
|
||||
}
|
||||
if (btn_bl) {
|
||||
style_btn(btn_bl, lcd_backlight() ? COL_ON : COL_DIM);
|
||||
}
|
||||
if (lbl_demo) {
|
||||
lv_label_set_text_fmt(lbl_demo, "Demo %u/%u",
|
||||
(unsigned)(g_demo_idx % lcd_demo_count() + 1),
|
||||
(unsigned)lcd_demo_count());
|
||||
}
|
||||
}
|
||||
|
||||
static void on_demo(lv_event_t *e) {
|
||||
if (lv_event_get_code(e) != LV_EVENT_CLICKED) {
|
||||
return;
|
||||
}
|
||||
lcd_demo(g_demo_idx);
|
||||
g_demo_idx = (uint8_t)((g_demo_idx + 1) % lcd_demo_count());
|
||||
ui_refresh_lcd();
|
||||
}
|
||||
|
||||
static void on_hello(lv_event_t *e) {
|
||||
if (lv_event_get_code(e) != LV_EVENT_CLICKED) {
|
||||
return;
|
||||
}
|
||||
lcd_set_backlight(true);
|
||||
lcd_set_line(0, "Hello World!");
|
||||
lcd_set_line(1, "LCD1602A");
|
||||
ui_refresh_lcd();
|
||||
}
|
||||
|
||||
static void on_clear(lv_event_t *e) {
|
||||
if (lv_event_get_code(e) != LV_EVENT_CLICKED) {
|
||||
return;
|
||||
}
|
||||
lcd_clear();
|
||||
ui_refresh_lcd();
|
||||
}
|
||||
|
||||
static void on_bl(lv_event_t *e) {
|
||||
if (lv_event_get_code(e) != LV_EVENT_CLICKED) {
|
||||
return;
|
||||
}
|
||||
lcd_set_backlight(!lcd_backlight());
|
||||
ui_refresh_lcd();
|
||||
}
|
||||
|
||||
void ui_create() {
|
||||
lv_obj_t *scr = lv_screen_active();
|
||||
lv_obj_set_style_bg_color(scr, lv_color_hex(COL_BG), 0);
|
||||
lv_obj_set_style_bg_opa(scr, LV_OPA_COVER, 0);
|
||||
|
||||
lbl_title = lv_label_create(scr);
|
||||
lv_label_set_text(lbl_title, "LCD1602A");
|
||||
lv_obj_set_style_text_color(lbl_title, lv_color_hex(COL_INK), 0);
|
||||
lv_obj_set_style_text_font(lbl_title, &lv_font_montserrat_28, 0);
|
||||
lv_obj_align(lbl_title, LV_ALIGN_TOP_MID, 0, 4);
|
||||
|
||||
lbl_pin = lv_label_create(scr);
|
||||
lv_label_set_text_fmt(lbl_pin, "I2C SDA%d SCL%d PCF8574", LCD_I2C_SDA_PIN,
|
||||
LCD_I2C_SCL_PIN);
|
||||
lv_obj_set_style_text_color(lbl_pin, lv_color_hex(COL_MUTED), 0);
|
||||
lv_obj_set_style_text_font(lbl_pin, &lv_font_montserrat_14, 0);
|
||||
lv_obj_align(lbl_pin, LV_ALIGN_TOP_MID, 0, 36);
|
||||
|
||||
lbl_status = lv_label_create(scr);
|
||||
lv_label_set_text(lbl_status, "...");
|
||||
lv_obj_set_style_text_font(lbl_status, &lv_font_montserrat_14, 0);
|
||||
lv_obj_align(lbl_status, LV_ALIGN_TOP_MID, 0, 54);
|
||||
|
||||
lbl_line0 = lv_label_create(scr);
|
||||
lv_label_set_text(lbl_line0, "[ ]");
|
||||
lv_obj_set_style_text_color(lbl_line0, lv_color_hex(COL_ACCENT), 0);
|
||||
lv_obj_set_style_text_font(lbl_line0, &lv_font_montserrat_18, 0);
|
||||
lv_obj_align(lbl_line0, LV_ALIGN_TOP_MID, 0, 78);
|
||||
|
||||
lbl_line1 = lv_label_create(scr);
|
||||
lv_label_set_text(lbl_line1, "[ ]");
|
||||
lv_obj_set_style_text_color(lbl_line1, lv_color_hex(COL_ACCENT), 0);
|
||||
lv_obj_set_style_text_font(lbl_line1, &lv_font_montserrat_18, 0);
|
||||
lv_obj_align(lbl_line1, LV_ALIGN_TOP_MID, 0, 104);
|
||||
|
||||
const int16_t gap = 8;
|
||||
const int16_t bw = (UI_HOR_RES - 48 - gap) / 2;
|
||||
const int16_t bx0 = 24;
|
||||
const int16_t row0 = 140;
|
||||
const int16_t row1 = 188;
|
||||
|
||||
btn_demo = make_btn(scr, "Demo", bx0, row0, bw, 40, on_demo, &lbl_demo);
|
||||
btn_hello = make_btn(scr, "Hello", bx0 + bw + gap, row0, bw, 40, on_hello,
|
||||
nullptr);
|
||||
btn_clear =
|
||||
make_btn(scr, "Clear", bx0, row1, bw, 40, on_clear, nullptr);
|
||||
btn_bl = make_btn(scr, "BL OFF", bx0 + bw + gap, row1, bw, 40, on_bl, &lbl_bl);
|
||||
|
||||
(void)btn_demo;
|
||||
(void)btn_hello;
|
||||
(void)btn_clear;
|
||||
|
||||
ui_refresh_lcd();
|
||||
}
|
||||
Reference in New Issue
Block a user