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:
2:298679fff37c
Child:
3:ae33b7f5a7c1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/behave.cpp	Tue Jul 08 21:51:16 2014 +0000
@@ -0,0 +1,3643 @@
+#include "behave.h"
+#include <ctype.h>
+#include <sstream> 
+
+// 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.
+extern unsigned int Image$$RW_IRAM1$$Base;
+extern unsigned int Image$$RW_IRAM1$$ZI$$Limit;
+extern unsigned int Image$$RW_IRAM2$$Base;
+extern unsigned int Image$$RW_IRAM2$$ZI$$Limit;
+extern unsigned int Image$$RW_IRAM3$$Base;
+extern unsigned int Image$$RW_IRAM3$$ZI$$Limit;
+
+uint32_t* globalTimeKeeperPtr; //this is a pointer to the slave timer (do not change this directly)
+extern eventQueue mainQueue;
+extern digitalPort* portVector[];
+
+extern Serial pc;
+extern bool resetTimer;
+extern bool clockSlave;
+extern bool changeToSlave;
+extern bool changeToStandAlone;
+extern outputStream textDisplay;
+extern int currentDIOstate[2];
+extern bool broadCastStateChanges;
+extern bool textStreaming;
+
+
+//static pools of memory for each object type
+extern event eventBlock[NUMEVENTS];
+extern condition conditionBlock[NUMCONDITIONS];
+extern intCompare intCompareBlock[NUMINTCOMPARE];
+extern action actionBlock[NUMACTIONS];
+extern portMessage portMessageBlock[NUMPORTMESSAGES];
+extern intOperation intOperationBlock[NUMINTOPERATIONS];
+extern displayAction displayActionBlock[NUMDISPLAYACTIONS];
+
+//used to find the first available object in the staticly defined pools of memory
+template<class T> T* findFirstUnUsed(T a[], const int arrayLength) {
+  
+  T* returnPtr = NULL;
+  for (int i = 0; i < arrayLength; i++) {
+    if (!a[i].isUsed) {
+        returnPtr = &a[i];
+        break;
+    }
+  }
+  return returnPtr;
+}
+        
+//used to count the number of available objects in the memory pool
+template<class T> int countUnUsed(T a[], const int arrayLength) {
+  
+  int count = 0;
+  for (int i = 0; i < arrayLength; i++) {
+    if (!a[i].isUsed) {
+        count++;
+    }
+  }
+  return count;
+}
+
+
+void displayMemoryLeft(void) {
+    pc.printf("Available slots left in memory\r\n");
+    pc.printf("  Blocks:  %d\r\n", countUnUsed(eventBlock, NUMEVENTS));
+    pc.printf("  Condition containers:  %d\r\n", countUnUsed(conditionBlock, NUMCONDITIONS));
+    pc.printf("  Int compare conditions:  %d\r\n", countUnUsed(intCompareBlock, NUMINTCOMPARE));
+    pc.printf("  Command containers:  %d\r\n", countUnUsed(actionBlock, NUMACTIONS));
+    pc.printf("  Port commands:  %d\r\n", countUnUsed(portMessageBlock, NUMPORTMESSAGES));
+    pc.printf("  Integer operater commands:  %d\r\n", countUnUsed(intOperationBlock, NUMINTOPERATIONS));
+    pc.printf("  Text display commands:  %d\r\n", countUnUsed(displayActionBlock, NUMDISPLAYACTIONS));
+}
+
+// Displays the size of static allocations for each RAM bank as indicated by
+// ARM linker to stdout.
+static void DisplayRAMBanks(void) {
+
+    pc.printf("Static RAM bank allocations\r\n");
+    pc.printf("  Main RAM = %u\r\n", (unsigned int)&Image$$RW_IRAM1$$ZI$$Limit - 
+                                  (unsigned int)&Image$$RW_IRAM1$$Base);
+    pc.printf("  RAM0     = %u\r\n", (unsigned int)&Image$$RW_IRAM2$$ZI$$Limit -
+                                  (unsigned int)&Image$$RW_IRAM2$$Base);
+    pc.printf("  RAM1     = %u\r\n", (unsigned int)&Image$$RW_IRAM3$$ZI$$Limit -
+                                  (unsigned int)&Image$$RW_IRAM3$$Base);
+}
+
+
+bool isNumber(const std::string& s) {
+    std::string::const_iterator it = s.begin();
+    while (it != s.end() && isdigit(*it)) ++it;
+    return !s.empty() && it == s.end();
+}
+
+void tokenize(const string& str,
+                      vector<string>& tokens,
+                      const string& delimiters = " ")
+{
+    // Skip delimiters at beginning.
+    string::size_type lastPos = str.find_first_not_of(delimiters, 0);
+    // Find first "non-delimiter".
+    string::size_type pos     = str.find_first_of(delimiters, lastPos);
+
+    while (string::npos != pos || string::npos != lastPos)
+    {
+        // Found a token, add it to the vector.
+        tokens.push_back(str.substr(lastPos, pos - lastPos));
+        // Skip delimiters.  Note the "not_of"
+        lastPos = str.find_first_not_of(delimiters, pos);
+        // Find next "non-delimiter"
+        pos = str.find_first_of(delimiters, lastPos);
+    }
+}
+
+
+digitalPort::digitalPort(DigitalOut* DOP, DigitalIn* DIP):
+    outPin(DOP),
+    inPin(DIP),
+    outState(0){
+    
+    lastInState = getDigitalIn();
+    inState = getDigitalIn();
+    lastChangeTime = 0;
+    lastOutChangeTime = 0;
+    lastChangeInterval = 0;
+    lastDownEvent.triggered = false;
+    lastUpEvent.triggered = false;
+    triggerUpEventPtr = NULL;
+    triggerDownEventPtr = NULL;
+    outStateChanged = false;
+}
+
+void digitalPort::setTriggerUpEvent(event* eventInput) {
+    if (triggerUpEventPtr != NULL) {
+         //delete triggerUpEventPtr;
+         triggerUpEventPtr->release();
+    }
+    triggerUpEventPtr = eventInput;
+}
+
+void digitalPort::setTriggerDownEvent(event* eventInput) {
+    if (triggerDownEventPtr != NULL) {
+         //delete triggerDownEventPtr;
+         triggerDownEventPtr->release();
+         
+    }
+    triggerDownEventPtr = eventInput;
+}
+
+
+int digitalPort::getDigitalIn() {
+    return inPin->read();
+}
+
+
+void digitalPort::setDigitalOut(int outVal) {
+    if (outVal == -1) {
+        outVal = 1-outState;
+    }
+    outPin->write(outVal);
+    if (outState != outVal) {
+        outStateChanged = true;
+        lastOutChangeTime = *globalTimeKeeperPtr;
+    }
+    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;
+  if ((*globalTimeKeeperPtr - lastChangeTime) > 1) { //prevents flutter triggers when button is pressed
+    inState = getDigitalIn();
+    changed = (lastInState != inState);   
+    if (changed) {
+        if (inState == 1) {
+            if (lastUpEvent.triggered) {
+                //there were hardware triggered since the last main loop.  We use that time
+                lastChangeInterval = lastUpEvent.timeStamp - lastChangeTime;
+                lastChangeTime = lastUpEvent.timeStamp;
+            } else {
+                //otherwise we use the current time
+                lastChangeInterval = *globalTimeKeeperPtr - lastChangeTime;
+                lastChangeTime = *globalTimeKeeperPtr;
+            }
+            if (triggerUpEventPtr != NULL) {triggerUpEventPtr->execute();}          
+        } else if (inState == 0) {
+            if (lastDownEvent.triggered) {
+                lastChangeInterval = lastDownEvent.timeStamp - lastChangeTime;
+                lastChangeTime = lastDownEvent.timeStamp;
+            } else {
+                lastChangeInterval = *globalTimeKeeperPtr - lastChangeTime;
+                lastChangeTime = *globalTimeKeeperPtr;
+            }
+            if (triggerDownEventPtr != NULL) {triggerDownEventPtr->execute();}            
+        }
+        
+    }      
+        
+    lastInState = inState;
+    
+  }
+  lastUpEvent.triggered = false;
+  lastDownEvent.triggered = false;
+  return changed;
+}
+
+int digitalPort::getLastChangeState() {
+    return lastInState;
+}
+uint32_t digitalPort::getTimeSinceLastChange() {
+    return lastChangeInterval;
+    
+}
+
+intVariable::intVariable():
+    value(0), 
+    tag(string("--------------------")) {  
+    isUsed = false;  
+}
+
+intVariable::intVariable(string tagInput, int initialValue):
+    value(initialValue), 
+    tag(string(tagInput)) {   
+    isUsed = true;   
+}
+
+void intVariable::set(string tagInput, int initialValue) {
+    value = initialValue; 
+    tag = string(tagInput);
+    isUsed = true;      
+}
+
+displayAction::displayAction():
+    dText(string("--------------------------------------------------")),
+    pcPtr(NULL) {   
+    dVariable = NULL;
+    isUsed = false;  
+}
+
+void displayAction::release() {
+    dText = "--------------------------------------------------";
+    pcPtr = NULL;  
+    dVariable = NULL;
+    isUsed = false;     
+}
+
+displayAction::displayAction(int* variable, string varNameInput, Serial* pcPtrInput):
+    dVariable(variable),
+    dText(varNameInput),
+    pcPtr(pcPtrInput) {
+    isUsed = true;  
+    
+}
+
+displayAction::displayAction(string text, Serial* pcPtrInput):
+    dText(text),
+    pcPtr(pcPtrInput) {   
+    dVariable = NULL;
+    isUsed = true;  
+}
+
+void displayAction::set(int* variable, string varNameInput, Serial* pcPtrInput) {
+    dVariable = variable;
+    dText = varNameInput;
+    pcPtr = pcPtrInput;
+    isUsed = true;  
+    
+}
+
+void displayAction::set(string text, Serial* pcPtrInput) {
+    dText = text;
+    pcPtr = pcPtrInput;   
+    dVariable = NULL;
+    isUsed = true;  
+}
+
+void displayAction::execute() {
+    
+    ostringstream convert;   // stream used for the conversion
+    convert << *globalTimeKeeperPtr;      // insert the textual representation of 'Number' in the characters in the stream
+
+    if (dVariable != NULL) {
+        ostringstream varConvert;
+        varConvert << *dVariable;
+        //pcPtr->printf("%d   %s = %d\r\n",*globalTimeKeeperPtr, dText.data(),*dVariable);
+        textDisplay.send(convert.str() + "  " + dText + " = " + varConvert.str() + "\r\n");
+    } else {
+        //pcPtr->printf("%d   %s\r\n",*globalTimeKeeperPtr, dText.data());
+        textDisplay.send(convert.str() + "  " + dText + "\r\n");
+       
+    }
+}
+
+intCompare::intCompare():
+    port(NULL) {
+    cmpVal = NULL;
+    cmpValGlobal = false;
+    intVal = NULL;
+    intOp = NULL;
+    portValPtr = NULL;
+    isUsed = false;  
+    
+}
+intCompare::intCompare(digitalPort* portInput, const char* cmpString, int cmpValInput, int whichToUse):
+    port(portInput) {
+    cmpVal = new int(cmpValInput);
+    cmpValGlobal = false;
+    intVal = NULL;
+    intOp = NULL;
+    setPointer(cmpString); 
+    isUsed = true;  
+    if (whichToUse == 1) {
+        portValPtr = &port->inState;
+    } else {
+        portValPtr = &port->outState;
+    } 
+}
+
+intCompare::intCompare(digitalPort* portInput, const char* cmpString, int* cmpIntVarInput, int whichToUse):
+    port(portInput),
+    cmpVal(cmpIntVarInput) {
+    cmpValGlobal = true;
+    intVal = NULL;
+    intOp = NULL;
+    setPointer(cmpString);
+    isUsed = true;  
+    if (whichToUse == 1) {
+        portValPtr = &port->inState;
+    } else {
+        portValPtr = &port->outState;
+    }
+}
+
+intCompare::intCompare(int* intVarInput, const char* cmpString, int* cmpIntVarInput):
+    cmpVal(cmpIntVarInput),
+    intVal(intVarInput) {
+    cmpValGlobal = true;
+    port = NULL;
+    intOp = NULL;
+    portValPtr = NULL;
+    isUsed = true;  
+    setPointer(cmpString);  
+}
+
+intCompare::intCompare(int* intVarInput, const char* cmpString, int cmpValInput):
+    intVal(intVarInput){
+    cmpVal = new int(cmpValInput);
+    cmpValGlobal = false;
+    port = NULL;
+    intOp = NULL;
+    portValPtr = NULL;
+    isUsed = true;  
+    setPointer(cmpString);
+}
+
+intCompare::intCompare(int* intVarInput, const char* cmpString, intOperation* cmpIntOpInput):
+    intVal(intVarInput) {
+    cmpVal = NULL;
+    port = NULL;
+    portValPtr = NULL;
+    cmpValGlobal = true;
+    intOp = cmpIntOpInput;
+    isUsed = true;  
+    setPointer_operation(cmpString);
+}
+
+intCompare::intCompare(digitalPort* portInput, const char* cmpString, intOperation* cmpIntOpInput, int whichToUse):
+    port(portInput) {
+    cmpVal = NULL;
+    intVal = NULL;
+    cmpValGlobal = true;
+    intOp = cmpIntOpInput;
+    setPointer_operation(cmpString);
+    isUsed = true;  
+    if (whichToUse == 1) {
+        portValPtr = &port->inState;
+    } else {
+        portValPtr = &port->outState;
+    }
+}
+
+
+
+void intCompare::set(digitalPort* portInput, const char* cmpString, int cmpValInput, int whichToUse) {
+    port = portInput;
+    cmpVal = new int(cmpValInput);
+    cmpValGlobal = false;
+    intVal = NULL;
+    intOp = NULL;
+    setPointer(cmpString); 
+    isUsed = true; 
+    if (whichToUse == 1) {
+        portValPtr = &port->inState;
+    } else {
+        portValPtr = &port->outState;
+    } 
+}
+
+void intCompare::set(digitalPort* portInput, const char* cmpString, int* cmpIntVarInput, int whichToUse) {
+    port = portInput;
+    cmpVal = cmpIntVarInput;
+    cmpValGlobal = true;
+    intVal = NULL;
+    intOp = NULL;
+    setPointer(cmpString);
+    isUsed = true; 
+    if (whichToUse == 1) {
+        portValPtr = &port->inState;
+    } else {
+        portValPtr = &port->outState;
+    }
+}
+
+void intCompare::set(int* intVarInput, const char* cmpString, int* cmpIntVarInput) {
+    cmpVal = cmpIntVarInput;
+    intVal = intVarInput; 
+    cmpValGlobal = true;
+    port = NULL;
+    intOp = NULL;
+    portValPtr = NULL;
+    setPointer(cmpString); 
+    isUsed = true;  
+}
+
+void intCompare::set(int* intVarInput, const char* cmpString, int cmpValInput) {
+    intVal = intVarInput;
+    cmpVal = new int(cmpValInput);
+    cmpValGlobal = false;
+    port = NULL;
+    intOp = NULL;
+    portValPtr = NULL;
+    setPointer(cmpString);
+    isUsed = true; 
+}
+
+void intCompare::set(int* intVarInput, const char* cmpString, intOperation* cmpIntOpInput) {
+    intVal = intVarInput;
+    cmpVal = NULL;
+    port = NULL;
+    portValPtr = NULL;
+    cmpValGlobal = true;
+    intOp = cmpIntOpInput;
+    setPointer_operation(cmpString);
+    isUsed = true; 
+}
+
+void intCompare::set(digitalPort* portInput, const char* cmpString, intOperation* cmpIntOpInput, int whichToUse) {
+    port = portInput;
+    cmpVal = NULL;
+    intVal = NULL;
+    cmpValGlobal = true;
+    intOp = cmpIntOpInput;
+    setPointer_operation(cmpString);
+    isUsed = true; 
+    if (whichToUse == 1) {
+        portValPtr = &port->inState;
+    } else {
+        portValPtr = &port->outState;
+    }
+}
+
+
+
+intCompare::~intCompare() {
+    if (!cmpValGlobal) delete cmpVal; //we only delete the intCompare object if it was created locally 
+    delete intOp;
+}
+
+void intCompare::release() {
+    if (!cmpValGlobal) delete cmpVal; //we only delete the intCompare object if it was created locally 
+    if (intOp != NULL) {
+        intOp->release();
+    }
+    port = NULL;
+    cmpVal = NULL;
+    cmpValGlobal = false;
+    intVal = NULL;
+    intOp = NULL;
+    portValPtr = NULL;
+    isUsed = false; 
+} 
+    
+
+void intCompare::setPointer(const char* cmpString) {
+    if (strcmp(cmpString, ">") == 0) {
+        isTruePtr = &intCompare::greaterThan;
+    }else if (strcmp(cmpString, ">=") == 0) {
+        isTruePtr = &intCompare::greaterOrEqual;
+    }else if (strcmp(cmpString, "<") == 0) {
+        isTruePtr = &intCompare::lessThan;
+    }else if (strcmp(cmpString, "<=") == 0) {
+        isTruePtr = &intCompare::lessOrEqual;
+    }else if (strcmp(cmpString, "==") == 0) {
+        isTruePtr = &intCompare::equal;
+    }else if (strcmp(cmpString, "!=") == 0) {
+        isTruePtr = &intCompare::notEqual;
+    }   
+}
+
+void intCompare::setPointer_operation(const char* cmpString) {
+    if (strcmp(cmpString, ">") == 0) {
+        isTruePtr = &intCompare::greaterThan_op;
+    }else if (strcmp(cmpString, ">=") == 0) {
+        isTruePtr = &intCompare::greaterOrEqual_op;
+    }else if (strcmp(cmpString, "<") == 0) {
+        isTruePtr = &intCompare::lessThan_op;
+    }else if (strcmp(cmpString, "<=") == 0) {
+        isTruePtr = &intCompare::lessOrEqual_op;
+    }else if (strcmp(cmpString, "==") == 0) {
+        isTruePtr = &intCompare::equal_op;
+    }else if (strcmp(cmpString, "!=") == 0) {
+        isTruePtr = &intCompare::notEqual_op;
+    }   
+}
+
+bool intCompare::isTrue() {
+    return (this->*isTruePtr)();
+    
+}
+
+bool intCompare::notEqual() {
+    if (intVal != NULL) {
+        return (*intVal != *cmpVal);
+    } else {
+        return (*portValPtr != *cmpVal);
+    }
+}
+
+bool intCompare::greaterThan() {
+    if (intVal != NULL) {
+        return (*intVal > *cmpVal);
+    } else {
+        return (*portValPtr > *cmpVal);
+    }
+}
+
+bool intCompare::greaterOrEqual() {
+    if (intVal != NULL) {
+        return (*intVal >= *cmpVal);
+    } else {
+        return (*portValPtr >= *cmpVal);
+    }
+}
+
+bool intCompare::lessThan() {
+    if (intVal != NULL) {
+        return (*intVal < *cmpVal);
+    } else {
+        return (*portValPtr < *cmpVal);
+    }
+}
+
+bool intCompare::lessOrEqual() {
+    if (intVal != NULL) {
+        return (*intVal <= *cmpVal);
+    } else {
+        return (*portValPtr <= *cmpVal);
+    }
+}
+
+bool intCompare::equal() {
+    if (intVal != NULL) {
+        return (*intVal == *cmpVal);
+    } else {
+        return (*portValPtr == *cmpVal);
+    }
+}
+
+bool intCompare::notEqual_op() {
+    if (intVal != NULL) {
+        return (*intVal != intOp->execute());
+    } else {
+        return (*portValPtr != intOp->execute());
+    }
+}
+
+bool intCompare::greaterThan_op() {
+    if (intVal != NULL) {
+        return (*intVal > intOp->execute());
+    } else {
+        return (*portValPtr > intOp->execute());
+    }
+}
+
+bool intCompare::greaterOrEqual_op() {
+    if (intVal != NULL) {
+        return (*intVal >= intOp->execute());
+    } else {
+        return (*portValPtr >= intOp->execute());
+    }
+}
+
+bool intCompare::lessThan_op() {
+    if (intVal != NULL) {
+        return (*intVal < intOp->execute());
+    } else {
+        return (*portValPtr < intOp->execute());
+    }
+}
+
+bool intCompare::lessOrEqual_op() {
+    if (intVal != NULL) {
+        return (*intVal <= intOp->execute());
+    } else {
+        return (*portValPtr <= intOp->execute());
+    }
+}
+
+bool intCompare::equal_op() {
+    if (intVal != NULL) {
+        return (*intVal == intOp->execute());
+    } else {
+        return (*portValPtr == intOp->execute());
+    }
+}
+
+intOperation::intOperation():
+    randHigh(-1) {
+    cmpVal = NULL;
+    intVal = NULL;
+    opPtr = NULL;
+    executePtr = NULL;
+    cmpValGlobal = false;
+    isUsed = false; 
+      
+}
+
+intOperation::intOperation(int randParam, const char* cmpString, int cmpValInput):
+    randHigh(randParam) {
+    cmpVal = new int(cmpValInput);
+    intVal = NULL;
+    opPtr = NULL;
+    cmpValGlobal = false;
+    isUsed = true; 
+    if (strcmp(cmpString, "+") == 0) {
+        executePtr = &intOperation::add;
+    }else if (strcmp(cmpString, "-") == 0) {
+        executePtr = &intOperation::subtract;
+    }else if (strcmp(cmpString, "+=") == 0) {
+        executePtr = &intOperation::addAndStore;
+    }else if (strcmp(cmpString, "-=") == 0) {
+        executePtr = &intOperation::subtractAndStore;
+    }else if (strcmp(cmpString, "=") == 0) {
+        executePtr = &intOperation::equals;
+    }
+    
+}
+
+intOperation::intOperation(int randParam, const char* cmpString, int* cmpIntVarInput):
+    randHigh(randParam),
+    cmpVal(cmpIntVarInput) {
+    intVal = NULL;
+    opPtr = NULL;
+    cmpValGlobal = true;
+    isUsed = true; 
+    if (strcmp(cmpString, "+") == 0) {
+        executePtr = &intOperation::add;
+    }else if (strcmp(cmpString, "-") == 0) {
+        executePtr = &intOperation::subtract;
+    }else if (strcmp(cmpString, "+=") == 0) {
+        executePtr = &intOperation::addAndStore;
+    }else if (strcmp(cmpString, "-=") == 0) {
+        executePtr = &intOperation::subtractAndStore;
+    }else if (strcmp(cmpString, "=") == 0) {
+        executePtr = &intOperation::equals;
+    }
+}
+
+intOperation::intOperation(int* intVarInput, const char* cmpString, int cmpValInput):
+    intVal(intVarInput) {
+    cmpVal = new int(cmpValInput);
+    randHigh = -1;
+    opPtr = NULL;
+    cmpValGlobal = false;
+    isUsed = true; 
+    if (strcmp(cmpString, "+") == 0) {
+        executePtr = &intOperation::add;
+    }else if (strcmp(cmpString, "-") == 0) {
+        executePtr = &intOperation::subtract;
+    }else if (strcmp(cmpString, "+=") == 0) {
+        executePtr = &intOperation::addAndStore;
+    }else if (strcmp(cmpString, "-=") == 0) {
+        executePtr = &intOperation::subtractAndStore;
+    }else if (strcmp(cmpString, "=") == 0) {
+        executePtr = &intOperation::equals;
+    }
+}
+
+intOperation::intOperation(int* intVarInput, const char* cmpString, int* cmpIntVarInput):
+    cmpVal(cmpIntVarInput),
+    intVal(intVarInput) {
+    randHigh = -1;
+    opPtr = NULL;
+    cmpValGlobal = true;
+    isUsed = true; 
+    if (strcmp(cmpString, "+") == 0) {
+        executePtr = &intOperation::add;
+    }else if (strcmp(cmpString, "-") == 0) {
+        executePtr = &intOperation::subtract;
+    }else if (strcmp(cmpString, "+=") == 0) {
+        executePtr = &intOperation::addAndStore;
+    }else if (strcmp(cmpString, "-=") == 0) {
+        executePtr = &intOperation::subtractAndStore;
+    }else if (strcmp(cmpString, "=") == 0) {
+        executePtr = &intOperation::equals;
+    }
+}
+
+intOperation::intOperation(int* intVarInput, intOperation* operationInput):
+    intVal(intVarInput) {
+    cmpVal = NULL;  
+    randHigh = -1;
+    opPtr = operationInput; 
+    executePtr = &intOperation::equals;
+    isUsed = true; 
+}
+
+void intOperation::set(int randParam, const char* cmpString, int cmpValInput) {
+    randHigh = randParam;
+    cmpVal = new int(cmpValInput);
+    intVal = NULL;
+    opPtr = NULL;
+    cmpValGlobal = false;
+    isUsed = true; 
+    if (strcmp(cmpString, "+") == 0) {
+        executePtr = &intOperation::add;
+    }else if (strcmp(cmpString, "-") == 0) {
+        executePtr = &intOperation::subtract;
+    }else if (strcmp(cmpString, "+=") == 0) {
+        executePtr = &intOperation::addAndStore;
+    }else if (strcmp(cmpString, "-=") == 0) {
+        executePtr = &intOperation::subtractAndStore;
+    }else if (strcmp(cmpString, "=") == 0) {
+        executePtr = &intOperation::equals;
+    }
+    
+}
+
+void intOperation::set(int randParam, const char* cmpString, int* cmpIntVarInput) {
+    randHigh = randParam;
+    cmpVal = cmpIntVarInput;
+    intVal = NULL;
+    opPtr = NULL;
+    cmpValGlobal = true;
+    isUsed = true; 
+    if (strcmp(cmpString, "+") == 0) {
+        executePtr = &intOperation::add;
+    }else if (strcmp(cmpString, "-") == 0) {
+        executePtr = &intOperation::subtract;
+    }else if (strcmp(cmpString, "+=") == 0) {
+        executePtr = &intOperation::addAndStore;
+    }else if (strcmp(cmpString, "-=") == 0) {
+        executePtr = &intOperation::subtractAndStore;
+    }else if (strcmp(cmpString, "=") == 0) {
+        executePtr = &intOperation::equals;
+    }
+}
+
+void intOperation::set(int* intVarInput, const char* cmpString, int cmpValInput) {
+    intVal = intVarInput;
+    cmpVal = new int(cmpValInput);
+    randHigh = -1;
+    opPtr = NULL;
+    cmpValGlobal = false;
+    isUsed = true; 
+    if (strcmp(cmpString, "+") == 0) {
+        executePtr = &intOperation::add;
+    }else if (strcmp(cmpString, "-") == 0) {
+        executePtr = &intOperation::subtract;
+    }else if (strcmp(cmpString, "+=") == 0) {
+        executePtr = &intOperation::addAndStore;
+    }else if (strcmp(cmpString, "-=") == 0) {
+        executePtr = &intOperation::subtractAndStore;
+    }else if (strcmp(cmpString, "=") == 0) {
+        executePtr = &intOperation::equals;
+    }
+}
+
+void intOperation::set(int* intVarInput, const char* cmpString, int* cmpIntVarInput) {
+    cmpVal = cmpIntVarInput;
+    intVal =intVarInput;
+    randHigh = -1;
+    opPtr = NULL;
+    cmpValGlobal = true;
+    isUsed = true; 
+    if (strcmp(cmpString, "+") == 0) {
+        executePtr = &intOperation::add;
+    }else if (strcmp(cmpString, "-") == 0) {
+        executePtr = &intOperation::subtract;
+    }else if (strcmp(cmpString, "+=") == 0) {
+        executePtr = &intOperation::addAndStore;
+    }else if (strcmp(cmpString, "-=") == 0) {
+        executePtr = &intOperation::subtractAndStore;
+    }else if (strcmp(cmpString, "=") == 0) {
+        executePtr = &intOperation::equals;
+    }
+}
+
+void intOperation::set(int* intVarInput, intOperation* operationInput) {
+    intVal = intVarInput;
+    cmpVal = NULL;  
+    randHigh = -1;
+    opPtr = operationInput; 
+    executePtr = &intOperation::equals;
+    isUsed = true; 
+
+}
+
+
+intOperation::~intOperation() {
+    if (!cmpValGlobal) delete cmpVal;
+    delete opPtr;
+}
+
+void intOperation::release() {
+    if (!cmpValGlobal) delete cmpVal;
+    if (opPtr != NULL) {
+        opPtr->release();
+    }
+    randHigh = -1;
+    cmpVal = NULL;
+    intVal = NULL;
+    opPtr = NULL;
+    executePtr = NULL;
+    cmpValGlobal = false;
+    isUsed = false;
+}
+    
+
+int intOperation::execute() {
+    return (this->*executePtr)();
+    
+}
+
+int intOperation::add() {
+    if (intVal != NULL) {
+        return (*intVal + *cmpVal);
+    }
+    else {
+        //srand(time(NULL));
+        srand(*globalTimeKeeperPtr);   
+        return (rand() % (randHigh+1)) + *cmpVal;
+        //return (port->getState() + *cmpVal);
+    }    
+}
+
+int intOperation::subtract() {
+    if (intVal != NULL) {
+        return (*intVal - *cmpVal);
+    }
+    else {
+        srand(*globalTimeKeeperPtr);   
+        return (rand() % (randHigh+1)) - *cmpVal;
+        //return (port->getState() - *cmpVal);
+    }    
+}
+
+int intOperation::addAndStore() {
+    if (intVal != NULL) {
+        *intVal = *intVal + *cmpVal;
+        return *intVal;
+    }
+    else {
+        
+        //Doesn't happen
+        return 0;
+        //port->setState(port->getState() + *cmpVal);
+        //return port->getState();
+    }
+    
+}
+
+int intOperation::subtractAndStore() {
+    if (intVal != NULL) {
+        *intVal = *intVal - *cmpVal;
+        return *intVal;
+    } else {
+        //doesn't happen
+        return 0;
+        //port->setState(port->getState() - *cmpVal);
+        //return port->getState();
+    }
+}
+
+int intOperation::equals() {
+    if ((intVal != NULL) && (opPtr == NULL)) {
+        *intVal = *cmpVal;
+        return *intVal;
+    } else if ((intVal != NULL) && (opPtr != NULL)) {
+        *intVal = opPtr->execute();
+        return *intVal;    
+    } else if (cmpVal != NULL){
+        
+        srand(*globalTimeKeeperPtr);     
+        *cmpVal = (rand() % (randHigh+1)); //this is how we assign a random number to variable
+        return *cmpVal;
+        
+    } 
+    return -1;
+}
+
+condition::condition() {
+    intCmp = NULL;
+    conditionPtrs[0] = NULL;
+    conditionPtrs[1] = NULL;
+    isUsed = false; 
+    conditionType = ARITHMATIC_CONDITION;
+}
+
+condition::condition(intCompare* compareInput) {
+
+    intCmp = compareInput;
+    conditionPtrs[0] = NULL;
+    conditionPtrs[1] = NULL;
+    
+    isUsed = true; 
+    conditionType = ARITHMATIC_CONDITION;
+    
+}
+
+condition::condition(condition* condition1, char condType, condition* condition2) {
+    intCmp = NULL;
+    conditionPtrs[0] = condition1;
+    conditionPtrs[1] = condition2;
+    isUsed = true; 
+    conditionType = condType;
+}
+
+condition::~condition() {
+    if (intCmp != NULL) {
+        delete intCmp;
+     }
+} 
+
+void condition::release() {
+   if (intCmp != NULL) {
+        intCmp->release();
+        intCmp=NULL;
+   }
+   if (conditionPtrs[0] != NULL) {
+        conditionPtrs[0]->release();
+        conditionPtrs[1]->release();
+        conditionPtrs[0]=NULL;
+        conditionPtrs[1]=NULL;
+   }
+   isUsed = false;
+}
+
+void condition::set(intCompare* compareInput) {
+    release();
+    intCmp = compareInput;
+    conditionPtrs[0] = NULL;
+    conditionPtrs[1] = NULL;
+    isUsed = true; 
+    conditionType = ARITHMATIC_CONDITION;
+}
+
+void condition::set(condition* condition1, char condType, condition* condition2) {
+    release();
+    intCmp = NULL;
+    conditionPtrs[0] = condition1;
+    conditionPtrs[1] = condition2;
+    isUsed = true; 
+    conditionType = condType;
+}
+
+bool condition::isTrue() {
+    
+    
+    bool result = true;
+    if (conditionType == ARITHMATIC_CONDITION) {
+        //pc.printf("Evauating arithmatic condition \r\n");
+        result = (intCmp->isTrue)();        
+    } else if (conditionType == AND_CONDITION) {
+        //pc.printf("Evauating AND condition \r\n");
+        result = conditionPtrs[0]->isTrue() && conditionPtrs[1]->isTrue();
+    } else if (conditionType == OR_CONDITION) {
+        //pc.printf("Evauating OR condition \r\n");
+        result = conditionPtrs[0]->isTrue() || conditionPtrs[1]->isTrue();
+    }
+    return result;
+    
+}
+
+portMessage::portMessage():
+    whichToSet(0),
+    value(0),
+    port(NULL) {
+    isUsed = false; 
+}
+
+void portMessage::release() {
+    
+    whichToSet = 0;
+    value = 0;
+    port = NULL;
+    isUsed = false; 
+}
+
+/*
+portMessage::portMessage(digitalPort* portIn, int whichToSetIn, int valueIn):
+    whichToSet(whichToSetIn),
+    value(valueIn),
+    port(portIn) {
+    isUsed = true; 
+}
+
+void portMessage::setMessage(digitalPort* portIn, int whichToSetIn, int valueIn) {
+    whichToSet = whichToSetIn;
+    value = valueIn;
+    port = portIn;
+    isUsed = true; 
+}*/
+
+portMessage::portMessage(int* portIn, int whichToSetIn, int valueIn):
+    whichToSet(whichToSetIn),
+    value(valueIn),
+    port(portIn) {
+    isUsed = true; 
+}
+
+void portMessage::setMessage(int* portIn, int whichToSetIn, int valueIn) {
+    whichToSet = whichToSetIn;
+    value = valueIn;
+    port = portIn;
+    isUsed = true; 
+}
+ 
+void portMessage::execute() {
+ 
+    if (port != NULL) {
+        if ((*port > 0) && (*port <= NUMPORTS)) {
+            portVector[*port]->setDigitalOut(value);
+        } else {
+            pc.printf("Error: port index assigned by variable does not exist.");
+        }
+    } else {
+        portVector[whichToSet]->setDigitalOut(value);
+    }
+    
+    /*
+    if (whichToSet == 1) {
+        port->setDigitalOut(value);
+    } else if (whichToSet == 2) {
+        //port->setState(value);
+    }*/
+}
+
+action::action():
+    actionType(0) {
+    op = NULL;
+    message = NULL;
+    eventToCreate = NULL;
+    displayActionPtr = NULL;
+    //eventDelay = 0;
+    sound = NULL;
+    sysCommand = -1;
+    isUsed = false; 
+        
+}
+
+action::~action() {
+    if (eventToCreate != NULL) delete eventToCreate;
+    if (op != NULL) delete op;
+    if (message != NULL) delete message;
+    delete displayActionPtr;
+    delete sound;
+}
+
+void action::release() {
+    if (eventToCreate != NULL) eventToCreate->release();
+    if (op != NULL) op->release();
+    if (message != NULL) message->release();
+    if (displayActionPtr != NULL) displayActionPtr->release();
+    delete sound; //still need to make a static soundControl array
+    
+    actionType = 0;
+    op = NULL;
+    message = NULL;
+    eventToCreate = NULL;
+    displayActionPtr = NULL;
+    //eventDelay = 0;
+    sound = NULL;
+    sysCommand = -1;
+    isUsed = false; 
+}
+
+action::action(intOperation* opInput):
+    actionType(1) {
+    op = opInput;
+    message = NULL;
+    eventToCreate = NULL;
+    displayActionPtr= NULL;
+    //eventDelay = 0;
+    sound = NULL;
+    sysCommand = -1;
+    isUsed = true; 
+}
+
+action::action(portMessage* messageInput):
+    actionType(2) {
+    op = NULL;
+    eventToCreate = NULL;
+    message = messageInput;   
+    displayActionPtr= NULL;
+    //eventDelay = 0;
+    sound = NULL;
+    sysCommand = -1;
+    isUsed = true; 
+
+}
+
+action::action(event* eventInput):
+    actionType(3) {
+    op = NULL;
+    message = NULL;
+    eventToCreate = eventInput;
+    displayActionPtr= NULL;
+    sound = NULL;
+    
+    //eventDelay = eventInput->timeLag;
+   
+    
+    sysCommand = -1;
+    isUsed = true; 
+}
+
+/*
+action::action(event* eventInput, uint32_t delay):
+    actionType(3) {
+    op = NULL;
+    message = NULL;
+    eventToCreate = eventInput;
+    displayActionPtr= NULL;
+    sound = NULL;
+    eventDelay = delay;
+    sysCommand = -1;
+    isUsed = true; 
+    
+}*/
+
+
+
+action::action(displayAction* displayInput): 
+    actionType(4) {
+    op = NULL;
+    message = NULL;
+    eventToCreate = NULL;
+    sound = NULL;
+    displayActionPtr = displayInput;
+    //eventDelay = 0;
+    sysCommand = -1;  
+    isUsed = true;   
+}
+
+action::action(soundControl* soundInput): 
+    actionType(5) {
+    op = NULL;
+    message = NULL;
+    eventToCreate = NULL;
+    sound = soundInput;
+    displayActionPtr = NULL;
+    //eventDelay = 0;
+    sysCommand = -1; 
+    isUsed = true;   
+}
+
+action::action(int8_t sysCommandInput): 
+    actionType(6) {
+    op = NULL;
+    message = NULL;
+    eventToCreate = NULL;
+    sound = NULL;
+    displayActionPtr = NULL;
+    //eventDelay = 0;
+    sysCommand = sysCommandInput; 
+    isUsed = true;   
+}
+
+void action::set(intOperation* opInput) {
+    actionType = 1;
+    op = opInput;
+    //eventDelay = 0;
+    isUsed = true; 
+    
+}
+
+void action::set(portMessage* messageInput) {
+    actionType = 2;
+    message = messageInput;
+    //eventDelay = 0;
+    isUsed = true; 
+    
+}
+
+void action::set(event* eventInput) {
+    actionType = 3;
+    eventToCreate = eventInput;  
+    //eventDelay = eventInput->timeLag;
+    
+    isUsed = true; 
+    
+}
+
+/*
+void action::set(event* eventInput, uint32_t delay) {
+    actionType = 3;
+    eventToCreate = eventInput;
+    eventDelay = delay;
+    isUsed = true; 
+    
+}*/
+
+
+
+void action::set(displayAction* displayInput) {
+    actionType = 4;
+    displayActionPtr = displayInput;
+    isUsed = true; 
+}
+
+void action::set(soundControl* soundInput) {
+    actionType = 5;
+    sound = soundInput;
+    isUsed = true; 
+}
+
+void action::set(int8_t sysCommandInput) {
+    actionType = 6;
+    sysCommand = sysCommandInput;
+    isUsed = true; 
+}
+
+void action::execute() {
+
+    if (actionType == 1) {
+        op->execute();
+    } else if (actionType == 2) {
+        message->execute();
+    } else if (actionType == 3) {       
+        this->execute(*globalTimeKeeperPtr); //route to the other overloaded method  
+    } else if (actionType == 4) {       
+        displayActionPtr->execute(); //send text via serial  
+    } else if (actionType == 5) {       
+        sound->execute(); //operate sound device
+    } else if (actionType == 6) {
+        switch(sysCommand) {
+            case 0:
+               mainQueue.eraseQueue();
+               break; 
+            case 1:
+               textStreaming = true;
+               break; 
+            case 2:
+               textStreaming = false;
+               break;  
+            case 3:
+                broadCastStateChanges = true;
+                break;
+            case 4:
+                broadCastStateChanges = false;
+                break;     
+        }
+        
+    }
+}
+
+void action::execute(uint32_t blockExecTime) {
+   
+    if (actionType == 1) {
+        op->execute();
+    } else if (actionType == 2) {
+        message->execute();
+    } else if (actionType == 3) { //an event block
+        //Because time will pass from the begining of the block, any defined delays should be updated
+        
+        //int newDelay = eventDelay-(*globalTimeKeeperPtr-blockExecTime);
+        int newDelay;
+        if (eventToCreate->timeLagIsConstant) {
+            newDelay = eventToCreate->timeLag - (*globalTimeKeeperPtr-blockExecTime);
+        } else {
+            newDelay = *eventToCreate->timeLagVar - (*globalTimeKeeperPtr-blockExecTime);
+        }
+        if (newDelay < 0) {newDelay = 0;}          
+        eventToCreate->addToQueue(newDelay); //add the event to the queue to be executed later 
+       
+        if (eventToCreate->hasWhileLoop) { //this is a while loop         
+             if (eventToCreate->isConditionTrue()) {
+                //newDelay = (blockExecTime + eventToCreate->whileLoopPeriod) - *globalTimeKeeperPtr;
+                int tmpPeriod;
+                if (eventToCreate->whileLoopPeriodIsConstant) { //constant while loop period
+                    newDelay = (blockExecTime + eventToCreate->whileLoopPeriod);
+                    tmpPeriod = eventToCreate->whileLoopPeriod;
+                } else {
+                    tmpPeriod = *eventToCreate->whileLoopPeriodVar;
+                    if (tmpPeriod < 0) {
+                        tmpPeriod = 0;
+                    }
+                    newDelay = (blockExecTime + tmpPeriod);
+                }
+                while ( (newDelay-*globalTimeKeeperPtr < 0) && (eventToCreate->isConditionTrue()) ) {
+                    eventToCreate->execute();
+                    newDelay = newDelay + tmpPeriod;
+                                   
+                }
+                newDelay = newDelay-*globalTimeKeeperPtr;           
+                if (newDelay > 0) {
+                    eventToCreate->addToQueue(newDelay);
+                } else {
+                    eventToCreate->addToQueue(1);
+                }
+             } else if (eventToCreate->nextElseEventPtr != NULL) {
+                    eventToCreate->nextElseEventPtr->addToQueue();
+                 
+            }         
+         }   
+    } else if (actionType == 4) {       
+        displayActionPtr->execute(); //send text via serial  
+    } else if (actionType == 5) {       
+        sound->execute(); //operate sound device    
+    } else if (actionType == 6) {       
+        switch(sysCommand) {
+            case 0:
+               mainQueue.eraseQueue();
+               break; 
+            case 1:
+               textStreaming = true;
+               break; 
+            case 2:
+               textStreaming = false;
+               break; 
+            case 3:
+                broadCastStateChanges = true;
+                break;
+            case 4:
+                broadCastStateChanges = false;
+                break;  
+        }
+    }
+}
+
+eventQueue::eventQueue(digitalPort** portVectorInput, uint32_t* timeKeeperSlaveInput):
+    portVector(portVectorInput),
+    timeKeeperPtr(timeKeeperSlaveInput){
+    
+    globalTimeKeeperPtr = timeKeeperPtr;
+    queueItem blankEvent;
+    blankEvent.timeToExecute = 0;
+    blankEvent.eventPtr = NULL;
+    queueSize = 100;
+    events.resize(queueSize,blankEvent);
+    
+    
+}
+
+void eventQueue::addEventToQueue(event* eventInput, uint32_t delay) {
+    //*updateSlavePtr = false;
+    uint32_t eventTime = *timeKeeperPtr + delay;
+    //*updateSlavePtr = true;  
+    //std::vector<queueItem>::size_type sz = events.size();
+    //Look for the first empty slot in the queue and place the event there.
+    //This means that the events in the queue are out of order, but 
+    //it prevents us from having to push_pack and pop off all the time.
+    for (unsigned i = 0; i < queueSize; i++) {
+        if (events[i].eventPtr == NULL) {
+            events[i].eventPtr = eventInput;
+            events[i].timeToExecute = eventTime;
+            break;
+        }
+    }    
+}
+
+void eventQueue::eraseQueue() {
+    //Erase all events in the queue 
+    std::vector<queueItem>::size_type sz = events.size();
+    for (unsigned i = 0; i < sz; i++) {
+        events[i].eventPtr = NULL;
+        
+    }
+}
+
+   
+//check if any of the events in the queue are up for execution
+void eventQueue::check(void) {
+
+    //*updateSlavePtr = false;
+    uint32_t currentTime = *timeKeeperPtr;
+    //*updateSlavePtr = true;
+    //std::vector<queueItem>::size_type sz = events.size();
+    for (unsigned i = 0; i < queueSize; i++) {
+        if (events[i].eventPtr != NULL) {
+          if(events[i].timeToExecute <= currentTime) {
+            if (!events[i].eventPtr->hasWhileLoop) {
+                //this is not a while loop, so no need to check if the condition is still true
+                events[i].eventPtr->execute();
+            } else if (events[i].eventPtr->isConditionTrue()){              
+                //The event is part of a while loop, so recheck the condition before executing
+                events[i].eventPtr->execute();
+                //if (events[i].eventPtr->isConditionTrue()) { //is the condition still true?
+                    int nextTime;
+                    int tmpPeriod;
+                    if (events[i].eventPtr->whileLoopPeriodIsConstant) {
+                        nextTime = (events[i].timeToExecute + events[i].eventPtr->whileLoopPeriod);
+                        tmpPeriod = events[i].eventPtr->whileLoopPeriod;
+                    } else {
+                        tmpPeriod = *events[i].eventPtr->whileLoopPeriodVar;
+                        if (tmpPeriod < 0) {
+                            tmpPeriod = 0;
+                        }
+                        nextTime = (events[i].timeToExecute + tmpPeriod);
+                        
+                    }
+                    //Just in case we are not keeping up, execute the event until we have cought up
+                    while ((nextTime-*timeKeeperPtr <= 0) && (events[i].eventPtr->isConditionTrue())) {
+                        events[i].eventPtr->execute();
+                        nextTime = nextTime+tmpPeriod;
+                                                
+                    }
+                    nextTime = nextTime - *timeKeeperPtr;
+                    if (nextTime > 0) {         
+                        //we add the event to the queue (but the condition is rechecked first)
+                        //if the condition is false, the 'then' statement is added to the queue instead
+                        events[i].eventPtr->addToQueue(nextTime);
+                    } else {
+                        //if we are having trouble keeping up, just add the next event in 1 ms
+                        events[i].eventPtr->addToQueue(1);
+                    }
+                /*
+                } else {
+                    if (events[i].eventPtr->nextElseEventPtr != NULL) {
+                        events[i].eventPtr->nextElseEventPtr->addToQueue();
+                    }
+                }*/
+                    
+            } else {
+                if (events[i].eventPtr->nextElseEventPtr != NULL) {
+                    events[i].eventPtr->nextElseEventPtr->addToQueue();
+                }
+            }
+            events[i].eventPtr = NULL;
+        }
+      }  
+    }    
+}
+
+
+event::event():
+    timeLag(0),
+    queuePtr(&mainQueue) {
+    nextElseEventPtr = NULL;
+    conditionToCheck = NULL;
+    blockType = 0; 
+    whileLoopPeriod = 0;
+    numConditions = 0;
+    numActions = 0;
+    isUsed = false; 
+    timeLagVar = NULL;
+    timeLagIsConstant = true;
+    whileLoopPeriodIsConstant = true;
+    hasWhileLoop = false;
+    whileLoopPeriodVar = NULL;
+   
+ }
+
+event::event(eventQueue* queueInput):
+    timeLag(0),
+    queuePtr(&mainQueue) {
+    nextElseEventPtr = NULL;
+    conditionToCheck = NULL;
+    blockType = 0; 
+    whileLoopPeriod = 0;
+    numConditions = 0;
+    numActions = 0;
+    isUsed = true; 
+    timeLagVar = NULL;
+    timeLagIsConstant = true;
+    whileLoopPeriodIsConstant = true;
+    hasWhileLoop = false;
+    whileLoopPeriodVar = NULL;
+   
+ }
+ 
+ event::~event() {
+    /*
+    while (!conditionArray.empty())
+    {
+        delete conditionArray.back();
+        conditionArray.pop_back();
+    }
+    
+    while (!actionArray.empty())
+    {
+        delete actionArray.back();
+        actionArray.pop_back();
+    }
+    
+    delete nextElseEventPtr;
+    */
+ 
+ }
+ 
+void event::release() {
+    
+    for (int i = 0; i < numActions; i++) {
+        actionArray[i]->release();
+    }
+    
+    if (conditionToCheck != NULL) {
+        conditionToCheck->release();
+        conditionToCheck = NULL;
+    }
+    
+    if (nextElseEventPtr != NULL) {
+        nextElseEventPtr->release();
+    }
+    timeLag = 0;
+    nextElseEventPtr = NULL;
+    blockType = 0; 
+    whileLoopPeriod = 0;
+    numConditions = 0;
+    numActions = 0;
+    isUsed = false;
+    timeLagVar = NULL;
+    timeLagIsConstant = true;
+    whileLoopPeriodIsConstant = true;
+    hasWhileLoop = false;
+    whileLoopPeriodVar = NULL;
+ }
+ 
+ void event::setTimeLag(uint32_t timeLagInput) {
+    timeLag = timeLagInput;
+    timeLagIsConstant = true;
+ }
+ 
+ void event::setTimeLag(int* timeLagInput) {
+    timeLagVar = timeLagInput;
+    timeLagIsConstant = false; //time lag is not defined by a constant
+ }
+ 
+ void event::setWhileLoopPeriod(uint32_t period) {
+    whileLoopPeriodIsConstant = true;
+    hasWhileLoop = true;
+    whileLoopPeriod = period;
+    
+ }
+ 
+ void event::setWhileLoopPeriod(int* period) {
+    whileLoopPeriodIsConstant = false;
+    hasWhileLoop = true;
+    whileLoopPeriodVar = period;
+
+ }
+ 
+ void event::addCondition(condition* conditionInput) {
+    if (conditionToCheck != NULL) {
+        conditionToCheck->release();
+    }
+    conditionToCheck = conditionInput;
+    
+    //conditionArray.push_back(conditionInput);
+ }
+ 
+ void event::addAction(action* actionInput) {
+    actionArray[numActions] = actionInput;
+    numActions++;
+    //actionArray.push_back(actionInput);
+ }
+ 
+ bool event::isConditionTrue(void) {
+    //if statement (can be left empty, which is interpreted as 'true')
+    //queuePtr->pcPtr->printf("Checking condition...\r\n");
+    bool result = true;
+    /*
+    std::vector<condition*>::size_type sz = conditionArray.size();
+    for (unsigned i = 0; i < sz; i++) {
+        if (!conditionArray[i]->isTrue()) {
+            result = false;
+            //queuePtr->pcPtr->printf("Consition false\r\n");
+        } //else {queuePtr->pcPtr->printf("Consition true\r\n");}
+    }
+    */
+    
+    if ((conditionToCheck!=NULL)&&(!conditionToCheck->isTrue())) {
+        result = false;        
+    } 
+    
+    return result;
+ } 
+ 
+ void event::execute(void) {   
+    //called from the event queue.  The condition is bypassed because it was already checked  
+    
+   
+    uint32_t timeAtStartExec = *globalTimeKeeperPtr;      
+    //std::vector<action*>::size_type sz = actionArray.size();
+    
+    /*
+    std::deque<action*>::size_type sz = actionArray.size();
+       
+    for (unsigned i = 0; i < sz; i++) {
+        actionArray[i]->execute(timeAtStartExec);
+        
+    }
+    */
+     for (unsigned i = 0; i < numActions; i++) {
+        actionArray[i]->execute(timeAtStartExec);
+        
+    }
+    
+ }
+ 
+ //Attach an 'else' statement to the event
+ void event::setNextElseEvent(event* eventInput) {
+    nextElseEventPtr = eventInput;
+ }
+ 
+ 
+ //When we we call addToQueue() the condition is checked.  If true, the event is added
+ //to the queue, otherwise we check if there was an 'else' statement attached to the event.
+ void event::addToQueue(void) {   
+    if (isConditionTrue()) {
+        if ((timeLagIsConstant)&&(timeLag == 0)) {
+            execute();
+            
+        } else if (timeLagIsConstant) {
+            queuePtr->addEventToQueue(this, this->timeLag);
+        } else if ((!timeLagIsConstant)&&(*timeLagVar <= 0)) {           
+            execute();
+        } else {
+            queuePtr->addEventToQueue(this, *timeLagVar);           
+        }
+    } else if ((this->nextElseEventPtr != NULL)&&(whileLoopPeriod == 0)) {
+        this->nextElseEventPtr->addToQueue();
+    }
+ }
+ 
+ //We can override the timeLag field and use another delay
+ void event::addToQueue(uint32_t delay) {   
+    if (this->isConditionTrue()) {
+        //if ((delay == 0) && (whileLoopPeriod == 0)) {
+        if ((delay == 0)) {
+            this->execute();
+        } else {
+            queuePtr->addEventToQueue(this, delay);
+        }
+    } else if ((this->nextElseEventPtr != NULL)) { //&&(!hasWhileLoop)) {
+        this->nextElseEventPtr->addToQueue();
+    }
+ }
+ 
+ 
+ 
+ functionItem::functionItem(action* actionInput, string tagInput): 
+    tag(tagInput),
+    actionPtr(actionInput) {
+ }
+ 
+ functionItem::~functionItem() {
+    delete actionPtr;
+ }
+ 
+ scriptStream::scriptStream(Serial* serialInput, digitalPort** portVectorInput, int numPortsInput, eventQueue* queueInput):
+    portVector(portVectorInput),
+    numPorts(numPortsInput),
+    pcPtr(serialInput),
+    queuePtr(queueInput) {
+    
+    currentPort = -1;
+    currentTriggerPort = -1;
+    currentTriggerDir = 1;
+    currentFunction = -1;
+     
+    lineError = false;
+    blockDepth = 0;
+    ifBlockInit = false;
+    whileBlockInit = false;
+    elseFlag = false;
+    currentDelay = 0;
+    
+ }
+ 
+ void scriptStream::addLineToCurrentBlock(char* lineInput) {
+     
+    bool compile = false;
+    bool keep = false;
+    for (int i = 0; i < 128; i++) {
+        if (lineInput[i] == ';') {
+            compile = true;
+        } else if (lineInput[i] == ' ') {
+            continue;
+        } else if (lineInput[i] == '\0') {
+            break;
+        } else {
+            keep = true;
+            compile = false;
+        }
+    }
+    if (keep) currentBlock.insert(currentBlock.begin(),string(lineInput));
+    if (compile) parseBlock();
+    
+ }
+ 
+ 
+ //SCRIPT PARSING - all script commands are defined here.
+ //-------------------------------------------------------
+ void scriptStream::parseBlock() {
+          
+    lineError = false;
+    blockDepth = 0;
+    ifBlockInit = false;
+    whileBlockInit = false;
+    elseFlag = false;
+    thenFlag = false;
+    currentDelay = 0;
+    
+    std::size_t stringInd = 0;
+    
+    bool wholeLineEvaluated = false;
+   
+    //pcPtr->printf("\r\n"); 
+    while (!currentBlock.empty()) {
+        wholeLineEvaluated = false;
+        tmpLine = currentBlock.back();
+        lineError = false;
+        //remove tabs
+        std::size_t found = tmpLine.find_first_of(9); //tab
+        while (found!=std::string::npos) {
+            tmpLine[found]= ' ';
+            found=tmpLine.find_first_of(9,found+1);
+        }
+        
+        found = tmpLine.find_first_of(37); //% for commenting
+        if (found!=std::string::npos) {
+            for (int p=found; p<tmpLine.size() ;p++) {
+                tmpLine[p]= ' ';
+            }
+        }
+
+        //break up the line into tokens separated by spaces
+        tokenize(tmpLine,tokens," ;");
+        
+        std::vector<string>::size_type sz = tokens.size();
+    
+        for (unsigned i = 0; i < sz; i++) {
+            //pcPtr->printf("%s", tokens[i].c_str());
+            
+            
+            //end statement signals the end of a block-----------------------------------------
+            if (tokens[i].compare("end") == 0) { //ends the current block
+                
+                if (ifBlockInit || whileBlockInit) {
+                    pcPtr->printf("Error: expected a 'do' statement\r\n");
+                    lineError = true;
+                }
+                
+                ifBlockInit = false;
+                whileBlockInit = false;
+                elseFlag = false;
+                
+                if (blockDepth > 0) {
+                    if (blockDepth == 1) {
+                        
+                        
+                        //pcPtr->printf("Close trigger block for port %d\r\n",currentTriggerPort);
+                        currentTriggerPort = -1;
+                        
+                        
+                        
+                        blockDepth = 0;
+                    } else if (blockDepth > 1) {
+                        //pcPtr->printf("Close block\r\n");
+                        blockDepth = blockDepth - 1;
+                    }
+                    
+                    while ((tmpEventPtrArray.back()->blockType == 3) || (tmpEventPtrArray.back()->blockType == 4)){
+                       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;
+                }
+                
+                
+            
+            //sound statement used to play wave files------------------------------------------------
+            //example: sound('soundfile')
+            //         sound(stop) 
+            } else if (tokens[i].find("sound(") != std::string::npos) {
+                if (ifBlockInit || whileBlockInit || elseFlag) {
+                    pcPtr->printf("Error: expected a 'do' statement\r\n");
+                    lineError = true;
+                }
+                wholeLineEvaluated = true;
+                int pos1 = tmpLine.find("sound(")+6;
+                int pos2 = tmpLine.find_first_of(")",pos1);
+                string dispVar = tmpLine.substr(pos1,pos2-pos1);
+                
+                int* tmpVar = findIntVariable(dispVar);
+                bool isText = false;
+                bool stopSignal = false;
+                bool resetSignal = false;
+                if (tmpVar == NULL) {
+                    if ((tmpLine.compare(pos1,1,"'")==0) && (tmpLine.compare(pos2-1,1,"'")==0)) {
+                        isText = true;                        
+                    } else if (dispVar.compare("stop") == 0) {
+                        stopSignal = true;
+                    } else if (dispVar.compare("reset") == 0) {
+                        resetSignal = true;    
+                    } else {    
+                        pcPtr->printf("Error: variable input to sound() does not exist\r\n");
+                        lineError = true;
+                    }
+                }
+                action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);                   
+                if (tmpAction == NULL) {                    
+                    pcPtr->printf("Error: no memory slots available.\r\n"); 
+                    lineError = true;
+                }
+                if (!lineError && (blockDepth == 0)) {
+                    //we are not inside a block structure, so play sound now
+                    if (stopSignal) {
+                        soundControl S;
+                        S.setPlayback(false);
+                        S.execute();
+                    } else if (resetSignal) {
+                        soundControl S;
+                        S.setReset();
+                        S.execute();
+                    } else if (isText) {
+                                             
+                        if (pos2-pos1-2 <= 20) {
+                            
+                            soundControl S;
+                            S.setFile(tmpLine.substr(pos1+1,pos2-pos1-2));
+                            S.execute();
+                        } else {
+                            pcPtr->printf("Error: sound file names must be 20 characters or less.\r\n");
+                            lineError = true;
+                        }
+                    } else {
+                        pcPtr->printf("Error: variable input to sound() not yet supported.  Enter a string in single quotes.\r\n");
+                        lineError = true;
+                    }
+                    
+                } else if (!lineError && (blockDepth > 0) ){
+                    //the disp function was put inside a block
+                    if (stopSignal) {
+                        soundControl* sPtr = new soundControl();
+                        sPtr->setPlayback(false);
+                        //action* tmpAction = new action(sPtr);
+                        tmpAction->set(sPtr);
+                        tmpEventPtrArray.back()->addAction(tmpAction);
+                    } else if (resetSignal) {
+                        soundControl* sPtr = new soundControl();
+                        sPtr->setReset();
+                        //action* tmpAction = new action(sPtr);
+                        tmpAction->set(sPtr);
+                        tmpEventPtrArray.back()->addAction(tmpAction);    
+                    } else if (isText) {
+                                             
+                        if (pos2-pos1-2 <= 20) {
+                            soundControl* sPtr = new soundControl();
+                            sPtr->setFile(tmpLine.substr(pos1+1,pos2-pos1-2));
+                            //action* tmpAction = new action(sPtr);
+                            tmpAction->set(sPtr);
+                            tmpEventPtrArray.back()->addAction(tmpAction);
+                        } else {
+                            pcPtr->printf("Error: sound file names must be 20 characters or less.\r\n");
+                            lineError = true;
+                        }
+                    } else {
+                        pcPtr->printf("Error: variable input to sound() not yet supported.  Enter a string in single quotes.\r\n");
+                        lineError = true;
+                    }
+                    
+                    //pcPtr->printf("Sound action\r\n");
+                }
+                
+            } else if (tokens[i].find("volume(") != std::string::npos) {
+                if (ifBlockInit || whileBlockInit || elseFlag) {
+                    pcPtr->printf("Error: expected a 'do' statement\r\n");
+                    lineError = true;
+                }
+                wholeLineEvaluated = true;
+                int pos1 = tmpLine.find("volume(")+7;
+                int pos2 = tmpLine.find_first_of(")",pos1);
+                string dispVar = tmpLine.substr(pos1,pos2-pos1);
+                
+                int* tmpVar = findIntVariable(dispVar);
+                bool isText = false;
+                if (tmpVar == NULL) {
+                    if (isNumber(dispVar)) {
+                        isText = true;
+                    } else {    
+                        pcPtr->printf("Error: variable input to volume() does not exist\r\n");
+                        lineError = true;
+                    }
+                }
+                action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);                   
+                if (tmpAction == NULL) {                    
+                    pcPtr->printf("Error: no memory slots available.\r\n"); 
+                    lineError = true;
+                }
+                if (!lineError && (blockDepth == 0)) {
+                    //we are not inside a block structure, so play sound now
+                    if (isText) {
+                        int newVolume = atoi(dispVar.data());                   
+                        if ((newVolume >=0)&&(newVolume <= 255)) {
+                            soundControl S;
+                            S.setVolume(newVolume);
+                            S.execute();
+                        } else {
+                            pcPtr->printf("Error: sound volume must be between 0 and 255 .\r\n");
+                            lineError = true;
+                        }
+                    } else {
+                        soundControl S;
+                        S.setVolume(tmpVar);
+                        S.execute();
+                    }
+                    
+                } else if (!lineError && (blockDepth > 0) ){
+                    //the disp function was put inside a block
+                    if (isText) {
+                        int newVolume = atoi(dispVar.data());                   
+                        
+                        soundControl* sPtr = new soundControl();
+                        sPtr->setVolume(newVolume);
+                        
+                        //action* tmpAction = new action(sPtr);
+                        tmpAction->set(sPtr);                      
+                        tmpEventPtrArray.back()->addAction(tmpAction);
+                                                       
+                    } else {
+                        soundControl* sPtr = new soundControl();
+                        sPtr->setVolume(tmpVar);
+                        //action* tmpAction = new action(sPtr);
+                        tmpAction->set(sPtr);
+                        tmpEventPtrArray.back()->addAction(tmpAction);
+                    }
+                                     
+                    //pcPtr->printf("Volume action\r\n");
+                }
+            //clock statement used to is used to control the clock-------------------------
+            //example: clock(reset); clock(slave); clock(standalone)    
+            } else if (tokens[i].find("clock(") != std::string::npos) { //clock commands
+                if (ifBlockInit || whileBlockInit || elseFlag) {
+                    pcPtr->printf("Error: expected a 'do' statement\r\n");
+                    lineError = true;
+                }
+                if (blockDepth > 0) {
+                    pcPtr->printf("Error: clock commands only allowed outside of block structure\r\n");
+                    lineError = true;
+                }
+                
+                if (!lineError) {
+                    int pos1 = tmpLine.find("clock(")+6;
+                    int pos2 = tmpLine.find_first_of(")",pos1);
+                    string dispVar = tmpLine.substr(pos1,pos2-pos1);
+                    
+                    
+                    if (blockDepth == 0) {
+                        if (dispVar.compare("reset") == 0) {
+                            resetTimer = true;
+                            queuePtr->eraseQueue();
+                            textDisplay.send(string("Clock reset to 0\r\n"));
+                            //pcPtr->printf("Clock reset to 0\r\n");
+                        } else if (dispVar.compare("slave") == 0) {
+                            if (!clockSlave) {
+                                changeToSlave = true;
+                                textDisplay.send(string("Slave mode\r\n"));
+                                //pcPtr->printf("Slave mode\r\n");
+                            }
+                        } else if (dispVar.compare("standalone") == 0) {
+                            if (clockSlave) {
+                                changeToStandAlone = true;
+                                textDisplay.send(string("Standalone mode\r\n"));
+                                //pcPtr->printf("Standalone mode\r\n");
+                            }
+                        } else {
+                            pcPtr->printf("Clock control statement not understood\r\n");
+                            lineError = true;
+                        }
+                    } 
+                }
+                    
+            //disp command used to display text via serial---------------------------------------
+            //example: disp('hello'); disp(myVar)   
+            } else if (tokens[i].find("disp(") != std::string::npos) { //display value of variable
+                
+                if (ifBlockInit || whileBlockInit || elseFlag) {
+                    pcPtr->printf("Error: expected a 'do' statement\r\n");
+                    lineError = true;
+                }
+                
+                //int pos1 = tokens[i].find("disp(")+5;
+                //int pos2 = tokens[i].find_first_of(")",pos1);
+                //string dispVar = tokens[i].substr(pos1,pos2-pos1);
+                
+                wholeLineEvaluated = true;
+                int pos1 = tmpLine.find("disp(")+5;
+                int pos2 = tmpLine.find_first_of(")",pos1);
+                string dispVar = tmpLine.substr(pos1,pos2-pos1);
+                
+                int* tmpVar = findIntVariable(dispVar);
+                bool isText = false;
+                if (tmpVar == NULL) {
+                    if ((tmpLine.compare(pos1,1,"'")==0) && (tmpLine.compare(pos2-1,1,"'")==0)) {
+                        isText = true;
+                    } else {    
+                        pcPtr->printf("Error: variable to display does not exist\r\n");
+                        lineError = true;
+                    }
+                }
+                displayAction* dPtr = findFirstUnUsed(displayActionBlock, NUMDISPLAYACTIONS);                   
+                if (dPtr == NULL) {                    
+                    pcPtr->printf("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), pcPtr);
+                        dPtr->execute();
+                        //delete dPtr;
+                        dPtr->release();
+                    } else {
+                        //displayAction* dPtr = new displayAction(tmpVar, dispVar, pcPtr);
+                        dPtr->set(tmpVar, dispVar, pcPtr);
+                        dPtr->execute();
+                        //delete dPtr;   
+                        dPtr->release();                  
+                    }
+                                      
+                } else if (!lineError && (blockDepth > 0) ){
+                    //the disp function was put inside a block
+                    action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);                   
+                    if (tmpAction == NULL) {                    
+                        pcPtr->printf("Error: no memory slots available.\r\n"); 
+                        lineError = true;
+                    }
+                    if (!lineError && isText) {
+                        //displayAction* dPtr = new displayAction(tmpLine.substr(pos1+1,pos2-pos1-2), pcPtr);
+                        dPtr->set(tmpLine.substr(pos1+1,pos2-pos1-2), pcPtr);
+                        tmpAction->set(dPtr);
+                        //action* tmpAction = new action(dPtr);
+                        tmpEventPtrArray.back()->addAction(tmpAction);
+                    } else if (!lineError) {
+                        //displayAction* dPtr = new displayAction(tmpVar, dispVar, pcPtr);
+                        dPtr->set(tmpVar, dispVar, pcPtr);
+                        tmpAction->set(dPtr);
+                        //action* tmpAction = new action(dPtr);
+                        tmpEventPtrArray.back()->addAction(tmpAction);
+                    }
+                    
+                    //pcPtr->printf("Display action\r\n");
+                }
+            
+            
+            //int is used to decalar new variables.  Only allowed outside of callbacks-------------------
+            //example: int a;  int b = 9    
+            } else if (tokens[i].compare("int") == 0) { //define a new integer variable
+                
+                if (ifBlockInit || whileBlockInit) {
+                    pcPtr->printf("Error: expected a 'do' statement\r\n");
+                    lineError = true;
+                }
+                tmpString = "";
+                wholeLineEvaluated = true;
+                int spacesBeforeEqualSign = 0;
+                bool countSpaces = true;
+                //combine the tokens without whitespaces
+                for (unsigned j = i+1; j < sz; j++) { 
+                    tmpString.append(tokens[j]);
+                    if (tokens[j].find_first_of("=") != std::string::npos) {
+                        if (tokens[j].find_first_of("=") > 0) spacesBeforeEqualSign++;
+                        countSpaces = false;
+                    } else if (countSpaces) {
+                        spacesBeforeEqualSign++;
+                    }   
+                }
+                
+                if (blockDepth > 0) {
+                    pcPtr->printf("Error: Variables can only be first declared outside of callbacks.\r\n");
+                    lineError = true;
+                }
+                
+                if ((!lineError) && (spacesBeforeEqualSign > 1)) {
+                    pcPtr->printf("Error: Variable can't have a space in it.\r\n");
+                    lineError = true;
+                }
+                stringInd = tmpString.find_first_of("=");
+                
+                bool variableCreated = false;
+                if (!lineError) {
+                    if (((stringInd == std::string::npos) && (sz == 2)) || (stringInd != std::string::npos)) {
+                        if (createIntVariable(tmpString.substr(0,stringInd))) {
+                            //pcPtr->printf("Created variable: %s\r\n", tmpString.substr(0,stringInd).data());
+                            variableCreated = true;
+                        } else {                         
+                            int* tmpVar = findIntVariable(tmpString.substr(0,stringInd));
+                            *tmpVar = 0;
+                            //pcPtr->printf("Reset variable %s to 0\r\n", tmpString.substr(0,stringInd).data());
+                            //lineError = true;
+                        }
+                    } else {
+                        pcPtr->printf("Error: variable declaration not understood.\r\n", tmpString.substr(0,stringInd).data());
+                        lineError = true;
+                    } 
+                }   
+                    
+                if ((!lineError) && (stringInd != std::string::npos)) { //evaluate the expression                  
+                    action* tmpAction = evaluateAssignmentForAction(tmpString);
+                    if (tmpAction != NULL) {
+                        tmpAction->execute();
+                        //delete tmpAction;
+                        tmpAction->release();
+                     } else {
+                        lineError = true;
+                        if (variableCreated) {
+                            delete globalVariables.back();
+                            globalVariables.pop_back();
+                        }
+                    } 
+                }
+            
+            //serial command is used to toggle whether or not to buffer up output text----------------
+            //examples: serial buffer; serial send
+            } else if (tokens[i].compare("serial") == 0) {
+                 if (ifBlockInit || whileBlockInit || elseFlag) {
+                    pcPtr->printf("Error: expected a 'do' statement\r\n");
+                    lineError = true;
+                }
+                bool stream = true;
+                if ((!lineError)&&(i+1 < sz)){
+                    if (tokens[i+1].compare("buffer") == 0) {                      
+                            stream = false;                        
+                    } else if (tokens[i+1].compare("send") == 0) {                   
+                            stream = true;                                             
+                    } else {
+                        pcPtr->printf("Error: 'serial' useage: 'serial buffer' or 'serial send'\r\n");
+                        lineError = true;
+                    }
+                }
+                i++;
+                if ((!lineError) && (blockDepth == 0)) {                    
+                    if (stream) {
+                        textStreaming = true;
+                    } else {
+                        textStreaming = false;
+                    }
+                } else if ((!lineError) && (blockDepth > 0)) {
+                     if (stream) {
+                        //action* tmpAction = new action(1); //code 1 = turn on text streaming
+                        action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);                   
+                        if (tmpAction == NULL) {                    
+                            pcPtr->printf("Error: no memory slots available.\r\n"); 
+                            lineError = true;
+                        } else {
+                            tmpAction->set(1);
+                            tmpEventPtrArray.back()->addAction(tmpAction);
+                        }
+                        
+                     } else {
+                        //action* tmpAction = new action(2); //code 2 = turn on text buffering
+                        action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);                   
+                        if (tmpAction == NULL) {                    
+                            pcPtr->printf("Error: no memory slots available.\r\n"); 
+                            lineError = true;
+                        } else {
+                            tmpAction->set(2);
+                            tmpEventPtrArray.back()->addAction(tmpAction);
+                        }
+                     }
+                }
+             
+            //updates command toggles the DIO update messages upon a change------------------
+            //examples: updates on; updates off     
+            } else if (tokens[i].compare("updates") == 0) {
+                 if (ifBlockInit || whileBlockInit || elseFlag) {
+                    pcPtr->printf("Error: expected a 'do' statement\r\n");
+                    lineError = true;
+                }
+                bool stream = true;
+                if ((!lineError)&&(i+1 < sz)){
+                    if (tokens[i+1].compare("on") == 0) {                      
+                            stream = true;                        
+                    } else if (tokens[i+1].compare("off") == 0) {                   
+                            stream = false;                                             
+                    } else {
+                        pcPtr->printf("Error: 'updates' useage: 'updates on' or 'updates off'\r\n");
+                        lineError = true;
+                    }
+                }
+                i++;
+                if ((!lineError) && (blockDepth == 0)) {                   
+                    if (stream) {
+                        broadCastStateChanges = true;
+                    } else {
+                        broadCastStateChanges = false;
+                    }
+                } else if ((!lineError) && (blockDepth > 0)) {                    
+                     if (stream) {
+                        //action* tmpAction = new action(3); //code 3 = turn on updates
+                        action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);                   
+                        if (tmpAction == NULL) {                    
+                            pcPtr->printf("Error: no memory slots available.\r\n"); 
+                            lineError = true;
+                        } else {
+                            tmpAction->set(3);
+                            tmpEventPtrArray.back()->addAction(tmpAction);
+                        }
+                     } else {
+                        //action* tmpAction = new action(4); //code 4 = turn off updates
+                        action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);                   
+                        if (tmpAction == NULL) {                    
+                            pcPtr->printf("Error: no memory slots available.\r\n"); 
+                            lineError = true;
+                        } else {
+                            tmpAction->set(4);
+                            tmpEventPtrArray.back()->addAction(tmpAction);
+                        }
+                        
+                     }
+                }
+                 
+            //clear is used to clear things from memory---------------------------------
+            //examples: clear all; clear callbacks; clear queue
+            } else if (tokens[i].compare("ram") == 0) {
+                if (ifBlockInit || whileBlockInit || elseFlag) {
+                    pcPtr->printf("Error: expected a 'do' statement\r\n");
+                    lineError = true;
+                }
+                if ((!lineError) && (blockDepth > 0)) {
+                    pcPtr->printf("Error: ram statement is not allowed inside a block.\r\n");
+                    lineError = true;
+                }
+                if (!lineError) {
+                    DisplayRAMBanks();
+                }
+            } else if (tokens[i].compare("memory") == 0) {
+                if (ifBlockInit || whileBlockInit || elseFlag) {
+                    pcPtr->printf("Error: expected a 'do' statement\r\n");
+                    lineError = true;
+                }
+                if ((!lineError) && (blockDepth > 0)) {
+                    pcPtr->printf("Error: memory statement is not allowed inside a block.\r\n");
+                    lineError = true;
+                }
+                if (!lineError) {
+                    displayMemoryLeft();
+                }
+            
+            
+            } else if (tokens[i].compare("clear") == 0) { //delete all created events and variables
+                if (ifBlockInit || whileBlockInit || elseFlag) {
+                    pcPtr->printf("Error: expected a 'do' statement\r\n");
+                    lineError = true;
+                }
+                int clearMode = 0;
+                if ((!lineError)&&(i+1 < sz)){
+                    if (tokens[i+1].compare("all") == 0) {
+                        clearMode = 1;
+                    } else if (tokens[i+1].compare("blocks") == 0) {
+                        clearMode = 2;                   
+                    } else if (tokens[i+1].compare("queue") == 0) {
+                        clearMode = 3;                    
+                    } else {
+                        pcPtr->printf("Error: clear what: all, blocks, or queue? \r\n");
+                        lineError = true;
+                    }
+                } else {
+                    pcPtr->printf("Error: clear what: all, blocks, or queue? \r\n");
+                    lineError = true;
+                }
+                    
+                
+                if ((!lineError) && (clearMode < 3) && (blockDepth > 0)) {
+                    pcPtr->printf("Error: 'clear all' and 'clear blocks' only allowed outside of block structures\r\n");
+                    lineError = true;
+                }
+                if (!lineError) {
+                    i++;
+                    //clear variables
+                    if (clearMode == 1) {
+                        while (!globalVariables.empty()) {               
+                            globalVariables.pop_back();                      
+                        }
+                    }
+                    
+                    //clear callbacks, functions, and queue
+                    if (clearMode < 3) { 
+                        for (int pNum = 1; pNum <= numPorts; pNum++) {
+                            //delete portVector[pNum]->triggerUpEventPtr;
+                            if (portVector[pNum]->triggerUpEventPtr != NULL) {
+                                portVector[pNum]->triggerUpEventPtr->release();
+                            }
+                            portVector[pNum]->triggerUpEventPtr = NULL;
+                            
+                            //delete portVector[pNum]->triggerDownEventPtr;
+                            if (portVector[pNum]->triggerDownEventPtr != NULL) {
+                                portVector[pNum]->triggerDownEventPtr->release();
+                            }
+                            portVector[pNum]->triggerDownEventPtr = NULL;
+                            while (!functionArray.empty()) {               
+                                delete functionArray.back();
+                                functionArray.pop_back();                      
+                            }                           
+                        }
+                        
+                        queuePtr->eraseQueue();
+                    }
+                    
+                    if (clearMode == 4) {
+                        if (blockDepth > 0) { //we are inside a block
+                            action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);                   
+                            if (tmpAction == NULL) {                    
+                                pcPtr->printf("Error: no memory slots available.\r\n"); 
+                                lineError = true;
+                            } else {
+                                                   
+                                int8_t code = 0;
+                                tmpAction->set(code);
+                                //action* tmpAction = new action(code); //code 0 = clear queue
+                                tmpEventPtrArray.back()->addAction(tmpAction);
+                            }
+                        } else {
+                            //clear queue now
+                            queuePtr->eraseQueue();
+                        }
+                    }
+                                     
+                    
+                }
+                
+            //do starts a block---------------------------------------------------------  
+            //example:  do in 500
+            //              ...
+            //          end
+                                
+            } else if (tokens[i].compare("do") == 0) { //the start of a block
+                                      
+                     if (!ifBlockInit && !whileBlockInit) {
+                         
+                         if ((currentTriggerPort > 0) || (currentFunction > 0)) { //check to make sure we are inside a trigger block
+                             //pcPtr->printf("Start new block\r\n"); 
+                                
+                         } else {
+                             pcPtr->printf("Error: a statement block must be placed inside a callback or function.\r\n"); 
+                             lineError = true;
+                         }
+                            
+                     }
+                     tmpEvent = findFirstUnUsed(eventBlock, NUMEVENTS);
+                     action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);
+                     bool eventReserved = false;
+                     if ((tmpEvent == NULL)||(tmpAction == NULL)) {                    
+                        pcPtr->printf("Error: no memory slots available.\r\n"); 
+                        lineError = true;
+                                       
+                    } else {
+                       
+                             
+                    }
+                                  
+                    if (i+2 < sz) { //a time delay in the block
+                        
+                        if ((!lineError) && (tokens[i+1].compare("in") == 0) && (isNumber(tokens[i+2]))) {
+                            
+                            currentDelay = atoi(tokens[i+2].data());
+                            if (currentDelay < 0) {
+                               pcPtr->printf("Error: block delay time must be a positive integer\r\n"); 
+                               lineError = true; 
+                            } else if (!ifBlockInit) { //a standalone do block
+                               //tmpEvent = new event(queuePtr);
+                               tmpEvent->isUsed = true;
+                               eventReserved = true;
+                               tmpEvent->setTimeLag(currentDelay);
+                                                             
+                               if ((!elseFlag) && ((!thenFlag))) {
+                                    //tmpEventPtrArray.back()->addAction(new action(tmpEvent));
+                                    tmpAction->set(tmpEvent);
+                                    tmpEventPtrArray.back()->addAction(tmpAction);
+                                    tmpEventPtrArray.push_back(tmpEvent);
+                                    tmpEventPtrArray.back()->blockType = 2; //this is a do block
+                                    blockDepth = blockDepth+1;
+                               } else if (elseFlag) {
+                                    tmpEventPtrArray.back()->setNextElseEvent(tmpEvent);
+                                    tmpEventPtrArray.push_back(tmpEvent);
+                                    tmpEventPtrArray.back()->blockType = 4; //an else block
+                               } else if (thenFlag) {
+                                    
+                                    tmpEventPtrArray.back()->setNextElseEvent(tmpEvent);
+                                    tmpEventPtrArray.push_back(tmpEvent);
+                                    tmpEventPtrArray.back()->blockType = 8; //a then block
+                               }
+                               //pcPtr->printf("Block delay: %d\r\n", tmpEventPtrArray.back()->timeLag); 
+                            } else { //an if block
+                               tmpEventPtrArray.back()->setTimeLag(currentDelay);
+                                                               
+                               if (!elseFlag && !thenFlag) {                 
+                                   if (blockDepth > 1) { //this is a nested block, so add it as an action to the parent block
+                                        tmpAction->set(tmpEventPtrArray.back());
+                                        tmpEventPtrArray.at(tmpEventPtrArray.size()-2)->addAction(tmpAction);
+                                        //tmpEventPtrArray.at(tmpEventPtrArray.size()-2)->addAction(new action(tmpEventPtrArray.back())); 
+                                   }                    
+                               } else if (elseFlag){
+                                   tmpEventPtrArray.at(tmpEventPtrArray.size()-2)->setNextElseEvent(tmpEventPtrArray.back());
+                               } else if (thenFlag){
+                                   tmpEventPtrArray.at(tmpEventPtrArray.size()-2)->setNextElseEvent(tmpEventPtrArray.back());
+                                   
+                               }
+                               //pcPtr->printf("Block delay: %d\r\n", tmpEventPtrArray.back()->timeLag); 
+                               
+                            }
+                            
+                         } else if ((!lineError) && (tokens[i+1].compare("in") == 0) && (findIntVariable(tokens[i+2])!=NULL)) {
+                            
+                            int* delayVar = findIntVariable(tokens[i+2]);
+                            //currentDelay = atoi(tokens[i+2].data());
+                            if (!ifBlockInit) { //a standalone do block
+                               //tmpEvent = new event(queuePtr);
+                               tmpEvent->isUsed = true;
+                               eventReserved = true;
+                               tmpEvent->setTimeLag(delayVar);
+                                                             
+                               if ((!elseFlag) && ((!thenFlag))) {
+                                    //tmpEventPtrArray.back()->addAction(new action(tmpEvent));
+                                    tmpAction->set(tmpEvent);
+                                    tmpEventPtrArray.back()->addAction(tmpAction);
+                                    tmpEventPtrArray.push_back(tmpEvent);
+                                    tmpEventPtrArray.back()->blockType = 2; //this is a do block
+                                    blockDepth = blockDepth+1;
+                               } else if (elseFlag) {
+                                    tmpEventPtrArray.back()->setNextElseEvent(tmpEvent);
+                                    tmpEventPtrArray.push_back(tmpEvent);
+                                    tmpEventPtrArray.back()->blockType = 4; //an else block
+                               } else if (thenFlag) {
+                                    
+                                    tmpEventPtrArray.back()->setNextElseEvent(tmpEvent);
+                                    tmpEventPtrArray.push_back(tmpEvent);
+                                    tmpEventPtrArray.back()->blockType = 8; //a then block
+                               }
+                               //pcPtr->printf("Block delay: %d\r\n", tmpEventPtrArray.back()->timeLag); 
+                            } else { //an if block
+                               tmpEventPtrArray.back()->setTimeLag(delayVar);
+                                                               
+                               if (!elseFlag && !thenFlag) {                 
+                                   if (blockDepth > 1) { //this is a nested block, so add it as an action to the parent block
+                                        tmpAction->set(tmpEventPtrArray.back());
+                                        tmpEventPtrArray.at(tmpEventPtrArray.size()-2)->addAction(tmpAction);
+                                        //tmpEventPtrArray.at(tmpEventPtrArray.size()-2)->addAction(new action(tmpEventPtrArray.back())); 
+                                   }                    
+                               } else if (elseFlag){
+                                   tmpEventPtrArray.at(tmpEventPtrArray.size()-2)->setNextElseEvent(tmpEventPtrArray.back());
+                               } else if (thenFlag){
+                                   tmpEventPtrArray.at(tmpEventPtrArray.size()-2)->setNextElseEvent(tmpEventPtrArray.back());
+                                   
+                               }
+                               //pcPtr->printf("Block delay: %d\r\n", tmpEventPtrArray.back()->timeLag); 
+                               
+                            }
+                            
+                         } else {
+                             pcPtr->printf("Error: block delay time must be a positive integer or a variable\r\n"); 
+                             lineError = true; 
+                         }
+                      } else if (!lineError && !ifBlockInit) { //no time delay given, standalone do
+                         currentDelay = 0;
+                         //tmpEvent = new event(queuePtr);
+                         tmpEvent->isUsed = true;
+                         eventReserved = true;
+                         tmpEvent->setTimeLag(currentDelay);
+                         if (!elseFlag && !thenFlag) {
+                            tmpAction->set(tmpEvent);
+                            tmpEventPtrArray.back()->addAction(tmpAction);
+                            //tmpEventPtrArray.back()->addAction(new action(tmpEvent));                            
+                            tmpEventPtrArray.push_back(tmpEvent);
+                            blockDepth = blockDepth+1;
+                         } else if (elseFlag) {
+                            tmpEventPtrArray.back()->setNextElseEvent(tmpEvent);
+                            tmpEventPtrArray.push_back(tmpEvent);
+                            tmpEventPtrArray.back()->blockType = 4; //an else block
+                         } else if (thenFlag) {
+                            tmpEventPtrArray.back()->setNextElseEvent(tmpEvent);
+                            tmpEventPtrArray.push_back(tmpEvent);
+                            tmpEventPtrArray.back()->blockType = 8; //a then block
+                         }
+                         //pcPtr->printf("Block delay: %d\r\n", tmpEventPtrArray.back()->timeLag); 
+                      } else if (!lineError) { //no time delay, if block
+                         
+                         currentDelay = 0;     
+                         tmpEventPtrArray.back()->setTimeLag(currentDelay);
+                         
+                         
+                         if (!elseFlag && !thenFlag) {
+                             if (blockDepth > 1) {
+                                tmpAction->set(tmpEventPtrArray.back());
+                                tmpEventPtrArray.at(tmpEventPtrArray.size()-2)->addAction(tmpAction);
+                                //tmpEventPtrArray.at(tmpEventPtrArray.size()-2)->addAction(new action(tmpEventPtrArray.back()));
+                             }
+                         } else {
+                             tmpEventPtrArray.at(tmpEventPtrArray.size()-2)->setNextElseEvent(tmpEventPtrArray.back());
+                         }
+                         
+                         
+                         //pcPtr->printf("Block delay: %d\r\n", tmpEventPtrArray.back()->timeLag); 
+                      }
+                      if (lineError && eventReserved) {
+                        tmpEvent->release();
+                      }           
+                      //close block initiation 
+                      ifBlockInit = false;
+                      whileBlockInit = false;
+                      wholeLineEvaluated = true;
+                      elseFlag = false;
+                      thenFlag = false;
+            
+            //callback starts a callback block------------------------------------------
+            //exmaple: callback portin(1) down
+            //              ...
+            //         end
+            } else if (tokens[i].compare("callback") == 0) { //a new callback block 
+                if (ifBlockInit || whileBlockInit || elseFlag) {
+                    pcPtr->printf("Error: expected a 'do' statement\r\n");
+                    lineError = true;
+                }
+                if (blockDepth != 0)  {
+                    pcPtr->printf("Error: Can't declare a callback block within another block\r\n"); 
+                    lineError = true;
+                }
+                if (!lineError) {  
+                    wholeLineEvaluated = true;                               
+                    if (i+2 < sz) {
+                        if ((tokens[i+1].find("portin[") != std::string::npos) && (tokens[i+1].size() > 8) ) { //callback for a digital port 
+                            int pos1 = tokens[i+1].find("portin[")+7;
+                            int pos2 = tokens[i+1].find_first_of("]",pos1);
+                            currentTriggerPort = atoi(tokens[i+1].substr(pos1,pos2-pos1).data());
+                                     
+                            if (currentTriggerPort <= 0) { 
+                                currentTriggerPort = -1;
+                                pcPtr->printf("Error: Not a valid port number\r\n");
+                                lineError = true;
+                            }
+                        } else {
+                            pcPtr->printf("Error: Not a valid callback input\r\n");
+                            lineError = true;
+                        } 
+                        if (tokens[i+2].compare("up") == 0) {
+                            currentTriggerDir = 1;
+                        } else if (tokens[i+2].compare("down") == 0) {
+                            currentTriggerDir = -1;
+                        } else {
+                            pcPtr->printf("Error: No trigger direction given\r\n");
+                            lineError = true;
+                        }
+                                    
+                    } else {
+                        if (!lineError) pcPtr->printf("Error: Not enough arguments for callback statement\r\n");
+                        lineError = true;
+                    } 
+                    if (sz > 3) {
+                        if (!((sz == 4) && (tokens[i+3].compare("do") == 0))) {
+                            pcPtr->printf("Error: Too many arguments in callback statement\r\n");
+                            lineError = true;
+                        }
+                    }
+                    
+                    tmpEvent = findFirstUnUsed(eventBlock, NUMEVENTS);                   
+                    if (tmpEvent != NULL) {                    
+                        tmpEvent->isUsed = true;
+                                             
+                    } else {
+                        pcPtr->printf("Error: no memory slots available.\r\n"); 
+                        lineError = true;
+                    }
+                    if (!lineError) {
+                        //pcPtr->printf("Current port: %d\r\n", currentTriggerPort); 
+                        blockDepth = 1;
+                        i = i+2;
+                        //create new event and attach it to the port
+                        //tmpEventPtrArray.push_back(new event(queuePtr));
+                        tmpEventPtrArray.push_back(tmpEvent);
+                        if (currentTriggerDir == 1) {
+                            
+                            portVector[currentTriggerPort]->setTriggerUpEvent(tmpEventPtrArray.back());
+                        } else {
+                            
+                            portVector[currentTriggerPort]->setTriggerDownEvent(tmpEventPtrArray.back());
+                        }
+                    
+                    }                                             
+                }
+            
+            //if starts an if block----------------------------------------------
+            //examples: if x < 10 && y == 1 do;  if a==1 do in 1000       
+            } else if (tokens[i].compare("if") == 0) { //a new if block
+                if (ifBlockInit || whileBlockInit) {
+                    pcPtr->printf("Error: expected a 'do' statement\r\n");
+                    lineError = true;
+                }
+                
+                ifBlockInit = true;
+                currentDelay = 0;
+                bool eventDefined = false;
+                tmpEvent = findFirstUnUsed(eventBlock, NUMEVENTS);
+                if (tmpEvent != NULL) {                    
+                    tmpEvent->isUsed = true; 
+                    eventDefined = true;                     
+                } else {
+                    pcPtr->printf("Error: no memory slots available.\r\n"); 
+                    lineError = true;
+                }
+                if (!lineError) {
+                    //this is a regular event
+                    //tmpEventPtrArray.push_back(new event(queuePtr)); 
+                    tmpEventPtrArray.push_back(tmpEvent); 
+                    
+                    if ((!elseFlag) && ((!thenFlag))) {
+                        tmpEventPtrArray.back()->blockType = 1; //this is an if block
+                        blockDepth = blockDepth + 1;
+                    } else if (elseFlag) {
+                         tmpEventPtrArray.back()->blockType = 3; //this is an else if block
+                    } else if (thenFlag) {
+                         tmpEventPtrArray.back()->blockType = 7; //this is a then if block
+                    }  
+                }    
+                
+                if (!lineError) {
+                    //combine the condition tokens without whitespaces
+                    tmpString = "";
+                    for (unsigned j = i+1; j < sz; j++) { 
+                        if (tokens[j].compare("do") != 0) {
+                           i++;
+                           tmpString.append(tokens[j]);
+                        } else {                     
+                            break;
+                        }
+                    }
+                    //adds the conditions to the current event
+                    
+                    if (!evaluateConditions(tmpString, tmpEventPtrArray.back())) lineError = true; 
+                }
+                
+                if (lineError && eventDefined) {
+                    tmpEvent->release();
+                } 
+                
+            
+            //else starts an else block-------------------------------------
+            //examples:  else do in 500;  else if x==7 do
+            } else if (tokens[i].compare("else") == 0) { //an else block
+                if (ifBlockInit || whileBlockInit) {
+                    pcPtr->printf("Error: expected a 'do' statement\r\n");
+                    lineError = true;
+                }
+                
+                //trigger blocks can't have else conditions
+                if ((!lineError) && (blockDepth < 2) && (currentTriggerPort > -1)) {
+                    pcPtr->printf("Error: else statement can not occur after a trigger block or outside a block\r\n");
+                    lineError = true;
+                }
+                
+                //check to make sure we are in an 'if' block
+                if ((!lineError) && (tmpEventPtrArray.back()->blockType != 1) && (tmpEventPtrArray.back()->blockType != 3)) { //not currently in an 'if' or 'else if' block
+                    pcPtr->printf("Error: else statement can only occur in an 'if' block\r\n");
+                    lineError = true;
+                }
+                if (!lineError) {
+                    elseFlag = true;
+                
+                }
+            } else if (tokens[i].compare("then") == 0) { //a then block
+                if (ifBlockInit || whileBlockInit) {
+                    pcPtr->printf("Error: expected a 'do' statement\r\n");
+                    lineError = true;
+                }
+                
+                //trigger blocks can't have else conditions
+                if ((!lineError) && (blockDepth < 2) && (currentTriggerPort > -1)) {
+                    pcPtr->printf("Error: 'then' statement can only occur after a 'while' block\r\n");
+                    lineError = true;
+                }
+                
+                //check to make sure we are in a 'while' block
+                if ((!lineError) && (tmpEventPtrArray.back()->blockType != 5)) { //not currently in a while block
+                    pcPtr->printf("Error: 'then' statement can only occur in a 'while' block\r\n");
+                    lineError = true;
+                }
+                if (!lineError) {
+                    thenFlag = true;
+                
+                }            
+            //while starts a while block----------------------------------------
+            //example:  while x<10 do every 100
+            //              ...
+            //          end
+            } else if (tokens[i].compare("while") == 0) { //a new while block
+                if (ifBlockInit || whileBlockInit) {
+                    pcPtr->printf("Error: expected a 'do' statement\r\n");
+                    lineError = true;
+                }
+                
+                if ((currentTriggerPort > 0) || (currentFunction > 0)) { //check to make sure we are inside a trigger block
+                       //pcPtr->printf("Start new block\r\n"); 
+                                
+                } else {
+                      pcPtr->printf("Error: a statement block must be placed inside a callback or function.\r\n"); 
+                      lineError = true;
+                }
+                //whileBlockInit = true;
+                currentDelay = 0;
+                
+                tmpEvent = findFirstUnUsed(eventBlock, NUMEVENTS);
+                if (tmpEvent != NULL) {                    
+                    tmpEvent->isUsed = true;
+                    tmpEvent->setTimeLag(currentDelay); 
+                } else {
+                    pcPtr->printf("Error: no memory slots available.\r\n"); 
+                    lineError = true;
+                }
+                
+                //tmpEvent = new event(queuePtr);
+                
+                                         
+                if (!lineError) {
+                    //combine the condition tokens without whitespaces
+                    tmpString = "";
+                    for (unsigned j = i+1; j < sz; j++) { 
+                        if (tokens[j].compare("do") != 0) {
+                           i++;
+                           tmpString.append(tokens[j]);
+                        } else {                     
+                            break;
+                        }
+                    }
+                    //adds the conditions to the current event
+                    if (!evaluateConditions(tmpString, tmpEvent)) lineError = true; 
+                }
+                
+                if (!lineError) {
+                    if ((i+3) < sz) {
+                        if ((tokens[i+1].compare("do") == 0) && (tokens[i+2].compare("every") == 0)) {
+                            
+                            if (isNumber(tokens[i+3])) {
+                                uint32_t period = atoi(tokens[i+3].data());
+                                if (period > 0) {
+                                    //pcPtr->printf("While block\r\n");
+                            
+                                    //tmpEvent->whileLoopPeriod = period;
+                                    tmpEvent->setWhileLoopPeriod(period);
+                                    if (!elseFlag) {
+                                        tmpEvent->blockType = 5; //this is a while block
+                                     
+                                        action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);
+                                        if (tmpAction == NULL) {
+                                            pcPtr->printf("Error: no memory slots available.\r\n");
+                                            lineError = true;      
+                                        } else {
+                                            tmpAction->set(tmpEvent);
+                                        }
+                                        //tmpEventPtrArray.back()->addAction(new action(tmpEvent));
+                                        tmpEventPtrArray.back()->addAction(tmpAction);
+                                    
+                                        tmpEventPtrArray.push_back(tmpEvent);
+                                        blockDepth = blockDepth+1;
+                                    } else {
+                                        tmpEvent->blockType = 6; //this is an else while block
+                                        tmpEventPtrArray.back()->setNextElseEvent(tmpEvent);
+                                        tmpEventPtrArray.push_back(tmpEvent);
+                                    }
+                                    wholeLineEvaluated = true;
+                                } else {
+                                    pcPtr->printf("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]);  
+                                //tmpEvent->whileLoopPeriodVar = period;
+                                tmpEvent->setWhileLoopPeriod(period);
+                                if (!elseFlag) {
+                                    tmpEvent->blockType = 5; //this is a while block
+                                     
+                                    action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);
+                                    if (tmpAction == NULL) {
+                                        pcPtr->printf("Error: no memory slots available.\r\n");
+                                        lineError = true;      
+                                    } else {
+                                        tmpAction->set(tmpEvent);
+                                    }
+                                    //tmpEventPtrArray.back()->addAction(new action(tmpEvent));
+                                    tmpEventPtrArray.back()->addAction(tmpAction);
+                                    
+                                    tmpEventPtrArray.push_back(tmpEvent);
+                                    blockDepth = blockDepth+1;
+                                } else {
+                                    tmpEvent->blockType = 6; //this is an else while block
+                                    tmpEventPtrArray.back()->setNextElseEvent(tmpEvent);
+                                    tmpEventPtrArray.push_back(tmpEvent);
+                                }
+                                wholeLineEvaluated = true; 
+                            }
+                        } else {
+                            pcPtr->printf("Error: expected a 'do every' statement\r\n");
+                            lineError = true;
+                        }
+                    } else {
+                        pcPtr->printf("Error: expected a 'do every' statement\r\n");
+                        lineError = true;
+                    }
+                }
+            
+            //if the line contains an '=' sign,the equality is evaulated-------------------------
+            //examples:  a = 1;  a = b + 5; a = random(100); portout[2] = 1; portout[2] = flip           
+            } else if ((tmpLine.find_first_of("=") != std::string::npos) ) { //an expression
+                if (ifBlockInit || whileBlockInit || elseFlag) {
+                    pcPtr->printf("Error: expected a 'do' statement\r\n");
+                    lineError = true;
+                }
+                                  
+                wholeLineEvaluated = true;                
+                tmpString = "";
+                int spacesBeforeEqualSign = 0;
+                bool countSpaces = true;
+                //combine the tokens without whitespaces
+                for (unsigned j = i; j < sz; j++) { 
+                    tmpString.append(tokens[j]);
+                    if (tokens[j].find_first_of("=") != std::string::npos) {
+                        if (tokens[j].find_first_of("=") > 0) spacesBeforeEqualSign++;
+                        countSpaces = false;
+                    } else if (countSpaces) {
+                        spacesBeforeEqualSign++;
+                    }   
+                }
+                if (!lineError && spacesBeforeEqualSign > 1) {
+                    pcPtr->printf("Error: Variable can't have a space in it.\r\n");
+                    lineError = true;
+                }
+               
+                if (!lineError) {
+                    if (blockDepth > 0) {
+                        action* tmpAction = evaluateAssignmentForAction(tmpString);
+                        if (tmpAction != NULL) {
+                            tmpEventPtrArray.back()->addAction(tmpAction);
+                            //pcPtr->printf("Added action with delay: %d\r\n", tmpEventPtrArray.back()->timeLag);
+                            
+                        } else {
+                            lineError = true;
+                        }
+                                         
+                    } else { //assignment was written outside of any block structure, so execute now
+                        
+                        
+                        action* tmpAction = evaluateAssignmentForAction(tmpString);
+                        
+                        if (tmpAction != NULL) {
+                            tmpAction->execute();
+                            //delete tmpAction;   
+                            tmpAction->release();                    
+                        } else {                         
+                            lineError = true;
+                        }                                        
+                    }
+                }
+            } else {
+                //if there was no match to any of the above, an error is given
+                pcPtr->printf("Error: statement not understood.\r\n");
+                lineError = true;
+            }
+            
+            if (lineError) break; //stop parsing the rest of the line if an error was detected   
+            
+            if (wholeLineEvaluated) { //some of the tokens forces the whole line to be avaluated at once
+                    i = sz; //skip ahead to end of the line
+            }
+            
+        } 
+        
+        //if there was an error, we quit compiling the code
+        if (lineError) {
+            pcPtr->printf("Line text: ");
+            while (!tokens.empty()) {
+                pcPtr->printf("%s ",tokens.front().data());
+                tokens.erase(tokens.begin());
+            }
+            pcPtr->printf("\r\n"); 
+            while (!currentBlock.empty()) {
+                currentBlock.pop_back();
+            }
+            delete tmpEvent;
+        } else {
+            
+            while (!tokens.empty()) {
+                tokens.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");
+    //displayMemoryLeft();
+    //DisplayRAMBanks();
+        
+}
+
+
+//used to return a pointer to a variable, if it exists
+int* scriptStream::findIntVariable(string nameInput) {
+    
+    int* outPtr = NULL; 
+    bool foundIt = false;
+    
+    if (nameInput.find("portout") != std::string::npos) { 
+        int pos1 = nameInput.find("portout[")+8;
+        int pos2 = nameInput.find_first_of("]",pos1);
+        int portnum = atoi(nameInput.substr(pos1,pos2-pos1).data());
+        int portVal = 0;
+        if ((portnum > 0) && (portnum <= numPorts)) {
+            outPtr = &portVector[portnum]->outState;
+            foundIt = true;
+        }
+    } else if (nameInput.find("portin") != std::string::npos) { 
+        int pos1 = nameInput.find("portin[")+7;
+        int pos2 = nameInput.find_first_of("]",pos1);
+        int portnum = atoi(nameInput.substr(pos1,pos2-pos1).data());
+        int portVal = 0;
+        if ((portnum > 0) && (portnum <= numPorts)) {
+            outPtr = &portVector[portnum]->inState;
+            foundIt = true;
+        }
+    }
+    
+    if (!foundIt) {
+        std::vector<intVariable*>::size_type sz = globalVariables.size();
+        for (unsigned i = 0; i < sz; i++) {
+            if (nameInput.compare(globalVariables[i]->tag) == 0) {
+                outPtr = &globalVariables[i]->value;
+                break;
+            }
+        }
+    }
+      
+    return outPtr;
+}
+
+bool scriptStream::createIntVariable(string nameInput) {
+    if (findIntVariable(nameInput) == NULL) {
+        globalVariables.push_back(new intVariable(nameInput, 0));
+        return true;
+    } else {
+        return false;
+    }
+}
+
+
+action* scriptStream::evaluateAssignmentForAction(string expression) {
+    
+    //action* tmpAction = new action(); //create a new action
+    action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);
+    if (tmpAction == NULL) {
+        pcPtr->printf("Error: no action memory slots available.\r\n");
+        return NULL;
+    }
+    std::size_t stringInd;
+    std::size_t stringInd2;
+    string afterEqual;
+    string beforeEqual;
+    //The expression might have up to three variables
+    int* tmpVar;
+    int* tmpVar2;
+    int* tmpVar3;
+    stringInd = expression.find_first_of("="); //location of = sign, if it exists
+    beforeEqual = expression.substr(0,stringInd); // the string after the = sign
+    afterEqual = expression.substr(stringInd+1,std::string::npos); // the string after the = sign
+    stringInd2 = afterEqual.find_first_of("+-"); //location of +/- sign (only one allowed)
+    tmpVar = findIntVariable(expression.substr(0,stringInd)); //returns pointer to the variable
+    
+    if (beforeEqual.find("portout[") != std::string::npos) { //set the output of a digital port 
+        int pos1 = beforeEqual.find("portout[")+8;
+        int pos2 = beforeEqual.find_first_of("]",pos1);
+        int portnum = atoi(beforeEqual.substr(pos1,pos2-pos1).data());
+        int* tmpVar = findIntVariable(beforeEqual.substr(pos1,pos2-pos1)); //returns pointer to the variable, if given
+        int portVal = 0;
+        if ((tmpVar != NULL)||((portnum > 0) && (portnum <= numPorts))) {
+           if (isNumber(afterEqual)) { //a simple numeric assign
+                portVal = atoi(afterEqual.data());
+                if ((portVal == 0) || (portVal == 1)) {
+                    //portMessage* tmpMessage = new portMessage(portVector[portnum],1,portVal);
+                    portMessage* tmpMessage = findFirstUnUsed(portMessageBlock, NUMPORTMESSAGES);
+                    if (tmpMessage == NULL) {
+                        pcPtr->printf("Error: no memory slots available.\r\n");
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        //tmpMessage->setMessage(portVector[portnum],1,portVal);
+                        if (tmpVar == NULL) { //a constant port number was given
+                            tmpMessage->setMessage(NULL,portnum,portVal);
+                        } else {
+                            tmpMessage->setMessage(tmpVar,0,portVal);
+                        }
+                    }
+                        
+                    
+                    tmpAction->set(tmpMessage);
+                    //pcPtr->printf("Action: digital port %d set to %d\r\n",portnum,portVal);
+                } else {
+                    pcPtr->printf("Error: portouts can only be directly assigned a 1, 0 or 'flip'\r\n");
+                    //delete tmpAction;
+                    tmpAction->release();
+                    return NULL;
+                }
+           } else if (afterEqual.compare("flip") == 0) {
+                //portMessage* tmpMessage = new portMessage(portVector[portnum],1,-1);
+                portMessage* tmpMessage = findFirstUnUsed(portMessageBlock, NUMPORTMESSAGES);
+                if (tmpMessage == NULL) {
+                    pcPtr->printf("Error: no memory slots available.\r\n");
+                    tmpAction->release();
+                    return NULL;
+                } else {
+                    //tmpMessage->setMessage(portVector[portnum],1,-1);
+                    if (tmpVar == NULL) { //a constant port number was given
+                        tmpMessage->setMessage(NULL,portnum,portVal);
+                    } else {
+                        tmpMessage->setMessage(tmpVar,0,portVal);
+                    }               
+                }
+                tmpAction->set(tmpMessage);
+           } else {
+                pcPtr->printf("Error: portouts can only be directly assigned a 1, 0, or 'flip'\r\n");
+                //delete tmpAction;
+                tmpAction->release();
+                return NULL;
+           }
+        } else {
+           pcPtr->printf("Port number not found (must be between 1 and %d, or an existing variable)\r\n", numPorts);
+           //delete tmpAction;
+           tmpAction->release();
+           return NULL;
+        }
+    } else if (beforeEqual.find("portin") != std::string::npos) {
+        pcPtr->printf("Error: portins can not be set\r\n");
+        //delete tmpAction;
+        tmpAction->release();
+        return NULL;
+    } else if (tmpVar != NULL) {
+        intOperation* tmpOp;
+        intOperation* tmpOp2;
+        if (isNumber(afterEqual)) { //a simple numeric assign
+            //tmpOp = new intOperation(tmpVar, "=", atoi(afterEqual.data()));
+            tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+            if (tmpOp == NULL) {
+                pcPtr->printf("Error: no memory slots available.\r\n");
+                tmpAction->release();
+                return NULL;
+            } else {
+                tmpOp->set(tmpVar, "=", atoi(afterEqual.data()));
+            }
+            tmpAction->set(tmpOp);
+            //pcPtr->printf("Action: set variable to constant numeric value\r\n");
+        } else if ((stringInd2 == std::string::npos)&&(afterEqual.find("random") != std::string::npos)) {
+             
+             int highVal = getRandomParam(afterEqual);
+            
+             if (highVal > 0) {
+                //tmpOp = new intOperation(highVal, "=", tmpVar); //for random assignment, we reverse the input order (because of overloading uniqueness)
+                tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                if (tmpOp == NULL) {
+                    pcPtr->printf("Error: no memory slots available.\r\n");
+                    tmpAction->release();
+                    return NULL;
+                } else {
+                    tmpOp->set(highVal, "=", tmpVar); //for random assignment, we reverse the input order (because of overloading uniqueness)
+                }
+                tmpAction->set(tmpOp);
+                //pcPtr->printf("Action: set variable to random value up to %d\r\n", highVal);
+             } else {
+                //delete tmpAction;
+                tmpAction->release();
+                return NULL;
+             }
+             
+        } else if (stringInd2 != std::string::npos) { //a +/- operation is there 
+           string multiplier("+");
+           int multiplierInt = 1;
+           if (afterEqual[stringInd2] == '-') {
+                multiplier = "-";
+                multiplierInt = -1;
+           }
+           tmpVar2 = findIntVariable(afterEqual.substr(0,stringInd2)); //before the +/- sign
+           tmpVar3 = findIntVariable(afterEqual.substr(stringInd2+1,std::string::npos)); //after the +/- sign
+           
+           if ((tmpVar2 != NULL) && isNumber(afterEqual.substr(stringInd2+1,std::string::npos))) { //variable +/- number
+                if (tmpVar2 == tmpVar) {
+                    multiplier.append("="); //final sign is += or -=
+                    //tmpOp = new intOperation(tmpVar, multiplier.data(), atoi(afterEqual.substr(stringInd2+1,std::string::npos).data()));
+                    tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (tmpOp == NULL) {
+                        pcPtr->printf("Error: no memory slots available.\r\n");
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        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");
+                } else {
+                    //tmpOp2 = new intOperation(tmpVar2,multiplier.data(), atoi(afterEqual.substr(stringInd2+1,std::string::npos).data()));
+                    //tmpOp = new intOperation(tmpVar, tmpOp2);
+                    tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if ((tmpOp == NULL)||(tmpOp2 == NULL)) {
+                        pcPtr->printf("Error: no memory slots available.\r\n");
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp2->set(tmpVar2,multiplier.data(), atoi(afterEqual.substr(stringInd2+1,std::string::npos).data()));
+                        tmpOp->set(tmpVar, tmpOp2);
+                    }
+                    tmpAction->set(tmpOp);
+                    //pcPtr->printf("Action: variable equals expression\r\n");
+                }
+                
+           } else if ((tmpVar3 != NULL) && isNumber(afterEqual.substr(0,stringInd2))) { //number +/- variable
+                if (tmpVar3 == tmpVar) {
+                    multiplier.append("=");
+                    //tmpOp = new intOperation(tmpVar, multiplier.data(), atoi(afterEqual.substr(0,stringInd2).data()));
+                    tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (tmpOp == NULL) {
+                        pcPtr->printf("Error: no memory slots available.\r\n");
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp->set(tmpVar, multiplier.data(), atoi(afterEqual.substr(0,stringInd2).data()));
+                    }
+                    tmpAction->set(tmpOp);
+                    //pcPtr->printf("Action: change variable by constant amount\r\n");
+                } else {
+                    //tmpOp2 = new intOperation(tmpVar3, multiplier.data(), atoi(afterEqual.substr(0, stringInd2).data()));
+                    //tmpOp = new intOperation(tmpVar, tmpOp2);
+                    tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if ((tmpOp == NULL)||(tmpOp2 == NULL)) {
+                        pcPtr->printf("Error: no memory slots available.\r\n");
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp2->set(tmpVar3, multiplier.data(), atoi(afterEqual.substr(0, stringInd2).data()));
+                        tmpOp->set(tmpVar, tmpOp2);
+                    }
+                    tmpAction->set(tmpOp);
+                    //pcPtr->printf("Action: variable equals expression\r\n");
+                }
+                
+           } else if ((tmpVar2 != NULL) && (tmpVar3 != NULL)) { //variable +/- variable
+                //tmpOp2 = new intOperation(tmpVar2, multiplier.data(), tmpVar3);
+                //tmpOp = new intOperation(tmpVar, tmpOp2);
+                tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                if ((tmpOp == NULL)||(tmpOp2 == NULL)) {
+                    pcPtr->printf("Error: no memory slots available.\r\n");
+                    tmpAction->release();
+                    return NULL;
+                } else {
+                    tmpOp2->set(tmpVar2, multiplier.data(), tmpVar3);
+                    tmpOp->set(tmpVar, tmpOp2);
+                }
+                tmpAction->set(tmpOp);
+                //pcPtr->printf("Action: set variable to operation involving two variables\r\n");
+                //tmpVar->value = tmpVar2->value + (multiplier * tmpVar3->value);
+           } else if ( isNumber(afterEqual.substr(stringInd2+1,std::string::npos)) && isNumber(afterEqual.substr(0,stringInd2)) ) { //number +/- number
+                //tmpOp = new intOperation(tmpVar, "=", atoi(afterEqual.substr(0,stringInd2).data()) + (multiplierInt * atoi(afterEqual.substr(stringInd2+1,std::string::npos).data())));
+                tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                if (tmpOp == NULL) {
+                    pcPtr->printf("Error: no memory slots available.\r\n");
+                    tmpAction->release();
+                    return NULL;
+                } else {
+                    tmpOp->set(tmpVar, "=", atoi(afterEqual.substr(0,stringInd2).data()) + (multiplierInt * atoi(afterEqual.substr(stringInd2+1,std::string::npos).data())));
+                }
+                tmpAction->set(tmpOp);
+                //pcPtr->printf("Action: set variable to constant numeric value\r\n");
+       
+           } else if ((afterEqual.substr(0,stringInd2).find("random") != std::string::npos) && isNumber(afterEqual.substr(stringInd2+1,std::string::npos))) { //random +/- number
+                int highVal = getRandomParam(afterEqual.substr(0,stringInd2));
+            
+                if (highVal > 0) {
+                    //tmpOp2 = new intOperation(highVal, multiplier.data(), atoi(afterEqual.substr(stringInd2+1,std::string::npos).data()));
+                    //tmpOp = new intOperation(tmpVar, tmpOp2); 
+                    tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if ((tmpOp == NULL)||(tmpOp2 == NULL)) {
+                        pcPtr->printf("Error: no memory slots available.\r\n");
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp2->set(highVal, multiplier.data(), atoi(afterEqual.substr(stringInd2+1,std::string::npos).data()));
+                        tmpOp->set(tmpVar, tmpOp2);
+                    }
+                    tmpAction->set(tmpOp);
+                    //pcPtr->printf("Action: set variable to random value plus number %d\r\n", highVal);
+                } else {
+                    //delete tmpAction;
+                    tmpAction->release();
+                    return NULL;
+                }
+           } else if ((afterEqual.substr(0,stringInd2).find("random") != std::string::npos) && (tmpVar3 != NULL)) { //random +/- variable
+                int highVal = getRandomParam(afterEqual.substr(0,stringInd2));
+            
+                if (highVal > 0) {
+                    //tmpOp2 = new intOperation(highVal, multiplier.data(), tmpVar3);
+                    //tmpOp = new intOperation(tmpVar, tmpOp2); 
+                    tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if ((tmpOp == NULL)||(tmpOp2 == NULL)) {
+                        pcPtr->printf("Error: no memory slots available.\r\n");
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp2->set(highVal, multiplier.data(), tmpVar3);
+                        tmpOp->set(tmpVar, tmpOp2);
+                    }
+                    tmpAction->set(tmpOp);
+                    //pcPtr->printf("Action: set variable to random value plus number %d\r\n", highVal);
+                } else {
+                    //delete tmpAction;
+                    tmpAction->release();
+                    return NULL;
+                }
+           
+           
+           } else if ((afterEqual.substr(stringInd2+1,std::string::npos).find("random") != std::string::npos) && isNumber(afterEqual.substr(0,stringInd2))) { //random +/- number
+                int highVal = getRandomParam(afterEqual.substr(stringInd2+1,std::string::npos));
+            
+                if (highVal > 0) {
+                    //tmpOp2 = new intOperation(highVal, multiplier.data(), atoi(afterEqual.substr(0, stringInd2).data()));
+                    //tmpOp = new intOperation(tmpVar, tmpOp2); 
+                    tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if ((tmpOp == NULL)||(tmpOp2 == NULL)) {
+                        pcPtr->printf("Error: no memory slots available.\r\n");
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp2->set(highVal, multiplier.data(), atoi(afterEqual.substr(0, stringInd2).data()));
+                        tmpOp->set(tmpVar, tmpOp2);
+                    }
+                    tmpAction->set(tmpOp);
+                    //pcPtr->printf("Action: set variable to random value plus number %d\r\n", highVal);
+                } else {
+                    //delete tmpAction;
+                    tmpAction->release();
+                    return NULL;
+                }
+           } else if ((afterEqual.substr(stringInd2+1,std::string::npos).find("random") != std::string::npos) && (tmpVar2 != NULL)) { //random +/- number
+                int highVal = getRandomParam(afterEqual.substr(stringInd2+1,std::string::npos));
+            
+                if (highVal > 0) {
+                    //tmpOp2 = new intOperation(highVal, multiplier.data(), tmpVar2);
+                    //tmpOp = new intOperation(tmpVar, tmpOp2); 
+                    tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if ((tmpOp == NULL)||(tmpOp2 == NULL)) {
+                        pcPtr->printf("Error: no memory slots available.\r\n");
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp2->set(highVal, multiplier.data(), tmpVar2);
+                        tmpOp->set(tmpVar, tmpOp2);
+                    }
+                    tmpAction->set(tmpOp);
+                    //pcPtr->printf("Action: set variable to random value plus number %d\r\n", highVal);
+                } else {
+                    //delete tmpAction;
+                    tmpAction->release();
+                    return NULL;
+                }
+           } else {
+                pcPtr->printf("Expression not understood: %s\r\n",afterEqual.data());
+                //delete tmpAction;
+                tmpAction->release();
+                return NULL;
+           }
+              
+        } else if (findIntVariable(afterEqual) != NULL) { //assign value of another variable
+           //tmpOp = new intOperation(tmpVar, "=", findIntVariable(afterEqual));
+           tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+           if (tmpOp == NULL) {
+               pcPtr->printf("Error: no memory slots available.\r\n");
+               tmpAction->release();
+               return NULL;
+           } else {
+               tmpOp->set(tmpVar, "=", findIntVariable(afterEqual));
+           }
+           tmpAction->set(tmpOp);       
+           //pcPtr->printf("Action: set variable to value of another\r\n");
+        } else {
+           pcPtr->printf("Variable not found: %s\r\n",afterEqual.data());
+           //delete tmpAction;
+           tmpAction->release();
+           return NULL;
+        }
+        
+    } else {
+        pcPtr->printf("Variable not found\r\n");
+        //delete tmpAction;
+        tmpAction->release();
+        return NULL;
+    }
+    return tmpAction;
+}
+
+bool scriptStream::isOutsideParenth(string expression,std::size_t foundItem) {
+       
+    int pDepth = 0;  // How many nested parentheses 
+    //pcPtr->printf("Check outside parentheses...");
+    if (foundItem < expression.length()) {
+        for (int i = 0; i <= foundItem; i++) { 
+            if (expression[i] == '(') {             
+                pDepth++;
+            } else if (expression[i] == ')') {              
+                pDepth--;
+            }
+        }
+        if (pDepth<=0) {
+            //pcPtr->printf("yes.");
+            return true;
+        } else {
+            //pcPtr->printf("no.");
+            return false;
+        }
+    } else {
+        return true;
+    }
+    
+}
+
+std::size_t scriptStream::findFirstOrOutsideParenth(string expression) {
+    
+    std::size_t foundItem = expression.find("||");    
+    while (foundItem != std::string::npos) {   
+        if (isOutsideParenth(expression,foundItem)) {
+            break;
+        }          
+        foundItem = expression.find("||",foundItem+1);
+    }   
+    return foundItem; 
+}
+
+std::size_t scriptStream::findFirstAndOutsideParenth(string expression) {
+    
+    std::size_t foundItem = expression.find("&&");    
+    while (foundItem != std::string::npos) {   
+        if (isOutsideParenth(expression,foundItem)){
+            break;
+        }          
+        foundItem = expression.find("&&",foundItem+1);
+    }   
+    return foundItem; 
+}
+    
+condition* scriptStream::parseConditions(string expression) {
+    //This function is used to parse a condition string
+    //such as (x < y && x != z) || (y == 2)
+    //This function first identifies the root node of the logic tree
+    //based on operator precedence ( () > && > || ), and then recursively calls itself
+    //to find the nodes of the branches. The basic building blocks of 
+    //the final condition object are arithmatic comparitors (a > b) and
+    //other condition objects.
+    
+    
+    //pcPtr->printf("Parsing condition: %s\r\n", expression.data());
+    condition* newCondition = NULL;
+    bool singleCondition = false; //no compound conditions
+    string afterComparator;
+    string beforeComparator;
+       
+    std::size_t found;
+       
+    //To make a parse tree, we start by looking for operators with the lowest precendence
+    //so we look for OR conditions first
+    char currentOperator = OR_CONDITION; 
+    //pcPtr->printf("Looking for OR condition...");
+    found = findFirstOrOutsideParenth(expression);
+    if (found==std::string::npos) { //no or conditions outside parentheses found, so we look for AND conditions
+        currentOperator = AND_CONDITION; 
+        //pcPtr->printf("Looking for AND condition...");
+        found = findFirstAndOutsideParenth(expression);
+    }
+    if (found==std::string::npos) { //no or/and conditions outside parentheses found
+        //if the expression is encapsulated in parentheses, remove the parentheses
+        bool removedParenth = false;
+        if ((expression[0] == '(') && (expression[expression.length()-1] == ')')) {
+            //pcPtr->printf("Remove parentheses");
+            expression = expression.substr(1,expression.length()-2);
+            removedParenth = true;
+        }
+        if (removedParenth) { //we removed parentheses, so try again
+            return parseConditions(expression);
+        } else {
+            singleCondition = true; //we assume that the condition is non-compound, i.e., a>b 
+        }
+    }
+    
+    if (singleCondition) { //no compound conditions found
+        //pcPtr->printf("Single condition");
+        std::size_t equalStringInd;
+        std::size_t greaterOrEqualStringInd;
+        std::size_t lessThanOrEqualStringInd;
+        std::size_t notEqualStringInd;
+        std::size_t greaterThanStringInd;
+        std::size_t lessThanStringInd;
+        std::size_t generalCompareStringInd;
+    
+   
+        string tmpCondition = expression;
+        string compareString;
+        //The expression might have up to three variables 
+        int* tmpVar;
+        int* tmpVar2;
+        int* tmpVar3;
+        
+        int offset = 0;
+        equalStringInd = tmpCondition.find("=="); //location of comparator
+        greaterOrEqualStringInd = tmpCondition.find(">="); //location of comparator
+        lessThanOrEqualStringInd = tmpCondition.find("<="); //location of comparator
+        notEqualStringInd = tmpCondition.find("!="); //location of comparator
+        greaterThanStringInd = tmpCondition.find_first_of(">"); //location of comparator
+        lessThanStringInd = tmpCondition.find_first_of("<"); //location of comparator
+        
+        if ((equalStringInd != std::string::npos) && (greaterOrEqualStringInd == std::string::npos) &&
+           (lessThanOrEqualStringInd == std::string::npos) && (notEqualStringInd == std::string::npos)){
+           
+           generalCompareStringInd = equalStringInd;
+           compareString = "==";
+        } else if ((equalStringInd == std::string::npos) && (greaterOrEqualStringInd != std::string::npos) &&
+           (lessThanOrEqualStringInd == std::string::npos) && (notEqualStringInd == std::string::npos)){
+          
+          generalCompareStringInd = greaterOrEqualStringInd;
+          compareString = ">=";
+        } else if ((equalStringInd == std::string::npos) && (greaterOrEqualStringInd == std::string::npos) &&
+           (lessThanOrEqualStringInd != std::string::npos) && (notEqualStringInd == std::string::npos)){
+          
+          generalCompareStringInd = lessThanOrEqualStringInd;
+          compareString = "<=";
+        } else if ((equalStringInd == std::string::npos) && (greaterOrEqualStringInd == std::string::npos) &&
+           (lessThanOrEqualStringInd == std::string::npos) && (notEqualStringInd != std::string::npos)){
+          
+          generalCompareStringInd = notEqualStringInd;
+          compareString = "!=";
+        } else if ((equalStringInd == std::string::npos) && (greaterOrEqualStringInd == std::string::npos) &&
+           (lessThanOrEqualStringInd == std::string::npos) && (notEqualStringInd == std::string::npos) &&
+           (greaterThanStringInd != std::string::npos) && (lessThanStringInd == std::string::npos)){
+          
+          generalCompareStringInd = greaterThanStringInd;
+          compareString = ">"; 
+          offset = 1;
+        } else if ((equalStringInd == std::string::npos) && (greaterOrEqualStringInd == std::string::npos) &&
+           (lessThanOrEqualStringInd == std::string::npos) && (notEqualStringInd == std::string::npos) &&
+           (greaterThanStringInd == std::string::npos) && (lessThanStringInd != std::string::npos)){
+          
+          generalCompareStringInd = lessThanStringInd;
+          compareString = "<"; 
+          offset = 1;
+        
+        }else {
+          pcPtr->printf("Condition not understood: %s\r\n", expression.data());
+          return 0;
+        }
+        
+        intCompare* newCompare = findFirstUnUsed(intCompareBlock, NUMINTCOMPARE);                   
+        if (newCompare == NULL) {                    
+            pcPtr->printf("Error: No memory slots available.");
+            return NULL;                                     
+        } 
+        newCondition = findFirstUnUsed(conditionBlock, NUMCONDITIONS);                   
+        if (newCondition == NULL) {                    
+            pcPtr->printf("Error: No memory slots available.");
+            return NULL;                                     
+        }  
+        afterComparator = tmpCondition.substr(generalCompareStringInd+2-offset,std::string::npos);
+       
+        beforeComparator = tmpCondition.substr(0,generalCompareStringInd);
+        tmpVar = findIntVariable(beforeComparator); //returns pointer to the variable            
+        if (tmpVar != NULL) { //before the comparator is a single variable
+            tmpVar2 = findIntVariable(afterComparator); //returns pointer to the variable
+            if (tmpVar2 != NULL) { //we are comapring a single variable to another
+                //intCompare* newCompare = new intCompare(tmpVar,compareString.data(),tmpVar2);
+                //currentEvent->addCondition(new condition(newCompare)); 
+                newCompare->set(tmpVar,compareString.data(),tmpVar2);                
+                newCondition->set(newCompare);
+                
+                //pcPtr->printf("Var vs. Var condition added: %s\r\n", tmpCondition.data());
+            } else if (isNumber(afterComparator)) {
+                //intCompare* newCompare = new intCompare(tmpVar,compareString.data(),atoi(afterComparator.data()));
+                //currentEvent->addCondition(new condition(newCompare)); 
+                newCompare->set(tmpVar,compareString.data(),atoi(afterComparator.data()));
+                newCondition->set(newCompare);
+                
+                //pcPtr->printf("Var vs. Int condition added: %s\r\n", tmpCondition.data());
+            } //more here 
+        
+        } else {
+          pcPtr->printf("Condition not understood: %s\r\n", expression.data());
+          
+          return NULL;
+        }
+               
+    } else { //this is a compound condition (with either && or ||)
+        //pcPtr->printf("Compound condition");
+        afterComparator = expression.substr(found+2,std::string::npos);   
+        beforeComparator = expression.substr(0,found);
+        newCondition = findFirstUnUsed(conditionBlock, NUMCONDITIONS);                   
+        if (newCondition == NULL) {                    
+            pcPtr->printf("Error: No memory slots available.");
+            return NULL;                                     
+        } else {
+            newCondition->isUsed = true; //reserve the condition slot;
+        } 
+        //recursively call this function to parse the sub conditions
+        condition* cond1 = parseConditions(beforeComparator);
+        if (cond1 == NULL) {
+            newCondition->release();
+            return NULL;
+        }
+        condition* cond2 = parseConditions(afterComparator);
+        if (cond2 == NULL) {
+            newCondition->release();
+            cond1->release();
+            return NULL;
+        }
+        newCondition->set(cond1,currentOperator, cond2);
+        
+    }
+    
+    return newCondition; //all went well, so return the newly made condition
+    
+}
+
+bool scriptStream::evaluateConditions(string expression, event* currentEvent) {
+    //calls the function to parse the condition string.  The condition pointer is then
+    //attached to the event
+    
+    condition* newCondition = NULL;
+    newCondition = parseConditions(expression);
+    if (newCondition == NULL) {
+        return false;
+    } else {
+        currentEvent->addCondition(newCondition); 
+        return true;
+    }
+}
+
+int scriptStream::getRandomParam(string expression) {
+
+      int pos1 = expression.find("random(")+7;
+      int pos2 = expression.find_first_of(")",pos1);
+      int highVal = atoi(expression.substr(pos1,pos2-pos1).data());
+             
+      if ((highVal > 0)) {
+         return highVal;
+      } else {
+         pcPtr->printf("Error: random parameter must be 1 or more\r\n");
+         return 0;
+      }
+ }  
+ 
+ 
+ outputStream::outputStream(int bufferSizeIn):
+       readHead(0),
+       writeHead(0),
+       totalWriteHead(0),
+       totalReadHead(0),
+       bufferSize(bufferSizeIn),
+       unsentData(false) {
+       
+       outputBuffer = new char[bufferSize];
+ 
+ }
+ 
+ outputStream::~outputStream() {
+    delete[] outputBuffer;
+ }
+ 
+ //adds text to the buffer
+ void outputStream::send(string outputString) {
+    int strLen = outputString.size();
+    
+    int total = 0;
+    int chunk = 0;
+    if (!(totalWriteHead+strLen > (totalReadHead + bufferSize))) {
+        while (strLen - total > 0) {
+            chunk = min((bufferSize - writeHead), strLen - total);
+            outputString.copy(outputBuffer + writeHead, chunk, total);
+            writeHead = (writeHead + chunk) % bufferSize;
+            totalWriteHead += chunk;
+            total += chunk;
+        }
+        if (total > 0) {
+            unsentData = true;
+        }
+    }
+ }
+ 
+ //the main loop gets one character per loop and write it to the serial port 
+ char outputStream::getNextChar() {
+    
+    
+    if (totalReadHead < totalWriteHead) {
+        tmpOut = *(outputBuffer+readHead);
+        readHead = (readHead+1) % bufferSize;
+        totalReadHead++;
+        if (totalReadHead >= totalWriteHead) {
+            unsentData = false;
+        }
+    }
+    return tmpOut;
+    
+ }
+    
\ No newline at end of file