1
0
mirror of https://github.com/whowechina/aic_pico.git synced 2025-02-17 19:09:24 +01:00

Optimize display and touch driver

This commit is contained in:
whowechina 2024-05-15 15:51:32 +08:00
parent 592bd472df
commit 228c1cfe63
5 changed files with 124 additions and 70 deletions

View File

@ -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})

View File

@ -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, &reg, 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, &reg, 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;
}

View File

@ -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();

View File

@ -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);
}
}
}

View File

@ -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);