Too Many Entries??

Hoping for a new start here. I've tried several versions of below, but any further entries past the 46th entry, including Case71() and below it, in the last section below (whether it's written as a switch/case or an if statement), and is always the same point. All variables are localized and set in each void, there are no other possible insertions of data or processes. The only thing that changes is the byte that is read from the Serial Device (slot machine) and can be a value of 0 to 155 (0x00 to 0x9B).

This has been written with either a single command entry (entering just a Case()) or with 15 lines of code with the same limited result of 46 variants. I've gone as far as commenting out the first section (any void with the term "SAS" in it) and still the second section cannot accept past the 46. There are no compile warnings or fails. Here's how much memory is used with ALL entries enabled, with no runtime.

Sketch uses 126698 bytes (49%) of program storage space. Maximum is 253952 bytes.
Global variables use 1657 bytes (20%) of dynamic memory, leaving 6535 bytes for local variables. Maximum is 8192 bytes.

Memory usage if I comment out beginning at entry #46 and then compile resulting in the program running:

Sketch uses 118814 bytes (46%) of program storage space. Maximum is 253952 bytes.
Global variables use 1655 bytes (20%) of dynamic memory, leaving 6537 bytes for local variables. Maximum is 8192 bytes.

Here's my setup and loop:

#include <SPI.h>
#include <SD.h>
#include <Ethernet.h>
#include <TextFinder.h>

//--- Items Requiring Global Usage
EthernetServer server(80);

//----- "Let's Roll!" - Todd Beamer, 09/11/2001 -----//

void setup() {
  Serial.begin(19200);
  Serial1.begin(19200);
  if (!SD.begin(4)) {
    ;
    return;
  }
  pinMode(4, OUTPUT);
  digitalWrite(4, HIGH);
  File myFile;
  uint8_t ip[4];
  myFile = SD.open("config.cfg"); {
    if (myFile) {
      ip[0] = myFile.parseInt();
      ip[1] = myFile.parseInt();
      ip[2] = myFile.parseInt();
      ip[3] = myFile.parseInt();
    }
    myFile.close();
    IPAddress ip (ip[0], ip[1], ip[2], ip[3]);
  }
  byte mac[] = {0xB0, 0x0B, 0xB0, 0x0B, 0xB0, 0x0B};
  Ethernet.begin(mac, ip);
  server.begin();
}
void loop() {

  checkForClient();

  getSASEvent();
}

Here's the two voids that process the single byte when no client is connected (running as a standalone). This works perfectly if the next section of code is clipped at 46 entries (written as either switch/case or if statements):

void getSASEvent() {
  byte SASByte[0];
  getSASCode(SASByte);
  if (SASByte[0] == 61) {
    byte SendByte[3];
    byte RecvByte[35];
    SendByte[0] = MachAdd;
    SendByte[1] = 0x4D;
    SendByte[2] = 0x00;
    SendTypeS(SendByte, 5);
    Serial1.readBytes(RecvByte, 35);
  }
  if (SASByte[0] == 81) {
    byte SendByte[2];
    byte RecvByte[24];
    SendByte[0] = MachAdd;
    SendByte[1] = 0x1B;
    SendTypeR(SendByte, 2);
    Serial1.readBytes(RecvByte, 24);
  }
  if (SASByte[0] == 87) {
    byte SendByte[11];
    byte RecvByte[10];
    SendByte[0] = MachAdd;
    SendByte[1] = 0x57;
    SendTypeR(SendByte, 2);
    Serial1.readBytes(RecvByte, 10);
    SendByte[0]  = MachAdd;
    SendByte[1]  = 0x58;
    SendByte[2]  = 0x01;
    SendByte[3]  = RecvByte[2];
    SendByte[4]  = 0x00;
    SendByte[5]  = 0x00;
    SendByte[6]  = RecvByte[3];
    SendByte[7]  = RecvByte[4];
    SendByte[8]  = RecvByte[5];
    SendByte[9]  = RecvByte[6];
    SendByte[10] = RecvByte[7];
    SendTypeS(SendByte, 13);
    Serial1.readBytes(RecvByte, 5);
  }
  if (SASByte[0] == 103) {
    byte SendByte[19];
    byte RecvByte[21];
    SendByte[0] = MachAdd;
    SendByte[1] = 0x70;
    SendTypeR(SendByte, 2);
    Serial1.readBytes(RecvByte, 21);
    SendByte[0] = MachAdd;
    SendByte[1] = 0x71;
    SendByte[2] = 0x10;
    SendByte[3] = 0x00;
    SendByte[4] = RecvByte[14];
    SendByte[5] = RecvByte[15];
    SendByte[6] = RecvByte[16];
    SendByte[7] = RecvByte[17];
    SendByte[8] = RecvByte[18];
    SendByte[9] = 0x00;
    SendByte[10] = RecvByte[10];
    SendByte[11] = RecvByte[11];
    SendByte[12] = RecvByte[12];
    SendByte[13] = RecvByte[13];
    SendByte[14] = RecvByte[14];
    SendByte[15] = RecvByte[15];
    SendByte[16] = RecvByte[16];
    SendByte[17] = RecvByte[17];
    SendByte[18] = RecvByte[18];
    SendTypeS(SendByte, 21);
    Serial1.readBytes(RecvByte, 21);
  }
  if (SASByte[0] == 104) {
    byte SendByte[4];
    byte RecvByte[6];
    SendByte[0] = MachAdd;
    SendByte[1] = 0x71;
    SendByte[2] = 0x01;
    SendByte[3] = 0xFF;
    SendTypeS(SendByte, 6);
    Serial.readBytes(RecvByte, 6);
  }
  if (SASByte[0] == 113) {
    byte SendByte[7];
    byte GSMACKNACK[1];
    SendByte[0] = MachAdd;
    SendByte[1] = 0x8A;
    SendByte[2] = 0x00;
    SendByte[3] = 0x01;
    SendByte[4] = 0x00;
    SendByte[5] = 0x00;
    SendByte[6] = 0x00;
    SendTypeS(SendByte, 9);
    Serial1.readBytes(GSMACKNACK, 1);
  }
}
void getSASCode(byte temp[]) {
  Serial1.read();
  UCSR1B = 0b10011101;
  Serial1.write(0x80);
  delay(20);
  Serial1.write(0x81);
  UCSR1B = 0b10011100;
  Serial1.readBytes(temp, 1);
}

