kopia lustrzana https://github.com/pimoroni/pimoroni-pico
HUB75 Perf, C++ scrolling text, docs
rodzic
4dc3f9b9c4
commit
1bb4383074
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
};
|
||||
|
|
@ -1,2 +1,3 @@
|
|||
include(interstate75_hello_world.cmake)
|
||||
include(interstate75_pio_dma.cmake)
|
||||
include(interstate75_pio_dma.cmake)
|
||||
include(interstate75_scrolling_text.cmake)
|
||||
|
|
@ -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}, // ""
|
||||
};
|
||||
|
|
@ -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
|
||||
)
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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`.
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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++) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
Ładowanie…
Reference in New Issue