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:
- 1:3a050d26d4f6
- Parent:
- 0:8dbd6bd9167f
diff -r 8dbd6bd9167f -r 3a050d26d4f6 behave.cpp --- a/behave.cpp Tue May 19 15:45:42 2015 +0000 +++ b/behave.cpp Wed Jun 03 22:54:25 2015 +0000 @@ -41,10 +41,13 @@ __attribute((section("AHBSRAM1"),aligned)) intCompare intCompareBlock[NUMINTCOMPARE]; __attribute((section("AHBSRAM0"),aligned)) action actionBlock[NUMACTIONS]; __attribute((section("AHBSRAM0"),aligned)) portMessage portMessageBlock[NUMPORTMESSAGES]; -//__attribute((section("AHBSRAM1"),aligned)) intVariable intVariableBlock[10]; +__attribute((section("AHBSRAM1"),aligned)) intVariable globalVarBlock[NUMINTVARS]; __attribute((section("AHBSRAM0"),aligned)) intOperation intOperationBlock[NUMINTOPERATIONS]; __attribute((section("AHBSRAM0"),aligned)) displayAction displayActionBlock[NUMDISPLAYACTIONS]; __attribute((section("AHBSRAM0"),aligned)) triggerFunctionAction triggerFunctionActionBlock[NUMTRIGGERACTIONS]; +__attribute((section("AHBSRAM1"),aligned)) char charBuffer[INPUTCHARBUFFERSIZE]; + + #endif #ifdef FPGAHARDWARE @@ -55,9 +58,11 @@ intCompare intCompareBlock[NUMINTCOMPARE]; action actionBlock[NUMACTIONS]; portMessage portMessageBlock[NUMPORTMESSAGES]; +intVariable globalVarBlock[NUMINTVARS]; intOperation intOperationBlock[NUMINTOPERATIONS]; displayAction displayActionBlock[NUMDISPLAYACTIONS]; triggerFunctionAction triggerFunctionActionBlock[NUMTRIGGERACTIONS]; +char charBuffer[INPUTCHARBUFFERSIZE]; #endif @@ -117,6 +122,8 @@ } void mainLoop::exec() { + //Start the main loop. + bool digitalInChanged = false; bool digitalOutChanged = false; uint32_t changeTime; @@ -124,8 +131,8 @@ int bufferPos = 0; - ostringstream timeConvert; // stream used for the conversion - ostringstream stateConvert; + //ostringstream timeConvert; // stream used for the conversion + //ostringstream stateConvert; int tmpChar; int junkChar; @@ -218,8 +225,9 @@ digitalInChanged = false; digitalOutChanged = false; changeTime = timeKeeper; + //hardware->pauseInterrupts(); for (int i = 0; i < NUMPORTS; i++) { - + //hardware->pauseInterrupts(); if (ports[i].update()) { digitalInChanged = true; @@ -233,6 +241,7 @@ currentDIOstate[0] &= ~(1 << i); } } + //hardware->resumeInterrupts(); if (ports[i].outStateChanged) { digitalOutChanged = true; changeTime = min(changeTime,ports[i].lastOutChangeTime); @@ -425,28 +434,18 @@ outState = outVal; } -//called when a digital in gets triggered -/* -void digitalPort::addStateChange(int newState, uint32_t timeStamp) { - - if ((newState == 0) && (!lastDownEvent.triggered)){ - lastDownEvent.timeStamp = timeStamp; - lastDownEvent.triggered = true; - } else if ((newState == 1) && (!lastUpEvent.triggered)) { - lastUpEvent.timeStamp = timeStamp; - lastUpEvent.triggered = true; - } -}*/ - bool digitalPort::update() { bool changed = false; + bool execUp = false; + bool execDown = false; if ((timeKeeper - lastChangeTime) > 1) { //prevents flutter triggers when button is pressed //changed = (lastInState != inState); - changed = (inPin->lastUpEvent.triggered || inPin->lastDownEvent.triggered); + changed = (inPin->lastUpEvent.triggered || inPin->lastDownEvent.triggered); //Either a down or up event happened if (changed) { + inPin->setUpdate(true); //Once we get the state of the pin, we buffer any pin changes until we are done checking inState = getDigitalIn(); //We need to ignore flutter when levers/beam breaks are triggered. So @@ -470,7 +469,7 @@ lastChangeTime = timeKeeper; } */ - if (triggerUpEventPtr != NULL) {triggerUpEventPtr->execute();} + if (triggerUpEventPtr != NULL) {execUp = true;} } else if (inState == 0) { lastChangeInterval = inPin->lastDownEvent.timeStamp - lastChangeTime; @@ -485,11 +484,11 @@ lastChangeTime = timeKeeper; }*/ - if (triggerDownEventPtr != NULL) {triggerDownEventPtr->execute();} + if (triggerDownEventPtr != NULL) {execDown = true;} } } else if (lastInState == inState) { - //Both up and down triggers must have happened, so we consider both + //Both up and down triggers must have happened, so we consider both (and execute in the right order) if (inState == 1) { lastChangeInterval = inPin->lastUpEvent.timeStamp - inPin->lastDownEvent.timeStamp; @@ -507,12 +506,20 @@ } } + lastInState = inState; + inPin->lastUpEvent.triggered = false; + inPin->lastDownEvent.triggered = false; + + inPin->setUpdate(false); //This also checks if there were any buffered changes that occured + } - - lastInState = inState; - inPin->lastUpEvent.triggered = false; - inPin->lastDownEvent.triggered = false; - + } + if (execUp) { + triggerUpEventPtr->execute(); + } + + if (execDown) { + triggerDownEventPtr->execute(); } return changed; @@ -538,13 +545,17 @@ isUsed = true; } -void intVariable::set(std::string& tagInput, int initialValue) { +void intVariable::set(const char* tagInput, int initialValue) { value = initialValue; //tag = string(tagInput); - strncpy(tag,tagInput.data(),MAXVARNAMESIZE); + strncpy(tag,tagInput,MAXVARNAMESIZE); isUsed = true; } +void intVariable::release() { + isUsed = false; +} + displayAction::displayAction(): dText(string("--------------------------------------------------")){ dVariable = NULL; @@ -2060,10 +2071,31 @@ bufferReadPos = 0; _linesAvailable = 0; + writeLine = 0; + readLine = 0; + for (int i=0; i < 200; i++) { + lines[i] = NULL; + } + } bool blockBuffer::addLine(char *input, int numChars) { + if (writeLine < 200) { + lines[writeLine] = (char*) malloc (numChars+1); + if (lines[writeLine] == NULL) { + textDisplay << "Could noy allocate memory for line."; + textDisplay.flush(); + return false; + } + strcpy(lines[writeLine],input); + writeLine++; + _linesAvailable++; + } else { + return false; + } + + /* if (bufferWritePos+numChars >= INPUTCHARBUFFERSIZE) { return false; } @@ -2073,11 +2105,28 @@ } _linesAvailable++; return true; + */ } +char* blockBuffer::getNextLine() { + + if (readLine < writeLine) { + + readLine++; + _linesAvailable--; + + return lines[readLine-1]; + } else { + return NULL; + } + +} + +/* string blockBuffer::getNextLine() { string outputLine; + int endOfLinePos = bufferReadPos; bool endOfLineFound = false; @@ -2110,7 +2159,9 @@ } return outputLine; + } +*/ int16_t blockBuffer::linesAvailable() { return _linesAvailable; @@ -2120,6 +2171,14 @@ _linesAvailable = 0; bufferReadPos = 0; bufferWritePos = 0; + + writeLine = 0; + readLine = 0; + for (int i=0; i< 200; i++) { + //delete [] lines[i]; + free (lines[i]); + lines[i] = NULL; + } } bool blockBuffer::empty() { @@ -2154,7 +2213,6 @@ functionEventArray[i] = NULL; } - } @@ -2190,6 +2248,7 @@ } if (compile) { parseBlock(); + currentBlock.resetBuffer(); } } @@ -2217,8 +2276,11 @@ while (!currentBlock.empty()) { wholeLineEvaluated = false; - //tmpLine = currentBlock.back(); - tmpLine = currentBlock.getNextLine(); + + //tmpLine = currentBlock.getNextLine(); + + tmpLine.assign(currentBlock.getNextLine()); + lineError = false; //remove tabs @@ -2296,8 +2358,9 @@ int pos1 = tmpLine.find("sound(")+6; int pos2 = tmpLine.find_first_of(")",pos1); string dispVar = tmpLine.substr(pos1,pos2-pos1); - - int* tmpVar = findIntVariable(dispVar); + //int* tmpVar = findIntVariable(dispVar); + int* tmpVar = findIntVariable(tmpLine.data(),pos1,pos2-1); + bool isText = false; bool stopSignal = false; bool resetSignal = false; @@ -2391,8 +2454,8 @@ int pos1 = tmpLine.find("volume(")+7; int pos2 = tmpLine.find_first_of(")",pos1); string dispVar = tmpLine.substr(pos1,pos2-pos1); - - int* tmpVar = findIntVariable(dispVar); + //int* tmpVar = findIntVariable(dispVar); + int* tmpVar = findIntVariable(tmpLine.data(),pos1,pos2-1); bool isText = false; if (tmpVar == NULL) { if (isNumber(dispVar)) { @@ -2518,11 +2581,11 @@ textDisplay <<"Error: expected a ) character\r\n"; lineError = true; } - + if (!lineError) { string dispVar = tmpLine.substr(pos1,pos2-pos1); - - int* tmpVar = findIntVariable(dispVar); + //int* tmpVar = findIntVariable(dispVar); + int* tmpVar = findIntVariable(tmpLine.data(),pos1,pos2-1); bool isText = false; if (tmpVar == NULL) { if ((tmpLine.compare(pos1,1,"'")==0) && (tmpLine.compare(pos2-1,1,"'")==0)) { @@ -2537,10 +2600,10 @@ textDisplay << "Error: no memory slots available.\r\n"; lineError = true; } - + if (!lineError && (blockDepth == 0)) { //we are not inside a block structure, so display now - + if (isText) { //displayAction* dPtr = new displayAction(tmpLine.substr(pos1+1,pos2-pos1-2), pcPtr); dPtr->set(tmpLine.substr(pos1+1,pos2-pos1-2)); @@ -2554,7 +2617,7 @@ //delete dPtr; dPtr->release(); } - + } else if (!lineError && (blockDepth > 0) ){ //the disp function was put inside a block textDisplay.debug("Display statement\r\n"); @@ -2576,8 +2639,8 @@ //action* tmpAction = new action(dPtr); tmpEventPtrArray.back()->addAction(tmpAction); } - - + + } } //---------------------------------------------- @@ -2697,7 +2760,9 @@ variableCreated = true; } else { textDisplay.debug("Attempting to use existing variable\r\n"); - int* tmpVar = findIntVariable(tmpString.substr(0,stringInd)); + //int* tmpVar = findIntVariable(tmpString.substr(0,stringInd)); + int* tmpVar = findIntVariable(tmpString.data(),0,stringInd-1); + *tmpVar = 0; //lineError = true; } @@ -2706,6 +2771,7 @@ lineError = true; } } + if ((!lineError) && (stringInd != std::string::npos)) { //evaluate the expression //action* tmpAction = evaluateAssignmentForAction(tmpString); action* tmpAction = evaluateAssignmentForAction(tmpString.data()); @@ -3035,9 +3101,9 @@ } - } else if ((!lineError) && (tokens[i+1].compare("in") == 0) && (findIntVariable(tokens[i+2])!=NULL)) { + } else if ((!lineError) && (tokens[i+1].compare("in") == 0) && (findIntVariable(tokens[i+2].data())!=NULL)) { textDisplay.debug("Do in VAR statement\r\n"); - int* delayVar = findIntVariable(tokens[i+2]); + int* delayVar = findIntVariable(tokens[i+2].data()); //currentDelay = atoi(tokens[i+2].data()); if (!ifBlockInit) { //a standalone do block //tmpEvent = new event(queuePtr); @@ -3459,9 +3525,9 @@ textDisplay << "Error: loop period must be a positive integer.\r\n"; lineError = true; } - } else if (findIntVariable(tokens[i+3])!=NULL) { - - int* period = findIntVariable(tokens[i+3]); + } else if (findIntVariable(tokens[i+3].data())!=NULL) { + + int* period = findIntVariable(tokens[i+3].data()); //tmpEvent->whileLoopPeriodVar = period; tmpEvent->setWhileLoopPeriod(period); if (!elseFlag) { @@ -3608,7 +3674,7 @@ } - +/* //used to return a pointer to a variable, if it exists int* scriptStream::findIntVariable(string nameInput) { @@ -3648,19 +3714,20 @@ outPtr = &globalVariables[i]->value; break; } - /* - if (nameInput.compare(globalVariables[i]->tag) == 0) { - outPtr = &globalVariables[i]->value; - break; - }*/ + } } textDisplay.debug("...done\r\n"); return outPtr; } - - +*/ + +int* scriptStream::findIntVariable(const char *nameInput) { + return findIntVariable(nameInput,0,strlen(nameInput)-1); +} + +/* //used to return a pointer to a variable, if it exists int* scriptStream::findIntVariable(const char* nameInput, int start, int end) { @@ -3710,11 +3777,71 @@ textDisplay.debug("done\r\n"); return outPtr; +}*/ + +//used to return a pointer to a variable, if it exists +int* scriptStream::findIntVariable(const char* nameInput, int start, int end) { + + textDisplay.debug("Finding variable..."); + int* outPtr = NULL; + bool foundIt = false; + + if (findStringLoc(nameInput,"portout[",start,end) != -1) { + int pos1 = findStringLoc(nameInput,"portout[",start,end)+8; + int pos2 = findStringLoc(nameInput, "]",pos1,end); + if ((pos1 == -1)||(pos2 == -1)) { + //syntax error + return NULL; + } + + //int portnum = atoi(nameInput.substr(pos1,pos2-pos1).data()); + long int portnum = strtol(nameInput+pos1,NULL,10); + if ((portnum > 0) && (portnum <= numPorts)) { + outPtr = &portVector[(int)portnum-1].outState; + foundIt = true; + } + } else if (findStringLoc(nameInput,"portin[",start,end) != -1) { + int pos1 = findStringLoc(nameInput,"portin[",start,end)+7; + int pos2 = findStringLoc(nameInput, "]",pos1,end); + if ((pos1 == -1)||(pos2 == -1)) { + //syntax error + return NULL; + } + long int portnum = strtol(nameInput+pos1,NULL,10); + + if ((portnum > 0) && (portnum <= numPorts)) { + outPtr = &portVector[(int)portnum-1].inState; + foundIt = true; + } + } + + if (!foundIt) { + //std::vector<intVariable*>::size_type sz = globalVariables.size(); + for (unsigned i = 0; i < NUMINTVARS; i++) { + //const char* varName = globalVariables[i]->tag.data(); + if ((findStringLoc(nameInput,globalVarBlock[i].tag,start,end) != -1) && (strlen(globalVarBlock[i].tag)==(end-start+1))) { + outPtr = &globalVarBlock[i].value; + textDisplay.debug("Variable already exists.\r\n"); + break; + } + } + } + //textDisplay.debug("done\r\n"); + + return outPtr; } -bool scriptStream::createIntVariable(string nameInput) { - if (findIntVariable(nameInput) == NULL) { - globalVariables.push_back(new intVariable(nameInput, 0)); + +bool scriptStream::createIntVariable(const string& nameInput) { + if (findIntVariable(nameInput.data()) == NULL) { + //globalVariables.push_back(new intVariable(nameInput, 0)); + intVariable* tmpVar = findFirstUnUsed(globalVarBlock, NUMINTVARS); + if (tmpVar == NULL) { + textDisplay << "Error: no memory slots available.\r\n"; + return false; + } + tmpVar->set(nameInput.data(),0); + return true; } else { return false; @@ -3758,8 +3885,9 @@ multiplierInt = -1; } - + tmpVar = findIntVariable(expression,0,beforeEqualLoc); //returns pointer to the variable + if (findStringLoc(expression,"portout[",0,beforeEqualLoc) != -1) { //set the output of a digital port textDisplay.debug("Portout assignment\r\n"); int pos1 = findStringLoc(expression,"portout[",0,beforeEqualLoc)+8; @@ -4286,6 +4414,7 @@ return tmpAction; } +/* action* scriptStream::evaluateAssignmentForAction(string expression) { //action* tmpAction = new action(); //create a new action @@ -4820,7 +4949,7 @@ } textDisplay.debug("Assignment successful\r\n"); return tmpAction; -} +}*/ /* bool scriptStream::isOutsideParenth(string& expression,std::size_t foundItem) {