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

mfuncs.cpp

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

File content as of revision 0:67a55a82ce06:

/* MMEx for MBED - MBED specific 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 mfuncs.cpp
  \brief Commands starting with M for MBED features
*/

#include "mfuncs.h"

/** main entry for parsing M-commands
 *
 */
void parse_M() {
  // process M-commands for mbed
  DBG_msg("parse_M", inbuf);
  err_num = noerror;
 
  wipesp(inbuf);                    // remove all spaces from string

  if (inbuf[1] != NULL) {
    switch (inbuf[1]) {
    case mled     : do_mled();        // control LED's
                    break;       
    case mversion : do_mversion();    // get version string
                    break;         
    case mwelcome : do_mwelcome();    // get welcome string
                    break;
    case mstatus  : do_mstatus();     // get MMex status
                    break;
    case mdebug   : do_mdebug();      // control DEBUG level
                    break;
    case merror   : do_merror();      // get latest error message
                    break;
    case mbaud    : do_mbaud();       // set console baud rate          
                    break;
    case mcase    : do_mcase();
                    break;
    case mtime    : do_mtime();
                    break;                    
    case mreset   : do_mreset();      // reset mbed            
                    break;                    
    default       : do_mdefault();    // command not recognized
                    break;
    }
  } else { do_mdefault(); }
}

/** control/read MBED led status
 *
 *  syntax: ML[number][value]<CR>
 * \n         [number]: 1, 2, 3, 4, LED number
 * \n         [value] : 0 (off), 1(ON), T(toggle), R(read)
 */
void do_mled() {
  DBG_msg("mled", inbuf);
  if ((inbuf[2] != NULL) && (inbuf[3] != NULL)) {
    // we have enough arguments
    switch (inbuf[3]) {
      case ledon   :
        switch (inbuf[2]) {
          case '1' : _led1.write(1); break;
          case '2' : _led2.write(1); break;
          case '3' : _led3.write(1); break;
          case '4' : _led4.write(1); break;
          default  : do_mdefault(); break;      
        }
        break;
        
      case ledoff  :
        switch (inbuf[2]) {
          case '1' : _led1.write(0); break;
          case '2' : _led2.write(0); break;
          case '3' : _led3.write(0); break;
          case '4' : _led4.write(0); break;
          default  : do_mdefault(); break;      
        }
        break;        
          
      case ledtog  :
        switch (inbuf[2]) {
          case '1' : _led1 = !_led1; break;
          case '2' : _led2 = !_led2; break;
          case '3' : _led3 = !_led3; break;
          case '4' : _led4 = !_led4; break;
          default  : do_mdefault(); break;      
        }
        break;
        
      case ledread :
        switch (inbuf[2]) {
          case '1' : send_int(_led1); break;
          case '2' : send_int(_led2); break;
          case '3' : send_int(_led3); break;
          case '4' : send_int(_led4); break;
          default  : do_mdefault(); break;
        }
        break;
    
      default    : do_mdefault();
                   break;        
    }    
  } else { do_mdefault(); }
} 
      
/** Read MMEx version information
 *
 *  syntax: MV<CR>
 *  
 */            
void do_mversion() {
  DBG_msg("mversion", inbuf);
  char str[] = msg_version;
  upstring(str);
  mldl.tx_string(str);
}
           
/** Read MMEx welcome message
 *
 *  syntax: MW<CR>
 *  
 */                                
void do_mwelcome() {
  DBG_msg("mwelcome", inbuf);
  welcome();
}
         
/** Read MMEx status message
 *
 *  syntax: MS<CR>
 *  
 */                    
void do_mstatus() {
  DBG_msg("mstatus", inbuf); 
  send_status();
}

/** Set MMEx debug level
 *
 *  syntax: MD[value]<CR>
 *  \n        [value]: 0 no debug output
 *  \n        [value]: 1 high level debug messages
 *  \n        [value]: 2 like 1, including SPI straffic
 *  
 */           
void do_mdebug() {
  DBG_msg("mdebug", inbuf);
  if (inbuf[2] != NULL) {
    // we have enough arguments
    switch (inbuf[2]) {
      case '0' : DBG_level = DBG_OFF;
                 mldl.DBG_set(DBG_OFF);
                 // now redirect stderr to NULL
                 freopen(NULL, "w", stderr);
                 freopen(NULL, "w", stdout);      
                 break;
      case '1' : DBG_level = DBG_ON;
                 mldl.DBG_set(DBG_ON);
                 //restore sterr and stdout
                 freopen("/pc", "w", stderr);
                 freopen("/pc", "w", stdout);                  
                 break;
      case '2' : DBG_level = DBG_FULL;
                 mldl.DBG_set(DBG_FULL);
                 //restore sterr and stdout
                 freopen("/pc", "w", stderr);
                 freopen("/pc", "w", stdout);      
                 break; 
      default  : do_mdefault();
                 break;    
    }
  } else { do_mdefault(); }
}

/** get latest error number
 *
 *  syntax: ME<CR>
 *  
 */         
void do_merror() {
  // get latest error message
  DBG_msg("do_merror", inbuf);
  send_2int(last_err);
  last_err = 0;      // clear after reading
}

