HUB75 Perf, C++ scrolling text, docs

pull/193/head
Phil Howard 2021-12-02 12:41:30 +00:00
rodzic 4dc3f9b9c4
commit 1bb4383074
10 zmienionych plików z 292 dodań i 29 usunięć

Wyświetl plik

@ -36,7 +36,6 @@ Pixel hsv_to_rgb(float h, float s, float v) {
}
}
Hub75::Hub75(uint width, uint height, Pixel *buffer, PanelType panel_type, bool inverted_stb)
: width(width), height(height), panel_type(panel_type), inverted_stb(inverted_stb)
{
@ -77,7 +76,7 @@ Hub75::Hub75(uint width, uint height, Pixel *buffer, PanelType panel_type, bool
}
}
void Hub75::set_color(uint x, uint y, uint32_t c) {
void Hub75::set_color(uint x, uint y, Pixel c) {
int offset = 0;
if(x >= width || y >= height) return;
if(y >= height / 2) {
@ -87,15 +86,15 @@ void Hub75::set_color(uint x, uint y, uint32_t c) {
} else {
offset = (y * width + x) * 2;
}
front_buffer[offset].color = c;
front_buffer[offset] = c;
}
void Hub75::set_rgb(uint x, uint y, uint8_t r, uint8_t g, uint8_t b) {
set_color(x, y, Pixel(r, g, b).color);
set_color(x, y, Pixel(r, g, b));
}
void Hub75::set_hsv(uint x, uint y, float h, float s, float v) {
set_color(x, y, hsv_to_rgb(h, s, v).color);
set_color(x, y, hsv_to_rgb(h, s, v));
}
void Hub75::FM6126A_write_register(uint16_t value, uint8_t position) {
@ -172,7 +171,6 @@ void Hub75::start(irq_handler_t handler) {
channel_config_set_bswap(&flip_config, false);
dma_channel_configure(dma_flip_channel, &flip_config, nullptr, nullptr, 0, false);
// Same handler for both DMA channels
irq_set_exclusive_handler(DMA_IRQ_0, handler);
irq_set_exclusive_handler(DMA_IRQ_1, handler);
@ -255,7 +253,14 @@ void Hub75::clear() {
}
}
void Hub75::flip() {
void Hub75::flip(bool copybuffer) {
dma_channel_config flip_config = dma_get_channel_config(dma_flip_channel);
channel_config_set_read_increment(&flip_config, copybuffer);
dma_channel_configure(dma_flip_channel, &flip_config, nullptr, nullptr, 0, false);
dma_channel_set_read_addr(dma_flip_channel, copybuffer ? front_buffer : &background, false);
dma_channel_set_write_addr(dma_flip_channel, back_buffer, false);
// Flip and block until the front buffer has been prepared
do_flip = true;
while(do_flip) {
@ -291,8 +296,6 @@ void Hub75::dma_complete() {
back_buffer = front_buffer;
front_buffer = tmp;
// Then, read the contents of the back buffer into the front buffer
dma_channel_set_read_addr(dma_flip_channel, back_buffer, false);
dma_channel_set_write_addr(dma_flip_channel, front_buffer, false);
dma_channel_set_trans_count(dma_flip_channel, width * height, true);
}

Wyświetl plik

@ -57,6 +57,7 @@ class Hub75 {
bool managed_buffer = false;
PanelType panel_type;
bool inverted_stb = false;
Pixel background = 0;
// DMA & PIO
uint dma_channel = 0;
@ -116,13 +117,13 @@ class Hub75 {
void FM6126A_write_register(uint16_t value, uint8_t position);
void FM6126A_setup();
void set_color(uint x, uint y, uint32_t c);
void set_color(uint x, uint y, Pixel c);
void set_rgb(uint x, uint y, uint8_t r, uint8_t g, uint8_t b);
void set_hsv(uint x, uint y, float r, float g, float b);
void display_update();
void clear();
void start(irq_handler_t handler);
void stop(irq_handler_t handler);
void flip();
void flip(bool copybuffer=true);
void dma_complete();
};

Wyświetl plik

@ -1,2 +1,3 @@
include(interstate75_hello_world.cmake)
include(interstate75_pio_dma.cmake)
include(interstate75_pio_dma.cmake)
include(interstate75_scrolling_text.cmake)

Wyświetl plik

@ -0,0 +1,100 @@
const uint8_t letter_width = 10;
const uint8_t letter_height = 14;
uint32_t font[][letter_width] = {
{0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, // " "
{0x0ffc, 0x0a04, 0x0ffc, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, // "!"
{0x007c, 0x0044, 0x007c, 0x0044, 0x007c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, // """
{0x03f0, 0x02d0, 0x0edc, 0x0804, 0x0edc, 0x0edc, 0x0804, 0x0edc, 0x02d0, 0x03f0}, // "//"
{0x0ef8, 0x0b8c, 0x1b76, 0x1002, 0x1b76, 0x0cd4, 0x079c, 0x0000, 0x0000, 0x0000}, // "$"
{0x0038, 0x006c, 0x0f54, 0x09ec, 0x0e78, 0x079c, 0x0de4, 0x0abc, 0x0d80, 0x0700}, // "%"
{0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, // "&"
{0x007c, 0x0044, 0x007c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, // "'"
{0x03f0, 0x0e1c, 0x19e6, 0x173a, 0x1c0e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, // "("
{0x1c0e, 0x173a, 0x19e6, 0x0e1c, 0x03f0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, // ")"
{0x00fc, 0x00b4, 0x00cc, 0x00cc, 0x00b4, 0x00fc, 0x0000, 0x0000, 0x0000, 0x0000}, // "*"
{0x01c0, 0x0140, 0x0770, 0x0410, 0x0770, 0x0140, 0x01c0, 0x0000, 0x0000, 0x0000}, // "+"
{0x1c00, 0x1700, 0x1900, 0x0f00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, // ","
{0x01c0, 0x0140, 0x0140, 0x0140, 0x0140, 0x0140, 0x01c0, 0x0000, 0x0000, 0x0000}, // "-"
{0x0e00, 0x0a00, 0x0e00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, // "."
{0x1e00, 0x1380, 0x1ce0, 0x0738, 0x01ce, 0x0072, 0x001e, 0x0000, 0x0000, 0x0000}, // "/"
{0x07f8, 0x0c0c, 0x0bf4, 0x0a14, 0x0bf4, 0x0c0c, 0x07f8, 0x0000, 0x0000, 0x0000}, // "0"
{0x0e70, 0x0a58, 0x0bec, 0x0804, 0x0bfc, 0x0a00, 0x0e00, 0x0000, 0x0000, 0x0000}, // "1"
{0x0e38, 0x0b2c, 0x09b4, 0x0ad4, 0x0b74, 0x0b8c, 0x0ef8, 0x0000, 0x0000, 0x0000}, // "2"
{0x0738, 0x0d2c, 0x0b34, 0x0bf4, 0x0b34, 0x0ccc, 0x07f8, 0x0000, 0x0000, 0x0000}, // "3"
{0x03c0, 0x0270, 0x0298, 0x0eec, 0x0804, 0x0efc, 0x0380, 0x0000, 0x0000, 0x0000}, // "4"
{0x0efc, 0x0a84, 0x0ab4, 0x0ab4, 0x0bb4, 0x0c74, 0x07dc, 0x0000, 0x0000, 0x0000}, // "5"
{0x07f8, 0x0c0c, 0x0bb4, 0x0ab4, 0x0bb4, 0x0c74, 0x07dc, 0x0000, 0x0000, 0x0000}, // "6"
{0x001c, 0x0014, 0x0f94, 0x08f4, 0x0f34, 0x01c4, 0x007c, 0x0000, 0x0000, 0x0000}, // "7"
{0x07f8, 0x0c4c, 0x0bb4, 0x0ab4, 0x0bb4, 0x0c4c, 0x07f8, 0x0000, 0x0000, 0x0000}, // "8"
{0x0ef8, 0x0b8c, 0x0b74, 0x0b54, 0x0b74, 0x0c0c, 0x07f8, 0x0000, 0x0000, 0x0000}, // "9"
{0x0e1c, 0x0a14, 0x0e1c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, // ":"
{0x1c00, 0x171c, 0x1914, 0x0f1c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, // ";"
{0x0380, 0x06c0, 0x0d60, 0x0ba0, 0x0ee0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, // "<"
{0x0ee0, 0x0aa0, 0x0aa0, 0x0aa0, 0x0aa0, 0x0aa0, 0x0aa0, 0x0ee0, 0x0000, 0x0000}, // "="
{0x0ee0, 0x0ba0, 0x0d60, 0x06c0, 0x0380, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, // ">"
{0x0000, 0x001c, 0x0fd4, 0x0a74, 0x0fb4, 0x00cc, 0x0078, 0x0000, 0x0000, 0x0000}, // "?"
{0x0ff0, 0x1818, 0x37ec, 0x2c74, 0x2bb4, 0x2bb4, 0x3c0c, 0x07f8, 0x0000, 0x0000}, // "@"
{0x0f80, 0x08f0, 0x0f1c, 0x0164, 0x0f1c, 0x08f0, 0x0f80, 0x0000, 0x0000, 0x0000}, // "A"
{0x0ffc, 0x0804, 0x0bb4, 0x0bb4, 0x0c4c, 0x07f8, 0x0000, 0x0000, 0x0000, 0x0000}, // "B"
{0x07f8, 0x0c0c, 0x0bf4, 0x0a14, 0x0a14, 0x0e1c, 0x0000, 0x0000, 0x0000, 0x0000}, // "C"
{0x0ffc, 0x0804, 0x0bf4, 0x0bf4, 0x0c0c, 0x07f8, 0x0000, 0x0000, 0x0000, 0x0000}, // "D"
{0x0ffc, 0x0804, 0x0bb4, 0x0ab4, 0x0ab4, 0x0efc, 0x0000, 0x0000, 0x0000, 0x0000}, // "E"
{0x0ffc, 0x0804, 0x0fb4, 0x00b4, 0x00f4, 0x001c, 0x0000, 0x0000, 0x0000, 0x0000}, // "F"
{0x07f8, 0x0c0c, 0x0bf4, 0x0bd4, 0x0b54, 0x0c5c, 0x07c0, 0x0000, 0x0000, 0x0000}, // "G"
{0x0ffc, 0x0804, 0x0fbc, 0x00a0, 0x0fbc, 0x0804, 0x0ffc, 0x0000, 0x0000, 0x0000}, // "H"
{0x0e1c, 0x0a14, 0x0bf4, 0x0804, 0x0bf4, 0x0a14, 0x0e1c, 0x0000, 0x0000, 0x0000}, // "I"
{0x0e1c, 0x0a14, 0x0bf4, 0x0c04, 0x07f4, 0x0014, 0x001c, 0x0000, 0x0000, 0x0000}, // "J"
{0x0ffc, 0x0804, 0x0fbc, 0x0e5c, 0x09e4, 0x0f3c, 0x0000, 0x0000, 0x0000, 0x0000}, // "K"
{0x0ffc, 0x0804, 0x0bfc, 0x0a00, 0x0a00, 0x0e00, 0x0000, 0x0000, 0x0000, 0x0000}, // "L"
{0x0ffc, 0x0804, 0x0fec, 0x00d8, 0x00b0, 0x00b0, 0x00d8, 0x0fec, 0x0804, 0x0ffc}, // "M"
{0x0ffc, 0x0804, 0x0fcc, 0x0738, 0x0cfc, 0x0804, 0x0ffc, 0x0000, 0x0000, 0x0000}, // "N"
{0x07f8, 0x0c0c, 0x0bf4, 0x0a14, 0x0a14, 0x0bf4, 0x0c0c, 0x07f8, 0x0000, 0x0000}, // "O"
{0x0ffc, 0x0804, 0x0f74, 0x0174, 0x018c, 0x00f8, 0x0000, 0x0000, 0x0000, 0x0000}, // "P"
{0x07f8, 0x0c0c, 0x0bf4, 0x0a14, 0x0a14, 0x1bf4, 0x140c, 0x17f8, 0x1c00, 0x0000}, // "Q"
{0x0ffc, 0x0804, 0x0f74, 0x0e74, 0x098c, 0x0ff8, 0x0000, 0x0000, 0x0000, 0x0000}, // "R"
{0x0ef8, 0x0b8c, 0x0b74, 0x0b54, 0x0cd4, 0x079c, 0x0000, 0x0000, 0x0000, 0x0000}, // "S"
{0x001c, 0x0014, 0x0ff4, 0x0804, 0x0ff4, 0x0014, 0x001c, 0x0000, 0x0000, 0x0000}, // "T"
{0x07fc, 0x0c04, 0x0bfc, 0x0a00, 0x0bfc, 0x0c04, 0x07fc, 0x0000, 0x0000, 0x0000}, // "U"
{0x01fc, 0x0704, 0x0cfc, 0x0b80, 0x0cfc, 0x0704, 0x01fc, 0x0000, 0x0000, 0x0000}, // "V"
{0x01fc, 0x0704, 0x0cfc, 0x0bc0, 0x0c40, 0x0bc0, 0x0cfc, 0x0704, 0x01fc, 0x0000}, // "W"
{0x0f3c, 0x09e4, 0x0edc, 0x0330, 0x0edc, 0x09e4, 0x0f3c, 0x0000, 0x0000, 0x0000}, // "X"
{0x003c, 0x00e4, 0x0f9c, 0x0870, 0x0f9c, 0x00e4, 0x003c, 0x0000, 0x0000, 0x0000}, // "Y"
{0x0f1c, 0x0994, 0x0af4, 0x0b34, 0x0bd4, 0x0a64, 0x0e3c, 0x0000, 0x0000, 0x0000}, // "Z"
{0x0ffc, 0x0804, 0x0bf4, 0x0a14, 0x0e1c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, // "{"
{0x001e, 0x0072, 0x01ce, 0x0738, 0x1ce0, 0x1380, 0x1e00, 0x0000, 0x0000, 0x0000}, // "\"
{0x0e1c, 0x0a14, 0x0bf4, 0x0804, 0x0ffc, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, // "}"
{0x0070, 0x0058, 0x006c, 0x0034, 0x006c, 0x0058, 0x0070, 0x0000, 0x0000, 0x0000}, // "^"
{0x1c00, 0x1400, 0x1400, 0x1400, 0x1400, 0x1400, 0x1400, 0x1c00, 0x0000, 0x0000}, // "_"
{0x000e, 0x001a, 0x0036, 0x002c, 0x0038, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, // "`"
{0x07c0, 0x0c60, 0x0ba0, 0x0aa0, 0x0ba0, 0x0c60, 0x0bc0, 0x0e00, 0x0000, 0x0000}, // "a"
{0x0ffc, 0x0804, 0x0bbc, 0x0ba0, 0x0c60, 0x07c0, 0x0000, 0x0000, 0x0000, 0x0000}, // "b"
{0x07c0, 0x0c60, 0x0ba0, 0x0aa0, 0x0ee0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, // "c"
{0x07c0, 0x0c60, 0x0ba0, 0x0bbc, 0x0804, 0x0ffc, 0x0000, 0x0000, 0x0000, 0x0000}, // "d"
{0x07c0, 0x0c60, 0x0aa0, 0x0aa0, 0x0b60, 0x0fc0, 0x0000, 0x0000, 0x0000, 0x0000}, // "e"
{0x0ff8, 0x080c, 0x0fb4, 0x00f4, 0x001c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, // "f"
{0x1fc0, 0x3660, 0x2da0, 0x2da0, 0x2da0, 0x3060, 0x1fc0, 0x0000, 0x0000, 0x0000}, // "g"
{0x0ffc, 0x0804, 0x0fbc, 0x0fa0, 0x0860, 0x0fc0, 0x0000, 0x0000, 0x0000, 0x0000}, // "h"
{0x0ff8, 0x0828, 0x0ff8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, // "i"
{0x1c00, 0x1400, 0x17f8, 0x1828, 0x0ff8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, // "j"
{0x0ffc, 0x0804, 0x0efc, 0x0d60, 0x0ba0, 0x0ee0, 0x0000, 0x0000, 0x0000, 0x0000}, // "k"
{0x07fc, 0x0c04, 0x0bfc, 0x0a00, 0x0e00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, // "l"
{0x0fc0, 0x0860, 0x0fa0, 0x07a0, 0x0460, 0x07a0, 0x0fa0, 0x0860, 0x0fc0, 0x0000}, // "m"
{0x0fc0, 0x0860, 0x0fa0, 0x0fa0, 0x0860, 0x0fc0, 0x0000, 0x0000, 0x0000, 0x0000}, // "n"
{0x07c0, 0x0c60, 0x0ba0, 0x0aa0, 0x0ba0, 0x0c60, 0x07c0, 0x0000, 0x0000, 0x0000}, // "o"
{0x3fe0, 0x2020, 0x3da0, 0x05a0, 0x0660, 0x03c0, 0x0000, 0x0000, 0x0000, 0x0000}, // "p"
{0x03c0, 0x0660, 0x05a0, 0x3da0, 0x2020, 0x37e0, 0x1c00, 0x0000, 0x0000, 0x0000}, // "q"
{0x0fc0, 0x0860, 0x0fa0, 0x00a0, 0x00e0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, // "r"
{0x0fc0, 0x0b60, 0x0aa0, 0x0da0, 0x07e0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, // "s"
{0x01c0, 0x0770, 0x0c10, 0x0b70, 0x0bc0, 0x0e00, 0x0000, 0x0000, 0x0000, 0x0000}, // "t"
{0x07e0, 0x0c20, 0x0be0, 0x0be0, 0x0c20, 0x07e0, 0x0000, 0x0000, 0x0000, 0x0000}, // "u"
{0x01e0, 0x0720, 0x0ce0, 0x0b80, 0x0ce0, 0x0720, 0x01e0, 0x0000, 0x0000, 0x0000}, // "v"
{0x01e0, 0x0720, 0x0ce0, 0x0b80, 0x0c80, 0x0b80, 0x0ce0, 0x0720, 0x01e0, 0x0000}, // "w"
{0x0ee0, 0x0ba0, 0x0d60, 0x06c0, 0x0d60, 0x0ba0, 0x0ee0, 0x0000, 0x0000, 0x0000}, // "x"
{0x1de0, 0x1720, 0x1ae0, 0x0d80, 0x06e0, 0x0320, 0x01e0, 0x0000, 0x0000, 0x0000}, // "y"
{0x0ee0, 0x0ba0, 0x09a0, 0x0aa0, 0x0b20, 0x0ba0, 0x0ee0, 0x0000, 0x0000, 0x0000}, // "z"
{0x01e0, 0x0f3c, 0x18c6, 0x17fa, 0x1c0e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, // "{"
{0x1ffe, 0x1002, 0x1ffe, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, // "|"
{0x1c0e, 0x17fa, 0x18c6, 0x0f3c, 0x01e0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, // "}"
{0x0380, 0x02c0, 0x0340, 0x0340, 0x02c0, 0x02c0, 0x0340, 0x01c0, 0x0000, 0x0000}, // "~"
{0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, // ""
};

Wyświetl plik

@ -0,0 +1,14 @@
set(OUTPUT_NAME interstate75_scrolling_text)
add_executable(${OUTPUT_NAME} interstate75_scrolling_text.cpp)
# enable usb output
pico_enable_stdio_usb(${OUTPUT_NAME} 1)
pico_add_extra_outputs(${OUTPUT_NAME})
target_link_libraries(${OUTPUT_NAME}
pico_stdlib
pico_multicore
hardware_vreg
hub75
)

Wyświetl plik

@ -0,0 +1,79 @@
#include <stdio.h>
#include <cmath>
#include <cstdint>
#include <string>
#include <string_view>
#include "pico/stdlib.h"
#include "hardware/vreg.h"
#include "common/pimoroni_common.hpp"
#include "hub75.hpp"
#include "font_outline_10x14.hpp"
using namespace pimoroni;
// Display size in pixels
// Should be either 64x64 or 32x32 but perhaps 64x32 an other sizes will work.
// Note: this example uses only 5 address lines so it's limited to 64 pixel high displays (32*2).
const uint8_t WIDTH = 64;
const uint8_t HEIGHT = 64;
Hub75 hub75(WIDTH, HEIGHT, nullptr, PANEL_GENERIC, true);
void __isr dma_complete() {
hub75.dma_complete();
}
void scroll_text(std::string_view text, uint y, float t, Pixel color) {
uint text_length = text.length();
uint x = uint(t);
uint letter = uint((x / letter_width) % text_length);
uint pixel = x % letter_width;
char c = text.at(letter);
for (auto s_x = 0u; s_x < WIDTH; s_x++) {
uint32_t col = font[c - 32][pixel];
for (auto s_y = 0u; s_y < letter_height; s_y++) {
// Calculate a bit of wiggle!
uint o_y = int(sinf((t / 3.0f) + s_x / 30.0f) * 8);
// Step through the uint32 that represents a single column
// of the current character, and render pixels for set bits.
if(col & (1 << s_y)) {
hub75.set_color(s_x, s_y + y + o_y, color);
}
}
// Advance to the text pixel/character
pixel++;
if (pixel == letter_width) {
pixel = 0;
letter++;
if (letter == text_length) letter = 0;
c = text.at(letter);
}
}
}
int main() {
vreg_set_voltage(VREG_VOLTAGE_1_20);
sleep_us(100);
set_sys_clock_khz(266000, true);
hub75.start(dma_complete);
std::string text = " Hello World! How are you today? ";
// Basic loop to draw something to the screen.
// This gets the distance from the middle of the display and uses it to paint a circular colour cycle.
while (true) {
hub75.background = hsv_to_rgb(millis() / 10000.0f, 1.0f, 0.5f);
// Shadow
scroll_text(text, HEIGHT / 2 - letter_height / 2 + 1, (millis() + 50) / 50.0f, Pixel(0, 0, 0));
// Text
scroll_text(text, HEIGHT / 2 - letter_height / 2, millis() / 50.0f, Pixel(255, 255, 255));
hub75.flip(false); // Flip and clear to the background colour
sleep_ms(1000 / 60);
}
}

Wyświetl plik

@ -4,17 +4,22 @@ The Interstate 75 library is intended for the Interstate 75 "HUB75" matrix panel
It can, in theory, be used with your own custom wiring, though custom pin assignments are not supported yet.
- [Notes On PIO Limitations](#notes-on-pio-limitations)
- [Notes On PIO & DMA Limitations](#notes-on-pio--dma-limitations)
- [Getting Started](#getting-started)
- [FM6216A Panels](#fm6216a-panels)
- [Set A Pixel](#set-a-pixel)
- [RGB](#rgb)
- [HSV](#hsv)
- [Quick Reference](#quick-reference)
- [Set A Pixel](#set-a-pixel)
- [Color](#color)
- [RGB](#rgb)
- [HSV](#hsv)
- [Update The Display](#update-the-display)
## Notes On PIO Limitations
## Notes On PIO & DMA Limitations
The Interstate 75 driver uses the PIO hardware on the RP2040. There are only two PIOs with four state machines each, and i75 uses one of these (`PIO0`) and two state machines- one for clocking out pixels, and another for latching/lighting a row.
It also uses two DMA channels, one to copy pixel data from the back buffer back to the front buffer and one to supply the row driving PIO with row data.
## Getting Started
Contruct a new `Hub75` instance, specifying the width/height of the display and any additional options.
@ -49,22 +54,69 @@ HEIGHT = 64
matrix = hub75.Hub75(WIDTH, HEIGHT, panel_type=hub75.PANEL_FM6126A)
```
## Set A Pixel
## Quick Reference
### Set A Pixel
You can set the colour of an pixel in either the RGB colourspace, or HSV (Hue, Saturation, Value). HSV is useful for creating rainbow patterns.
### RGB
#### Color
Set the top left-most LED - `0, 0` - to a pre-calculated colour.
```python
matrix.set_color(0, 0, color)
```
There are a couple of functions for generating colours, which take your red, green and blue values, gamma correct them and pack them into a single number. By converting a colour and saving this value you can pay the cost of conversion up-front and drawing pixels in that colour will be faster:
```python
red = hub75.color(255, 0, 0)
red = hub75.color_hsv(1.0, 0, 0)
```
Eg:
```python
red = hub75.color(255, 0, 0)
for x in range(32):
matrix.set_color(0, 0, red)
```
#### RGB
Set the top left-most LED - `0, 0` - to Purple `255, 0, 255`:
```python
matrixx.set_rgb(0, 0, 255, 0, 255)
matrix.set_rgb(0, 0, 255, 0, 255)
```
### HSV
#### HSV
Set the top left-most LED - `0, o` - to Red `0.0`:
```python
matrix.set_hsv(0, 0, 0.0, 1.0, 1.0)
```
### Update The Display
You can update the back buffer - the framebuffer used by the driver to drive the screen - by calling `flip`:
```python
matrix.flip()
```
`flip` will swap the front buffer (the one you draw into) with the back buffer (the one the screen is refreshed from) so that the display can start drawing your changes immediately.
Since the back buffer contains your *previous* frame it then blocks and copies across the contents of the buffer you've just flipped.
If you want fresh, clear buffer to draw into at the start of your next frame you can use `flip_and_clear` instead:
```python
background_color = hub75.color(0, 0, 0)
matrix.flip_and_clear(background_color)
```
This will fill your buffer with the background colour, so you don't need to call `clear`.

Wyświetl plik

@ -13,6 +13,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(Hub75_clear_obj, Hub75_clear);
MP_DEFINE_CONST_FUN_OBJ_1(Hub75_start_obj, Hub75_start);
MP_DEFINE_CONST_FUN_OBJ_1(Hub75_stop_obj, Hub75_stop);
MP_DEFINE_CONST_FUN_OBJ_1(Hub75_flip_obj, Hub75_flip);
MP_DEFINE_CONST_FUN_OBJ_2(Hub75_flip_and_clear_obj, Hub75_flip_and_clear);
MP_DEFINE_CONST_FUN_OBJ_3(Hub75_color_obj, Hub75_color);
MP_DEFINE_CONST_FUN_OBJ_3(Hub75_color_hsv_obj, Hub75_color_hsv);
@ -30,6 +31,7 @@ STATIC const mp_rom_map_elem_t Hub75_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_start), MP_ROM_PTR(&Hub75_start_obj) },
{ MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&Hub75_stop_obj) },
{ MP_ROM_QSTR(MP_QSTR_flip), MP_ROM_PTR(&Hub75_flip_obj) },
{ MP_ROM_QSTR(MP_QSTR_flip_and_clear), MP_ROM_PTR(&Hub75_flip_and_clear_obj) },
};
STATIC MP_DEFINE_CONST_DICT(Hub75_locals_dict, Hub75_locals_dict_table);

Wyświetl plik

@ -124,10 +124,17 @@ mp_obj_t Hub75_clear(mp_obj_t self_in) {
mp_obj_t Hub75_flip(mp_obj_t self_in) {
_Hub75_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Hub75_obj_t);
self->hub75->do_flip = true;
while (self->hub75->do_flip) {
MICROPY_EVENT_POLL_HOOK
}
self->hub75->flip();
return mp_const_none;
}
mp_obj_t Hub75_flip_and_clear(mp_obj_t self_in, mp_obj_t color) {
_Hub75_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Hub75_obj_t);
self->hub75->background.color = mp_obj_get_int(color);
self->hub75->flip(false);
return mp_const_none;
}
@ -165,7 +172,8 @@ mp_obj_t Hub75_set_color_masked(size_t n_args, const mp_obj_t *pos_args, mp_map_
int x = args[ARG_x].u_int;
int y = args[ARG_y].u_int;
int c = args[ARG_color].u_int;
Pixel c;
c.color = args[ARG_color].u_int;
int m = args[ARG_mask].u_int;
_Hub75_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self].u_obj, _Hub75_obj_t);
@ -202,7 +210,8 @@ mp_obj_t Hub75_set_color(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_a
int x = args[ARG_x].u_int;
int y = args[ARG_y].u_int;
int c = args[ARG_color].u_int;
Pixel c;
c.color = args[ARG_color].u_int;
_Hub75_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self].u_obj, _Hub75_obj_t);
self->hub75->set_color(x, y, c);
@ -267,7 +276,8 @@ mp_obj_t Hub75_set_hsv(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_arg
mp_obj_t Hub75_set_all_color(mp_obj_t self_in, mp_obj_t color) {
_Hub75_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Hub75_obj_t);
int c = mp_obj_get_int(color);
Pixel c;
c.color = mp_obj_get_int(color);
for (auto x = 0u; x < self->hub75->width; x++) {
for (auto y = 0u; y < self->hub75->height; y++) {

Wyświetl plik

@ -20,4 +20,5 @@ extern mp_obj_t Hub75_color_hsv(mp_obj_t h, mp_obj_t s, mp_obj_t v);
extern mp_obj_t Hub75_set_all_hsv(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
extern mp_obj_t Hub75_set_all_color(mp_obj_t self_in, mp_obj_t color);
extern mp_obj_t Hub75_clear(mp_obj_t self_in);
extern mp_obj_t Hub75_flip(mp_obj_t self_in);
extern mp_obj_t Hub75_flip(mp_obj_t self_in);
extern mp_obj_t Hub75_flip_and_clear(mp_obj_t self_in, mp_obj_t color);