125 lines
4.2 KiB
C++
125 lines
4.2 KiB
C++
#include <stdint.h>
|
|
#include "pico/stdlib.h"
|
|
#include "pico/multicore.h"
|
|
|
|
#include "hardware/pio.h"
|
|
#include "hardware/dma.h"
|
|
#include "hardware/irq.h"
|
|
#include "hub75.pio.h"
|
|
|
|
const uint DATA_BASE_PIN = 0;
|
|
const uint DATA_N_PINS = 6;
|
|
const uint ROWSEL_BASE_PIN = 6;
|
|
const uint ROWSEL_N_PINS = 5;
|
|
|
|
// This gamma table is used to correct our 8-bit (0-255) colours up to 11-bit,
|
|
// allowing us to gamma correct without losing dynamic range.
|
|
constexpr uint16_t GAMMA_12BIT[256] = {
|
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
|
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
|
|
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 47, 50,
|
|
52, 54, 57, 59, 62, 65, 67, 70, 73, 76, 79, 82, 85, 88, 91, 94,
|
|
98, 101, 105, 108, 112, 115, 119, 123, 127, 131, 135, 139, 143, 147, 151, 155,
|
|
160, 164, 169, 173, 178, 183, 187, 192, 197, 202, 207, 212, 217, 223, 228, 233,
|
|
239, 244, 250, 255, 261, 267, 273, 279, 285, 291, 297, 303, 309, 316, 322, 328,
|
|
335, 342, 348, 355, 362, 369, 376, 383, 390, 397, 404, 412, 419, 427, 434, 442,
|
|
449, 457, 465, 473, 481, 489, 497, 505, 513, 522, 530, 539, 547, 556, 565, 573,
|
|
582, 591, 600, 609, 618, 628, 637, 646, 656, 665, 675, 685, 694, 704, 714, 724,
|
|
734, 744, 755, 765, 775, 786, 796, 807, 817, 828, 839, 850, 861, 872, 883, 894,
|
|
905, 917, 928, 940, 951, 963, 975, 987, 998, 1010, 1022, 1035, 1047, 1059, 1071, 1084,
|
|
1096, 1109, 1122, 1135, 1147, 1160, 1173, 1186, 1199, 1213, 1226, 1239, 1253, 1266, 1280, 1294,
|
|
1308, 1321, 1335, 1349, 1364, 1378, 1392, 1406, 1421, 1435, 1450, 1465, 1479, 1494, 1509, 1524,
|
|
1539, 1554, 1570, 1585, 1600, 1616, 1631, 1647, 1663, 1678, 1694, 1710, 1726, 1743, 1759, 1775,
|
|
1791, 1808, 1824, 1841, 1858, 1875, 1891, 1908, 1925, 1943, 1960, 1977, 1994, 2012, 2029, 2047};
|
|
|
|
|
|
// We don't *need* to make Pixel a fancy struct with RGB values, but it helps.
|
|
#pragma pack(push, 1)
|
|
struct alignas(4) Pixel {
|
|
uint16_t _;
|
|
uint16_t r;
|
|
uint16_t g;
|
|
uint16_t b;
|
|
constexpr Pixel() : _(0), r(0), g(0), b(0) {};
|
|
constexpr Pixel(uint8_t r, uint8_t g, uint8_t b) : _(0), r(GAMMA_12BIT[r]), g(GAMMA_12BIT[g]), b(GAMMA_12BIT[b]) {};
|
|
};
|
|
#pragma pack(pop)
|
|
|
|
enum PanelType {
|
|
PANEL_GENERIC = 0,
|
|
PANEL_FM6126A,
|
|
};
|
|
|
|
class Hub75 {
|
|
public:
|
|
uint8_t width;
|
|
uint8_t height;
|
|
Pixel *front_buffer;
|
|
Pixel *back_buffer;
|
|
bool managed_buffer = false;
|
|
bool running = false;
|
|
PanelType panel_type;
|
|
|
|
// DMA & PIO
|
|
uint dma_channel = 0;
|
|
volatile bool do_flip = false;
|
|
uint bit = 0;
|
|
uint row = 0;
|
|
|
|
PIO pio = pio0;
|
|
uint sm_data = 0;
|
|
uint sm_row = 1;
|
|
|
|
uint data_prog_offs = 0;
|
|
uint row_prog_offs = 0;
|
|
|
|
|
|
// Top half of display - 16 rows on a 32x32 panel
|
|
unsigned int pin_r0 = 0;
|
|
unsigned int pin_g0 = 1;
|
|
unsigned int pin_b0 = 2;
|
|
|
|
// Bottom half of display - 16 rows on a 64x64 panel
|
|
unsigned int pin_r1 = 3;
|
|
unsigned int pin_g1 = 4;
|
|
unsigned int pin_b1 = 5;
|
|
|
|
// Address pins, 5 lines = 2^5 = 32 values (max 64x64 display)
|
|
unsigned int pin_row_a = 6;
|
|
unsigned int pin_row_b = 7;
|
|
unsigned int pin_row_c = 8;
|
|
unsigned int pin_row_d = 9;
|
|
unsigned int pin_row_e = 10;
|
|
|
|
// Sundry things
|
|
unsigned int pin_clk = 11; // Clock
|
|
unsigned int pin_stb = 12; // Strobe/Latch
|
|
unsigned int pin_oe = 13; // Output Enable
|
|
|
|
const bool clk_polarity = 1;
|
|
const bool stb_polarity = 1;
|
|
const bool oe_polarity = 0;
|
|
|
|
// User buttons and status LED
|
|
unsigned int pin_sw_a = 14;
|
|
unsigned int pin_sw_user = 23;
|
|
|
|
unsigned int pin_led_r = 16;
|
|
unsigned int pin_led_g = 17;
|
|
unsigned int pin_led_b = 18;
|
|
|
|
Hub75(uint8_t width, uint8_t height, Pixel *buffer) : Hub75(width, height, buffer, PANEL_GENERIC) {};
|
|
Hub75(uint8_t width, uint8_t height, Pixel *buffer, PanelType panel_type);
|
|
~Hub75();
|
|
|
|
void FM6126A_write_register(uint16_t value, uint8_t position);
|
|
void FM6126A_setup();
|
|
void set_rgb(uint8_t x, uint8_t y, uint8_t r, uint8_t g, uint8_t b);
|
|
void set_hsv(uint8_t x, uint8_t 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 dma_complete();
|
|
}; |