MMEx with SPI Slave to allow legacy devices to communicate with modern media such as USB, SD cards, the internet and all of the mbed\'s other interfaces

Dependencies:   NetServices MSCUsbHost mbed TMP102 SDFileSystem

pfuncs.cpp

Committer:
DeMein
Date:
2011-02-27
Revision:
0:67a55a82ce06

File content as of revision 0:67a55a82ce06:

/* MMEx for MBED - Parameter Command processing
 * Copyright (c) 2011 MK
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

/**
  \file pfuncs.cpp
  \brief Commands starting with P for processing Parameters
*/

#include "pfuncs.h"

string param[maxparams + 1];        // our array of parameter strings

/** translate the parameter character to its array index
 *
 *  @param C parameter character '0' to '9', 'E', etc
 *  @return index in Parameter array, -1 if C was not valid
 *
 */
int getpnum(char C) {

  switch (C) {
    case par_0:
    case par_1:
    case par_2:
    case par_3:
    case par_4:
    case par_5:
    case par_6:
    case par_7:
    case par_8:
    case par_9: return(C - '0');          
    case par_E: return(10); 
    case par_R: return(11);
    case par_S: return(12);
    case par_C: return(13);
    case par_X: return(14);
    case par_I: return(15);
    case par_J: return(16);
    case par_H: return(17);        
    case par_M: return(18);    
    case par_U: return(19);
    case par_N: return(20);
    case par_P: return(21);
    
    default:    return(-1);
  }
}  

/** translate the parameter index to its character value
 *
 *  @param pnum index in Parameter array, -1 if C was not valid
 *  @return parameter character '0' to '9', 'E', etc 
 *
 */
char getnump(int pnum) {
  switch (pnum) {
    case  0: return('0');
    case  1: return('1');
    case  2: return('2');
    case  3: return('3');
    case  4: return('4');
    case  5: return('5');
    case  6: return('6');
    case  7: return('7');
    case  8: return('8');
    case  9: return('9');
    case 10: return('E');
    case 11: return('R');
    case 12: return('S');
    case 13: return('C');
    case 14: return('X');
    case 15: return('I');
    case 16: return('J');
    case 17: return('H');
    case 18: return('M');
    case 19: return('U');
    case 20: return('N');
    case 21: return('P');
    default: return(NULL);
  }
}
 
/** main entry for parsing P-commands
 *
 */ 
void parse_P() {
  DBG_msg("parse_P", inbuf);

  if (inbuf[1] != NULL) {
    switch (inbuf[1]) {
      case pclear : do_pclear();      // clear parameter
                    break;       
      case pget   : do_pget();        // get parameter
                    break;         
      case pset   : do_pset();        // set parameter
                    break;               
      case plen   : do_plen();        // retrun the length of a parametr string
                    break;     
      case psave  : do_psave();       // save all parameters to LocalDisk
                    break;   
      case pread  : do_pread();       // read all parameters from LocalDisk
                    break;                   
      case pxeq   : do_pxeq();
                    break;                        
      default     : do_pdefault();    // command not recognized
                    break;
    }
  } else { do_pdefault(); }
}
         
/** clear a Parameter
 *
 *  syntax: PC [param]
 *  \n         [param]: one of the defined Parameters
 *
 */                  
void do_pclear() {
  int pnum = 0;
  
  DBG_msg("do_pclear", inbuf);
  
  wipesp(inbuf);
  pnum = getpnum(inbuf[2]);
  if (pnum >= 0) {
    DBG_int("clear parameter #", pnum);
    param[pnum].clear();
  } else { do_pdefault(); }
}

/** retrieve the value of a parameter
 *
 *  syntax: PG [param]
 *  \n         [param]: one of the defined Parameters
 *
 */  
void do_pget() {
  int pnum = 0;
  char * cstr;
      
  DBG_msg("do_pget", inbuf);
  
  wipesp(inbuf);
  pnum = getpnum(inbuf[2]);
  if (pnum >= 0) {
    cstr = new char [param[pnum].size() + 1];
    strcpy (cstr, param[pnum].c_str());
    DBG_int("get parameter #", pnum);  
    DBG_msg("get parameter: ", cstr);   
    upstring(cstr); 
    mldl.tx_string(cstr);  
    delete[] cstr;
  } else { do_pdefault(); }  
}

