Mini Gif Player Black screen

General project help for Adafruit customers

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
fghelikopter1
 
Posts: 5
Joined: Sat Apr 01, 2023 7:37 am

Mini Gif Player Black screen

Post by fghelikopter1 »

Dear All
I am new to adafruit and wanted to use the Mini Gif players in a few Cockpit screens in a big radio controlled helicopter.
RP240 , 1,9" 170x320 ST7789
Always geet black screen , LCD lights up on side
Tried the code change did not work
#define TFT_CS 7
#define TFT_DC 8
#define TFT_RST 9
Checked wiring with multimeter , ok
used feather_rp2040_147_TFT, worked ok displayed graphics demo on all boards
Arduino Board 2.6.4
IDE 1.8.19
always get black screen
Now i am running out of ideas
Please help me
Kind regards Guenther

User avatar
mikeysklar
 
Posts: 13936
Joined: Mon Aug 01, 2016 8:10 pm

Re: Mini Gif Player Black screen

Post by mikeysklar »

A few questions.

1) Are you on a MacOS machine when copying the files over to the Feather RP2040? If so, the hidden .files "dot files" can be copied over as well and cause the mini gif player throw up a black screen.

Code: Select all

sudo mdutil -i off -d /Volumes/RPI-RP2
and clear out any invisible dot files manually (shift-command-. in finder)

2) Make sure you using the badger-172.gif only.

3) Do you have the PhilHower core board support package installed for Arduino? That is a necessary step mentioned in the guide, but only via link.

https://learn.adafruit.com/adafruit-fea ... -ide-setup

User avatar
fghelikopter1
 
Posts: 5
Joined: Sat Apr 01, 2023 7:37 am

Re: Mini Gif Player Black screen

Post by fghelikopter1 »

hi
Thank you for the answer
I found the solution in the post
Mine GIF Player: Only badger-320.gif works
there are many limitations on the GIFS
Now got it working
One point i was not able to figure out yet due my lack of programming skills
Play all the gifs in an endless loop
Still searching how to modify the code

User avatar
mikeysklar
 
Posts: 13936
Joined: Mon Aug 01, 2016 8:10 pm

Re: Mini Gif Player Black screen

Post by mikeysklar »

The code is set to play all the GIF files found 5 times. You can modify that value with changing:

Code: Select all

#define NUM_LOOPS 5
To go endlessly you would have to change this area of the code in the main loop(). You can change the code to a while(1) from a for() loop or reset loops back to zero.

Code: Select all

        // play thru n times
        for (int loops=0; loops<NUM_LOOPS; loops++) {
          while (gif.playFrame(true, NULL));
          gif.reset();
        }

User avatar
fghelikopter1
 
Posts: 5
Joined: Sat Apr 01, 2023 7:37 am

Re: Mini Gif Player Black screen

Post by fghelikopter1 »

Hi
Thank you very much for your help.
Due your help i am on the right way see attached.
Meanwhile one display died (no backlight anymore ), but i got new displays today:-)
What i did not figure out how to use a directory for the Gif files.
in Root directory i am somehow limited to 170 files max
it seems to be FAT 12 which is limited to 200 files .
Tried to format with FAT 32
but had no luck blue screen on display on program start
So i thought maybe
by creating a root directory called A and to place the files there i hoped to get rid of this limit .
i tried to modify #define GIFDIRNAME to multiple formats like "/A" " \A" or "//A" "\\A\" and numerous other combinations
did not work
Also searched for solutions in the forum but found no document how to format GIFDIRNAME
Attachments
cockpit.jpg
cockpit.jpg (27.17 KiB) Viewed 127 times

User avatar
mikeysklar
 
Posts: 13936
Joined: Mon Aug 01, 2016 8:10 pm

Re: Mini Gif Player Black screen

Post by mikeysklar »

The AnimatedGIF player appears to have support for other FAT based filesystems (16, 32, FATFS, etc.) beyond FAT12.

https://github.com/bitbank2/AnimatedGIF/search?q=fat12

Changing the default GIFDIRNAME is a little more involved because you cannot use a #define for a string like this just for a single characters.

; example code

Code: Select all

 #define GIFDIRNAME "/"
; change that will not work

Code: Select all

 #define GIFDIRNAME "/A/"
So need to create a character array or hard code the “/A”.

