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
Diff: behave.cpp
- 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); + } + } + + + +} +