diff --git a/drivers/hub75/hub75.cpp b/drivers/hub75/hub75.cpp index 0d4ac48a..13ace73e 100644 --- a/drivers/hub75/hub75.cpp +++ b/drivers/hub75/hub75.cpp @@ -77,7 +77,7 @@ Hub75::Hub75(uint width, uint height, Pixel *buffer, PanelType panel_type, bool } } -void Hub75::set_rgb(uint x, uint y, uint8_t r, uint8_t g, uint8_t b) { +void Hub75::set_color(uint x, uint y, uint32_t c) { int offset = 0; if(x >= width || y >= height) return; if(y >= height / 2) { @@ -87,20 +87,15 @@ void Hub75::set_rgb(uint x, uint y, uint8_t r, uint8_t g, uint8_t b) { } else { offset = (y * width + x) * 2; } - front_buffer[offset] = Pixel(r, g, b); + front_buffer[offset].color = 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); } void Hub75::set_hsv(uint x, uint y, float h, float s, float v) { - int offset = 0; - if(x >= width || y >= height) return; - if(y >= height / 2) { - y -= height / 2; - offset = (y * width + x) * 2; - offset += 1; - } else { - offset = (y * width + x) * 2; - } - front_buffer[offset] = hsv_to_rgb(h, s, v); + set_color(x, y, hsv_to_rgb(h, s, v).color); } void Hub75::FM6126A_write_register(uint16_t value, uint8_t position) { diff --git a/drivers/hub75/hub75.hpp b/drivers/hub75/hub75.hpp index c97136b6..30234cd4 100644 --- a/drivers/hub75/hub75.hpp +++ b/drivers/hub75/hub75.hpp @@ -37,6 +37,7 @@ constexpr uint16_t GAMMA_10BIT[256] = { struct Pixel { uint32_t color; constexpr Pixel() : color(0) {}; + constexpr Pixel(uint32_t color) : color(color) {}; constexpr Pixel(uint8_t r, uint8_t g, uint8_t b) : color((GAMMA_10BIT[b] << 20) | (GAMMA_10BIT[g] << 10) | GAMMA_10BIT[r]) {}; }; @@ -45,6 +46,8 @@ enum PanelType { PANEL_FM6126A, }; +Pixel hsv_to_rgb(float h, float s, float v); + class Hub75 { public: uint width; @@ -113,6 +116,7 @@ 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_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(); diff --git a/micropython/examples/interstate75/font_10x14.py b/micropython/examples/interstate75/font_10x14.py new file mode 100644 index 00000000..83e28f39 --- /dev/null +++ b/micropython/examples/interstate75/font_10x14.py @@ -0,0 +1,100 @@ +letter_width = 10 +letter_height = 14 +font = [ + [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], # "" +] diff --git a/micropython/examples/interstate75/font_8x12.py b/micropython/examples/interstate75/font_8x12.py new file mode 100644 index 00000000..37410aeb --- /dev/null +++ b/micropython/examples/interstate75/font_8x12.py @@ -0,0 +1,100 @@ +letter_width = 8 +letter_height = 12 +font = [ + [0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000], # " " + [0x2fc, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000], # "!" + [0x01c, 0x000, 0x01c, 0x000, 0x000, 0x000, 0x000, 0x000], # """ + [0x090, 0x090, 0x3fc, 0x090, 0x090, 0x3fc, 0x090, 0x090], # "#" + [0x238, 0x244, 0x7fe, 0x244, 0x184, 0x000, 0x000, 0x000], # "$" + [0x008, 0x014, 0x308, 0x0c0, 0x030, 0x10c, 0x280, 0x100], # "%" + [0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000], # "&" + [0x01c, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000], # "'" + [0x0f0, 0x30c, 0x402, 0x000, 0x000, 0x000, 0x000, 0x000], # "(" + [0x402, 0x30c, 0x0f0, 0x000, 0x000, 0x000, 0x000, 0x000], # ")" + [0x024, 0x018, 0x018, 0x024, 0x000, 0x000, 0x000, 0x000], # "*" + [0x040, 0x040, 0x1f0, 0x040, 0x040, 0x000, 0x000, 0x000], # "+" + [0x400, 0x300, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000], # "," + [0x040, 0x040, 0x040, 0x040, 0x040, 0x000, 0x000, 0x000], # "-" + [0x200, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000], # "." + [0x600, 0x180, 0x060, 0x018, 0x006, 0x000, 0x000, 0x000], # "/" + [0x1f8, 0x204, 0x204, 0x204, 0x1f8, 0x000, 0x000, 0x000], # "0" + [0x210, 0x208, 0x3fc, 0x200, 0x200, 0x000, 0x000, 0x000], # "1" + [0x208, 0x304, 0x284, 0x244, 0x238, 0x000, 0x000, 0x000], # "2" + [0x108, 0x204, 0x204, 0x264, 0x198, 0x000, 0x000, 0x000], # "3" + [0x0c0, 0x0b0, 0x088, 0x3fc, 0x080, 0x000, 0x000, 0x000], # "4" + [0x23c, 0x224, 0x224, 0x224, 0x1c4, 0x000, 0x000, 0x000], # "5" + [0x1f8, 0x224, 0x224, 0x224, 0x1c4, 0x000, 0x000, 0x000], # "6" + [0x004, 0x004, 0x384, 0x064, 0x01c, 0x000, 0x000, 0x000], # "7" + [0x1d8, 0x224, 0x224, 0x224, 0x1d8, 0x000, 0x000, 0x000], # "8" + [0x238, 0x244, 0x244, 0x244, 0x1f8, 0x000, 0x000, 0x000], # "9" + [0x204, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000], # ":" + [0x400, 0x304, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000], # ";" + [0x080, 0x140, 0x220, 0x000, 0x000, 0x000, 0x000, 0x000], # "<" + [0x220, 0x220, 0x220, 0x220, 0x220, 0x220, 0x000, 0x000], # "=" + [0x220, 0x140, 0x080, 0x000, 0x000, 0x000, 0x000, 0x000], # ">" + [0x000, 0x004, 0x2c4, 0x024, 0x018, 0x000, 0x000, 0x000], # "?" + [0x3f0, 0x408, 0x9c4, 0xa24, 0xa24, 0x1f8, 0x000, 0x000], # "@" + [0x380, 0x070, 0x04c, 0x070, 0x380, 0x000, 0x000, 0x000], # "A" + [0x3fc, 0x224, 0x224, 0x1d8, 0x000, 0x000, 0x000, 0x000], # "B" + [0x1f8, 0x204, 0x204, 0x204, 0x000, 0x000, 0x000, 0x000], # "C" + [0x3fc, 0x204, 0x204, 0x1f8, 0x000, 0x000, 0x000, 0x000], # "D" + [0x3fc, 0x224, 0x224, 0x224, 0x000, 0x000, 0x000, 0x000], # "E" + [0x3fc, 0x024, 0x024, 0x004, 0x000, 0x000, 0x000, 0x000], # "F" + [0x1f8, 0x204, 0x204, 0x244, 0x1c0, 0x000, 0x000, 0x000], # "G" + [0x3fc, 0x020, 0x020, 0x020, 0x3fc, 0x000, 0x000, 0x000], # "H" + [0x204, 0x204, 0x3fc, 0x204, 0x204, 0x000, 0x000, 0x000], # "I" + [0x204, 0x204, 0x1fc, 0x004, 0x004, 0x000, 0x000, 0x000], # "J" + [0x3fc, 0x020, 0x0d0, 0x30c, 0x000, 0x000, 0x000, 0x000], # "K" + [0x3fc, 0x200, 0x200, 0x200, 0x000, 0x000, 0x000, 0x000], # "L" + [0x3fc, 0x008, 0x010, 0x020, 0x020, 0x010, 0x008, 0x3fc], # "M" + [0x3fc, 0x018, 0x060, 0x180, 0x3fc, 0x000, 0x000, 0x000], # "N" + [0x1f8, 0x204, 0x204, 0x204, 0x204, 0x1f8, 0x000, 0x000], # "O" + [0x3fc, 0x044, 0x044, 0x038, 0x000, 0x000, 0x000, 0x000], # "P" + [0x1f8, 0x204, 0x204, 0x204, 0x204, 0x5f8, 0x400, 0x000], # "Q" + [0x3fc, 0x044, 0x0c4, 0x338, 0x000, 0x000, 0x000, 0x000], # "R" + [0x238, 0x244, 0x244, 0x184, 0x000, 0x000, 0x000, 0x000], # "S" + [0x004, 0x004, 0x3fc, 0x004, 0x004, 0x000, 0x000, 0x000], # "T" + [0x1fc, 0x200, 0x200, 0x200, 0x1fc, 0x000, 0x000, 0x000], # "U" + [0x07c, 0x180, 0x200, 0x180, 0x07c, 0x000, 0x000, 0x000], # "V" + [0x07c, 0x180, 0x200, 0x1c0, 0x200, 0x180, 0x07c, 0x000], # "W" + [0x30c, 0x090, 0x060, 0x090, 0x30c, 0x000, 0x000, 0x000], # "X" + [0x00c, 0x030, 0x3c0, 0x030, 0x00c, 0x000, 0x000, 0x000], # "Y" + [0x304, 0x284, 0x264, 0x214, 0x20c, 0x000, 0x000, 0x000], # "Z" + [0x3fc, 0x204, 0x204, 0x000, 0x000, 0x000, 0x000, 0x000], # "[" + [0x006, 0x018, 0x060, 0x180, 0x600, 0x000, 0x000, 0x000], # "\" + [0x204, 0x204, 0x3fc, 0x000, 0x000, 0x000, 0x000, 0x000], # "]" + [0x010, 0x008, 0x004, 0x008, 0x010, 0x000, 0x000, 0x000], # "^" + [0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x000, 0x000], # "_" + [0x002, 0x004, 0x008, 0x000, 0x000, 0x000, 0x000, 0x000], # "`" + [0x1c0, 0x220, 0x220, 0x220, 0x1c0, 0x200, 0x000, 0x000], # "a" + [0x3fc, 0x220, 0x220, 0x1c0, 0x000, 0x000, 0x000, 0x000], # "b" + [0x1c0, 0x220, 0x220, 0x000, 0x000, 0x000, 0x000, 0x000], # "c" + [0x1c0, 0x220, 0x220, 0x3fc, 0x000, 0x000, 0x000, 0x000], # "d" + [0x1c0, 0x2a0, 0x2a0, 0x240, 0x000, 0x000, 0x000, 0x000], # "e" + [0x3f8, 0x024, 0x004, 0x000, 0x000, 0x000, 0x000, 0x000], # "f" + [0x4c0, 0x920, 0x920, 0x920, 0x7c0, 0x000, 0x000, 0x000], # "g" + [0x3fc, 0x020, 0x020, 0x3c0, 0x000, 0x000, 0x000, 0x000], # "h" + [0x3e8, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000], # "i" + [0x400, 0x400, 0x3e8, 0x000, 0x000, 0x000, 0x000, 0x000], # "j" + [0x3fc, 0x080, 0x140, 0x220, 0x000, 0x000, 0x000, 0x000], # "k" + [0x1fc, 0x200, 0x200, 0x000, 0x000, 0x000, 0x000, 0x000], # "l" + [0x3c0, 0x020, 0x020, 0x1c0, 0x020, 0x020, 0x3c0, 0x000], # "m" + [0x3c0, 0x020, 0x020, 0x3c0, 0x000, 0x000, 0x000, 0x000], # "n" + [0x1c0, 0x220, 0x220, 0x220, 0x1c0, 0x000, 0x000, 0x000], # "o" + [0xfe0, 0x120, 0x120, 0x0c0, 0x000, 0x000, 0x000, 0x000], # "p" + [0x0c0, 0x120, 0x120, 0xfe0, 0x400, 0x000, 0x000, 0x000], # "q" + [0x3c0, 0x020, 0x020, 0x000, 0x000, 0x000, 0x000, 0x000], # "r" + [0x240, 0x2a0, 0x120, 0x000, 0x000, 0x000, 0x000, 0x000], # "s" + [0x040, 0x1f0, 0x240, 0x200, 0x000, 0x000, 0x000, 0x000], # "t" + [0x1e0, 0x200, 0x200, 0x1e0, 0x000, 0x000, 0x000, 0x000], # "u" + [0x060, 0x180, 0x200, 0x180, 0x060, 0x000, 0x000, 0x000], # "v" + [0x060, 0x180, 0x200, 0x180, 0x200, 0x180, 0x060, 0x000], # "w" + [0x220, 0x140, 0x080, 0x140, 0x220, 0x000, 0x000, 0x000], # "x" + [0x460, 0x280, 0x100, 0x080, 0x060, 0x000, 0x000, 0x000], # "y" + [0x220, 0x320, 0x2a0, 0x260, 0x220, 0x000, 0x000, 0x000], # "z" + [0x060, 0x39c, 0x402, 0x000, 0x000, 0x000, 0x000, 0x000], # "{" + [0x7fe, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000], # "|" + [0x402, 0x39c, 0x060, 0x000, 0x000, 0x000, 0x000, 0x000], # "}" + [0x080, 0x040, 0x040, 0x080, 0x080, 0x040, 0x000, 0x000], # "~" + [0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000], # "" +] diff --git a/micropython/examples/interstate75/i75_128x64_scrolling_wavy_clock.py b/micropython/examples/interstate75/i75_128x64_scrolling_wavy_clock.py new file mode 100644 index 00000000..c6f30cd9 --- /dev/null +++ b/micropython/examples/interstate75/i75_128x64_scrolling_wavy_clock.py @@ -0,0 +1,53 @@ +from time import ticks_ms +import math + +from machine import RTC +import hub75 +# from font_8x12 import font, letter_width, letter_height +from font_10x14 import font, letter_width, letter_height + +WIDTH, HEIGHT = 128, 64 + +rtc = RTC() + +hub = hub75.Hub75(WIDTH, HEIGHT, stb_invert=True) +hub.start() +hub.clear() + +t_s = ticks_ms() +f_s = ticks_ms() / 1000.0 + +frames = 0 + + +def scroll_text(text, y, t): + text_length = len(text) + x = int(t) + letter = int((x / letter_width) % text_length) + pixel = x % letter_width + char = ord(text[letter]) + for s_x in range(WIDTH): + col = font[char - 32][pixel] + s_y = y + int(math.sin((t / 3.0) + s_x / 30.0) * 8) + hub.set_color_masked(s_x, s_y, col, hub75.color_hsv((t + s_x) / WIDTH, 1.0, 1.0)) + pixel += 1 + if pixel == letter_width: + pixel = 0 + letter += 1 + if letter == text_length: + letter = 0 + char = ord(text[letter]) + + +while True: + year, month, day, wd, hour, minute, second, _ = rtc.datetime() + text = " {:02}:{:02}:{:02} {:04}/{:02}/{:02}".format(hour, minute, second, year, month, day) + + hub.clear() + t = (ticks_ms() - t_s) / 50.0 + scroll_text(text, int(HEIGHT / 2) - int(letter_height / 2), t) + hub.flip() + frames += 1 + if frames % 60 == 0: + f_e = ticks_ms() / 1000.0 + print(frames / (f_e - f_s)) diff --git a/micropython/examples/interstate75/i75_64x64_scrolling_text.py b/micropython/examples/interstate75/i75_64x64_scrolling_text.py new file mode 100644 index 00000000..85480be3 --- /dev/null +++ b/micropython/examples/interstate75/i75_64x64_scrolling_text.py @@ -0,0 +1,50 @@ +from time import ticks_ms +import math + +import hub75 +# from font_8x12 import font, letter_width, letter_height +from font_10x14 import font, letter_width, letter_height + + +WIDTH, HEIGHT = 64, 64 + +hub = hub75.Hub75(WIDTH, HEIGHT, stb_invert=True) +hub.start() +hub.clear() + +text = " Hello World!" + +t_s = ticks_ms() +f_s = ticks_ms() / 1000.0 + +frames = 0 + + +def scroll_text(text, y, t): + text_length = len(text) + x = int(t) + letter = int((x / letter_width) % text_length) + pixel = x % letter_width + char = ord(text[letter]) + for s_x in range(WIDTH): + col = font[char - 32][pixel] + s_y = y + int(math.sin((t / 3.0) + s_x / 30.0) * 8) + hub.set_color_masked(s_x, s_y, col, hub75.color_hsv(s_x / WIDTH, 1.0, 1.0)) + pixel += 1 + if pixel == letter_width: + pixel = 0 + letter += 1 + if letter == text_length: + letter = 0 + char = ord(text[letter]) + + +while True: + hub.clear() + t = (ticks_ms() - t_s) / 50.0 + scroll_text(text, int(HEIGHT / 2) - int(letter_height / 2), t) + hub.flip() + frames += 1 + if frames % 60 == 0: + f_e = ticks_ms() / 1000.0 + print(frames / (f_e - f_s)) diff --git a/micropython/modules/hub75/README.md b/micropython/modules/hub75/README.md new file mode 100644 index 00000000..e3318a3e --- /dev/null +++ b/micropython/modules/hub75/README.md @@ -0,0 +1,70 @@ +# Interstate 75 + +The Interstate 75 library is intended for the Interstate 75 "HUB75" matrix panel driver board. + +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) +- [Getting Started](#getting-started) + - [FM6216A Panels](#fm6216a-panels) +- [Set A Pixel](#set-a-pixel) + - [RGB](#rgb) + - [HSV](#hsv) + +## Notes On PIO 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. + +## Getting Started + +Contruct a new `Hub75` instance, specifying the width/height of the display and any additional options. + +```python +import hub75 + +WIDTH = 64 +HEIGHT = 64 + +matrix = hub75.Hub75(WIDTH, HEIGHT, stb_invert=True) +``` + +Use `stb_invert` if you see a missing middle row corruption on the top row. + +Start the matrix strip by calling `start`. This sets up DMA and PIO to drive your panel, pulling rows from the back buffer and refreshing as fast as it can. + +```python +matrix.start() +``` + +### FM6216A Panels + +Some panels - based on the FM6126A chips - require a couple of register settings in order for them to display anything at all. Interstate 75 will set these for you if you specify `panel_type=hub75.PANEL_FM6126A`. Eg: + +```python +import hub75 + +WIDTH = 64 +HEIGHT = 64 + +matrix = hub75.Hub75(WIDTH, HEIGHT, panel_type=hub75.PANEL_FM6126A) +``` + +## 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 + +Set the top left-most LED - `0, 0` - to Purple `255, 0, 255`: + +```python +matrixx.set_rgb(0, 0, 255, 0, 255) +``` + +### 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) +``` diff --git a/micropython/modules/hub75/hub75.c b/micropython/modules/hub75/hub75.c index d434ec41..92b936b3 100644 --- a/micropython/modules/hub75/hub75.c +++ b/micropython/modules/hub75/hub75.c @@ -3,20 +3,29 @@ /***** Methods *****/ MP_DEFINE_CONST_FUN_OBJ_1(Hub75___del___obj, Hub75___del__); +MP_DEFINE_CONST_FUN_OBJ_KW(Hub75_set_color_obj, 3, Hub75_set_color); MP_DEFINE_CONST_FUN_OBJ_KW(Hub75_set_rgb_obj, 5, Hub75_set_rgb); MP_DEFINE_CONST_FUN_OBJ_KW(Hub75_set_hsv_obj, 5, Hub75_set_hsv); +MP_DEFINE_CONST_FUN_OBJ_KW(Hub75_set_color_masked_obj, 5, Hub75_set_color_masked); +MP_DEFINE_CONST_FUN_OBJ_2(Hub75_set_all_color_obj, Hub75_set_all_color); MP_DEFINE_CONST_FUN_OBJ_KW(Hub75_set_all_hsv_obj, 3, Hub75_set_all_hsv); 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_3(Hub75_color_obj, Hub75_color); +MP_DEFINE_CONST_FUN_OBJ_3(Hub75_color_hsv_obj, Hub75_color_hsv); + /***** Binding of Methods *****/ STATIC const mp_rom_map_elem_t Hub75_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&Hub75___del___obj) }, + { MP_ROM_QSTR(MP_QSTR_set_color), MP_ROM_PTR(&Hub75_set_color_obj) }, { MP_ROM_QSTR(MP_QSTR_set_rgb), MP_ROM_PTR(&Hub75_set_rgb_obj) }, { MP_ROM_QSTR(MP_QSTR_set_hsv), MP_ROM_PTR(&Hub75_set_hsv_obj) }, + { MP_ROM_QSTR(MP_QSTR_set_color_masked), MP_ROM_PTR(&Hub75_set_color_masked_obj) }, { MP_ROM_QSTR(MP_QSTR_set_all_hsv), MP_ROM_PTR(&Hub75_set_all_hsv_obj) }, + { MP_ROM_QSTR(MP_QSTR_set_all_color), MP_ROM_PTR(&Hub75_set_all_color_obj) }, { MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&Hub75_clear_obj) }, { MP_ROM_QSTR(MP_QSTR_start), MP_ROM_PTR(&Hub75_start_obj) }, { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&Hub75_stop_obj) }, @@ -41,6 +50,8 @@ STATIC const mp_map_elem_t hub75_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_Hub75), (mp_obj_t)&Hub75_type }, { MP_OBJ_NEW_QSTR(MP_QSTR_PANEL_GENERIC), MP_ROM_INT(0) }, { MP_OBJ_NEW_QSTR(MP_QSTR_PANEL_FM6126A), MP_ROM_INT(1) }, + { MP_ROM_QSTR(MP_QSTR_color), MP_ROM_PTR(&Hub75_color_obj) }, + { MP_ROM_QSTR(MP_QSTR_color_hsv), MP_ROM_PTR(&Hub75_color_hsv_obj) } }; STATIC MP_DEFINE_CONST_DICT(mp_module_hub75_globals, hub75_globals_table); diff --git a/micropython/modules/hub75/hub75.cpp b/micropython/modules/hub75/hub75.cpp index 6ca1fd69..45be9bb3 100644 --- a/micropython/modules/hub75/hub75.cpp +++ b/micropython/modules/hub75/hub75.cpp @@ -139,10 +139,6 @@ void Hub75_display_update() { mp_obj_t Hub75_start(mp_obj_t self_in) { _Hub75_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Hub75_obj_t); - //size_t stack_size = 0; - //mp_thread_create(&Hub75_display_update, nullptr, &stack_size); - //multicore_reset_core1(); - //multicore_launch_core1(Hub75_display_update); self->hub75->start(dma_complete); return mp_const_none; } @@ -153,6 +149,67 @@ mp_obj_t Hub75_stop(mp_obj_t self_in) { return mp_const_none; } +mp_obj_t Hub75_set_color_masked(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_self, ARG_x, ARG_y, ARG_mask, ARG_color }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_mask, MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_color, MP_ARG_REQUIRED | MP_ARG_INT }, + }; + + // Parse args. + 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); + + int x = args[ARG_x].u_int; + int y = args[ARG_y].u_int; + int c = 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); + + for(auto py = 0; py < 32; py++) { + if(m & (1 << py)) { + self->hub75->set_color(x, py + y, c); + } + } + + return mp_const_none; +} + +mp_obj_t Hub75_color(mp_obj_t r, mp_obj_t g, mp_obj_t b) { + return mp_obj_new_int(Pixel(mp_obj_get_int(r), mp_obj_get_int(g), mp_obj_get_int(b)).color); +} + +mp_obj_t Hub75_color_hsv(mp_obj_t h, mp_obj_t s, mp_obj_t v) { + return mp_obj_new_int(hsv_to_rgb(mp_obj_get_float(h), mp_obj_get_float(s), mp_obj_get_float(v)).color); +} + +mp_obj_t Hub75_set_color(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_self, ARG_x, ARG_y, ARG_color }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_color, MP_ARG_REQUIRED | MP_ARG_INT }, + }; + + // Parse args. + 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); + + int x = args[ARG_x].u_int; + int y = args[ARG_y].u_int; + int c = 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); + + return mp_const_none; +} + mp_obj_t Hub75_set_rgb(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_self, ARG_x, ARG_y, ARG_r, ARG_g, ARG_b }; static const mp_arg_t allowed_args[] = { @@ -207,6 +264,20 @@ mp_obj_t Hub75_set_hsv(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_arg return mp_const_none; } +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); + + for (auto x = 0u; x < self->hub75->width; x++) { + for (auto y = 0u; y < self->hub75->height; y++) { + self->hub75->set_color(x, y, c); + } + } + + return mp_const_none; +} + mp_obj_t Hub75_set_all_hsv(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_self, ARG_h, ARG_s, ARG_v }; static const mp_arg_t allowed_args[] = { diff --git a/micropython/modules/hub75/hub75.h b/micropython/modules/hub75/hub75.h index 7a72b804..93582aa6 100644 --- a/micropython/modules/hub75/hub75.h +++ b/micropython/modules/hub75/hub75.h @@ -1,5 +1,6 @@ // Include MicroPython API. #include "py/runtime.h" +#include "py/objstr.h" /***** Extern of Class Definition *****/ extern const mp_obj_type_t Hub75_type; @@ -10,8 +11,13 @@ extern mp_obj_t Hub75_make_new(const mp_obj_type_t *type, size_t n_args, size_t extern mp_obj_t Hub75___del__(mp_obj_t self_in); extern mp_obj_t Hub75_start(mp_obj_t self_in); extern mp_obj_t Hub75_stop(mp_obj_t self_in); +extern mp_obj_t Hub75_set_color(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); extern mp_obj_t Hub75_set_rgb(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); extern mp_obj_t Hub75_set_hsv(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); +extern mp_obj_t Hub75_set_color_masked(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); +extern mp_obj_t Hub75_color(mp_obj_t r, mp_obj_t g, mp_obj_t b); +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); \ No newline at end of file