Code: Select all

char gifdirname[] = “/A/“;

User avatar
fghelikopter1
 
Posts: 5
Joined: Sat Apr 01, 2023 7:37 am

Re: Mini Gif Player Black screen

Post by fghelikopter1 »

Hello
Thanks for your help
In the meantime i got a few displays to replace the broken one
What do you mean with hard code
hard code the “/A”.
Everywhere i tried to replace in the code Gifdirname with “/A/“ had no success , Bluescreen

Code: Select all

// SPDX-FileCopyrightText: 2022 Limor Fried for Adafruit Industries
//
// SPDX-License-Identifier: MIT

#include <AnimatedGIF.h>
#include <SdFat.h>
#include <Adafruit_SPIFlash.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h> // Hardware-specific library for ST7735
#include <Adafruit_ST7789.h> // Hardware-specific library for ST7789

#define TFT_CS         7
#define TFT_DC         8
#define TFT_RST        9

#define DISPLAY_WIDTH 320
#define DISPLAY_HEIGHT 170

#define GIFDIRNAME "/"
#define NUM_LOOPS 2


#if defined(ARDUINO_ARCH_ESP32)
  // ESP32 use same flash device that store code.
  // Therefore there is no need to specify the SPI and SS
  Adafruit_FlashTransport_ESP32 flashTransport;

#elif defined(ARDUINO_ARCH_RP2040)
  // RP2040 use same flash device that store code for file system. Therefore we
  // only need to specify start address and size (no need SPI or SS)
  // By default (start=0, size=0), values that match file system setting in
  // 'Tools->Flash Size' menu selection will be used.
  // Adafruit_FlashTransport_RP2040 flashTransport;

  // To be compatible with CircuitPython partition scheme (start_address = 1 MB,
  // size = total flash - 1 MB) use const value (CPY_START_ADDR, CPY_SIZE) or
  // subclass Adafruit_FlashTransport_RP2040_CPY. Un-comment either of the
  // following line:
  //  Adafruit_FlashTransport_RP2040
  //    flashTransport(Adafruit_FlashTransport_RP2040::CPY_START_ADDR,
  //                   Adafruit_FlashTransport_RP2040::CPY_SIZE);
  Adafruit_FlashTransport_RP2040_CPY flashTransport;

#else
  // On-board external flash (QSPI or SPI) macros should already
  // defined in your board variant if supported
  // - EXTERNAL_FLASH_USE_QSPI
  // - EXTERNAL_FLASH_USE_CS/EXTERNAL_FLASH_USE_SPI
  #if defined(EXTERNAL_FLASH_USE_QSPI)
    Adafruit_FlashTransport_QSPI flashTransport;

  #elif defined(EXTERNAL_FLASH_USE_SPI)
    Adafruit_FlashTransport_SPI flashTransport(EXTERNAL_FLASH_USE_CS, EXTERNAL_FLASH_USE_SPI);

  #else
    #error No QSPI/SPI flash are defined on your board variant.h !
  #endif
#endif

Adafruit_SPIFlash flash(&flashTransport);

// file system object from SdFat
FatFileSystem fatfs;

Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);
AnimatedGIF gif;
File32 f, root;

void * GIFOpenFile(const char *fname, int32_t *pSize)
{
  f = fatfs.open(fname);
  if (f)
  {
    *pSize = f.size();
    return (void *)&f;
  }
  return NULL;
} /* GIFOpenFile() */

void GIFCloseFile(void *pHandle)
{
  File32 *f = static_cast<File32 *>(pHandle);
  if (f != NULL)
     f->close();
} /* GIFCloseFile() */

int32_t GIFReadFile(GIFFILE *pFile, uint8_t *pBuf, int32_t iLen)
{
    int32_t iBytesRead;
    iBytesRead = iLen;
    File32 *f = static_cast<File32 *>(pFile->fHandle);
    // Note: If you read a file all the way to the last byte, seek() stops working
    if ((pFile->iSize - pFile->iPos) < iLen)
       iBytesRead = pFile->iSize - pFile->iPos - 1; // <-- ugly work-around
    if (iBytesRead <= 0)
       return 0;
    iBytesRead = (int32_t)f->read(pBuf, iBytesRead);
    pFile->iPos = f->position();
    return iBytesRead;
} /* GIFReadFile() */

