2021-03-24 12:18:56 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "hardware/spi.h"
|
|
|
|
#include "hardware/gpio.h"
|
2021-05-14 18:12:37 +01:00
|
|
|
#include "../../common/pimoroni_common.hpp"
|
2021-03-24 12:18:56 +00:00
|
|
|
|
|
|
|
namespace pimoroni {
|
|
|
|
|
|
|
|
class ST7789 {
|
2021-04-20 10:54:10 +01:00
|
|
|
spi_inst_t *spi = PIMORONI_SPI_DEFAULT_INSTANCE;
|
2021-04-23 13:22:00 +01:00
|
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------
|
|
|
|
// Variables
|
|
|
|
//--------------------------------------------------
|
|
|
|
private:
|
2021-03-24 12:18:56 +00:00
|
|
|
// screen properties
|
|
|
|
uint16_t width;
|
|
|
|
uint16_t height;
|
2022-05-12 12:04:55 +01:00
|
|
|
bool round;
|
2021-03-24 12:18:56 +00:00
|
|
|
uint16_t row_stride;
|
2021-04-23 13:35:19 +01:00
|
|
|
uint32_t dma_channel;
|
|
|
|
|
2021-03-24 12:18:56 +00:00
|
|
|
// interface pins with our standard defaults where appropriate
|
2021-04-20 10:54:10 +01:00
|
|
|
uint cs = SPI_BG_FRONT_CS;
|
|
|
|
uint dc = SPI_DEFAULT_MISO;
|
|
|
|
uint sck = SPI_DEFAULT_SCK;
|
|
|
|
uint mosi = SPI_DEFAULT_MOSI;
|
|
|
|
uint miso = PIN_UNUSED; // used as data/command
|
|
|
|
uint bl = SPI_BG_FRONT_PWM;
|
|
|
|
uint vsync = PIN_UNUSED; // only available on some products
|
2021-03-24 12:18:56 +00:00
|
|
|
|
Improve ST7789 frame rate ~4x
The ST7789's Tscycw (time between serial write clock cycles) is
16 ns. This can be found on page 44 of the datasheet I'm using:
https://www.waveshare.com/w/upload/a/ae/ST7789_Datasheet.pdf
(I do not know which manufacturer Pimoroni products use and if
their parts might be different. But it seems like this wouldn't
change.)
The existing code sets the SPI baud to 16 * 1000 * 1000. But baud
is Hz, not seconds. That 16 * 1000 * 1000 doesn't represent 16 ns.
It represents 16,000,000 Hz.
16 ns * (1 Hz / s) = 62,500,000 Hz.
This commit changes the baud from 16 * 1000 * 1000 to 62'500'000,
representing ~4x speed improvement in SPI and thus ~4x frame rate
improvement, since the display's frame rate is currently
SPI-limited.
A before & after video can be seen here:
https://www.youtube.com/watch?v=n2y19TCnATo
Note that also on page 44 of that datasheet Tscycr (the read speed)
is only 150 ns, not 16 ns. Right now, the Pimoroni code doesn't read
any values back from the ST7789 so it is safe to operate at the
higher speed.
Also note that the 16 * 1000 * 1000 is the requested baud. The actual
baud is the closest the Pico can get, which is 15,625,000.
The new requested baud of 62'500'000 results in an exact match.
2021-11-11 23:20:21 +00:00
|
|
|
// The ST7789 requires 16 ns between SPI rising edges.
|
|
|
|
// 16 ns = 62,500,000 Hz
|
|
|
|
static const uint32_t SPI_BAUD = 62'500'000;
|
2021-03-24 12:18:56 +00:00
|
|
|
|
2022-05-12 12:04:55 +01:00
|
|
|
|
2021-03-24 12:18:56 +00:00
|
|
|
public:
|
2021-04-20 10:54:10 +01:00
|
|
|
// frame buffer where pixel data is stored
|
|
|
|
uint16_t *frame_buffer;
|
|
|
|
|
2021-04-19 16:36:31 +01:00
|
|
|
ST7789(uint16_t width, uint16_t height, uint16_t *frame_buffer, BG_SPI_SLOT slot) :
|
|
|
|
width(width), height(height), frame_buffer(frame_buffer) {
|
|
|
|
switch(slot) {
|
2021-06-05 18:58:23 +01:00
|
|
|
case PICO_EXPLORER_ONBOARD:
|
|
|
|
cs = SPI_BG_FRONT_CS;
|
|
|
|
bl = PIN_UNUSED;
|
|
|
|
break;
|
2021-04-19 16:36:31 +01:00
|
|
|
case BG_SPI_FRONT:
|
2021-04-20 10:54:10 +01:00
|
|
|
cs = SPI_BG_FRONT_CS;
|
|
|
|
bl = SPI_BG_FRONT_PWM;
|
2021-04-19 16:36:31 +01:00
|
|
|
break;
|
|
|
|
case BG_SPI_BACK:
|
2021-04-20 10:54:10 +01:00
|
|
|
cs = SPI_BG_BACK_CS;
|
|
|
|
bl = SPI_BG_BACK_PWM;
|
2021-04-19 16:36:31 +01:00
|
|
|
break;
|
|
|
|
}
|
2022-03-21 17:02:46 +00:00
|
|
|
if(!this->frame_buffer) {
|
|
|
|
this->frame_buffer = new uint16_t(width * height);
|
|
|
|
}
|
2021-04-19 16:36:31 +01:00
|
|
|
}
|
|
|
|
|
2021-03-24 12:18:56 +00:00
|
|
|
ST7789(uint16_t width, uint16_t height, uint16_t *frame_buffer) :
|
|
|
|
width(width), height(height), frame_buffer(frame_buffer) {}
|
|
|
|
|
|
|
|
ST7789(uint16_t width, uint16_t height, uint16_t *frame_buffer,
|
|
|
|
spi_inst_t *spi,
|
2021-04-20 10:54:10 +01:00
|
|
|
uint cs, uint dc, uint sck, uint mosi, uint miso = PIN_UNUSED, uint bl = PIN_UNUSED) :
|
|
|
|
spi(spi),
|
|
|
|
width(width), height(height),
|
|
|
|
cs(cs), dc(dc), sck(sck), mosi(mosi), miso(miso), bl(bl), frame_buffer(frame_buffer) {}
|
2021-03-24 12:18:56 +00:00
|
|
|
|
2021-04-23 13:22:00 +01:00
|
|
|
|
|
|
|
//--------------------------------------------------
|
|
|
|
// Methods
|
|
|
|
//--------------------------------------------------
|
|
|
|
public:
|
2021-06-14 15:26:58 +01:00
|
|
|
void init(bool auto_init_sequence = true, bool round = false, uint32_t spi_baud = SPI_BAUD);
|
2022-05-12 12:04:55 +01:00
|
|
|
void configure_display(bool rotate180);
|
2021-03-24 12:18:56 +00:00
|
|
|
|
2021-03-30 15:15:13 +01:00
|
|
|
spi_inst_t* get_spi() const;
|
2021-04-20 10:54:10 +01:00
|
|
|
uint get_cs() const;
|
|
|
|
uint get_dc() const;
|
|
|
|
uint get_sck() const;
|
|
|
|
uint get_mosi() const;
|
|
|
|
uint get_bl() const;
|
2021-03-30 15:15:13 +01:00
|
|
|
|
2021-03-24 12:18:56 +00:00
|
|
|
void command(uint8_t command, size_t len = 0, const char *data = NULL);
|
|
|
|
void vsync_callback(gpio_irq_callback_t callback);
|
|
|
|
void update(bool dont_block = false);
|
|
|
|
void set_backlight(uint8_t brightness);
|
|
|
|
void flip();
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|