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

ufuncs.cpp

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

File content as of revision 0:67a55a82ce06:

/* MMEx for MBED - processing for U commands
 * Copyright (c) 2011 MK
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

/**
  \file ufuncs.cpp
  \brief processing for U commands, to be filled in by users
*/

#include "ufuncs.h"
#include "TMP102.h"
#include <RPCVariable.h>

TMP102 temperature(p28, p27, 0x90); //A0 pin is connected to ground

/*
 *  Registers from HP41
 */
struct _regs {
    char regX[14];
    char regY[14];
    char regZ[14];
    char regT[14];
    char regL[14];
    char regA[29];
} regs;

/**
 *  return the struct Regs via RPC as a character string
 *  RPC call is /regs_read/run
 *  RPC has a size limit of 64 bytes. Therefore, the result depends
 *  on the first character of the argument string: 
 *     A returns Alpha,
 *     L returns LastX
 *     Anything else returns the complete stack X~T
 *  All numerical data is in internal format, client must convert numbers.
 */
void rpc_regsread( char *input, char *output )
{
    switch ( toupper( *input ) ) {
    
    case 'A':
        strcpy( output, regs.regA );
        break;
        
    case 'L':
        memcpy( output, regs.regL, 14 );
        output[ 14 ] = '\0';
        break;

    default:
        memcpy( output, &regs, 4 * 14 );
        output[ 4 * 14 ] = '\0';
    }
}
RPCFunction rpcregs( rpc_regsread, "regs_read" );
 
/** 
 *  main entry for parsing U-commands
 *
 */ 
void parse_U() {
  DBG_msg("parse_U", inbuf);
  err_num = noerror;
 
  // wipesp(inbuf);                    // remove all spaces from string

  if (inbuf[1] != NULL) {
    switch (inbuf[1]) {
      case utemp  : do_utemp();     
                    break;       
      case ustack : do_ustack();     
                    break;                      
      case ualpha : do_ualpha();     
                    break;                      
      default     : do_udefault();    // command not recognized
                    break;
    }
  } else { do_udefault(); }
}

/** read TMP02 temp sensor
 *
 *  syntax:  UT     return temp value in degrees C
 *  \n       UTF    return temp value in degrees F
 */
void do_utemp(){
  char s[20];
  wipesp(inbuf);  // remove spaces
  DBG_msg("do_utemp", inbuf);
  
  float temp = temperature.read();  
  if (inbuf[2] == 'F') {
    temp = (temp * 1.8) + 32;
  }
  
  sprintf(s, "%.4f", temp);
  DBG_msg("do_utemp", s);
  mldl.tx_string(s);
} 

/** read 7 bytes as a register from input stream
 *
 *  @param *reg pointer to a register (14 chars)
 *  @return last char read if all OK, -1 or -2 when interrupted
 *
 */
int read_reg(char *reg) {
  int i;
  int c;
  
  for (i = 0; i < 7; i++) {
    c = mldl.rxx_read(data_mode);      // get byte
    // DBG_chr("read", c);
    if ((c == -1) || (c == -2)) {
      return c;                        // <EOF> or interrupt 
    } else {
      // data OK
      reg[i * 2]     = ((c >> 4) & 0x0f ) + '0';
      reg[i * 2 + 1] = (c & 0x0f) + '0';
      // DBG_int("1 - ", reg[i*2]);
      // DBG_int("2 - ", reg[i*2+1]);
    }
  }
  return c;
}    

/** read 28 bytes re[presenting the ALPHA registers M, N, O and Pm
 *
 *  @return last char read if all OK, -1 or -2 when interrupted
 */
int read_alpha() {
  int i;
  int c;
  
  regs.regA[28] = NULL;
  for (i = 0; i < 28; i++) {
    c = mldl.rxx_read(data_mode);      // get byte
    // DBG_chr("read", c);
    if ((c == -1) || (c == -2)) {
      return c;                        // <EOF> or interrupt 
    } else {
      regs.regA[i] = c;
    }
  }
  return c;
}      

 
/** show a register on the debug console
 *
 *  @param *reg pointer to a register (14 chars
 */
