A scripting environment used to define precise output/input temporal relationships.
Dependencies: SMARTWAV mbed HelloWorld
Dependents: perturbRoom_legacy
Fork of HelloWorld by
Revision 4:34aca2142df9, committed 2014-09-25
- Comitter:
- mkarlsso
- Date:
- Thu Sep 25 23:42:30 2014 +0000
- Parent:
- 3:ae33b7f5a7c1
- Commit message:
- Longer script loading without hanging due to memory limitations
Changed in this revision
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);
diff -r ae33b7f5a7c1 -r 34aca2142df9 behave.h --- a/behave.h Sat Jul 19 03:03:36 2014 +0000 +++ b/behave.h Thu Sep 25 23:42:30 2014 +0000 @@ -23,6 +23,7 @@ #define NUMPORTS 8 +#define INPUTCHARBUFFERSIZE 3072 class event; //we foreward declare this because of class interdependencies @@ -385,6 +386,25 @@ action* actionPtr; }; +class blockBuffer { + +public: + blockBuffer(); + bool addLine(char* input, int numChars); + string getNextLine(); + int16_t linesAvailable(); + bool empty(); + void resetBuffer(); + +private: + //__attribute((section("AHBSRAM1"),aligned)) char charBuffer[INPUTCHARBUFFERSIZE]; + char charBuffer[INPUTCHARBUFFERSIZE]; + 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 { @@ -403,13 +423,15 @@ int getRandomParam(string expression); + + private: int currentTriggerPort; int currentTriggerDir; int currentPort; int currentFunction; - + string tmpLine; vector<string> tokens; @@ -426,7 +448,8 @@ vector<intVariable*> globalVariables; vector<event*> tmpEventPtrArray; vector<functionItem*> functionArray; //any blocks declared outsite callback blocks are stored here - list<string> currentBlock; + //list<string> currentBlock; + blockBuffer currentBlock; digitalPort** portVector;
diff -r ae33b7f5a7c1 -r 34aca2142df9 main.cpp --- a/main.cpp Sat Jul 19 03:03:36 2014 +0000 +++ b/main.cpp Thu Sep 25 23:42:30 2014 +0000 @@ -14,7 +14,7 @@ //static char buf1[0x2000] __attribute__((section("AHBSRAM0"))); __attribute((section("AHBSRAM0"),aligned)) outputStream textDisplay(512); -__attribute((section("AHBSRAM0"),aligned)) char buffer[128]; +__attribute((section("AHBSRAM0"),aligned)) char buffer[256]; __attribute((section("AHBSRAM1"),aligned)) event eventBlock[NUMEVENTS]; @@ -61,6 +61,9 @@ DigitalOut clockOutSignal(p7); InterruptIn clockExternalIncrement(p8); +//Camera trigger signal +//DigitalOut camera30Hz(p27); + //Pins for digital ports. Each port has 1 out and 1 in //DigitalOut out1(LED1); //route to LED for debugging @@ -197,6 +200,7 @@ currentBroadcastBit = 0; } + //Every second, we broadcast out the current time if ((timeKeeper % 1000) == 0) { currentBroadcastTime = timeKeeper; @@ -336,7 +340,7 @@ //Set up input buffer for the serial port //char buffer[128]; int bufferPos = 0; - eraseBuffer(buffer,128); + eraseBuffer(buffer,256); ostringstream timeConvert; // stream used for the conversion ostringstream stateConvert; @@ -359,14 +363,14 @@ if ((tmpChar == 13) || (tmpChar == 10)) { //carrriage return parser.addLineToCurrentBlock(buffer); bufferPos = 0; - eraseBuffer(buffer,128); + eraseBuffer(buffer,256); } //pc.putc(tmpChar); } while (tmpChar != EOF); buffer[bufferPos] = 59; parser.addLineToCurrentBlock(buffer); - eraseBuffer(buffer,128); + eraseBuffer(buffer,256); fclose(fp); } else { pc.printf("No startup script found.\r\n");