Microcontroller firmware that uses a simple, yet powerful scripting language to control the timing of input and output events with high temporal resolution. Written by Mattias Karlsson

Dependencies:   SMARTWAV mbed

Revision:
4:abee20c0bf2a
Parent:
3:d7b0a0890d96
Child:
5:67d67d452545
diff -r d7b0a0890d96 -r abee20c0bf2a behave.cpp
--- a/behave.cpp	Sat Oct 10 22:37:17 2015 +0000
+++ b/behave.cpp	Fri Jan 15 22:13:23 2016 +0000
@@ -293,7 +293,7 @@
         numTriggersToProcess = hardware->getPendingFunctionTriggers(shortcutTriggers);
         for (int i = 0; i < numTriggersToProcess; i++) {
             textDisplay << "Trigger function " << shortcutTriggers[i]+1 << "\r\n";
-            if ((shortcutTriggers[i] < NUMTRIGGERACTIONS) && functionSpotTaken[shortcutTriggers[i]]) {
+            if ((shortcutTriggers[i] < NUMTRIGGERACTIONS) && functionSpotTaken[shortcutTriggers[i]] && functionEventArray[i]->isUsed) {
                 //textDisplay << "Executing function array index " << shortcutTriggers[i] << "\r\n";
                 functionEventArray[shortcutTriggers[i]]->execute();
             }
@@ -481,7 +481,7 @@
                         lastChangeTime = timeKeeper;
                     }
                     */
-                    if (triggerUpEventPtr != NULL) {triggerUpEventPtr->execute();}
+                    if (triggerUpEventPtr != NULL && triggerUpEventPtr->isUsed) {triggerUpEventPtr->execute();}
                 } else if (inState == 0) {
 
                     lastChangeInterval = inPin->lastDownEvent.timeStamp - lastChangeTime;
@@ -496,7 +496,7 @@
                         lastChangeTime = timeKeeper;
                     }*/
 
-                    if (triggerDownEventPtr != NULL) {triggerDownEventPtr->execute();}
+                    if (triggerDownEventPtr != NULL && triggerDownEventPtr->isUsed){triggerDownEventPtr->execute();}
                 }
             } else if (lastInState == inState) {
 
@@ -506,15 +506,15 @@
                     lastChangeInterval = inPin->lastUpEvent.timeStamp - inPin->lastDownEvent.timeStamp;
                     lastChangeTime = inPin->lastUpEvent.timeStamp;
 
-                    if (triggerDownEventPtr != NULL) {triggerDownEventPtr->execute();}
-                    if (triggerUpEventPtr != NULL) {triggerUpEventPtr->execute();}
+                    if (triggerDownEventPtr != NULL && triggerDownEventPtr->isUsed) {triggerDownEventPtr->execute();}
+                    if (triggerUpEventPtr != NULL && triggerUpEventPtr->isUsed) {triggerUpEventPtr->execute();}
                 } else if (inState == 0) {
 
                     lastChangeInterval = inPin->lastDownEvent.timeStamp - inPin->lastUpEvent.timeStamp;
                     lastChangeTime = inPin->lastDownEvent.timeStamp;
 
-                    if (triggerUpEventPtr != NULL) {triggerUpEventPtr->execute();}
-                    if (triggerDownEventPtr != NULL) {triggerDownEventPtr->execute();}
+                    if (triggerUpEventPtr != NULL && triggerUpEventPtr->isUsed) {triggerUpEventPtr->execute();}
+                    if (triggerDownEventPtr != NULL && triggerDownEventPtr->isUsed) {triggerDownEventPtr->execute();}
                 }
             }
 
