Karpova Lab fork of stateScript

Dependencies:   SMARTWAV SOMO_II mbed

Fork of stateScript_v2_karpova by Andy Lustig

Revision:
0:8dbd6bd9167f
Child:
1:3a050d26d4f6
Child:
3:d7b0a0890d96
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/behave.h	Tue May 19 15:45:42 2015 +0000
@@ -0,0 +1,572 @@
+//#include "mbed.h"
+#include <stdint.h>
+#include <string.h>
+#include <string>
+#include <vector>
+#include <list>
+#include <deque>
+#include <queue>
+#include "hardwareInterface.h"
+
+
+#define MBEDHARDWARE  //here is where we define which platform we are compiling for
+//#define FPGAHARDWARE
+
+#define MAXVARNAMESIZE 30 //The maximum number of characters of a variable name
+
+
+
+
+
+#ifdef MBEDHARDWARE
+    #include "mbedInterface.h"
+#endif
+#ifdef FPGAHARDWARE
+    #include "fpgaInterface.h"
+#endif
+
+
+#define NUMEVENTS 50
+#define NUMCONDITIONS 150
+#define NUMINTCOMPARE 150
+#define NUMACTIONS 150
+#define NUMPORTMESSAGES 150
+#define NUMINTOPERATIONS 150
+#define NUMDISPLAYACTIONS 30
+#define NUMTRIGGERACTIONS 30
+
+#define ARITHMATIC_CONDITION    0
+#define OR_CONDITION    1
+#define AND_CONDITION    2
+
+#define NUMFUNCTIONS 50
+#define INPUTCHARBUFFERSIZE 3072
+
+using namespace std;
+
+class event; //we foreward declare this because of class interdependencies
+
+//used in the digital port class to organize digital change events
+/*
+struct changeEvent {
+    uint32_t timeStamp;
+    bool triggered;
+};*/
+
+
+//The digitalPort object directly controls and keeps data about the port. Each port has
+//one digital out and one digital in.
+class digitalPort {
+public:
+    digitalPort();
+    //digitalPort(sDigitalOut* DOP, sDigitalIn* DIP);
+    void init(sDigitalOut* DOP, sDigitalIn* DIP);
+    void setDigitalOut(int outVal);
+    //int  getDigitalOut();
+    int  getDigitalIn();
+    int getLastChangeState();
+    uint32_t getTimeSinceLastChange();
+    uint32_t lastChangeTime;
+    uint32_t lastOutChangeTime;
+
+    void setTriggerUpEvent(event* eventInput); //attahces a routine to an upward change
+    void setTriggerDownEvent(event* eventInput); //attahces a routine to a downward change
+    //void addStateChange(int newState, uint32_t timeStamp);
+
+    bool update(); //called from the main loop
+
+    int inState;
+    int outState;
+
+    bool outStateChanged;
+
+    event* triggerUpEventPtr;
+    event* triggerDownEventPtr;
+
+private:
+
+    sDigitalOut* outPin;
+    sDigitalIn*  inPin;
+    int lastInState;
+    uint32_t lastChangeInterval;
+
+    //changeEvent lastUpEvent;
+    //changeEvent lastDownEvent;
+};
+
+
+//an intVariable contains an integer value and the name of that variable within the script
+class intVariable {
+
+public:
+    intVariable();
+    intVariable(std::string& tagInput, int initialValue);
+    void set(std::string& tagInput, int initialValue);
+    int value;
+    //string tag;
+    char tag[MAXVARNAMESIZE+1];
+    bool isUsed;
+
+};
+
+
+//ACTION SECTION-- an 'action' is a command in the script. It can be a single command,
+//or a block containing a set of actions
+//------------------------------------------------------------------------------------
+
+//display actions are used to output text messages via the serial port.  The user can display
+//either a static text string or the value of a single variable.
+class displayAction {
+
+public:
+    displayAction();
+    void set(int* variable, string varNameInput);
+    void set(string text);
+    bool isUsed;
+    void execute();
+    void release();
+
+private:
+    int* dVariable;
+    string dText;
+
+};
+
+class triggerFunctionAction {
+
+public:
+    triggerFunctionAction();
+    triggerFunctionAction(int functionNum);
+    void set(int functionNum);
+    bool isUsed;
+    void execute();
+    void release();
+private:
+    int functionNum;
+
+
+};
+
+//intOpertaion is an action that does addition or subtraction of integers and returns/stores the result
+//these operation are very limited so far (only + or - allowed, and only one operation per object,
+//for example a = b + b works but a = b + c + d does not. The output value can also be set to a random number.
+class intOperation {
+
+public:
+    intOperation();
+
+    /*
+     intOperation(int randParam, const char* cmpString, int cmpValInput);
+     intOperation(int randParam, const char* cmpString, int* cmpIntVarInput);
+     intOperation(int* intVarInput, const char* cmpString, int cmpValInput);
+     intOperation(int* intVarInput, const char* cmpString, int* cmpIntVarInput);
+     intOperation(int* intVarInput, intOperation* operationInput);
+     */
+
+    ~intOperation();
+
+    //Supported operations with rand:
+    //a = rand(x)
+    //a = rand(x) + 3
+    //a = rand(x) + b
+    void setRandOp(int randParam, const char* cmpString, int cmpValInput, bool flipped);
+    void setRandOp(int randParam, const char* cmpString, int* cmpIntVarInput, bool flipped);
+
+    //Supported regular operations
+    //a = 5
+    //a = b
+    //a = b + 6
+    //a = b + c
+    void set(int* intVarInput, const char* cmpString, int cmpValInput);
+    void set(int* intVarInput, const char* cmpString, int* cmpIntVarInput);
+    void set(int* intVarInput, intOperation* operationInput);
+
+
+    //Supported operations with clock()
+    //a = clock()
+    //a = clock() + 5
+    //a = clock() + b
+    void setClockOp(int* intVarInput);
+    void setClockOp(const char* cmpString, int cmpValInput, bool flip);
+    void setClockOp(const char* cmpString, int* cmpIntVarInput, bool flip);
+
+    void release();
+    bool isUsed;
+    int execute();
+
+private:
+    int randHigh;
+    int* cmpVal;
+    int* intVal;
+    intOperation* opPtr;
+    bool cmpValGlobal;
+    bool isClockAssign; //if the current clock value is part of the operation
+    bool inputsFlipped;
+    int (intOperation::*executePtr)();
+    int addAndStore();
+    int subtractAndStore();
+    int add();
+    int subtract();
+    int equals();
+
+};
+
+//portMessage is an action to change a digital port.  So far, You can only change the digital out (0 or 1)
+class portMessage {
+public:
+
+    portMessage();
+    //portMessage(digitalPort* portIn, int whichToSet, int value); //whichToSet: 1 DigitalOut; 2 State
+    //void setMessage(digitalPort* portIn, int whichToSet, int value); //whichToSet: 1 DigitalOut; 2 State
+    //portMessage(int* portIn, int whichToSet, int value); //whichToSet:
+    void setMessage(int* portIn, int whichToSet, int value, digitalPort* portVector); //whichToSet:
+
+    void execute();
+    void release();
+    bool isUsed;
+
+private:
+    int whichToSet; //hard coded port number
+    int* port; //alternative variable port number
+    int value;
+
+    digitalPort* portVector;
+
+};
+
+//holder class for all possible actions. This include general system commands.
+class action {
+public:
+
+    action();
+    ~action();
+    action(intOperation* opInput);
+    action(portMessage* messageInput);
+    action(event* eventInput);
+    //action(event* eventInput, uint32_t delay);
+    action(displayAction* displayInput);
+    action(sSound* soundInput);
+    action(triggerFunctionAction* triggerFuncInput);
+    action(int8_t sysCommandInput); //for general system commands
+
+    void set(intOperation* opInput);
+    void set(portMessage* messageInput);
+    void set(event* eventInput);
+    //void set(event* eventInput, uint32_t delay);
+
+    void set(displayAction* displayInput);
+    void set(sSound* soundInput);
+    void set(triggerFunctionAction* triggerFuncInput);
+    void set(int8_t sysCommandInput);
+    void execute();
+    void execute(uint32_t blockExecTime);
+    void release();
+    bool isUsed;
+
+private:
+    intOperation* op;
+    portMessage* message;
+    event* eventToCreate;
+    displayAction* displayActionPtr;
+    sSound* sound;
+    triggerFunctionAction* triggerFunc;
+    //uint32_t eventDelay;
+    int8_t sysCommand;
+    char actionType;
+
+};
+//-----------------------------------------------------
+
+//CONDITION SECTION-- a 'condition' is used in the beginning of a block (if-else blocks or while blocks)
+//If the condition is true, the block is exectuted during a callback
+//------------------------------------------------------------------------------------
+
+
+//intCompare is a condition class that compares the state value of a port or
+//an integer variable to another integer variable or operation output
+class intCompare {
+
+public:
+    intCompare();
+    intCompare(digitalPort* portInput, const char* cmpString, int cmpValInput, int whichToUse);
+    intCompare(digitalPort* portInput, const char* cmpString, int* cmpIntVarInput, int whichToUse);
+    intCompare(int* intVarInput, const char* cmpString, int cmpValInput);
+    intCompare(int* intVarInput, const char* cmpString, int* cmpIntVarInput);
+    intCompare(int* intVarInput, const char* cmpString, intOperation* cmpIntOpInput);
+    intCompare(digitalPort* portInput, const char* cmpString, intOperation* cmpIntOpInput, int whichToUse);
+
+    void set(digitalPort* portInput, const char* cmpString, int cmpValInput, int whichToUse);
+    void set(digitalPort* portInput, const char* cmpString, int* cmpIntVarInput, int whichToUse);
+    void set(int* intVarInput, const char* cmpString, int cmpValInput);
+    void set(int* intVarInput, const char* cmpString, int* cmpIntVarInput);
+    void set(int* intVarInput, const char* cmpString, intOperation* cmpIntOpInput);
+    void set(digitalPort* portInput, const char* cmpString, intOperation* cmpIntOpInput, int whichToUse);
+
+    void release();
+
+    ~intCompare();
+    bool isTrue();
+    bool isUsed;
+
+private:
+    digitalPort* port;
+    int* portValPtr;
+    int* cmpVal;
+    int* intVal;
+    intOperation* intOp;
+    void setPointer(const char* cmpString);
+    void setPointer_operation(const char* cmpString);
+    bool (intCompare::*isTruePtr)();
+    bool cmpValGlobal;
+    bool greaterThan();
+    bool greaterOrEqual();
+    bool lessThan();
+    bool lessOrEqual();
+    bool equal();
+    bool notEqual();
+    bool greaterThan_op();
+    bool greaterOrEqual_op();
+    bool lessThan_op();
+    bool lessOrEqual_op();
+    bool equal_op();
+    bool notEqual_op();
+};
+
+
+//holder class for all possible conditions (so far only intCompare)
+class condition {
+public:
+
+    condition();
+    condition(intCompare* compareInput);
+    condition(condition* condition1, char condType, condition* condition2);
+    ~condition();
+    void set(intCompare* compareInput);
+    void set(condition* condition1, char condType, condition* condition2);
+    bool isTrue();
+    bool isUsed;
+    void release(); //called when the event is no longer being used;
+private:
+
+    //char conditionType; //1 for intCompare
+    intCompare* intCmp;
+    condition*  conditionPtrs[2];
+    char        conditionType;
+
+
+};
+//--------------------------------------------
+
+
+//queueItem connects a pre-defined event with an exectution time.
+//They are placed in the eventQueue
+struct queueItem {
+    uint32_t timeToExecute;
+    event* eventPtr;
+};
+
+
+//Organizes events in a temporal queue.  check() is called from the main loop.
+//If the execution time of the event has passed, then the event is exectuted.
+class eventQueue {
+public:
+    eventQueue();
+    void addEventToQueue(event* eventInput, uint32_t delay);
+    void eraseQueue(); //clear all future events
+    void check(void);
+
+private:
+    std::vector<queueItem> events;
+    int queueSize;
+
+};
+
+//An 'event' is a block of 'actions' that can be gated with a boolean 'condition' set. All
+//conditions in the set must be true for the block of actions to be executed. Right now,
+//there is no OR logic (||), only AND (&&).
+//The entire event is placed on the event queue to be executed at a given delay.
+//At that future time, the condition is checked and if true, the block of actions
+//is exectuted. Note: an 'action' can be another event (or even the parent event), allowing
+//nested 'if' and 'while' statements.
+class event {
+public:
+
+    event();
+    event(eventQueue* queueInput);
+    ~event();
+    void setTimeLag(uint32_t timeLagInput); //the event will be exectuted at this time from now
+    void setTimeLag(int* timeLagInput); //the event will be exectuted at this time from now
+    void setWhileLoopPeriod(uint32_t period);
+    void setWhileLoopPeriod(int* period);
+    void addCondition(condition* conditionInput); //contains a set of conditions to check and a truth table
+    bool isConditionTrue(void); //checks if the condition is true
+    void addAction(action* actionInput); //called during script parsing, when the block is being defined
+    void addToQueue(void); //places the event on the event queue with default time lag.  When the time
+    //lag has expired, the the block is executed
+    void addToQueue(uint32_t delay);
+    void execute(void); //Execute without checking the condition. Called only from the event queue
+    void setNextElseEvent(event* eventInput); //allows for else event block
+    uint32_t timeLag; //default time from now when the event will be executed (this is ignored once placed in event queue)
+    int* timeLagVar; //exectution time lab defined by a variable
+    eventQueue* queuePtr;
+    void release(); //called when the event is no longer being used;
+
+    char blockType;  //0 callback
+    //1 if ... do block (with conditions)
+    //2 do block (no conditions)
+    //3 else if ... do block
+    //4 else do (no conditions)
+    //5 while ... do every ... block
+    //6 else while ... do every ... block
+    //7 then if ... do block
+    //8 then do (no conditions)
+
+    uint32_t whileLoopPeriod; //if non-zero, the block is a while loop (executed at regular intervals)
+    int* whileLoopPeriodVar;
+    event* nextElseEventPtr;
+    bool isUsed;
+    bool timeLagIsConstant;
+    bool whileLoopPeriodIsConstant;
+    bool hasWhileLoop;
+
+private:
+    int numConditions;
+    int numActions;
+    condition* conditionToCheck;
+    action* actionArray[20];
+
+    //if statement (can be left empty, which is interpreted as 'true')
+    //std::vector<condition*> conditionArray;
+    //std::deque<action*> actionArray;
+
+};
+
+//each functionItem help a poiter to an action, and the name of the function.  Not currently in use.
+class functionItem {
+public:
+    functionItem(action* actionInput, string tagInput);
+    ~functionItem();
+    string tag;
+    action* actionPtr;
+};
+
+class blockBuffer {
+
+public:
+    blockBuffer();
+    bool addLine(char* input, int numChars);
+    string getNextLine();
+    int16_t linesAvailable();
+    bool empty();
+    void resetBuffer();
+
+private:
+#ifdef MBEDHARDWARE
+    //On the MBED, we need to put this on a different memory bank
+    __attribute((section("AHBSRAM1"),aligned)) char charBuffer[INPUTCHARBUFFERSIZE];
+#else
+    char charBuffer[INPUTCHARBUFFERSIZE];
+#endif
+    int16_t bufferWritePos;
+    int16_t bufferReadPos;
+    int16_t _linesAvailable;
+
+};
+
+//Parser for the incoming text.  The parser is called when a line terminates with a semicolon (;).
+//Only the final line in a callback block should have a semicolon.
+class scriptStream {
+public:
+    scriptStream(digitalPort* portVectorInput, int numPortsInput, eventQueue* queueInput, sSystem* system);
+    void parseBlock();
+    void addLineToCurrentBlock(char* lineInput); // if the line did not end with a semicolon, add it to the current block
+    int* findIntVariable(string nameInput); //used to retrieve the pointer to the designated variable if it exists
+    int* findIntVariable(const char* nameInput); //used to retrieve the pointer to the designated variable if it exists
+    int* findIntVariable(const char* nameInput, int start, int end); //used to retrieve the pointer to the designated variable if it exists
+
+    bool createIntVariable(string nameInput); // creates a new interger variable
+    action* evaluateAssignmentForAction(string expression); //parses a numerical assignment or operation (a = b - c)
+    action* evaluateAssignmentForAction(const char* expression); //parses a numerical assignment or operation (a = b - c)
+
+    bool evaluateConditions(string& expression, event* currentEvent); //parses a condition statement (a == b && c > d)
+    //condition* parseConditions(string& expression); //parses a condition statement (a == b && c > d)
+    //std::size_t findFirstOrOutsideParenth(string& expression);
+    //std::size_t findFirstAndOutsideParenth(string& expression);
+    //bool isOutsideParenth(string& expression,std::size_t foundItem);
+
+    condition* parseConditions(const char* expression,int start, int end); //parses a condition statement (a == b && c > d)
+    int findFirstOrOutsideParenth(const char* expression, int start, int end);
+    int findFirstAndOutsideParenth(const char* expression, int start, int end);
+    bool isOutsideParenth(const char* expression,int foundItem, int start, int end);
+    bool isNum(const char* expression, int start, int end);
+    bool areStringsSame(const char* str1, const char* str2, int start, int end);
+
+    int getRandomParam(string expression);
+    int getRandomParam(const char* expression,int start,int end);
+
+
+    int findStringLoc(const char* refString,const char* findString,int start, int end);
+
+
+
+private:
+
+    int currentTriggerPort;
+    int currentTriggerDir;
+    int currentPort;
+    int currentFunction;
+
+    string tmpLine;
+    vector<string> tokens;
+
+    bool lineError;
+    int blockDepth;
+    bool ifBlockInit;
+    bool whileBlockInit;
+    bool elseFlag;
+    bool thenFlag;
+    bool expectingDoStatement;
+    int currentDelay;
+    event* tmpEvent;
+    string tmpString;
+
+    vector<intVariable*> globalVariables;
+    vector<event*> tmpEventPtrArray;
+    //event* functionEventArray[NUMFUNCTIONS];
+    //bool   functionSpotTaken[NUMFUNCTIONS];
+
+    //vector<functionItem*> functionArray; //any blocks declared outsite callback blocks are stored here
+    //list<string> currentBlock;
+    blockBuffer currentBlock;
+    digitalPort* portVector;
+    sSystem* system;
+
+
+
+    int numPorts;
+    eventQueue* queuePtr;
+
+};
+
+
+class mainLoop
+
+{
+public:
+    mainLoop();
+    void init();
+    void exec();
+private:
+    void eraseBuffer();
+    uint32_t currentDIOstate[2];
+    bool digitalInChanged;
+    bool digitalOutChanged;
+    scriptStream *parser;
+    sSystem *hardware; //hardware interface
+    sSerialPort *pc; //communication to computer
+    char buffer[256];
+    digitalPort ports[NUMPORTS];
+
+
+
+};