int32_t GIFSeekFile(GIFFILE *pFile, int32_t iPosition)
{ 
  int i = micros();
  File32 *f = static_cast<File32 *>(pFile->fHandle);
  f->seek(iPosition);
  pFile->iPos = (int32_t)f->position();
  i = micros() - i;
//  Serial.printf("Seek time = %d us\n", i);
  return pFile->iPos;
} /* GIFSeekFile() */

// Draw a line of image directly on the LCD
void GIFDraw(GIFDRAW *pDraw)
{
    uint8_t *s;
    uint16_t *d, *usPalette, usTemp[320];
    int x, y, iWidth;

    iWidth = pDraw->iWidth;
    // Serial.printf("Drawing %d pixels\n", iWidth);

    if (iWidth + pDraw->iX > DISPLAY_WIDTH)
       iWidth = DISPLAY_WIDTH - pDraw->iX;
    usPalette = pDraw->pPalette;
    y = pDraw->iY + pDraw->y; // current line
    if (y >= DISPLAY_HEIGHT || pDraw->iX >= DISPLAY_WIDTH || iWidth < 1)
       return; 
    s = pDraw->pPixels;
    if (pDraw->ucDisposalMethod == 2) // restore to background color
    {
      for (x=0; x<iWidth; x++)
      {
        if (s[x] == pDraw->ucTransparent)
           s[x] = pDraw->ucBackground;
      }
      pDraw->ucHasTransparency = 0;
    }

    // Apply the new pixels to the main image
    if (pDraw->ucHasTransparency) // if transparency used
    {
      uint8_t *pEnd, c, ucTransparent = pDraw->ucTransparent;
      int x, iCount;
      pEnd = s + iWidth;
      x = 0;
      iCount = 0; // count non-transparent pixels
      while(x < iWidth)
      {
        c = ucTransparent-1;
        d = usTemp;
        while (c != ucTransparent && s < pEnd)
        {
          c = *s++;
          if (c == ucTransparent) // done, stop
          {
            s--; // back up to treat it like transparent
          }
          else // opaque
          {
             *d++ = usPalette[c];
             iCount++;
          }
        } // while looking for opaque pixels
        if (iCount) // any opaque pixels?
        {
          tft.startWrite();
          tft.setAddrWindow(pDraw->iX+x, y, iCount, 1);
          tft.writePixels(usTemp, iCount, false, false);
          tft.endWrite();
          x += iCount;
          iCount = 0;
        }
        // no, look for a run of transparent pixels
        c = ucTransparent;
        while (c == ucTransparent && s < pEnd)
        {
          c = *s++;
          if (c == ucTransparent)
             iCount++;
          else
             s--; 
        }
        if (iCount)
        {
          x += iCount; // skip these
          iCount = 0;
        }
      }
    }
    else
    {
      s = pDraw->pPixels;
      // Translate the 8-bit pixels through the RGB565 palette (already byte reversed)
      for (x=0; x<iWidth; x++)
        usTemp[x] = usPalette[*s++];
      tft.startWrite();
      tft.setAddrWindow(pDraw->iX, y, iWidth, 1);
      tft.writePixels(usTemp, iWidth, false, false);
      tft.endWrite();
    }
} /* GIFDraw() */


