Skip to content

Commit 37c23e7

Browse files
committed
Add support for scrolling text asynchronously
1 parent 8b1c030 commit 37c23e7

File tree

3 files changed

+126
-9
lines changed

3 files changed

+126
-9
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// To use ArduinoGraphics APIs, please include BEFORE Arduino_LED_Matrix and TextAnimation
2+
#include "ArduinoGraphics.h"
3+
#include "Arduino_LED_Matrix.h"
4+
#include "TextAnimation.h"
5+
6+
ArduinoLEDMatrix matrix;
7+
8+
// 100 frames maximum. Compute as maximum length of text you want to print (eg. 20 chars)
9+
// multiplied by font width (eg. 5 for Font_5x7), so 20 chars * 5 px = 100. If you enter lower
10+
// value (or your text get unexpectedly long), animation will be cut and end soon.
11+
TEXT_ANIMATION_DEFINE(anim, 100)
12+
13+
int counter;
14+
bool requestNext = false;
15+
16+
void setup() {
17+
pinMode(LED_BUILTIN, OUTPUT);
18+
19+
matrix.begin();
20+
matrix.beginDraw();
21+
22+
matrix.stroke(0xFFFFFFFF);
23+
matrix.textFont(Font_5x7);
24+
matrix.textScrollSpeed(60);
25+
matrix.setCallback(matrixCallback);
26+
27+
const char text[] = " UNO r4 ";
28+
matrix.beginText(0, 1, 0xFFFFFF);
29+
matrix.println(text);
30+
matrix.endTextAnimation(SCROLL_LEFT, anim);
31+
32+
matrix.loadTextAnimationSequence(anim);
33+
matrix.play();
34+
35+
// now animation play asynchronously. Will call matrixCallback once completed.
36+
}
37+
38+
void matrixCallback() {
39+
// callback is executed in IRQ and should run as fast as possible
40+
requestNext = true;
41+
}
42+
43+
void loop() {
44+
if (requestNext) {
45+
requestNext = false;
46+
47+
matrix.beginText(0, 1, 0xFFFFFF);
48+
matrix.print(" ");
49+
matrix.println(counter);
50+
matrix.endTextAnimation(SCROLL_RIGHT, anim);
51+
52+
if (counter++ >= 20) {
53+
counter = 0;
54+
}
55+
56+
matrix.loadTextAnimationSequence(anim);
57+
matrix.play();
58+
}
59+
60+
delay(500);
61+
digitalWrite(LED_BUILTIN, 0);
62+
delay(500);
63+
digitalWrite(LED_BUILTIN, 1);
64+
}

Diff for: libraries/Arduino_LED_Matrix/src/Arduino_LED_Matrix.h

+47-9
Original file line numberDiff line numberDiff line change
@@ -141,8 +141,10 @@ static uint32_t reverse(uint32_t x)
141141
}
142142

143143
// TODO: this is dangerous, use with care
144-
#define loadSequence(frames) loadWrapper(frames, sizeof(frames))
145-
#define renderBitmap(bitmap, rows, columns) loadPixels(&bitmap[0][0], rows*columns)
144+
#define loadSequence(frames) loadWrapper(frames, sizeof(frames))
145+
#define renderBitmap(bitmap, rows, columns) loadPixels(&bitmap[0][0], rows*columns)
146+
#define endTextAnimation(scrollDirection, anim) endTextToAnimationBuffer(scrollDirection, anim ## _buf, sizeof(anim ## _buf), anim ## _buf_used)
147+
#define loadTextAnimationSequence(anim) loadWrapper(anim ## _buf, anim ## _buf_used)
146148

147149
static uint8_t __attribute__((aligned)) framebuffer[NUM_LEDS / 8];
148150

@@ -227,11 +229,11 @@ class ArduinoLEDMatrix
227229
return false;
228230
}
229231

