ST7789: Experimental 8bit framebuffer.

driver/sh1107
Phil Howard 2022-05-25 17:22:20 +01:00
rodzic 446db105f9
commit 7abe4aae7f
10 zmienionych plików z 97 dodań i 40 usunięć

Wyświetl plik

@ -88,7 +88,7 @@ namespace pimoroni {
configure_display(false);
if(bl != PIN_UNUSED) {
update(); // Send the new buffer to the display to clear any previous content
//update(); // Send the new buffer to the display to clear any previous content
sleep_ms(50); // Wait for the update to apply
set_backlight(255); // Turn backlight on now surprises have passed
}
@ -219,8 +219,24 @@ namespace pimoroni {
gpio_put(cs, 1);
}
void ST7789::update() {
command(reg::RAMWR, width * height * sizeof(uint16_t), (const char*)frame_buffer);
void ST7789::update(uint16_t *palette) {
//command(reg::RAMWR, width * height * sizeof(uint16_t), (const char*)frame_buffer);
command(reg::RAMWR);
uint16_t row[width];
gpio_put(dc, 1); // data mode
gpio_put(cs, 0);
for(auto y = 0u; y < height; y++) {
for(auto x = 0u; x < width; x++) {
auto i = y * width + x;
row[x] = palette[frame_buffer[i]];
}
if(spi) {
spi_write_blocking(spi, (const uint8_t*)row, width * sizeof(uint16_t));
} else {
write_blocking_parallel((const uint8_t*)row, width * sizeof(uint16_t));
}
}
gpio_put(cs, 1);
}
void ST7789::set_backlight(uint8_t brightness) {

Wyświetl plik

@ -36,10 +36,10 @@ namespace pimoroni {
public:
// frame buffer where pixel data is stored
uint16_t *frame_buffer;
uint8_t *frame_buffer;
// Parallel init
ST7789(uint16_t width, uint16_t height, uint16_t *frame_buffer,
ST7789(uint16_t width, uint16_t height, uint8_t *frame_buffer,
uint cs, uint dc, uint wr_sck, uint rd_sck, uint d0, uint bl = PIN_UNUSED) :
spi(nullptr),
width(width), height(height), round(false),
@ -68,7 +68,7 @@ namespace pimoroni {
}
// Serial init
ST7789(uint16_t width, uint16_t height, bool round, uint16_t *frame_buffer,
ST7789(uint16_t width, uint16_t height, bool round, uint8_t *frame_buffer,
spi_inst_t *spi,
uint cs, uint dc, uint sck, uint mosi, uint bl = PIN_UNUSED) :
spi(spi),
@ -101,7 +101,7 @@ namespace pimoroni {
uint get_bl() const;
void command(uint8_t command, size_t len = 0, const char *data = NULL);
void update();
void update(uint16_t *palette);
void set_backlight(uint8_t brightness);
void flip();
@ -133,7 +133,7 @@ namespace pimoroni {
void write_blocking_parallel(const uint8_t *src, size_t len);
void common_init() {
if(!this->frame_buffer) {
this->frame_buffer = new uint16_t[width * height];
this->frame_buffer = new uint8_t[width * height];
}
// if a backlight pin is provided then set it up for

Wyświetl plik

@ -30,7 +30,7 @@ namespace pimoroni {
}
void ST7789Generic::update() {
st7789.update();
st7789.update(palette);
}
void ST7789Generic::flip() {

Wyświetl plik

@ -10,34 +10,34 @@ namespace pimoroni {
ST7789 st7789;
public:
ST7789Generic(uint16_t width, uint16_t height, bool round=false, uint16_t *frame_buffer=nullptr) :
ST7789Generic(uint16_t width, uint16_t height, bool round=false, uint8_t *frame_buffer=nullptr) :
PicoGraphics(width, height, frame_buffer),
st7789(width, height, round, frame_buffer, PIMORONI_SPI_DEFAULT_INSTANCE, SPI_BG_FRONT_CS, SPI_DEFAULT_MISO, SPI_DEFAULT_SCK, SPI_DEFAULT_MOSI, SPI_BG_FRONT_PWM) {
this->frame_buffer = st7789.frame_buffer;
this->frame_buffer = (Pen *)st7789.frame_buffer;
this->st7789.init();
};
ST7789Generic(uint16_t width, uint16_t height, bool round, uint16_t *frame_buffer, BG_SPI_SLOT slot) :
ST7789Generic(uint16_t width, uint16_t height, bool round, uint8_t *frame_buffer, BG_SPI_SLOT slot) :
PicoGraphics(width, height, frame_buffer),
st7789(width, height, round, frame_buffer, PIMORONI_SPI_DEFAULT_INSTANCE, st7789.get_slot_cs(slot), SPI_DEFAULT_MISO, SPI_DEFAULT_SCK, SPI_DEFAULT_MOSI, st7789.get_slot_bl(slot)) {
this->frame_buffer = st7789.frame_buffer;
this->frame_buffer = (Pen *)st7789.frame_buffer;
this->st7789.init();
};
ST7789Generic(uint16_t width, uint16_t height, bool round, uint16_t *frame_buffer,
ST7789Generic(uint16_t width, uint16_t height, bool round, uint8_t *frame_buffer,
spi_inst_t *spi,
uint cs, uint dc, uint sck, uint mosi, uint bl = PIN_UNUSED) :
PicoGraphics(width, height, frame_buffer),
st7789(width, height, round, frame_buffer, spi, cs, dc, sck, mosi, bl) {
this->frame_buffer = st7789.frame_buffer;
this->frame_buffer = (Pen *)st7789.frame_buffer;
this->st7789.init();
};
ST7789Generic(uint16_t width, uint16_t height, uint16_t *frame_buffer,
ST7789Generic(uint16_t width, uint16_t height, uint8_t *frame_buffer,
uint cs, uint dc, uint wr_sck, uint rd_sck, uint d0, uint bl = PIN_UNUSED) :
PicoGraphics(width, height, frame_buffer),
st7789(width, height, frame_buffer, cs, dc, wr_sck, rd_sck, d0, bl) {
this->frame_buffer = st7789.frame_buffer;
this->frame_buffer = (Pen *)st7789.frame_buffer;
this->st7789.init();
};

Wyświetl plik

@ -14,7 +14,7 @@ const uint8_t MOTOR2P = 11;
namespace pimoroni {
PicoExplorer::PicoExplorer(uint16_t *buf)
PicoExplorer::PicoExplorer(uint8_t *buf)
: PicoGraphics(WIDTH, HEIGHT, buf),
screen(WIDTH, HEIGHT, false, buf, PIMORONI_SPI_DEFAULT_INSTANCE, screen.get_slot_cs(PICO_EXPLORER_ONBOARD), SPI_DEFAULT_MISO, SPI_DEFAULT_SCK, SPI_DEFAULT_MOSI, screen.get_slot_bl(PICO_EXPLORER_ONBOARD)) {
__fb = buf;
@ -52,7 +52,7 @@ namespace pimoroni {
}
void PicoExplorer::update() {
screen.update();
screen.update(palette);
}
bool PicoExplorer::is_pressed(uint8_t button) {

Wyświetl plik

@ -34,13 +34,13 @@ namespace pimoroni {
static const uint GP6 = 6;
static const uint GP7 = 7;
uint16_t *__fb;
uint8_t *__fb;
private:
ST7789 screen;
int8_t audio_pin = -1;
public:
PicoExplorer(uint16_t *buf);
PicoExplorer(uint8_t *buf);
void init();
void update();

Wyświetl plik

@ -1,8 +1,8 @@
#include "pico_graphics.hpp"
namespace pimoroni {
PicoGraphics::PicoGraphics(uint16_t width, uint16_t height, uint16_t *frame_buffer)
: frame_buffer(frame_buffer), bounds(0, 0, width, height), clip(0, 0, width, height) {
PicoGraphics::PicoGraphics(uint16_t width, uint16_t height, void *frame_buffer)
: frame_buffer((Pen *)frame_buffer), bounds(0, 0, width, height), clip(0, 0, width, height) {
set_font(&font6);
};
@ -18,6 +18,21 @@ namespace pimoroni {
pen = p;
}
void PicoGraphics::set_pen_raw(uint16_t p) {
for(auto i=0u; i < palette_ptr; i++) {
if(palette[i] == p) {
pen = i;
return;
};
}
if(palette_ptr < 256) {
palette[palette_ptr] = p;
pen = palette_ptr;
palette_ptr += 1;
}
}
void PicoGraphics::set_clip(const Rect &r) {
clip = bounds.intersection(r);
}

Wyświetl plik

@ -10,7 +10,7 @@
// supports only 16-bit (565) RGB framebuffers
namespace pimoroni {
typedef uint16_t Pen;
typedef uint8_t Pen;
struct Rect;
@ -45,7 +45,7 @@ namespace pimoroni {
class PicoGraphics {
public:
uint16_t *frame_buffer;
Pen *frame_buffer;
Rect bounds;
Rect clip;
@ -54,18 +54,32 @@ namespace pimoroni {
const bitmap::font_t *font;
uint16_t palette[256];
uint16_t palette_ptr = 0;
public:
PicoGraphics(uint16_t width, uint16_t height, uint16_t *frame_buffer);
PicoGraphics(uint16_t width, uint16_t height, void *frame_buffer);
void set_font(const bitmap::font_t *font);
void set_pen(uint8_t r, uint8_t g, uint8_t b);
void set_pen(Pen p);
void set_pen_raw(uint16_t p);
constexpr Pen create_pen(uint8_t r, uint8_t g, uint8_t b) {
uint16_t p = ((r & 0b11111000) << 8) |
((g & 0b11111100) << 3) |
((b & 0b11111000) >> 3);
return __builtin_bswap16(p);
p = __builtin_bswap16(p);
for(auto i=0u; i < palette_ptr; i++) {
if(palette[i] == p) return i;
}
if(palette_ptr < 256) {
palette[palette_ptr] = p;
palette_ptr += 1;
}
return palette_ptr - 1;
};
void set_clip(const Rect &r);

Wyświetl plik

@ -27,7 +27,7 @@ mp_obj_t picoexplorer_init(mp_obj_t buf_obj) {
}
// Create a new display pointing to the newly provided buffer
explorer = new PicoExplorer((uint16_t *)bufinfo.buf);
explorer = new PicoExplorer((uint8_t *)bufinfo.buf);
explorer->init();
return mp_const_none;

Wyświetl plik

@ -14,7 +14,7 @@ typedef struct _GenericST7789_obj_t {
mp_obj_base_t base;
ST7789Generic *st7789;
bool parallel;
uint16_t *buffer;
uint8_t *buffer;
} GenericST7789_obj_t;
/***** Print *****/
@ -85,12 +85,12 @@ mp_obj_t GenericST7789_make_new(const mp_obj_type_t *type, size_t n_args, size_t
if (args[ARG_buffer].u_obj != mp_const_none) {
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[ARG_buffer].u_obj, &bufinfo, MP_BUFFER_RW);
self->buffer = (uint16_t *)bufinfo.buf;
if(bufinfo.len < (size_t)(width * height * 2)) {
self->buffer = (uint8_t *)bufinfo.buf;
if(bufinfo.len < (size_t)(width * height)) {
mp_raise_ValueError("Supplied buffer is too small!");
}
} else {
self->buffer = m_new(uint16_t, width * height);
self->buffer = m_new(uint8_t, width * height);
}
if(args[ARG_slot].u_int != -1) {
@ -166,12 +166,12 @@ mp_obj_t GenericST7789Parallel_make_new(const mp_obj_type_t *type, size_t n_args
if (args[ARG_buffer].u_obj != mp_const_none) {
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[ARG_buffer].u_obj, &bufinfo, MP_BUFFER_RW);
self->buffer = (uint16_t *)bufinfo.buf;
if(bufinfo.len < (size_t)(width * height * 2)) {
self->buffer = (uint8_t *)bufinfo.buf;
if(bufinfo.len < (size_t)(width * height)) {
mp_raise_ValueError("Supplied buffer is too small!");
}
} else {
self->buffer = m_new(uint16_t, width * height);
self->buffer = m_new(uint8_t, width * height);
}
int cs = args[ARG_cs].u_int;
@ -187,6 +187,8 @@ mp_obj_t GenericST7789Parallel_make_new(const mp_obj_type_t *type, size_t n_args
self->st7789->configure_display(true);
}
mp_printf(&mp_plat_print, "ST7789Generic - %lu\n", sizeof(ST7789Generic));
return MP_OBJ_FROM_PTR(self);
}
@ -223,10 +225,11 @@ mp_obj_t GenericST7789_set_backlight(size_t n_args, const mp_obj_t *pos_args, mp
mp_obj_t GenericST7789_set_pen(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
if(n_args <= 2) {
enum { ARG_self, ARG_pen };
enum { ARG_self, ARG_pen, ARG_raw };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_pen, MP_ARG_REQUIRED | MP_ARG_INT },
{ MP_QSTR_raw, MP_ARG_OBJ, { .u_obj = mp_const_false } },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
@ -236,10 +239,19 @@ mp_obj_t GenericST7789_set_pen(size_t n_args, const mp_obj_t *pos_args, mp_map_t
int pen = args[ARG_pen].u_int;
if(pen < 0 || pen > 0xffff)
mp_raise_ValueError("p is not a valid pen.");
else
self->st7789->set_pen(pen);
if (args[ARG_raw].u_obj == mp_const_false) {
if(pen < 0 || pen > 0xff) {
mp_raise_ValueError("p is not a valid pen.");
} else {
self->st7789->set_pen(pen);
}
} else {
if(pen < 0 || pen > 0xffff) {
mp_raise_ValueError("p is not a valid pen.");
} else {
self->st7789->set_pen_raw(pen);
}
}
}
else {
enum { ARG_self, ARG_r, ARG_g, ARG_b };