Skip to content

Commit f57ec8a

Browse files
committed
led_matrix: add initial stub for proper library
1 parent 008c3d2 commit f57ec8a

File tree

1 file changed

+196
-1
lines changed

1 file changed

+196
-1
lines changed

libraries/LED_Matrix/src/LED_Matrix.h

Lines changed: 196 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,196 @@
1-
// placeholder at the moment
1+
#include "Arduino.h"
2+
#include "FspTimer.h"
3+
4+
#define NUM_LEDS 96
5+
6+
static const int pin_zero_index = 28;
7+
8+
static const uint8_t pins[][2] = {
9+
{ 7, 3 }, // 0
10+
{ 3, 7 },
11+
{ 7, 4 },
12+
{ 4, 7 },
13+
{ 3, 4 },
14+
{ 4, 3 },
15+
{ 7, 8 },
16+
{ 8, 7 },
17+
{ 3, 8 },
18+
{ 8, 3 },
19+
{ 4, 8 }, // 10
20+
{ 8, 4 },
21+
{ 7, 0 },
22+
{ 0, 7 },
23+
{ 3, 0 },
24+
{ 0, 3 },
25+
{ 4, 0 },
26+
{ 0, 4 },
27+
{ 8, 0 },
28+
{ 0, 8 },
29+
{ 7, 6 }, // 20
30+
{ 6, 7 },
31+
{ 3, 6 },
32+
{ 6, 3 },
33+
{ 4, 6 },
34+
{ 6, 4 },
35+
{ 8, 6 },
36+
{ 6, 8 },
37+
{ 0, 6 },
38+
{ 6, 0 },
39+
{ 7, 5 }, // 30
40+
{ 5, 7 },
41+
{ 3, 5 },
42+
{ 5, 3 },
43+
{ 4, 5 },
44+
{ 5, 4 },
45+
{ 8, 5 },
46+
{ 5, 8 },
47+
{ 0, 5 },
48+
{ 5, 0 },
49+
{ 6, 5 }, // 40
50+
{ 5, 6 },
51+
{ 7, 1 },
52+
{ 1, 7 },
53+
{ 3, 1 },
54+
{ 1, 3 },
55+
{ 4, 1 },
56+
{ 1, 4 },
57+
{ 8, 1 },
58+
{ 1, 8 },
59+
{ 0, 1 }, // 50
60+
{ 1, 0 },
61+
{ 6, 1 },
62+
{ 1, 6 },
63+
{ 5, 1 },
64+
{ 1, 5 },
65+
{ 7, 2 },
66+
{ 2, 7 },
67+
{ 3, 2 },
68+
{ 2, 3 },
69+
{ 4, 2 },
70+
{ 2, 4 },
71+
{ 8, 2 },
72+
{ 2, 8 },
73+
{ 0, 2 },
74+
{ 2, 0 },
75+
{ 6, 2 },
76+
{ 2, 6 },
77+
{ 5, 2 },
78+
{ 2, 5 },
79+
{ 1, 2 },
80+
{ 2, 1 },
81+
{ 7, 10 },
82+
{ 10, 7 },
83+
{ 3, 10 },
84+
{ 10, 3 },
85+
{ 4, 10 },
86+
{ 10, 4 },
87+
{ 8, 10 },
88+
{ 10, 8 },
89+
{ 0, 10 },
90+
{ 10, 0 },
91+
{ 6, 10 },
92+
{ 10, 6 },
93+
{ 5, 10 },
94+
{ 10, 5 },
95+
{ 1, 10 },
96+
{ 10, 1 },
97+
{ 2, 10 },
98+
{ 10, 2 },
99+
{ 7, 9 },
100+
{ 9, 7 },
101+
{ 3, 9 },
102+
{ 9, 3 },
103+
{ 4, 9 },
104+
{ 9, 4 },
105+
};
106+
107+
#define LED_MATRIX_PORT0_MASK ((1 << 3) | (1 << 4) | (1 << 11) | (1 << 12) | (1 << 13) | (1 << 15))
108+
#define LED_MATRIX_PORT2_MASK ((1 << 4) | (1 << 5) | (1 << 6) | (1 << 12) | (1 << 13))
109+
110+
static void turnLed(int idx, bool on) {
111+
R_PORT0->PCNTR1 &= ~((uint32_t) LED_MATRIX_PORT0_MASK);
112+
R_PORT2->PCNTR1 &= ~((uint32_t) LED_MATRIX_PORT2_MASK);
113+
114+
if (on) {
115+
bsp_io_port_pin_t pin_a = g_pin_cfg[pins[idx][0] + pin_zero_index].pin;
116+
R_PFS->PORT[pin_a >> 8].PIN[pin_a & 0xFF].PmnPFS =
117+
IOPORT_CFG_PORT_DIRECTION_OUTPUT | IOPORT_CFG_PORT_OUTPUT_HIGH;
118+
119+
bsp_io_port_pin_t pin_c = g_pin_cfg[pins[idx][1] + pin_zero_index].pin;
120+
R_PFS->PORT[pin_c >> 8].PIN[pin_c & 0xFF].PmnPFS =
121+
IOPORT_CFG_PORT_DIRECTION_OUTPUT | IOPORT_CFG_PORT_OUTPUT_LOW;
122+
}
123+
}
124+
125+
static uint32_t reverse(uint32_t x)
126+
{
127+
x = ((x >> 1) & 0x55555555u) | ((x & 0x55555555u) << 1);
128+
x = ((x >> 2) & 0x33333333u) | ((x & 0x33333333u) << 2);
129+
x = ((x >> 4) & 0x0f0f0f0fu) | ((x & 0x0f0f0f0fu) << 4);
130+
x = ((x >> 8) & 0x00ff00ffu) | ((x & 0x00ff00ffu) << 8);
131+
x = ((x >> 16) & 0xffffu) | ((x & 0xffffu) << 16);
132+
return x;
133+
}
134+
135+
// TODO: this is dangerous, use with care
136+
#define load(x) load_wrapper(x, sizeof(x))
137+
138+
static uint8_t __attribute__((aligned)) framebuffer[NUM_LEDS / 8];
139+
140+
class LED_Matrix {
141+
142+
public:
143+
LED_Matrix() {}
144+
// TODO: find a better name
145+
// autoscroll will be slower than calling next() at precise times
146+
void autoscroll(uint32_t interval_ms) {
147+
_interval = interval_ms;
148+
}
149+
void on(size_t pin) {
150+
turnLed(pin, true);
151+
}
152+
void off(size_t pin) {
153+
turnLed(pin, false);
154+
}
155+
void begin() {
156+
uint8_t type;
157+
uint8_t ch = FspTimer::get_available_timer(type);
158+
// TODO: avoid passing "this" argument to remove autoscroll
159+
led_timer.begin(TIMER_MODE_PERIODIC, type, ch, 10000.0, 50.0, turnOnLedISR, this);
160+
led_timer.setup_overflow_irq();
161+
led_timer.open();
162+
led_timer.start();
163+
}
164+
void next() {
165+
uint32_t frame[3];
166+
static int j = 0;
167+
frame[0] = reverse(*(_frames+(j*3)+0));
168+
frame[1] = reverse(*(_frames+(j*3)+1));
169+
frame[2] = reverse(*(_frames+(j*3)+2));
170+
j = (j + 1) % _lines;
171+
memcpy(framebuffer, (uint32_t*)frame, sizeof(frame));
172+
}
173+
void load_wrapper(const uint32_t frames[][3], uint32_t howMany) {
174+
_frames = (uint32_t*)frames;
175+
_lines = (howMany / 3) / sizeof(uint32_t);
176+
}
177+
private:
178+
uint32_t* _frames;
179+
uint32_t _lines;
180+
uint32_t _interval = 0;
181+
uint32_t _last_interval = 0;
182+
FspTimer led_timer;
183+
184+
static void turnOnLedISR(timer_callback_args_t *arg) {
185+
static volatile int i_isr = 0;
186+
turnLed(i_isr, ((framebuffer[i_isr >> 3] & (1 << (i_isr % 8))) != 0));
187+
i_isr = (i_isr + 1) % NUM_LEDS;
188+
if (arg != nullptr && arg->p_context != nullptr) {
189+
LED_Matrix* _m = (LED_Matrix*)arg->p_context;
190+
if (_m->_interval != 0 && millis() - _m->_last_interval > _m->_interval) {
191+
_m->next();
192+
_m->_last_interval = millis();
193+
}
194+
}
195+
}
196+
};

0 commit comments

Comments
 (0)