230-
void loadPixels(uint8_t *arr, size_t size){
232+
static void loadPixelsToBuffer(uint8_t* arr, size_t size, uint32_t* dst) {
231233
uint32_t partialBuffer = 0;
232234
uint8_t pixelIndex = 0;
233235
uint8_t *frameP = arr;
234-
uint32_t *frameHolderP = _frameHolder;
236+
uint32_t *frameHolderP = dst;
235237
while (pixelIndex < size) {
236238
partialBuffer |= *frameP++;
237239
if ((pixelIndex + 1) % 32 == 0) {
@@ -240,6 +242,10 @@ class ArduinoLEDMatrix
240242
partialBuffer = partialBuffer << 1;
241243
pixelIndex++;
242244
}
245+
}
246+
247+
void loadPixels(uint8_t *arr, size_t size){
248+
loadPixelsToBuffer(arr, size, _frameHolder);
243249
loadFrame(_frameHolder);
244250
};
245251

@@ -255,9 +261,9 @@ class ArduinoLEDMatrix
255261

256262
void clear() {
257263
const uint32_t fullOff[] = {
258-
0x00000000,
259-
0x00000000,
260-
0x00000000
264+
0x00000000,
265+
0x00000000,
266+
0x00000000
261267
};
262268
loadFrame(fullOff);
263269
}
@@ -277,16 +283,48 @@ class ArduinoLEDMatrix
277283
renderBitmap(_canvasBuffer, canvasHeight, canvasWidth);
278284
}
279285

280-
// display the drawing
286+
// display the drawing or capture it to buffer when rendering dynamic anymation
281287
void endDraw() {
282288
ArduinoGraphics::endDraw();
283-
renderBitmap(_canvasBuffer, canvasHeight, canvasWidth);
289+
290+
if (!captureAnimation) {
291+
renderBitmap(_canvasBuffer, canvasHeight, canvasWidth);
292+
} else {
293+
if (captureAnimationHowManyRemains >= 4) {
294+
loadPixelsToBuffer(&_canvasBuffer[0][0], sizeof(_canvasBuffer), captureAnimationFrame);
295+
captureAnimationFrame[3] = _textScrollSpeed;
296+
captureAnimationFrame += 4;
297+
captureAnimationHowManyRemains -= 16;
298+
}
299+
}
300+
}
301+
302+
void endTextToAnimationBuffer(int scrollDirection, uint32_t frames[][4], uint32_t howManyMax, uint32_t& howManyUsed) {
303+
captureAnimationFrame = &frames[0][0];
304+
captureAnimationHowManyRemains = howManyMax;
305+
306+
captureAnimation = true;
307+
ArduinoGraphics::textScrollSpeed(0);
308+
ArduinoGraphics::endText(scrollDirection);
309+
ArduinoGraphics::textScrollSpeed(_textScrollSpeed);
310+
captureAnimation = false;
311+
312+
howManyUsed = howManyMax - captureAnimationHowManyRemains;
313+
}
314+
315+
void textScrollSpeed(unsigned long speed) {
316+
ArduinoGraphics::textScrollSpeed(speed);
317+
_textScrollSpeed = speed;
284318
}
285319

286320
private:
321+
uint32_t* captureAnimationFrame = nullptr;
322+
uint32_t captureAnimationHowManyRemains = 0;
323+
bool captureAnimation = false;
287324
static const byte canvasWidth = 12;
288325
static const byte canvasHeight = 8;
289326
uint8_t _canvasBuffer[canvasHeight][canvasWidth] = {{0}};
327+
unsigned long _textScrollSpeed = 100;
290328
#endif
291329

292330
private:

Diff for: libraries/Arduino_LED_Matrix/src/TextAnimation.h

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#pragma once
2+
3+
#include "Arduino.h"
4+
5+
#if not __has_include("ArduinoGraphics.h")
6+
#error "TextAnimation work only when ArduinoGraphics is installed and used. Include ArduinoGraphics first."
7+
#endif
8+
9+
#define TEXT_ANIMATION_DECLARE(NAME, MAX_CHARS) \
10+
extern uint32_t NAME ## _buf[MAX_CHARS][4]; \
11+
extern uint32_t NAME ## _buf_used;
12+
13+
#define TEXT_ANIMATION_DEFINE(NAME, MAX_CHARS) \
14+
uint32_t NAME ## _buf[MAX_CHARS][4]; \
15+
uint32_t NAME ## _buf_used = 0;

0 commit comments

Comments
 (0)