switched to pio refresh time: 250ms -> 25ms
This commit is contained in:
14
src/main.c
14
src/main.c
@@ -6,7 +6,8 @@
|
||||
|
||||
// lcd configuration
|
||||
const struct tft_config lcd_config = {
|
||||
.spi = PICO_DEFAULT_SPI_INSTANCE,
|
||||
.pio = pio0,
|
||||
.sm = 0,
|
||||
.gpio_din = PICO_DEFAULT_SPI_TX_PIN,
|
||||
.gpio_clk = PICO_DEFAULT_SPI_SCK_PIN,
|
||||
.gpio_cs = PICO_DEFAULT_SPI_CSN_PIN,
|
||||
@@ -21,19 +22,18 @@ int main()
|
||||
{
|
||||
stdio_init_all();
|
||||
|
||||
// gpio_init(DLED_PIN);
|
||||
// gpio_set_dir(DLED_PIN, GPIO_OUT);
|
||||
set_sys_clock_khz(200 * 1000, true);
|
||||
|
||||
uint offset = pio_add_program(lcd_config.pio, &tft_program);
|
||||
tft_program_init(lcd_config.pio, lcd_config.sm, offset, lcd_config.gpio_din, lcd_config.gpio_clk, 1.f);
|
||||
|
||||
tft_init(&lcd_config);
|
||||
|
||||
while (true) {
|
||||
// gpio_put(DLED_PIN, 0);
|
||||
// sleep_ms(250);
|
||||
// gpio_put(DLED_PIN, 1);
|
||||
// sleep_ms(1000);
|
||||
absolute_time_t start = get_absolute_time();
|
||||
tft_fill(0b0000000000000000);
|
||||
tft_fill(0b1111111111111111);
|
||||
tft_fill(0b0000000000000000);
|
||||
absolute_time_t end = get_absolute_time();
|
||||
volatile int64_t diff = absolute_time_diff_us(start, end);
|
||||
printf("test");
|
||||
|
||||
207
src/tft.c
207
src/tft.c
@@ -3,171 +3,64 @@
|
||||
static struct tft_config tft_cfg;
|
||||
static bool tft_data_mode = false;
|
||||
|
||||
void tft_cmd(uint8_t cmd, const uint8_t* data, size_t len)
|
||||
{
|
||||
spi_set_format(tft_cfg.spi, 8, SPI_CPOL_0, SPI_CPHA_0, SPI_MSB_FIRST);
|
||||
tft_data_mode = false;
|
||||
|
||||
gpio_put(tft_cfg.gpio_cs, 0);
|
||||
gpio_put(tft_cfg.gpio_dc, 0);
|
||||
|
||||
spi_write_blocking(tft_cfg.spi, &cmd, sizeof(cmd));
|
||||
|
||||
if (len) {
|
||||
gpio_put(tft_cfg.gpio_dc, 1);
|
||||
spi_write_blocking(tft_cfg.spi, data, len);
|
||||
}
|
||||
gpio_put(tft_cfg.gpio_cs, 1);
|
||||
gpio_put(tft_cfg.gpio_dc, 1);
|
||||
}
|
||||
void tft_caset(uint16_t xs, uint16_t xe)
|
||||
{
|
||||
uint8_t data[] = {
|
||||
xs >> 8,
|
||||
xs & 0xff,
|
||||
xe >> 8,
|
||||
xe & 0xff,
|
||||
};
|
||||
|
||||
// CASET (2Ah): Column Address Set
|
||||
tft_cmd(0x2a, data, sizeof(data));
|
||||
void tft_set_dc_cs(bool dc, bool cs) {
|
||||
sleep_us(1);
|
||||
gpio_put_masked((1u << tft_cfg.gpio_dc) | (1u << tft_cfg.gpio_cs), !!dc << tft_cfg.gpio_dc | !!cs << tft_cfg.gpio_cs);
|
||||
sleep_us(1);
|
||||
}
|
||||
|
||||
void tft_raset(uint16_t ys, uint16_t ye)
|
||||
{
|
||||
uint8_t data[] = {
|
||||
ys >> 8,
|
||||
ys & 0xff,
|
||||
ye >> 8,
|
||||
ye & 0xff,
|
||||
};
|
||||
|
||||
// RASET (2Bh): Row Address Set
|
||||
tft_cmd(0x2b, data, sizeof(data));
|
||||
void tft_write_cmd(PIO pio, uint sm, const uint8_t *cmd, size_t count) {
|
||||
tft_wait_idle(pio, sm);
|
||||
tft_set_dc_cs(0, 0);
|
||||
tft_put(pio, sm, *cmd++);
|
||||
if (count >= 2) {
|
||||
tft_wait_idle(pio, sm);
|
||||
tft_set_dc_cs(1, 0);
|
||||
for (size_t i = 0; i < count - 1; ++i)
|
||||
tft_put(pio, sm, *cmd++);
|
||||
}
|
||||
tft_wait_idle(pio, sm);
|
||||
tft_set_dc_cs(1, 1);
|
||||
}
|
||||
void tft_init(const struct tft_config* config)
|
||||
{
|
||||
|
||||
void lcd_init(PIO pio, uint sm, const uint8_t *init_seq) {
|
||||
const uint8_t *cmd = init_seq;
|
||||
while (*cmd) {
|
||||
tft_write_cmd(pio, sm, cmd + 2, *cmd);
|
||||
//sleep_ms(*(cmd + 1) * 5);
|
||||
sleep_ms(200);
|
||||
cmd += *cmd + 2;
|
||||
}
|
||||
}
|
||||
|
||||
void tft_start_pixels(PIO pio, uint sm) {
|
||||
uint8_t cmd = 0x2c; // RAMWR
|
||||
tft_write_cmd(pio, sm, &cmd, 1);
|
||||
tft_set_dc_cs(1, 0);
|
||||
}
|
||||
|
||||
void tft_init(const struct tft_config* config) {
|
||||
memcpy(&tft_cfg, config, sizeof(tft_cfg));
|
||||
|
||||
set_sys_clock_khz(250 * 1000, true);
|
||||
gpio_init(tft_cfg.gpio_cs);
|
||||
gpio_init(tft_cfg.gpio_dc);
|
||||
gpio_init(tft_cfg.gpio_rst);
|
||||
gpio_init(tft_cfg.gpio_bl);
|
||||
gpio_set_dir(tft_cfg.gpio_cs, GPIO_OUT);
|
||||
gpio_set_dir(tft_cfg.gpio_dc, GPIO_OUT);
|
||||
gpio_set_dir(tft_cfg.gpio_rst, GPIO_OUT);
|
||||
gpio_set_dir(tft_cfg.gpio_bl, GPIO_OUT);
|
||||
|
||||
volatile uint ach = spi_init(tft_cfg.spi, 67 * 1000 * 1000); // original 125 * 1000 * 1000
|
||||
spi_set_format(tft_cfg.spi, 8, SPI_CPOL_0, SPI_CPHA_0, SPI_MSB_FIRST);
|
||||
|
||||
gpio_set_function(tft_cfg.gpio_din, GPIO_FUNC_SPI);
|
||||
gpio_set_function(tft_cfg.gpio_clk, GPIO_FUNC_SPI);
|
||||
|
||||
gpio_init(tft_cfg.gpio_cs);
|
||||
gpio_init(tft_cfg.gpio_dc);
|
||||
gpio_init(tft_cfg.gpio_rst);
|
||||
gpio_init(tft_cfg.gpio_bl);
|
||||
|
||||
gpio_set_dir(tft_cfg.gpio_cs, GPIO_OUT);
|
||||
gpio_set_dir(tft_cfg.gpio_dc, GPIO_OUT);
|
||||
gpio_set_dir(tft_cfg.gpio_rst, GPIO_OUT);
|
||||
gpio_set_dir(tft_cfg.gpio_bl, GPIO_OUT);
|
||||
|
||||
gpio_put(tft_cfg.gpio_cs, 1);
|
||||
gpio_put(tft_cfg.gpio_dc, 1);
|
||||
gpio_put(tft_cfg.gpio_rst, 1);
|
||||
sleep_ms(100);
|
||||
|
||||
// SWRESET (01h): Software Reset
|
||||
tft_cmd(0x01, NULL, 0);
|
||||
sleep_ms(150);
|
||||
|
||||
// SLPOUT (11h): Sleep Out
|
||||
tft_cmd(0x11, NULL, 0);
|
||||
sleep_ms(50);
|
||||
|
||||
// COLMOD (3Ah): Interface Pixel Format
|
||||
// - RGB interface color format = 65K of RGB interface
|
||||
// - Control interface color format = 16bit/pixel
|
||||
tft_cmd(0x3a, (uint8_t[]) { 0x55 }, 1);
|
||||
sleep_ms(10);
|
||||
|
||||
// MADCTL (36h): Memory Data Access Control
|
||||
// - Page Address Order = Top to Bottom
|
||||
// - Column Address Order = Left to Right
|
||||
// - Page/Column Order = Normal Mode
|
||||
// - Line Address Order = LCD Refresh Top to Bottom
|
||||
// - RGB/BGR Order = RGB
|
||||
// - Display Data Latch Data Order = LCD Refresh Left to Right
|
||||
tft_cmd(0x36, (uint8_t[]) { 0x00 }, 1);
|
||||
|
||||
tft_caset(0, tft_cfg.width);
|
||||
tft_raset(0, tft_cfg.height);
|
||||
|
||||
// INVON (21h): Display Inversion On
|
||||
// tft_cmd(0x21, NULL, 0);
|
||||
// sleep_ms(10);
|
||||
|
||||
// NORON (13h): Normal Display Mode On
|
||||
tft_cmd(0x13, NULL, 0);
|
||||
sleep_ms(10);
|
||||
|
||||
// DISPON (29h): Display On
|
||||
tft_cmd(0x29, NULL, 0);
|
||||
sleep_ms(10);
|
||||
|
||||
gpio_put(tft_cfg.gpio_bl, 1);
|
||||
gpio_put(tft_cfg.gpio_cs, 1);
|
||||
gpio_put(tft_cfg.gpio_rst, 1);
|
||||
lcd_init(tft_cfg.pio, tft_cfg.sm, st7789_init_seq);
|
||||
gpio_put(tft_cfg.gpio_bl, 1);
|
||||
}
|
||||
void tft_ramwr()
|
||||
{
|
||||
gpio_put(tft_cfg.gpio_cs, 0);
|
||||
gpio_put(tft_cfg.gpio_dc, 0);
|
||||
|
||||
// RAMWR (2Ch): Memory Write
|
||||
uint8_t cmd = 0x2c;
|
||||
spi_write_blocking(tft_cfg.spi, &cmd, sizeof(cmd));
|
||||
|
||||
gpio_put(tft_cfg.gpio_cs, 0);
|
||||
gpio_put(tft_cfg.gpio_dc, 1);
|
||||
}
|
||||
void tft_write(const void* data, size_t len)
|
||||
{
|
||||
spi_write16_blocking(tft_cfg.spi, data, len / 2);
|
||||
}
|
||||
|
||||
void tft_put(uint16_t pixel)
|
||||
{
|
||||
tft_write(&pixel, sizeof(pixel));
|
||||
}
|
||||
|
||||
void tft_fill(uint16_t pixel)
|
||||
{
|
||||
void tft_fill(uint16_t color) {
|
||||
tft_start_pixels(tft_cfg.pio, tft_cfg.sm);
|
||||
int num_pixels = tft_cfg.width * tft_cfg.height;
|
||||
|
||||
tft_set_cursor(0, 0);
|
||||
if (!tft_data_mode) {
|
||||
tft_ramwr();
|
||||
|
||||
spi_set_format(tft_cfg.spi, 16, SPI_CPOL_0, SPI_CPHA_0, SPI_MSB_FIRST);
|
||||
|
||||
tft_data_mode = true;
|
||||
}
|
||||
|
||||
printf("test");
|
||||
for (int i = 0; i < num_pixels; i++) {
|
||||
|
||||
tft_put(pixel);
|
||||
tft_put(tft_cfg.pio, tft_cfg.sm, color >> 8);
|
||||
tft_put(tft_cfg.pio, tft_cfg.sm, color & 0xff);
|
||||
}
|
||||
printf("test");
|
||||
}
|
||||
|
||||
void tft_set_cursor(uint16_t x, uint16_t y)
|
||||
{
|
||||
tft_caset(x, tft_cfg.width);
|
||||
tft_raset(y, tft_cfg.height);
|
||||
}
|
||||
|
||||
void tft_vertical_scroll(uint16_t row)
|
||||
{
|
||||
uint8_t data[] = {
|
||||
(row >> 8) & 0xff,
|
||||
row & 0x00ff
|
||||
};
|
||||
|
||||
// VSCSAD (37h): Vertical Scroll Start Address of RAM
|
||||
tft_cmd(0x37, data, sizeof(data));
|
||||
}
|
||||
35
src/tft.h
35
src/tft.h
@@ -4,11 +4,14 @@
|
||||
#include "hardware/gpio.h"
|
||||
#include "hardware/spi.h"
|
||||
#include "hardware/divider.h"
|
||||
#include "tft.pio.h"
|
||||
#include "pico/stdlib.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
struct tft_config {
|
||||
spi_inst_t* spi;
|
||||
PIO pio;
|
||||
uint sm;
|
||||
uint gpio_din;
|
||||
uint gpio_clk;
|
||||
int gpio_cs;
|
||||
@@ -19,15 +22,25 @@ struct tft_config {
|
||||
uint16_t height;
|
||||
};
|
||||
|
||||
void tft_cmd(uint8_t cmd, const uint8_t* data, size_t len);
|
||||
void tft_caset(uint16_t xs, uint16_t xe);
|
||||
void tft_raset(uint16_t ys, uint16_t ye);
|
||||
void tft_init(const struct tft_config* config);
|
||||
void tft_ramwr();
|
||||
void tft_write(const void* data, size_t len);
|
||||
void tft_put(uint16_t pixel);
|
||||
void tft_fill(uint16_t pixel);
|
||||
void tft_set_cursor(uint16_t x, uint16_t y);
|
||||
void tft_vertical_scroll(uint16_t row);
|
||||
|
||||
// Note the delays have been shortened a little
|
||||
static const uint8_t st7789_init_seq[] = {
|
||||
1, 20, 0x01, // Software reset
|
||||
1, 10, 0x11, // Exit sleep mode
|
||||
2, 2, 0x3a, 0x55, // Set colour mode to 16 bit
|
||||
2, 0, 0x36, 0x00, // Set MADCTL: row then column, refresh is bottom to top ????
|
||||
5, 0, 0x2a, 0x00, 0x00, 320 >> 8, 320 & 0xff, // CASET: column addresses
|
||||
5, 0, 0x2b, 0x00, 0x00, 480 >> 8, 480 & 0xff, // RASET: row addresses
|
||||
1, 2, 0x13, // Normal display on, then 10 ms delay
|
||||
1, 2, 0x29, // Main screen turn on, then wait 500 ms
|
||||
0 // Terminate list
|
||||
};
|
||||
|
||||
|
||||
void tft_set_dc_cs(bool dc, bool cs);
|
||||
void tft_write_cmd(PIO pio, uint sm, const uint8_t *cmd, size_t count);
|
||||
void lcd_init(PIO pio, uint sm, const uint8_t *init_seq);
|
||||
void tft_start_pixels(PIO pio, uint sm);
|
||||
void tft_init(const struct tft_config* config);
|
||||
void tft_fill(uint16_t color);
|
||||
#endif // TFT_H
|
||||
@@ -27,7 +27,7 @@ static inline void tft_program_init(PIO pio, uint sm, uint offset, uint data_pin
|
||||
pio_gpio_init(pio, clk_pin);
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, data_pin, 1, true);
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, clk_pin, 1, true);
|
||||
pio_sm_config c = st7789_lcd_program_get_default_config(offset);
|
||||
pio_sm_config c = tft_program_get_default_config(offset);
|
||||
sm_config_set_sideset_pins(&c, clk_pin);
|
||||
sm_config_set_out_pins(&c, data_pin, 1);
|
||||
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
|
||||
|
||||
Reference in New Issue
Block a user