1
0
mirror of https://github.com/whowechina/aic_pico.git synced 2024-11-28 07:20:49 +01:00

Display and touch driver

This commit is contained in:
whowechina 2024-05-14 13:20:57 +08:00
parent db9fd0a1c9
commit 592bd472df
4 changed files with 365 additions and 0 deletions

86
firmware/src/cst816t.c Normal file
View File

@ -0,0 +1,86 @@
/*
* CST816T Touch Sensor Driver
* WHowe <github.com/whowechina>
*
*/
#include <stdint.h>
#include <stdbool.h>
#include "hardware/gpio.h"
#include "hardware/i2c.h"
#include "cst816t.h"
#define CST816T_I2C_ADDR 0x15
static i2c_inst_t *i2c_port = i2c0;
void cst816t_init_i2c(i2c_inst_t *i2c, uint8_t scl, uint8_t sda)
{
i2c_port = i2c;
i2c_init(i2c_port, 200 * 000);
gpio_set_function(scl, GPIO_FUNC_I2C);
gpio_set_function(sda, GPIO_FUNC_I2C);
}
void cst816t_init(i2c_inst_t *i2c, uint8_t trst, uint8_t tint)
{
i2c_port = i2c;
gpio_init(trst);
gpio_set_dir(trst, GPIO_OUT);
gpio_put(trst, 1);
gpio_init(tint);
gpio_set_dir(tint, GPIO_IN);
gpio_pull_up(tint);
}
static struct {
uint8_t xa;
uint8_t xb;
uint8_t ya;
uint8_t yb;
int8_t dx;
int8_t dy;
} ctx = { 1, 1, 1, 1 };
void cst816t_set_ratio(uint8_t xa, uint8_t xb, uint8_t ya, uint8_t yb)
{
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));
}
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,
};
return report;
}

26
firmware/src/cst816t.h Normal file
View File

@ -0,0 +1,26 @@
/*
* CST816T Touch Sensor Driver
* WHowe <github.com/whowechina>
*
*/
#include <stdint.h>
#include <stdbool.h>
#include "hardware/i2c.h"
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);
typedef struct {
uint8_t gesture;
uint8_t finger;
uint8_t event;
uint16_t x;
uint16_t y;
} cst816t_report_t;
cst816t_report_t cst816t_read();

227
firmware/src/st7789.c Normal file
View File

