Andy Lustig
/
Nucleo_statescript
stateScript for Nucleo-F401RE board
Diff: behave.h
- Revision:
- 0:ecf80f0172d0
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/behave.h Mon Feb 08 18:56:09 2016 +0000 @@ -0,0 +1,571 @@ +//#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 NUCLEOHARDWARE + +#define MAXVARNAMESIZE 30 //The maximum number of characters of a variable name + +#ifdef MBEDHARDWARE + #include "mbedInterface.h" +#endif +#ifdef FPGAHARDWARE + #include "fpgaInterface.h" +#endif +#ifdef NUCLEOHARDWARE + #include "nucleoInterface.h" +#endif + +#define BLOCKMEMORYTYPES 1 +#define VARIABLEMEMORYTYPES 2 +#define ENVSETTINGSMEMORYTYPES 4 + + +/* +#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 NUMFUNCTIONS 50 +#define INPUTCHARBUFFERSIZE 3072 +*/ + +#define ARITHMATIC_CONDITION 0 +#define OR_CONDITION 1 +#define AND_CONDITION 2 + +extern "C" void mbed_reset();//reset mbed through software + + + +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(); //Parses everything since the last semicolon was found + void addLineToCurrentBlock(char* lineInput); // if the line did not end with a semicolon, add it to the current block + +private: + + 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(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); + void clearEnvironmentVariables(int mode); + + 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]; + + + +};