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

cfuncs.cpp

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

File content as of revision 0:67a55a82ce06:

/* MMEx for MBED - Console I/O 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 cfuncs.cpp
  \brief Commands starting with C for Console I/O
*/

#include "cfuncs.h"

/** main entry for parsing C-commands
 *
 *  syntax: Cx[argument]
 */
void parse_C() {
  DBG_msg("parse_C", inbuf);
  err_num = noerror;
 
  wipesp(inbuf);                    // remove all spaces from string

  if (inbuf[1] != NULL) {
    switch (inbuf[1]) {
    case cwrite   : do_cwrite();        // control LED's
                    break;       
    case cread    : do_cread();    // get version string
                    break;         
    case copen    : do_copen();    // get welcome string
                    break;
    case cbaud    : do_cbaud();     // get MMex status
                    break;
    case cparam   : do_cparam();      // control DEBUG level
                    break;                   
    default       : do_cdefault();    // command not recognized
                    break;
    }
  } else { do_mdefault(); }
}

/** write the string on the command line to the console
 *
 *  syntax: CW[string]<CR>
 */
void do_cwrite() {
  int i = 2;
  
  DBG_msg("do_cwrite", inbuf);
  
  while (inbuf[i] != NULL) {
    // now we write the data
    pc.putc(inbuf[i]);
    DBG_chr("do_cwrite", inbuf[i]);
    i++;
  }
  pc.putc(c_cr);     // write a <CR>
}

/** read characters from the console until a <CR> is found, 
 *  stream may be interrupted by the HP41 by sending >F
 *
 *  syntax: CR<CR>
 */
void do_cread() {
  bool go = true;
  bool stopread = false;
  char c = 0;
  
  DBG_msg("do_cread", inbuf);
    
  // now run the main reading loop
  while (go) {
    if (pc.readable()) {
      // we have data
      c = pc.getc();
      mldl.tx_add(c);     // add it to the SPI ringbuffer
      DBG_chr("do_cread", c);
      if (c == c_cr) {   // is it a Carriage Return ?
        mldl.tx_add(c_escape);
        mldl.tx_add(c_eof); 
        DBG_msg("do_cread:", "CR found ");  
      }
    }
            
    // now check if we have to stop?    
    if (!mldl.rx_empty()) {
      stopread = (mldl.rxx_read(data_mode) < 0);   // intentional stop of read
    }    
    go = !((c == c_cr) || stopread);
  }

  if (stopread) {
    DBG_msg("do_cread", "forced stop read received");
    mldl.flush_tx();    // empty transmit buffer
  }
}      
    
/** write the parameter indicated by the argument to the console, 
 *  stream may be interrupted by the HP41 by sending >F
 *
 *  syntax: CP[param]<CR>
 */    
void do_cparam() {
  int pnum = 0;
  int i = 0;
  char * cstr;
      
  DBG_msg("do_cparam", 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);    
    while (cstr[i] != NULL) {
      pc.putc(cstr[i]);         // send the data
      i++;
    }
    pc.putc(c_cr);              // send an extra <CR>
    delete[] cstr;
  } else { do_cdefault(); }  
}  
  
/** set console baud rate
 *
 *  syntax: CB[value]<CR>
 */    
void do_cbaud() {
  long int baud = 0;
  
  DBG_msg("do_cbaud", inbuf);  
  
  wipesp(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_cbaud", "invalid baud rate");
    send_error(err_notrecognized); 
  } else {
    // now set baud rate
    DBG_int("set baudrate", baud);
    pc.baud(baud);      
  }
}

/** open a channel between the MLDL2000 SPI and Console.
 *  Any data received from SPI will be sent to the Console, 
 *  data read from the Console will be sent to SPI.
 *  \n Interrupt stream by sending >F or >I from the HP41,
 *  interruption from the Console is not possible.
 *  If the transmit buffer becomes full, characters from 
 *  the Console may be lost, there is no handshake protocol
 *
 *  syntax: CO<CR>
 */  
void do_copen() {
  bool stopread = false;
  char chin = 0;
  int chout = 0;
    
  DBG_msg("do_copen", inbuf);
    
  // now run the main loop
  while (!stopread) {    
    if (!mldl.rx_empty()) {
      // there is data to send 
      chout = mldl.rxx_read(data_mode);
      if (chout < 0) {
        // >F or >I found
        stopread = true;
        DBG_msg("do_cread", "forced stop read received");
        mldl.flush_tx();    // empty transmit buffer
      } else {
        // we can send the char
        pc.putc(chout);
        DBG_chr("do_copen write", chout);
      }
    }    
    if (pc.readable()) {
      // we have data
      chin = pc.getc();
      mldl.tx_add(chin);     // add it to the SPI ringbuffer
      DBG_chr("do_copen read", chin);
    }
  }            
}   

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