Weird bug, (SDFat, Multiplexing)

So I have made my own basic RGB format with no alpha, one byte for R, one byte for G, one byte for B.
And my display is a 24x15 RGB LED matrix, so 360 x 3 = 1080 bytes per frame. I wrote a Java program to scale down video and store it in this tiny resolution. The display is multiplexed using 74hc595s to open the columns, and TLC5940s to sink the rows.

So my file format was a file with 100 frames, so it took up 108KB.

When I run the code below with 100 frames, it plays the video, and gets to about frame 60 at a regular pace, and then the frame processing counter speeds up, and every LED just flashes red for the last 40 frames.

Then the SD code opens the next file, and the video starts playing again.

So I thought maybe 100 frames was too much for the Arduino Mega, so I changed my file format to 30 frames per file. But now, it gets to about frame 15 or so, and then the frame processing counter speeds up, flashing red for the last 15 frames.

Bizarre. So it's as though my program just messes up quicker, since i gave it less work to do. Makes no sense.

Any idea what it might be??

I set up the SDFat with SoftSPI, where the chipSelect pin is the SS pin of my SD shield.
if (!sd.begin(chipSelect, SPI_HALF_SPEED)) sd.initErrorHalt();

byte youtubebuffer[1080][3];

...

for (int numFiles = 1; numFiles < 20; numFiles++) 
  {
    char buff[10];
    sprintf( buff, "s_%d.dat", numFiles );
    if (!myFile.open(buff, O_READ)) {
      sd.errorHalt("opening s_0 for read failed");
    }
    Serial.println(buff);

    int bytesRead;
    byte r, g, b;

    for (int frame = 0; frame < 30; frame++)
    {
      for(int x = 0; x < 1080; x++)
      {
        //each byte holds a value from 0-255           
        youtubebuffer[x][0] = myFile.read();         
        youtubebuffer[x][1] = myFile.read();         
        youtubebuffer[x][2] = myFile.read();
      }     
      printBuffer(frame);

    }               

  myFile.close();
  Serial.write("Closed");
  }


void printBuffer(int counter)
{
  int r,g,b;
  int ndx = 0;
  
  for(int x = 0; x < 24; x++)
  {
//     Tlc.clear();
    openCol(x);
    for(int y = 0; y < 15; y++)
    {
      //each byte holds a value from 0-255           
      r = youtubebuffer[ndx][0] ;  
      g = youtubebuffer[ndx][1] ;  
      b = youtubebuffer[ndx][2] ;


      int red = getRedSinkValue(y);
      int green = red+1;
      int blue = red+2;  
      
      if (r != 0)
      {
        Tlc.set(red, r <<2);
      }
      else
      {
        Tlc.set(red, 0);
      }
      if (g != 0)
      {
        Tlc.set(green, g <<2);
      }
      else
      {
        Tlc.set(green, 0);
      }
      if (b != 0)
      {
        Tlc.set(blue, b <<2);
      }
      else
      {
        Tlc.set(blue, 0);
      }
      ndx++;
//            Serial.print(r);
//              Serial.print(" ");
//              Serial.print(g);
//              Serial.print(" ");
//              Serial.print(b);
//              Serial.print(" ");

//Serial.println(ndx);
    }

    Tlc.update(); 
  }
  
        Serial.print(counter);
        Serial.print("\n");
 

}
      if (r != 0)
      {
        Tlc.set(red, r <<2);
      }
      else
      {
        Tlc.set(red, 0);
      }

What is 0 left shifted by 2? Still 0, if my fat-fingered calculations are correct. I can't see why you have special handling for 0. 8 lines should be 0, 3 times.

Beyond that, all the for loops with magic numbers that don't mean anything to me means I can't help.

yeah, you're right about 0 shifted is 0.

I figured it had something to do with the buffer, that maybe the SD reading packs out half way, and the red flashing is because it was getting 0 and shifting it left was making it visible. It's possible actually, now that I think about it, that maybe if the SDFat library is maybe failing on myFile.read(), which returns an "int16_t", so it could be returning a negative number into my array, which is in twos complement, so it will have a 1 at the start, which means the colour setting code, which assumes numbers are positive, will display the negative number as a colour.

well I'll test my hypothesis. But it doesn't make sense why it's cool with doing 60 frames, and then only 15 frames when I make my loop smaller. weird bug man.

ps. the magic numbers i explained in the post...
24 x 15 is my resolution.
1080 is because a 24x15 frame is 360 pixels x 3 colours = 1080 bytes.
30 is the number of frames.

Ah ha so I was right, at least about the -1. I see also that the read returns an int16_t. I wonder why all the SDFat examples show it reading a byte. Maybe it's the same effect.

I've changed my code a bit, and at about frame 10, it starts outputting -1. So it's definitely an SD problem, at least. I wonder if it's a power issue, or a memory issue. I'll try give it dedicated power later this week and see if that helps.

  for (int numFiles = 1; numFiles < 20; numFiles++) 
  {
    char buff[10];
    sprintf( buff, "s_%d.dat", numFiles );
    if (!myFile.open(buff, O_READ)) {
      sd.errorHalt("opening s_0 for read failed");
    }
    Serial.println(buff);

    int bytesRead;
    int16_t r, g, b;

    for (int frame = 0; frame < 30; frame++)
    {
      for(int x = 0; x < 1080; x++)
      {
        //each byte holds a value from 0-255           
        r = myFile.read();         
        g = myFile.read();         
        b = myFile.read();

if (r < 0 || g < 0 || b < 0) {
              Serial.print(r);
              Serial.print(" ");
              Serial.print(g);
              Serial.print(" ");
              Serial.print(b);
              Serial.print(" ");
}
        youtubebuffer[x][0] = lowByte(r);         
        youtubebuffer[x][1] = lowByte(g);         
        youtubebuffer[x][2] = lowByte(b);
        
      }     
      printBuffer(frame);

    }               

 // close the file:
  myFile.close();
  Serial.write("Closed");


  }

One thing you should test before each read is that there is something to read - i.e. that you are not at the end of the file.

As for the magic numbers, use

#define RES_X 24
#define RES_Y 15

etc., and replace the numbers with the names. That way, you only encounter the magic numbers adjacent to the names.

Ok I worked out the bug. hehe i'm an idiot.
my buffer should be [360][3] (i've actually made it [1080] straight, so I can use the cleaner code:

while (( ok = myFile.read(youtubebuffer, 1080)) == 1080)
{
printBuffer(frame);
frame++;
}

now i've got a bug where it's not displaying green. But otherwise, it's playing my videos, and it's freaking amazing. would be better if it had green though.

Ok I worked out the bug. hehe i'm an idiot.

That can be a big bug to work around. 8)

while (( ok = myFile.read(youtubebuffer, 1080)) == 1080)

How is ok defined, and why would one expect a variable named ok to hold a value of 1080?

now i've got a bug where it's not displaying green.

Repeating the forum mantra just for drill: Post ALL of your code.

But otherwise, it's playing my videos, and it's freaking amazing.

So, post a video, damn it.

would be better if it had green though.

The grass is always greener on the other side. 8)