From 228c1cfe635dffac93ca8be58ef425f00d1f07e6 Mon Sep 17 00:00:00 2001 From: whowechina Date: Wed, 15 May 2024 15:51:32 +0800 Subject: [PATCH] Optimize display and touch driver --- firmware/src/CMakeLists.txt | 3 +- firmware/src/cst816t.c | 70 +++++++++++++--------- firmware/src/cst816t.h | 7 ++- firmware/src/st7789.c | 113 ++++++++++++++++++++++++------------ firmware/src/st7789.h | 1 + 5 files changed, 124 insertions(+), 70 deletions(-) diff --git a/firmware/src/CMakeLists.txt b/firmware/src/CMakeLists.txt index 4d8db4f..39834f5 100644 --- a/firmware/src/CMakeLists.txt +++ b/firmware/src/CMakeLists.txt @@ -13,6 +13,7 @@ function(make_firmware board board_def) add_executable(${board} main.c save.c config.c commands.c light.c keypad.c + cst816t.c st7789.c cli.c usb_descriptors.c) target_compile_definitions(${board} PUBLIC ${board_def}) pico_enable_stdio_usb(${board} 1) @@ -20,7 +21,7 @@ function(make_firmware board board_def) pico_generate_pio_header(${board} ${CMAKE_CURRENT_LIST_DIR}/ws2812.pio) target_link_libraries(${board} PRIVATE - aic hardware_pio hardware_pwm hardware_flash) + aic hardware_pio hardware_pwm hardware_dma hardware_flash) pico_add_extra_outputs(${board}) diff --git a/firmware/src/cst816t.c b/firmware/src/cst816t.c index 184c311..34eca2e 100644 --- a/firmware/src/cst816t.c +++ b/firmware/src/cst816t.c @@ -16,13 +16,22 @@ static i2c_inst_t *i2c_port = i2c0; +static void cst816t_read_reg_n(uint8_t reg, uint8_t *buf, uint8_t len) +{ + i2c_write_blocking_until(i2c_port, CST816T_I2C_ADDR, ®, 1, true, + make_timeout_time_ms(1)); + i2c_read_blocking_until(i2c_port, CST816T_I2C_ADDR, buf, len, false, + make_timeout_time_ms(1)); +} void cst816t_init_i2c(i2c_inst_t *i2c, uint8_t scl, uint8_t sda) { i2c_port = i2c; - i2c_init(i2c_port, 200 * 000); + i2c_init(i2c_port, 200 * 1000); gpio_set_function(scl, GPIO_FUNC_I2C); gpio_set_function(sda, GPIO_FUNC_I2C); + gpio_pull_up(scl); + gpio_pull_up(sda); } void cst816t_init(i2c_inst_t *i2c, uint8_t trst, uint8_t tint) @@ -39,48 +48,53 @@ void cst816t_init(i2c_inst_t *i2c, uint8_t trst, uint8_t tint) } static struct { - uint8_t xa; - uint8_t xb; - uint8_t ya; - uint8_t yb; - int8_t dx; - int8_t dy; + uint16_t x1; + uint16_t x2; + uint16_t y1; + uint16_t y2; + uint16_t width; + uint16_t height; } ctx = { 1, 1, 1, 1 }; -void cst816t_set_ratio(uint8_t xa, uint8_t xb, uint8_t ya, uint8_t yb) +void cst816t_crop(uint16_t x1, uint16_t x2, uint16_t y1, uint16_t y2, uint16_t width, uint16_t height) { - ctx.xa = xa ? xa : 1; - ctx.xb = xb; - ctx.ya = ya ? ya : 1; - ctx.yb = yb; -} - -void cst816t_set_offset(int8_t dx, int8_t dy) -{ - ctx.dx = dx; - ctx.dy = dy; -} - -static void cst816t_read_reg_n(uint8_t reg, uint8_t *buf, uint8_t len) -{ - i2c_write_blocking_until(i2c_port, CST816T_I2C_ADDR, ®, 1, true, - make_timeout_time_ms(1)); - i2c_read_blocking_until(i2c_port, CST816T_I2C_ADDR, buf, len, false, - make_timeout_time_ms(1)); + ctx.x1 = x1; + ctx.x2 = x2; + ctx.y1 = y1; + ctx.y2 = y2; + ctx.width = width; + ctx.height = height; } cst816t_report_t cst816t_read() { uint8_t buf[6]; + cst816t_read_reg_n(0x01, buf, 6); cst816t_report_t report = { .gesture = buf[0], .finger = buf[1], .event = (buf[2] >> 4) & 0x0f, - .x = (((buf[2] & 0x0f) << 8) | buf[3]) * ctx.xb / ctx.xa + ctx.dx, - .y = ((buf[4] << 8) | buf[5]) * ctx.yb / ctx.ya + ctx.dy, + .raw_x = ((buf[2] & 0x0f) << 8) | buf[3], + .raw_y = ((buf[4] & 0x0f) << 8) | buf[5], }; + int x = (report.raw_x - ctx.x1) * ctx.width / (ctx.x2 - ctx.x1); + int y = (report.raw_y - ctx.y1) * ctx.height / (ctx.y2 - ctx.y1); + if (x < 0) { + x = 0; + } else if (x >= ctx.width) { + x = ctx.width - 1; + } + if (y < 0) { + y = 0; + } else if (y >= ctx.height) { + y = ctx.height - 1; + } + + report.x = x; + report.y = y; + return report; } diff --git a/firmware/src/cst816t.h b/firmware/src/cst816t.h index d5434cf..0b7fdf3 100644 --- a/firmware/src/cst816t.h +++ b/firmware/src/cst816t.h @@ -12,15 +12,16 @@ void cst816t_init_i2c(i2c_inst_t *i2c, uint8_t scl, uint8_t sda); void cst816t_init(i2c_inst_t *i2c, uint8_t trst, uint8_t tint); -void cst816t_set_ratio(uint8_t xa, uint8_t xb, uint8_t ya, uint8_t yb); -void cst816t_set_offset(int8_t dx, int8_t dy); +void cst816t_crop(uint16_t x1, uint16_t x2, uint16_t y1, uint16_t y2, uint16_t width, uint16_t height); typedef struct { - uint8_t gesture; + uint8_t gesture; uint8_t finger; uint8_t event; uint16_t x; uint16_t y; + uint16_t raw_x; + uint16_t raw_y; } cst816t_report_t; cst816t_report_t cst816t_read(); diff --git a/firmware/src/st7789.c b/firmware/src/st7789.c index 007dbec..d12440f 100644 --- a/firmware/src/st7789.c +++ b/firmware/src/st7789.c @@ -16,6 +16,7 @@ #include "hardware/spi.h" #include "hardware/dma.h" #include "hardware/pwm.h" +#include "hardware/clocks.h" #include "st7789.h" @@ -30,8 +31,14 @@ static struct { int dma_tx; dma_channel_config dma_cfg; } ctx; +static struct { + uint16_t x; + uint16_t y; + uint16_t w; + uint16_t h; +} crop = { 0, 0, WIDTH, HEIGHT }; -static uint16_t vram[HEIGHT][WIDTH]; +static uint16_t vram[HEIGHT * WIDTH]; static void send_cmd(uint8_t cmd, const void *data, size_t len) { @@ -46,29 +53,13 @@ static void send_cmd(uint8_t cmd, const void *data, size_t len) } } -void st7789_reset() -{ - gpio_put(ctx.dc, 1); - gpio_put(ctx.rst, 1); - sleep_ms(100); - - send_cmd(0x01, NULL, 0); // Software Reset - sleep_ms(130); - - send_cmd(0x11, NULL, 0); // Sleep Out - sleep_ms(10); - - send_cmd(0x3a, "\x55", 1); // 16bit RGB (5-6-5) - send_cmd(0x36, "\x00", 1); // Regular VRam Access - - send_cmd(0x21, NULL, 0); // Display Inversion for TTF - send_cmd(0x13, NULL, 0); // Normal Display Mode On - send_cmd(0x29, NULL, 0); // Turn On Display -} - void st7789_init_spi(spi_inst_t *port, uint8_t sck, uint8_t tx, uint8_t csn) { - spi_init(port, 125 * 1000 * 1000); + // to get max freq for SPI + uint32_t freq = clock_get_hz(clk_sys); + clock_configure(clk_peri, 0, CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLK_SYS, freq, freq); + spi_init(port, freq); + gpio_set_function(tx, GPIO_FUNC_SPI); gpio_set_function(sck, GPIO_FUNC_SPI); gpio_init(csn); @@ -121,6 +112,48 @@ void st7789_init(spi_inst_t *port, uint8_t dc, uint8_t rst, uint8_t ledk) st7789_reset(); } +static void update_addr() +{ + uint16_t xe = crop.x + crop.w - 1; + uint8_t ca[] = { crop.x >> 8, crop.x & 0xff, xe >> 8, xe & 0xff }; + send_cmd(0x2a, ca, sizeof(ca)); + + uint16_t ye = crop.y + crop.h - 1; + uint8_t ra[] = { crop.y >> 8, crop.y & 0xff, ye >> 8, ye & 0xff }; + send_cmd(0x2b, ra, sizeof(ra)); +} + +void st7789_reset() +{ + gpio_put(ctx.dc, 1); + gpio_put(ctx.rst, 1); + sleep_ms(100); + + send_cmd(0x01, NULL, 0); // Software Reset + sleep_ms(130); + + send_cmd(0x11, NULL, 0); // Sleep Out + sleep_ms(10); + + send_cmd(0x3a, "\x55", 1); // 16bit RGB (5-6-5) + send_cmd(0x36, "\x00", 1); // Regular VRam Access + + send_cmd(0x21, NULL, 0); // Display Inversion for TTF + send_cmd(0x13, NULL, 0); // Normal Display Mode On + send_cmd(0x29, NULL, 0); // Turn On Display + + update_addr(); +} + +void st7789_crop(uint16_t x, uint16_t y, uint16_t w, uint16_t h) +{ + crop.x = x; + crop.y = y; + crop.w = w; + crop.h = h; + update_addr(); +} + void st7789_dimmer(uint8_t level) { pwm_set_gpio_level(ctx.ledk, level); @@ -134,13 +167,12 @@ void st7789_vsync() void st7789_render(bool vsync) { send_cmd(0x2c, NULL, 0); - spi_set_format(ctx.spi, 16, SPI_CPOL_1, SPI_CPHA_1, SPI_MSB_FIRST); dma_channel_configure(ctx.dma_tx, &ctx.dma_cfg, - &spi_get_hw(ctx.spi)->dr, // write address - vram, // read address - sizeof(vram) / 2, // count + &spi_get_hw(ctx.spi)->dr, // write to + vram, // read from + crop.w * crop.h, // element count true); // start right now if (vsync) { st7789_vsync(); @@ -157,48 +189,53 @@ void st7789_clear() memset(vram, 0, sizeof(vram)); } +void static inline put_pixel(uint16_t x, uint16_t y, uint16_t color) +{ + vram[y * crop.w + x] = color; +} + void st7789_pixel(uint16_t x, uint16_t y, uint16_t color) { - if ((x >= WIDTH) || (y >= HEIGHT)) { + if ((x >= crop.w) || (y >= crop.h)) { return; } - vram[y][x] = color; + put_pixel(x, y, color); } void st7789_hline(uint16_t x, uint16_t y, uint16_t w, uint16_t color) { - if ((x >= WIDTH) || (y >= HEIGHT)) { + if ((x >= crop.w) || (y >= crop.h)) { return; } - w = x + w > WIDTH ? WIDTH - x : w; + w = x + w > crop.w ? crop.w - x : w; for (int i = 0; i < w; i++) { - vram[y][x + i] = color; + put_pixel(x + i, y, color); } } void st7789_vline(uint16_t x, uint16_t y, uint16_t h, uint16_t color) { - if ((x >= WIDTH) || (y >= HEIGHT)) { + if ((x >= crop.w) || (y >= crop.h)) { return; } - h = y + h > HEIGHT ? HEIGHT - y : h; + h = y + h > crop.h ? crop.h - y : h; for (int i = 0; i < h; i++) { - vram[y + i][x] = color; + put_pixel(x, y + i, color); } } void st7789_bar(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color) { - if ((x >= WIDTH) || (y >= HEIGHT)) { + if ((x >= crop.w) || (y >= crop.h)) { return; } - w = x + w > WIDTH ? WIDTH - x : w; - h = y + h > HEIGHT ? HEIGHT - y : h; + w = x + w > crop.w ? crop.w - x : w; + h = y + h > crop.h ? crop.h - y : h; for (int i = 0; i < h; i++) { for (int j = 0; j < w; j++) { - vram[y + i][x + j] = color; + put_pixel(x + j, y + i, color); } } } diff --git a/firmware/src/st7789.h b/firmware/src/st7789.h index 386f0d6..265518b 100644 --- a/firmware/src/st7789.h +++ b/firmware/src/st7789.h @@ -13,6 +13,7 @@ void st7789_reset(); void st7789_init_spi(spi_inst_t *port, uint8_t sck, uint8_t tx, uint8_t csn); void st7789_init(spi_inst_t *port, uint8_t dc, uint8_t rst, uint8_t ledk); +void st7789_crop(uint16_t x, uint16_t y, uint16_t w, uint16_t h); void st7789_dimmer(uint8_t level); void st7789_vsync(); void st7789_render(bool vsync);