/******************************************************************************* MODULE : Commands.c Processes commands from logging interface MODULE IS ADAPTED FROM ANOTHER VERY OLD PROJECT So some code may look really ugly. Even to my eyes ;-) 19xxxxxx AB Initial 20191219 AB Slightly updated for JADE EFM32JG1B test *******************************************************************************/ // --- Includes --------------------------------------------------------------- #define LOGGING_TOKEN COMMAND_LOGGING #include "TraceLeUart.h" #include #include #include #include #include #include #include #include "types.h" #include "Command.h" #include "TraceLeUart.h" //#include "Nvm.h" //#include "Iic.h" #include "Adc.h" //#include "ComAnet.h" //#include "MasterAnet.h" //#include "SlaveAnet.h" #include "Leds.h" #include "Hardware.h" // --- Pin Definitions -------------------------------------------------------- // --- Defines ---------------------------------------------------------------- #define MAX_CHAR_COMPARE 3 /* max. number of characters valid for command compare */ #define MAX_ARGS 5 /* max. number of arguments to be processed */ #define MAX_COMMAND_LENGTH 15 /* max. length of command */ #define MAX_LINE_LENGTH 50 /* max. length of on command line */ #define MAX_ARG_LENGTH 6 /* max. length of one argument */ #define BUFFER_SIZE 100 // max. size of line including command and args... /* Commands are defined as array of strings and as consecutive numbers for easier handling in command.c */ #define DUMMY 0 #define VERSION 1 #define UPTIME 2 #define ADCS 3 #define HELP 4 #define LIST_EEPROM 5 #define CLEAR_EEPROM 6 #define NVMSTATUS 7 #define LOGGING 8 #define STATUS 9 #define ERRORS 10 #define IRQS 11 #define LED 12 #define COVOLT 13 #define RELAIS 14 #define BOOT 15 #define HWLOGGING 16 #define NEW_LINE 17 // have to be 2 items more than #defines above #ifndef NO_TRACE // #commands length const char saCommands[20] [33] = { "DUMMy", "VERSion", "UPTIme", "ADCS [1|2|3|4]", "HELP", "LIST_eeprom", "CLEAR_eeprom (attention !!!)", "NVMStatus", "LOGGing", "STATus", "ERROrs", "IRQS", "LED num [0|1] (num=0|2)", "COVoltage correct. LINE in mV", "RELais 1|2|? toggle relais", "BOOT sw reset to booter", "HWLogging - toggle on/off", "\n", "\0"}; // --- Typedefs --------------------------------------------------------------- // --- PUBLIC Variables ------------------------------------------------------- static BYTE bNewCommands; // number of commands waiting to be processed // incremented in uart receiver IRQ routine // --- Variables -------------------------------------------------------------- static BYTE bArgc ; // number of arguments // static BYTE bLogLevel ; // level of logging messages static char sCommand[MAX_COMMAND_LENGTH + 1] ; // input command buffer static char sArg[MAX_ARGS][MAX_ARG_LENGTH + 1] ; // buffer for command arguments static char sTmpBuffer[BUFFER_SIZE] ; // temporary buffer // --- Macros ----------------------------------------------------------------- #endif // NO_TRACE // --- Functionprototypes ----------------------------------------------------- extern int StackCheck (void); void CommandProcessing(void); BYTE CommandCompare (void); // --- Code ------------------------------------------------------------------- void CommandInit(void) { #ifndef NO_TRACE bNewCommands = 0; #endif // NO_TRACE } /****************************************************************************** void CommandProcessing (void) Called whenever a new command arrived in input buffer. Or from main loop every 200ms. Decodes commands an processes arguments. Notification about new command via global variable. Input buffer read with direct fetch from uart. ******************************************************************************/ void CommandProcessing(void) { #ifndef NO_TRACE if ( !TraceCommandAvail() ) return; // check if commands are ready BYTE bChar, bTmp; BYTE bCount = 0; // BYTE j, i; // char cBuf[81]; // char cBuf1[10]; // int iT0, iT1, iT2, iT3, iT4, iT5, iT6;//, iT7; int iTemp; do { if ( ! (bChar = TraceGetKey() ) ) // read byte from UART input buffer { if ( !bCount ) { /* if no characters are processed till now then error, else normal abortion of while loop */ TRACE_L2("CMD: Error - TraceGetKey returns 0 (false triggered new command?)"); TRACE_L2("CMD: bNewCommands: %d", bNewCommands); } break; /* error on getkey breaks */ } if ( bChar == '\b' && bCount ) bCount--; /* Backspace processing */ else { if ( bChar != '\b' && bCount < (BUFFER_SIZE-1) ) { if ( bChar != '\n' && bChar != '\r' ) { /* don't process CR or LF */ //sTmpBuffer[bCount] = toupper(bChar); // 20090116 AB make case sensitive (command is still insensitive, see command compare) sTmpBuffer[bCount] = bChar; bCount++; } } } if ( bChar != '\n' && bChar != '\r' ) TRACE_L2("Key '%c'", bChar); } while ( (( (bChar != '\r') && (bChar != '\n') ) && (bCount < (BUFFER_SIZE-1)) ) || (bChar == '\b') ); /* (the BUFFER_SIZE-1 character overflows bCount and breaks while loop) if BUFFER_SIZE overflows then break while loop */ if ( bCount == (BUFFER_SIZE-1) ) /* sTmpBuffer overflow - line to long, read till no character or line end (\n or \r) */ { while ( (bChar = TraceGetKey()) ) { /* characters available to read */ if ( bChar == '\n' || bChar == '\r' ) break; /* Read until end of command to flush too long commands */ } } if ( bCount > 0 ) sTmpBuffer[bCount] = '\0'; else { sTmpBuffer[0]= '\0'; } TraceCommandAvailDec(); /* one command read from input buffer */ if ( !bCount ) { TRACE_L2("CMD: Error - input stream to long or no input (only or "); return; /* input stream to long, bCount overflow */ } TRACE_L2("%s\n", sTmpBuffer); /* debugging print complete Command Line */ if ( bCount < MAX_LINE_LENGTH ) bChar = CommandCompare (); /* only commands shorter than MAX_LINE_LENGTH characters are allowed */ else { TRACE_L2("\nCMD: Error - command line to long\n"); return; } bCount = 0; /* increment bCount whenever one argument was processed */ TRACE_L2("Command compare gives command %d", (int) bChar); switch ( bChar ) { case VERSION: TracePrintFirmwareVersion(); //TRACE(" ZTM-BD Build: %s %s", TraGetBuildTime(), TraGetBuildDate()); // __DEBUG will be set by MPLAB for debug builds #if defined (__DEBUG__) || defined (DEBUG) || defined (__DEBUG) TRACE (" DEBUG"); #endif TracePrintHwInfo(); //TracePrintKeypadInfo(); break; case UPTIME: TracePrintUptime(); TracePrintStartTime(); break; case ADCS: bTmp = 1; switch (sArg[0][0]) { case '0': case '1': case '2': case '3': case '4': bTmp = atoi(&sArg[0][0]); // fall through default: AdcTrace(bTmp); break; } bCount--; break; case HELP: TRACE(" Valid commands -"); bTmp = 1; while ( saCommands[bTmp][0] != '\n' ) { TRACE(" %s", saCommands[bTmp]); bTmp++; } TRACE(" Only the first %d characters are decisive. Not case sensitive.", (int) MAX_CHAR_COMPARE); break; /* 20180917 remmed out cause of FLASH space constraints case LIST_EEPROM: j = 0; do { cBuf[0] = '\0'; for (i = 0; i < 16; i++, j++) { sprintf(cBuf1, " 0x%02X", NvmGetChar(j)); strcat(cBuf, cBuf1); } TRACE("%s", cBuf); } while (j < 128); //EEPROM_SIZE); break; case CLEAR_EEPROM: for (i = 0; i < 8; i++) NvmStoreChar(i, 0xFF); TRACE("CMD: cleared first %d bytes in EEPROM", i); break; */ case NVMSTATUS: TRACE(" "); // NvmTraceStatus(); break; case LOGGING: /*if (!bArgc) { TRACE("CMD: Logging is %s", bLogLevel ? "ON" : "OFF"); } else // At least one Argument { bCount++; if (!strncmp ( (char *) &sArg[0], "OFF", MAX_ARG_LENGTH) ) bLogLevel = FALSE; if (!strncmp ( (char *) &sArg[0], "ON" , MAX_ARG_LENGTH) ) bLogLevel = TRUE; TRACE("CMD: Switch logging to %s", (char *) &sArg[0]); }; */break; case STATUS: if ( (iTemp = StackCheck()) >= 0 ) // check if stack is initialized to enable stack check { TRACE("CMD: stack - %d bytes free", iTemp ); } else { TRACE("CMD: stack - can not be checked"); } // IicPrintStatus(); // ComTraceErrors(); break; case ERRORS: //TRACE("CMD: Errors <- not implemented yet!"); break; case IRQS: TracePrintIRQs(); // ComTraceIRQs(); // MasTraceIRQs(); // SlvTraceIRQs(); // IicTraceIRQs(); break; case LED: if (bArgc) { if (bArgc == 1) LedToggle(sArg[0][0] - '0'); else { switch (sArg[1][0]) { case '0': LedOff(sArg[0][0] - '0'); bCount--; break; case '1': LedOn(sArg[0][0] - '0'); bCount--; break; } } bArgc--; } else { TRACE("COM: use f.i. LED 0 1"); } break; case COVOLT: break; case RELAIS: break; case BOOT: // restart (jump into booter) __disable_irq(); // __asm("CPSID i"); // GPIO_PinModeSet(gpioPortB, 13, gpioModeInputPull, 0); // STOP_FAST_START // GPIO_PinModeSet(gpioPortC, 14, gpioModePushPull, 1); // START_FAST_START _delay_us( 50000 ); NVIC_SystemReset(); break; case NEW_LINE: /* ignore new line */ break; case HWLOGGING: /* toggle Hardware logging */ // HwLoggingToggle(); break; default: if ( strlen(sTmpBuffer) < 47 ) { TRACE("CMD: Unknown command '%s'. Try 'HELP'", sTmpBuffer); } else { TRACE("CMD: Unknown command '%47s'. Try 'HELP'", sTmpBuffer); } break; } if ( bArgc > bCount ) /* all arguments processed ? */ { TRACE("CMD: Arguments not processed -"); while ( bCount < bArgc ) { TRACE(" '%s'", sArg[bCount]); bCount++; } } return; #endif // NO_TRACE } BYTE CommandCompare () { #ifndef NO_TRACE BYTE bChar = 0, bCount = 0, bTmp = 0, k, l; if ( bNewCommands > 20 ) /* if too much commands flush transmit buffer to get more processing time and suppress further echos */ { // SNT_FLU (); bNewCommands = 0; TRACE("CMD: Too much commands: %d", bNewCommands); TRACE("CMD: Input buffer flushed\n"); } if ( (l = strlen (sTmpBuffer)) ) { bArgc = 0; while ( sTmpBuffer[bCount] == ' ' && bCount < l && bTmp < MAX_COMMAND_LENGTH ) bCount++; /* remove leading blanks */ while ( sTmpBuffer[bCount] != ' ' && bCount < l && bTmp < MAX_COMMAND_LENGTH ) { if ( sTmpBuffer[bCount] != '\n' && sTmpBuffer[bCount] != '\r' && sTmpBuffer[bCount] != ' ' ) { sCommand[bTmp] = toupper(sTmpBuffer[bCount]); // 20090116 command case insensitive, args case sensitive bTmp++; } bCount++; } sCommand[bTmp] = '\0'; TRACE_L2(" CMD: command_compare - Command string %s\n", sCommand); for ( k = 0; k < MAX_ARGS; k++ ) { while ( sTmpBuffer[bCount] == ' ' && bCount < l ) bCount++; /* remove blanks */ bTmp = 0; while ( sTmpBuffer[bCount] != ' ' && bCount < l && bTmp < MAX_ARG_LENGTH ) { if ( sTmpBuffer[bCount] != '\n' && sTmpBuffer[bCount] != '\r' && sTmpBuffer[bCount] != ' ' ) { sArg[k][bTmp] = toupper(sTmpBuffer[bCount]); // 20101006 args case insensitive too bTmp++; } bCount++; } sArg[k][bTmp] = '\0'; TRACE_L2(" CMD: command_compare ARG "); TRACE_L2("%u bArgc: %u %u - %s\n", k, bArgc, bArgc, sArg[k]); if ( bTmp ) bArgc++; if ( bCount >= l ) break; /* end if no more input characters to process */ } while ( saCommands[bChar][0] != '\0' && bChar < 50 ) // no more than 50 commands allowed { bChar++; TRACE_L2(" CMD: comparing to %s", saCommands[bChar]); if ( !strncmp (saCommands[bChar], (char *)sCommand, MAX_CHAR_COMPARE) ) break; } } TRACE_L2(" CMD: command %d found ", (int) bChar); return bChar; #else return 1; #endif // NO_TRACE }