Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed
src/command.cpp
- Committer:
- mfwic
- Date:
- 2019-01-11
- Revision:
- 21:fe0ea1860c9f
- Parent:
- 20:5de24e4ae1c5
- Child:
- 25:8bcc8bea0e31
File content as of revision 21:fe0ea1860c9f:
//-------------------------------------------------------------------------------
//
// Treehouse Inc.
// Colorado Springs, Colorado
//
// Copyright (c) 2016 by Treehouse Designs Inc.
//
// This code is the property of Treehouse, Inc. (Treehouse)
// and may not be redistributed in any form without prior written
// permission of the copyright holder, Treehouse.
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
//
//-------------------------------------------------------------------------------
//
// REVISION HISTORY:
//
// $Author: $
// $Rev: $
// $Date: $
// $URL: $
//
//-------------------------------------------------------------------------------
#include "mbed.h"
#include "string.h"
#include "stdio.h"
#include "stdlib.h"
#include "ctype.h"
#include "serial.h"
#include "globals.h"
#include "math.h"
#include "parameters.h"
#include "all_io.h"
//#include "calibrate.h"
#include "boards.h"
#include "menu.h"
#include "command.h"
unsigned int boardsActive = ALLON;
unsigned int boardMults = 32;
unsigned int commandData;
extern unsigned short my12;
/************* FILE SCOPE VARIABLES ************************/
char setvalue = FALSE;
int endOfCommand = 0;
int commandError = 0;
int menuLevel = LEVEL_MAIN;
int readback = 0;
/************************************************************
* Routine: getDelimiter
* Input: none
* Output: none
* Description:
* searches for a delimiter and moves the buffer location
* to be just past it
*
**************************************************************/
void getDelimiter(void)
{
++bufloc;
while ((rxbuf[bufloc] != ' ') &&
(rxbuf[bufloc] != ',') &&
(rxbuf[bufloc] != '=') &&
(rxbuf[bufloc] != 0 ))
{
bufloc++;
}
}
/************************************************************
* Routine: gethex
* Input: hex character
* Returns: hex integer
* Description:
* Converts a hex character to a value
**************************************************************/
char gethex(char val)
{
int retval;
switch(val)
{
case '0':
retval = 0;
break;
case '1':
retval = 1;
break;
case '2':
retval = 2;
break;
case '3':
retval = 3;
break;
case '4':
retval = 4;
break;
case '5':
retval = 5;
break;
case '6':
retval = 6;
break;
case '7':
retval = 7;
break;
case '8':
retval = 8;
break;
case '9':
retval = 9;
break;
case 'A':
retval = 10;
break;
case 'B':
retval = 11;
break;
case 'C':
retval = 12;
break;
case 'D':
retval = 13;
break;
case 'E':
retval = 14;
break;
case 'F':
retval = 15;
break;
default:
retval = 0;
break;
}
return retval;
}
/************************************************************
* Routine: showfval
* Input: setval (GET or SET)
* value (float value to display)
* Output: none
* Description:
* Sends a floating point number (value) over the serial port
* if it is being retrieved (GET)
*
**************************************************************/
void showfval(char setval,float value)
{
if(!setval)
{
sprintf(strbuf," %4.9f",value);
sendSerial(strbuf);
}
}
/************************************************************
* Routine: showival
* Input: setval (GET or SET)
* value (integer value to display)
* Output: none
* Description:
* Sends an integer (value) over the serial port
* if it is being retrieved (GET)
*
**************************************************************/
void showival(char setval, int value)
{
if(!setval)
{
sprintf(strbuf," %i",value);
sendSerial(strbuf);
}
}
/************************************************************
* Routine: showcval
* Input: setval (GET or SET)
* value (character to display)
* Output: none
* Description:
* Sends a character over the serial port
* if it is being retrieved (GET)
*
**************************************************************/
void showcval(char setval, int value)
{
if(!setval)
{
sprintf(strbuf," %c",(char)value);
sendSerial(strbuf);
}
}
/************************************************************
* Routine: showlval
* Input: setval (GET or SET)
* value (integer value to display)
* Output: none
* Description:
* Sends an long (value) over the serial port
* if it is being retrieved (GET)
*
**************************************************************/
void showlval(char setval, long value)
{
if(!setval)
{
sprintf(strbuf," %ld",value);
sendSerial(strbuf);
}
}
/************************************************************
* Routine: showuival
* Input: setval (GET or SET)
* value (integer value to display)
* Output: none
* Description:
* Sends an unsigned int (value) over the serial port
* if it is being retrieved (GET)
*
**************************************************************/
void showuival(char setval, unsigned int value)
{
if(!setval)
{
sprintf(strbuf," %u",value);
sendSerial(strbuf);
}
}
/************************************************************
* Routine: showhval
* Input: setval (GET or SET)
* value (hex integeger value to display)
* Output: none
* Description:
* Sends an integer (value) in hex over the serial port
* if it is being retrieved (GET)
*
**************************************************************/
void showhval(char setval, int value)
{
if(!setval)
{
if(serialStatus.computer)
sprintf(strbuf," %u",(unsigned int)value);
else
sprintf(strbuf," 0x%04x",value);
sendSerial(strbuf);
}
}
/************************************************************
* Routine: getival
* Input: setval (GET or SET)
* Returns: the value if it is being SET or 0 if it is a GET
* Description:
* Gets an integer from the serial port connection.
*
**************************************************************/
int getival(char setval)
{
if (setval)
{
return atoi(&rxbuf[++bufloc]);
}
return 0;
}
/************************************************************
* Routine: getcval
* Input: setval (GET or SET)
* Returns: the value if it is being SET or 0 if it is a GET
* Description:
* Gets an character from the serial port connection.
*
**************************************************************/
int getcval(char setval)
{
if(setval)
{
// skip one space
++bufloc;
// skip spaces and the equals sign
while((rxbuf[bufloc] == ' ') || (rxbuf[bufloc] == '='))
bufloc++;
return rxbuf[bufloc++];
}
else
return 0;
}
/************************************************************
* Routine: getlval
* Input: setval (GET or SET)
* Returns: the value if it is being SET or 0 if it is a GET
* Description:
* Gets an long from the serial port connection.
*
**************************************************************/
long getlval(char setval)
{
if(setval)
return atol(&rxbuf[++bufloc]);
else
return 0;
}
/************************************************************
* Routine: getfval
* Input: setval (GET or SET)
* Returns: the value if it is being SET or 0 if it is a GET
* Description:
* Gets an float from the serial port connection.
*
**************************************************************/
float getfval(char setval)
{
if(setval)
return atof(&rxbuf[++bufloc]);
else
return 0;
}
/************************************************************
* Routine: validateEntry
* Input: setval (GET or SET)
* limlo -- low limit
* limhi -- high limit
* address -- address in eeprom to use
* Returns: 0 if entry validates and is written
* 1 if entry fails
* Description:
* Gets or sets a value in eeprom at the address but only
* if it is between the limits will it write the value to
* eeprom
*
**************************************************************/
int validateEntry(char setvalue, float limlo, float limhi, float *address)
{
float val;
if (setvalue)
{
val = getfval(SET);
if ((val >= limlo) && (val <= limhi))
{
*address = val;
}
else
{
showRangeError(0, 0, val);
return 0;
}
}
else
{
val = *address;
sprintf(strbuf, " %4.3f", val);
sendSerial(strbuf);
}
return 1;
}
/************************************************************
* Routine: validateEntry
* Input: setval (GET or SET)
* limlo -- low limit
* limhi -- high limit
* address -- address in eeprom to use
*
* Returns: FALSE if entry fails
* TRUE if entry validates and is written
*
* Description:
* Gets or sets a value in eeprom at the address but only
* if it is between the limits will it write the value to
* eeprom
*
**************************************************************/
int validateInt(char setvalue, int limlo, int limhi, int *address)
{
float val;
if (setvalue)
{
val = getfval(SET);
if ((val >= limlo) && (val <= limhi))
{
*address = val;
}
else
{
showRangeError(1, val, 0);
return FALSE;
}
}
else
{
val = *address;
sprintf(strbuf, " %4.0f", val);
sendSerial(strbuf);
}
return TRUE;
}
/************************************************************
* Routine: parseCommand
* Input: setvalue (GET or SET), command buffer
* Returns: none
* Description:
* parses a command and gets the commandstring
**************************************************************/
void parseCommand(char setvalue, char *commandString)
{
int i, endofc;
char store;
// Ignore any white space and the optional ';' character before the start of
// the command string (any ']' character is from the last command so skip that,
// too)
while ((isspace(rxbuf[bufloc])) || (rxbuf[bufloc] == ';') || (rxbuf[bufloc] == ']'))
{
bufloc++;
if ((rxbuf[bufloc] == 0x0D) || (rxbuf[bufloc] == 0)) break;
}
if (setvalue)
{
// We need a value for SET so hitting the end is a problem
if ((rxbuf[bufloc] == 0) || (rxbuf[bufloc] == 0x0D))
{
commandError = 1;
return;
}
}
// Find the end of the command string
endofc = bufloc + 1;
// White space, '[' and '?' all terminate the command string
while ((!isspace(rxbuf[endofc])) && (rxbuf[endofc] != '[') && (rxbuf[endofc] != '?'))
{
endofc++;
// (As does hitting the end of rxbuf!)
if ((rxbuf[endofc] == 0x0D) || (rxbuf[endofc] == 0)) break;
}
// Save the character that marks the end of the command string
store = rxbuf[endofc];
// sprintf(strbuf, "store == %c\r\n", store);
// sendSerial(strbuf);
// Command strings ending in '?' are readbacks
readback = ((store == '?') ? 1 : 0);
// Set end to null character so string can now be copied
rxbuf[endofc] = 0;
// Copy the command string into commandString
char commandStringBuf[80];
char *tok;
strcpy(commandStringBuf, &rxbuf[bufloc]);
if(strstr(commandStringBuf, "=")){
tok = strtok(commandStringBuf, "=");
strcpy(commandString, tok);
tok = strtok(NULL, "=");
commandData = atoi(tok);
//if(DEBUG){
// sprintf(strbuf, "commandStringBuf= %s, commandData= %d", commandStringBuf, commandData);
// sendSerial(strbuf);
//}
}
else{
strcpy(commandString, commandStringBuf);
}
// Convert the command string to all uppercase characters
for (i = 0; i < strlen(commandString); i++)
{
commandString[i] = toupper(commandString[i]);
}
// Replace the character we clobbered in rxbuf
rxbuf[endofc] = store;
// Update bufloc to the end of the command string
bufloc = endofc;
}
/************************************************************
* Routine: validateChannel
* Input: channel
* Returns: none
* Description:
* Verifies that the channel number is a valid value between
* 1 and MAX_BOARDS, setting commandError if the check fails
**************************************************************/
void validateChannel(int channel)
{
if ((channel < 1) || (channel > MAX_BOARDS))
{
sprintf(strbuf, " Invalid channel/board: %d (range is 1 - %d)", channel, MAX_BOARDS);
sendSerial(strbuf);
commandError = 1;
}
}
/************************************************************
* Routine: setPairVariable
* Input: *avariable,*bvariable
* Returns: none
* Description:
* sets a single channel variable
**************************************************************/
void setPairVariable(float *avariable, float *bvariable, float limitlo, float limithi)
{
if (!readback)
{
if (validateEntry(SET, limitlo, limithi, avariable))
{
*bvariable = *avariable;
}
}
}
/************************************************************
* Routine: testMenu
* Input: none
* Returns: none
* Description:
* testMenu
**************************************************************/
void testMenu(void)
{
int ival;
int ch, dac;
//float fval;
unsigned int data;
char commandString[80] = { 0 };
commandError = 0;
parseCommand(GET, commandString);
if (!strcmp(commandString, "LEDS")) // duh do I have to tell you?
{
//testLEDs();
return;
}
if (!strcmp(commandString, "SELFTEST"))
{
if ((rxbuf[bufloc] == 0x0D) || (rxbuf[bufloc] == 0))
{
//ival = DEFAULT_SELFTEST_BOARDS;
ival = 0;
}
else
{
ival = getival(SET);
if ((ival < 1) || (ival > MAX_BOARDS))
{
sprintf(strbuf, " Invalid number of channels/boards (range is 1 - %d)", MAX_BOARDS);
sendSerial(strbuf);
commandError = 1;
return;
}
}
//selfTest(ival);
return;
}
if (!strcmp(commandString, "HVEN")) // high voltage enable
{
ival = getival(SET);
//hv_en = ival;
return;
}
if (!strcmp(commandString, "DAC"))
{
ch = getival(SET);
getDelimiter();
dac = getival(SET);
getDelimiter();
data = getival(SET);
validateChannel(ch);
if (commandError) return;
ch--;
//sendData((unsigned int)ch, (unsigned int)dac, data);
sprintf(strbuf, " ch: %u dac: %u value: %u", ch + 1, dac, data);
sendSerial(strbuf);
return;
}
if (!strcmp(commandString, "DINIT"))
{
//initDACs();
return;
}
if (!strcmp(commandString, "FINIT"))
{
//formatParameterSector();
return;
}
if (!strcmp(commandString, "CINIT"))
{
//initCalParameters();
sprintf(strbuf, " All calibration parameters set to default values");
sendSerial(strbuf);
return;
}
if (strcmp(commandString, ""))
{
commandError = 1;
}
}//end void testMenu
unsigned int checkRegisterCompatibility(unsigned int reg)
{
int i;
unsigned int boardsEnabled = 0;
for (i = 0; i < MAX_BOARDS; i++)
{
//if (ch[i][reg].enabled == 1)
//{
// Set the corresponding bit
boardsEnabled |= (1 << i);
//}
}
// Invert the bits because 0 == enabled on the SPI write
boardsEnabled = ~boardsEnabled;
return (boardsEnabled ^ boardEnableBits) & 0x000003FF;
}
/************************************************************
* Routine: doCommand
* Input: none
* Returns: none
* Description:
* This is the start of the command string.
**************************************************************/
void doCommand(void)
{
int ival;
unsigned int boardEnables;
char commandString[80] = { 0 };
bufloc = 0;
commandError = 0;
parseCommand(GET, commandString);
if (!strcmp(commandString, "MENU"))
{
menuRedraw(NO_PROMPT);
}
else if (!strcmp(commandString, "HELP"))
{
menuRedraw(NO_PROMPT);
}
else if (!strcmp(commandString, "BRDS"))
// BRDS is used to get/set the wr_out value.
// The integer value of boardsActive is used to change wr_out via setBoardEnables(boardsActive).
// Slots 12 to 0 are activated with the wr_out signals
// wr_out[13] = slots[12:0]
{
if (readback)
{
sprintf(strbuf, " %d", boardsActive);
sendSerial(strbuf);
}
else if (running == 1)
{
sprintf(strbuf, " Parameters may not be updated while running!");
sendSerial(strbuf);
}
else
{
boardsActive = commandData;
if(checkRange(boardsActive, 0, 8191) == 1){
wr_out_code = setBoardEnables(boardsActive);
testing = TRUE;
}else{
showRangeError(1, boardsActive, 0.0);
}
}
}
else if (!strcmp(commandString, "MULT"))
// MULT is used to get/set the en_out value.
// The integer value of boardMults is used to change en_out via setBoardWeights(boardMults).
// en_out are binary weighted signals that activate groups of DC-DC converters on the slot cards.
// en_out[6] = {en32, en16, en8, en4, en2, en1}
{
if (readback)
{
sprintf(strbuf, " %d", boardMults);
sendSerial(strbuf);
}
else if (running == 1)
{
sprintf(strbuf, " Parameters may not be updated while running!");
sendSerial(strbuf);
}
else
{
boardMults = commandData;
if(checkRange(boardMults, 0, 63) == 1){
en_out_code = setBoardWeights(boardMults);
/*unsigned int bmult=boardMults;
for(int count=0;count<33;count++){
en_out_code = setBoardWeights(bmult++);
wait(0.25);
}
en_out_code = setBoardWeights(boardMults);
sprintf(strbuf, " en_out_code=%d\r\n", en_out_code);
sendSerial(strbuf);*/
testing = TRUE;
}else{
showRangeError(1, boardMults, 0.0);
}
}
}
else if (!strcmp(commandString, "MY12"))
// MULT is used to get/set the en_out value.
// The integer value of boardMults is used to change en_out via setBoardWeights(boardMults).
// en_out are binary weighted signals that activate groups of DC-DC converters on the slot cards.
// en_out[6] = {en32, en16, en8, en4, en2, en1}
{
//if(DEBUG){
// sprintf(strbuf, "my12=%d commandData=%d\r\n", my12, commandData);
// sendSerial(strbuf);
//}
if (readback)
{
sprintf(strbuf, " %d", my12);
sendSerial(strbuf);
}else{
my12 = commandData;
testing = FALSE;
}
}
else if (!strcmp(commandString, "ALLOFF"))
{
my12 = 0;
running = FALSE;
testing = FALSE;
if(DEBUG){
sprintf(strbuf, "wr_out_code=%d\r\n", wr_out_code);
sendSerial(strbuf);
}
}
else if (!strcmp(commandString, "ALLON"))
{
wr_out_code = setBoardEnables((unsigned int)ALLON);
testing = TRUE;
}
else if (!strcmp(commandString, "RUN"))
{
// Skip over any white space and the optional '[' character
while ((isspace(rxbuf[bufloc])) || (rxbuf[bufloc] == '[')) bufloc++;
if(rxbuf[bufloc] == NULL){
boardsActive = ALLON;
startConverter(boardsActive);
testing = FALSE;
}
else if (rxbuf[bufloc] == '0')
//if (rxbuf[bufloc] == '0')
{
stopConverter();
//setDacsToZeroVolts();
testing = FALSE;
}
else if ((rxbuf[bufloc] > '0') && (rxbuf[bufloc] < '0' + MAX_BOARDS))
{
ival = atoi(&rxbuf[bufloc]);
//ival--;
if (running == 0)
{
boardsActive = ival;
startConverter(boardsActive);
testing = FALSE;
}
else
{
// Compare the board enable flags between registers
boardEnables = checkRegisterCompatibility(ival);
// If board enable flags match, change the register set
if (boardEnables == 0)
{
boardsActive = ival;
}
else
{
sprintf(strbuf, " Board enable flags do not match (0x%08x)", boardEnables);
sendSerial(strbuf);
}
}
}
else
{
sprintf(strbuf, " Invalid number of boards (1 - %d)", MAX_BOARDS);
sendSerial(strbuf);
commandError = 1;
}
}
else if (!strcmp(commandString, "STOP"))
{
stopConverter();
testing = FALSE;
my12 = 0;
//hv_en = OFF;
}
else if(!strcmp(commandString, "TEST"))
{
if (running == 1)
{
sprintf(strbuf, " Parameters may not be updated while running!");
sendSerial(strbuf);
}
else
{
testMenu();
}
}
else if(!strcmp(commandString, "CAL"))
{
if (running == 1)
{
sprintf(strbuf, " Parameters may not be updated while running!");
sendSerial(strbuf);
commandError = 1;
}
if (!commandError){
raw = TRUE;
menuRedraw(NO_PROMPT);
}
}
else if(!strcmp(commandString, "UNCAL"))
{
if (running == 1)
{
sprintf(strbuf, " Parameters may not be updated while running!");
sendSerial(strbuf);
commandError = 1;
}
if (!commandError){
raw = FALSE;
menuRedraw(NO_PROMPT);
}
}
else
{
if (strcmp(commandString, ""))
{
commandError = 1;
}
}
if (commandError)
{
sendSerial(" !");
}
//sendCRLF();
menuPrompt(MENU_DCM1);
}
/************************************************************
* Routine: processCommand
* Input: none
* Returns: none
* Description:
* This is the main serial communications routine. Everything
* starts here as soon as a command is avaiable for processing.
**************************************************************/
void processCommand(void)
{
if (!serialStatus.command && !serialStatus.repeat)
{
return;
}
doCommand(); // if not computer (i.e. terminal) you can do the command as well
bufloc = 0;
rxbuf[bufloc] = 0;
serialStatus.computer = FALSE;
serialStatus.command = FALSE;
//sendSerial("didCommand\r\n");
}
/************************************************************
* Routine: waitCommand
* Input: none
* Returns: none
* Description:
**************************************************************/
bool waitCommand(void)
{
if (!serialStatus.command && !serialStatus.repeat)
{
return TRUE;
}
serialStatus.computer = FALSE;
serialStatus.command = FALSE;
return FALSE;
}
// Verify that the same boards are enabled in both the current register and
// the specified register