Auxiliaries I use for CreaBot
Revision 1:6f5b84940d04, committed 2019-06-21
- Comitter:
- sepp_nepp
- Date:
- Fri Jun 21 15:26:49 2019 +0000
- Parent:
- 0:32b17da1ddae
- Commit message:
- The Command Interpreter is the only key function that is now included inside the Bot-Auxiliaries ...;
Changed in this revision
diff -r 32b17da1ddae -r 6f5b84940d04 Bot_Auxiliaries.cpp --- a/Bot_Auxiliaries.cpp Wed Oct 31 14:22:26 2018 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,197 +0,0 @@ -// ***************************************************************** -// Handle all the LEDs with some general function wrappers functions -// ***************************************************************** -#include "Bot_Auxiliaries.h" - -// Added a lookup function from a color number to a color, used by Creabot -int LED_CAR::ColNr2Color( char ColNr) -{ switch (ColNr) { - case 0: return BLACK; - case 1: return WHITE; - case 2: return RED; - case 3: return GREEN; - case 4: return BLUE; - case 5: return PURPLE; - default: return BLACK; - } -} - -void LED_CAR::LEDsOff( void ) { - StopRotation(); - StopBlink() ; - for (int lNr=0; lNr<NumLEDs; lNr++) - { SetColor(BLACK,lNr); } -} - -void LED_CAR::LEDsRainbow( void ) -{ for (int Nr=0; Nr<NumLEDs; Nr++) - { SetColor(ColNr2Color(Nr + 1),Nr); } -} - -void LED_CAR::LEDNrCol(LED_Nr aNr, int parameter) -{ - SetColor( ColNr2Color( aNr ), aNr); -} - -void LED_CAR::LEDsRainbowMove( double speed ) -{ LEDsRainbow( ); - StartRotation(0.3); -} - -void LED_CAR::LEDClignote(LED_Nr aNr, int OnOff) { - if (OnOff == 1) { - SetColor( ORANGE, aNr); - StartBlink(0.5) ;} - else { LEDsOff(); } -} - -// ***************************************************************** -// Handle all the LEDs specifically with the LED Position definitions -// ***************************************************************** - -void LED_CAR::LEDFront(int ColNr) -{ - SetColor( ColNr2Color( ColNr ), ledAvD); - SetColor( ColNr2Color( ColNr ), ledAvG); -} - -void LED_CAR::LEDRear(int ColNr) -{ - SetColor( ColNr2Color( ColNr ), ledArD); - SetColor( ColNr2Color( ColNr ), ledArG); -} - -void LED_CAR::LEDCligR(int speed) { - if ( (speed>0) && (speed<4) ) { - SetColor(ORANGE, ledAvD) ; - SetColor(ORANGE, ledArD) ; - StartBlink(float(speed)/4) ;} - else { LEDsOff(); } - } - -void LED_CAR::LEDCligL(int speed) { - if ( (speed>0) && (speed<4) ) { - SetColor(ORANGE, ledAvG) ; - SetColor(ORANGE, ledArG) ; - StartBlink(float(speed)/4) ;} - else { LEDsOff(); } -} - -void LED_CAR::LEDAnim(int speed) { - if ( (speed>0) && (speed<4) ) - { LEDsRainbowMove(float(speed)/4); } - else { LEDsOff(); } -} - - -//************************************ -// Interpreter Class Creation -//************************************ -// Strategy: the interpreter accumulates characters in its input buffer -// it flags the presence of complete lines -// it also flags Overflow of the buffer in which case all subsequent characters -// are lost until the queue is emptied, and a CR-LF is received -// Defined States of the interpreter: -// MyState = isStartNew, isLineFilling, isOverflow, isWaitNewLine}; - - -Interpreter::Interpreter() -{ Reinit( ); - MyState = isStartNew; -} - -void Interpreter::Reinit( void ) { - MyState = isWaitNewLine; // indicates no buffer overflow - WriteIndex = 0; // points to next index to write to - LinesComplete = 0; // indicates that no complete line is currently available - // Start Scanning at the start - ScanIndex = 0; - BufAvail = BuffLen;// the full buffer size is available - } - -// Barebone function, assumes that checks havee been performed by writeBuf! -void Interpreter::AddChar( char aChar ) { - if (WriteIndex == BuffLen) {WriteIndex=0;} - else {WriteIndex++;} - RingBuf[WriteIndex]=aChar; // all right, buffer it! - BufAvail--; // Buffer is shrinking - if (BufAvail==0) { MyState = isOverflow; } -} - -// High level method to add a Char to the buffer, -// Separates at Chars 10, 13, 0; replaced by a single 0 char -// Blocking write when buffer has overflowed -void Interpreter::writeBuf(char aChar) { - bool LineEnds = aChar==10 || aChar==13 || aChar==0; - switch (MyState) { - case isOverflow: break; - case isStartNew: - // avoid that consecutive CR LF are counted as multiple lines - if (!LineEnds) {AddChar(aChar ); MyState = isLineFilling; } - break; - case isLineFilling: - if (!LineEnds) {AddChar(aChar);} - else - {MyState = isStartNew; // ready for the next line - // Between consecutive commands, the endstring=NULL character is inserted - // this is to indicate that line was already counted as completed - AddChar(0 ); // append a line end char, will detect bufferFull! - LinesComplete++; } // count completed lines - break; - case isWaitNewLine: // waiting for a new line end to arrive after an overflow - if (LineEnds) { MyState = isStartNew; } - break; - default: MyState = isOverflow; // goes into error state, should never happen though - } -} // writeBuf - -// Barebone function, that performs the checks to be performed! -// Passes back the actC, and reads already the nextChar into actC -char Interpreter::GetAChar( void ) { -char oldC = actC; - if (BufAvail==BuffLen) { actC = 0; } // buffer is empty - else // something is in the buffer - { if (ScanIndex == BuffLen) {ScanIndex=0;} - else {ScanIndex++;} - actC=RingBuf[ScanIndex]; // all right, get it - BufAvail++; // Buffer is increasing - } // something is in the buffer - return oldC; -} - -// skip true blank, but also Tab characters -void Interpreter::SkipBlanks( void ) { - while(BufAvail<BuffLen && (actC==' ' || actC==9|| actC==0)) { GetAChar(); } -} // SkipBlanks - -int Interpreter::ReadAnInt( void ) { -bool Negative = false; -int Result = 0; - if (actC=='-') {Negative = true; GetAChar(); } - else if (actC=='+') {Negative = false; GetAChar(); } - while(BufAvail<BuffLen && actC>='0' && actC<='9') - { Result = Result * 10 + (GetAChar()-'0') ; } - return Negative? -Result : Result; -} // ReadAnInt - - -RD_CMD_TYPE Interpreter::ParseCommand( void ) { - RD_CMD_TYPE cmd; // locally built command - actC=RingBuf[ScanIndex]; - SkipBlanks(); - // Next Character is the command - cmd.Command = GetAChar(); - // Next Blanks are to be omitted, but are not even mandatory - SkipBlanks(); - if ((actC>='0' && actC<='9') || actC=='-' || actC=='+' ) - { cmd.Parameter= ReadAnInt(); cmd.NumParam = 1; } - else { cmd.Parameter= 0; cmd.NumParam = 0; } - SkipBlanks( ); // There should be at least a trailing NUL character to be removed - LinesComplete--; // one line less in the storage - - return cmd; // return the built command -} - - - -
diff -r 32b17da1ddae -r 6f5b84940d04 Bot_Auxiliaries.h --- a/Bot_Auxiliaries.h Wed Oct 31 14:22:26 2018 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,101 +0,0 @@ - -#ifndef BOT_AUXILIARIES_H -#define BOT_AUXILIARIES_H - -#include "mbed.h" -#include "LED_WS2812.h" - - -// Put the LED names in the order they are chained up -enum LED_Nr{ ledAvG, ledAvD, ledArD, ledArG, NumLEDs }; - - -// ***************************************************************** -// Handle all the LEDs with some general function wrappers functions -// ***************************************************************** - -/** Control 4 LEDs around the Car: front / rear, left / right - * - * Example: - * @code - * // --- Define the PIN where the LED band is connected ----- - * LED_CAR ledBand(PB_5,4); - * Setup rainbow colors for the ledBand - * ledBand.LEDsRainbow(); - * Rotate the colors for the ledBand - * ledBand.StartRotation(0.6) ; - * Turn off the LEDs: - * ledBand.LEDsOff(); - * @endcode - */ - - -class LED_CAR: public LED_WS2812 -{ - public: - /** Create a Car-LED object to control the four LEDs around the car - * - * @param PinName Pin Name through wich the LEDs are controlled - * @param _nbLeds Number of LEDs actually implemented, defaults to 4 - */ - LED_CAR(PinName _PinOut, int _nbLeds):LED_WS2812(_PinOut, _nbLeds) { }; - - void LEDsOff( void ); - void LEDsRainbow( void ); - void LEDNrCol(LED_Nr aNr, int parameter) ; - void LEDsRainbowMove( double speed ); - void LEDClignote(LED_Nr aNr, int OnOff); - int ColNr2Color( char ColNr); - - // ***************************************************************** - // Handle all the LEDs specifically with the LED Position definitions - // ***************************************************************** - - void LEDFront(int ColNr) ; - void LEDRear(int ColNr) ; - void LEDCligR(int speed); - void LEDCligL(int speed); - void LEDAnim(int speed); -}; // class LED_CAR - -const int BuffLen = 512; - -// Define States of the interpreter -enum InterpretState { isStartNew, isLineFilling, isOverflow, isWaitNewLine}; - -typedef struct RD_CMD_TYPE { - char Command; // Holds the next read command character - int Parameter ; // Holds one int Parameter - int NumParam ; // Indicates how many parameters where found - } RD_CMD_TYPE; - - -// Uses a Ring buffer to buffer incomiing characters -// Uses a parsing function to extract lines containing a command each -class Interpreter{ - public: - // Interpreter Class Creation - Interpreter(); - void Reinit( void ); - - public: // the writing mechanics - void AddChar ( char aChar ); // Barebone function, assumes that checks havee been performed by writeBuf! - void writeBuf( char c) ; // High level method to add a Char to the buffer, - char RingBuf[BuffLen]; - InterpretState MyState;// Indicates if buffer overflow, line ended etc. - int WriteIndex ; // points to next index to write to - int BufAvail ; // indicates how much of the buffer is still available - int LinesComplete; // Indicates how many complete lines are available - - public: // the reading mechanics - RD_CMD_TYPE ParseCommand( void ) ; - int ScanIndex; // points to next index to read from to - char actC ; // holds the actual character - private: - char GetAChar ( void ); - void SkipBlanks( void ); - int ReadAnInt ( void ); - char actPP ( void ); -}; // class Interpreter - -#endif \ No newline at end of file
diff -r 32b17da1ddae -r 6f5b84940d04 CMD_Interpreter.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CMD_Interpreter.cpp Fri Jun 21 15:26:49 2019 +0000 @@ -0,0 +1,200 @@ +// ***************************************************************** +// Handle all the LEDs with some general function wrappers functions +// ***************************************************************** +#include "CMD_Interpreter.h" + +//************************************ +// Interpreter Class Creation +//************************************ +// Strategy: the interpreter accumulates characters in its input buffer +// it flags the presence of complete lines +// it also flags Overflow of the buffer in which case all subsequent characters +// are lost until the queue is emptied, and a CR-LF is received +// Defined States of the interpreter: +// MyState = isStartNew, isLineFilling, isOverflow, isWaitNewLine}; + +// #define DEBUG(...) { snprintf(buff, sizeof(buff), __VA_ARGS__); DataLog( buff ); } + +Interpreter::Interpreter( void ) +{ Reinit( ); + MyState = isStartNew; + AllCommands = NULL; + NumCommands = 0; +} + +void Interpreter::FillCommands( int aNumCommands, const EXE_CMD_TYPE *ACommands ) +{ int cnt; + AllCommands = new EXE_CMD_TYPE[ aNumCommands ]; + for( cnt=0; cnt<aNumCommands; cnt++) + { AllCommands[cnt] = ACommands[cnt]; } ; + NumCommands = aNumCommands; +} + +void Interpreter::Reinit( void ) { + MyState = isWaitNewLine; // indicates no buffer overflow + WriteIndex = 0; // points to next index to write to + LinesComplete = 0; // indicates that no complete line is currently available + // Start Scanning at the start + ScanIndex = 0; + BufAvail = BuffLen;// the full buffer size is available + } + +// Barebone function, assumes that checks havee been performed by writeBuf! +void Interpreter::AddChar( char aChar ) { + if (aChar == 8) // is it a backspace code, then remove one character: + { if (BufAvail<BuffLen) { // there's actually a character to be removed + BufAvail++; // Buffer regrows + if (WriteIndex == 0) {WriteIndex=BuffLen-1;} + else {WriteIndex--;} // recoil the write index + } + } + else { + if (WriteIndex == BuffLen-1) {WriteIndex=0;} + else {WriteIndex++;} + RingBuf[WriteIndex]=aChar; // all right, buffer it! + BufAvail--; // Buffer is shrinking + if (BufAvail==0) { MyState = isOverflow; } + } +} + +// High level method to add a Char to the buffer, +// Separates at Chars 10, 13, 0; replaced by a single 0 char +// Blocking write when buffer has overflowed +void Interpreter::writeBuf(char aChar) { + bool LineEnds = aChar==10 || aChar==13 || aChar==0; + switch (MyState) { + case isOverflow: break; + case isStartNew: // ready for the next line to start + // avoid that consecutive CR LF are counted as multiple lines + if (!LineEnds) {AddChar(aChar ); MyState = isLineFilling; } + break; + case isLineFilling:// New line has started filling + if (!LineEnds) {AddChar(aChar);} + else + {MyState = isStartNew; // ready for the next line + // Between consecutive commands, the endstring=NULL character is inserted + // this is to indicate that line was already counted as completed + AddChar(0 ); // append a line end char, will detect bufferFull! + LinesComplete++; } // count completed lines + break; + case isWaitNewLine: // waiting for a new line end to arrive after an overflow + if (LineEnds) { MyState = isStartNew; } + break; + default: MyState = isOverflow; // goes into error state, should never happen though + } +} // writeBuf + +// Barebone function, that performs the checks to be performed! +// Passes back the actC, and reads already the nextChar into actC +char Interpreter::GetAChar( void ) { +char oldC = actC; + if (BufAvail==BuffLen) { actC = 0; LinesComplete=0; } // buffer is empty, no more lines!! + else // something is in the buffer + { if (ScanIndex == BuffLen) {ScanIndex=0;} + else {ScanIndex++;} + actC=RingBuf[ScanIndex]; // all right, get it + if (actC==0) {LinesComplete--; } // now there is one line less in the storage + BufAvail++; // Buffer is increasing + } // something is in the buffer + return oldC; +} + +// skip true blank, but also Tab characters +void Interpreter::SkipBlanks( void ) { + while(BufAvail<BuffLen && (actC==' ' || actC==9|| actC==0)) { GetAChar(); } +} // SkipBlanks + +int Interpreter::ReadAnInt( void ) { +bool Negative = false; +int Result = 0; + if (actC=='-') {Negative = true; GetAChar(); } + else if (actC=='+') {Negative = false; GetAChar(); } + while(BufAvail<BuffLen && actC>='0' && actC<='9') + { Result = Result * 10 + (GetAChar()-'0') ; } + return Negative? -Result : Result; +} // ReadAnInt + + +RD_CMD_TYPE Interpreter::ParseCommand( void ) { + RD_CMD_TYPE cmd; // locally built command + actC=RingBuf[ScanIndex]; // initialiye the actC variable, as the first char to use + SkipBlanks(); + // Next Character is the command + cmd.Command = GetAChar(); + // Next Blanks are to be omitted, but are not even mandatory + SkipBlanks(); + if ((actC>='0' && actC<='9') || actC=='-' || actC=='+' ) + { cmd.Parameter= ReadAnInt(); cmd.NumParam = 1; } + else { cmd.Parameter= 0; cmd.NumParam = 0; } + SkipBlanks( ); // There should be at least a trailing NUL character to be removed + return cmd; // return the built command +} + +bool Interpreter::executeCommand(RD_CMD_TYPE cmd) { + int CmdNr; + bool Found; + CmdNr = 0; + Found = false; + // DEBUG("Com '%c'=%d %d NPar=%d \n\r",cmd.Command, cmd.Command, cmd.Parameter, cmd.NumParam); + // While not found go through all the commands, linear; they are not sorted by alphabet. + while(CmdNr<NumCommands && !Found) + { // DEBUG("NR:%d \n\r", CmdNr); + if (AllCommands[CmdNr].cmd == cmd.Command) + { // the command character matches + if (cmd.NumParam == AllCommands[CmdNr].Npar) + { // DEBUG("Execute: %s \n\r", AllCommands[CmdNr].help); + AllCommands[CmdNr].Handler( cmd.Parameter ); // then call the handler + } + // else { DataLog("Param Mismatch!\n\r"); } // Inform about Parameter error + Found = true; // and mark as found + } + else { CmdNr++; } // go on serarching + } // while + // if ( !Found ) { CmdInval(cmd.Command) ; } // call invalid command function + return Found; +} + +bool Interpreter::ProcessPresentCommands( void ) +{ RD_CMD_TYPE Readcmd; + if (MyState==isOverflow) { Reinit(); } + if(LinesComplete>0) + { // DEBUG("X: Scan=%d ", Interp.ScanIndex); + Readcmd = ParseCommand(); + executeCommand( Readcmd ); + //DEBUG("state=%d; wix=%d; rix=%d; buf=%s ", Interp.MyState, Interp.WriteIndex, Interp.ScanIndex, &Interp.RingBuf[Interp.ScanIndex]); + return true; + } + else { return false; } +} + +char *ParamHelp[] = {" ", "<param>", "<par><par>"}; + +void Interpreter::PrtCmdHelp (Serial *aSerial ) // Display list of Commands +{ EXE_CMD_TYPE *com; + int CmdNr; + char *parStr; + // DataLog("List of commands: \n\r"); + // Go Through all commands in the table + for (CmdNr = 0; CmdNr<NumCommands; CmdNr++ ) + { com = &AllCommands[CmdNr]; // get a pointer to the command + parStr = ParamHelp[com->Npar]; // Get the string that represents the number of parameters + aSerial->printf( " %c %s => %s \n\r", com->cmd, parStr, com->help.c_str() ); // output the full command help + } +} + +/* +void Interpreter::CmdInval( int param ) // Feedback that the command is invalid +{ DEBUG( " Invalid command %d = '%c'; use: 'h' for help. \n\r", param, char(param) ) ; +} + +string Interpreter::GetLastMessage( void ) +{ string LastMsg = LastMessage; + LastMessage = ""; // Empty the old Message + return LastMsg; +} + +void Interpreter::DataLog( char *DebugMessage ) +{ if (LastMessage=="" ) { LastMessage = DebugMessage; } + else { LastMessage = LastMessage + "\n\r" + DebugMessage; } +}; +*/
diff -r 32b17da1ddae -r 6f5b84940d04 CMD_Interpreter.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CMD_Interpreter.h Fri Jun 21 15:26:49 2019 +0000 @@ -0,0 +1,68 @@ + +#ifndef CMD_Interpreter_H +#define CMD_Interpreter_H + +#include "mbed.h" +#include <string> + +const int BuffLen = 512; + +// define commands to be handled! +typedef void (*caseHandler)(int param); + +typedef struct EXE_CMD_TYPE{ + char cmd; // THe single command character + char Npar; // The number of parameters needed by the command, only for help text. All command Hanlders must have a Parameter + caseHandler Handler; // Command Handlers + string help; // Help Text for that command + }EXE_CMD_TYPE; + +// Define States of the interpreter +enum InterpretState { isStartNew, isLineFilling, isOverflow, isWaitNewLine}; + +typedef struct RD_CMD_TYPE { + char Command; // Holds the next read command character + int Parameter ; // Holds one int Parameter + int NumParam ; // Indicates how many parameters where found + } RD_CMD_TYPE; + +// Uses a Ring buffer to buffer incomiing characters +// Uses a parsing function to extract lines containing a command each +class Interpreter{ + public: + // Interpreter Class Creation + Interpreter( void ); + void Reinit( void ); + void FillCommands(int aNumCommands, const EXE_CMD_TYPE *ACommands ); + public: // the writing mechanics + void AddChar ( char aChar ); // Barebone function, assumes that checks havee been performed by writeBuf! + void writeBuf( char c ) ; // High level method to add a Char to the buffer, + char RingBuf[BuffLen]; + InterpretState MyState;// Indicates if buffer overflow, line ended etc. + int WriteIndex ; // points to next index to write to + int BufAvail ; // indicates how much of the buffer is still available + int LinesComplete; // Indicates how many complete lines are available + bool ProcessPresentCommands( void ); + RD_CMD_TYPE ParseCommand( void ); + bool executeCommand(RD_CMD_TYPE cmd); + void PrtCmdHelp ( Serial *aSerial ); // Display list of Commands + // void GetLastMessage( string LastMsg); // not possible to implement at the moment + public: // the reading mechanics + int ScanIndex; // points to next index to read from to + char actC ; // holds the actual character + private: + char GetAChar ( void ); + void SkipBlanks( void ); + int ReadAnInt ( void ); + char actPP ( void ); + EXE_CMD_TYPE* AllCommands; // Defines an array of all commands to be filled by the user. + int NumCommands; // Holds the actual number of commands that are stored in the array + /* + char buff[100]; // Intermediate buffer to hold messages for datalogging + string LastMessage; + void DataLog( char *DebugMessage ); + void CmdInval( int param ); // Feedback that the command is invalid + */ +}; // class Interpreter + +#endif // CMD_Interpreter_H \ No newline at end of file