aboutsummaryrefslogtreecommitdiff
path: root/examples/AnimatedGIFPanel_SD/AnimatedGIFPanel_SD.ino
blob: 9612244fc28f39917a76375ab75e3bfcfa3ab9c8 (plain)
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);

}