void setup() {
  Serial.begin(115200);


  Serial.println("Adafruit SPIFlash Animated GIF Example");

  // Initialize flash library and check its chip ID.
  if (!flash.begin()) {
    Serial.println("Error, failed to initialize flash chip!");
    while(1);
  }
  Serial.print("Flash chip JEDEC ID: 0x"); Serial.println(flash.getJEDECID(), HEX);

  // First call begin to mount the filesystem.  Check that it returns true
  // to make sure the filesystem was mounted.
  if (!fatfs.begin(&flash)) {
    Serial.println("Failed to mount filesystem!");
    Serial.println("Was CircuitPython loaded on the board first to create the filesystem?");
    while(1);
  }
  Serial.println("Mounted filesystem!");

  if (!root.open(GIFDIRNAME)) {
    Serial.println("Open dir failed");
  }
  while (f.openNext(&root, O_RDONLY)) {
    f.printFileSize(&Serial);
    Serial.write(' ');
    f.printModifyDateTime(&Serial);
    Serial.write(' ');
    f.printName(&Serial);
    if (f.isDir()) {
      // Indicate a directory.
      Serial.write('/');
    }
    Serial.println();
    f.close();
  }
  root.close();
  
  tft.init(DISPLAY_HEIGHT, DISPLAY_WIDTH);
  tft.fillScreen(ST77XX_BLUE);
  tft.setRotation(1);
  gif.begin(LITTLE_ENDIAN_PIXELS);
}
void loop() {

  char thefilename[80];
  
  if (!root.open(GIFDIRNAME)) {
    Serial.println("Open GIF directory failed");
    while (1);
  }
  while (f.openNext(&root, O_RDONLY)) {
    f.printFileSize(&Serial);
    Serial.write(' ');
    f.printModifyDateTime(&Serial);
    Serial.write(' ');
    f.printName(&Serial);
    if (f.isDir()) {
      // Indicate a directory.
      Serial.write('/');
    }
    Serial.println();
    f.getName(thefilename, sizeof(thefilename)-1);
    f.close();
    if (strstr(thefilename, ".gif") || strstr(thefilename, ".GIF")) {
      // found a gif mebe!
      if (gif.open(thefilename, GIFOpenFile, GIFCloseFile, GIFReadFile, GIFSeekFile, GIFDraw)) {
        GIFINFO gi;
        Serial.printf("Successfully opened GIF %s; Canvas size = %d x %d\n",  thefilename, gif.getCanvasWidth(), gif.getCanvasHeight());
        if (gif.getInfo(&gi)) {
          Serial.printf("frame count: %d\n", gi.iFrameCount);
          Serial.printf("duration: %d ms\n", gi.iDuration);
          Serial.printf("max delay: %d ms\n", gi.iMaxDelay);
          Serial.printf("min delay: %d ms\n", gi.iMinDelay);
        }
        // play thru n times
        for (int loops=0; loops<NUM_LOOPS; loops++) {
          while (gif.playFrame(true, NULL));
          gif.reset();
        }
        gif.close();
      } else {
        Serial.printf("Error opening file %s = %d\n", thefilename, gif.getLastError());
      }
    }
     }
root.close();
   }

User avatar
mikeysklar
 
Posts: 13936
Joined: Mon Aug 01, 2016 8:10 pm

Re: Mini Gif Player Black screen

Post by mikeysklar »

You need to change from using a #define to a character array char gifdirname[] when trying to give a path with multiple characters.

User avatar
fghelikopter1
 
Posts: 5
Joined: Sat Apr 01, 2023 7:37 am

Re: Mini Gif Player Black screen

Post by fghelikopter1 »

Hello
still getting a blue screen
tried multiple formats for subdirectory
always blue screen

Code: Select all


// SPDX-FileCopyrightText: 2022 Limor Fried for Adafruit Industries
//
// SPDX-License-Identifier: MIT

#include <AnimatedGIF.h>
#include <SdFat.h>
#include <Adafruit_SPIFlash.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h> // Hardware-specific library for ST7735
#include <Adafruit_ST7789.h> // Hardware-specific library for ST7789

#define TFT_CS         7
#define TFT_DC         8
#define TFT_RST        9

#define DISPLAY_WIDTH 320
#define DISPLAY_HEIGHT 170

char gifdirname[] = "/A/";
#define NUM_LOOPS 2


#if defined(ARDUINO_ARCH_ESP32)
  // ESP32 use same flash device that store code.
  // Therefore there is no need to specify the SPI and SS
  Adafruit_FlashTransport_ESP32 flashTransport;

#elif defined(ARDUINO_ARCH_RP2040)
  // RP2040 use same flash device that store code for file system. Therefore we
  // only need to specify start address and size (no need SPI or SS)
  // By default (start=0, size=0), values that match file system setting in
  // 'Tools->Flash Size' menu selection will be used.
  // Adafruit_FlashTransport_RP2040 flashTransport;

  // To be compatible with CircuitPython partition scheme (start_address = 1 MB,
  // size = total flash - 1 MB) use const value (CPY_START_ADDR, CPY_SIZE) or
  // subclass Adafruit_FlashTransport_RP2040_CPY. Un-comment either of the
  // following line:
  //  Adafruit_FlashTransport_RP2040
  //    flashTransport(Adafruit_FlashTransport_RP2040::CPY_START_ADDR,
  //                   Adafruit_FlashTransport_RP2040::CPY_SIZE);
  Adafruit_FlashTransport_RP2040_CPY flashTransport;

