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

Files at this revision

API Documentation at this revision

Comitter:
DeMein
Date:
Sun Feb 27 18:54:40 2011 +0000
Commit message:
Version as submitted to the NXP Design Challenge

Changed in this revision

FATFileSystem.lib Show annotated file Show diff for this revision Revisions of this file
MSCUsbHost.lib Show annotated file Show diff for this revision Revisions of this file
NetServices.lib Show annotated file Show diff for this revision Revisions of this file
RPCInterface.lib Show annotated file Show diff for this revision Revisions of this file
SDFileSystem.lib Show annotated file Show diff for this revision Revisions of this file
TMP102.lib Show annotated file Show diff for this revision Revisions of this file
cfuncs.cpp Show annotated file Show diff for this revision Revisions of this file
cfuncs.h Show annotated file Show diff for this revision Revisions of this file
debug.cpp Show annotated file Show diff for this revision Revisions of this file
debug.h Show annotated file Show diff for this revision Revisions of this file
fat.lib Show annotated file Show diff for this revision Revisions of this file
ffuncs.cpp Show annotated file Show diff for this revision Revisions of this file
ffuncs.h Show annotated file Show diff for this revision Revisions of this file
globaldefs.h Show annotated file Show diff for this revision Revisions of this file
helper.cpp Show annotated file Show diff for this revision Revisions of this file
helper.h Show annotated file Show diff for this revision Revisions of this file
lpc17xx_ssp.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
mbeddefs.cpp Show annotated file Show diff for this revision Revisions of this file
mbeddefs.h Show annotated file Show diff for this revision Revisions of this file
mfuncs.cpp Show annotated file Show diff for this revision Revisions of this file
mfuncs.h Show annotated file Show diff for this revision Revisions of this file
mmex.cpp Show annotated file Show diff for this revision Revisions of this file
mmex.h Show annotated file Show diff for this revision Revisions of this file
nfuncs.cpp Show annotated file Show diff for this revision Revisions of this file
nfuncs.h Show annotated file Show diff for this revision Revisions of this file
pfuncs.cpp Show annotated file Show diff for this revision Revisions of this file
pfuncs.h Show annotated file Show diff for this revision Revisions of this file
rfuncs.cpp Show annotated file Show diff for this revision Revisions of this file
rfuncs.h Show annotated file Show diff for this revision Revisions of this file
spissp/spissp.cpp Show annotated file Show diff for this revision Revisions of this file
spissp/spissp.h Show annotated file Show diff for this revision Revisions of this file
ufuncs.cpp Show annotated file Show diff for this revision Revisions of this file
ufuncs.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FATFileSystem.lib	Sun Feb 27 18:54:40 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_unsupported/code/fatfilesystem/
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MSCUsbHost.lib	Sun Feb 27 18:54:40 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/chris/code/MSCUsbHost/#cfb58054ab28
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NetServices.lib	Sun Feb 27 18:54:40 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/segundo/code/NetServices/#4e2468d7d5cb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RPCInterface.lib	Sun Feb 27 18:54:40 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/MichaelW/code/RPCInterface/#a9e2c45097c8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SDFileSystem.lib	Sun Feb 27 18:54:40 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/simon/code/SDFileSystem/#b1ddfc9a9b25
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TMP102.lib	Sun Feb 27 18:54:40 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/donatien/code/TMP102/#b469676e9a9e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cfuncs.cpp	Sun Feb 27 18:54:40 2011 +0000
@@ -0,0 +1,220 @@
+/* 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); 
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cfuncs.h	Sun Feb 27 18:54:40 2011 +0000
@@ -0,0 +1,48 @@
+/* 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.h
+  \brief header file for cfuncs
+*/
+
+#ifndef CFUNCS_H
+#define CFUNCS_H
+
+#include "mmex.h"
+
+// definition of the M-functions
+#define cwrite   'W'         // control LED's
+#define cread    'R'         // get version string
+#define copen    'O'         // get welcome string
+#define cbaud    'B'         // get MMex status
+#define cparam   'P'         // control DEBUG level
+
+void parse_C();
+void do_cwrite(); 
+void do_cread();
+void do_copen();
+void do_cbaud();
+void do_cparam();
+void do_cdefault();
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debug.cpp	Sun Feb 27 18:54:40 2011 +0000
@@ -0,0 +1,91 @@
+/* MMEx for MBED - Debug messages
+ * 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 debug.cpp
+  \brief Functions for generating console debug messages
+*/
+
+#include "debug.h"
+
+/** DBG_level
+ *
+ *  @brief global variable for level of debug messages
+ */
+int DBG_level = DBG_ON;
+
+/** show a debug message with two strings
+ *
+ *  @param src this will typically be the name of the function
+ *  @param msg message specific information
+ */
+void DBG_msg(char* src, char *msg) {
+  if (DBG_level != DBG_OFF) {
+    printf("%s :: %s\n", src, msg);
+  } 
+}
+
+/** show a debug message with a string and an integer
+ *
+ *  @param src this will typically be the name of the function
+ *  @param i integer passed
+ */
+void DBG_int(char* src, int i) {
+  // prints a single integer as debug message
+  if (DBG_level != DBG_OFF) {
+    printf("%s : %d\n", src, i);
+  }
+} 
+
+/** show a debug message with a string and a character both a character and hex value
+ *
+ *  @param src this will typically be the name of the function
+ *  @param c character to be shown
+ */
+void DBG_chr(char* src, char c) {
+  if (DBG_level != DBG_OFF) {
+    int cc = c;
+    if (c < 32) c = '.';
+    printf("%s : %c [%02x]\n", src, c, cc);
+  }
+} 
+
+/** show one character in hex, input from SPI to the MBED
+ *
+ *  @param c input to be shown
+ */
+void DBG_inchar(char C) {
+  // prints only one char in hex, preceded by a + for input followed by a space
+  if (DBG_level == DBG_FULL) {
+    printf("+%02x ", C);
+  }
+}
+
+/** show one character in hex, output from MBED to SPI
+ *
+ *  @param c output to be shown
+ */
+void DBG_outchar(char C) {
+  if (DBG_level == DBG_FULL) {
+    printf("-%02x ", C);
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debug.h	Sun Feb 27 18:54:40 2011 +0000
@@ -0,0 +1,45 @@
+/* MMEx for MBED - Debug messages
+ * 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 debug.h
+  \brief Functions for generating console debug messages
+*/
+
+#ifndef FUNCTIONS_H
+#define FUNCTIONS_H
+
+#include "mmex.h"
+
+extern int DBG_level;
+ 
+#define DBG_OFF  0
+#define DBG_ON   1
+#define DBG_FULL 2
+ 
+void DBG_msg(char* src, char *msg);
+void DBG_int(char* src, int i);
+void DBG_chr(char* src, char c); 
+void DBG_inchar(char C);
+void DBG_outchar(char C);
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fat.lib	Sun Feb 27 18:54:40 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/simon/code/fat/#560a6744936c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ffuncs.cpp	Sun Feb 27 18:54:40 2011 +0000
@@ -0,0 +1,791 @@
+/* MMEx for MBED - File 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 ffuncs.cpp
+  \brief Commands starting with F for File I/O
+*/
+
+#include "ffuncs.h"
+
+FILE *fp1; 
+SDFileSystem sd(p5, p6, p7, p8, fs_sd);
+MSCFileSystem msc(fs_usb);
+LocalFileSystem local(fs_local);
+
+// directory handles
+FATFS_DIR dj;
+DIR *d;  
+char odirectory = NULL;   // keeps track of which directory was opened
+
+fhandle handles[10]; 
+
+/** initialize file handles on startup
+ *
+ */
+void init_handles() {
+  // initialize the file handles  
+  for (int i = 0; i < 10; i++) {
+    // handles[i].filename = NULL;
+    // handles[i].medium   = NULL;
+    // handles[i].fsp      = NULL;
+    // handles[i].direct   = NULL;
+    // handles[i].filemode = NULL;
+    // handles[i].fullpath = NULL;
+    handles[i].fp       = NULL;     // we only use this to test
+  }
+}
+
+/** main entry for parsing F-commands
+ *
+ */
+void parse_F() {
+  err_num = noerror;
+  DBG_msg("parse_F", inbuf);
+ 
+  wipesp(inbuf);           // first remove space from string
+
+  if (inbuf[1] != NULL) {
+    switch (inbuf[1]) {
+    case fmount   : do_fmount();        // mount storage medium
+                    break;       
+    case funmount : do_funmount();      // unmount storage medium
+                    break;         
+    case ffopen   : do_ffopen();        // open file
+                    break;
+    case ffread   : do_ffread();        // read from file
+                    break;
+    case ffwrite  : do_ffwrite();       // write to file
+                    break;
+    case ffclose  : do_ffclose();       // close file
+                    break;
+    case ffseek   : do_ffseek();        // seek to file position
+                    break;
+    case fflush   : do_fflush();        // flush file        
+                    break;
+    case fdir     : do_fdir();          // get first directory entry
+                    break;
+    case fndir    : do_fndir();         // get next directory entry    
+                    break;
+    case fftell   : do_fftell();        // get next directory entry    
+                    break;                    
+    case ffsize   : do_ffsize();        // get next directory entry    
+                    break;                    
+    default       : do_fdefault();      // command not recognized
+                    break;
+    }
+  } else {
+    do_fdefault();                      // command not recognized
+  }
+}
+
+/** mount storage device
+ *
+ *  syntax: FM[medium]<CR>
+ * \n [medium]: U, S, L
+ */
+void do_fmount() {
+  int rslt = 0;
+  
+  DBG_msg("do_fmount", inbuf);
+  if (inbuf[2] != NULL) {
+    switch (inbuf[2]) {
+      case f_sdcard : DBG_msg("do_fmount", "SD, 1st init");                 
+                      rslt = sd.disk_initialize();             //initialize file system   
+                      DBG_msg("do_fmount", "SD, 2nd init");
+                      rslt = sd.disk_initialize();             //initialize file system 
+                      break;                      
+      case f_local  : // mount local flash, nothing really to do, it is always there                     
+                      break;                      
+      case f_usb    : rslt = msc.disk_initialize();             // enumerate USB device    
+                      break;                                            
+      default       : do_fdefault();                     // command not recognized
+                      break;    
+    }     
+  } else {
+    do_fdefault();      
+  }
+  if (rslt != noerror) {              // could not mount SD or USB device
+    DBG_int("device not mounted", rslt); 
+    send_error(err_not_mounted);
+  }
+}
+
+/** unmount storage device
+ *
+ *  syntax: FU[medium]<CR>
+ * \n         [medium]: U, S, L
+ */
+void do_funmount() {
+  // unmount storage device
+  int rslt = 0;
+  DBG_msg("do_funmount", inbuf);
+ 
+  if (inbuf[2] != NULL) {
+    switch (inbuf[2]) {
+      case f_sdcard : rslt = sd.disk_sync();
+                      break;                      
+      case f_local  : // sync not needed, class does not have this functions                    
+                      break;                      
+      case f_usb    : rslt = msc.disk_sync();            // enumerate USB device    
+                      break;                                            
+      default       : do_fdefault();                     // command not recognized
+                      break;    
+    }     
+  } else {
+    DBG_msg("do_funmount", "argument error");      
+    do_fdefault(); 
+  }
+  if (rslt != noerror) {              // could not mount SD or USB device
+                                      // will never see this message
+    DBG_int("device not unmounted", rslt); 
+    send_error(err_not_mounted);
+  }
+}
+
+/** open file on storage device
+ *
+ *  syntax: FO [handle] [mode] [medium] [name]
+ * \n          [handle]: 0..9
+ * \n          [mode]  : R, W, A 
+ * \n          [medium]: U, S, L
+ * \n          [name]  : filename in 8.3 format
+ * \n anything after FO may be replaced by a Parameter when %n is present
+ */
+void do_ffopen() {
+  int han = 0;            // variable for handle
+  int i = 0;
+  int pos = 0;
+  int pnum = 0;
+  unsigned char c;
+  char * cstr;
+    
+  wipesp(inbuf);
+   
+  DBG_msg("do_ffopen", inbuf);  
+  
+  // check for a % sign in inbuf
+  pos = 2;
+  while ((inbuf[pos] != NULL) && (inbuf[pos] != c_percent)) pos++;
+  
+  if ((inbuf[pos] != NULL) && ((pnum = getpnum(inbuf[pos + 1])) >= 0)) {
+    // found and valid parameter, now insert
+    cstr = new char [param[pnum].size() + 1];
+    strcpy (cstr, param[pnum].c_str());
+    DBG_msg("param", cstr);
+    DBG_int("pos", pos);
+    remchar(inbuf, pos, 2);       // remove %n, works better for insert
+    DBG_msg("do_ffopen", inbuf); 
+    insertstr(inbuf, cstr, pos);  // insert
+    DBG_msg("do_ffopen", inbuf); 
+    delete[] cstr;
+  }
+    
+  // check the arguments
+  c = inbuf[2];             // [handle]
+  if ((c != NULL) && (c >= '0') && (c <= '9')) {
+    // [handle] in range
+    han = c - '0';
+  } else {
+    do_fdefault();
+    return;          // terminate this function
+  }
+  
+  if (handles[han].fp != NULL) {        // file handle in use!
+    DBG_msg("do_ffopen", "file handle in use");
+    send_error(err_handle_used);
+    return;
+  }
+  
+  c = inbuf[4];            // [medium]
+  if (c != NULL) {
+    switch (c) {
+      case f_sdcard : handles[han].medium = f_sdcard;                                       
+                      strcpy(handles[han].fsp, fsp_sd);
+                      break;                      
+      case f_local  : handles[han].medium = f_local;
+                      strcpy(handles[han].fsp, fsp_local);
+                      break;                      
+      case f_usb    : handles[han].medium = f_usb;
+                      strcpy(handles[han].fsp, fsp_usb);
+                      break;                                            
+      default       : do_fdefault();                            // command not recognized
+                      break;    
+    } 
+  } else {
+    do_fdefault();
+    return;        // terminate this function  
+  } 
+
+  c = inbuf[3];       // get filemode
+  if (c != NULL) {
+    switch (c) {
+      case 'W' : handles[han].filemode = f_modew;
+                 break;
+      case 'R' : handles[han].filemode = f_moder;
+                 break; 
+      case 'A' : handles[han].filemode = f_modea;
+                 break;
+      default  : do_fdefault();                    // command not recognized
+                 break;
+    }
+  } else {
+    do_fdefault();
+    return;          // terminate this function
+  }
+  
+  // now get filename
+  i = 0;
+  while ((inbuf[i + 5] != NULL) && (i <= 13)) {
+    // will not check until end of name, take max 12 chars
+    handles[han].filename[i] = inbuf[i + 5];
+    i++;
+    handles[han].filename[i] = NULL;  // guarantee null terminated string
+  }
+ 
+  // create full pathname
+  strcpy(handles[han].fullpath, handles[han].fsp);
+  strcat(handles[han].fullpath, handles[han].filename);
+  char tmp[5]; 
+  sprintf(tmp,"%c", handles[han].filemode);
+    
+  DBG_msg("filename:", handles[han].filename);
+  DBG_msg("path    :", handles[han].fullpath);
+  DBG_int("handle# :", han);
+  DBG_chr("mode    :", handles[han].filemode);
+  DBG_chr("medium  :", handles[han].medium);
+    
+  // now open file  
+  handles[han].fp = fopen(handles[han].fullpath,tmp);
+  if (handles[han].fp != NULL) {
+    DBG_msg("do_ffopen", "file opened");
+  } else {
+    DBG_msg("do_ffopen", "file NOT opened");
+    send_error(err_filenotopen);
+  }  
+}
+
+/** read file contents
+ *
+ *  syntax: FR [handle] [value]
+ *  \n         [handle]: 0..9
+ *  \n         [value] : number of byte to read
+ *  \n when [value]=0 or omitted will read until <EOF>, 
+ *  reading can be interrupted by sending >F or >I
+ */
+void do_ffread() {
+  long int numbytes = 0;
+  long int count = 0;
+  int i, m;
+  int han;
+  bool go = true;
+  bool stopread = false;
+  
+  DBG_msg("do_ffread", inbuf);  
+  
+  rx_max = 0;
+  tx_max = 0;
+  
+  int c = inbuf[2];            // [handle]
+  if ((c != NULL) && (c >= '0') && (c <= '9')) {
+    // [handle] in range
+    han = c - '0';
+  } else {
+    do_fdefault();
+    return;           // exit with error
+  }
+  DBG_int("handle :", han);
+  if (handles[han].fp == NULL) {     // file handle not in use!
+    DBG_msg("do_ffread", "no valid file handle");
+    send_error(err_no_handle);
+    return;
+  }   
+  
+  count = 0;
+  // next chars on the commandline is the number of bytes to read
+  if (inbuf[3] == NULL) {
+    // no value on the command line
+    numbytes = 0;
+  } else {
+    // now process line
+    for (i = 3; ((inbuf[i] >='0') && (inbuf[i] <= '9')); i++ ) {
+      numbytes = 10 * numbytes + (inbuf[i] - '0');
+    }
+  }
+  DBG_int("do_ffread bytes:", numbytes);
+  
+  // now ready to really do the read
+  // must monitor input buffer to check if we need to stop!  
+  while (go) {       
+    m = mldl.rx_use();
+    if (m > rx_max) rx_max = m;
+    m = mldl.tx_use();
+    if (m > tx_max) tx_max = m;    
+    
+    c = getc(handles[han].fp);     // read one byte
+    // remove comment below to list all bytes read
+    DBG_chr("do_ffread: ", c);         
+    if (c == EOF) {
+      // EOF found, send <EOF> sequence
+      mldl.tx_add(c_escape);
+      mldl.tx_add(c_eof); 
+      DBG_int("do_ffread: EOF at byte ", count);
+    } else {
+      // no problem, just send data
+      mldl.tx_addp(c);
+      count++;      // increase counter  
+    }               
+    // now check if we have to stop?    
+    if (!mldl.rx_empty()) {
+      stopread = (mldl.rxx_read(data_mode) < 0);   // intentional stop of read
+    }    
+    go = !((c == EOF) || (count == numbytes) || stopread);
+  }    
+  
+  // in case the complete file is read, now wait until buffer is emptied  
+  while (!stopread && !mldl.tx_empty()) {
+    // keep checking for EOF
+    if (!mldl.rx_empty()) {
+      stopread = (mldl.rxx_read(data_mode) < 0);
+    }
+  }
+  
+  if (stopread) {
+    DBG_msg("do_ffread", "forced stop read received");
+    mldl.flush_tx();    // empty transmit buffer
+  }
+  
+  DBG_int("do_ffread: end read at byte ", count);
+  DBG_int("rx_max", rx_max);
+  DBG_int("tx_max", tx_max); 
+}
+
+/** write to file
+ *
+ *  syntax: FW [handle]
+ *  \n         [handle]: 0..9
+ *  \ wait for prompt, then send data to be written. 
+ *  End writing by sending >F
+ */
+void do_ffwrite() {
+  int han, m;
+  bool go = true;
+  int count = 0;
+  
+  DBG_msg("do_ffwrite", inbuf);  
+  int c = inbuf[2];            // [handle]
+  if ((c != NULL) && (c >= '0') && (c <= '9')) {
+    // [handle] in range
+    han = c - '0';
+  } else {
+    do_fdefault();
+    return;           // check how to exit with error
+  }
+  DBG_int("handle :", han);
+  if (handles[han].fp == NULL) {     // file handle not in use!
+    DBG_msg("do_ffwrite", "no valid file handle");
+    send_error(err_no_handle);
+    return;
+  }   
+  send_prompt();              // now send a prompt and we are ready to go
+  while (go) {                  // as long as we can continue   
+    m = mldl.rx_use();
+    if (m > rx_max) rx_max = m;
+    m = mldl.tx_use();
+    if (m > tx_max) tx_max = m;                     
+    c = mldl.rxx_read(data_mode);             // get data     
+    if ((c == -1) || (c == -2)) go = false;   // <EOF> or interrupt 
+    if (go) {
+      // remove comment below to list all bytes written
+      DBG_chr("fwrite", c);
+      count++;
+
+      fputc(c, handles[han].fp);      
+    } else {
+      DBG_int("fwrite: ", c);
+    }
+  }
+  DBG_int("fwrite written", count);
+  DBG_int("rx_max", rx_max);
+  DBG_int("tx_max", tx_max); 
+}
+
+/** close file
+ *
+ *  syntax: FC [handle]
+ *  \n         [handle]: 0..9
+ */
+void do_ffclose() {
+  int han = 0;
+  int rslt = 0;
+  DBG_msg("do_ffclose", inbuf);
+ 
+  char c = inbuf[2];      // file handle should be here
+  if ((c != NULL) && (c >= '0') && (c <= '9')) {
+    // [handle] in range
+    han = c - '0';
+  } else {
+    do_fdefault();
+    return;           // check how to exit with error
+  }    
+  if (handles[han].fp == NULL) {     // file handle not in use!
+    DBG_msg("do_ffclose", "no valid file handle");
+    send_error(err_no_handle);
+    return;
+  }        
+  rslt = fclose(handles[han].fp);
+  handles[han].fp = NULL;
+  DBG_int("do_ffclose result", rslt);  
+}
+
+/** seek to file position
+ *
+ *  syntax: FS [handle] [value]
+ *  \n         [handle]: 0..9
+ *  \n         [value] : new position
+ *  \n if [value] is ommitted, will assume 0, 
+ *  will always seek relative to the start of the file
+ */
+void do_ffseek() {
+  DBG_msg("do_ffseek", inbuf);
+ 
+  long int position = 0;  // max value is 2147483647
+  int i;
+  int han;
+  
+  int c = inbuf[2];            // [handle]
+  if ((c != NULL) && (c >= '0') && (c <= '9')) {
+    // [handle] in range
+    han = c - '0';
+  } else {
+    do_fdefault();
+    return;           // check how to exit with error
+  }
+  DBG_int("handle :", han);
+  if (handles[han].fp == NULL) {     // file handle not in use!
+    DBG_msg("do_ffseek", "no valid file handle");
+    send_error(err_no_handle);
+    return;
+  }  
+  
+   // next chars on the commandline is the number of bytes to read
+  if (inbuf[3] == NULL) {
+    // no value on the command line
+    position = 0;
+  } else {
+    // now process line
+    for (i = 3; ((inbuf[i] >='0') && (inbuf[i] <= '9')); i++ ) {
+      position = 10 * position + (inbuf[i] - '0');
+    }
+  }
+  
+  if (fseek(handles[han].fp, position, SEEK_SET) < 0) {
+    // error in fseek
+    send_error(err_seek);
+    return;
+  }
+}
+
+/** flush file
+ *
+ *  syntax: FF [handle]
+ *  \n         [handle]: 0..9
+ *  \n fflush is not implemented in the file systems
+ */
+void do_fflush() {
+  DBG_msg("do_fflush", inbuf);
+}  
+
+
+/** open directory and list first entry
+ *
+ *  syntax: FD [medium]
+ *  \n         [medium]: U, S, L
+ *  \n returns the first directory item, 
+ *  subdirectories are not yet supported,
+ *  if the listing is empty >F is returned
+ */
+void do_fdir() {
+  FILINFO finfo;
+  FRESULT res ;
+  struct dirent *p;
+  char tmp[25]; 
+  
+  DBG_msg("do_ffdir", inbuf);
+        
+  if (inbuf[2] != NULL) {
+    switch (inbuf[2]) {
+      case f_sdcard : res = f_opendir(&dj, "0:/");
+                      odirectory = f_sdcard; 
+                      break;                      
+      case f_local  : d = opendir(rt_local);
+                      odirectory = f_local;                      
+                      break;                      
+      case f_usb    : res = f_opendir(&dj, "1:/");
+                      odirectory = f_usb;
+                      break;                                            
+      default       : do_fdefault();    // command not recognized
+                      break;    
+    }     
+  } else {
+    do_fdefault();      
+    return;
+  }
+   
+  if (odirectory == f_local) {
+    // get listing from local flash
+    if (d != NULL) { 
+      if ((p = readdir(d)) != NULL) {
+        sprintf(tmp,"%s", p->d_name);      
+        DBG_msg("do_ffdir", tmp);
+        upstring(tmp);
+        mldl.tx_string(tmp);
+      } else {
+        DBG_msg("do_ffdir", "Last directory entry");             
+        mldl.tx_add(c_escape);    // send <EOF> sequence
+        mldl.tx_add(c_eof);
+      }
+    } else {
+      // could not open directory  
+      DBG_msg("do_ffdir", "Could not open directory");
+      send_error(err_directory);
+    }
+  } else {
+    // get listing from USB or SD card
+    
+    /* File attribute bits for directory entry  */
+    // #define AM_RDO    0x01    /* Read only   */
+    // #define AM_HID    0x02    /* Hidden      */
+    // #define AM_SYS    0x04    /* System      */
+    // #define AM_VOL    0x08    /* Volume label */
+    // #define AM_LFN    0x0F    /* LFN entry   */
+    // #define AM_DIR    0x10    /* Directory   */
+    // #define AM_ARC    0x20    /* Archive     */
+    
+    if (res == FR_OK) {
+      res = f_readdir(&dj, &finfo);
+      if ((res == FR_OK) && finfo.fname[0] != 0) {
+        if ((finfo.fattrib & AM_DIR) == AM_DIR) {
+          // file is a directory entry
+          sprintf(tmp,"./%s %d", finfo.fname, finfo.fsize);
+        } else {
+          sprintf(tmp,"%s %d", finfo.fname, finfo.fsize);
+        } 
+        DBG_msg("ffdir", tmp);
+        upstring(tmp);
+        mldl.tx_string(tmp);
+      } else {
+        DBG_msg("do_ffdir", "Last directory entry");
+        mldl.tx_add(c_escape);    // send <EOF> sequence
+        mldl.tx_add(c_eof);                
+      }
+    } else {
+      // could not open directory  
+      DBG_msg("do_ffdir", "Could not open directory");
+      send_error(err_directory);      
+    }
+  }  
+}
+
+/** lists the next directory item
+ *
+ *  syntax: FN [medium]
+ *  \n         [medium]: U, S, L
+ *  returns the next directory item, must be preceded by a FD call. 
+ *  Subdirectories are not yet supported, 
+ *  after the last item >F is returned
+ */
+void do_fndir() {
+  FILINFO finfo;
+  FRESULT res ;
+  struct dirent *p;
+  char tmp[25];   
+    
+  DBG_msg("do_fndir", inbuf);
+
+  if (odirectory == f_local) {
+    // get listing from local flash
+    if (d != NULL) { 
+      if ((p = readdir(d)) != NULL) {
+        sprintf(tmp,"%s", p->d_name);      
+        DBG_msg("ffdir", tmp);
+        upstring(tmp);
+        mldl.tx_string(tmp);
+      } else {
+        DBG_msg("ffdir", "Last directory entry");
+        mldl.tx_add(c_escape);    // send <EOF> sequence
+        mldl.tx_add(c_eof);         
+      }
+    }
+  } else {
+    // get listing from USB or SD card
+    res = f_readdir(&dj, &finfo);
+    if ((res == FR_OK) && finfo.fname[0] != 0) {
+      if ((finfo.fattrib & AM_DIR) == AM_DIR) {
+        // file is a directory entry
+        sprintf(tmp,"./%s %d", finfo.fname, finfo.fsize);
+      } else {
+        sprintf(tmp,"%s %d", finfo.fname, finfo.fsize);
+      }  
+      DBG_msg("do_fndir", tmp);
+      upstring(tmp);
+      mldl.tx_string(tmp);
+    } else {
+      DBG_msg("do_fndir", "Last directory entry");
+        mldl.tx_add(c_escape);    // send <EOF> sequence
+        mldl.tx_add(c_eof);       
+    }       
+  }  
+}  
+
+/** returns the value of the current file pointer
+ *
+ *  syntax: FT [handle]
+ *  \n         [handle]: 0..9
+ *  returns the value of the file pointer for the open file with the
+ *  given handle.
+ */
+void do_fftell() {
+  int han = 0;
+  int rslt = 0;
+  char tmp[25];
+  
+  DBG_msg("do_ftell", inbuf);
+ 
+  char c = inbuf[2];      // file handle should be here
+  if ((c != NULL) && (c >= '0') && (c <= '9')) {
+    // [handle] in range
+    han = c - '0';
+  } else {
+    do_fdefault();
+    return;           // check how to exit with error
+  }    
+  if (handles[han].fp == NULL) {     // file handle not in use!
+    DBG_msg("do_ffclose", "no valid file handle");
+    send_error(err_no_handle);
+    return;
+  }        
+  rslt = ftell(handles[han].fp);
+  sprintf(tmp,"%d", rslt); 
+  mldl.tx_string(tmp);
+
+  DBG_int("do_ftell result", rslt);  
+}  
+  
+/** returns the size of a file
+ *
+ *  syntax: FZ [medium] [name]
+ *  \n         [medium]: S, L or U
+ *  \n         [name]: valid 8.3 filename
+ *  \n         argument may contain %n for replacement by the Parameter n
+ *  returns the size of a file. This function will open and close the file!
+ */
+void do_ffsize() {
+  int i = 0;
+  int pos = 0;
+  int pnum = 0;
+  int size = 0;
+  char filename[20];
+  char fullpath[50];
+  char tmp[25];
+  unsigned char c;
+  char * cstr;
+    
+  wipesp(inbuf);
+   
+  DBG_msg("do_fsize", inbuf);  
+  
+  // check for a % sign in inbuf
+  pos = 2;
+  while ((inbuf[pos] != NULL) && (inbuf[pos] != c_percent)) pos++;
+  
+  if ((inbuf[pos] != NULL) && ((pnum = getpnum(inbuf[pos + 1])) >= 0)) {
+    //  found and valid parameter, now insert
+    cstr = new char [param[pnum].size() + 1];
+    strcpy (cstr, param[pnum].c_str());
+    DBG_msg("param", cstr);
+    DBG_int("pos", pos);
+    remchar(inbuf, pos, 2);       // remove %n, works better for insert
+    DBG_msg("do_fsize", inbuf); 
+    insertstr(inbuf, cstr, pos);  // insert
+    DBG_msg("do_fsize", inbuf); 
+    delete[] cstr;
+  }
+  
+  c = inbuf[2];            // [medium]
+  if (c != NULL) {
+    switch (c) {
+      case f_sdcard : strcpy(fullpath, fsp_sd);
+                      break;                      
+      case f_local  : strcpy(fullpath, fsp_local);
+                      break;                      
+      case f_usb    : strcpy(fullpath, fsp_usb);
+                      break;                                            
+      default       : do_fdefault();     // command not recognized
+                      break;    
+    } 
+  } else {
+    do_fdefault();
+    return;        // terminate this function  
+  } 
+  
+  // now get filename
+  i = 0;
+  while ((inbuf[i + 3] != NULL) && (i <= 13)) {
+    // will not check until end of name, take max 13 chars
+    filename[i] = inbuf[i + 3];
+    i++;  
+    filename[i] = NULL;  // ensure null terminated string
+  }
+ 
+  // create full pathname
+  strcat(fullpath, filename);
+    
+  DBG_msg("filename", fullpath);
+    
+  // now open file  
+  FILE *fp = fopen(fullpath, "r");
+  if (fp != NULL) {
+    DBG_msg("do_fsize", "file opened");
+  } else {
+    DBG_msg("do_fsize", "file NOT opened");
+    send_error(err_filenotopen);
+    return;                            // and get out
+  }  
+  
+  fseek(fp, 0L, SEEK_END);   // seek to end
+  size = ftell(fp);          // get size
+  fclose(fp);                // close file
+  sprintf(tmp,"%d", size); 
+  mldl.tx_string(tmp);
+   
+  DBG_int("do_fsize result", size);
+  
+}
+  
+/** send error message, command not recognized,
+ */   
+void do_fdefault() {
+  // get version string
+  DBG_msg("do_fdefault", "unsupported command");
+  send_error(err_novalidcommand);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ffuncs.h	Sun Feb 27 18:54:40 2011 +0000
@@ -0,0 +1,94 @@
+/* MMEx for MBED - File 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 ffuncs.h
+  \brief header file for ffuncs
+*/
+
+#ifndef FFUNCS_H
+#define FFUNCS_H
+
+#include "mmex.h"
+
+// definition of the F-functions
+#define fmount   'M'         // mount filesystem
+#define funmount 'U'         // Unmount filesystem
+#define ffopen   'O'         // File Open
+#define ffread   'R'         // File Read
+#define ffwrite  'W'         // File Write
+#define ffclose  'C'         // File Close
+#define ffseek   'S'         // File Seek
+#define fflush   'F'         // File Flush
+#define fdir     'D'         // Directory listing first entry
+#define fndir    'N'         // Directory listing next entry
+#define fftell   'T'         // Get value of file pointer
+#define ffsize   'Z'         // Get size of file
+
+#define f_sdcard 'S'         // SD card is the medium
+#define f_usb    'U'         // USB stick is the storage medium
+#define f_local  'L'         // local flash is the storage medium
+
+#define f_modew  'w'         // file mode is write
+#define f_moder  'r'         // file mode is read
+#define f_modea  'a'         // file mode is append
+
+#define fs_local "local"     // name for local filesystem
+#define fs_sd    "sd"        // name for SD card filesystem
+#define fs_usb   "usb"       // name for USB filesystem
+
+#define fsp_local "/local/"  // path name for local filesystem
+#define fsp_sd    "/sd/"     // path name for SD card filesystem
+#define fsp_usb   "/usb/"    // path name for USB filesystem
+
+#define rt_local "/local"    // root path name for local filesystem
+#define rt_sd    "/sd"       // root path name for SD card filesystem
+#define rt_usb   "/usb"      // root path name for USB filesystem
+
+struct fhandle {             // used for saving info in file handles
+         char filename[20];  // filename
+         char medium;        // S, U or F
+         char fsp[10];       // path name, root only
+         char direct[20];    // string with current directory
+         char filemode;      // current filemode
+         char fullpath[50];  // full path
+         FILE *fp;           // file pointer
+       }; 
+
+void init_handles();
+void parse_F();
+
+void do_fmount(); 
+void do_funmount();
+void do_ffopen();
+void do_ffread();
+void do_ffwrite();
+void do_ffclose();
+void do_ffseek();
+void do_fflush(); 
+void do_fdir();
+void do_fndir();
+void do_fftell();
+void do_ffsize();
+void do_fdefault();
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/globaldefs.h	Sun Feb 27 18:54:40 2011 +0000
@@ -0,0 +1,77 @@
+/* MMEx for MBED - Support functions
+ * 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 globaldefs.h.h
+  \brief header file for some global definitions
+*/
+
+#ifndef GLOBALDEFS_H
+#define GLOBALDEFS_H
+
+// control characters
+#define c_prompt  '!'            // prompt character
+#define c_escape  '>'            // escape character
+#define c_arrow   '>'            // to send the > character
+#define c_eof     'F'            // for End-Of-File/End-Of-Transmission
+#define c_return  'C'            // for Cariiage Return
+#define c_null    'N'            // for null character
+#define c_zero    '0'            // alternative for null
+#define c_hex     '$'            // hex chars to follow
+#define c_hexalt  'X'            // hex chars to follow
+#define c_append  '+'            // append to string
+#define c_intrpt  'I'            // interrupt pending command
+#define c_space   ' '            // space character
+#define c_cr      0x0d           // Carriage Return or <CR>
+#define c_percent '%'            // percent character
+
+#define c_error   'E'
+#define c_busy    'B'
+
+#define c_rpc     '/'
+#define c_rpcapp  '+'
+#define c_rpcexe  '*'
+
+// control strings
+#define cc_arrow  ">>"
+#define cc_prompt ">!"
+#define cc_null   ">N"
+#define cc_eof    ">F"
+#define cc_error  ">E"
+#define cc_busy   ">B"
+
+// main command grouping
+#define cmd_m     'M'
+#define cmd_c     'C'
+#define cmd_f     'F'
+#define cmd_r     'R'
+#define cmd_rpc   '/'
+#define cmd_n     'N'
+#define cmd_p     'P'
+#define cmd_u     'U'
+#define cmd_c     'C'
+
+#define command_mode true
+#define data_mode    false
+
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/helper.cpp	Sun Feb 27 18:54:40 2011 +0000
@@ -0,0 +1,122 @@
+/* MMEx for MBED - Support functions
+ * 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 helper.cpp
+  \brief various support functions for the MMEx
+*/
+
+#include "helper.h"
+
+/** remove all spaces from a string
+ *
+ *  @param src the string to be modified
+ *
+ */  
+void wipesp(char *src) {
+  // remove all spaces from a string
+  char *dst = src;
+
+  while (*src != 0) {
+    if (*src != c_space) {
+      *dst++ = *src; // copy
+    }
+    src++;
+  }
+  *dst = 0;
+}  
+
+/** remove part of a string
+ *
+ *  @param src the string to be modified
+ *  pos start position for removing characters
+ *  len number of characters to remove
+ *
+ */ 
+void remchar(char *src, int pos, int len) {
+  char *dst = src;
+  int i = 0;
+  
+  if (pos < 0) return;
+  if (len < 0) return;
+  
+  src += pos;
+  dst = src;
+  src += len; 
+  for ( i = pos + 1; *src != 0; i++ ) *dst++ = *src++;  
+  *dst = 0;  // Ensure the string is null-terminated. 
+}
+ 
+/** convert a hex char '0' to 'F' in its decimal equivalent
+ *
+ *  @param C character
+ *  @return a value 0 to 15, 0 when C was not in '0'..'F'
+ *
+ */  
+int hex2int(char C) {
+  if ((C >= '0') && (C <= '9')) return(C - '0');
+  if ((C >= 'A') && (C <= 'F')) return(C - 'A' + 10);
+  return(0);
+}
+ 
+/** insert a string in another string
+ *
+ *  @param str1 target string where insert takes place in
+ *  @param str2 string to be inserted
+ *  @param pos position of insertion
+ *
+ */              
+void insertstr(char *str1, char *str2, int pos) {
+  int i;
+  int sz1 = 0;  // size of str1
+  int sz2 = 0;  // size of str2
+  char *dst = str1;  // save start of str1
+  char *end = str1;  // end of str1
+     
+  for (i = 0; str1[i] != 0; i++) sz1++;  // length of string1
+  for (i = 0; str2[i] != 0; i++) sz2++;  // length of string2
+  
+  str1 += pos;        // insert point
+  end  += sz1;        // end of string 1
+  dst  += sz1 + sz2;  // end of new string
+  
+  // now move the end of str1 to make room
+  for (i = 0; i <= sz2; i++) *dst-- = *end--;
+    
+  // and move str2 in the free space inside str1
+  for (i = 0; i < sz2; i++) *str1++ = *str2++;  
+}
+
+/** convert a string to upper case if global variable upcase is true
+ *
+ *  @param str string to modify
+ */  
+void upstring(char * str) {
+  if (upcase) {  
+    while (*str != NULL) {    
+      if ((*str >= 'a') && (*str <= 'z')) *str = *str - 0x20;       
+      str++;    
+    }  
+  }    
+}     
+      
+      
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/helper.h	Sun Feb 27 18:54:40 2011 +0000
@@ -0,0 +1,40 @@
+/* MMEx for MBED - Support functions
+ * 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 helper.h
+  \brief header file for helper.cpp
+*/
+
+#ifndef HELPER_H
+#define HELPER_H
+
+#include "mbed.h"
+#include "mmex.h"
+
+void wipesp(char *src);
+void remchar(char *src, int pos, int len);
+int hex2int(char C);
+void insertstr(char *str1, char *str2, int pos);
+void upstring(char *str);
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lpc17xx_ssp.h	Sun Feb 27 18:54:40 2011 +0000
@@ -0,0 +1,396 @@
+/* MMEx for MBED - LPC17xx SSP Interface definitions
+ * 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.
+ *
+ * This file is slightly modified from the original NXP source
+ */
+
+/**
+  \file lpc17xx_ssp.h
+  \brief LPC17xx SSP Interface definitions
+*/
+
+
+/* Peripheral group ----------------------------------------------------------- */
+#ifndef LPC17XX_SSP_H_
+#define LPC17XX_SSP_H_
+
+#include "mbed.h"
+
+/*********************************************************************//**
+ * Macro defines for CR0 register
+ **********************************************************************/
+
+/** SSP data size select, must be 4 bits to 16 bits */
+#define SSP_CR0_DSS(n)           ((uint32_t)((n-1)&0xF))
+/** SSP control 0 Motorola SPI mode */
+#define SSP_CR0_FRF_SPI          ((uint32_t)(0<<4))
+/** SSP control 0 TI synchronous serial mode */
+#define SSP_CR0_FRF_TI           ((uint32_t)(1<<4))
+/** SSP control 0 National Micro-wire mode */
+#define SSP_CR0_FRF_MICROWIRE      ((uint32_t)(2<<4))
+/** SPI clock polarity bit (used in SPI mode only), (1) = maintains the
+   bus clock high between frames, (0) = low */
+#define SSP_CR0_CPOL_HI        ((uint32_t)(1<<6))
+/** SPI clock out phase bit (used in SPI mode only), (1) = captures data
+   on the second clock transition of the frame, (0) = first */
+#define SSP_CR0_CPHA_SECOND    ((uint32_t)(1<<7))
+/** SSP serial clock rate value load macro, divider rate is
+   PERIPH_CLK / (cpsr * (SCR + 1)) */
+#define SSP_CR0_SCR(n)       ((uint32_t)((n&0xFF)<<8))
+/** SSP CR0 bit mask */
+#define SSP_CR0_BITMASK        ((uint32_t)(0xFFFF))
+
+
+/*********************************************************************//**
+ * Macro defines for CR1 register
+ **********************************************************************/
+/** SSP control 1 loopback mode enable bit */
+#define SSP_CR1_LBM_EN        ((uint32_t)(1<<0))
+/** SSP control 1 enable bit */
+#define SSP_CR1_SSP_EN        ((uint32_t)(1<<1))
+/** SSP control 1 slave enable */
+#define SSP_CR1_SLAVE_EN    ((uint32_t)(1<<2))
+/** SSP control 1 slave out disable bit, disables transmit line in slave
+   mode */
+#define SSP_CR1_SO_DISABLE    ((uint32_t)(1<<3))
+/** SSP CR1 bit mask */
+#define SSP_CR1_BITMASK        ((uint32_t)(0x0F))
+
+
+/*********************************************************************//**
+ * Macro defines for DR register
+ **********************************************************************/
+/** SSP data bit mask */
+#define SSP_DR_BITMASK(n)   ((n)&0xFFFF)
+
+/*********************************************************************//**
+ * Macro defines for SR register
+ **********************************************************************/
+/** SSP status TX FIFO Empty bit */
+#define SSP_SR_TFE      ((uint32_t)(1<<0))
+/** SSP status TX FIFO not full bit */
+#define SSP_SR_TNF      ((uint32_t)(1<<1))
+/** SSP status RX FIFO not empty bit */
+#define SSP_SR_RNE      ((uint32_t)(1<<2))
+/** SSP status RX FIFO full bit */
+#define SSP_SR_RFF      ((uint32_t)(1<<3))
+/** SSP status SSP Busy bit */
+#define SSP_SR_BSY      ((uint32_t)(1<<4))
+/** SSP SR bit mask */
+#define SSP_SR_BITMASK    ((uint32_t)(0x1F))
+
+
+/*********************************************************************//**
+ * Macro defines for CPSR register
+ **********************************************************************/
+/** SSP clock prescaler */
+#define SSP_CPSR_CPDVSR(n)     ((uint32_t)(n&0xFF))
+/** SSP CPSR bit mask */
+#define SSP_CPSR_BITMASK    ((uint32_t)(0xFF))
+
+
+/*********************************************************************//**
+ * Macro define for (IMSC) Interrupt Mask Set/Clear registers
+ **********************************************************************/
+/** Receive Overrun */
+#define SSP_IMSC_ROR    ((uint32_t)(1<<0))
+/** Receive TimeOut */
+#define SSP_IMSC_RT        ((uint32_t)(1<<1))
+/** Rx FIFO is at least half full */
+#define SSP_IMSC_RX        ((uint32_t)(1<<2))
+/** Tx FIFO is at least half empty */
+#define SSP_IMSC_TX        ((uint32_t)(1<<3))
+/** IMSC bit mask */
+#define SSP_IMSC_BITMASK    ((uint32_t)(0x0F))
+
+/*********************************************************************//**
+ * Macro define for (RIS) Raw Interrupt Status registers
+ **********************************************************************/
+/** Receive Overrun */
+#define SSP_RIS_ROR        ((uint32_t)(1<<0))
+/** Receive TimeOut */
+#define SSP_RIS_RT        ((uint32_t)(1<<1))
+/** Rx FIFO is at least half full */
+#define SSP_RIS_RX        ((uint32_t)(1<<2))
+/** Tx FIFO is at least half empty */
+#define SSP_RIS_TX        ((uint32_t)(1<<3))
+/** RIS bit mask */
+#define SSP_RIS_BITMASK    ((uint32_t)(0x0F))
+
+
+/*********************************************************************//**
+ * Macro define for (MIS) Masked Interrupt Status registers
+ **********************************************************************/
+/** Receive Overrun */
+#define SSP_MIS_ROR        ((uint32_t)(1<<0))
+/** Receive TimeOut */
+#define SSP_MIS_RT        ((uint32_t)(1<<1))
+/** Rx FIFO is at least half full */
+#define SSP_MIS_RX        ((uint32_t)(1<<2))
+/** Tx FIFO is at least half empty */
+#define SSP_MIS_TX        ((uint32_t)(1<<3))
+/** MIS bit mask */
+#define SSP_MIS_BITMASK    ((uint32_t)(0x0F))
+
+
+/*********************************************************************//**
+ * Macro define for (ICR) Interrupt Clear registers
+ **********************************************************************/
+/** Writing a 1 to this bit clears the "frame was received when
+ * RxFIFO was full" interrupt */
+#define SSP_ICR_ROR        ((uint32_t)(1<<0))
+/** Writing a 1 to this bit clears the "Rx FIFO was not empty and
+ * has not been read for a timeout period" interrupt */
+#define SSP_ICR_RT        ((uint32_t)(1<<1))
+/** ICR bit mask */
+#define SSP_ICR_BITMASK    ((uint32_t)(0x03))
+
+
+/*********************************************************************//**
+ * Macro defines for DMACR register
+ **********************************************************************/
+/** SSP bit for enabling RX DMA */
+#define SSP_DMA_RXDMA_EN      ((uint32_t)(1<<0))
+/** SSP bit for enabling TX DMA */
+#define SSP_DMA_TXDMA_EN      ((uint32_t)(1<<1))
+/** DMACR    bit mask */
+#define SSP_DMA_BITMASK        ((uint32_t)(0x03))
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+
+/* Public Types --------------------------------------------------------------- */
+/** @defgroup SSP_Public_Types
+ * @{
+ */
+
+/** @brief SSP configuration structure */
+typedef struct {
+    uint32_t Databit;         /** Databit number, should be SSP_DATABIT_x,
+                            where x is in range from 4 - 16 */
+    uint32_t CPHA;            /** Clock phase, should be:
+                            - SSP_CPHA_FIRST: first clock edge
+                            - SSP_CPHA_SECOND: second clock edge */
+    uint32_t CPOL;            /** Clock polarity, should be:
+                            - SSP_CPOL_HI: high level
+                            - SSP_CPOL_LO: low level */
+    uint32_t Mode;            /** SSP mode, should be:
+                            - SSP_MASTER_MODE: Master mode
+                            - SSP_SLAVE_MODE: Slave mode */
+    uint32_t FrameFormat;    /** Frame Format:
+                            - SSP_FRAME_SPI: Motorola SPI frame format
+                            - SSP_FRAME_TI: TI frame format
+                            - SSP_FRAME_MICROWIRE: National Microwire frame format */
+    uint32_t ClockRate;        /** Clock rate,in Hz */
+} SSP_CFG_Type;
+
+/**
+ * @brief SSP Transfer Type definitions
+ */
+typedef enum {
+    SSP_TRANSFER_POLLING = 0,    /**< Polling transfer */
+    SSP_TRANSFER_INTERRUPT        /**< Interrupt transfer */
+} SSP_TRANSFER_Type;
+
+/**
+ * @brief SPI Data configuration structure definitions
+ */
+typedef struct {
+    void *tx_data;                /**< Pointer to transmit data */
+    uint32_t tx_cnt;            /**< Transmit counter */
+    void *rx_data;                /**< Pointer to transmit data */
+    uint32_t rx_cnt;            /**< Receive counter */
+    uint32_t length;            /**< Length of transfer data */
+    uint32_t status;            /**< Current status of SSP activity */
+    void (*callback)(void);        /**< Pointer to Call back function when transmission complete
+                                used in interrupt transfer mode */
+} SSP_DATA_SETUP_Type;
+
+
+
+/* Public Macros -------------------------------------------------------------- */
+
+
+/** Macro to determine if it is valid SSP port number */
+#define PARAM_SSPx(n)    ((((uint32_t *)n)==((uint32_t *)LPC_SSP0)) \
+|| (((uint32_t *)n)==((uint32_t *)LPC_SSP1)))
+
+/*********************************************************************//**
+ * SSP configuration parameter defines
+ **********************************************************************/
+/** Clock phase control bit */
+#define SSP_CPHA_FIRST            ((uint32_t)(0))
+#define SSP_CPHA_SECOND            SSP_CR0_CPHA_SECOND
+#define PARAM_SSP_CPHA(n)         ((n==SSP_CPHA_FIRST) || (n==SSP_CPHA_SECOND))
+
+/** Clock polarity control bit */
+/* There's no bug here!!!
+ * - If bit[6] in SSPnCR0 is 0: SSP controller maintains the bus clock low between frames.
+ * That means the active clock is in HI state.
+ * - If bit[6] in SSPnCR0 is 1 (SSP_CR0_CPOL_HI): SSP controller maintains the bus clock
+ * high between frames. That means the active clock is in LO state.
+ */
+#define SSP_CPOL_HI                ((uint32_t)(0))
+#define SSP_CPOL_LO                SSP_CR0_CPOL_HI
+#define PARAM_SSP_CPOL(n)        ((n==SSP_CPOL_HI) || (n==SSP_CPOL_LO))
+
+/** SSP master mode enable */
+#define SSP_SLAVE_MODE            SSP_CR1_SLAVE_EN
+#define SSP_MASTER_MODE            ((uint32_t)(0))
+#define PARAM_SSP_MODE(n)        ((n==SSP_SLAVE_MODE) || (n==SSP_MASTER_MODE))
+
+/** SSP data bit number defines */
+#define SSP_DATABIT_4        SSP_CR0_DSS(4)             /*!< Databit number = 4 */
+#define SSP_DATABIT_5        SSP_CR0_DSS(5)             /*!< Databit number = 5 */
+#define SSP_DATABIT_6        SSP_CR0_DSS(6)             /*!< Databit number = 6 */
+#define SSP_DATABIT_7        SSP_CR0_DSS(7)             /*!< Databit number = 7 */
+#define SSP_DATABIT_8        SSP_CR0_DSS(8)             /*!< Databit number = 8 */
+#define SSP_DATABIT_9        SSP_CR0_DSS(9)             /*!< Databit number = 9 */
+#define SSP_DATABIT_10        SSP_CR0_DSS(10)         /*!< Databit number = 10 */
+#define SSP_DATABIT_11        SSP_CR0_DSS(11)         /*!< Databit number = 11 */
+#define SSP_DATABIT_12        SSP_CR0_DSS(12)         /*!< Databit number = 12 */
+#define SSP_DATABIT_13        SSP_CR0_DSS(13)         /*!< Databit number = 13 */
+#define SSP_DATABIT_14        SSP_CR0_DSS(14)         /*!< Databit number = 14 */
+#define SSP_DATABIT_15        SSP_CR0_DSS(15)         /*!< Databit number = 15 */
+#define SSP_DATABIT_16        SSP_CR0_DSS(16)         /*!< Databit number = 16 */
+#define PARAM_SSP_DATABIT(n)     ((n==SSP_DATABIT_4) || (n==SSP_DATABIT_5) \
+|| (n==SSP_DATABIT_6) || (n==SSP_DATABIT_16) \
+|| (n==SSP_DATABIT_7) || (n==SSP_DATABIT_8) \
+|| (n==SSP_DATABIT_9) || (n==SSP_DATABIT_10) \
+|| (n==SSP_DATABIT_11) || (n==SSP_DATABIT_12) \
+|| (n==SSP_DATABIT_13) || (n==SSP_DATABIT_14) \
+|| (n==SSP_DATABIT_15))
+
+/** SSP Frame Format definition */
+/** Motorola SPI mode */
+#define SSP_FRAME_SPI        SSP_CR0_FRF_SPI
+/** TI synchronous serial mode */
+#define SSP_FRAME_TI        SSP_CR0_FRF_TI
+/** National Micro-wire mode */
+#define SSP_FRAME_MICROWIRE    SSP_CR0_FRF_MICROWIRE
+
+#define PARAM_SSP_FRAME(n) ((n==SSP_FRAME_SPI) || (n==SSP_FRAME_TI)\
+|| (n==SSP_FRAME_MICROWIRE))
+
+
+/*********************************************************************//**
+ * SSP Status defines
+ **********************************************************************/
+/** SSP status TX FIFO Empty bit */
+#define SSP_STAT_TXFIFO_EMPTY        SSP_SR_TFE
+/** SSP status TX FIFO not full bit */
+#define SSP_STAT_TXFIFO_NOTFULL        SSP_SR_TNF
+/** SSP status RX FIFO not empty bit */
+#define SSP_STAT_RXFIFO_NOTEMPTY    SSP_SR_RNE
+/** SSP status RX FIFO full bit */
+#define SSP_STAT_RXFIFO_FULL        SSP_SR_RFF
+/** SSP status SSP Busy bit */
+#define SSP_STAT_BUSY                SSP_SR_BSY
+
+#define PARAM_SSP_STAT(n) ((n==SSP_STAT_TXFIFO_EMPTY) || (n==SSP_STAT_TXFIFO_NOTFULL) \
+|| (n==SSP_STAT_RXFIFO_NOTEMPTY) || (n==SSP_STAT_RXFIFO_FULL) \
+|| (n==SSP_STAT_BUSY))
+
+
+/*********************************************************************//**
+ * SSP Interrupt Configuration defines
+ **********************************************************************/
+/** Receive Overrun */
+#define SSP_INTCFG_ROR        SSP_IMSC_ROR
+/** Receive TimeOut */
+#define SSP_INTCFG_RT        SSP_IMSC_RT
+/** Rx FIFO is at least half full */
+#define SSP_INTCFG_RX        SSP_IMSC_RX
+/** Tx FIFO is at least half empty */
+#define SSP_INTCFG_TX        SSP_IMSC_TX
+
+#define PARAM_SSP_INTCFG(n)    ((n==SSP_INTCFG_ROR) || (n==SSP_INTCFG_RT) \
+|| (n==SSP_INTCFG_RX) || (n==SSP_INTCFG_TX))
+
+
+/*********************************************************************//**
+ * SSP Configured Interrupt Status defines
+ **********************************************************************/
+/** Receive Overrun */
+#define SSP_INTSTAT_ROR        SSP_MIS_ROR
+/** Receive TimeOut */
+#define SSP_INTSTAT_RT        SSP_MIS_RT
+/** Rx FIFO is at least half full */
+#define SSP_INTSTAT_RX        SSP_MIS_RX
+/** Tx FIFO is at least half empty */
+#define SSP_INTSTAT_TX        SSP_MIS_TX
+
+#define PARAM_SSP_INTSTAT(n) ((n==SSP_INTSTAT_ROR) || (n==SSP_INTSTAT_RT) \
+|| (n==SSP_INTSTAT_RX) || (n==SSP_INTSTAT_TX))
+
+
+/*********************************************************************//**
+ * SSP Raw Interrupt Status defines
+ **********************************************************************/
+/** Receive Overrun */
+#define SSP_INTSTAT_RAW_ROR        SSP_RIS_ROR
+/** Receive TimeOut */
+#define SSP_INTSTAT_RAW_RT        SSP_RIS_RT
+/** Rx FIFO is at least half full */
+#define SSP_INTSTAT_RAW_RX        SSP_RIS_RX
+/** Tx FIFO is at least half empty */
+#define SSP_INTSTAT_RAW_TX        SSP_RIS_TX
+
+#define PARAM_SSP_INTSTAT_RAW(n)    ((n==SSP_INTSTAT_RAW_ROR) || (n==SSP_INTSTAT_RAW_RT) \
+|| (n==SSP_INTSTAT_RAW_RX) || (n==SSP_INTSTAT_RAW_TX))
+
+
+/*********************************************************************//**
+ * SSP Interrupt Clear defines
+ **********************************************************************/
+/** Writing a 1 to this bit clears the "frame was received when
+ * RxFIFO was full" interrupt */
+#define SSP_INTCLR_ROR        SSP_ICR_ROR
+/** Writing a 1 to this bit clears the "Rx FIFO was not empty and
+ * has not been read for a timeout period" interrupt */
+#define SSP_INTCLR_RT        SSP_ICR_RT
+
+#define PARAM_SSP_INTCLR(n)    ((n==SSP_INTCLR_ROR) || (n==SSP_INTCLR_RT))
+
+
+/*********************************************************************//**
+ * SSP DMA defines
+ **********************************************************************/
+/** SSP bit for enabling RX DMA */
+#define SSP_DMA_TX        SSP_DMA_RXDMA_EN
+/** SSP bit for enabling TX DMA */
+#define SSP_DMA_RX        SSP_DMA_TXDMA_EN
+
+#define PARAM_SSP_DMA(n)    ((n==SSP_DMA_TX) || (n==SSP_DMA_RX))
+
+/* SSP Status Implementation definitions */
+#define SSP_STAT_DONE        (1UL<<8)        /**< Done */
+#define SSP_STAT_ERROR        (1UL<<9)        /**< Error */
+
+#endif /* LPC17XX_SSP_H_ */
+
+/* --------------------------------- End Of File ------------------------------ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sun Feb 27 18:54:40 2011 +0000
@@ -0,0 +1,125 @@
+/* MMEx for MBED - Main function
+ * 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 main.cpp
+  \brief main function for the MMEx application
+*/
+
+#include "mmex.h"
+#include "mbed.h"
+
+/** read data from the commandline until a <CR> is found
+ *
+ *  @return returns the number of characters read (including the <CR>)
+ */
+int readin() {
+  int i = 0;
+  bool go = true;
+  unsigned char inp;
+
+  while (go) {                  // as long as we can continue          
+    inp = mldl.rxx_read(command_mode);    // read data with protocol    
+    switch (inp) {
+      case NULL : break;         // do nothing, read next value
+      case c_cr : inbuf[i] = NULL;  //terminate string
+                  go = false;
+                  break;
+      default:    inbuf[i] = inp;
+                  i++;
+                  break;
+    }  // switch
+    if(i >= bufsize) {               // command is too long!
+      // add proper error handling
+      go = false;
+      inbuf[i] = NULL;          // terminate string 
+    }
+  }  
+  return i;
+}
+
+/** MMEx main function, never returns
+ *
+ */
+int main() {
+  int numin;
+  
+  init_handles();
+  
+  pc.baud(start_baud);
+    
+  mldl.init();                // initialize spi
+  mldl.DBG_set(DBG_ON);
+  
+  welcome();                 // send welcome message
+  
+  init_loadp();              // auto load PARAM_A.TXT
+  init_xeq();                // auto execute parameter X
+  
+  while(1) {
+    // main loop for parsing commands
+    send_prompt();   
+    DBG_msg("main", "send prompt");            
+    
+    // remove comments below for more extended debugging
+    // DBG_int("rx_room", mldl.rx_room());
+    // DBG_int("tx_room", mldl.tx_room());
+    // DBG_int("rx_empty", mldl.rx_empty());
+    // DBG_int("rx_full", mldl.rx_full());
+    // DBG_int("tx_empty", mldl.tx_empty());
+    // DBG_int("tx_full", mldl.tx_full());        
+
+    numin = readin();     // read input command, must end with <CR>      
+    // we are interpreting commands, string is in inbuf[]    
+    if (inbuf[0] != NULL) { 
+      DBG_msg("main", inbuf);
+      switch (inbuf[0]) {
+        case cmd_f : param[par_C_].assign(inbuf);
+                     parse_F();        // File functions                     
+                     break;      
+        case cmd_m : param[par_C_].assign(inbuf);
+                     parse_M();        // MBed functions
+                     break;
+        case cmd_p : parse_P();        // Parameter functions
+                     break;
+        case cmd_rpc : 
+        case cmd_r:  param[par_C_].assign(inbuf);
+                     parse_R();        // RPC functions
+                     break;
+        case cmd_n : param[par_C_].assign(inbuf);
+                     parse_N();        // Network functions
+                     break;
+        case cmd_u : param[par_C_].assign(inbuf);
+                     parse_U();        // User functions
+                     break;
+        case cmd_c : param[par_C_].assign(inbuf);
+                     parse_C();        // User functions
+                     break;
+                
+        default  :   DBG_msg("do_maindefault", inbuf);
+                     do_maindefault(); // first char not recognized
+                     break;
+      }
+    }
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Sun Feb 27 18:54:40 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/63bcd7ba4912
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbeddefs.cpp	Sun Feb 27 18:54:40 2011 +0000
@@ -0,0 +1,40 @@
+/* MMEx for MBED - global declarations of MBED classes
+ * 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 mbeddefs.c
+  \brief global declarations of some MBED classes
+*/
+
+#include "mbeddefs.h"
+
+Serial pc(USBTX, USBRX, "pc");            // tx, rx
+
+DigitalOut _led1(LED1);
+DigitalOut _led2(LED2);
+DigitalOut _led3(LED3);
+DigitalOut _led4(LED4);
+DigitalIn  mldlp09(p9);
+DigitalIn  mldlp10(p10);
+
+spislirq mldl(0);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbeddefs.h	Sun Feb 27 18:54:40 2011 +0000
@@ -0,0 +1,50 @@
+/* MMEx for MBED - global declarations of MBED classes
+ * 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 mbeddefs.h
+  \brief global declarations of some MBED classes
+*/
+
+#ifndef MBEDDEFS_H
+#define MBEDDEFS_H
+
+#include "mmex.h"
+#include "spissp.h"
+
+extern Serial pc;                  // tx, rx
+extern DigitalOut _led1;
+extern DigitalOut _led2;
+extern DigitalOut _led3;
+extern DigitalOut _led4;
+extern DigitalIn  mldlp09;
+extern DigitalIn  mldlp10;
+extern spislirq mldl;
+
+/** reset the MBED module
+ *
+ */
+extern "C" void mbed_reset(); 
+
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mfuncs.cpp	Sun Feb 27 18:54:40 2011 +0000
@@ -0,0 +1,363 @@
+/* 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); 
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mfuncs.h	Sun Feb 27 18:54:40 2011 +0000
@@ -0,0 +1,66 @@
+/* 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.h
+  \brief Commands starting with M for MBED features
+*/
+
+#ifndef MFUNCS_H
+#define MFUNCS_H
+
+#include "mmex.h"
+
+// definition of the M-functions
+#define mled     'L'         // control LED's
+#define mversion 'V'         // get version string
+#define mwelcome 'W'         // get welcome string
+#define mstatus  'S'         // get MMex status
+#define mdebug   'D'         // control DEBUG level
+#define merror   'E'         // get latest error message
+#define mbaud    'B'         // set console baud rate
+#define mcase    'C'         // set case of text output
+#define mtime    'T'         // set/get mbed RTC value
+#define mreset   'R'         // MBed warm restart
+
+#define ledon    '1'         // value for LED ON
+#define ledoff   '0'         // value for LED ON
+#define ledtog   'T'         // value for LED toggle
+#define ledread  'R'         // value for LED read
+
+#define ucase    'U'         // value for Upper Case
+#define nocase   'N'         // value for no change to case
+
+void parse_M();
+void do_mled(); 
+void do_mversion();
+void do_mwelcome();
+void do_mstatus();
+void do_mdebug();
+void do_merror(); 
+void do_mreset();
+void do_mbaud();
+void do_mcase();
+void do_mtime();
+void do_mdefault();
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mmex.cpp	Sun Feb 27 18:54:40 2011 +0000
@@ -0,0 +1,121 @@
+/* MMEx for MBED - MMEx specific functions
+ * 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 mmex.cpp
+  \brief MMEx specific functions
+*/
+
+#include "mmex.h"
+
+char inbuf[bufsize];                     
+char outbuf[bufsize];
+
+int rx_max = 0;
+int tx_max = 0;
+
+int err_num = 0;       // global error number
+int last_err = 0;
+bool upcase = false;   // global for change of case for text output
+
+const char *err_text[] = { 
+  err_0,  err_1,  err_2,  NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+  err_10, err_11, err_12, err_13, err_14, err_15, err_16, err_17, err_18, err_19,
+  err_20, err_21, err_22, err_23, err_24, err_25, err_26, err_27, err_28, err_29, 
+  err_30, err_31, err_32, err_33, err_34, err_35, err_36, err_37, err_38, err_39 } ;
+
+/** send the MMEx prompt sequence
+ *
+ */  
+void send_prompt() {
+  mldl.tx_add(c_escape);
+  mldl.tx_add(c_prompt);
+}
+
+/** send the MMEx welcome message
+ *
+ */  
+void welcome() {
+  DBG_msg("MMEx welcome", msg_welcome msg_version);
+  char str[] = msg_welcome msg_version; 
+  upstring(str);
+  mldl.tx_string(str);
+}
+
+/** send the actual MMEx status
+ *
+ */  
+void send_status() {
+  char str[] = "MMEx running";
+  upstring(str);
+  mldl.tx_string(str); 
+}
+
+/** send error message, command not recognized
+ *
+ */
+void do_maindefault() {
+  // command not recognized
+  DBG_msg("main", "parameter not recognized");
+  send_error(err_notrecognized);
+}
+
+/** send an integer value to the SPI interface
+ *
+ *  @param val value to be sent
+ *
+ */  
+void send_int(int val) {
+  sprintf(outbuf, "%d", val);
+  mldl.tx_string(outbuf);
+}
+
+/** send a 2-digit integer value to the SPI interface
+ *
+ *  @param val value to be sent
+ *
+ */  
+void send_2int(int val) {
+  sprintf(outbuf, "%02d", val);
+  mldl.tx_string(outbuf);
+}
+
+/** global error message processing, send error sequence
+ *  and prepare message string
+ *
+ *  @param val error value
+ *
+ */ 
+void send_error(int val) {
+  char str[20];
+  sprintf(str, "%02d", val); 
+  err_num = val;
+  last_err = val;
+  DBG_msg("error found: ", str);
+  sprintf(str, "%02d:", err_num);
+  param[par_E_].assign(str);
+  param[par_E_] += err_text[err_num];
+  mldl.tx_add(c_escape);
+  mldl.tx_add(c_error);
+}
+ 
+ 
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mmex.h	Sun Feb 27 18:54:40 2011 +0000
@@ -0,0 +1,178 @@
+/* MMEx for MBED - MMEx specific functions
+ * 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 mmex.h
+  \brief MMEx specific functions with all global includes
+*/
+
+#ifndef MMEX_H
+#define MMEX_H
+
+#include "spissp.h"
+#include "mbed.h"
+
+#include "mbeddefs.h"
+
+#include "rpc.h"
+#include "RPCFunction.h"
+#include "RPCVariable.h"
+
+#include "helper.h"
+#include "debug.h"
+
+#include "cfuncs.h"
+#include "ffuncs.h"
+#include "mfuncs.h"
+#include "nfuncs.h"
+#include "pfuncs.h"
+#include "rfuncs.h"
+#include "ufuncs.h"
+
+#include "MSCFileSystem.h"
+#include "SDFileSystem.h"
+
+#include <string>        // allow use of string classes
+
+#include "EthernetNetIf.h"
+#include "HTTPClient.h"
+#include "NTPClient.h"
+#include "HTTPServer.h"
+#include "HTTPStream.h"
+#include "RPCFunction.h"
+
+#define bufsize 255
+
+extern char inbuf[bufsize];                     
+extern char outbuf[bufsize];
+
+extern int rx_max;
+extern int tx_max;
+
+// startup values
+#define start_baud 9600       // baudrate after startup
+
+#define c_error   'E'
+#define c_busy    'B'
+
+#define c_rpc     '/'
+#define c_rpcapp  '+'
+#define c_rpcexe  '*'
+
+// control strings
+#define cc_arrow  ">>"
+#define cc_prompt ">!"
+#define cc_null   ">N"
+#define cc_eof    ">F"
+#define cc_error  ">E"
+#define cc_busy   ">B"
+
+// main command grouping
+#define cmd_m     'M'
+#define cmd_c     'C'
+#define cmd_f     'F'
+#define cmd_r     'R'
+#define cmd_rpc   '/'
+#define cmd_n     'N'
+#define cmd_p     'P'
+#define cmd_u     'U'
+#define cmd_c     'C'
+
+#define command_mode true
+#define data_mode    false
+
+// error messages, generic
+#define noerror               0
+#define err_notimplemented    1   // command not implemented
+#define err_notrecognized     2   // invalid command parameter
+#define err_novalidcommand    3   // no valid command found
+
+// error messages, file operations
+#define err_filenotopen      10   // could not open file
+#define err_not_mounted      11   // error in mounting file
+#define err_handle_used      12   // file handle in use
+#define err_no_handle        13   // file handle not defined
+#define err_directory        14   // error in opening directory
+#define err_seek             15   // error in seek
+
+#define err_paramnoxeq       20   // error executing parameter string
+
+#define err_net_timeout      30   // network timout
+#define err_net_NTP          31   // error in NTP
+
+// error message text definitions
+#define err_0     "no error"
+#define err_1     "command not implemented"
+#define err_2     "invalid command parameter"
+#define err_3     "no valid command found"
+
+#define err_10    "could not open file"
+#define err_11    "error in mounting file"
+#define err_12    "file handle in use"
+#define err_13    "file handle not defined"
+#define err_14    "error in opening directory"
+#define err_15    "error in seek"
+#define err_16    "error"
+#define err_17    "error"
+#define err_18    "error"
+#define err_19    "error"
+#define err_20    "cannot execute paramstring"
+
+#define err_21    "error"
+#define err_22    "error"
+#define err_23    "error"
+#define err_24    "error"
+#define err_25    "error"
+#define err_26    "error"
+#define err_27    "error"
+#define err_28    "error"
+#define err_29    "error"
+
+#define err_30    "network timeout"
+#define err_31    "error in NTP"
+#define err_32    "error"
+#define err_33    "error"
+#define err_34    "error"
+#define err_35    "error"
+#define err_36    "error"
+#define err_37    "error"
+#define err_38    "error"
+#define err_39    "error"
+
+
+#define msg_welcome "MMEx "
+#define msg_version __DATE__
+
+extern int err_num;
+extern int last_err;
+extern int tmode; 
+extern bool upcase;   // global for change of case for text output
+
+void send_prompt();
+void welcome();
+void do_maindefault();
+void send_int(int val);
+void send_2int(int val);
+void send_error(int val);
+void send_status();
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nfuncs.cpp	Sun Feb 27 18:54:40 2011 +0000
@@ -0,0 +1,382 @@
+/* MMEx for MBED - Network 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 nfuncs.cpp
+  \brief Commands starting with N for Networking commands
+*/
+
+#include "nfuncs.h"
+
+EthernetNetIf *eth;
+HTTPClient http;
+HTTPResult result;
+HTTPServer *server;
+bool completed = false;
+
+/**
+ *  Global variable to indicate if network is running
+ */
+bool network_enabled = false;
+
+/**
+ *  Global variable to indicate if HTTP Server is running
+ */
+bool httpserver_enabled = false; 
+ 
+/**
+ *  Poll the network (must be called periodically while server is active)
+ */
+void netpoll() 
+{
+  if (network_enabled) {
+    _led3 = 1;
+    Net::poll();
+    _led3 = 0;
+  }
+}
+
+/** main entry for parsing C-commands
+ *
+ */
+void parse_N() {
+  // process parameters
+  DBG_msg("parse_N", inbuf);
+  err_num = noerror;
+ 
+  wipesp(inbuf);                    // remove all spaces from string
+
+  if (inbuf[1] != NULL) {
+    switch (inbuf[1]) {
+      case ninit    : do_ninit();
+                      break;
+      case nstop    : do_nstop();
+                      break;
+      case ntime    : do_ntime();
+                      break;                    
+      case nget     : do_nget();
+                      break;      
+      case nhttp    : do_nhttp();
+                      break;                                        
+      default       : do_ndefault();    // command not recognized
+                      break;
+    }
+  } else { do_ndefault(); }
+}
+            
+/** initialize the network interface
+ *
+ *  syntax: NI
+ */
+void do_ninit() {
+  char * hostname;
+  char * ipnums;
+  char s[50];
+  char ips[4][25];
+
+  DBG_msg("do_ninit", "Network initialisation\n");
+  
+  EthernetErr ethErr;
+
+  // check for alternate hostname in parameters
+  hostname = new char [param[par_H_].size() + 1];     // Host parameter
+  strcpy (hostname, param[par_H_].c_str());
+  if (hostname == NULL) hostname = MMEx_Hostname;
+  
+  // check for DCHP or not
+  // Parameter J is the fixed IP address in the following format:
+  //   ip netmask gateway dns
+  // each ip address is in the format x.y.z.t, separated by spaces
+  // When Param J is empty, DHCP will be used
+  ipnums =  new char [param[par_J_].size() + 1];     // Host parameter
+  strcpy (ipnums, param[par_J_].c_str());  
+  
+  
+  if (param[par_J_].size()< 10) {
+    DBG_msg("do_ninit", "DHCP config"); 
+    // DHCP chosen, initialize network
+    eth = new EthernetNetIf(hostname);
+    
+    // eth->setup();
+  } else {
+    // process fixed IP adresses
+    DBG_msg("do_ninit", "fixed IP"); 
+    DBG_msg("IP adresses", ipnums); 
+    
+    IpAddr *ipparam[4];
+    sscanf(ipnums, "%s %s %s %s", ips[0], ips[1], ips[2], ips[3]);
+    DBG_msg("IP number", ips[0]);
+    DBG_msg("netmask  ", ips[1]);
+    DBG_msg("gateway  ", ips[2]);
+    DBG_msg("dns      ", ips[3]);
+    
+    for ( int i = 0; i < 4; ++i ) {   
+      int ip1, ip2, ip3, ip4;
+      sscanf(ips[i], "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4);
+      ipparam[i] = new IpAddr(ip1, ip2, ip3, ip4);
+    }      
+    // Setup IP with given adresses
+    eth = new EthernetNetIf(*ipparam[0],*ipparam[1],*ipparam[2],*ipparam[3]);
+    // eth->setup();
+  }
+  
+  int count = 0;
+  do {
+      DBG_int("do_ninit setup", ++count);
+      ethErr = eth->setup();
+      if (ethErr) DBG_int("do_ninit timeout", ethErr);
+  } while ((ethErr != ETH_OK) && (count < 5));   
+     
+  if (ethErr == ETH_OK) {
+    // connection worked 
+    network_enabled = true;
+    mldl.attach(&netpoll);  
+    DBG_msg("do_ninit", "Connected OK\n");
+    const char* hwAddr = eth->getHwAddr();
+    sprintf(s, "%02x:%02x:%02x:%02x:%02x:%02x",
+               hwAddr[0], hwAddr[1], hwAddr[2], hwAddr[3], hwAddr[4], hwAddr[5]);
+    DBG_msg("ninit MAC addr", s);   
+    param[par_M_].assign(s);             // set MAC address
+
+    IpAddr ethIp = eth->getIp();
+    sprintf(s, "%d.%d.%d.%d", ethIp[0], ethIp[1], ethIp[2], ethIp[3]);
+    upstring(s);    
+    DBG_msg("ninit MAC addr", s);
+    param[par_I_].assign(s);            // set MAC address 
+    
+    sprintf(s, "%s", eth->getHostname());
+    DBG_msg("ninit Hostname", s);
+    param[par_H_].assign(s);            // set Hostname
+  } else {
+    // in case initialization did not work
+    network_enabled = false;
+    DBG_msg("ninit", "network timout");
+    send_error(err_net_timeout);
+  }
+}
+
+/** stop the network interface
+ *
+ *  syntax: NS
+ */
+void do_nstop() {
+  DBG_msg("do_nstop", inbuf);
+  mldl.attach(NULL);  
+  delete eth;
+  network_enabled = false;
+}      
+      
+/** get network time
+ *
+ *  syntax: NT
+ *  URL of NTP server must be in parameter U
+ */
+void do_ntime() {
+  char s[255];  // for intermediate results
+  char s1[255]; // for intermediate results
+  time_t ctTime;
+  NTPClient ntp;
+  DBG_msg("do_ntime", inbuf);
+  
+  ctTime = time(NULL);         // current system time
+  sprintf(s, "%d %s", ctTime, ctime(&ctTime));
+  DBG_msg("MMEx time", s);
+  strcpy(s, param[par_U_].c_str());    // URL from parameter U
+  
+  Host server(IpAddr(), 123, s);
+  NTPResult r =  ntp.setTime(server);
+  if (r == NTP_OK) {
+    // time set
+    ctTime = time(NULL);
+    sprintf(s1, "%d %s", ctTime, ctime(&ctTime));
+    DBG_msg("MMEx time", s1);
+  } else {
+    // error in setting the time    
+    send_error(err_net_NTP);
+  }
+}         
+
+
+void request_callback(HTTPResult r) {
+  result = r;
+  completed = true;
+}
+
+/** get file through HTTP Stream
+ *
+ *  syntax: NG
+ *  URL of must be in parameter U, %n may be used for filename
+ */
+void do_nget() {
+
+  HTTPStream stream;
+  char Buf[512 + 1] = {0};
+  char s[255];    // for temp storage
+  int pnum, pos, count;
+  char * cstr;
+  int rdata, i;
+  bool go = true;
+  bool stopread = false;
+  int numbytes = 0;
+  
+  DBG_msg("do_nget", inbuf);
+  
+  completed = false;
+  
+  count = 0;
+  // next chars on the commandline is the number of bytes to read
+  if (inbuf[2] == NULL) {
+    // no value on the command line
+    numbytes = 0;
+  } else {
+    // now process line
+    for (i = 2; ((inbuf[i] >='0') && (inbuf[i] <= '9')); i++ ) {
+      numbytes = 10 * numbytes + (inbuf[i] - '0');
+    }
+  }
+  DBG_int("do_nget bytes:", numbytes);
+  
+  stream.readNext((byte*)Buf, 512);   //Point to buffer for the first read  
+  strcpy(s, param[par_U_].c_str());   // URL from parameter U
+    
+  // check for a % sign in s
+  pos = 0;
+  while ((s[pos] != NULL) && (s[pos] != c_percent)) pos++;  
+  if ((s[pos] != NULL) && ((pnum = getpnum(s[pos + 1])) >= 0)) {
+    // found and valid parameter, now insert
+    cstr = new char [param[pnum].size() + 1];
+    strcpy (cstr, param[pnum].c_str());
+    DBG_msg("param", cstr);
+    DBG_int("pos", pos);
+    remchar(s, pos, 2);           // remove %n, works better for insert
+    DBG_msg("do_nget", s); 
+    insertstr(s, cstr, pos);  // insert
+    DBG_msg("do_nget", s); 
+    delete[] cstr;
+  }
+    
+  HTTPResult r = http.get(s, &stream, request_callback);      // try to get the data
+  
+  // this is the main loop for reading the file
+  while((!completed)) {
+    Net::poll(); // polls the Networking stack
+    if(stream.readable()) {     
+      rdata = stream.readLen();  // number of bytes read   
+      DBG_int("rdata", rdata);   
+      Buf[stream.readLen()] = 0;  //Transform this buffer in zero-terminated char* string
+      
+      // now send data to our transmit buffer
+      i = 0;
+      while (go && (i < rdata)) {
+        DBG_chr("rd", Buf[i]);
+        mldl.tx_addp(Buf[i]);
+        i++;
+        count++;
+        // now check if we have to stop?    
+        if (!mldl.rx_empty()) {
+          stopread = (mldl.rxx_read(data_mode) < 0);   // intentional stop of read 
+          DBG_msg("do_nget", "forced stop");       
+        } 
+        go = !((count == numbytes) || stopread);
+      }
+      
+      //Buffer has been read, now we can put more data in it
+      stream.readNext((byte*)Buf, 512); 
+    }
+  }
+  
+  // we are done with the required number of bytes or found EOF
+  if (!stopread && (count != numbytes)) {
+    // real EOF found, so terminate by sending EOF
+    mldl.tx_add(c_escape);
+    mldl.tx_add(c_eof); 
+    DBG_int("do_nget: EOF at byte ", count);
+  }      
+      
+  if (stopread) {
+    DBG_msg("do_nget", "forced stop read received");
+    mldl.flush_tx();    // empty transmit buffer
+  }  
+    
+  DBG_int("do_nget: end read at byte ", count);
+}
+
+/** HTTP Server commands
+ *
+ * syntax: NHI[medium]: initialise and start HTTP Server
+ * [medium] = S, U or L for the filesystem to be used
+ * default filesystem is "/local"
+ * \n NHS: stop HTTP Server
+ *
+ */  
+void do_nhttp() {
+  char c;
+  char medium[10];
+  
+  DBG_msg("do_nhttp", inbuf);
+  
+  c = inbuf[3];            // [medium]
+  switch (c) {
+    case f_sdcard : strcpy(medium, rt_sd);    // "/sd"
+                    break;                   
+    case f_local  : strcpy(medium, rt_local); // "/local"
+                    break;                      
+    case f_usb    : strcpy(medium, rt_usb);   //  "/usb"
+                    break;                                            
+    default       : strcpy(medium, "/local"); // default
+                    break;    
+  } 
+
+  if (inbuf[2] == ninit) {
+    // HTTP server initialize
+    DBG_msg("HTTP Init", medium);
+    if (!network_enabled) do_ninit();
+    server = new HTTPServer;
+    FSHandler::mount(medium, "/" );
+    server->addHandler<FSHandler>("/");
+    server->addHandler<RPCHandler>("/rpc");
+    server->addHandler<SimpleHandler>("/simple");
+    server->bind(80);
+    httpserver_enabled = true; 
+    DBG_msg( "HTTP server", "started" );          
+    return;
+  }
+  
+  if (inbuf[2] == nstop) {    
+    // HTTP Server stop
+    delete server;
+    httpserver_enabled = false;
+    DBG_msg( "HTTP server", "stopped" );
+    return;
+  }
+ 
+  do_ndefault();
+}
+             
+/** send error message, command not recognized
+ *
+ */                              
+void do_ndefault() {
+  // command not recognized
+  DBG_msg("do_ndefault", inbuf);
+  send_error(err_notrecognized); 
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nfuncs.h	Sun Feb 27 18:54:40 2011 +0000
@@ -0,0 +1,65 @@
+/* MMEx for MBED - Network 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 nfuncs.h
+  \brief Commands starting with N for Networking commands
+*/
+
+#ifndef NFUNCS_H
+#define NFUNCS_H
+
+#include "mmex.h"
+
+// definition of the N-functions for Network
+#define ninit    'I'         // Initialize network
+#define nstop    'S'         // Stop Network
+#define ntime    'T'         // Get time through NTP server
+#define nget     'G'         // Get file data
+#define nhttp    'H'         // HTTP Server commands
+
+#define MMEx_Hostname "MMEx"
+
+/**
+ *  Global variable to enable/disable the HTTP-Server
+ */
+extern bool network_enabled;
+
+/**
+ *  Global variable to indicate if HTTP Server is running
+ */
+extern bool httpserver_enabled; 
+
+/**
+ *  Poll the network (must be called periodically while server is active)
+ */
+void netpoll();
+
+void parse_N();
+void do_ninit();
+void do_nstop();
+void do_ntime();
+void do_nget();
+void do_nhttp();
+void do_ndefault();
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pfuncs.cpp	Sun Feb 27 18:54:40 2011 +0000
@@ -0,0 +1,428 @@
+/* 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); 
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pfuncs.h	Sun Feb 27 18:54:40 2011 +0000
@@ -0,0 +1,103 @@
+/* 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.h
+  \brief Commands starting with P for processing Parameters
+*/
+
+#ifndef PFUNCS_H
+#define PFUNCS_H
+
+#include "mmex.h"
+#include <string>        // allow use of string classes
+
+// definition of the P-functions
+#define pclear   'C'         // Clear Parameter
+#define pset     'S'         // Set Parameter to value
+#define pget     'G'         // Get Parameter
+#define plen     'L'         // return the length of the parameter string
+#define psave    'V'         // Save all parameters to LocalDisk
+#define pread    'R'         // Read all parameters from LocalDisk
+#define pxeq     'X'         // Execute parameter string as command
+
+// definitions for the user defined parameters
+#define par_0    '0'         // 0, user parameter
+#define par_1    '1'         // 1, user parameter
+#define par_2    '2'         // 2, user parameter
+#define par_3    '3'         // 3, user parameter
+#define par_4    '4'         // 4, user parameter
+#define par_5    '5'         // 5, user parameter
+#define par_6    '6'         // 6, user parameter
+#define par_7    '7'         // 7, user parameter
+#define par_8    '8'         // 8, user parameter
+#define par_9    '9'         // 9, user parameter
+
+// other parameters predefined
+#define par_E    'E'         // (10) E: most recent Error message
+#define par_R    'R'         // (11) R: RPC Command string
+#define par_S    'S'         // (12) S: RPC Result string
+#define par_C    'C'         // (13) C: Most recent MMEx command
+#define par_X    'X'         // (14) X: Auto execute command string
+
+// Networking parameters
+#define par_I    'I'         // (15) I: Network IP Address
+#define par_J    'J'         // (16) J: Network IP Address when no DHCP
+#define par_H    'H'         // (17) H: Network Host name
+#define par_M    'M'         // (18) M: Network MAC hardware address
+#define par_U    'U'         // (19) U: Network URL
+#define par_N    'N'         // (20) N: Networkl User name
+#define par_P    'P'         // (21) P: Network Password
+
+#define par_E_   10          // (10) E: most recent Error message
+#define par_R_   11          // (11) R: RPC Command string
+#define par_S_   12          // (12) S: RPC Result string
+#define par_C_   13          // (13) C: Most recent command string
+#define par_X_   14          // (14) X: Auto execute command string
+
+#define par_I_   15          // (15) I: Network IP Address
+#define par_J_   16          // (16) J: Network IP Address when no DHCP
+#define par_H_   17          // (17) H: Network Host name
+#define par_M_   18          // (18) M: Network MAC hardware address
+#define par_U_   19          // (19) U: Network URL
+#define par_N_   20          // (20) N: Networkl User name
+#define par_P_   21          // (21) P: Network Password
+
+
+#define maxparams 21          // number of last parameter
+
+extern string param[maxparams + 1];  // our array of parameter strings
+
+int getpnum(char C);
+void parse_P();
+void do_pclear(); 
+void do_pset();
+void do_pget();
+void do_plen();
+void do_psave();
+void do_pread();
+void do_pxeq();
+void init_loadp();  
+void init_xeq();
+void do_pdefault();
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rfuncs.cpp	Sun Feb 27 18:54:40 2011 +0000
@@ -0,0 +1,120 @@
+/* MMEx for MBED - RPC 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 rfuncs.cpp
+  \brief Commands starting with R or / for processing RPC
+*/
+
+#include "rfuncs.h"
+
+/** main entry for parsing R- or /-commands
+ *
+ */ 
+void parse_R() {
+  DBG_msg("parse_R", inbuf);
+  err_num = noerror;
+
+  if (inbuf[1] != NULL) {
+    switch (inbuf[1]) {
+      case rslash  : do_rslash();
+                     break;
+      case rresult : do_rresult();
+                     break;
+      case rxeq    : do_rxeq();
+                     break;            
+      default      : do_rdefault();    // command not recognized
+                     break;
+    }
+  } else { do_rdefault(); }
+}
+
+/** Define the value of the PC command string
+ *
+ *  syntax:  R/[string]      define new RPX command (same as //)
+ *  \n  or: R/>+[string]    appends to existing RPC string
+ *
+ */   
+void do_rslash() {   
+  DBG_msg("do_rslash", inbuf);
+  
+  while (inbuf[2] == c_space) remchar(inbuf, 2, 1);  // remove leading space
+  remchar(inbuf, 0, 1);                  // remove the R of 1st slash
+  
+  // now retrieve string from the command line, i starts at 3
+
+  // if first chars are not ">+" the string will be new
+  if ((inbuf[3] == c_escape) && (inbuf[4] == c_append)) {      
+    // string is append, >+ from inbuf
+    remchar(inbuf, 1, 2);
+    DBG_msg("append RPC cmd", inbuf);
+    param[par_R_].append(inbuf);    
+  } else {    
+    DBG_msg("new RPC cmd ", inbuf);
+    param[par_R_].assign(inbuf);      // no append, assign string
+  }    
+}
+
+/** Return the result of the previous RPC operation
+ *
+ *  syntax:  RR or /R
+ */ 
+void do_rresult() {
+  char * cstr;
+  
+  DBG_msg("do_rresult", inbuf);
+  cstr = new char [param[par_S_].size() + 1];
+  strcpy(cstr, param[par_S_].c_str());
+  DBG_msg("RPC result", cstr); 
+  upstring(cstr);
+  mldl.tx_string(cstr);  
+  delete[] cstr;
+}
+
+/** Execute the current RPC string
+ *
+ *  syntax:  RX or /X
+ */
+void do_rxeq() {
+  char outbuf[256];
+  char * cstr;
+      
+  DBG_msg("do_rxeq", inbuf);
+  
+  cstr = new char [param[par_R_].size() + 1];
+  strcpy(cstr, param[par_R_].c_str());
+  DBG_msg("RPC execute", cstr);    
+
+  rpc(cstr, outbuf);                // do the RPC
+  delete[] cstr;
+  
+  DBG_msg("RPC result", outbuf);  
+  param[par_S_].assign(outbuf);     // store result
+}
+
+/** send error message, command not recognized
+ *
+ */    
+void do_rdefault() {
+  DBG_msg("do_rdefault", inbuf);
+  send_error(err_notrecognized); 
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rfuncs.h	Sun Feb 27 18:54:40 2011 +0000
@@ -0,0 +1,46 @@
+/* MMEx for MBED - RPC 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 rfuncs.h
+  \brief Commands starting with R or / for processing RPC
+*/
+
+#ifndef RFUNCS_H
+#define RFUNCS_H
+
+#include "mmex.h"
+
+// definition of the R-functions for RPC
+#define rslash   '/'         // Define RPC command string
+#define rresult  'R'         // Return RPC result string
+#define rxeq     'X'         // Execute RPC command
+
+#define MMEx_Hostname "MMEx"
+
+void parse_R();
+void do_rslash();
+void do_rresult();
+void do_rxeq();
+void do_rdefault();
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/spissp/spissp.cpp	Sun Feb 27 18:54:40 2011 +0000
@@ -0,0 +1,510 @@
+/* MMEx for MBED - SPI interfacing and ringbuffer functions
+ * 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 spissp.cpp
+  \brief SPI interfacing and ringbuffer functions
+*/
+
+#include "spissp.h"
+
+ /** Library for the interrupt driven SPI SLave
+ *
+ */
+spislirq *spislirq::instance;
+
+ /** Library for the interrupt driven SPI SLave
+ *
+ */
+spislirq::spislirq (int PortNum): smldl(p11, p12, p13, p14), 
+                                  pc(USBTX, USBRX, "pc"), _led4(LED4)
+  { }
+
+/** initialization of SPI Slave and buffers
+ *  
+ */
+void spislirq::init()   {
+    uint32_t tmp;
+
+    smldl.format(8,3);             // SPI format: 8 bits, mode 3
+                                   // mode | POL PHA
+                                   // -----+--------
+                                   //   0  |  0   0
+                                   //   1  |  0   1
+                                   //   2  |  1   0
+                                   //   3  |  1   1
+    smldl.frequency(1000000);      // more or less universal speed at 1 MHz
+                                   // determines time out IRQ time!
+
+    // initialize buffers
+    rx_in = 0;
+    rx_out = 0;
+    tx_in = 0;
+    tx_out = 0;
+
+    // add code here to set the SSP interrupt register and enable interrupts
+    // setup IMSC Interrupt Mask Set/Clear Register
+    // only enable interrupts for RX FIFO half full and RX timeout
+    tmp = (SSP_IMSC_RT | SSP_IMSC_RX) & SSP_IMSC_BITMASK;
+
+    LPC_SSP0->IMSC = tmp;
+
+    // attach our interrupt service routine
+    instance = this;
+    NVIC_SetVector(SSP0_IRQn, (uint32_t)&_spi_isr);
+    enable_irq();
+ }
+
+/** disable SSP0 interrupts
+ *  will discard the byte if buffer full
+ */
+ void spislirq::disable_irq(void)
+{
+    NVIC_DisableIRQ(SSP0_IRQn);
+}
+
+/** enable SSP0 interrupts
+ *  will discard the byte if buffer full
+ */
+void spislirq::enable_irq(void)
+{
+    NVIC_EnableIRQ(SSP0_IRQn);
+}
+
+/** instantiation of isr
+ *  will discard the byte if buffer full
+ */
+void spislirq::_spi_isr(void)
+{
+    instance->spi_isr();
+}
+
+/** add one byte to the transmit buffer, no blocking, no protocol
+ *  will discard the byte if buffer full
+ *
+ *  @param c byte to send
+ *
+ */
+void spislirq::txx_add(unsigned char c) {
+  if (!tx_full()) {
+    txxbuf[tx_in] = c;
+    tx_in = (tx_in + 1) % bufsize;
+  }
+}
+
+/** SPI SLave interrupt service routine
+ *
+ */
+void spislirq::spi_isr(void)
+{
+  uint16_t inp;
+
+  _led4 = !_led4;   // visualize we are in the isr
+
+  // we get in the ISR when there is at least one input char pending
+  // IRQ sources: - RX FIFO at least half full (4 chars)
+  //              - RX FIFO not empty and not read from a time-out period
+
+
+  // first we check if there is enough room left in the RX buffer
+  // if there is less than 10% left we signal this to the SPI Master
+  // is is very unlikely that the TX buffer is full when there is risk for
+  // overrun, but we can always send the '>B' the next time, as there will
+  // be more than 20 free chars in the buffer
+  if (rx_perc() > 90) {
+    txx_add('>');
+    txx_add('B');
+  }
+
+  // now do the real work, just like in spi_rw():
+  // 1. fill output FIFO with data from TX buffer
+
+  while ((!tx_empty()) && tx_fifo_notfull) {
+    // we can indeed try to transmit data
+    // put as much data as possible in the transmit FIFO
+    LPC_SSP0->DR =  (uint16_t)txxbuf[tx_out];
+    tx_out = (tx_out + 1) % bufsize;
+  }
+
+  // in case the TX FIFO and output buffer are empty, add 0x00
+  if (tx_empty() && tx_fifo_empty) {
+    LPC_SSP0->DR =  (uint16_t)0x00;
+  }
+
+  if irq_RTMIS {
+    // interrupt on timeout, clear RTIC to clear interrupt
+    LPC_SSP0->ICR = (SSP_ICR_RT & SSP_ICR_BITMASK);
+  }
+
+  // we must ensure that always the complete RX FIFO is read
+  // when the RX buffer is really full, characters are discarded
+  while (rx_fifo_notempty) {
+    inp = LPC_SSP0->DR;
+    if ((inp != 0x00) && !rx_full()) {
+      // received value only interesting when not 0x00
+      rxxbuf[rx_in] = inp;
+      rx_in = (rx_in + 1) % bufsize;
+    }
+  }
+}
+
+
+/** returns the number of bytes available in the transmit buffer
+ *
+ *  @return available space in transmit buffer
+ */
+int spislirq::tx_room() {
+  if (tx_in < tx_out) {
+    return(tx_out - tx_in - 1);
+  } else {
+    return(bufsize - tx_in + tx_out - 1);
+  }
+}
+
+/** returns the percentage used in the transmit buffer
+ *
+ *  @return percentage from 0 to 100
+ */
+int spislirq::tx_perc() {
+  // returns the percentage used in the transmit buffer
+  return(100 * tx_use() / bufsize);
+}
+
+/** returns the percentage used in the receive buffer
+ *
+ *  @return percentage from 0 to 100
+ */
+int spislirq::rx_perc() {
+  // returns the percentage used in the transmit buffer
+  return(100 * rx_use() / bufsize);
+}
+
+
+/** returns the amount af actual bytes used in the transmit buffer
+ *
+ *  @return bytes used in transmit buffer
+ */
+int spislirq::tx_use() {
+  return(bufsize - tx_room() - 1);
+}
+
+/** returns the number of bytes available in the receive buffer
+ *
+ *  @return available space in transmit buffer
+ */
+int spislirq::rx_room() {
+  if (rx_in < rx_out) {
+    return(rx_out - rx_in - 1);
+  } else {
+    return(bufsize - rx_in + rx_out -1);
+  }
+}
+
+/** returns the amount af actual bytes used in the receive buffer
+ *
+ *  @return bytes used in receive buffer
+ */
+int spislirq::rx_use() {
+  return(bufsize - rx_room() - 1);
+}
+
+/** empties the transmit buffer
+ */
+void spislirq::flush_tx() {
+  tx_out = tx_in = 0;
+}
+
+/** empties the receive buffer
+ */
+void spislirq::flush_rx() {
+  rx_out = rx_in = 0;
+}
+
+/** check if the TX buffer is empty
+ * @return true if the TX buffer is empty
+ */
+bool spislirq::tx_empty() {
+  return (tx_in == tx_out);
+}
+
+/** check if the TX buffer is full
+ * @return true if the TX buffer is full
+ */
+bool spislirq::tx_full() {
+  return(((tx_in + 1) % bufsize) == tx_out);
+}
+
+/** check if the RX buffer is empty
+ * @return true if the RX buffer is empty
+ */
+bool spislirq::rx_empty() {
+  return(rx_in == rx_out);
+}
+
+/** check if the RX buffer is full
+ * @return true if the RX buffer is full
+ */
+bool spislirq::rx_full() {
+  return(((rx_in + 1) % bufsize) == rx_out);
+}
+
+/** add one byte to the transmit buffer, no protocol handling is done
+ *
+ *  @param Bt byte to send
+ *  @return 0 when succesfull, will block until there is room in the buffer
+ *
+ */
+int spislirq::tx_add(unsigned char c) {
+  while (tx_full()) {
+    do_callback();
+    wait_ms(1);
+  }
+  do_callback();
+  disable_irq();
+  if (!tx_full()) {
+    txxbuf[tx_in] = c;
+    tx_in = (tx_in + 1) % bufsize;
+    enable_irq();
+    // DBG_outchar(c);
+    return 0;
+  } else {
+    enable_irq();
+    return -1;
+  }
+}
+
+/** add one byte to the transmit buffer with protocol handling,
+ *  function will block until there is room in the transmit buffer
+ *
+ *  @param Bt byte to send
+ */
+void spislirq::tx_addp(unsigned char c) {
+  // first empty buffer to at least 90%
+  switch (c) {
+    case c_arrow  : tx_add(c_escape);    // to send the > character
+                    tx_add(c_arrow);     // to send the > character
+                    break;
+    case NULL     : tx_add(c_escape);    // to send the > character
+                    tx_add(c_null);      // to send the N character
+                    break;
+    default       : tx_add(c);          // just send it ...
+                    break;
+  }
+}
+
+/** adds a complete string to the transmit buffer, with protocol processing.
+ *  function will block until there is room in the transmit buffer
+ *
+ *  @param S string to be transmitted
+ *  @return always returns 0
+ */
+int spislirq::tx_string(char S[]) {
+  int i = 0;
+
+  while ((S[i] != 0x00)) {
+    // add until end of string
+    tx_addp(S[i]);
+    i++;
+  }
+  return(0);
+}
+
+/** inserts one byte in the receive buffer without protocol processing
+ *  used for command batch processing
+ *
+ *  @return the character read, blocks if RX buffer is empty!
+ *
+ */
+int spislirq::rx_add(unsigned char c) {
+  while (rx_full()) {
+  do_callback();
+    wait_ms(1);  // wait until RC buffer full
+  }
+  disable_irq();
+  if (!rx_full()) {
+    rxxbuf[rx_in] = c;
+    rx_in = (rx_in + 1) % bufsize;
+    enable_irq();
+    return c;
+  }
+  enable_irq();
+  return c;
+}
+
+/** read one byte from the receive buffer without protocol processing
+ *
+ *  @return the character read, blocks if RX buffer is empty!
+ *
+ */
+int spislirq::rx_read() {
+  unsigned char c = 0;
+
+  while (rx_empty()) {
+    do_callback();
+    wait_us(500);
+  }
+  disable_irq();
+  if (!rx_empty()) {
+    c = rxxbuf[rx_out];
+    rx_out = (rx_out + 1) % bufsize;
+    enable_irq();
+    // DBG_inchar(c);
+    return c;
+  }
+  enable_irq();
+  return c;
+}
+
+/** peeks in receive buffer, reads next pending input char without advancing buffer pointer
+ *
+ *  @return the character read, blocks if RX buffer is empty!
+ *
+ */
+int spislirq::rx_peek() {
+  unsigned char c = 0;
+
+  while (rx_empty()) {
+    do_callback();
+    wait_us(500);
+  }
+  disable_irq();
+  if (!rx_empty()) {
+    c = rxxbuf[rx_out];
+  }
+  enable_irq();
+  return c;
+}
+
+/** read one byte, will wait until a valid char is read,
+ *  this function is blocking and will process escape characters,
+ *  when an escape is seen, will try to read the next char
+ *
+ *  @param mode command line processing or data read (ignored)
+ *  @return character read, or -1 when >F seen, -2 when >I seen
+ *
+ */
+int spislirq::rxx_read(bool mode) {
+  unsigned char bt1 = 0;
+  unsigned char bt2 = 0;
+  unsigned char h1  = 0;
+  unsigned char h2  = 0;
+  int rslt = 0;
+
+  bt1 = rx_read();
+
+  // we have now a character, check for escape codes
+  if (bt1 == c_escape) {
+    // this is an escape, now check for the next character
+    bt2 = rx_peek();        // peek in buffer, but do not read
+
+    switch (bt2) {
+      case c_arrow  : bt2 = rx_read();                   // read the char
+                      rslt = c_escape;
+                      break;
+
+      case c_eof    : bt2 = rx_read();                   // read the char
+                      rslt = -1;                         // <EOF>
+                      break;
+
+      case c_return : bt2 = rx_read();                   // read the char
+                      rslt = 0x0d;                       // carriage return
+                      break;
+
+      case c_null   :
+      case c_zero   : bt2 = rx_read();                   // read the char
+                      rslt = 0;                          // zero char
+                      break;
+
+      case c_hex    :
+      case c_hexalt : bt2 = rx_read();                    // read the char
+                      // now get next two chars, which must be hex digits
+                      h1 = rx_read();                     // get data from buffer
+                      h2 = rx_read();                     // get data from buffer
+
+                      rslt = 16 * hex2int(h1) + hex2int(h2); // calculate the result
+                      break;
+
+      case c_intrpt : bt2 = rx_read();                   // read the char
+                      rslt = -2;                         // interrupt
+                      break;
+
+      default       : rslt = bt1;                        // ignore
+
+    }  // end of switch(bt2)
+
+  } else {
+    // regular data send, no escape character
+    rslt = bt1;
+  }
+  return rslt;
+}
+
+void spislirq::DBG_set(int l) {
+  if ((l >= DBG_OFF) && (l <= DBG_FULL)) DBG_level = l;
+}
+
+
+/** show a debug message with a string and a character both a character and hex value
+ *
+ *  @param src this will typically be the name of the function
+ *  @param c character to be shown
+ */
+void spislirq::DBG_chr(char* src, char c) {
+  if (DBG_level != DBG_OFF) {
+    int cc = c;
+    if (c < 32) c = '.';
+    printf("%s : %c [%02x]\n", src, c, cc);
+  }
+}
+
+/** show one character in hex, input from SPI to the MBED
+ *
+ *  @param c input to be shown
+ */
+void spislirq::DBG_inchar(char C) {
+  // prints only one char in hex, preceded by a + for input followed by a space
+  if (DBG_level == DBG_FULL) {
+    printf("+%02x ", C);
+  }
+}
+
+/** show one character in hex, output from MBED to SPI
+ *
+ *  @param c output to be shown
+ */
+void spislirq::DBG_outchar(char C) {
+  if (DBG_level == DBG_FULL) {
+    printf("-%02x ", C);
+  }
+}
+
+/** convert a hex char '0' to 'F' in its decimal equivalent
+ *
+ *  @param C character
+ *  @return a value 0 to 15, 0 when C was not in '0'..'F'
+ *
+ */
+int spislirq::hex2int(char C) {
+  if ((C >= '0') && (C <= '9')) return(C - '0');
+  if ((C >= 'A') && (C <= 'F')) return(C - 'A' + 10);
+  return(0);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/spissp/spissp.h	Sun Feb 27 18:54:40 2011 +0000
@@ -0,0 +1,245 @@
+/* MMEx for MBED - SPI interfacing and ringbuffer functions
+ * 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 spissp.h
+  \brief SPI interfacing and ringbuffer functions
+*/
+
+#ifndef SPISSP_H
+#define SPISSP_H
+
+#include "mbed.h"
+#include "lpc17xx_ssp.h"
+#include "globaldefs.h"
+
+// macros for managing the SSP interface SSP0 only!
+#define tx_fifo_notfull  (LPC_SSP0->SR & SSP_STAT_TXFIFO_NOTFULL)
+#define tx_fifo_empty    (LPC_SSP0->SR & SSP_STAT_TXFIFO_EMPTY)
+#define rx_fifo_notempty (LPC_SSP0->SR & SSP_STAT_RXFIFO_NOTEMPTY)
+#define rx_fifo_full     (LPC_SSP0->SR & SSP_STAT_RXFIFO_FULL)
+
+#define irq_RTMIS        (LPC_SSP0->MIS & SSP_MIS_RT)    // RX FIFO timeout
+#define irq_RXMIS        (LPC_SSP0->MIS & SSP_MIS_RX)    // RX FIFO half full
+#define irq_RISOVR       (LPC_SSP0->RIS & SSP_RIS_ROR)   // receive overrun
+ 
+#define DBG_OFF  0
+#define DBG_ON   1
+#define DBG_FULL 2 
+ 
+
+ /** Library for the interrupt driven SPI SLave
+ *
+ */
+class spislirq {
+
+public:
+
+ /** initialize the SPI interface
+ *
+ */ 
+  spislirq(int PortNum);
+
+/** initialization of SPI Slave and buffers
+ *  
+ */  
+  void init();
+  
+/** attach callback for network (or other?) polling
+ *  
+ */  
+  void attach(void (*function)(void)) {
+    _callback.attach(function);  
+  }
+   /** attach callback for network (or other?) polling
+ *  
+ */  
+   
+/** disable SSP0 interrupts
+ *  will discard the byte if buffer full
+ */  
+  void disable_irq(void);
+  
+/** enable SSP0 interrupts
+ *  will discard the byte if buffer full
+ */  
+  void enable_irq(void);
+
+/** add one byte to the transmit buffer, no blocking, no protocol
+ *  will discard the byte if buffer full
+ *
+ *  @param c byte to send
+ */  
+  void txx_add(unsigned char c);
+
+/** returns the number of bytes available in the transmit buffer
+ *
+ *  @return available space in transmit buffer
+ */
+  int tx_room();
+  
+/** returns the amount af actual bytes used in the transmit buffer
+ *
+ *  @return bytes used in transmit buffer
+ */  
+  int tx_use();
+  
+/** returns the number of bytes available in the receive buffer
+ *
+ *  @return available space in transmit buffer
+ */  
+  int rx_room();
+  
+/** returns the percentage used in the transmit buffer
+ *
+ *  @return percentage from 0 to 100
+ */  
+  int tx_perc();
+  
+/** returns the percentage used in the receive buffer
+ *
+ *  @return percentage from 0 to 100
+ */  
+  int rx_perc();
+  
+/** returns the amount af actual bytes used in the receive buffer
+ *
+ *  @return bytes used in receive buffer
+ */  
+  int rx_use();
+  
+/** empties the transmit buffer
+ */  
+  void flush_tx();
+  
+/** empties the receive buffer
+ */  
+  void flush_rx();
+  
+/** add one byte to the transmit buffer, no protocol handling is done
+ *
+ *  @param Bt byte to send
+ *  @return 0 when succesfull, will block until there is room in the buffer
+ *
+ */  
+  int tx_add(unsigned char Bt);
+  
+/** add one byte to the transmit buffer with protocol handling,
+ *  function will block until there is room in the transmit buffer
+ *
+ *  @param Bt byte to send
+ */  
+  void tx_addp(unsigned char Bt);
+  
+/** adds a complete string to the transmit buffer, with protocol processing.
+ *  function will block until there is room in the transmit buffer
+ *
+ *  @param S string to be transmitted
+ *  @return always returns 0
+ */  
+  int tx_string(char S[]);
+  
+/** read one byte from the receive buffer without protocol processing
+ *
+ *  @return the character read, blocks if RX buffer is empty!
+ *
+ */  
+  int rx_read();
+  
+/** inserts one byte in the receive buffer without protocol processing
+ *  used for command batch processing
+ *
+ *  @return the character read, blocks if RX buffer is empty!
+ *
+ */  
+  int rx_add(unsigned char c);
+  
+/** peeks in receive buffer, reads next pending input char without advancing buffer pointer
+ *
+ *  @return the character read, blocks if RX buffer is empty!
+ *
+ */  
+  int rx_peek();
+  
+/** read one byte, will wait until a valid char is read,
+ *  this function is blocking and will process escape characters,
+ *  when an escape is seen, will try to read the next char
+ *
+ *  @param mode command line processing or data read (ignored)
+ *  @return character read, or -1 when >F seen, -2 when >I seen
+ *
+ */  
+  int rxx_read(bool mode);  
+  void DBG_set(int l);
+
+/** check if the TX buffer is empty
+ * @return true if the TX buffer is empty
+ */
+  bool tx_empty();
+  
+/** check if the TX buffer is full
+ * @return true if the TX buffer is full
+ */  
+  bool tx_full();
+  
+/** check if the RX buffer is empty
+ * @return true if the RX buffer is empty
+ */  
+  bool rx_empty();
+  
+/** check if the RX buffer is full
+ * @return true if the RX buffer is full
+ */  
+  bool rx_full();
+
+
+private:
+
+SPISlave smldl;        // uses SPI Class from MBED library
+Serial pc;
+DigitalOut _led4;
+FunctionPointer _callback;
+
+int hex2int(char C);
+void spi_isr();        // interrupt service routine
+static void _spi_isr(void);
+static spislirq *instance;
+void DBG_outchar(char C);
+void DBG_inchar(char C);
+void DBG_chr(char* src, char c);
+void do_callback(void) { _callback.call(); };
+  
+
+// buffers and pointers in buffers
+#define bufsize   255
+unsigned char rxxbuf[bufsize];     // receive buffer
+unsigned char txxbuf[bufsize];     // transmit buffer
+int tx_in;       
+int tx_out;        
+int rx_in;
+int rx_out;
+
+int DBG_level;
+
+};
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ufuncs.cpp	Sun Feb 27 18:54:40 2011 +0000
@@ -0,0 +1,292 @@
+/* MMEx for MBED - processing for U commands
+ * 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 ufuncs.cpp
+  \brief processing for U commands, to be filled in by users
+*/
+
+#include "ufuncs.h"
+#include "TMP102.h"
+#include <RPCVariable.h>
+
+TMP102 temperature(p28, p27, 0x90); //A0 pin is connected to ground
+
+/*
+ *  Registers from HP41
+ */
+struct _regs {
+    char regX[14];
+    char regY[14];
+    char regZ[14];
+    char regT[14];
+    char regL[14];
+    char regA[29];
+} regs;
+
+/**
+ *  return the struct Regs via RPC as a character string
+ *  RPC call is /regs_read/run
+ *  RPC has a size limit of 64 bytes. Therefore, the result depends
+ *  on the first character of the argument string: 
+ *     A returns Alpha,
+ *     L returns LastX
+ *     Anything else returns the complete stack X~T
+ *  All numerical data is in internal format, client must convert numbers.
+ */
+void rpc_regsread( char *input, char *output )
+{
+    switch ( toupper( *input ) ) {
+    
+    case 'A':
+        strcpy( output, regs.regA );
+        break;
+        
+    case 'L':
+        memcpy( output, regs.regL, 14 );
+        output[ 14 ] = '\0';
+        break;
+
+    default:
+        memcpy( output, &regs, 4 * 14 );
+        output[ 4 * 14 ] = '\0';
+    }
+}
+RPCFunction rpcregs( rpc_regsread, "regs_read" );
+ 
+/** 
+ *  main entry for parsing U-commands
+ *
+ */ 
+void parse_U() {
+  DBG_msg("parse_U", inbuf);
+  err_num = noerror;
+ 
+  // wipesp(inbuf);                    // remove all spaces from string
+
+  if (inbuf[1] != NULL) {
+    switch (inbuf[1]) {
+      case utemp  : do_utemp();     
+                    break;       
+      case ustack : do_ustack();     
+                    break;                      
+      case ualpha : do_ualpha();     
+                    break;                      
+      default     : do_udefault();    // command not recognized
+                    break;
+    }
+  } else { do_udefault(); }
+}
+
+/** read TMP02 temp sensor
+ *
+ *  syntax:  UT     return temp value in degrees C
+ *  \n       UTF    return temp value in degrees F
+ */
+void do_utemp(){
+  char s[20];
+  wipesp(inbuf);  // remove spaces
+  DBG_msg("do_utemp", inbuf);
+  
+  float temp = temperature.read();  
+  if (inbuf[2] == 'F') {
+    temp = (temp * 1.8) + 32;
+  }
+  
+  sprintf(s, "%.4f", temp);
+  DBG_msg("do_utemp", s);
+  mldl.tx_string(s);
+} 
+
+/** read 7 bytes as a register from input stream
+ *
+ *  @param *reg pointer to a register (14 chars)
+ *  @return last char read if all OK, -1 or -2 when interrupted
+ *
+ */
+int read_reg(char *reg) {
+  int i;
+  int c;
+  
+  for (i = 0; i < 7; i++) {
+    c = mldl.rxx_read(data_mode);      // get byte
+    // DBG_chr("read", c);
+    if ((c == -1) || (c == -2)) {
+      return c;                        // <EOF> or interrupt 
+    } else {
+      // data OK
+      reg[i * 2]     = ((c >> 4) & 0x0f ) + '0';
+      reg[i * 2 + 1] = (c & 0x0f) + '0';
+      // DBG_int("1 - ", reg[i*2]);
+      // DBG_int("2 - ", reg[i*2+1]);
+    }
+  }
+  return c;
+}    
+
+/** read 28 bytes re[presenting the ALPHA registers M, N, O and Pm
+ *
+ *  @return last char read if all OK, -1 or -2 when interrupted
+ */
+int read_alpha() {
+  int i;
+  int c;
+  
+  regs.regA[28] = NULL;
+  for (i = 0; i < 28; i++) {
+    c = mldl.rxx_read(data_mode);      // get byte
+    // DBG_chr("read", c);
+    if ((c == -1) || (c == -2)) {
+      return c;                        // <EOF> or interrupt 
+    } else {
+      regs.regA[i] = c;
+    }
+  }
+  return c;
+}      
+
+ 
+/** show a register on the debug console
+ *
+ *  @param *reg pointer to a register (14 chars
+ */
+void show_reg(char *c, char *reg) {
+  char s[25];
+    
+  sprintf(s, "%c.%c%c%c%c%c%c%c%c%c%c.%c.%c%c", 
+          reg[0],  reg[1],  reg[2], reg[3],  reg[4],  reg[5],  reg[6],
+          reg[7],  reg[8],  reg[9], reg[10], reg[11], reg[12], reg[13]);
+  DBG_msg(c, s);
+}
+  
+/** receive stack from HP41
+ *
+ *  syntax:  US<CR> [data]
+ *  \n       [data] is a binary stream of 5* 7 bytes
+ *  procedure is like File Write due to processing of escape characters
+ *  must send exact number of bytes, or terminate with '>F'
+ *  representing X, Y, Z, T, L
+ */
+void do_ustack() {
+  int i;
+
+  DBG_msg("do_ustack", inbuf);
+  
+  // command is received, just send prompt
+  
+  send_prompt();              // now send a prompt and we are ready to go
+  
+  i = read_reg(regs.regX);
+  i = read_reg(regs.regY);
+  i = read_reg(regs.regZ);
+  i = read_reg(regs.regT);
+  i = read_reg(regs.regL);
+   
+  if (i >= 0) {
+    show_reg("L", regs.regL);
+    show_reg("T", regs.regT);
+    show_reg("Z", regs.regZ);
+    show_reg("Y", regs.regY);
+    show_reg("X", regs.regX);           
+  } else {
+    DBG_msg("do_ustack", "interrupted");
+    show_reg("L", regs.regL);
+    show_reg("T", regs.regT);
+    show_reg("Z", regs.regZ);
+    show_reg("Y", regs.regY);
+    show_reg("X", regs.regX); 
+  }
+}
+
+/** receive alpha from HP41
+ *
+ *  syntax:  US<CR> [data]
+ *  \n       [data] is a binary stream of 24 bytes
+ *  procedure is like File Write due to processing of escape characters
+ *  must send exact number of bytes, or terminate with '>F'
+ */
+void do_ualpha() {
+  int i, j;
+  char tempA[29];
+  
+  DBG_msg("do_ualpha", inbuf);
+
+  i = read_alpha();
+
+  if (i >= 0) {
+    DBG_msg("ALPHA", regs.regA);
+  } else {
+    DBG_msg("do_ualpha", "interrupted");
+    DBG_msg("ALPHA", regs.regA);
+    return;
+  }
+    
+  // now rearrange due to the ordering of ALPHA
+  tempA[ 0] = regs.regA[25];
+  tempA[ 1] = regs.regA[26];
+  tempA[ 2] = regs.regA[27];  // P register
+  
+  tempA[ 3] = regs.regA[14];
+  tempA[ 4] = regs.regA[15];
+  tempA[ 5] = regs.regA[16];
+  tempA[ 6] = regs.regA[17];
+  tempA[ 7] = regs.regA[18];
+  tempA[ 8] = regs.regA[19];
+  tempA[ 9] = regs.regA[20];  // O register
+    
+  tempA[10] = regs.regA[ 7];
+  tempA[11] = regs.regA[ 8];
+  tempA[12] = regs.regA[ 9];
+  tempA[13] = regs.regA[10];
+  tempA[14] = regs.regA[11];
+  tempA[15] = regs.regA[12];
+  tempA[16] = regs.regA[13];  // N register
+  
+  tempA[17] = regs.regA[ 0];
+  tempA[18] = regs.regA[ 1];
+  tempA[19] = regs.regA[ 2];
+  tempA[20] = regs.regA[ 3];
+  tempA[21] = regs.regA[ 4];
+  tempA[22] = regs.regA[ 5];
+  tempA[23] = regs.regA[ 6];  // M-register
+  
+  // find first real ALPHA char
+  i = 0;
+  while (tempA[i] == NULL) i++;
+  
+  for (j = 0; (j + i + 1) < 25; j++) {
+    regs.regA[j] = tempA[i + j];
+  }
+  
+  regs.regA[j] = NULL;  
+
+  DBG_msg("ALPHA", regs.regA);
+
+}
+
+/** send error message, command not recognized,
+ */                                 
+void do_udefault() {
+  // command not recognized
+  DBG_msg("do_udefault", inbuf);
+  send_error(err_notrecognized); 
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ufuncs.h	Sun Feb 27 18:54:40 2011 +0000
@@ -0,0 +1,56 @@
+/* MMEx for MBED - processing for U commands
+ * 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 ufuncs.h
+  \brief processing for U commands, to be filled in by users
+*/
+
+#ifndef UFUNCS_H
+#define UFUNCS_H
+
+#include "mmex.h"
+
+// definition of the U-functions for User defined functions
+
+#define utemp  'T'
+#define ustack 'S'
+#define ualpha 'A'
+
+
+extern char regX[14];
+extern char regY[14];
+extern char regZ[14];
+extern char regT[14];
+extern char regL[14];
+extern char regA[29];
+
+int read_reg(char *reg);
+void show_reg(char *c, char *reg);
+void parse_U();
+void do_utemp();
+void do_ustack();
+void do_ualpha();
+
+void do_udefault();
+
+#endif
\ No newline at end of file