A scripting environment used to define precise output/input temporal relationships.

Dependencies:   SMARTWAV mbed HelloWorld

Dependents:   perturbRoom_legacy

Fork of HelloWorld by Simon Ford

Files at this revision

API Documentation at this revision

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

behave.cpp Show annotated file Show diff for this revision Revisions of this file
behave.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
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");