Efficient coding needed.

Hi,

This is another of my posts where I've actually got something that works, I just want to make it work better.

I'm trying to create AT commands for use talking to a modem, to save space I want store the string themselves in program memory, and access each command by a number. I start by storing the strings in memory....

// AT commands for satellite modem.
const prog_char SAT_COM_000[]      PROGMEM = "AT+";     // Standard commmand prefix.
const prog_char SAT_COM_001[]      PROGMEM = "=";       // Use 'equals' when setting a value
const prog_char SAT_COM_002[]      PROGMEM = "?";       // Use '?' when querying a value.
const prog_char SAT_COM_522[]      PROGMEM = "CIER";    // 5.22 +CIER – Indicator Event Reporting
const prog_char SAT_COM_523[]      PROGMEM = "CRIS";    // 5.23 +CRIS – Ring Indication Status
const prog_char SAT_COM_533[]      PROGMEM = "SBDWT";   // 5.33 +SBDWT – Short Burst Data: Write a Text Message to the Module

And then I have a function to populate my command buffer atCmd[] with the command that corresponds to the number in the name of the constant.......

void SatModem::formATcmd(int cmdNum, bool set, int val1)
{
  atCmd[0]=0;                    // Flush the current contents of the buffer
  strcpy_P(atCmd,SAT_COM_000);   // Start with "AT+"
  switch (cmdNum)                // Add a command string that corresponds to the command number.... 
  {
    case 522:
      strcat_P(atCmd,SAT_COM_522);
      break;
    case 523:
      strcat_P(atCmd,SAT_COM_523);
      break;
    case 533:
      strcat_P(atCmd,SAT_COM_533);
      break;
    default:
      //"E - Satellite modem uncoded AT command."
      strcpy_P(_info,SAT_MOD_08);
      logging(_info);   // Display to screen, or log to SD card
      break;
  }

  // Choose between a set, or a query command
  if (set==true)
  {
    strcat_P(atCmd,SAT_COM_001); // Stick a '=' on the end
  }
  else
  {
    strcat_P(atCmd,SAT_COM_002); // Stick a '?' on the end
  }

  // Append a numeric value to the end (if specified)
  if (val1 >=0)
  {
    sprintf(_info,"%d",val1);   // convert val1 into a string in the general purpose buffer
    strcat(atCmd,_info);
  }
}

As you can see, it's a simple little function, but the case statement is going to get very large as I add more and more commands to the list. Is there a better way of doing this? Maybe someway I can the command number to directly reference the progmem constant I'm after?

Thanks

atCmd[0]=0; ... not needed as the second line creates a string (OK no big optimization)
strcpy_P(atCmd,SAT_COM_000); // Start with "AT+"

If you can map the command numbers to 1,2,3,4,5 ... you can make an array of strings which makes the selection easier.

// not working but to get the idea

void SatModem::formATcmd(int cmdNum, bool set, int val1)
{
  sprintf(atCmd,"AT+%s%c", satcom[ func(cmdNum) ], set ? '=' : '?'); // satcom being the array of strings, func the mapping function.

  // Append a numeric value to the end (if specified)
  if (val1 >=0)
  {
    sprintf(_info,"%d",val1);   // convert val1 into a string in the general purpose buffer
    strcat(atCmd, _info);
  }
}

command2index[10] = { 8, 522, 523, 533, ... }
int func(int cmd)
{
  for int idx = 0; idx < 10; idx++)
  {
     if ( command2index[idx] == cmd ) return idx;
  }
  return 0;  // 0 is the error index.
}