#else
  // On-board external flash (QSPI or SPI) macros should already
  // defined in your board variant if supported
  // - EXTERNAL_FLASH_USE_QSPI
  // - EXTERNAL_FLASH_USE_CS/EXTERNAL_FLASH_USE_SPI
  #if defined(EXTERNAL_FLASH_USE_QSPI)
    Adafruit_FlashTransport_QSPI flashTransport;

  #elif defined(EXTERNAL_FLASH_USE_SPI)
    Adafruit_FlashTransport_SPI flashTransport(EXTERNAL_FLASH_USE_CS, EXTERNAL_FLASH_USE_SPI);

  #else
    #error No QSPI/SPI flash are defined on your board variant.h !
  #endif
#endif

Adafruit_SPIFlash flash(&flashTransport);

// file system object from SdFat
FatFileSystem fatfs;

Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);
AnimatedGIF gif;
File32 f, root;

void * GIFOpenFile(const char *fname, int32_t *pSize)
{
  f = fatfs.open(fname);
  if (f)
  {
    *pSize = f.size();
    return (void *)&f;
  }
  return NULL;
} /* GIFOpenFile() */

void GIFCloseFile(void *pHandle)
{
  File32 *f = static_cast<File32 *>(pHandle);
  if (f != NULL)
     f->close();
} /* GIFCloseFile() */

int32_t GIFReadFile(GIFFILE *pFile, uint8_t *pBuf, int32_t iLen)
{
    int32_t iBytesRead;
    iBytesRead = iLen;
    File32 *f = static_cast<File32 *>(pFile->fHandle);
    // Note: If you read a file all the way to the last byte, seek() stops working
    if ((pFile->iSize - pFile->iPos) < iLen)
       iBytesRead = pFile->iSize - pFile->iPos - 1; // <-- ugly work-around
    if (iBytesRead <= 0)
       return 0;
    iBytesRead = (int32_t)f->read(pBuf, iBytesRead);
    pFile->iPos = f->position();
    return iBytesRead;
} /* GIFReadFile() */

int32_t GIFSeekFile(GIFFILE *pFile, int32_t iPosition)
{ 
  int i = micros();
  File32 *f = static_cast<File32 *>(pFile->fHandle);
  f->seek(iPosition);
  pFile->iPos = (int32_t)f->position();
  i = micros() - i;
//  Serial.printf("Seek time = %d us\n", i);
  return pFile->iPos;
} /* GIFSeekFile() */

// Draw a line of image directly on the LCD
void GIFDraw(GIFDRAW *pDraw)
{
    uint8_t *s;
    uint16_t *d, *usPalette, usTemp[320];
    int x, y, iWidth;

    iWidth = pDraw->iWidth;
    // Serial.printf("Drawing %d pixels\n", iWidth);

    if (iWidth + pDraw->iX > DISPLAY_WIDTH)
       iWidth = DISPLAY_WIDTH - pDraw->iX;
    usPalette = pDraw->pPalette;
    y = pDraw->iY + pDraw->y; // current line
    if (y >= DISPLAY_HEIGHT || pDraw->iX >= DISPLAY_WIDTH || iWidth < 1)
       return; 
    s = pDraw->pPixels;
    if (pDraw->ucDisposalMethod == 2) // restore to background color
    {
      for (x=0; x<iWidth; x++)
      {
        if (s[x] == pDraw->ucTransparent)
           s[x] = pDraw->ucBackground;
      }
      pDraw->ucHasTransparency = 0;
    }

    // Apply the new pixels to the main image
    if (pDraw->ucHasTransparency) // if transparency used
    {
      uint8_t *pEnd, c, ucTransparent = pDraw->ucTransparent;
      int x, iCount;
      pEnd = s + iWidth;
      x = 0;
      iCount = 0; // count non-transparent pixels
      while(x < iWidth)
      {
        c = ucTransparent-1;
        d = usTemp;
        while (c != ucTransparent && s < pEnd)
        {
          c = *s++;
          if (c == ucTransparent) // done, stop
          {
            s--; // back up to treat it like transparent
          }
          else // opaque
          {
             *d++ = usPalette[c];
             iCount++;
          }
        } // while looking for opaque pixels
        if (iCount) // any opaque pixels?
        {
          tft.startWrite();
          tft.setAddrWindow(pDraw->iX+x, y, iCount, 1);
          tft.writePixels(usTemp, iCount, false, false);
          tft.endWrite();
          x += iCount;
          iCount = 0;
        }
        // no, look for a run of transparent pixels
        c = ucTransparent;
        while (c == ucTransparent && s < pEnd)
        {
          c = *s++;
          if (c == ucTransparent)
             iCount++;
          else
             s--; 
        }
        if (iCount)
        {
          x += iCount; // skip these
          iCount = 0;
        }
      }
    }
    else
    {
      s = pDraw->pPixels;
      // Translate the 8-bit pixels through the RGB565 palette (already byte reversed)
      for (x=0; x<iWidth; x++)
        usTemp[x] = usPalette[*s++];
      tft.startWrite();
      tft.setAddrWindow(pDraw->iX, y, iWidth, 1);
      tft.writePixels(usTemp, iWidth, false, false);
      tft.endWrite();
    }
} /* GIFDraw() */


