-
Notifications
You must be signed in to change notification settings - Fork 24
/
Copy pathdoublebuffer_scrolltext.ino
212 lines (189 loc) · 8.5 KB
/
doublebuffer_scrolltext.ino
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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
/* ----------------------------------------------------------------------
Double-buffering (smooth animation) Protomatter library example.
PLEASE SEE THE "simple" EXAMPLE FOR AN INTRODUCTORY SKETCH.
Comments here pare down many of the basics and focus on the new concepts.
This example is written for a 64x32 matrix but can be adapted to others.
------------------------------------------------------------------------- */
#include <Adafruit_Protomatter.h>
#include <Fonts/FreeSansBold18pt7b.h> // Large friendly font
/* ----------------------------------------------------------------------
The RGB matrix must be wired to VERY SPECIFIC pins, different for each
microcontroller board. This first section sets that up for a number of
supported boards.
------------------------------------------------------------------------- */
#if defined(_VARIANT_MATRIXPORTAL_M4_) // MatrixPortal M4
uint8_t rgbPins[] = {7, 8, 9, 10, 11, 12};
uint8_t addrPins[] = {17, 18, 19, 20, 21};
uint8_t clockPin = 14;
uint8_t latchPin = 15;
uint8_t oePin = 16;
#elif defined(ARDUINO_ADAFRUIT_MATRIXPORTAL_ESP32S3) // MatrixPortal ESP32-S3
uint8_t rgbPins[] = {42, 41, 40, 38, 39, 37};
uint8_t addrPins[] = {45, 36, 48, 35, 21};
uint8_t clockPin = 2;
uint8_t latchPin = 47;
uint8_t oePin = 14;
#elif defined(_VARIANT_FEATHER_M4_) // Feather M4 + RGB Matrix FeatherWing
uint8_t rgbPins[] = {6, 5, 9, 11, 10, 12};
uint8_t addrPins[] = {A5, A4, A3, A2};
uint8_t clockPin = 13;
uint8_t latchPin = 0;
uint8_t oePin = 1;
#elif defined(__SAMD51__) // M4 Metro Variants (Express, AirLift)
uint8_t rgbPins[] = {6, 5, 9, 11, 10, 12};
uint8_t addrPins[] = {A5, A4, A3, A2};
uint8_t clockPin = 13;
uint8_t latchPin = 0;
uint8_t oePin = 1;
#elif defined(_SAMD21_) // Feather M0 variants
uint8_t rgbPins[] = {6, 7, 10, 11, 12, 13};
uint8_t addrPins[] = {0, 1, 2, 3};
uint8_t clockPin = SDA;
uint8_t latchPin = 4;
uint8_t oePin = 5;
#elif defined(NRF52_SERIES) // Special nRF52840 FeatherWing pinout
uint8_t rgbPins[] = {6, A5, A1, A0, A4, 11};
uint8_t addrPins[] = {10, 5, 13, 9};
uint8_t clockPin = 12;
uint8_t latchPin = PIN_SERIAL1_RX;
uint8_t oePin = PIN_SERIAL1_TX;
#elif USB_VID == 0x239A && USB_PID == 0x8113 // Feather ESP32-S3 No PSRAM
// M0/M4/RP2040 Matrix FeatherWing compatible:
uint8_t rgbPins[] = {6, 5, 9, 11, 10, 12};
uint8_t addrPins[] = {A5, A4, A3, A2};
uint8_t clockPin = 13; // Must be on same port as rgbPins
uint8_t latchPin = RX;
uint8_t oePin = TX;
#elif USB_VID == 0x239A && USB_PID == 0x80EB // Feather ESP32-S2
// M0/M4/RP2040 Matrix FeatherWing compatible:
uint8_t rgbPins[] = {6, 5, 9, 11, 10, 12};
uint8_t addrPins[] = {A5, A4, A3, A2};
uint8_t clockPin = 13; // Must be on same port as rgbPins
uint8_t latchPin = RX;
uint8_t oePin = TX;
#elif defined(ESP32)
// 'Safe' pins, not overlapping any peripherals:
// GPIO.out: 4, 12, 13, 14, 15, 21, 27, GPIO.out1: 32, 33
// Peripheral-overlapping pins, sorted from 'most expendible':
// 16, 17 (RX, TX)
// 25, 26 (A0, A1)
// 18, 5, 9 (MOSI, SCK, MISO)
// 22, 23 (SCL, SDA)
uint8_t rgbPins[] = {4, 12, 13, 14, 15, 21};
uint8_t addrPins[] = {16, 17, 25, 26};
uint8_t clockPin = 27; // Must be on same port as rgbPins
uint8_t latchPin = 32;
uint8_t oePin = 33;
#elif defined(ARDUINO_TEENSY40)
uint8_t rgbPins[] = {15, 16, 17, 20, 21, 22}; // A1-A3, A6-A8, skip SDA,SCL
uint8_t addrPins[] = {2, 3, 4, 5};
uint8_t clockPin = 23; // A9
uint8_t latchPin = 6;
uint8_t oePin = 9;
#elif defined(ARDUINO_TEENSY41)
uint8_t rgbPins[] = {26, 27, 38, 20, 21, 22}; // A12-14, A6-A8
uint8_t addrPins[] = {2, 3, 4, 5};
uint8_t clockPin = 23; // A9
uint8_t latchPin = 6;
uint8_t oePin = 9;
#elif defined(ARDUINO_ADAFRUIT_FEATHER_RP2040)
// RP2040 support requires the Earle Philhower board support package;
// will not compile with the Arduino Mbed OS board package.
// The following pinout works with the Adafruit Feather RP2040 and
// original RGB Matrix FeatherWing (M0/M4/RP2040, not nRF version).
// Pin numbers here are GP## numbers, which may be different than
// the pins printed on some boards' top silkscreen.
uint8_t rgbPins[] = {8, 7, 9, 11, 10, 12};
uint8_t addrPins[] = {25, 24, 29, 28};
uint8_t clockPin = 13;
uint8_t latchPin = 1;
uint8_t oePin = 0;
#endif
/* ----------------------------------------------------------------------
Matrix initialization is explained EXTENSIVELY in "simple" example sketch!
It's very similar here, but we're passing "true" for the last argument,
enabling double-buffering -- this permits smooth animation by having us
draw in a second "off screen" buffer while the other is being shown.
------------------------------------------------------------------------- */
Adafruit_Protomatter matrix(
64, // Matrix width in pixels
6, // Bit depth -- 6 here provides maximum color options
1, rgbPins, // # of matrix chains, array of 6 RGB pins for each
4, addrPins, // # of address pins (height is inferred), array of pins
clockPin, latchPin, oePin, // Other matrix control pins
true); // HERE IS THE MAGIC FOR DOUBLE-BUFFERING!
// Sundry globals used for animation ---------------------------------------
int16_t textX; // Current text position (X)
int16_t textY; // Current text position (Y)
int16_t textMin; // Text pos. (X) when scrolled off left edge
char str[64]; // Buffer to hold scrolling message text
int16_t ball[3][4] = {
{ 3, 0, 1, 1 }, // Initial X,Y pos+velocity of 3 bouncy balls
{ 17, 15, 1, -1 },
{ 27, 4, -1, 1 }
};
uint16_t ballcolor[3]; // Colors for bouncy balls (init in setup())
// SETUP - RUNS ONCE AT PROGRAM START --------------------------------------
void setup(void) {
Serial.begin(9600);
// Initialize matrix...
ProtomatterStatus status = matrix.begin();
Serial.print("Protomatter begin() status: ");
Serial.println((int)status);
if(status != PROTOMATTER_OK) {
// DO NOT CONTINUE if matrix setup encountered an error.
for(;;);
}
// Unlike the "simple" example, we don't do any drawing in setup().
// But we DO initialize some things we plan to animate...
// Set up the scrolling message...
sprintf(str, "Adafruit %dx%d RGB LED Matrix",
matrix.width(), matrix.height());
matrix.setFont(&FreeSansBold18pt7b); // Use nice bitmap font
matrix.setTextWrap(false); // Allow text off edge
matrix.setTextColor(0xFFFF); // White
int16_t x1, y1;
uint16_t w, h;
matrix.getTextBounds(str, 0, 0, &x1, &y1, &w, &h); // How big is it?
textMin = -w; // All text is off left edge when it reaches this point
textX = matrix.width(); // Start off right edge
textY = matrix.height() / 2 - (y1 + h / 2); // Center text vertically
// Note: when making scrolling text like this, the setTextWrap(false)
// call is REQUIRED (to allow text to go off the edge of the matrix),
// AND it must be BEFORE the getTextBounds() call (or else that will
// return the bounds of "wrapped" text).
// Set up the colors of the bouncy balls.
ballcolor[0] = matrix.color565(0, 20, 0); // Dark green
ballcolor[1] = matrix.color565(0, 0, 20); // Dark blue
ballcolor[2] = matrix.color565(20, 0, 0); // Dark red
}
// LOOP - RUNS REPEATEDLY AFTER SETUP --------------------------------------
void loop(void) {
// Every frame, we clear the background and draw everything anew.
// This happens "in the background" with double buffering, that's
// why you don't see everything flicker. It requires double the RAM,
// so it's not practical for every situation.
matrix.fillScreen(0); // Fill background black
// Draw the big scrolly text
matrix.setCursor(textX, textY);
matrix.print(str);
// Update text position for next frame. If text goes off the
// left edge, reset its position to be off the right edge.
if((--textX) < textMin) textX = matrix.width();
// Draw the three bouncy balls on top of the text...
for(byte i=0; i<3; i++) {
// Draw 'ball'
matrix.fillCircle(ball[i][0], ball[i][1], 5, ballcolor[i]);
// Update ball's X,Y position for next frame
ball[i][0] += ball[i][2];
ball[i][1] += ball[i][3];
// Bounce off edges
if((ball[i][0] == 0) || (ball[i][0] == (matrix.width() - 1)))
ball[i][2] *= -1;
if((ball[i][1] == 0) || (ball[i][1] == (matrix.height() - 1)))
ball[i][3] *= -1;
}
// AFTER DRAWING, A show() CALL IS REQUIRED TO UPDATE THE MATRIX!
matrix.show();
delay(20); // 20 milliseconds = ~50 frames/second
}