/** set console (UBSB) baud rate
 *
 *  syntax: MB[value]<CR>
 *  \n        [value]: new baud rate
 *  
 */              
void do_mbaud() {
  long int baud = 0;
  
  DBG_msg("do_mbaud", inbuf);          
  
   // next chars on the commandline is the baud rate
  if (inbuf[2] != NULL) {
    // now process line
    for (int i = 2; ((inbuf[i] >='0') && (inbuf[i] <= '9')); i++ ) {
      baud = 10 * baud + (inbuf[i] - '0');
    }    
  }   
  if (baud == 0) {
    DBG_msg("do_mbaud", "invalid baud rate");
    send_error(err_notrecognized); 
  } else {
    // now set baud rate
    DBG_int("set baudrate", baud);
    pc.baud(baud);      
  }
}
           
/** set case for output of text commands
 *
 *  syntax: MC[value]<CR>
 *  \n        [value]: U all output upper case
 *  \n        [value]: N no change to output (or any other value)
 *  
 */              
void do_mcase() {
  DBG_msg("do_mcase", inbuf);          
  
  // next char on commandline is 'U'
  upcase = false;              // default value
  if (inbuf[2] == ucase ) { 
    upcase = true;             // change default if 'U'
    DBG_msg("do_mcase", "change to uppercase");
  } else {
    DBG_msg("do_mcase", "no change");    
  }
}           

/** get or set the MBED RTC time
 *
 *  syntax: MT<CR>  return the current time set in the RTC in date format
 *  \n      MTS<CR> return the current time in seconds
 *  \n      MT[value]<CR> set the time in date format 
 *  \n      MTS[value]<CR> set the current time in seconds
 *  \n date format is [year][month][day][hour][minute][second], all 2 digits, 
 *  \n year is 4 digits
 *  \n seconds format is number of seconds since Jan 1, 1970 (Unix convention)
 */  
void do_mtime() {
  bool secs = false;
  time_t seconds;
  struct tm t;      // for YYYYMMDDHHMMSS format
  
  
  char s[40];      // to hold output string
  int i = 2;
  DBG_msg("do_mtime", inbuf); 
  
  if (inbuf[2] == 'S') {
    secs = true;  // seconds mode
    i = 3;           // char counter for time value
  }
  
  // check if there is a parameter, if so read it
  if (inbuf[i] == NULL) {
    // no parameter, return current time
    seconds = time(NULL);     // get current time
    if (!secs) { 
      // translate to YYYYMMDDHHMMSS
      t = *localtime(&seconds);
      sprintf(s, "%04d%02d%02d%02d%02d%02d", 
              t.tm_year + 1900, t.tm_mon + 1, t.tm_mday,
              t.tm_hour, t.tm_min, t.tm_sec);
      DBG_msg("read time", s);      
      mldl.tx_string(s);                          
    } else {
      sprintf(s, "%d", seconds);
      DBG_msg("read time", s);
      mldl.tx_string(s);
    }
    
  } else {
    // set time from input
    if (secs) {
      // seconds format
      seconds = 0;
      while ((inbuf[i] != NULL) && (inbuf[i] >= '0') && (inbuf[i] <= '9')) {
        seconds = (10 * seconds) + (inbuf[i] - '0');
        i++;
      }
      sprintf(s, "%d", seconds);
      DBG_msg("set time", s);
    } else {
      // YYYYMMDDHHMMSS format
      DBG_msg("set time", inbuf);
      int j = 0;
      for (j = 0; j < 39; j++) s[j] = '0';
      s[39] = NULL;
      j = 0;
      while ((inbuf[i] != NULL) && (inbuf[i] >= '0') && (inbuf[i] <= '9')) {
        s[j] = inbuf[i];
        i++;
        j++;
      }      
      DBG_msg("set time s", s);       
      i =  1000 * (s[ 0] - '0') +  100 * (s[ 1] - '0') + 10 * (s[ 1] - '0') + (s[ 3] - '0');
      t.tm_year = i - 1900;
      
      i = 10 * (s[ 4] - '0') + (s[ 5] - '0');
      t.tm_mon  = i - 1;
      
      i = 10 * (s[ 6] - '0') + (s[ 7] - '0');;
      t.tm_mday = i;

      i = 10 * (s[ 8] - '0') + (s[ 9] - '0');    
      t.tm_hour = i;
      
      i = 10 * (s[10] - '0') + (s[11] - '0');      
      t.tm_min  = i;
      
      i = 10 * (s[10] - '0') + (s[11] - '0');
      t.tm_sec  = i;   
    
      seconds = mktime(&t);
      
    }
    set_time(seconds);
  }
}           
             
/** (soft) reset the MBED module
 *
 *  syntax: MR<CR>
 *  
 */   
void do_mreset() {
  DBG_msg("do_mreset", inbuf); 
  mbed_reset();
}

/** send error message, command not recognized
 *
 */                    
void do_mdefault() {
  // command not recognized
  DBG_msg("do_mdefault", inbuf);
  send_error(err_notrecognized); 
}