void setup() {
  Serial.begin(115200);


  Serial.println("Adafruit SPIFlash Animated GIF Example");

  // Initialize flash library and check its chip ID.
  if (!flash.begin()) {
    Serial.println("Error, failed to initialize flash chip!");
    while(1);
  }
  Serial.print("Flash chip JEDEC ID: 0x"); Serial.println(flash.getJEDECID(), HEX);

  // First call begin to mount the filesystem.  Check that it returns true
  // to make sure the filesystem was mounted.
  if (!fatfs.begin(&flash)) {
    Serial.println("Failed to mount filesystem!");
    Serial.println("Was CircuitPython loaded on the board first to create the filesystem?");
    while(1);
  }
  Serial.println("Mounted filesystem!");

  if (!root.open(gifdirname)) {
    Serial.println("Open dir failed");
  }
  while (f.openNext(&root, O_RDONLY)) {
    f.printFileSize(&Serial);
    Serial.write(' ');
    f.printModifyDateTime(&Serial);
    Serial.write(' ');
    f.printName(&Serial);
    if (f.isDir()) {
      // Indicate a directory.
      Serial.write('/');
    }
    Serial.println();
    f.close();
  }
  root.close();
  
  tft.init(DISPLAY_HEIGHT, DISPLAY_WIDTH);
  tft.fillScreen(ST77XX_BLUE);
  tft.setRotation(1);
  gif.begin(LITTLE_ENDIAN_PIXELS);
}
void loop() {

  char thefilename[80];
  
  if (!root.open(gifdirname)) {
    Serial.println("Open GIF directory failed");
    while (1);
  }
  while (f.openNext(&root, O_RDONLY)) {
    f.printFileSize(&Serial);
    Serial.write(' ');
    f.printModifyDateTime(&Serial);
    Serial.write(' ');
    f.printName(&Serial);
    if (f.isDir()) {
      // Indicate a directory.
      Serial.write('/');
    }
    Serial.println();
    f.getName(thefilename, sizeof(thefilename)-1);
    f.close();
    if (strstr(thefilename, ".gif") || strstr(thefilename, ".GIF")) {
      // found a gif mebe!
      if (gif.open(thefilename, GIFOpenFile, GIFCloseFile, GIFReadFile, GIFSeekFile, GIFDraw)) {
        GIFINFO gi;
        Serial.printf("Successfully opened GIF %s; Canvas size = %d x %d\n",  thefilename, gif.getCanvasWidth(), gif.getCanvasHeight());
        if (gif.getInfo(&gi)) {
          Serial.printf("frame count: %d\n", gi.iFrameCount);
          Serial.printf("duration: %d ms\n", gi.iDuration);
          Serial.printf("max delay: %d ms\n", gi.iMaxDelay);
          Serial.printf("min delay: %d ms\n", gi.iMinDelay);
        }
        // play thru n times
        for (int loops=0; loops<NUM_LOOPS; loops++) {
          while (gif.playFrame(true, NULL));
          gif.reset();
        }
        gif.close();
      } else {
        Serial.printf("Error opening file %s = %d\n", thefilename, gif.getLastError());
      }
    }
     }
root.close();
   }

Locked
Please be positive and constructive with your questions and comments.

Return to “General Project help”