A scripting environment used to define precise output/input temporal relationships.
Dependencies: SMARTWAV mbed HelloWorld
Dependents: perturbRoom_legacy
Fork of HelloWorld by
Diff: behave.cpp
- Revision:
- 4:34aca2142df9
- Parent:
- 3:ae33b7f5a7c1
diff -r ae33b7f5a7c1 -r 34aca2142df9 behave.cpp --- a/behave.cpp Sat Jul 19 03:03:36 2014 +0000 +++ b/behave.cpp Thu Sep 25 23:42:30 2014 +0000 @@ -2,6 +2,8 @@ #include <ctype.h> #include <sstream> +int16_t randomSeedCounter; //used for seeding random numbers + // These external symbols are maintained by the linker to indicate the // location of various regions in the device's memory. They will be used by // DisplayRAMBanks() to dump the size of each RAM bank to stdout. @@ -910,7 +912,8 @@ return *intVal; } else if (cmpVal != NULL){ - srand(*globalTimeKeeperPtr); + srand(*globalTimeKeeperPtr+randomSeedCounter); + randomSeedCounter++; //for seeding the next rand call, just in case it happens before the clock advances *cmpVal = (rand() % (randHigh+1)); //this is how we assign a random number to variable return *cmpVal; @@ -1678,6 +1681,71 @@ delete actionPtr; } + blockBuffer::blockBuffer() { + bufferWritePos = 0; + bufferWritePos = 0; + _linesAvailable = 0; + + } + + bool blockBuffer::addLine(char *input, int numChars) { + + if (bufferWritePos+numChars >= INPUTCHARBUFFERSIZE) { + return false; + } + for(int i=0;i<numChars;i++) { + charBuffer[bufferWritePos] = input[i]; + bufferWritePos++; + } + _linesAvailable++; + return true; + } + + string blockBuffer::getNextLine() { + + string outputLine; + int endOfLinePos = bufferReadPos; + bool endOfLineFound = false; + if (_linesAvailable > 0) { + //Find the end of the next line + while (endOfLinePos < INPUTCHARBUFFERSIZE) { + if (charBuffer[endOfLinePos] == '\0') { + endOfLineFound = true; + break; + } + endOfLinePos++; + } + + //If the end was found, copy to output string + if (endOfLineFound) { + outputLine.append(charBuffer+bufferReadPos,endOfLinePos-bufferReadPos); + bufferReadPos = endOfLinePos+1; + _linesAvailable--; + } + } + if (_linesAvailable == 0) { + //we have read out all of the lines, so reset the buffer for the next block. + resetBuffer(); + } + return outputLine; + + } + + int16_t blockBuffer::linesAvailable() { + return _linesAvailable; + } + + void blockBuffer::resetBuffer() { + _linesAvailable = 0; + bufferReadPos = 0; + bufferWritePos = 0; + } + + bool blockBuffer::empty() { + return (_linesAvailable == 0); + } + + scriptStream::scriptStream(Serial* serialInput, digitalPort** portVectorInput, int numPortsInput, eventQueue* queueInput): portVector(portVectorInput), numPorts(numPortsInput), @@ -1688,21 +1756,30 @@ currentTriggerPort = -1; currentTriggerDir = 1; currentFunction = -1; + + randomSeedCounter = 0; //used for seeding random numbers lineError = false; blockDepth = 0; ifBlockInit = false; whileBlockInit = false; elseFlag = false; + thenFlag = false; currentDelay = 0; + } + void scriptStream::addLineToCurrentBlock(char* lineInput) { bool compile = false; bool keep = false; - for (int i = 0; i < 128; i++) { + int numCharInLine = 0; + //A line ending with ';' then carriage return initiates the compile sequence + //Otherwise, add the line to the buffer and compile later + for (int i = 0; i < 256; i++) { + numCharInLine++; if (lineInput[i] == ';') { compile = true; } else if (lineInput[i] == ' ') { @@ -1710,12 +1787,22 @@ } else if (lineInput[i] == '\0') { break; } else { - keep = true; + keep = true; compile = false; } + } - if (keep) currentBlock.insert(currentBlock.begin(),string(lineInput)); - if (compile) parseBlock(); + //if (keep) currentBlock.insert(currentBlock.begin(),string(lineInput)); + if (keep) { + if (!currentBlock.addLine(lineInput,numCharInLine)) { + pcPtr->printf("Error: script input buffer full. The block is too long.\r\n"); + currentBlock.resetBuffer(); + compile = false; + } + } + if (compile) { + parseBlock(); + } } @@ -1724,6 +1811,7 @@ //------------------------------------------------------- void scriptStream::parseBlock() { + lineError = false; blockDepth = 0; ifBlockInit = false; @@ -1732,14 +1820,19 @@ thenFlag = false; currentDelay = 0; + std::size_t stringInd = 0; bool wholeLineEvaluated = false; //pcPtr->printf("\r\n"); while (!currentBlock.empty()) { + + wholeLineEvaluated = false; - tmpLine = currentBlock.back(); + //tmpLine = currentBlock.back(); + tmpLine = currentBlock.getNextLine(); + lineError = false; //remove tabs std::size_t found = tmpLine.find_first_of(9); //tab @@ -1795,6 +1888,7 @@ tmpEventPtrArray.pop_back(); //recursively remove the pointers to all else blocks } tmpEventPtrArray.pop_back(); //remove the pointer to the finished block + } else { pcPtr->printf("Error: End statement without block\r\n"); lineError = true; @@ -2908,8 +3002,13 @@ tokens.erase(tokens.begin()); } pcPtr->printf("\r\n"); + /* while (!currentBlock.empty()) { currentBlock.pop_back(); + }*/ + currentBlock.resetBuffer(); + while (!tokens.empty()) { + tokens.pop_back(); } delete tmpEvent; } else { @@ -2917,18 +3016,25 @@ while (!tokens.empty()) { tokens.pop_back(); } - currentBlock.pop_back(); + //currentBlock.pop_back(); + } } //make sure that all blocks have a matching end statement + + if ((!lineError)&&(blockDepth > 0)) { pcPtr->printf("Error: Missing 1 or more end statements\r\n"); lineError = true; - } - //pcPtr->printf("~~~\r\n"); //signals that the code was compiled - textDisplay.send("~~~\r\n"); + currentBlock.resetBuffer(); + } + + if ((!lineError)&&(blockDepth == 0)) { + textDisplay.send("~~~\r\n"); + } + //displayMemoryLeft(); //DisplayRAMBanks(); @@ -3133,7 +3239,7 @@ tmpOp->set(tmpVar, multiplier.data(), atoi(afterEqual.substr(stringInd2+1,std::string::npos).data())); } tmpAction->set(tmpOp); - pcPtr->printf("Action: change variable by constant amount\r\n"); + //pcPtr->printf("Action: change variable by constant amount\r\n"); } else { tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);