/** set the value of a parameter
 *
 *  syntax: PS [param][string] overwrites previous Parameter
 *  \n or PS [param]>+[string] to append to Parameter
 *  \n         [param]: one of the defined Parameters
 *
 */  
void do_pset() {
  int pnum = 0;
  
  DBG_msg("do_pset", inbuf);
  
  while (inbuf[2] == c_space) remchar(inbuf, 2, 1);  // remove the spaces
  
  pnum = getpnum(inbuf[2]);
  DBG_int("pnum", pnum);
  if (pnum >= 0) {
    // now retrieve string from the command line, i starts at 3
    DBG_int("set parameter #", pnum);
    
    // if first chars are not ">+" the string will be new
    if ((inbuf[3] == c_escape) && (inbuf[4] == c_append)) {      
      // string is append, remove first 5 chars (command and >+) from inbuf
      remchar(inbuf, 0, 5);
      DBG_msg("append parameter ", inbuf);
      param[pnum].append(inbuf);    
    } else {    
      remchar(inbuf, 0, 3);
      DBG_msg("new parameter ", inbuf);
      param[pnum].assign(inbuf);     // no append, assign string
    }
  } else { do_pdefault(); }      
}

/** return the length of a parameter string
 *
 *  syntax: PL [param]
 *  \n         [param]: one of the defined Parameters
 *
 */  
void do_plen() {
  int pnum = 0;
  char tmp[25];
  
  DBG_msg("do_plen", inbuf);
  
  wipesp(inbuf);
  pnum = getpnum(inbuf[2]);
  if (pnum >= 0) {
    DBG_int("parameter #", pnum);  
    sprintf(tmp,"%d", param[pnum].length()); 
    DBG_msg("parameter length ", tmp);   
    mldl.tx_string(tmp);  
  } else { do_pdefault(); }      
}  
  
/** save all parameters to LocalDisk, with filename PARAMS_[num].TXT
 *
 *  syntax: PV [num]
 *  \n         [num]: simngle digit or character
 * \n overwrites an existing file
 
 */   
void do_psave() {
  int pnum = 0;
  char fname[25];
  char * cstr;
 
  DBG_msg("do_psave", inbuf);   
    
  wipesp(inbuf);
  
  if (inbuf[2] != NULL) {   
    sprintf(fname, "/local/param_%c.txt", inbuf[2]);
    DBG_msg("create file ", fname);
    FILE *fp = fopen(fname, "w");  // Open file for writing
    if (fp != NULL) {
      for (pnum = 0; pnum <= maxparams; pnum++) {
        cstr = new char [param[pnum].size() + 1];        
        sprintf(cstr, "%c-", getnump(pnum));
        strcat (cstr, param[pnum].c_str());
        DBG_msg("saving ", cstr);
        fprintf(fp, "%s\n", cstr);        
        delete[] cstr;
      }
      fclose(fp);
    } else {
      // error opening file
      DBG_msg("do_psave", "file NOT opened");
      send_error(err_filenotopen);
    }
  } else {
    DBG_msg("do_psave", inbuf);
    send_error(err_novalidcommand);
  }
}    

/** read all parameters from LocalDisk, with filename PARAMS_[num].TXT
 *
 *  syntax: PR [num]
 *  \n         [num]: single digit or character
 *
 */  
void do_pread() {
  int pnum = 0;
  char fname[25];
  char cstr[511];  // maximum length per parameter
  
  DBG_msg("do_pread", inbuf);
  
  wipesp(inbuf);
  
  if (inbuf[2] != NULL) {
    sprintf(fname, "/local/param_%c.txt", inbuf[2]);  
    DBG_msg("open file ", fname);
    FILE *fp = fopen(fname, "r");  // Open file for reading
    if (fp != NULL) {
      for (pnum = 0; pnum <= maxparams; pnum++) {     
        DBG_int("param ", pnum);
        fgets(cstr, 511, fp);
        DBG_msg("read ", cstr);
        remchar(cstr, 0, 2);    // remove the firs 2 chars (parameter char)        
        param[pnum].assign(cstr);
        param[pnum].erase(param[pnum].end() - 1); // remove /n                    
      }
      fclose(fp);
    } else {
      // error opening file
      DBG_msg("do_pread", "file NOT opened");
      send_error(err_filenotopen);      
    }
  } else { 
    DBG_msg("do_pread", inbuf);
    send_error(err_novalidcommand);
  }
}    

