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:
- 2018-12-12
- Revision:
- 16:5791665200cb
- Parent:
- 14:e55ae9bb2a81
- Child:
- 20:5de24e4ae1c5
File content as of revision 16:5791665200cb:
//------------------------------------------------------------------------------- // // 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 = 1; unsigned int boardMults = 1; 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); 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 = 1; 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