Auxiliaries I use for CreaBot

Files at this revision

API Documentation at this revision

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

Bot_Auxiliaries.cpp Show diff for this revision Revisions of this file
Bot_Auxiliaries.h Show diff for this revision Revisions of this file
CMD_Interpreter.cpp Show annotated file Show diff for this revision Revisions of this file
CMD_Interpreter.h Show annotated file Show diff for this revision Revisions of this file
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