/** Execute the chosen parameter string as an MMEx command
 *
 *  syntax: PX [param]
 *  \n         [param]: one of the defined Parameters
 *
 */                               
void do_pxeq() {
  int pnum = 0;
  int i;
  char * cstr;
  
  DBG_msg("do_pxeq", inbuf);  
  
  wipesp(inbuf);
  pnum = getpnum(inbuf[2]);
  if (((pnum >= 0) && (pnum <= 9)) || (pnum == par_C_) || (pnum == par_X_)) {
    // only for valid parameters
    cstr = new char [param[pnum].size() + 1];
    strcpy (cstr, param[pnum].c_str());
    DBG_int("xeq parameter #", pnum);  
    DBG_msg("xeq parameter: ", cstr);    
    
    if (mldl.rx_room() >= (param[pnum].length() + 1)) {
      DBG_int("init XQ", mldl.rx_room());
      // enough room in our rx buffer
      i = 0;
      while (cstr[i] != NULL) {
        // add to buffer
        mldl.rx_add(cstr[i]);
        DBG_chr("XQ add", cstr[i]);
        i++;
      }
      mldl.rx_add(c_cr);
    } else {
      // not enough room
      DBG_msg("do_pxeq", "rx buffer full");
      send_error(err_paramnoxeq);
    }
    delete[] cstr;
  } else {
    if (pnum == par_R_) {
      // RPC function to execute
      do_pdefault();
    } else { do_pdefault(); }  
  }
}   
                        
/** automatic all parameters from LocalDisk on startup, with filename PARAMS_A.TXT
 *
 */ 
void init_loadp() {
  int pnum = 0;
  char cstr[511];  // maximum length per parameter
  
  DBG_msg("init_loadp", "PARAM_A.TXT");
 
  FILE *fp = fopen("/local/PARAM_A.TXT", "r");  // Open file for reading
  if (fp != NULL) {
    for (pnum = 0; pnum <= maxparams; pnum++) {     
      DBG_int("param ", pnum);
      fgets(cstr, 511, fp);
      DBG_msg("read ", cstr);
      remchar(cstr, 0, 2);    // remove the firs 2 chars (parameter char)        
      param[pnum].assign(cstr);
      param[pnum].erase(param[pnum].end() - 1); // remove /n                    
    }
    fclose(fp);
  } else {
    // error opening file
    DBG_msg("file not found", "PARAM_A.TXT");
    // send_error(err_filenotopen);      // no error sent on startup
  }
}      

/** execute the auto execute string in Parameter X on startup if it exists
 *
 */   
void init_xeq() {
  int pnum = 0;
  int i;
  char * cstr;
  
  DBG_msg("init_xeq", "parameter X");  

  pnum = getpnum('X');
  if (pnum >= 0) {
    cstr = new char [param[pnum].size() + 1];
    strcpy (cstr, param[pnum].c_str());
    DBG_int("xeq parameter #", pnum);  
    DBG_msg("xeq parameter: ", cstr);    
    
        
    if ((mldl.rx_room() >= param[pnum].length() + 1) && !param[pnum].empty()) {
      // enough room in our rx buffer and we have something to execute
      DBG_int("init XQ", mldl.rx_room());
      i = 0;
      while (cstr[i] != NULL) {
        // add to buffer
        mldl.rx_add(cstr[i]);
        DBG_chr("XQI add", cstr[i]);
        i++;
      }
      mldl.rx_add(c_cr);
    } else {
      // not enough room
      DBG_msg("init_xeq", "rx buffer full or no command");
    }
    delete[] cstr;
  } 
}
        
/** send error message, command not recognized
 *
 */                               
void do_pdefault() {
  DBG_msg("do_pdefault", inbuf);
  send_error(err_notrecognized); 
}