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

Dependencies:   SMARTWAV mbed HelloWorld

Dependents:   perturbRoom_legacy

Fork of HelloWorld by Simon Ford

Revision:
4:34aca2142df9
Parent:
3:ae33b7f5a7c1
--- 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);