@@ -133,14 +133,15 @@ static uint32_t reverse(uint32_t x)
133
133
}
134
134
135
135
// TODO: this is dangerous, use with care
136
- #define load (x ) load_wrapper(x, sizeof (x))
136
+ #define loadSequence (frames ) loadWrapper(frames, sizeof (frames))
137
+ #define renderBitmap (bitmap, rows, columns ) loadPixels(&bitmap[0 ][0 ], rows*columns)
137
138
138
139
static uint8_t __attribute__ ((aligned)) framebuffer[NUM_LEDS / 8];
139
140
140
- class LED_Matrix {
141
+ class ArduinoLEDMatrix {
141
142
142
143
public:
143
- LED_Matrix () {}
144
+ ArduinoLEDMatrix () {}
144
145
// TODO: find a better name
145
146
// autoscroll will be slower than calling next() at precise times
146
147
void autoscroll (uint32_t interval_ms) {
@@ -156,41 +157,102 @@ class LED_Matrix {
156
157
uint8_t type;
157
158
uint8_t ch = FspTimer::get_available_timer (type);
158
159
// 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 ();
160
+ _ledTimer .begin (TIMER_MODE_PERIODIC, type, ch, 10000.0 , 50.0 , turnOnLedISR, this );
161
+ _ledTimer .setup_overflow_irq ();
162
+ _ledTimer .open ();
163
+ _ledTimer .start ();
163
164
}
164
165
void next () {
165
166
uint32_t frame[3 ];
166
- static int j = 0 ;
167
- frame[0 ] = reverse (*(_frames+(j*4 )+0 ));
168
- frame[1 ] = reverse (*(_frames+(j*4 )+1 ));
169
- frame[2 ] = reverse (*(_frames+(j*4 )+2 ));
170
- _interval = *(_frames+(j*4 )+3 );
171
- j = (j + 1 ) % _lines;
167
+ frame[0 ] = reverse (*(_frames+(_currentFrame*4 )+0 ));
168
+ frame[1 ] = reverse (*(_frames+(_currentFrame*4 )+1 ));
169
+ frame[2 ] = reverse (*(_frames+(_currentFrame*4 )+2 ));
170
+ _interval = *(_frames+(_currentFrame*4 )+3 );
171
+ _currentFrame = (_currentFrame + 1 ) % _framesCount;
172
+ if (_currentFrame == 0 ){
173
+ if (!_loop){
174
+ _interval = 0 ;
175
+ }
176
+ if (_callBack != nullptr ){
177
+ _callBack ();
178
+ _sequenceDone = true ;
179
+ }
180
+ }
172
181
memcpy (framebuffer, (uint32_t *)frame, sizeof (frame));
173
182
}
174
- void load_wrapper (const uint32_t frames[][4 ], uint32_t howMany) {
183
+ void loadFrame (const uint32_t buffer[3 ]){
184
+ uint32_t tempBuffer[][4 ] = {{
185
+ buffer[0 ], buffer[1 ], buffer[2 ], 0
186
+ }};
187
+ loadSequence (tempBuffer);
188
+ next ();
189
+ _interval = 0 ;
190
+ }
191
+ void renderFrame (uint8_t frameNumber){
192
+ _currentFrame = frameNumber % _framesCount;
193
+ next ();
194
+ _interval = 0 ;
195
+ }
196
+ void play (bool loop = false ){
197
+ _loop = loop;
198
+ _sequenceDone = false ;
199
+ next ();
200
+ }
201
+ bool sequenceDone (){
202
+ if (_sequenceDone){
203
+ _sequenceDone = false ;
204
+ return true ;
205
+ }
206
+ return false ;
207
+ }
208
+
209
+ void loadPixels (uint8_t *arr, size_t size){
210
+ uint32_t partialBuffer = 0 ;
211
+ uint8_t pixelIndex = 0 ;
212
+ uint8_t *frameP = arr;
213
+ uint32_t *frameHolderP = _frameHolder;
214
+ while (pixelIndex < size) {
215
+ partialBuffer |= *frameP++;
216
+ if ((pixelIndex + 1 ) % 32 == 0 ) {
217
+ *(frameHolderP++) = partialBuffer;
218
+ }
219
+ partialBuffer = partialBuffer << 1 ;
220
+ pixelIndex++;
221
+ }
222
+ loadFrame (_frameHolder);
223
+ };
224
+
225
+ void loadWrapper (const uint32_t frames[][4 ], uint32_t howMany) {
226
+ _currentFrame = 0 ;
175
227
_frames = (uint32_t *)frames;
176
- _lines = (howMany / 4 ) / sizeof (uint32_t );
228
+ _framesCount = (howMany / 4 ) / sizeof (uint32_t );
229
+ }
230
+ // WARNING: callbacks are fired from ISR. The execution time will be limited.
231
+ void setCallback (voidFuncPtr callBack){
232
+ _callBack = callBack;
177
233
}
234
+
178
235
private:
236
+ int _currentFrame = 0 ;
237
+ uint32_t _frameHolder[3 ];
179
238
uint32_t * _frames;
180
- uint32_t _lines ;
239
+ uint32_t _framesCount ;
181
240
uint32_t _interval = 0 ;
182
- uint32_t _last_interval = 0 ;
183
- FspTimer led_timer;
241
+ uint32_t _lastInterval = 0 ;
242
+ bool _loop = false ;
243
+ FspTimer _ledTimer;
244
+ bool _sequenceDone = false ;
245
+ voidFuncPtr _callBack;
184
246
185
247
static void turnOnLedISR (timer_callback_args_t *arg) {
186
248
static volatile int i_isr = 0 ;
187
249
turnLed (i_isr, ((framebuffer[i_isr >> 3 ] & (1 << (i_isr % 8 ))) != 0 ));
188
250
i_isr = (i_isr + 1 ) % NUM_LEDS;
189
251
if (arg != nullptr && arg->p_context != nullptr ) {
190
- LED_Matrix * _m = (LED_Matrix *)arg->p_context ;
191
- if (_m->_interval != 0 && millis () - _m->_last_interval > _m->_interval ) {
252
+ ArduinoLEDMatrix * _m = (ArduinoLEDMatrix *)arg->p_context ;
253
+ if (_m->_interval != 0 && millis () - _m->_lastInterval > _m->_interval ) {
192
254
_m->next ();
193
- _m->_last_interval = millis ();
255
+ _m->_lastInterval = millis ();
194
256
}
195
257
}
196
258
}
0 commit comments