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
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
|
/*********************************************************************
* AnimatedGif LED Matrix Panel example where the GIFs are
* stored on a SD card connected to the ESP32 using the
* standard GPIO pins used for SD card acces via. SPI.
*
* Put the gifs into a directory called 'gifs' (case sensitive) on
* a FAT32 formatted SDcard.
********************************************************************/
#include "FS.h"
#include "SD.h"
#include "SPI.h"
#include <ESP32-HUB75-MatrixPanel-I2S-DMA.h>
#include <AnimatedGIF.h>
/********************************************************************
* Pin mapping below is for LOLIN D32 (ESP 32)
*
* Default pin mapping used by this library is NOT compatable with the use of the
* ESP32-Arduino 'SD' card library (there is overlap). As such, some of the pins
* used for the HUB75 panel need to be shifted.
*
* 'SD' card library requires GPIO 23, 18 and 19
* https://github.com/espressif/arduino-esp32/tree/master/libraries/SD
*
*/
/*
* Connect the SD card to the following pins:
*
* SD Card | ESP32
* D2 -
* D3 SS
* CMD MOSI
* VSS GND
* VDD 3.3V
* CLK SCK
* VSS GND
* D0 MISO
* D1 -
*/
/**** SD Card GPIO mappings ****/
#define SS_PIN 5
//#define MOSI_PIN 23
//#define MISO_PIN 19
//#define CLK_PIN 18
/**** HUB75 GPIO mapping ****/
// GPIO 34+ are on the ESP32 are input only!!
// https://randomnerdtutorials.com/esp32-pinout-reference-gpios/
#define A_PIN 33 // remap esp32 library default from 23 to 33
#define B_PIN 32 // remap esp32 library default from 19 to 32
#define C_PIN 22 // remap esp32 library defaultfrom 5 to 22
//#define R1_PIN 25 // library default for the esp32, unchanged
//#define G1_PIN 26 // library default for the esp32, unchanged
//#define B1_PIN 27 // library default for the esp32, unchanged
//#define R2_PIN 14 // library default for the esp32, unchanged
//#define G2_PIN 12 // library default for the esp32, unchanged
//#define B2_PIN 13 // library default for the esp32, unchanged
//#define D_PIN 17 // library default for the esp32, unchanged
//#define E_PIN -1 // IMPORTANT: Change to a valid pin if using a 64x64px panel.
//#define LAT_PIN 4 // library default for the esp32, unchanged
//#define OE_PIN 15 // library default for the esp32, unchanged
//#define CLK_PIN 16 // library default for the esp32, unchanged
/***************************************************************
* HUB 75 LED DMA Matrix Panel Configuration
**************************************************************/
#define PANEL_RES_X 64 // Number of pixels wide of each INDIVIDUAL panel module.
#define PANEL_RES_Y 32 // Number of pixels tall of each INDIVIDUAL panel module.
#define PANEL_CHAIN 1 // Total number of panels chained one to another
/**************************************************************/
AnimatedGIF gif;
MatrixPanel_I2S_DMA *dma_display = nullptr;
static int totalFiles = 0; // GIF files count
static File FSGifFile; // temp gif file holder
static File GifRootFolder; // directory listing
std::vector<std::string> GifFiles; // GIF files path
const int maxGifDuration = 30000; // ms, max GIF duration
#include "gif_functions.hpp"
#include "sdcard_functions.hpp"
/**************************************************************/
void draw_test_patterns();
int gifPlay( const char* gifPath )
{ // 0=infinite
if( ! gif.open( gifPath, GIFOpenFile, GIFCloseFile, GIFReadFile, GIFSeekFile, GIFDraw ) ) {
log_n("Could not open gif %s", gifPath );
}
Serial.print("Playing: "); Serial.println(gifPath);
int frameDelay = 0; // store delay for the last frame
int then = 0; // store overall delay
while (gif.playFrame(true, &frameDelay)) {
then += frameDelay;
if( then > maxGifDuration ) { // avoid being trapped in infinite GIF's
//log_w("Broke the GIF loop, max duration exceeded");
break;
}
}
gif.close();
return then;
}
void setup()
{
Serial.begin(115200);
// **************************** Setup SD Card access via SPI ****************************
if(!SD.begin(SS_PIN)){
// bool begin(uint8_t ssPin=SS, SPIClass &spi=SPI, uint32_t frequency=4000000, const char * mountpoint="/sd", uint8_t max_files=5, bool format_if_empty=false);
Serial.println("Card Mount Failed");
return;
}
uint8_t cardType = SD.cardType();
if(cardType == CARD_NONE){
Serial.println("No SD card attached");
return;
}
Serial.print("SD Card Type: ");
if(cardType == CARD_MMC){
Serial.println("MMC");
} else if(cardType == CARD_SD){
Serial.println("SDSC");
} else if(cardType == CARD_SDHC){
Serial.println("SDHC");
} else {
Serial.println("UNKNOWN");
}
uint64_t cardSize = SD.cardSize() / (1024 * 1024);
Serial.printf("SD Card Size: %lluMB\n", cardSize);
//listDir(SD, "/", 1, false);
Serial.printf("Total space: %lluMB\n", SD.totalBytes() / (1024 * 1024));
Serial.printf("Used space: %lluMB\n", SD.usedBytes() / (1024 * 1024));
// **************************** Setup DMA Matrix ****************************
HUB75_I2S_CFG mxconfig(
PANEL_RES_X, // module width
PANEL_RES_Y, // module height
PANEL_CHAIN // Chain length
);
// Need to remap these HUB75 DMA pins because the SPI SDCard is using them.
// Otherwise the SD Card will not work.
mxconfig.gpio.a = A_PIN;
mxconfig.gpio.b = B_PIN;
mxconfig.gpio.c = C_PIN;
// mxconfig.gpio.d = D_PIN;
//mxconfig.clkphase = false;
//mxconfig.driver = HUB75_I2S_CFG::FM6126A;
// Display Setup
dma_display = new MatrixPanel_I2S_DMA(mxconfig);
// Allocate memory and start DMA display
if( not dma_display->begin() )
Serial.println("****** !KABOOM! HUB75 memory allocation failed ***********");
dma_display->setBrightness8(128); //0-255
dma_display->clearScreen();
// **************************** Setup Sketch ****************************
Serial.println("Starting AnimatedGIFs Sketch");
// SD CARD STOPS WORKING WITH DMA DISPLAY ENABLED>...
File root = SD.open("/gifs");
if(!root){
Serial.println("Failed to open directory");
return;
}
File file = root.openNextFile();
while(file){
if(!file.isDirectory())
{
Serial.print(" FILE: ");
Serial.print(file.name());
Serial.print(" SIZE: ");
Serial.println(file.size());
std::string filename = "/gifs/" + std::string(file.name());
Serial.println(filename.c_str());
GifFiles.push_back( filename );
// Serial.println("Adding to gif list:" + String(filename));
totalFiles++;
}
file = root.openNextFile();
}
file.close();
Serial.printf("Found %d GIFs to play.", totalFiles);
//totalFiles = getGifInventory("/gifs");
// This is important - Set the right endianness.
gif.begin(LITTLE_ENDIAN_PIXELS);
}
void loop(){
// Iterate over a vector using range based for loop
for(auto & elem : GifFiles)
{
gifPlay( elem.c_str() );
gif.reset();
delay(500);
}
}
void draw_test_patterns()
{
// fix the screen with green
dma_display->fillRect(0, 0, dma_display->width(), dma_display->height(), dma_display->color444(0, 15, 0));
delay(500);
// draw a box in yellow
dma_display->drawRect(0, 0, dma_display->width(), dma_display->height(), dma_display->color444(15, 15, 0));
delay(500);
// draw an 'X' in red
dma_display->drawLine(0, 0, dma_display->width()-1, dma_display->height()-1, dma_display->color444(15, 0, 0));
dma_display->drawLine(dma_display->width()-1, 0, 0, dma_display->height()-1, dma_display->color444(15, 0, 0));
delay(500);
// draw a blue circle
dma_display->drawCircle(10, 10, 10, dma_display->color444(0, 0, 15));
delay(500);
// fill a violet circle
dma_display->fillCircle(40, 21, 10, dma_display->color444(15, 0, 15));
delay(500);
delay(1000);
}
|