Here's the second area. No other actions in the rest of the code have any affect this:

void getStatusCode(byte temp[]) {
  Serial1.read();
  UCSR1B = 0b10011101;
  Serial1.write(0x80);
  delay(20);
  Serial1.write(0x81);
  UCSR1B = 0b10011100;
  Serial1.readBytes(temp, 1);
}

This section of code calls the void shown above and it's only purpose is to display the Byte read (each Case()) with a client.println() statement from the Serial Device. This is the section that must be partially commented out for the program to run:

while (client.available()) {
   byte StatusByte[0];
   getStatusCode(StatusByte);
   int StatusInt = StatusByte[0];
   switch (StatusInt) {
     case 17:
       Case17();
       break;
     case 18:
       Case18();
       break;
     case 19:
       Case19();
       break;   (Had to clip due to 9000 character limit)
       
     case 70:
       Case70();
       break;
/*     case 71:   <--- This entry and below must be commented out.
       Case71();
       break;
     case 72:
       Case72();
       break;    (Clipped to save characters)

     case 154:
       Case154();
       break;
     case 155:
       Case155();
       break;  */

I just looked at another section of my code that deals with 67 (21 more than listed above) that doesn't interact with the Serial and uses an integer that is sent from a web page, then deals with the Serial device. That section of code does a ton more processing as well.

At this point, I don't know if I'm dealing with a timeout issue or if iterations are multiplied because of process to read the byte from the Serial Device.

I thought I had created enough of a "separation of function" to avoid this situation, but even combining the two "get*****Events" didn't help with the number of cases/ifs that can be dealt with. I'm still stuck at the number 46 in either situation.

Looking at the flow of your code,

when client is available, you call a function getStatusCode(StatusByte) and inside that function you do a serial read? What exactly are you reading from? another CPU? a sensor? It looks to me that you are running a webserver listening on port 80, and when you have a client connected, you read from a serial device.

And then after that, you write back to it

What exactly does this part does?

Serial1.read();
UCSR1B = 0b10011101;
Serial1.write(0x80);
delay(20);
Serial1.write(0x81);
UCSR1B = 0b10011100;
Serial1.readBytes(temp, 1);

hzrnbgy:
Looking at the flow of your code,

when client is available, you call a function getStatusCode(StatusByte) and inside that function you do a serial read? What exactly are you reading from? another CPU? a sensor? It looks to me that you are running a webserver listening on port 80, and when you have a client connected, you read from a serial device.

And then after that, you write back to it

What exactly does this part does?

Serial1.read();
UCSR1B = 0b10011101;
Serial1.write(0x80);
delay(20);
Serial1.write(0x81);
UCSR1B = 0b10011100;
Serial1.readBytes(temp, 1);

You are correct on the data flow. The serial device is a slot machine sending status codes constantly and what I'm having the Arduino read from.

The section you pointed out with the UCSR1B is sending a "wake up" bit to the slot machine to tell it to send it's latest status code ('0') if nothing is happening. Each one of the 155 possible codes is something the machine is announcing (to whoever is listening) what is currently happening with it.

In an unrelated section of the code, the webserver is running for, and supporting, a webpage for a user to connect to. It passes that status code received to one of the webpages generated by the Arduino. The web interface also allows for a user to make changes to the slot machine (i.e. System Time, what's printed on a voucher, Enable/Disable certain games, etc.) There are over 75 commands that someone can select from to control or view different internal meters the machine tracks.

The part that is giving me hell is the Status Page. It's read only by the user, and it's only purpose is to highlight an icon if something has changed ($1 bill inserted, CMOS Failure, Voucher Paid, etc). There are about 80 icons I'm trying to control, but currently I can't due to some limitation I can't seem to fix.

This two statement kind of contradicts each other

You are correct on the data flow. The serial device is a slot machine sending status codes constantly and what I'm having the Arduino read from.

The section you pointed out with the UCSR1B is sending a "wake up" bit to the slot machine to tell it to send it's latest status code ('0') if nothing is happening

Is the slot machines constantly sending status or do you have to "wake" it up for it to send it's status? The reason why I'm asking is maybe you can leverage a "serial received interrupt" to have the Arduino just listen and update a variable so it does not have to query the slot machine and save you some delays (as part of your function). What could happen is a new Ethernet client pops out while you are inside the delay and you can't respond to it.

hzrnbgy:
This two statement kind of contradicts each other
Is the slot machines constantly sending status or do you have to "wake" it up for it to send it's status? The reason why I'm asking is maybe you can leverage a "serial received interrupt" to have the Arduino just listen and update a variable so it does not have to query the slot machine and save you some delays (as part of your function). What could happen is a new Ethernet client pops out while you are inside the delay and you can't respond to it.

I can see why it looks like I contradicted myself. The machine is only sends that status code only after it receives that 'wakeup' bit (which tells the slot machine 'someone' is listening). It is constantly sending out a 'ping' (sorta say) and why the first line reads Serial1.read. If the Arduino 'hears' that ping, it immediately sends out the 0x80 and 0x81 (wake-up bit) and the second Serial1.read will get the actual status code the machine is sending out.

  Serial1.read();
  UCSR1B = 0b10011101;
  Serial1.write(0x80);
  delay(20);
  Serial1.write(0x81);
  UCSR1B = 0b10011100;
  Serial1.readBytes(temp, 1);

I've tried to setup ArduinoJson to actually do that. Unfortunately, I could not "breakout" just the status code from the other data being sent in the Json stream. I even purchased the book from the guy to make sure I wasn't screwing something up. His email response confirmed my dilemma and that it wouldn't work.

I believe I've figured out there is actually a memory allocation limit for the process I'm having a problem with. I changed everything back to IF statements from CASES again. I found that if I commented out the 'larger' IF statements (just like the 'larger' CASE statements prior), I was able to include more of the 'smaller' IF statements. With the 'larger' statements commented out I was able to get a total of 60 instead of the original 46 I was stuck at.

A sample of the 'larger' IF statements that were commented out:

if (SASByte[0] == 72) client.print(F("<script>btn43.style.backgroundColor='#32CD32'; btn42.style.backgroundColor='#808080'; btn44.style.backgroundColor='#808080';\n"
                         "btn45.style.backgroundColor='#808080'; btn46.style.backgroundColor='#808080'; btn47.style.backgroundColor='#808080';\n"
                         "btn48.style.backgroundColor='#808080'; btn17.style.backgroundColor='#808080'; btn17.style.color='#FFFFFF'; btn18.style.backgroundColor='#808080';\n"

And what the single line, 'smaller' IF statements look like:

if (SASByte[0] == 61) client.print(F("<script>btn33.style.backgroundColor='#32CD32'</script>\n"));

As a side note, putting the 'larger' statements into PROGMEM made no difference to the number of statements that did not require being commented out. It'd be great to find out if a 'tweaking' in the compiler will get me past this roadblock. This is the last thing in this program to fix (saving the best for last, maybe?). LOL

Here's a change I did to the void using the IF statements. I also moved 'byte SASByte[0]' and 'EthernetClient client = server.available()' to make them Global (removed about 2K in program size). The commented out entry referred to a 1341 character long string.

void getSASEvent() {
  getSASCode(SASByte);
  if (SASByte[0] == 17) client.print(F("<script>btn1.style.backgroundColor='#FF0000'</script>\n"));
//  if (SASByte[0] == 18) client.print(strcpy_P(CaseNbr, (char *)pgm_read_word(&(string_table[1]))));
  if (SASByte[0] == 19) client.print(F("<script>btn2.style.backgroundColor='#FF0000'</script>\n"));
  if (SASByte[0] == 20) client.print(F("<script>btn2.style.backgroundColor='#808080'</script>\n"));
  if (SASByte[0] == 21) client.print(F("<script>btn3.style.backgroundColor='#FF0000'</script>\n"));

Going on a hunch, I decided to try another compiler and found there is a difference between them. I'm guessing I need to try out several to see which one works best? Recommendations are welcome.

There's not much of a difference, but it matters. The first is the Arduino IDE v1.8.13 and the second is the vMicro plug-in for the Microchip Studio 7. The Arduino IDE compiled a size 280 bytes larger. The vMicro plug-in also allowed for an additional line in my IF statements (I'll be changing everything back to switch/case to see if that improves the results).

Arduino IDE 1.8.13 -

Sketch uses 118078 bytes (46%) of program storage space. Maximum is 253952 bytes.
Global variables use 1670 bytes (20%) of dynamic memory, leaving 6522 bytes for local variables. Maximum is 8192 bytes.

vMicro plug-in for Microchip Studio 7 -

Program TryNumber4 size: 117,798 bytes (used 46% of a 253,952 byte maximum) (38.30 secs)
Minimum Memory Usage: 1670 bytes (20% of a 8192 byte maximum)