void show_reg(char *c, char *reg) {
  char s[25];
    
  sprintf(s, "%c.%c%c%c%c%c%c%c%c%c%c.%c.%c%c", 
          reg[0],  reg[1],  reg[2], reg[3],  reg[4],  reg[5],  reg[6],
          reg[7],  reg[8],  reg[9], reg[10], reg[11], reg[12], reg[13]);
  DBG_msg(c, s);
}
  
/** receive stack from HP41
 *
 *  syntax:  US<CR> [data]
 *  \n       [data] is a binary stream of 5* 7 bytes
 *  procedure is like File Write due to processing of escape characters
 *  must send exact number of bytes, or terminate with '>F'
 *  representing X, Y, Z, T, L
 */
void do_ustack() {
  int i;

  DBG_msg("do_ustack", inbuf);
  
  // command is received, just send prompt
  
  send_prompt();              // now send a prompt and we are ready to go
  
  i = read_reg(regs.regX);
  i = read_reg(regs.regY);
  i = read_reg(regs.regZ);
  i = read_reg(regs.regT);
  i = read_reg(regs.regL);
   
  if (i >= 0) {
    show_reg("L", regs.regL);
    show_reg("T", regs.regT);
    show_reg("Z", regs.regZ);
    show_reg("Y", regs.regY);
    show_reg("X", regs.regX);           
  } else {
    DBG_msg("do_ustack", "interrupted");
    show_reg("L", regs.regL);
    show_reg("T", regs.regT);
    show_reg("Z", regs.regZ);
    show_reg("Y", regs.regY);
    show_reg("X", regs.regX); 
  }
}

/** receive alpha from HP41
 *
 *  syntax:  US<CR> [data]
 *  \n       [data] is a binary stream of 24 bytes
 *  procedure is like File Write due to processing of escape characters
 *  must send exact number of bytes, or terminate with '>F'
 */
void do_ualpha() {
  int i, j;
  char tempA[29];
  
  DBG_msg("do_ualpha", inbuf);

  i = read_alpha();

  if (i >= 0) {
    DBG_msg("ALPHA", regs.regA);
  } else {
    DBG_msg("do_ualpha", "interrupted");
    DBG_msg("ALPHA", regs.regA);
    return;
  }
    
  // now rearrange due to the ordering of ALPHA
  tempA[ 0] = regs.regA[25];
  tempA[ 1] = regs.regA[26];
  tempA[ 2] = regs.regA[27];  // P register
  
  tempA[ 3] = regs.regA[14];
  tempA[ 4] = regs.regA[15];
  tempA[ 5] = regs.regA[16];
  tempA[ 6] = regs.regA[17];
  tempA[ 7] = regs.regA[18];
  tempA[ 8] = regs.regA[19];
  tempA[ 9] = regs.regA[20];  // O register
    
  tempA[10] = regs.regA[ 7];
  tempA[11] = regs.regA[ 8];
  tempA[12] = regs.regA[ 9];
  tempA[13] = regs.regA[10];
  tempA[14] = regs.regA[11];
  tempA[15] = regs.regA[12];
  tempA[16] = regs.regA[13];  // N register
  
  tempA[17] = regs.regA[ 0];
  tempA[18] = regs.regA[ 1];
  tempA[19] = regs.regA[ 2];
  tempA[20] = regs.regA[ 3];
  tempA[21] = regs.regA[ 4];
  tempA[22] = regs.regA[ 5];
  tempA[23] = regs.regA[ 6];  // M-register
  
  // find first real ALPHA char
  i = 0;
  while (tempA[i] == NULL) i++;
  
  for (j = 0; (j + i + 1) < 25; j++) {
    regs.regA[j] = tempA[i + j];
  }
  
  regs.regA[j] = NULL;  

  DBG_msg("ALPHA", regs.regA);

}

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