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
--- 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
-}
-
-
-
-
--- 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
--- /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; }
+};
+*/
--- /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