ST7789/PicoGraphics: Templated framebuffer formats.
This commit is contained in:
parent
dbed4a463f
commit
7e4725d1cd
|
@ -9,4 +9,4 @@ target_include_directories(${DRIVER_NAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR})
|
|||
target_include_directories(st7789 INTERFACE ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
# Pull in pico libraries that we need
|
||||
target_link_libraries(${DRIVER_NAME} INTERFACE pico_stdlib pimoroni_bus hardware_spi hardware_pwm hardware_dma)
|
||||
target_link_libraries(${DRIVER_NAME} INTERFACE pico_stdlib pimoroni_bus hardware_spi hardware_pwm hardware_dma pico_graphics)
|
||||
|
|
|
@ -201,6 +201,101 @@ namespace pimoroni {
|
|||
gpio_put(cs, 1);
|
||||
}
|
||||
|
||||
void ST7789::update(PicoGraphics<PenRGB565> *graphics) {
|
||||
command(reg::RAMWR, width * height * sizeof(uint16_t), (const char*)graphics->get_data());
|
||||
}
|
||||
|
||||
void ST7789::update(PicoGraphics<PenRGB332> *graphics) {
|
||||
uint8_t command = reg::RAMWR;
|
||||
|
||||
gpio_put(dc, 0); // command mode
|
||||
|
||||
gpio_put(cs, 0);
|
||||
|
||||
if(spi) {
|
||||
spi_write_blocking(spi, &command, 1);
|
||||
} else {
|
||||
write_blocking_parallel(&command, 1);
|
||||
}
|
||||
|
||||
gpio_put(dc, 1); // data mode
|
||||
|
||||
uint16_t row_buf[width];
|
||||
|
||||
for(auto y = 0u; y < height; y++) {
|
||||
graphics->get_data(y, &row_buf);
|
||||
// TODO: Add DMA->SPI / PIO while we prep the next row
|
||||
if(spi) {
|
||||
spi_write_blocking(spi, (const uint8_t*)row_buf, width * sizeof(uint16_t));
|
||||
} else {
|
||||
write_blocking_parallel((const uint8_t*)row_buf, width * sizeof(uint16_t));
|
||||
}
|
||||
}
|
||||
|
||||
gpio_put(cs, 1);
|
||||
}
|
||||
|
||||
void ST7789::update(PicoGraphics<PenP8> *graphics) {
|
||||
uint8_t command = reg::RAMWR;
|
||||
|
||||
gpio_put(dc, 0); // command mode
|
||||
|
||||
gpio_put(cs, 0);
|
||||
|
||||
if(spi) {
|
||||
spi_write_blocking(spi, &command, 1);
|
||||
} else {
|
||||
write_blocking_parallel(&command, 1);
|
||||
}
|
||||
|
||||
gpio_put(dc, 1); // data mode
|
||||
|
||||
uint16_t row_buf[width];
|
||||
|
||||
for(auto y = 0u; y < height; y++) {
|
||||
graphics->get_data(y, &row_buf);
|
||||
// TODO: Add DMA->SPI / PIO while we prep the next row
|
||||
if(spi) {
|
||||
spi_write_blocking(spi, (const uint8_t*)row_buf, width * sizeof(uint16_t));
|
||||
} else {
|
||||
write_blocking_parallel((const uint8_t*)row_buf, width * sizeof(uint16_t));
|
||||
}
|
||||
}
|
||||
|
||||
gpio_put(cs, 1);
|
||||
}
|
||||
|
||||
void ST7789::update(PicoGraphics<PenP4> *graphics) {
|
||||
uint8_t command = reg::RAMWR;
|
||||
|
||||
gpio_put(dc, 0); // command mode
|
||||
|
||||
gpio_put(cs, 0);
|
||||
|
||||
if(spi) {
|
||||
spi_write_blocking(spi, &command, 1);
|
||||
} else {
|
||||
write_blocking_parallel(&command, 1);
|
||||
}
|
||||
|
||||
gpio_put(dc, 1); // data mode
|
||||
|
||||
uint16_t row_buf[width];
|
||||
|
||||
for(auto y = 0u; y < height; y++) {
|
||||
graphics->get_data(y, &row_buf);
|
||||
// TODO: Add DMA->SPI / PIO while we prep the next row
|
||||
if(spi) {
|
||||
spi_write_blocking(spi, (const uint8_t*)row_buf, width * sizeof(uint16_t));
|
||||
} else {
|
||||
write_blocking_parallel((const uint8_t*)row_buf, width * sizeof(uint16_t));
|
||||
}
|
||||
}
|
||||
|
||||
gpio_put(cs, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
// Native 16-bit framebuffer update
|
||||
void ST7789::update() {
|
||||
command(reg::RAMWR, width * height * sizeof(uint16_t), (const char*)frame_buffer);
|
||||
|
@ -238,6 +333,7 @@ namespace pimoroni {
|
|||
|
||||
gpio_put(cs, 1);
|
||||
}
|
||||
*/
|
||||
|
||||
void ST7789::set_backlight(uint8_t brightness) {
|
||||
// gamma correct the provided 0-255 brightness value onto a
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "hardware/pwm.h"
|
||||
#include "common/pimoroni_common.hpp"
|
||||
#include "common/pimoroni_bus.hpp"
|
||||
#include "libraries/pico_graphics/pico_graphics.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
|
@ -41,15 +42,11 @@ namespace pimoroni {
|
|||
|
||||
|
||||
public:
|
||||
|
||||
// frame buffer where pixel data is stored
|
||||
void *frame_buffer;
|
||||
|
||||
// Parallel init
|
||||
ST7789(uint16_t width, uint16_t height, Rotation rotation, void *frame_buffer, ParallelPins pins) :
|
||||
spi(nullptr),
|
||||
width(width), height(height), rotation(rotation), round(false),
|
||||
cs(pins.cs), dc(pins.dc), wr_sck(pins.wr_sck), rd_sck(pins.rd_sck), d0(pins.d0), bl(pins.bl), frame_buffer(frame_buffer) {
|
||||
cs(pins.cs), dc(pins.dc), wr_sck(pins.wr_sck), rd_sck(pins.rd_sck), d0(pins.d0), bl(pins.bl) {
|
||||
|
||||
gpio_set_function(wr_sck, GPIO_FUNC_SIO);
|
||||
gpio_set_dir(wr_sck, GPIO_OUT);
|
||||
|
@ -71,7 +68,7 @@ namespace pimoroni {
|
|||
ST7789(uint16_t width, uint16_t height, Rotation rotation, bool round, void *frame_buffer, SPIPins pins) :
|
||||
spi(pins.spi),
|
||||
width(width), height(height), rotation(rotation), round(round),
|
||||
cs(pins.cs), dc(pins.dc), wr_sck(pins.sck), d0(pins.mosi), bl(pins.bl), frame_buffer(frame_buffer) {
|
||||
cs(pins.cs), dc(pins.dc), wr_sck(pins.sck), d0(pins.mosi), bl(pins.bl) {
|
||||
|
||||
// configure spi interface and pins
|
||||
spi_init(spi, SPI_BAUD);
|
||||
|
@ -86,17 +83,15 @@ namespace pimoroni {
|
|||
void command(uint8_t command, size_t len = 0, const char *data = NULL);
|
||||
void set_backlight(uint8_t brightness);
|
||||
|
||||
void update();
|
||||
void update(uint16_t *palette);
|
||||
void update(PicoGraphics<PenRGB565> *graphics);
|
||||
void update(PicoGraphics<PenRGB332> *graphics);
|
||||
void update(PicoGraphics<PenP8> *graphics);
|
||||
void update(PicoGraphics<PenP4> *graphics);
|
||||
|
||||
private:
|
||||
void configure_display(Rotation rotate);
|
||||
void write_blocking_parallel(const uint8_t *src, size_t len);
|
||||
void common_init() {
|
||||
if(!this->frame_buffer) {
|
||||
this->frame_buffer = new uint8_t[width * height];
|
||||
}
|
||||
|
||||
gpio_set_function(dc, GPIO_FUNC_SIO);
|
||||
gpio_set_dir(dc, GPIO_OUT);
|
||||
|
||||
|
|
|
@ -1,135 +1,40 @@
|
|||
#include "pico_graphics.hpp"
|
||||
|
||||
namespace pimoroni {
|
||||
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);
|
||||
set_palette_mode(PaletteModeRGB332);
|
||||
};
|
||||
|
||||
void PicoGraphics::set_font(const bitmap::font_t *font){
|
||||
template<class T>
|
||||
void PicoGraphics<T>::set_font(const bitmap::font_t *font){
|
||||
this->font = font;
|
||||
}
|
||||
|
||||
void PicoGraphics::set_pen(Pen p) {
|
||||
pen = p;
|
||||
template<class T>
|
||||
void PicoGraphics<T>::set_pen(uint16_t p) {
|
||||
pen.set_color(p);
|
||||
}
|
||||
|
||||
void PicoGraphics::set_palette_mode(PaletteMode mode) {
|
||||
palette_mode = mode;
|
||||
if(mode == PaletteModeRGB332) {
|
||||
rgb332_palette();
|
||||
} else {
|
||||
empty_palette();
|
||||
}
|
||||
}
|
||||
|
||||
int PicoGraphics::create_pen(uint8_t r, uint8_t g, uint8_t b) {
|
||||
if (palette_mode == PaletteModeRGB332) {
|
||||
return rgb_to_rgb332_index(r, g, b); // Fast pack RGB into palette index
|
||||
} else {
|
||||
RGB565 c = create_pen_rgb565(r, g, b);
|
||||
int result = search_palette(c);
|
||||
|
||||
if (result == -1) {
|
||||
result = put_palette(create_pen_rgb565(r, g, b));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
void PicoGraphics::set_pen(uint8_t r, uint8_t g, uint8_t b) {
|
||||
int result = create_pen(r, g, b);
|
||||
(void)result;
|
||||
}
|
||||
|
||||
int PicoGraphics::search_palette(RGB565 c) {
|
||||
for(auto i = 0u; i < 256; i++) {
|
||||
if((palette_status[i] & PaletteStatusUsed) && palette[i] == c) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int PicoGraphics::put_palette(RGB565 c) {
|
||||
if(palette_mode != PaletteModeUSER) return -1;
|
||||
|
||||
for(auto i = 0u; i < 256; i++) {
|
||||
if(!(palette_status[i] & (PaletteStatusUsed | PaletteStatusReserved))) {
|
||||
palette[i] = c;
|
||||
palette_status[i] = PaletteStatusUsed;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void PicoGraphics::set_palette(uint8_t i, RGB565 c) {
|
||||
if(palette_mode != PaletteModeUSER) return;
|
||||
|
||||
palette[i] = c;
|
||||
palette_status[i] |= PaletteStatusUsed;
|
||||
}
|
||||
|
||||
int PicoGraphics::reserve_palette() {
|
||||
if(palette_mode != PaletteModeUSER) return - 1;
|
||||
|
||||
for (auto i = 0u; i < 256; i++) {
|
||||
if (!palette_status[i]) {
|
||||
palette_status[i] = PaletteStatusReserved;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void PicoGraphics::empty_palette() {
|
||||
for (auto i = 0u; i < 256; i++) {
|
||||
palette[i] = 0;
|
||||
palette_status[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void PicoGraphics::rgb332_palette() {
|
||||
for (auto i = 0u; i < 256; i++) {
|
||||
// Convert the implicit RGB332 (i) into RGB565
|
||||
// 0b11100 000 0b00011100 0b00000011
|
||||
palette[i] = ((i & 0b11100000) << 8) | ((i & 0b00011100) << 6) | ((i & 0b00000011) << 3);
|
||||
palette[i] = __builtin_bswap16(palette[i]);
|
||||
palette_status[i] = PaletteStatusUsed;
|
||||
}
|
||||
}
|
||||
|
||||
void PicoGraphics::set_clip(const Rect &r) {
|
||||
template<class T>
|
||||
void PicoGraphics<T>::set_clip(const Rect &r) {
|
||||
clip = bounds.intersection(r);
|
||||
}
|
||||
|
||||
void PicoGraphics::remove_clip() {
|
||||
template<class T>
|
||||
void PicoGraphics<T>::remove_clip() {
|
||||
clip = bounds;
|
||||
}
|
||||
|
||||
Pen* PicoGraphics::ptr(const Rect &r) {
|
||||
return frame_buffer + r.x + r.y * bounds.w;
|
||||
}
|
||||
|
||||
Pen* PicoGraphics::ptr(const Point &p) {
|
||||
return frame_buffer + p.x + p.y * bounds.w;
|
||||
}
|
||||
|
||||
Pen* PicoGraphics::ptr(int32_t x, int32_t y) {
|
||||
return frame_buffer + x + y * bounds.w;
|
||||
}
|
||||
|
||||
void PicoGraphics::clear() {
|
||||
template<class T>
|
||||
void PicoGraphics<T>::clear() {
|
||||
rectangle(clip);
|
||||
}
|
||||
|
||||
void PicoGraphics::pixel(const Point &p) {
|
||||
template<class T>
|
||||
void PicoGraphics<T>::pixel(const Point &p) {
|
||||
if(!clip.contains(p)) return;
|
||||
*ptr(p) = pen;
|
||||
pen.set_pixel(frame_buffer, p.x, p.y, bounds.w);
|
||||
}
|
||||
|
||||
void PicoGraphics::pixel_span(const Point &p, int32_t l) {
|
||||
template<class T>
|
||||
void PicoGraphics<T>::pixel_span(const Point &p, int32_t l) {
|
||||
// check if span in bounds
|
||||
if( p.x + l < clip.x || p.x >= clip.x + clip.w ||
|
||||
p.y < clip.y || p.y >= clip.y + clip.h) return;
|
||||
|
@ -139,31 +44,36 @@ namespace pimoroni {
|
|||
if(clipped.x < clip.x) {l += clipped.x - clip.x; clipped.x = clip.x;}
|
||||
if(clipped.x + l >= clip.x + clip.w) {l = clip.x + clip.w - clipped.x;}
|
||||
|
||||
Pen *dest = ptr(clipped);
|
||||
Point dest(clipped.x, clipped.y);
|
||||
while(l--) {
|
||||
*dest++ = pen;
|
||||
pen.set_pixel(frame_buffer, dest.x, dest.y, bounds.w);
|
||||
dest.x++;
|
||||
}
|
||||
}
|
||||
|
||||
void PicoGraphics::rectangle(const Rect &r) {
|
||||
template<class T>
|
||||
void PicoGraphics<T>::rectangle(const Rect &r) {
|
||||
// clip and/or discard depending on rectangle visibility
|
||||
Rect clipped = r.intersection(clip);
|
||||
|
||||
if(clipped.empty()) return;
|
||||
|
||||
Pen *dest = ptr(clipped);
|
||||
Point dest(clipped.x, clipped.y);
|
||||
while(clipped.h--) {
|
||||
// draw span of pixels for this row
|
||||
for(int32_t i = 0; i < clipped.w; i++) {
|
||||
*dest++ = pen;
|
||||
}
|
||||
pixel_span(dest, clipped.w);
|
||||
/*for(int32_t i = 0; i < clipped.w; i++) {
|
||||
pen.set_pixel(frame_buffer, dest.x, dest.y, bounds.w);
|
||||
dest.x++;
|
||||
}*/
|
||||
|
||||
// move to next scanline
|
||||
dest += bounds.w - clipped.w;
|
||||
dest.y++;
|
||||
}
|
||||
}
|
||||
|
||||
void PicoGraphics::circle(const Point &p, int32_t radius) {
|
||||
template<class T>
|
||||
void PicoGraphics<T>::circle(const Point &p, int32_t radius) {
|
||||
// circle in screen bounds?
|
||||
Rect bounds = Rect(p.x - radius, p.y - radius, radius * 2, radius * 2);
|
||||
if(!bounds.intersects(clip)) return;
|
||||
|
@ -191,19 +101,22 @@ namespace pimoroni {
|
|||
}
|
||||
}
|
||||
|
||||
void PicoGraphics::character(const char c, const Point &p, uint8_t scale) {
|
||||
template<class T>
|
||||
void PicoGraphics<T>::character(const char c, const Point &p, uint8_t scale) {
|
||||
bitmap::character(font, [this](int32_t x, int32_t y, int32_t w, int32_t h){
|
||||
rectangle(Rect(x, y, w, h));
|
||||
}, c, p.x, p.y, scale);
|
||||
}
|
||||
|
||||
void PicoGraphics::text(const std::string &t, const Point &p, int32_t wrap, uint8_t scale) {
|
||||
template<class T>
|
||||
void PicoGraphics<T>::text(const std::string &t, const Point &p, int32_t wrap, uint8_t scale) {
|
||||
bitmap::text(font, [this](int32_t x, int32_t y, int32_t w, int32_t h){
|
||||
rectangle(Rect(x, y, w, h));
|
||||
}, t, p.x, p.y, wrap, scale);
|
||||
}
|
||||
|
||||
int32_t PicoGraphics::measure_text(const std::string &t, uint8_t scale) {
|
||||
template<class T>
|
||||
int32_t PicoGraphics<T>::measure_text(const std::string &t, uint8_t scale) {
|
||||
return bitmap::measure_text(font, t, scale);
|
||||
}
|
||||
|
||||
|
@ -215,7 +128,8 @@ namespace pimoroni {
|
|||
return (p1.y == p2.y && p1.x > p2.x) || (p1.y < p2.y);
|
||||
}
|
||||
|
||||
void PicoGraphics::triangle(Point p1, Point p2, Point p3) {
|
||||
template<class T>
|
||||
void PicoGraphics<T>::triangle(Point p1, Point p2, Point p3) {
|
||||
Rect triangle_bounds(
|
||||
Point(std::min(p1.x, std::min(p2.x, p3.x)), std::min(p1.y, std::min(p2.y, p3.y))),
|
||||
Point(std::max(p1.x, std::max(p2.x, p3.x)), std::max(p1.y, std::max(p2.y, p3.y))));
|
||||
|
@ -257,13 +171,13 @@ namespace pimoroni {
|
|||
int32_t w1 = w1row;
|
||||
int32_t w2 = w2row;
|
||||
|
||||
Pen *dest = ptr(triangle_bounds.x, triangle_bounds.y + y);
|
||||
Point dest = Point(triangle_bounds.x, triangle_bounds.y + y);
|
||||
for (int32_t x = 0; x < triangle_bounds.w; x++) {
|
||||
if ((w0 | w1 | w2) >= 0) {
|
||||
*dest = pen;
|
||||
pen.set_pixel(frame_buffer, dest.x, dest.y, bounds.w);
|
||||
}
|
||||
|
||||
dest++;
|
||||
dest.x++;
|
||||
|
||||
w0 += a12;
|
||||
w1 += a20;
|
||||
|
@ -276,7 +190,8 @@ namespace pimoroni {
|
|||
}
|
||||
}
|
||||
|
||||
void PicoGraphics::polygon(const std::vector<Point> &points) {
|
||||
template<class T>
|
||||
void PicoGraphics<T>::polygon(const std::vector<Point> &points) {
|
||||
static int32_t nodes[64]; // maximum allowed number of nodes per scanline for polygon rendering
|
||||
|
||||
int32_t miny = points[0].y, maxy = points[0].y;
|
||||
|
@ -322,7 +237,8 @@ namespace pimoroni {
|
|||
}
|
||||
}
|
||||
|
||||
void PicoGraphics::line(Point p1, Point p2) {
|
||||
template<class T>
|
||||
void PicoGraphics<T>::line(Point p1, Point p2) {
|
||||
// fast horizontal line
|
||||
if(p1.y == p2.y) {
|
||||
int32_t start = std::max(clip.x, std::min(p1.x, p2.x));
|
||||
|
@ -335,10 +251,10 @@ namespace pimoroni {
|
|||
if(p1.x == p2.x) {
|
||||
int32_t start = std::max(clip.y, std::min(p1.y, p2.y));
|
||||
int32_t length = std::min(clip.y + clip.h, std::max(p1.y, p2.y)) - start;
|
||||
Pen *dest = ptr(p1.x, start);
|
||||
Point dest(p1.x, start);
|
||||
while(length--) {
|
||||
*dest = pen;
|
||||
dest += bounds.w;
|
||||
pen.set_pixel(frame_buffer, dest.x, dest.y, bounds.w);
|
||||
dest.y++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -357,7 +273,7 @@ namespace pimoroni {
|
|||
int32_t x = p1.x;
|
||||
int32_t y = p1.y << 16;
|
||||
while(s--) {
|
||||
pixel(Point(x, y >> 16));
|
||||
pen.set_pixel(frame_buffer, x, y >> 16, bounds.w);
|
||||
y += sy;
|
||||
x += sx;
|
||||
}
|
||||
|
@ -369,7 +285,7 @@ namespace pimoroni {
|
|||
int32_t y = p1.y;
|
||||
int32_t x = p1.x << 16;
|
||||
while(s--) {
|
||||
pixel(Point(x >> 16, y));
|
||||
pen.set_pixel(frame_buffer, x >> 16, y, bounds.w);
|
||||
y += sy;
|
||||
x += sx;
|
||||
}
|
||||
|
|
|
@ -9,9 +9,9 @@
|
|||
// a tiny little graphics library for our Pico products
|
||||
// supports only 16-bit (565) RGB framebuffers
|
||||
namespace pimoroni {
|
||||
|
||||
typedef uint8_t Pen;
|
||||
typedef uint8_t RGB332;
|
||||
typedef uint16_t RGB565;
|
||||
typedef int Pen;
|
||||
|
||||
struct Rect;
|
||||
|
||||
|
@ -44,46 +44,26 @@ namespace pimoroni {
|
|||
void deflate(int32_t v);
|
||||
};
|
||||
|
||||
class PicoGraphics {
|
||||
class PicoGraphicsPenType {
|
||||
public:
|
||||
Pen *frame_buffer;
|
||||
|
||||
Rect bounds;
|
||||
Rect clip;
|
||||
|
||||
Pen pen;
|
||||
|
||||
const bitmap::font_t *font;
|
||||
|
||||
RGB565 palette[256];
|
||||
uint8_t palette_status[256];
|
||||
|
||||
enum PaletteMode {
|
||||
PaletteModeRGB332 = 0,
|
||||
PaletteModeUSER = 1
|
||||
struct PaletteEntry {
|
||||
RGB565 color;
|
||||
bool used;
|
||||
};
|
||||
|
||||
enum PaletteStatus : uint8_t {
|
||||
PaletteStatusReserved = 1,
|
||||
PaletteStatusUsed = 2
|
||||
};
|
||||
|
||||
PaletteMode palette_mode = PaletteModeRGB332;
|
||||
|
||||
public:
|
||||
PicoGraphics(uint16_t width, uint16_t height, void *frame_buffer);
|
||||
void set_font(const bitmap::font_t *font);
|
||||
void set_pen(Pen p);
|
||||
void set_palette_mode(PaletteMode mode);
|
||||
|
||||
[[deprecated("Use uint8_t create_pen(uint8_t, uint8_t, uint8_t).")]]
|
||||
void set_pen(uint8_t r, uint8_t g, uint8_t b);
|
||||
|
||||
static constexpr Pen rgb_to_rgb332_index(uint8_t r, uint8_t g, uint8_t b) {
|
||||
static constexpr RGB332 rgb_to_rgb332(uint8_t r, uint8_t g, uint8_t b) {
|
||||
return (r & 0b11100000) | ((g & 0b11100000) >> 3) | ((b & 0b11000000) >> 6);
|
||||
}
|
||||
|
||||
static constexpr RGB565 create_pen_rgb565(uint8_t r, uint8_t g, uint8_t b) {
|
||||
static constexpr RGB565 rgb332_to_rgb565(RGB332 c) {
|
||||
uint16_t p = ((c & 0b11100000) << 8) |
|
||||
((c & 0b00011100) << 6) |
|
||||
((c & 0b00000011) << 3);
|
||||
return __builtin_bswap16(p);
|
||||
}
|
||||
|
||||
static constexpr RGB565 rgb_to_rgb565(uint8_t r, uint8_t g, uint8_t b) {
|
||||
uint16_t p = ((r & 0b11111000) << 8) |
|
||||
((g & 0b11111100) << 3) |
|
||||
((b & 0b11111000) >> 3);
|
||||
|
@ -91,12 +71,228 @@ namespace pimoroni {
|
|||
return __builtin_bswap16(p);
|
||||
}
|
||||
|
||||
static constexpr RGB565 create_pen_rgb332(uint8_t r, uint8_t g, uint8_t b) {
|
||||
uint16_t p = ((r & 0b11100000) << 8) |
|
||||
((g & 0b11100000) << 3) |
|
||||
((b & 0b11000000) >> 3);
|
||||
virtual void set_pixel(void *frame_buffer, uint x, uint y, uint stride);
|
||||
virtual int create(uint8_t r, uint8_t g, uint8_t b);
|
||||
virtual void set_color(uint c);
|
||||
virtual void set_color(uint8_t r, uint8_t g, uint8_t b);
|
||||
virtual void update_color(uint8_t i, uint8_t r, uint8_t g, uint8_t b);
|
||||
|
||||
return __builtin_bswap16(p);
|
||||
virtual void palette_lookup(void *frame_buffer, void *result, uint offset, uint length);
|
||||
static size_t buffer_size(uint w, uint h); // Must be static, since user must know required size to alloc framebuffer
|
||||
};
|
||||
|
||||
class PenP4 : public PicoGraphicsPenType {
|
||||
public:
|
||||
uint8_t color;
|
||||
PaletteEntry palette[8];
|
||||
PenP4() {
|
||||
palette[0].color = rgb_to_rgb565(57, 48, 57); // Black
|
||||
palette[1].color = rgb_to_rgb565(255, 255, 255); // White
|
||||
palette[2].color = rgb_to_rgb565(58, 91, 70); // Green
|
||||
palette[3].color = rgb_to_rgb565(61, 59, 94); // Blue
|
||||
palette[4].color = rgb_to_rgb565(156, 72, 75); // Red
|
||||
palette[5].color = rgb_to_rgb565(208, 190, 71); // Yellow
|
||||
palette[6].color = rgb_to_rgb565(177, 106, 73); // Orange
|
||||
palette[7].color = rgb_to_rgb565(255, 255, 255); // Clear
|
||||
}
|
||||
void set_color(uint c) {
|
||||
color = c & 0xf;
|
||||
}
|
||||
void set_color(uint8_t r, uint8_t g, uint8_t b) override {
|
||||
// TODO look up closest palette colour, or just NOOP?
|
||||
}
|
||||
void update_color(uint8_t i, uint8_t r, uint8_t g, uint8_t b) {}
|
||||
void reset_color(uint8_t i) {}
|
||||
int create(uint8_t r, uint8_t g, uint8_t b) override {
|
||||
return -1; // Can never create new colours, fixed palette!
|
||||
}
|
||||
void set_pixel(void *frame_buffer, uint x, uint y, uint stride) override {
|
||||
// pointer to byte in framebuffer that contains this pixel
|
||||
uint8_t *buf = (uint8_t *)frame_buffer;
|
||||
uint8_t *p = &buf[(x / 2) + (y * stride / 2)];
|
||||
|
||||
uint8_t o = (~x & 0b1) * 4; // bit offset within byte
|
||||
uint8_t m = ~(0b1111 << o); // bit mask for byte
|
||||
uint8_t b = color << o; // bit value shifted to position
|
||||
|
||||
*p &= m; // clear bits
|
||||
*p |= b; // set value
|
||||
}
|
||||
void palette_lookup(void *frame_buffer, void *result, uint offset, uint length) override {
|
||||
uint8_t *src = (uint8_t *)frame_buffer;
|
||||
uint16_t *dst = (uint16_t *)result;
|
||||
for(auto x = 0u; x < length; x++) {
|
||||
uint8_t c = src[(offset / 2) + (x / 2)];
|
||||
uint8_t o = (~x & 0b1) * 4; // bit offset within byte
|
||||
uint8_t b = (c >> o) & 0xf; // bit value shifted to position
|
||||
dst[x] = palette[b].color;
|
||||
}
|
||||
}
|
||||
static size_t buffer_size(uint w, uint h) {
|
||||
return w * h / 2;
|
||||
}
|
||||
};
|
||||
|
||||
class PenP8 : public PicoGraphicsPenType {
|
||||
public:
|
||||
uint8_t color;
|
||||
PaletteEntry palette[256];
|
||||
PenP8() {
|
||||
for(auto i = 0u; i < 256; i++) {
|
||||
reset_color(i);
|
||||
}
|
||||
}
|
||||
void set_color(uint c) override {
|
||||
color = c;
|
||||
}
|
||||
void set_color(uint8_t r, uint8_t g, uint8_t b) override {
|
||||
// TODO look up closest palette colour, or just NOOP?
|
||||
}
|
||||
void update_color(uint8_t i, uint8_t r, uint8_t g, uint8_t b) {
|
||||
palette[i].color = rgb_to_rgb565(r, g, b);
|
||||
palette[i].used = true;
|
||||
}
|
||||
void reset_color(uint8_t i) {
|
||||
palette[i].color = 0;
|
||||
palette[i].used = false;
|
||||
}
|
||||
int create(uint8_t r, uint8_t g, uint8_t b) override {
|
||||
// Create a colour and place it in the palette if there's space
|
||||
RGB565 c = rgb_to_rgb565(r, g, b);
|
||||
for(auto i = 0u; i < 256u; i++) {
|
||||
if(!palette[i].used) {
|
||||
palette[i].color = c;
|
||||
palette[i].used = true;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
void set_pixel(void *frame_buffer, uint x, uint y, uint stride) override {
|
||||
uint8_t *buf = (uint8_t *)frame_buffer;
|
||||
buf[y * stride + x] = color;
|
||||
}
|
||||
void palette_lookup(void *frame_buffer, void *result, uint offset, uint length) override {
|
||||
uint8_t *src = (uint8_t *)frame_buffer;
|
||||
uint16_t *dst = (uint16_t *)result;
|
||||
for(auto x = 0u; x < length; x++) {
|
||||
dst[x] = palette[src[offset + x]].color;
|
||||
}
|
||||
}
|
||||
static size_t buffer_size(uint w, uint h) {
|
||||
return w * h;
|
||||
}
|
||||
};
|
||||
|
||||
class PenRGB332 : public PicoGraphicsPenType {
|
||||
public:
|
||||
RGB332 color;
|
||||
PaletteEntry palette[256];
|
||||
PenRGB332() {
|
||||
for(auto i = 0u; i < 256; i++) {
|
||||
reset_color(i);
|
||||
}
|
||||
}
|
||||
void set_color(uint c) {
|
||||
color = c;
|
||||
}
|
||||
void set_color(uint8_t r, uint8_t g, uint8_t b) override {
|
||||
color = rgb_to_rgb332(r, g, b);
|
||||
}
|
||||
void update_color(uint8_t i, uint8_t r, uint8_t g, uint8_t b) {
|
||||
palette[i].color = rgb_to_rgb565(r, g, b);
|
||||
palette[i].used = true;
|
||||
}
|
||||
void reset_color(uint8_t i) {
|
||||
palette[i].color = rgb332_to_rgb565(i);
|
||||
palette[i].used = true;
|
||||
}
|
||||
int create(uint8_t r, uint8_t g, uint8_t b) override {
|
||||
return rgb_to_rgb332(r, g, b);
|
||||
}
|
||||
void set_pixel(void *frame_buffer, uint x, uint y, uint stride) override {
|
||||
uint8_t *buf = (uint8_t *)frame_buffer;
|
||||
buf[y * stride + x] = color;
|
||||
}
|
||||
void palette_lookup(void *frame_buffer, void *result, uint offset, uint length) override {
|
||||
uint8_t *src = (uint8_t *)frame_buffer;
|
||||
uint16_t *dst = (uint16_t *)result;
|
||||
for(auto x = 0u; x < length; x++) {
|
||||
dst[x] = palette[src[offset + x]].color;
|
||||
}
|
||||
}
|
||||
static size_t buffer_size(uint w, uint h) {
|
||||
return w * h;
|
||||
}
|
||||
};
|
||||
|
||||
class PenRGB565 : public PicoGraphicsPenType {
|
||||
public:
|
||||
uint16_t color;
|
||||
void set_color(uint c) override {
|
||||
color = c;
|
||||
}
|
||||
void update_color(uint8_t i, uint8_t r, uint8_t g, uint8_t b) {
|
||||
// Palette only. Does nothing.
|
||||
}
|
||||
void reset_color(uint8_t i) {
|
||||
// Palette only. Does nothing.
|
||||
}
|
||||
void set_color(uint8_t r, uint8_t g, uint8_t b) override {
|
||||
color = rgb_to_rgb565(r, g, b);
|
||||
}
|
||||
int create(uint8_t r, uint8_t g, uint8_t b) override {
|
||||
return rgb_to_rgb565(r, g, b);
|
||||
}
|
||||
void set_pixel(void *frame_buffer, uint x, uint y, uint stride) override {
|
||||
uint16_t *buf = (uint16_t *)frame_buffer;
|
||||
buf[y * stride + x] = color;
|
||||
}
|
||||
void palette_lookup(void *frame_buffer, void *result, uint offset, uint length) override {
|
||||
}
|
||||
static size_t buffer_size(uint w, uint h) {
|
||||
return w * h * sizeof(RGB565);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T=PicoGraphicsPenType>
|
||||
class PicoGraphics {
|
||||
public:
|
||||
void *frame_buffer;
|
||||
|
||||
Rect bounds;
|
||||
Rect clip;
|
||||
|
||||
const bitmap::font_t *font;
|
||||
|
||||
T pen;
|
||||
|
||||
public:
|
||||
PicoGraphics(uint16_t width, uint16_t height, void *frame_buffer)
|
||||
: frame_buffer(frame_buffer), bounds(0, 0, width, height), clip(0, 0, width, height) {
|
||||
set_font(&font6);
|
||||
if(frame_buffer == nullptr) {
|
||||
frame_buffer = (void *)(new uint8_t[pen.buffer_size(width, height)]);
|
||||
}
|
||||
};
|
||||
|
||||
void set_font(const bitmap::font_t *font);
|
||||
void set_pen(uint16_t p);
|
||||
|
||||
int create_pen(uint8_t r, uint8_t g, uint8_t b) {
|
||||
return pen.create(r, g, b);
|
||||
}
|
||||
|
||||
void set_pen(uint8_t r, uint8_t g, uint8_t b) {
|
||||
pen.set_color(r, g, b);
|
||||
}
|
||||
|
||||
void update_pen(uint8_t i, uint8_t r, uint8_t g, uint8_t b) {
|
||||
pen.update_color(i, r, g, b);
|
||||
}
|
||||
|
||||
void reset_pen(uint8_t i) {
|
||||
pen.reset_color(i);
|
||||
}
|
||||
|
||||
void set_dimensions(int width, int height) {
|
||||
|
@ -106,23 +302,16 @@ namespace pimoroni {
|
|||
clip.h = height;
|
||||
}
|
||||
|
||||
int create_pen(uint8_t r, uint8_t g, uint8_t b);
|
||||
|
||||
int reserve_palette();
|
||||
void empty_palette();
|
||||
void rgb332_palette();
|
||||
|
||||
int search_palette(RGB565 c);
|
||||
int get_palette(uint8_t i);
|
||||
void set_palette(uint8_t i, RGB565 c);
|
||||
int put_palette(RGB565 c);
|
||||
|
||||
void set_clip(const Rect &r);
|
||||
void remove_clip();
|
||||
|
||||
Pen* ptr(const Point &p);
|
||||
Pen* ptr(const Rect &r);
|
||||
Pen* ptr(int32_t x, int32_t y);
|
||||
void* get_data() {
|
||||
return frame_buffer;
|
||||
}
|
||||
|
||||
void get_data(uint y, void *row_buf) {
|
||||
pen.palette_lookup(frame_buffer, row_buf, y * bounds.w, bounds.w);
|
||||
}
|
||||
|
||||
void clear();
|
||||
void pixel(const Point &p);
|
||||
|
@ -137,4 +326,9 @@ namespace pimoroni {
|
|||
void line(Point p1, Point p2);
|
||||
};
|
||||
|
||||
template class PicoGraphics<PenP4>;
|
||||
template class PicoGraphics<PenP8>;
|
||||
template class PicoGraphics<PenRGB332>;
|
||||
template class PicoGraphics<PenRGB565>;
|
||||
|
||||
}
|
||||
|
|
|
@ -5,11 +5,5 @@
|
|||
|
||||
|
||||
namespace pimoroni {
|
||||
void PicoGraphicsST7789::update() {
|
||||
st7789.update(palette);
|
||||
}
|
||||
|
||||
void PicoGraphicsST7789::set_backlight(uint8_t brightness) {
|
||||
st7789.set_backlight(brightness);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,42 +6,46 @@
|
|||
|
||||
namespace pimoroni {
|
||||
|
||||
class PicoGraphicsST7789 : public PicoGraphics {
|
||||
template <class T=PicoGraphicsPenType>
|
||||
class PicoGraphicsST7789 : public PicoGraphics<T> {
|
||||
private:
|
||||
ST7789 st7789;
|
||||
|
||||
public:
|
||||
PicoGraphicsST7789(uint16_t width, uint16_t height, Rotation rotation, bool round=false, void *frame_buffer=nullptr) :
|
||||
PicoGraphics(width, height, frame_buffer),
|
||||
PicoGraphics<T>(width, height, frame_buffer),
|
||||
st7789(width, height, rotation, round, frame_buffer, get_spi_pins(BG_SPI_FRONT)) {
|
||||
common_init();
|
||||
};
|
||||
|
||||
PicoGraphicsST7789(uint16_t width, uint16_t height, Rotation rotation, bool round, void *frame_buffer, SPIPins bus_pins) :
|
||||
PicoGraphics(width, height, frame_buffer),
|
||||
PicoGraphics<T>(width, height, frame_buffer),
|
||||
st7789(width, height, rotation, round, frame_buffer, bus_pins) {
|
||||
common_init();
|
||||
};
|
||||
|
||||
PicoGraphicsST7789(uint16_t width, uint16_t height, Rotation rotation, void *frame_buffer, ParallelPins bus_pins) :
|
||||
PicoGraphics(width, height, frame_buffer),
|
||||
PicoGraphics<T>(width, height, frame_buffer),
|
||||
st7789(width, height, rotation, frame_buffer, bus_pins) {
|
||||
common_init();
|
||||
};
|
||||
|
||||
void common_init() {
|
||||
this->frame_buffer = (Pen *)st7789.frame_buffer;
|
||||
this->st7789.init();
|
||||
this->set_dimensions(this->st7789.width, this->st7789.height);
|
||||
this->st7789.update(palette);
|
||||
st7789.init();
|
||||
this->set_dimensions(st7789.width, st7789.height);
|
||||
st7789.update(this);
|
||||
}
|
||||
|
||||
void update() {
|
||||
st7789.update(this);
|
||||
}
|
||||
|
||||
void set_backlight(uint8_t brightness) {
|
||||
st7789.set_backlight(brightness);
|
||||
}
|
||||
|
||||
void update();
|
||||
void set_backlight(uint8_t brightness);
|
||||
void configure_display(bool rotate180);
|
||||
void set_framebuffer(void* frame_buffer) {
|
||||
this->frame_buffer = (Pen *)frame_buffer;
|
||||
st7789.frame_buffer = frame_buffer;
|
||||
this->frame_buffer = frame_buffer;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -10,9 +10,8 @@ MP_DEFINE_CONST_FUN_OBJ_2(GenericST7789_set_backlight_obj, GenericST7789_set_bac
|
|||
MP_DEFINE_CONST_FUN_OBJ_2(GenericST7789_set_framebuffer_obj, GenericST7789_set_framebuffer);
|
||||
|
||||
// Palette management
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(GenericST7789_set_palette_mode_obj, GenericST7789_set_palette_mode);
|
||||
MP_DEFINE_CONST_FUN_OBJ_3(GenericST7789_set_palette_obj, GenericST7789_set_palette);
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(GenericST7789_reserve_palette_obj, GenericST7789_reserve_palette);
|
||||
MP_DEFINE_CONST_FUN_OBJ_KW(GenericST7789_update_pen_obj, 4, GenericST7789_update_pen);
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(GenericST7789_reset_pen_obj, GenericST7789_reset_pen);
|
||||
|
||||
// Pen
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(GenericST7789_set_pen_obj, GenericST7789_set_pen);
|
||||
|
@ -41,9 +40,8 @@ STATIC const mp_rom_map_elem_t GenericST7789_locals_dict_table[] = {
|
|||
{ MP_ROM_QSTR(MP_QSTR_set_pen), MP_ROM_PTR(&GenericST7789_set_pen_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&GenericST7789_update_obj) },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_set_palette_mode), MP_ROM_PTR(&GenericST7789_set_palette_mode_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_set_palette), MP_ROM_PTR(&GenericST7789_set_palette_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_reserve_palette), MP_ROM_PTR(&GenericST7789_reserve_palette_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_update_pen), MP_ROM_PTR(&GenericST7789_update_pen_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_reset_pen), MP_ROM_PTR(&GenericST7789_reset_pen_obj) },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_set_backlight), MP_ROM_PTR(&GenericST7789_set_backlight_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_create_pen), MP_ROM_PTR(&GenericST7789_create_pen_obj) },
|
||||
|
|
|
@ -4,7 +4,9 @@
|
|||
|
||||
#include "micropython/modules/util.hpp"
|
||||
|
||||
|
||||
#ifndef PICO_GRAPHICS_PEN_TYPE
|
||||
#define PICO_GRAPHICS_PEN_TYPE PenP4
|
||||
#endif
|
||||
|
||||
using namespace pimoroni;
|
||||
|
||||
|
@ -14,7 +16,7 @@ extern "C" {
|
|||
|
||||
typedef struct _GenericST7789_obj_t {
|
||||
mp_obj_base_t base;
|
||||
PicoGraphicsST7789 *st7789;
|
||||
PicoGraphicsST7789<PICO_GRAPHICS_PEN_TYPE> *st7789;
|
||||
void *buffer;
|
||||
} GenericST7789_obj_t;
|
||||
|
||||
|
@ -66,32 +68,34 @@ mp_obj_t GenericST7789_make_new(const mp_obj_type_t *type, size_t n_args, size_t
|
|||
break;
|
||||
}
|
||||
|
||||
size_t required_size = PICO_GRAPHICS_PEN_TYPE::buffer_size(width, height);
|
||||
|
||||
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 = bufinfo.buf;
|
||||
if(bufinfo.len < (size_t)(width * height * sizeof(Pen))) {
|
||||
if(bufinfo.len < (size_t)(required_size)) {
|
||||
mp_raise_ValueError("Supplied buffer is too small!");
|
||||
}
|
||||
} else {
|
||||
self->buffer = m_new(uint8_t, width * height * sizeof(Pen));
|
||||
self->buffer = m_new(uint8_t, required_size);
|
||||
}
|
||||
|
||||
if (display == DISPLAY_TUFTY_2040) {
|
||||
if (args[ARG_bus].u_obj == mp_const_none) {
|
||||
self->st7789 = m_new_class(PicoGraphicsST7789, width, height, rotate, self->buffer, {10, 11, 12, 13, 14, 2});
|
||||
self->st7789 = m_new_class(PicoGraphicsST7789<PICO_GRAPHICS_PEN_TYPE>, width, height, rotate, self->buffer, {10, 11, 12, 13, 14, 2});
|
||||
} else if (mp_obj_is_type(args[ARG_bus].u_obj, &ParallelPins_type)) {
|
||||
_PimoroniBus_obj_t *bus = (_PimoroniBus_obj_t *)MP_OBJ_TO_PTR(args[ARG_bus].u_obj);
|
||||
self->st7789 = m_new_class(PicoGraphicsST7789, width, height, rotate, self->buffer, *(ParallelPins *)(bus->pins));
|
||||
self->st7789 = m_new_class(PicoGraphicsST7789<PICO_GRAPHICS_PEN_TYPE>, width, height, rotate, self->buffer, *(ParallelPins *)(bus->pins));
|
||||
} else {
|
||||
mp_raise_ValueError("ParallelBus expected!");
|
||||
}
|
||||
} else {
|
||||
if (args[ARG_bus].u_obj == mp_const_none) {
|
||||
self->st7789 = m_new_class(PicoGraphicsST7789, width, height, rotate, round, self->buffer, get_spi_pins(BG_SPI_FRONT));
|
||||
self->st7789 = m_new_class(PicoGraphicsST7789<PICO_GRAPHICS_PEN_TYPE>, width, height, rotate, round, self->buffer, get_spi_pins(BG_SPI_FRONT));
|
||||
} else if (mp_obj_is_type(args[ARG_bus].u_obj, &SPIPins_type)) {
|
||||
_PimoroniBus_obj_t *bus = (_PimoroniBus_obj_t *)MP_OBJ_TO_PTR(args[ARG_bus].u_obj);
|
||||
self->st7789 = m_new_class(PicoGraphicsST7789, width, height, rotate, round, self->buffer, *(SPIPins *)(bus->pins));
|
||||
self->st7789 = m_new_class(PicoGraphicsST7789<PICO_GRAPHICS_PEN_TYPE>, width, height, rotate, round, self->buffer, *(SPIPins *)(bus->pins));
|
||||
} else {
|
||||
mp_raise_ValueError("SPIBus expected!");
|
||||
}
|
||||
|
@ -146,7 +150,7 @@ mp_obj_t GenericST7789_set_backlight(mp_obj_t self_in, mp_obj_t brightness) {
|
|||
}
|
||||
|
||||
mp_obj_t GenericST7789_module_RGB332(mp_obj_t r, mp_obj_t g, mp_obj_t b) {
|
||||
return mp_obj_new_int(PicoGraphicsST7789::create_pen_rgb332(
|
||||
return mp_obj_new_int(PicoGraphicsPenType::rgb_to_rgb332(
|
||||
mp_obj_get_int(r),
|
||||
mp_obj_get_int(g),
|
||||
mp_obj_get_int(b)
|
||||
|
@ -154,7 +158,7 @@ mp_obj_t GenericST7789_module_RGB332(mp_obj_t r, mp_obj_t g, mp_obj_t b) {
|
|||
}
|
||||
|
||||
mp_obj_t GenericST7789_module_RGB565(mp_obj_t r, mp_obj_t g, mp_obj_t b) {
|
||||
return mp_obj_new_int(PicoGraphicsST7789::create_pen_rgb565(
|
||||
return mp_obj_new_int(PicoGraphicsPenType::rgb_to_rgb565(
|
||||
mp_obj_get_int(r),
|
||||
mp_obj_get_int(g),
|
||||
mp_obj_get_int(b)
|
||||
|
@ -164,40 +168,44 @@ mp_obj_t GenericST7789_module_RGB565(mp_obj_t r, mp_obj_t g, mp_obj_t b) {
|
|||
mp_obj_t GenericST7789_set_pen(mp_obj_t self_in, mp_obj_t pen) {
|
||||
GenericST7789_obj_t *self = MP_OBJ_TO_PTR2(self_in, GenericST7789_obj_t);
|
||||
|
||||
self->st7789->set_pen(mp_obj_get_int(pen) & 0xff);
|
||||
self->st7789->set_pen(mp_obj_get_int(pen));
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t GenericST7789_set_palette_mode(mp_obj_t self_in, mp_obj_t mode) {
|
||||
mp_obj_t GenericST7789_reset_pen(mp_obj_t self_in, mp_obj_t pen) {
|
||||
GenericST7789_obj_t *self = MP_OBJ_TO_PTR2(self_in, GenericST7789_obj_t);
|
||||
|
||||
self->st7789->set_palette_mode((PicoGraphicsST7789::PaletteMode)mp_obj_get_int(mode));
|
||||
self->st7789->reset_pen(mp_obj_get_int(pen));
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t GenericST7789_set_palette(mp_obj_t self_in, mp_obj_t index, mp_obj_t colour) {
|
||||
GenericST7789_obj_t *self = MP_OBJ_TO_PTR2(self_in, GenericST7789_obj_t);
|
||||
mp_obj_t GenericST7789_update_pen(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum { ARG_self, ARG_i, ARG_r, ARG_g, ARG_b };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ },
|
||||
{ MP_QSTR_i, MP_ARG_REQUIRED | MP_ARG_INT },
|
||||
{ MP_QSTR_r, MP_ARG_REQUIRED | MP_ARG_INT },
|
||||
{ MP_QSTR_g, MP_ARG_REQUIRED | MP_ARG_INT },
|
||||
{ MP_QSTR_b, MP_ARG_REQUIRED | MP_ARG_INT }
|
||||
};
|
||||
|
||||
self->st7789->set_palette(
|
||||
mp_obj_get_int(index) & 0xff,
|
||||
mp_obj_get_int(colour) & 0xffff
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
GenericST7789_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self].u_obj, GenericST7789_obj_t);
|
||||
|
||||
self->st7789->update_pen(
|
||||
args[ARG_i].u_int & 0xff,
|
||||
args[ARG_r].u_int & 0xff,
|
||||
args[ARG_g].u_int & 0xff,
|
||||
args[ARG_b].u_int & 0xff
|
||||
);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t GenericST7789_reserve_palette(mp_obj_t self_in) {
|
||||
GenericST7789_obj_t *self = MP_OBJ_TO_PTR2(self_in, GenericST7789_obj_t);
|
||||
|
||||
int result = self->st7789->reserve_palette();
|
||||
|
||||
if (result == -1) mp_raise_ValueError("reserve_palette failed. No space in palette!");
|
||||
|
||||
return mp_obj_new_int(result);
|
||||
}
|
||||
|
||||
mp_obj_t GenericST7789_create_pen(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum { ARG_self, ARG_r, ARG_g, ARG_b };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
|
|
|
@ -27,9 +27,8 @@ extern mp_obj_t GenericST7789_update(mp_obj_t self_in);
|
|||
extern mp_obj_t GenericST7789_set_backlight(mp_obj_t self_in, mp_obj_t brightness);
|
||||
|
||||
// Palette management
|
||||
extern mp_obj_t GenericST7789_set_palette_mode(mp_obj_t self_in, mp_obj_t mode);
|
||||
extern mp_obj_t GenericST7789_set_palette(mp_obj_t self_in, mp_obj_t index, mp_obj_t colour);
|
||||
extern mp_obj_t GenericST7789_reserve_palette(mp_obj_t self_in);
|
||||
extern mp_obj_t GenericST7789_update_pen(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
|
||||
extern mp_obj_t GenericST7789_reset_pen(mp_obj_t self_in, mp_obj_t pen);
|
||||
|
||||
// Pen
|
||||
extern mp_obj_t GenericST7789_set_pen(mp_obj_t self_in, mp_obj_t pen);
|
||||
|
|
Loading…
Reference in New Issue