@@ -615,7 +615,7 @@
 
 void triggerFunctionAction::execute() {
 
-    if (functionSpotTaken[functionNum]) {
+    if (functionSpotTaken[functionNum] && functionEventArray[functionNum]->isUsed) {
         functionEventArray[functionNum]->execute();
     }
 
@@ -2215,7 +2215,7 @@
 //-------------------------------------------------------
 void scriptStream::parseBlock() {
 
-
+    tmpEvent = NULL;
     lineError = false;
     blockDepth = 0;
     ifBlockInit = false;
@@ -2477,10 +2477,16 @@
                     textDisplay << "Error: clock commands only allowed outside of block structure\r\n";
                     lineError = true;
                 }
+                int pos1 = tmpLine.find("clock(")+6;
+                int pos2 = tmpLine.find_first_of(")",pos1);
+                if (pos2 == std::string::npos) {
+                    textDisplay << "Syntax Error: expected a ')'\r\n";
+                    lineError = true;
+                }
 
                 if (!lineError) {
-                    int pos1 = tmpLine.find("clock(")+6;
-                    int pos2 = tmpLine.find_first_of(")",pos1);
+                    //int pos1 = tmpLine.find("clock(")+6;
+                    //int pos2 = tmpLine.find_first_of(")",pos1);
                     string dispVar = tmpLine.substr(pos1,pos2-pos1);
 
 
@@ -2612,61 +2618,67 @@
                 wholeLineEvaluated = true;
                 int pos1 = tmpLine.find("trigger(")+8;
                 int pos2 = tmpLine.find_first_of(")",pos1);
-                int funcNum = atoi(tmpLine.substr(pos1,pos2-pos1).data());
-                if ((funcNum > 0) && (funcNum < NUMFUNCTIONS+1)) {
-                    if (functionSpotTaken[funcNum-1]) {
-
-
-                    } else {
-                        textDisplay << "Error: function number does not exist\r\n";
-                        lineError = true;
-                    }
-                } else {
-                    textDisplay << "Error: not a valid function number\r\n";
+                if (pos2 == std::string::npos) {
+                    textDisplay << "Syntax error: expected a ')'\r\n";
                     lineError = true;
                 }
 
-                funcNum--;  //change to 0-based index
-                if (!lineError && (blockDepth == 0)) {
-                    //we are not inside a block structure, so execute function now
-                    //textDisplay << "Exectuting function";
-                    //textDisplay.flush();
-
-                    functionEventArray[funcNum]->execute();
-
-                } else if (!lineError && (blockDepth > 0) ){
-                    //the trigger function was put inside a block, so we need to create a new action
-                    textDisplay.debug("Trigger statement\r\n");
-                    triggerFunctionAction* tPtr = findFirstUnUsed(triggerFunctionActionBlock, NUMTRIGGERACTIONS);
-                    if (tPtr == NULL) {
-                        textDisplay << "Error: no memory slots available.\r\n";
+                if (!lineError) {
+                    int funcNum = atoi(tmpLine.substr(pos1,pos2-pos1).data());
+                    if ((funcNum > 0) && (funcNum < NUMFUNCTIONS+1)) {
+                        if (functionSpotTaken[funcNum-1] && functionEventArray[funcNum]->isUsed) {
+
+
+                        } else {
+                            textDisplay << "Error: function number does not exist\r\n";
+                            lineError = true;
+                        }
+                    } else {
+                        textDisplay << "Error: not a valid function number\r\n";
                         lineError = true;
                     }
 
-                    if (!lineError) {
-                        //we only give provide it the function number, instead
-                        //of a pointer to the event.  That way, if the user modifies
-                        //the function (which would change the pointer), all callbacks
-                        //still using that function number will use the new function.
-                        tPtr->set(funcNum);
-                        action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);
-                        if (tmpAction == NULL) {
+                    funcNum--;  //change to 0-based index
+                    if (!lineError && (blockDepth == 0)) {
+                        //we are not inside a block structure, so execute function now
+                        //textDisplay << "Exectuting function";
+                        //textDisplay.flush();
+
+                        functionEventArray[funcNum]->execute();
+
+                    } else if (!lineError && (blockDepth > 0) ){
+                        //the trigger function was put inside a block, so we need to create a new action
+                        textDisplay.debug("Trigger statement\r\n");
+                        triggerFunctionAction* tPtr = findFirstUnUsed(triggerFunctionActionBlock, NUMTRIGGERACTIONS);
+                        if (tPtr == NULL) {
                             textDisplay << "Error: no memory slots available.\r\n";
                             lineError = true;
                         }
+
                         if (!lineError) {
-
-                            tmpAction->set(tPtr);
-                            tmpEventPtrArray.back()->addAction(tmpAction);
+                            //we only give provide it the function number, instead
+                            //of a pointer to the event.  That way, if the user modifies
+                            //the function (which would change the pointer), all callbacks
+                            //still using that function number will use the new function.
+                            tPtr->set(funcNum);
+                            action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);
+                            if (tmpAction == NULL) {
+                                textDisplay << "Error: no memory slots available.\r\n";
+                                lineError = true;
+                            }
+                            if (!lineError) {
+
+                                tmpAction->set(tPtr);
+                                tmpEventPtrArray.back()->addAction(tmpAction);
+                            }
                         }
+
+
                     }
 
-
                 }
 
 
-
-
                 //int is used to decalar new variables.  Only allowed outside of callbacks-------------------
                 //example: int a;  int b = 9
             } else if (tokens[i].compare("int") == 0) { //define a new integer variable
@@ -2812,7 +2824,6 @@
                     //int pos1 = tmpLine.find("trigger(")+8;
                     //int pos2 = tmpLine.find_first_of(")",pos1);
                     int tempPort = atoi(tokens[i+2].data());
-                    
                     if (tempPort > 0) {
                         specifiedPort = tempPort-1;
                     } else {
@@ -2919,72 +2930,24 @@
                 if (!lineError) {
                     //i++;
                     //clear variables
+
                     if (clearMode == 1) {
-                        while (!globalVariables.empty()) {
-                            delete globalVariables.back();
-                            globalVariables.pop_back();
-                        }
-                        broadCastStateChanges = true;
-                        for (int i=0;i<NUMPORTS;i++) {
-                            system->setPortUpdatesOn(i);
-                        }
-                    }
-
-                    //clear callbacks, functions, and queue
-                    if (clearMode < 3) {
-                        for (int pNum = 0; pNum < NUMPORTS; pNum++) {
-                            //delete portVector[pNum]->triggerUpEventPtr;
-                            if (portVector[pNum].triggerUpEventPtr != NULL) {
-                                portVector[pNum].triggerUpEventPtr->release();
-                            }
-                            portVector[pNum].triggerUpEventPtr = NULL;
-
-                            //delete portVector[pNum]->triggerDownEventPtr;
-                            if (portVector[pNum].triggerDownEventPtr != NULL) {
-                                portVector[pNum].triggerDownEventPtr->release();
-                            }
-                            portVector[pNum].triggerDownEventPtr = NULL;
-
-
-                            /*
-                             while (!functionArray.empty()) {
-                             delete functionArray.back();
-                             functionArray.pop_back();
-                             } */
-                        }
-                        for (int i = 0; i < NUMFUNCTIONS; i++) {
-                            functionSpotTaken[i] = false;
-                            functionEventArray[i] = NULL;
-                        }
-                        for (int i = 0; i < NUMEVENTS; i++) {
-                            eventBlock[i].release();
-                        }
-                        for (int i = 0; i < NUMCONDITIONS; i++) {
-                            conditionBlock[i].release();
-                        }
-                        for (int i = 0; i < NUMINTCOMPARE; i++) {
-                            intCompareBlock[i].release();
-                        }
-                        for (int i = 0; i < NUMACTIONS; i++) {
-                            actionBlock[i].release();
-                        }
-                        for (int i = 0; i < NUMPORTMESSAGES; i++) {
-                            portMessageBlock[i].release();
-                        }
-                        for (int i = 0; i < NUMINTOPERATIONS; i++) {
-                            intOperationBlock[i].release();
-                        }
-                        for (int i = 0; i < NUMDISPLAYACTIONS; i++) {
-                            displayActionBlock[i].release();
-                        }
-                        for (int i = 0; i <NUMTRIGGERACTIONS; i++) {
-                            triggerFunctionActionBlock[i].release();
-                        }
-
-                        queuePtr->eraseQueue();
-                    }
-
-                    if (clearMode == 4) {
+                        //Clears everything
+                        int sendClearMode = 0;
+                        sendClearMode |= BLOCKMEMORYTYPES;
+                        sendClearMode |= VARIABLEMEMORYTYPES;
+                        sendClearMode |= ENVSETTINGSMEMORYTYPES;
+
+                        clearEnvironmentVariables(sendClearMode);
+
+                    } else if  (clearMode == 2) {
+                        //Clear just varaibles
+                        int sendClearMode = 0;
+                        sendClearMode |= VARIABLEMEMORYTYPES;
+                        clearEnvironmentVariables(sendClearMode);
+
+                    } else if (clearMode == 3) {
+                        //Clear the current event queue (can itself be a queued action)
                         if (blockDepth > 0) { //we are inside a block
                             action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);
                             if (tmpAction == NULL) {
@@ -3612,6 +3575,7 @@
             }
 
             if (lineError) {
+                 textDisplay.flush();
                  break; //stop parsing the rest of the line if an error was detected
             }
             if (wholeLineEvaluated) { //some of the tokens forces the whole line to be avaluated at once
@@ -3624,20 +3588,43 @@
         if (lineError) {
 
             textDisplay << "Line text: ";
+            /*
             while (!tokens.empty()) {
                 textDisplay << tokens.front()<< " ";
-                tokens.erase(tokens.begin());
+                //tokens.erase(tokens.begin());
+            }*/
+
+            //Display the line with the syntax error
+            for (int tokInd = 0; tokInd < tokens.size(); tokInd++) {
+                textDisplay << tokens.at(tokInd) << " ";
             }
             textDisplay << "\r\n";
+            textDisplay.flush();
 
             currentBlock.resetBuffer();
+
+            //Clear the line tokens
             while (!tokens.empty()) {
                 tokens.pop_back();
             }
+
+            if (tmpEventPtrArray.size() > 0) {
+                tmpEventPtrArray.at(0)->release(); //release the unfinished block (and all children)
+            }
+            while (tmpEventPtrArray.size() > 0){
+                tmpEventPtrArray.pop_back();
+            }
+
+
             //delete tmpEvent;
-            tmpEvent->release();
+            /*
+            if (tmpEvent != NULL) {
+                tmpEvent->release();
+            }
+            */
         } else {
 
+            //Clear the line tokens
             while (!tokens.empty()) {
                 tokens.pop_back();
             }
@@ -5489,3 +5476,73 @@
 
 }
 
+void scriptStream::clearEnvironmentVariables(int clearMode) {
+    //Modes:
+
+    //clear callbacks, functions, and queue
+    if (clearMode & BLOCKMEMORYTYPES) {
+        for (int pNum = 0; pNum < NUMPORTS; pNum++) {
+            //delete portVector[pNum]->triggerUpEventPtr;
+            if (portVector[pNum].triggerUpEventPtr != NULL) {
+                portVector[pNum].triggerUpEventPtr->release();
+            }
+            portVector[pNum].triggerUpEventPtr = NULL;
+
+            //delete portVector[pNum]->triggerDownEventPtr;
+            if (portVector[pNum].triggerDownEventPtr != NULL) {
+                portVector[pNum].triggerDownEventPtr->release();
+            }
+            portVector[pNum].triggerDownEventPtr = NULL;
+
+        }
+        for (int i = 0; i < NUMFUNCTIONS; i++) {
+            functionSpotTaken[i] = false;
+            functionEventArray[i] = NULL;
+        }
+        for (int i = 0; i < NUMEVENTS; i++) {
+            eventBlock[i].release();
+        }
+        for (int i = 0; i < NUMCONDITIONS; i++) {
+            conditionBlock[i].release();
+        }
+        for (int i = 0; i < NUMINTCOMPARE; i++) {
+            intCompareBlock[i].release();
+        }
+        for (int i = 0; i < NUMACTIONS; i++) {
+            actionBlock[i].release();
+        }
+        for (int i = 0; i < NUMPORTMESSAGES; i++) {
+            portMessageBlock[i].release();
+        }
+        for (int i = 0; i < NUMINTOPERATIONS; i++) {
+            intOperationBlock[i].release();
+        }
+        for (int i = 0; i < NUMDISPLAYACTIONS; i++) {
+            displayActionBlock[i].release();
+        }
+        for (int i = 0; i <NUMTRIGGERACTIONS; i++) {
+            triggerFunctionActionBlock[i].release();
+        }
+
+        queuePtr->eraseQueue();
+    }
+
+    if (clearMode & VARIABLEMEMORYTYPES) {
+        while (!globalVariables.empty()) {
+            delete globalVariables.back();
+            globalVariables.pop_back();
+        }
+    }
+
+    if (clearMode & ENVSETTINGSMEMORYTYPES) {
+        //set all environment settings to default values
+        broadCastStateChanges = true;
+        for (int i=0;i<NUMPORTS;i++) {
+            system->setPortUpdatesOn(i);
+        }
+    }
+
+
+
+}
+