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
Diff: ufuncs.cpp
- Revision:
- 0:67a55a82ce06
--- /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