Reading serial data into an array of filenames

Passing data between a Mega and a Teensy 4.1. I have a banner message char Banner[19] on the Mega which I fill up from Serial3 from the Teensy using Serial3.readByes(). That works fine. Then the Teensy passes a load of 19 character long file names to the Mega which I have to read one character at a time then put into a 2-D array of char (uint8_t). This works fine the first time I do it, but something gets screwed up when I try to read the file names a second or subsequent time. I was hoping to use readBytes() to read in the filenames and fill up an array of file names but can’t work out how to declare the array.

Currently I have

uint8_t  FileNames[MaxNumOfFiles][19];
char Banner[19];

and to fill Banner I do

    if(Serial3.available() > 0) {  //  interrupt routine for data from T4.1
      Serial3.readBytes(Banner, 18);     //
      Serial.println(Banner); 
    }

// Filling the FileNames array I do :

  if(Serial3.available() > 0) {  //  interrupt routine for data from Teensy
    incomingbyte = Serial3.read();     // remember this is ASCII code - 49 = '1'
    while (incomingbyte != 0x03F) {     // looking for next ? char
      incomingbyte = Serial3.read();     
    }
    if (incomingbyte == 0x03F) {    // file data is coming over
      for (uint8_t d = 0; d < MaxNumOfFiles; d++)   {
        for (uint8_t e = 0; e < 19; e++)  { 
          FileData[d][e] = Serial3.read();
        }  
      } 
    Serial3.flush();
    } 
  }

// this works fine first time, but never again. 

How do I declare an array of File names?
Ideally something like 

char FileNamesArray[filenames][MaxNumOfFiles];

You can probably tell I'm not very good at this!
Any help greatly appreciated

curious why you say your passing a filename and not data that goes into a file.

i would suggest reading a line of data and then processing the entire line rather that reading and processing a byte at a time.

looks like 0x3F, '?' is a start byte and then you expect MaxNumFiles of 19 chars to follow.

reading type-length-values, TLVs would be more reliable and flexible. you could have separate types for each msg

You would do

char FileNames[MaxNumOfFiles][maxFileNameLength+1]; 

I would suggest to study Serial Input Basics to handle getting the input and use end markers like \n (new line) to separate the various messages

Note that flush() only applies to the serial transmit buffer, it does nothing with the receive buffer.

Note that you are blindly reading from Serial3, regardless of whether or not there are any characters in the receive buffer. I would be surprised if you ever receive more than about 3 1/2 file names, since you will quickly empty the receive buffer and read a bunch of -1 values for the rest of the array.

Can you explain/describe what the data stream your reading “looks like” a little better?

look this over

you'll likely think this is too much code to just receive some data, but it provides some format checking, recovery and the framework for handling different messages

char s [90];

// -----------------------------------------------------------------------------
const int MaxName = 10;
const int NameLen = 20;

char names [MaxName][NameLen] = {};

// -------------------------------------
void
loadName (
    int   idx,
    byte *val,
    int   len )
{
    memcpy (& names [idx][0], val, len);
    names [idx][len] = '\0';
}

// -------------------------------------
void
dispNames ()
{
    for (int i = 0; i < MaxName; i++)  {
        sprintf (s, "    %2d: ", i);
        Serial.print   (s);
        Serial.println (& names [i][0]);
    }
}

// -----------------------------------------------------------------------------
void
processTlv (
    byte  type,
    byte  len,
    byte *val )
{
    sprintf (s, "processTlv: type %c, len %d, %s", type, len, val);
    Serial.println (s);

    switch (type)  {
    case 'A':
        loadName (0, val, len);
        break;

    case 'B':
        loadName (1, val, len);
        break;

    case 'D':
        dispNames ();
        break;
    }
}

// -------------------------------------
bool
validLen (
    byte len )
{
    return len < 50;
}

// -------------------------------------
bool
validType (
    byte type )
{
    return 'A' <= type && type <= 'G';
}

// -------------------------------------
void chkSerial ()
{
    static byte type = 0;
    static byte len  = 0;
    static byte val [90];
    static byte idx  = 0;

    if (Serial.available ())  {
        byte c = Serial.read ();
        if (len) {
            val [idx++] = c;
            if (len == idx)  {
                val [idx] = '\0';       // terminate string with nul
                processTlv (type, len, val);
                type = len = idx = 0;
            }
        }
        else if (type)  {
            len = c - '0';          //  - '0'  for testing
            if (0 == len)  {
                processTlv (type, len, val);
                type = len = idx = 0;
            }

            if (! validLen (len))  {
                Serial.println ("chkSerial: invalid length");
                type = len = idx = 0;
            }
        }
        else if (validType (c))
            type = c;
        else
            Serial.println ("chkSerial: invalid type");
    }
}

// -----------------------------------------------------------------------------
void loop ()
{
    chkSerial ();
}

// -----------------------------------------------------------------------------
void setup ()
{
    Serial.begin (9600);
}

Thankyou for your inputs. I’ll take a look at TLVs and Serial Input Basics. Why filenames and not actual file data? Reason is the list of files on the T4.1 has to be displayed on the Mega screen so one can be chosen to be played or deleted (they are all audio files with file names generated using date and time), e.g. 28-01 14:52.wav042 is passed as a file recorded on 28 Jan at 14:52 and is 42 minutes long.