@ -0,0 +1,227 @@
/*
* ST7789 Buffered Display Driver for Pico with DMA Support
* WHowe <github.com/whowechina>
*
* LEDK is driven by PWM to adjust brightness
*/
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "pico/stdlib.h"
#include "hardware/gpio.h"
#include "hardware/spi.h"
#include "hardware/dma.h"
#include "hardware/pwm.h"
#include "st7789.h"
#define WIDTH 240
#define HEIGHT 320
static struct {
spi_inst_t *spi;
uint8_t dc;
uint8_t rst;
uint8_t ledk;
int dma_tx;
dma_channel_config dma_cfg;
} ctx;
static uint16_t vram[HEIGHT][WIDTH];
static void send_cmd(uint8_t cmd, const void *data, size_t len)
{
spi_set_format(ctx.spi, 8, SPI_CPOL_1, SPI_CPHA_1, SPI_MSB_FIRST);
gpio_put(ctx.dc, 0);
spi_write_blocking(ctx.spi, &cmd, sizeof(cmd));
gpio_put(ctx.dc, 1);
if (len > 0) {
spi_write_blocking(ctx.spi, data, 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);
gpio_set_function(tx, GPIO_FUNC_SPI);
gpio_set_function(sck, GPIO_FUNC_SPI);
gpio_init(csn);
gpio_set_dir(csn, GPIO_OUT);
gpio_put(csn, 0);
}
static void init_gpio()
{
gpio_init(ctx.dc);
gpio_set_dir(ctx.dc, GPIO_OUT);
gpio_init(ctx.rst);
gpio_set_dir(ctx.rst, GPIO_OUT);
gpio_init(ctx.ledk);
gpio_set_function(ctx.ledk, GPIO_FUNC_PWM);
gpio_set_drive_strength(ctx.ledk, GPIO_DRIVE_STRENGTH_12MA);
}
static void init_pwm()
{
uint slice_num = pwm_gpio_to_slice_num(ctx.ledk);
pwm_config cfg = pwm_get_default_config();
pwm_config_set_clkdiv(&cfg, 4.f);
pwm_init(slice_num, &cfg, true);
pwm_set_wrap(slice_num, 255);
pwm_set_enabled(slice_num, true);
}
static void init_dma()
{
ctx.dma_tx = dma_claim_unused_channel(true);
ctx.dma_cfg = dma_channel_get_default_config(ctx.dma_tx);
channel_config_set_transfer_data_size(&ctx.dma_cfg, DMA_SIZE_16);
channel_config_set_dreq(&ctx.dma_cfg, spi_get_dreq(ctx.spi, true));
}
void st7789_init(spi_inst_t *port, uint8_t dc, uint8_t rst, uint8_t ledk)
{
ctx.spi = port;
ctx.dc = dc;
ctx.rst = rst;
ctx.ledk = ledk;
init_gpio();
init_pwm();
init_dma();
st7789_reset();
}
void st7789_dimmer(uint8_t level)
{
pwm_set_gpio_level(ctx.ledk, level);
}
void st7789_vsync()
{
dma_channel_wait_for_finish_blocking(ctx.dma_tx);
}
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
true); // start right now
if (vsync) {
st7789_vsync();
}
}
uint16_t st7789_rgb565(uint32_t rgb32)
{
return ((rgb32 >> 8) & 0xf800) | ((rgb32 >> 5) & 0x07e0) | ((rgb32 >> 3) & 0x001f);
}
void st7789_clear()
{
memset(vram, 0, sizeof(vram));
}
void st7789_pixel(uint16_t x, uint16_t y, uint16_t color)
{
if ((x >= WIDTH) || (y >= HEIGHT)) {
return;
}
vram[y][x] = color;
}
void st7789_hline(uint16_t x, uint16_t y, uint16_t w, uint16_t color)
{
if ((x >= WIDTH) || (y >= HEIGHT)) {
return;
}
w = x + w > WIDTH ? WIDTH - x : w;
for (int i = 0; i < w; i++) {
vram[y][x + i] = color;
}
}
void st7789_vline(uint16_t x, uint16_t y, uint16_t h, uint16_t color)
{
if ((x >= WIDTH) || (y >= HEIGHT)) {
return;
}
h = y + h > HEIGHT ? HEIGHT - y : h;
for (int i = 0; i < h; i++) {
vram[y + i][x] = color;
}
}
void st7789_bar(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color)
{
if ((x >= WIDTH) || (y >= HEIGHT)) {
return;
}
w = x + w > WIDTH ? WIDTH - x : w;
h = y + h > HEIGHT ? HEIGHT - y : h;
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
vram[y + i][x + j] = color;
}
}
}
void st7789_line(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t color)
{
int dx = abs(x1 - x0), sx = x0 < x1 ? 1 : -1;
int dy = abs(y1 - y0), sy = y0 < y1 ? 1 : -1;
int err = (dx > dy ? dx : -dy) / 2, e2;
for (;;) {
st7789_pixel(x0, y0, color);
if (x0 == x1 && y0 == y1) {
break;
}
e2 = err;
if (e2 > -dx) {
err -= dy;
x0 += sx;
}
if (e2 < dy) {
err += dx;
y0 += sy;
}
}
}

26
firmware/src/st7789.h Normal file
View File

@ -0,0 +1,26 @@
/*
* ST7789 Buffered Display Driver for Pico with DMA Support
* WHowe <github.com/whowechina>
*
* LEDK is driven by PWM to adjust brightness
*/
#include <stdint.h>
#include <stdbool.h>
#include "hardware/spi.h"
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_dimmer(uint8_t level);
void st7789_vsync();
void st7789_render(bool vsync);
uint16_t st7789_rgb565(uint32_t rgb32);
void st7789_clear();
void st7789_pixel(uint16_t x, uint16_t y, uint16_t color);
void st7789_hline(uint16_t x, uint16_t y, uint16_t w, uint16_t color);
void st7789_vline(uint16_t x, uint16_t y, uint16_t h, uint16_t color);
void st7789_bar(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color);
void st7789_line(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t color);