kopia lustrzana https://github.com/pimoroni/pimoroni-pico
Limited support for palette and RGB888 modes
rodzic
a7435c6a5e
commit
daf7232024
|
@ -9,7 +9,7 @@
|
|||
namespace pimoroni {
|
||||
|
||||
void DVDisplay::init() {
|
||||
uint8_t mode = 0xFF;
|
||||
uint8_t res_mode = 0xFF;
|
||||
uint16_t full_width = width;
|
||||
uint16_t full_height = height;
|
||||
|
||||
|
@ -23,26 +23,26 @@ namespace pimoroni {
|
|||
}
|
||||
|
||||
if (full_width == 640) {
|
||||
mode = 0;
|
||||
res_mode = 0;
|
||||
}
|
||||
else if (full_width == 720) {
|
||||
if (full_height == 480) mode = 1;
|
||||
else if (full_height == 400) mode = 2;
|
||||
else if (full_height == 576) mode = 3;
|
||||
if (full_height == 480) res_mode = 1;
|
||||
else if (full_height == 400) res_mode = 2;
|
||||
else if (full_height == 576) res_mode = 3;
|
||||
}
|
||||
else if (full_width == 800) {
|
||||
if (full_height == 600) mode = 0x10;
|
||||
else if (full_height == 480) mode = 0x11;
|
||||
else if (full_height == 450) mode = 0x12;
|
||||
if (full_height == 600) res_mode = 0x10;
|
||||
else if (full_height == 480) res_mode = 0x11;
|
||||
else if (full_height == 450) res_mode = 0x12;
|
||||
}
|
||||
else if (full_width == 960) {
|
||||
if (full_height == 540) mode = 0x14;
|
||||
if (full_height == 540) res_mode = 0x14;
|
||||
}
|
||||
else if (full_width == 1280) {
|
||||
if (full_height == 720) mode = 0x15;
|
||||
if (full_height == 720) res_mode = 0x15;
|
||||
}
|
||||
|
||||
if (mode == 0xFF) {
|
||||
if (res_mode == 0xFF) {
|
||||
printf("Resolution %dx%d is not supported. Will use 720x480.\n", width, height);
|
||||
}
|
||||
|
||||
|
@ -73,8 +73,8 @@ namespace pimoroni {
|
|||
|
||||
printf("Start I2C\n");
|
||||
|
||||
if (mode != 0xFF) {
|
||||
i2c.reg_write_uint8(I2C_ADDR, I2C_REG_SET_RES, mode);
|
||||
if (res_mode != 0xFF) {
|
||||
i2c.reg_write_uint8(I2C_ADDR, I2C_REG_SET_RES, res_mode);
|
||||
}
|
||||
|
||||
i2c.reg_write_uint8(I2C_ADDR, I2C_REG_START, 1);
|
||||
|
@ -82,7 +82,7 @@ namespace pimoroni {
|
|||
}
|
||||
|
||||
void DVDisplay::flip() {
|
||||
if (use_palette_mode) {
|
||||
if (mode == MODE_PALETTE) {
|
||||
write_palette();
|
||||
if (pixel_buffer_location.y != -1) {
|
||||
ram.write(point_to_address_palette(pixel_buffer_location), pixel_buffer, pixel_buffer_x);
|
||||
|
@ -169,6 +169,26 @@ namespace pimoroni {
|
|||
ram.write_repeat(address, val, len << 1);
|
||||
}
|
||||
|
||||
void DVDisplay::write(uint32_t address, size_t len, const RGB888 colour)
|
||||
{
|
||||
const int VAL_BUFFER_LEN = 60;
|
||||
const int VAL_BUFFER_LEN_IN_PIXELS = (VAL_BUFFER_LEN / 3) * 4;
|
||||
uint32_t vals[VAL_BUFFER_LEN];
|
||||
|
||||
for (int i = 0, j = 0; i < VAL_BUFFER_LEN_IN_PIXELS && i < (int)len; i += 4) {
|
||||
vals[j++] = colour | (colour << 24);
|
||||
vals[j++] = (colour >> 8) | (colour << 16);
|
||||
vals[j++] = (colour >> 16) | (colour << 8);
|
||||
}
|
||||
|
||||
for (int len_bytes = len * 3; len_bytes > 0; len_bytes -= VAL_BUFFER_LEN_IN_PIXELS * 3) {
|
||||
uint len_to_write = std::min(len_bytes, VAL_BUFFER_LEN_IN_PIXELS * 3);
|
||||
ram.write(address, vals, len_to_write);
|
||||
address += len_to_write;
|
||||
}
|
||||
ram.wait_for_finish_blocking();
|
||||
}
|
||||
|
||||
void DVDisplay::read(uint32_t address, size_t len, uint16_t *data)
|
||||
{
|
||||
ram.read_blocking(address, (uint32_t*)data, (len + 1) >> 1);
|
||||
|
@ -211,6 +231,16 @@ namespace pimoroni {
|
|||
write(point_to_address(p), l, colour);
|
||||
}
|
||||
|
||||
void DVDisplay::write_pixel(const Point &p, RGB888 colour)
|
||||
{
|
||||
ram.write(point_to_address24(p), &colour, 3);
|
||||
}
|
||||
|
||||
void DVDisplay::write_pixel_span(const Point &p, uint l, RGB888 colour)
|
||||
{
|
||||
write(point_to_address24(p), l, colour);
|
||||
}
|
||||
|
||||
void DVDisplay::write_pixel_span(const Point &p, uint l, uint16_t *data)
|
||||
{
|
||||
uint32_t offset = 0;
|
||||
|
@ -230,12 +260,14 @@ namespace pimoroni {
|
|||
read(point_to_address(p), l, data);
|
||||
}
|
||||
|
||||
void DVDisplay::enable_palette(bool enable)
|
||||
void DVDisplay::set_mode(Mode new_mode)
|
||||
{
|
||||
use_palette_mode = enable;
|
||||
mode = new_mode;
|
||||
rewrite_header = true;
|
||||
write_header();
|
||||
write_palette();
|
||||
if (mode == MODE_PALETTE) {
|
||||
write_palette();
|
||||
}
|
||||
}
|
||||
|
||||
void DVDisplay::set_palette(RGB888 new_palette[PALETTE_SIZE])
|
||||
|
@ -316,11 +348,11 @@ namespace pimoroni {
|
|||
ram.wait_for_finish_blocking();
|
||||
|
||||
uint addr = 4 * 7;
|
||||
uint line_type = 0x90000000u;
|
||||
if (use_palette_mode) line_type = 0xa0000000u;
|
||||
uint line_type = 0x80000000u + ((uint)mode << 28);
|
||||
printf("Write header, line type %08x\n", line_type);
|
||||
for (int i = 0; i < height; i += 8) {
|
||||
for (int j = 0; j < 8; ++j) {
|
||||
buf[j] = line_type + ((uint32_t)h_repeat << 24) + ((i + j) * width * 2) + base_address;
|
||||
buf[j] = line_type + ((uint32_t)h_repeat << 24) + ((i + j) * width * 6) + base_address;
|
||||
}
|
||||
ram.write(addr, buf, 8 * 4);
|
||||
ram.wait_for_finish_blocking();
|
||||
|
|
|
@ -15,7 +15,16 @@
|
|||
namespace pimoroni {
|
||||
|
||||
// This is ARGB1555 only for now
|
||||
class DVDisplay : public IDirectDisplayDriver<uint16_t>, public IPaletteDisplayDriver {
|
||||
class DVDisplay : public IDirectDisplayDriver<uint16_t>, public IDirectDisplayDriver<RGB888>, public IPaletteDisplayDriver {
|
||||
public:
|
||||
static constexpr int PALETTE_SIZE = 32;
|
||||
|
||||
enum Mode {
|
||||
MODE_RGB555 = 1,
|
||||
MODE_PALETTE = 2,
|
||||
MODE_RGB888 = 3,
|
||||
};
|
||||
|
||||
//--------------------------------------------------
|
||||
// Variables
|
||||
//--------------------------------------------------
|
||||
|
@ -53,19 +62,19 @@ namespace pimoroni {
|
|||
uint8_t bank = 0;
|
||||
uint8_t h_repeat = 1;
|
||||
uint8_t v_repeat = 1;
|
||||
Mode mode = MODE_RGB555;
|
||||
|
||||
public:
|
||||
static constexpr int PALETTE_SIZE = 32;
|
||||
|
||||
// Valid resolutions are:
|
||||
// 640x480 (60Hz), 720x480 (60Hz), 720x400 (70Hz), 720x576 (50Hz)
|
||||
// 800x600 (60Hz), 800x480 (60Hz), 800x450 (60Hz), 960x540 (50Hz), 1280x720 (30Hz)
|
||||
// Note resolutions on the second line require quite extreme overclocking and may not work on all hardware.
|
||||
// Either or both of the horizontal or vertical component of any resolution may be halved.
|
||||
DVDisplay(uint16_t width, uint16_t height)
|
||||
DVDisplay(uint16_t width, uint16_t height, Mode mode = MODE_RGB555)
|
||||
: ram(CS, D0)
|
||||
, i2c(I2C_SDA, I2C_SCL)
|
||||
, width(width), height(height)
|
||||
, mode(mode)
|
||||
, pixel_buffer_location(-1, -1)
|
||||
{}
|
||||
|
||||
|
@ -102,18 +111,23 @@ namespace pimoroni {
|
|||
}
|
||||
}
|
||||
|
||||
// 16bpp interface
|
||||
void write_pixel(const Point &p, uint16_t colour) override;
|
||||
void write_pixel_span(const Point &p, uint l, uint16_t colour) override;
|
||||
void write_pixel_span(const Point &p, uint l, uint16_t *data);
|
||||
void read_pixel_span(const Point &p, uint l, uint16_t *data) override;
|
||||
|
||||
// 24bpp interface
|
||||
void write_pixel(const Point &p, RGB888 colour) override;
|
||||
void write_pixel_span(const Point &p, uint l, RGB888 colour) override;
|
||||
|
||||
void init();
|
||||
void flip();
|
||||
|
||||
// 32 colour palette mode. Note that palette entries range from 0-31,
|
||||
// but when writing colour values the palette entry is in bits 6-2, so the
|
||||
// entry value is effectively multiplied by 4.
|
||||
void enable_palette(bool enable);
|
||||
void set_mode(Mode new_mode);
|
||||
void set_palette(RGB888 palette[PALETTE_SIZE]);
|
||||
void set_palette_colour(uint8_t entry, RGB888 colour);
|
||||
|
||||
|
@ -146,7 +160,6 @@ namespace pimoroni {
|
|||
|
||||
private:
|
||||
uint8_t palette[PALETTE_SIZE * 3] alignas(4);
|
||||
bool use_palette_mode = false;
|
||||
bool rewrite_header = false;
|
||||
|
||||
static constexpr int PIXEL_BUFFER_LEN_IN_WORDS = 16;
|
||||
|
@ -158,6 +171,7 @@ namespace pimoroni {
|
|||
void read(uint32_t address, size_t len, uint16_t *data);
|
||||
void write(uint32_t address, size_t len, const uint8_t colour);
|
||||
void read(uint32_t address, size_t len, uint8_t *data);
|
||||
void write(uint32_t address, size_t len, const RGB888 colour);
|
||||
|
||||
void write_palette();
|
||||
void write_header();
|
||||
|
@ -165,11 +179,15 @@ namespace pimoroni {
|
|||
void i2c_modify_bit(uint8_t reg, uint bit, bool enable);
|
||||
|
||||
uint32_t point_to_address(const Point &p) {
|
||||
return base_address + ((p.y * (uint32_t)width) + p.x) * 2;
|
||||
return base_address + ((p.y * (uint32_t)width * 3) + p.x) * 2;
|
||||
}
|
||||
|
||||
uint32_t point_to_address_palette(const Point &p) {
|
||||
return base_address + (p.y * (uint32_t)width * 2) + p.x;
|
||||
return base_address + (p.y * (uint32_t)width * 6) + p.x;
|
||||
}
|
||||
|
||||
uint32_t point_to_address24(const Point &p) {
|
||||
return base_address + ((p.y * (uint32_t)width * 2) + p.x) * 3;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
Plik diff jest za duży
Load Diff
Plik diff jest za duży
Load Diff
|
@ -9,14 +9,16 @@
|
|||
|
||||
using namespace pimoroni;
|
||||
|
||||
#define FRAME_WIDTH 720
|
||||
#define FRAME_HEIGHT 480
|
||||
#define FRAME_WIDTH 360
|
||||
#define FRAME_HEIGHT 240
|
||||
|
||||
#define READ_EDID 1
|
||||
#define READ_EDID 0
|
||||
#if READ_EDID
|
||||
extern "C" { int decode_edid(unsigned char* edid); }
|
||||
#endif
|
||||
|
||||
#define USE_PALETTE 0
|
||||
|
||||
void on_uart_rx() {
|
||||
while (uart_is_readable(uart1)) {
|
||||
uint8_t ch = uart_getc(uart1);
|
||||
|
@ -44,9 +46,9 @@ int main() {
|
|||
gpio_set_dir(BUTTON_A, GPIO_IN);
|
||||
gpio_pull_up(BUTTON_A);
|
||||
|
||||
//sleep_ms(5000);
|
||||
sleep_ms(5000);
|
||||
|
||||
DVDisplay display(FRAME_WIDTH, FRAME_HEIGHT);
|
||||
DVDisplay display(FRAME_WIDTH, FRAME_HEIGHT, DVDisplay::MODE_RGB888);
|
||||
display.init();
|
||||
//display.test();
|
||||
|
||||
|
@ -61,19 +63,29 @@ int main() {
|
|||
}
|
||||
#endif
|
||||
|
||||
display.enable_palette(true);
|
||||
#if USE_PALETTE
|
||||
display.set_mode(DVDisplay::MODE_PALETTE)
|
||||
PicoGraphics_PenDV_P5 graphics(FRAME_WIDTH, FRAME_HEIGHT, display);
|
||||
#else
|
||||
//display.set_mode(DVDisplay::MODE_RGB888);
|
||||
PicoGraphics_PenDV_RGB888 graphics(FRAME_WIDTH, FRAME_HEIGHT, display);
|
||||
#endif
|
||||
|
||||
graphics.create_pen(0, 0, 0);
|
||||
graphics.create_pen(0xFF, 0xFF, 0xFF);
|
||||
|
||||
#if USE_PALETTE
|
||||
for (int i = 0; i < 25; ++i) {
|
||||
graphics.create_pen_hsv(i * 0.04f, 1.0f, 1.0f);
|
||||
}
|
||||
#endif
|
||||
|
||||
graphics.set_pen(0xFF, 0, 0);
|
||||
printf(".\n");
|
||||
graphics.clear();
|
||||
printf("..\n");
|
||||
display.flip();
|
||||
printf("...\n");
|
||||
sleep_ms(2000);
|
||||
graphics.set_pen(0, 0, 0xFF);
|
||||
graphics.clear();
|
||||
|
@ -84,7 +96,8 @@ int main() {
|
|||
|
||||
constexpr int NUM_CIRCLES = 50;
|
||||
struct Circle {
|
||||
uint16_t x, y, size, grow, pen;
|
||||
uint16_t x, y, size, grow;
|
||||
uint32_t pen;
|
||||
} circles[NUM_CIRCLES];
|
||||
|
||||
for(int i =0 ; i < 50 ; i++)
|
||||
|
@ -93,7 +106,11 @@ int main() {
|
|||
circles[i].grow = std::max(0, (rand() % 50) - 25);
|
||||
circles[i].x = rand() % graphics.bounds.w;
|
||||
circles[i].y = rand() % graphics.bounds.h;
|
||||
#if USE_PALETTE
|
||||
circles[i].pen = 2 + (i >> 1);
|
||||
#else
|
||||
circles[i].pen = graphics.create_pen_hsv(i * 0.02f, 1.0f, 1.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
int frames = 0;
|
||||
|
|
|
@ -19,6 +19,7 @@ add_library(pico_graphics
|
|||
${CMAKE_CURRENT_LIST_DIR}/pico_graphics_pen_rgb888.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/pico_graphics_pen_inky7.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/pico_graphics_pen_dv_rgb555.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/pico_graphics_pen_dv_rgb888.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/pico_graphics_pen_dv_p5.cpp
|
||||
)
|
||||
|
||||
|
|
|
@ -203,7 +203,8 @@ namespace pimoroni {
|
|||
PEN_RGB888,
|
||||
PEN_INKY7,
|
||||
PEN_DV_RGB555,
|
||||
PEN_DV_P5
|
||||
PEN_DV_P5,
|
||||
PEN_DV_RGB888,
|
||||
};
|
||||
|
||||
void *frame_buffer;
|
||||
|
@ -615,6 +616,24 @@ namespace pimoroni {
|
|||
}
|
||||
};
|
||||
|
||||
class PicoGraphics_PenDV_RGB888 : public PicoGraphics {
|
||||
public:
|
||||
RGB888 color;
|
||||
IDirectDisplayDriver<RGB888> &driver;
|
||||
|
||||
PicoGraphics_PenDV_RGB888(uint16_t width, uint16_t height, IDirectDisplayDriver<RGB888> &direct_display_driver);
|
||||
void set_pen(uint c) override;
|
||||
void set_pen(uint8_t r, uint8_t g, uint8_t b) override;
|
||||
int create_pen(uint8_t r, uint8_t g, uint8_t b) override;
|
||||
int create_pen_hsv(float h, float s, float v) override;
|
||||
void set_pixel(const Point &p) override;
|
||||
void set_pixel_span(const Point &p, uint l) override;
|
||||
|
||||
static size_t buffer_size(uint w, uint h) {
|
||||
return w * h * sizeof(RGB888);
|
||||
}
|
||||
};
|
||||
|
||||
class PicoGraphics_PenDV_P5 : public PicoGraphics {
|
||||
public:
|
||||
static const uint16_t palette_size = 32;
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
#include "pico_graphics.hpp"
|
||||
|
||||
namespace pimoroni {
|
||||
PicoGraphics_PenDV_RGB888::PicoGraphics_PenDV_RGB888(uint16_t width, uint16_t height, IDirectDisplayDriver<RGB888> &direct_display_driver)
|
||||
: PicoGraphics(width, height, nullptr),
|
||||
driver(direct_display_driver)
|
||||
{
|
||||
this->pen_type = PEN_DV_RGB888;
|
||||
}
|
||||
void PicoGraphics_PenDV_RGB888::set_pen(uint c) {
|
||||
color = c;
|
||||
}
|
||||
void PicoGraphics_PenDV_RGB888::set_pen(uint8_t r, uint8_t g, uint8_t b) {
|
||||
RGB src_color{r, g, b};
|
||||
color = src_color.to_rgb888();
|
||||
}
|
||||
int PicoGraphics_PenDV_RGB888::create_pen(uint8_t r, uint8_t g, uint8_t b) {
|
||||
return RGB(r, g, b).to_rgb888();
|
||||
}
|
||||
int PicoGraphics_PenDV_RGB888::create_pen_hsv(float h, float s, float v) {
|
||||
return RGB::from_hsv(h, s, v).to_rgb888();
|
||||
}
|
||||
void PicoGraphics_PenDV_RGB888::set_pixel(const Point &p) {
|
||||
driver.write_pixel(p, color);
|
||||
}
|
||||
void PicoGraphics_PenDV_RGB888::set_pixel_span(const Point &p, uint l) {
|
||||
driver.write_pixel_span(p, l, color);
|
||||
}
|
||||
}
|
Ładowanie…
Reference in New Issue