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
Revision 0:67a55a82ce06, committed 2011-02-27
- 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
--- /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, ®s, 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