statescriptMP

Dependencies:   SMARTWAV USBDevice mbed

Files at this revision

API Documentation at this revision

Comitter:
alustig3
Date:
Mon May 18 01:18:45 2015 +0000
Commit message:
statescript MP

Changed in this revision

SMARTWAV.lib Show annotated file Show diff for this revision Revisions of this file
USBDevice.lib Show annotated file Show diff for this revision Revisions of this file
behave.cpp Show annotated file Show diff for this revision Revisions of this file
behave.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
soundControl.cpp Show annotated file Show diff for this revision Revisions of this file
soundControl.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 9d97f34c6f46 SMARTWAV.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SMARTWAV.lib	Mon May 18 01:18:45 2015 +0000
@@ -0,0 +1,1 @@
+https://mbed.org/users/emmanuelchio/code/SMARTWAV/#d3cb5755b201
diff -r 000000000000 -r 9d97f34c6f46 USBDevice.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBDevice.lib	Mon May 18 01:18:45 2015 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/USBDevice/#335f2506f422
diff -r 000000000000 -r 9d97f34c6f46 behave.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/behave.cpp	Mon May 18 01:18:45 2015 +0000
@@ -0,0 +1,3733 @@
+#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;
+}
+digitalPort::digitalPort(DigitalOut* DOP):  //ANDY
+    outPin(DOP),
+    outState(0){
+    
+    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.setPlayback(true);//ANDY
+                            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("kaboom") == 0){//MAX ANDY
+            mbed_reset();            
+          }
+            
+            
+            
+            
+             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;
+                        }                                        
+                    }
+                }
+            } 
+            ////ANDY
+//            else if (tokens[i].find("opto(") != std::string::npos) {
+//                wholeLineEvaluated = true;
+//                int pos1 = tmpLine.find("opto(")+5;
+//                int pos2 = tmpLine.find_first_of(")",pos1);
+//                string dispVar = tmpLine.substr(pos1,pos2-pos1);
+//                device.printf(dispVar.c_str());
+//            }
+                
+            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,-1);
+                    } else {
+                        tmpMessage->setMessage(tmpVar,0,-1);
+                    }               
+                }
+                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 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (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);
+                    }
+                    
+                    tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (tmpOp == NULL) {
+                        pcPtr->printf("Error: no memory slots available.\r\n");
+                        tmpOp2->release();
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        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("="); //makes "+=" or "-="
+                    //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 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (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 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    
+                    if (tmpOp == NULL) {
+                        pcPtr->printf("Error: no memory slots available.\r\n");
+                        tmpOp2->release();
+                        tmpAction->release();
+                        return NULL;
+                    } else {                        
+                        tmpOp->set(tmpVar, tmpOp2);
+                    }
+                    tmpAction->set(tmpOp);
+                    //pcPtr->printf("Action: variable equals expression\r\n");
+                }
+                
+           } else if ((tmpVar2 != NULL) && (tmpVar3 != NULL)) { //variable +/- variable
+                              
+                tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                if (tmpOp2 == NULL) {
+                    pcPtr->printf("Error: no memory slots available.\r\n");
+                    tmpAction->release();
+                    return NULL;
+                } else {
+                    tmpOp2->set(tmpVar2, multiplier.data(), tmpVar3);                   
+                }
+                tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                
+                if (tmpOp == NULL) {
+                    pcPtr->printf("Error: no memory slots available.\r\n");
+                    tmpOp2->release();
+                    tmpAction->release();
+                    return NULL;
+                } else {
+                    
+                    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 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (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 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    
+                    if (tmpOp == NULL) {
+                        pcPtr->printf("Error: no memory slots available.\r\n");
+                        tmpOp2->release();
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        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 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (tmpOp2 == NULL) {
+                        pcPtr->printf("Error: no memory slots available.\r\n");
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp2->set(highVal, multiplier.data(), tmpVar3);                     
+                    }
+                    tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);                   
+                    if (tmpOp == NULL) {
+                        pcPtr->printf("Error: no memory slots available.\r\n");
+                        tmpOp2->release();
+                        tmpAction->release();
+                        return NULL;
+                    } else {                       
+                        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 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (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 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);                   
+                    if (tmpOp == NULL) {
+                        pcPtr->printf("Error: no memory slots available.\r\n");
+                        tmpOp2->release();
+                        tmpAction->release();
+                        return NULL;
+                    } else {                      
+                        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 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (tmpOp2 == NULL) {
+                        pcPtr->printf("Error: no memory slots available.\r\n");
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp2->set(highVal, multiplier.data(), tmpVar2);                       
+                    }
+                    tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);                  
+                    if (tmpOp == NULL) {
+                        pcPtr->printf("Error: no memory slots available.\r\n");
+                        tmpOp2->release();
+                        tmpAction->release();
+                        return NULL;
+                    } else {                       
+                        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
diff -r 000000000000 -r 9d97f34c6f46 behave.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/behave.h	Mon May 18 01:18:45 2015 +0000
@@ -0,0 +1,462 @@
+#include "mbed.h"
+#include <stdint.h>
+#include <string.h>
+#include <string>
+#include <vector>
+#include <list>
+#include <deque>
+#include <queue>
+#include "soundControl.h"
+
+
+#define NUMEVENTS 50
+#define NUMCONDITIONS 150
+#define NUMINTCOMPARE 150
+#define NUMACTIONS 150
+#define NUMPORTMESSAGES 150
+#define NUMINTOPERATIONS 150
+#define NUMDISPLAYACTIONS 30
+
+#define ARITHMATIC_CONDITION    0
+#define OR_CONDITION    1
+#define AND_CONDITION    2
+
+#define NUMPORTS 10
+
+extern "C" void mbed_reset();//MAX and ANDY
+class event; //we foreward declare this because of class interdependencies
+
+//used in the digital port class to organize digital change events
+struct changeEvent {
+    uint32_t timeStamp;
+    bool triggered;
+};
+
+//The digitalPort object directly controls and keeps data about the port. Each port has
+//one digital out and one digital in.
+class digitalPort {
+public:
+    digitalPort(DigitalOut* DOP, DigitalIn* DIP);
+    digitalPort(DigitalOut* DOP);
+    void setDigitalOut(int outVal);
+    //int  getDigitalOut();
+    int  getDigitalIn();
+    int getLastChangeState();
+    uint32_t getTimeSinceLastChange();
+    uint32_t lastChangeTime;
+    uint32_t lastOutChangeTime;
+    
+    void setTriggerUpEvent(event* eventInput); //attahces a routine to an upward change
+    void setTriggerDownEvent(event* eventInput); //attahces a routine to a downward change
+    void addStateChange(int newState, uint32_t timeStamp);
+    
+    bool update(); //called from the main loop
+    
+    int inState;
+    int outState;
+    
+    bool outStateChanged;
+   
+    event* triggerUpEventPtr;
+    event* triggerDownEventPtr;
+
+private:
+
+    DigitalOut* outPin;
+    DigitalIn*  inPin;
+    int lastInState;
+    uint32_t lastChangeInterval;
+    
+    changeEvent lastUpEvent;
+    changeEvent lastDownEvent; 
+};
+
+
+//an intVariable contains an integer value and the name of that variable within the script
+class intVariable {
+
+public:
+    intVariable();
+    intVariable(string tagInput, int initialValue); 
+    void set(string tagInput, int initialValue);
+    int value;
+    string tag;
+    bool isUsed;
+      
+};
+
+
+//ACTION SECTION-- an 'action' is a command in the script. It can be a single command, 
+//or a block containing a set of actions
+//------------------------------------------------------------------------------------
+
+//display actions are used to output text messages via the serial port.  The user can display 
+//either a static text string or the value of a single variable. 
+class displayAction {
+
+public:
+    displayAction();
+    displayAction(int* variable, string varNameInput, Serial* pcPtrInput);
+    displayAction(string text, Serial* pcPtrInput);
+    void set(int* variable, string varNameInput, Serial* pcPtrInput);
+    void set(string text, Serial* pcPtrInput);
+    bool isUsed;
+    void execute();
+    void release();
+
+private:
+    int* dVariable;
+    string dText;
+    Serial* pcPtr;
+};
+
+//intOpertaion is an action that does addition or subtraction of integers and returns/stores the result
+//these operation are very limited so far (only + or - allowed, and only one operation per object, 
+//for example a = b + b works but a = b + c + d does not. The output value can also be set to a random number.
+class intOperation {
+
+public:
+    intOperation();
+    intOperation(int randParam, const char* cmpString, int cmpValInput);
+    intOperation(int randParam, const char* cmpString, int* cmpIntVarInput);
+    intOperation(int* intVarInput, const char* cmpString, int cmpValInput);
+    intOperation(int* intVarInput, const char* cmpString, int* cmpIntVarInput);
+    intOperation(int* intVarInput, intOperation* operationInput);
+    
+    ~intOperation();
+    
+    void set(int randParam, const char* cmpString, int cmpValInput);
+    void set(int randParam, const char* cmpString, int* cmpIntVarInput);
+    void set(int* intVarInput, const char* cmpString, int cmpValInput);
+    void set(int* intVarInput, const char* cmpString, int* cmpIntVarInput);
+    void set(int* intVarInput, intOperation* operationInput);
+    void release();
+    bool isUsed;
+    int execute();
+    
+private:
+    int randHigh;
+    int* cmpVal;
+    int* intVal;
+    intOperation* opPtr;
+    bool cmpValGlobal;
+    int (intOperation::*executePtr)();
+    int addAndStore();
+    int subtractAndStore();
+    int add();
+    int subtract();
+    int equals();
+    
+};
+
+//portMessage is an action to change a digital port.  So far, You can only change the digital out (0 or 1) 
+class portMessage {
+public:
+
+    portMessage();
+    //portMessage(digitalPort* portIn, int whichToSet, int value); //whichToSet: 1 DigitalOut; 2 State
+    //void setMessage(digitalPort* portIn, int whichToSet, int value); //whichToSet: 1 DigitalOut; 2 State
+    portMessage(int* portIn, int whichToSet, int value); //whichToSet: 
+    void setMessage(int* portIn, int whichToSet, int value); //whichToSet: 
+
+    void execute();
+    void release();
+    bool isUsed;
+
+private:
+    int whichToSet; //hard coded port number
+    int* port; //alternative variable port number
+    int value;
+    //digitalPort* port;
+
+};
+
+//holder class for all possible actions. This include general system commands.
+class action {
+public:
+    
+    action();
+    ~action();
+    action(intOperation* opInput);
+    action(portMessage* messageInput);
+    action(event* eventInput);
+    //action(event* eventInput, uint32_t delay);
+    action(displayAction* displayInput);
+    action(soundControl* soundInput);
+    action(int8_t sysCommandInput); //for general system commands 
+       
+    void set(intOperation* opInput);
+    void set(portMessage* messageInput);
+    void set(event* eventInput);
+    //void set(event* eventInput, uint32_t delay);
+    
+    void set(displayAction* displayInput);
+    void set(soundControl* soundInput);
+    void set(int8_t sysCommandInput);
+    void execute();
+    void execute(uint32_t blockExecTime);
+    void release();
+    bool isUsed;
+        
+private:
+    intOperation* op;
+    portMessage* message;
+    event* eventToCreate;
+    displayAction* displayActionPtr;
+    soundControl* sound;
+    //uint32_t eventDelay;
+    int8_t sysCommand;   
+    char actionType;
+    
+};
+//-----------------------------------------------------
+
+//CONDITION SECTION-- a 'condition' is used in the beginning of a block (if-else blocks or while blocks)
+//If the condition is true, the block is exectuted during a callback 
+//------------------------------------------------------------------------------------
+
+
+//intCompare is a condition class that compares the state value of a port or 
+//an integer variable to another integer variable or operation output
+class intCompare {
+
+public:
+    intCompare();
+    intCompare(digitalPort* portInput, const char* cmpString, int cmpValInput, int whichToUse);
+    intCompare(digitalPort* portInput, const char* cmpString, int* cmpIntVarInput, int whichToUse);
+    intCompare(int* intVarInput, const char* cmpString, int cmpValInput);
+    intCompare(int* intVarInput, const char* cmpString, int* cmpIntVarInput);
+    intCompare(int* intVarInput, const char* cmpString, intOperation* cmpIntOpInput);
+    intCompare(digitalPort* portInput, const char* cmpString, intOperation* cmpIntOpInput, int whichToUse);
+    
+    void set(digitalPort* portInput, const char* cmpString, int cmpValInput, int whichToUse);
+    void set(digitalPort* portInput, const char* cmpString, int* cmpIntVarInput, int whichToUse);
+    void set(int* intVarInput, const char* cmpString, int cmpValInput);
+    void set(int* intVarInput, const char* cmpString, int* cmpIntVarInput);
+    void set(int* intVarInput, const char* cmpString, intOperation* cmpIntOpInput);
+    void set(digitalPort* portInput, const char* cmpString, intOperation* cmpIntOpInput, int whichToUse);
+    
+    void release();
+    
+    ~intCompare();
+    bool isTrue();
+    bool isUsed;
+    
+private:
+    digitalPort* port;
+    int* portValPtr;
+    int* cmpVal;
+    int* intVal;
+    intOperation* intOp;
+    void setPointer(const char* cmpString);
+    void setPointer_operation(const char* cmpString);
+    bool (intCompare::*isTruePtr)();
+    bool cmpValGlobal;
+    bool greaterThan();
+    bool greaterOrEqual();
+    bool lessThan();
+    bool lessOrEqual();
+    bool equal();
+    bool notEqual();
+    bool greaterThan_op();
+    bool greaterOrEqual_op();
+    bool lessThan_op();
+    bool lessOrEqual_op();
+    bool equal_op();
+    bool notEqual_op();
+};
+
+
+//holder class for all possible conditions (so far only intCompare)
+class condition {
+public:
+    
+    condition();
+    condition(intCompare* compareInput);
+    condition(condition* condition1, char condType, condition* condition2);
+    ~condition();
+    void set(intCompare* compareInput);
+    void set(condition* condition1, char condType, condition* condition2);
+    bool isTrue();
+    bool isUsed;
+    void release(); //called when the event is no longer being used;
+private:
+
+    //char conditionType; //1 for intCompare
+    intCompare* intCmp;
+    condition*  conditionPtrs[2];
+    char        conditionType;
+    
+       
+};
+//--------------------------------------------
+
+
+//queueItem connects a pre-defined event with an exectution time.
+//They are placed in the eventQueue
+struct queueItem {
+    uint32_t timeToExecute;
+    event* eventPtr;
+};
+
+
+//Organizes events in a temporal queue.  check() is called from the main loop. 
+//If the execution time of the event has passed, then the event is exectuted.
+class eventQueue {
+public:
+    eventQueue(digitalPort** portVectorInput, uint32_t* timeKeeperSlaveInput);
+    void addEventToQueue(event* eventInput, uint32_t delay);
+    void eraseQueue(); //clear all future events
+    void check(void);
+         
+private:
+    std::vector<queueItem> events;
+    digitalPort** portVector;
+    uint32_t* timeKeeperPtr;
+    int queueSize; 
+    
+};
+
+//An 'event' is a block of 'actions' that can be gated with a boolean 'condition' set. All 
+//conditions in the set must be true for the block of actions to be executed. Right now, 
+//there is no OR logic (||), only AND (&&).
+//The entire event is placed on the event queue to be executed at a given delay.  
+//At that future time, the condition is checked and if true, the block of actions
+//is exectuted. Note: an 'action' can be another event (or even the parent event), allowing
+//nested 'if' and 'while' statements.
+class event {
+public:
+    
+    event();
+    event(eventQueue* queueInput);
+    ~event();
+    void setTimeLag(uint32_t timeLagInput); //the event will be exectuted at this time from now
+    void setTimeLag(int* timeLagInput); //the event will be exectuted at this time from now
+    void setWhileLoopPeriod(uint32_t period);
+    void setWhileLoopPeriod(int* period);
+    void addCondition(condition* conditionInput); //contains a set of conditions to check and a truth table
+    bool isConditionTrue(void); //checks if the condition is true
+    void addAction(action* actionInput); //called during script parsing, when the block is being defined
+    void addToQueue(void); //places the event on the event queue with default time lag.  When the time
+    //lag has expired, the the block is executed
+    void addToQueue(uint32_t delay);
+    void execute(void); //Execute without checking the condition. Called only from the event queue 
+    void setNextElseEvent(event* eventInput); //allows for else event block
+    uint32_t timeLag; //default time from now when the event will be executed (this is ignored once placed in event queue)
+    int* timeLagVar; //exectution time lab defined by a variable
+    eventQueue* queuePtr;
+    void release(); //called when the event is no longer being used;
+    
+    char blockType;  //0 callback
+                    //1 if ... do block (with conditions)
+                    //2 do block (no conditions)
+                    //3 else if ... do block
+                    //4 else do (no conditions)
+                    //5 while ... do every ... block
+                    //6 else while ... do every ... block
+                    //7 then if ... do block
+                    //8 then do (no conditions)
+   
+    uint32_t whileLoopPeriod; //if non-zero, the block is a while loop (executed at regular intervals)
+    int* whileLoopPeriodVar;
+    event* nextElseEventPtr;
+    bool isUsed;
+    bool timeLagIsConstant;
+    bool whileLoopPeriodIsConstant;
+    bool hasWhileLoop;
+    
+private:
+    int numConditions;
+    int numActions;
+    condition* conditionToCheck; 
+    action* actionArray[20]; 
+    
+    //if statement (can be left empty, which is interpreted as 'true')
+    //std::vector<condition*> conditionArray;
+    //std::deque<action*> actionArray; 
+      
+};
+
+//each functionItem help a poiter to an action, and the name of the function
+class functionItem {
+public:
+    functionItem(action* actionInput, string tagInput);
+    ~functionItem();
+    string tag;
+    action* actionPtr;
+};
+
+//Parser for the incoming text.  The parser is called when a line terminates with a semicolon (;).
+//Only the final line in a callback block should have a semicolon.  
+class scriptStream {
+public:
+    scriptStream(Serial* serialInput, digitalPort** portVectorInput, int numPortsInput, eventQueue* queueInput);
+    void parseBlock();
+    void addLineToCurrentBlock(char* lineInput); // if the line did not end with a semicolon, add it to the current block
+    int* findIntVariable(string nameInput); //used to retrieve the pointer to the designated variable if it exists
+    bool createIntVariable(string nameInput); // creates a new interger variable
+    action* evaluateAssignmentForAction(string expression); //parses a numerical assignment or operation (a = b - c)
+    bool evaluateConditions(string expression, event* currentEvent); //parses a condition statement (a == b && c > d)
+    condition* parseConditions(string expression); //parses a condition statement (a == b && c > d)
+    std::size_t findFirstOrOutsideParenth(string expression);
+    std::size_t findFirstAndOutsideParenth(string expression);
+    bool isOutsideParenth(string expression,std::size_t foundItem);
+    
+    int getRandomParam(string expression);
+    
+private:
+
+    int currentTriggerPort;
+    int currentTriggerDir;
+    int currentPort;
+    int currentFunction;
+    
+    string tmpLine; 
+    vector<string> tokens;
+    
+    bool lineError;
+    int blockDepth;
+    bool ifBlockInit;
+    bool whileBlockInit;
+    bool elseFlag;
+    bool thenFlag;
+    int currentDelay;
+    event* tmpEvent;
+    string tmpString;
+    
+    vector<intVariable*> globalVariables;
+    vector<event*> tmpEventPtrArray;
+    vector<functionItem*> functionArray; //any blocks declared outsite callback blocks are stored here
+    list<string> currentBlock;
+    digitalPort** portVector;
+    
+    
+    int numPorts;
+    Serial* pcPtr;
+    eventQueue* queuePtr;
+
+};
+
+
+//Used to buffer output text. Used mainly for 'display' commands within the script,
+//and alloed the reset of the block to execute quickly instead.  The text is then streamed out
+//slowly via serial (one character per main loop execution). outputStream is a simple circular 
+//buffer that cannot be resized after initiation.  
+class outputStream {
+
+public:
+    outputStream(int bufferSizeIn);
+    ~outputStream();
+    void send(string outputString);
+    char getNextChar();
+    bool unsentData;
+
+private:
+    int readHead;
+    int writeHead;
+    int totalWriteHead;
+    int totalReadHead;
+    int bufferSize;
+    char tmpOut;
+    char* outputBuffer;
+};
\ No newline at end of file
diff -r 000000000000 -r 9d97f34c6f46 main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Mon May 18 01:18:45 2015 +0000
@@ -0,0 +1,513 @@
+#include "mbed.h"
+#include <stdint.h>
+#include "behave.h"
+#include <string.h>
+#include <sstream>
+#include "SMARTWAV.h"
+#include "USBSerial.h"
+
+
+uint32_t timeKeeper; //the main clock (updated every ms) 
+bool resetTimer = false; //if true, the clock is reset 
+bool clockSlave = false; //slave mode
+bool changeToSlave = false;
+bool changeToStandAlone = false;
+
+//static char buf1[0x2000] __attribute__((section("AHBSRAM0")));
+__attribute((section("AHBSRAM0"),aligned)) outputStream textDisplay(512);
+__attribute((section("AHBSRAM0"),aligned)) char buffer[128];
+
+
+__attribute((section("AHBSRAM1"),aligned)) event eventBlock[NUMEVENTS];
+
+__attribute((section("AHBSRAM1"),aligned)) condition conditionBlock[NUMCONDITIONS];
+
+__attribute((section("AHBSRAM1"),aligned)) intCompare intCompareBlock[NUMINTCOMPARE];
+
+__attribute((section("AHBSRAM0"),aligned)) action actionBlock[NUMACTIONS];
+
+__attribute((section("AHBSRAM0"),aligned)) portMessage portMessageBlock[NUMPORTMESSAGES];
+
+//__attribute((section("AHBSRAM1"),aligned)) intVariable intVariableBlock[10];
+
+__attribute((section("AHBSRAM0"),aligned)) intOperation intOperationBlock[NUMINTOPERATIONS];
+
+__attribute((section("AHBSRAM0"),aligned)) displayAction displayActionBlock[NUMDISPLAYACTIONS];
+
+
+
+Ticker clockBroadCast; //timer used when sending out timestamps on a GPIO
+uint32_t currentBroadcastTime;
+int currentBroadcastBit = 0;
+bool broadcastHigh = false;
+
+int currentDIOstate[2] = {0,0}; //the first number is a bit-wise representaion of the digital inputs, the 2nd is for the outputs 
+bool digitalInChanged = false;
+bool digitalOutChanged = false;
+bool broadCastStateChanges = true;
+bool textStreaming = true;
+uint32_t changeTime;
+
+LocalFileSystem local("local");  
+
+digitalPort* portVector[NUMPORTS+1]; //create the digital ports
+
+float brightness = 0.0;
+
+//Define the digial ports
+
+//Pins for clock syncing
+//InterruptIn clockResetInt(p24);
+DigitalOut clockOutSync(p19);
+DigitalOut clockOutSignal(p29);
+InterruptIn clockExternalIncrement(p30);
+
+
+//Pins for digital ports.  Each port has 1 out and 1 in
+//DigitalOut out1(LED1); //route to LED for debugging
+//1A,1B
+DigitalOut out1(p5);
+DigitalIn in1(p6);
+InterruptIn int1(p6);
+__attribute((section("AHBSRAM0"),aligned)) digitalPort port1(&out1, &in1);
+//1C,1D
+DigitalOut out2(p7);
+DigitalIn in2(p8);
+InterruptIn int2(p8);
+__attribute((section("AHBSRAM0"),aligned)) digitalPort port2(&out2, &in2);
+//2A,2B
+DigitalOut out3(p17);
+DigitalIn in3(p18);
+InterruptIn int3(p18);
+__attribute((section("AHBSRAM0"),aligned)) digitalPort port3(&out3, &in3);
+//2C,2D
+DigitalOut out4(p11);
+DigitalIn in4(p12);
+InterruptIn int4(p12);
+__attribute((section("AHBSRAM0"),aligned)) digitalPort port4(&out4, &in4);
+//3A,3B
+DigitalOut out5(p21);
+DigitalIn in5(p22);
+InterruptIn int5(p22);
+__attribute((section("AHBSRAM0"),aligned)) digitalPort port5(&out5, &in5);
+//3C,3D
+DigitalOut out6(p15);
+DigitalIn in6(p16);
+InterruptIn int6(p16);
+__attribute((section("AHBSRAM0"),aligned)) digitalPort port6(&out6, &in6);
+//4A,4B
+DigitalOut out7(p9);
+DigitalIn in7(p10);
+InterruptIn int7(p10);
+__attribute((section("AHBSRAM0"),aligned)) digitalPort port7(&out7, &in7);
+//5A,5B
+DigitalOut out8(p13);
+DigitalIn in8(p14);
+InterruptIn int8(p14);
+__attribute((section("AHBSRAM0"),aligned)) digitalPort port8(&out8, &in8);
+//6A,6B
+DigitalOut out9(p23);
+DigitalIn in9(p24);
+InterruptIn int9(p24);
+__attribute((section("AHBSRAM0"),aligned)) digitalPort port9(&out9, &in9);
+//Pump1
+DigitalOut out10(p25);
+__attribute((section("AHBSRAM0"),aligned)) digitalPort port10(&out10);
+//Pump2
+DigitalOut out11(p26);
+__attribute((section("AHBSRAM0"),aligned)) digitalPort port11(&out11);
+
+
+
+//Serial communication
+Serial pc(USBTX, USBRX); // tx, rx
+//USBSerial pc;
+
+
+//Main event queue
+eventQueue mainQueue(portVector, &timeKeeper);
+
+//The script parser 
+scriptStream parser(&pc, portVector, NUMPORTS, &mainQueue);
+
+//The sound output uses a SmartWav device and their simple serial library
+SMARTWAV sWav(p28,p27,p20);    //(TX,RX,Reset);
+//Serial device(p9,p10);
+//Erases the input buffer for serial input
+void eraseBuffer(char* buffer,int numToErase) {
+    for (int i = 0; i < numToErase; i++) {
+        buffer[i] = NULL;
+    }
+}
+
+
+//Called by clockBroadCast timer to output a 32-bit timestamp.  When the timestmap has been
+//sent, the function is detached from the timer.
+void broadcastNextBit() {
+       
+    if (currentBroadcastBit < 32) {
+        broadcastHigh = !broadcastHigh; //flip the sync signal
+        if (broadcastHigh) {
+            clockOutSync = 1;
+            clockOutSignal = (currentBroadcastTime & ( 1 << currentBroadcastBit)) >> currentBroadcastBit;
+            
+        } else {
+            clockOutSync = 0;
+            clockOutSignal = 0;
+            currentBroadcastBit++;
+        }
+    }
+}
+
+
+//intiatiation of timer2 (specific to the LPC17xx chip). This is used in 
+//standalone mode to increment the clock every ms.
+//we use lower-lever code here to get better control over the timer if we reset it
+void timer0_init(void)
+{
+    //LPC_SC->PCLKSEL1 &= (3 << 12); //mask
+    //LPC_SC->PCLKSEL1 |= (1 << 12); //sets it to 1*SystemCoreClock - table 42 (page 57 in user manual)
+    
+    //LPC_SC->PCLKSEL0 &= (3 << 3); //mask
+    //LPC_SC->PCLKSEL0 |= (1 << 3); //sets it to 1*SystemCoreClock - table 42 (page 57 in user manual)
+    LPC_SC->PCONP |=1<1;            //timer0 power on
+    LPC_TIM0->MR0 = 23980;        //1 msec
+    //LPC_TIM0->PR  = (SystemCoreClock / 1000000); //microsecond steps
+    //LPC_TIM0->MR0 = 1000;        //100 msec
+    //LPC_TIM0->MR0  = (SystemCoreClock / 1000000); //microsecond steps
+    LPC_TIM0->MCR = 3;              //interrupt and reset control
+                                    //3 = Interrupt & reset timer0 on match
+                                    //1 = Interrupt only, no reset of timer0
+    NVIC_EnableIRQ(TIMER0_IRQn);    //enable timer0 interrupt
+    LPC_TIM0->TCR = 1;              //enable Timer0
+    
+    
+    /*
+    LPC_SC->PCONP |= (0x1<<22);     // turn on power for timer 2
+    LPC_TIM2->TCR = 0x02;           // reset timer
+    LPC_TIM2->PR  = (SystemCoreClock / 1000000); //microsecond steps
+    LPC_TIM2->MR0 = 1000;            // 1000 microsecond interval interrupts
+    LPC_TIM2->IR  = 0x3f;           // reset all interrrupts
+    LPC_TIM2->MCR = 0x03;           // reset timer on match and generate interrupt (MR0)
+    LPC_TIM2->TCR = 0x01;           // start timer
+    
+    NVIC_EnableIRQ(TIMER2_IRQn); // Enable the interrupt
+    */
+    //pc.printf("Done timer_init\n\r");
+}
+
+//This is the callback for timer2
+extern "C" void TIMER0_IRQHandler (void) {
+
+    if((LPC_TIM0->IR & 0x01) == 0x01) {  // if MR0 interrupt, proceed
+    
+        LPC_TIM0->IR |= 1 << 0;         // Clear MR0 interrupt flag
+        timeKeeper++;
+        
+        if (resetTimer) {
+            timeKeeper = 0;
+            resetTimer = false; 
+        }
+       
+        if (currentBroadcastBit > 31) {
+            clockBroadCast.detach();
+            currentBroadcastBit = 0;
+        }
+    
+        //Every second, we broadcast out the current time 
+        if ((timeKeeper % 1000) == 0) {
+            currentBroadcastTime = timeKeeper;
+            clockOutSync = 1;
+        
+            currentBroadcastBit = 0;
+     
+            clockOutSignal = (currentBroadcastTime & ( 1 << currentBroadcastBit)) >> currentBroadcastBit;
+            broadcastHigh = true;
+            clockBroadCast.attach_us(&broadcastNextBit, 1000);
+        }               
+    }
+}
+
+
+//In slave mode, the clock is updated with an external trigger every ms.  No need for
+//100us resolution.
+void callback_clockExternalIncrement(void) {
+    
+    timeKeeper++;
+       
+    if (resetTimer) {
+        timeKeeper = 0;
+        resetTimer = false; 
+    }
+      
+    if (currentBroadcastBit > 31) {
+        clockBroadCast.detach();
+        currentBroadcastBit = 0;
+    }
+    
+    //Every second, we broadcast out the current time 
+    if ((timeKeeper % 1000) == 0) {
+        currentBroadcastTime = timeKeeper;
+        clockOutSync = 1;
+        
+        currentBroadcastBit = 0;
+     
+        clockOutSignal = (currentBroadcastTime & ( 1 << currentBroadcastBit)) >> currentBroadcastBit;
+        broadcastHigh = true;
+        clockBroadCast.attach_us(&broadcastNextBit, 1000);
+    }
+}
+
+//Every digital port's in pin has a hardware interrupt.  We use a callback stub for each port
+//that routes the int_callback.
+void int_callback(int portNum, int direction) {
+    portVector[portNum]->addStateChange(direction, timeKeeper);   
+}
+
+//Callback stubs
+void callback_port1_rise(void) { int_callback(1, 1); }
+void callback_port1_fall(void) { int_callback(1, 0); }
+void callback_port2_rise(void) { int_callback(2, 1); }
+void callback_port2_fall(void) { int_callback(2, 0); }
+void callback_port3_rise(void) { int_callback(3, 1); }
+void callback_port3_fall(void) { int_callback(3, 0); }
+void callback_port4_rise(void) { int_callback(4, 1); }
+void callback_port4_fall(void) { int_callback(4, 0); }
+void callback_port5_rise(void) { int_callback(5, 1); }
+void callback_port5_fall(void) { int_callback(5, 0); }
+void callback_port6_rise(void) { int_callback(6, 1); }
+void callback_port6_fall(void) { int_callback(6, 0); }
+void callback_port7_rise(void) { int_callback(7, 1); }
+void callback_port7_fall(void) { int_callback(7, 0); }
+void callback_port8_rise(void) { int_callback(8, 1); }
+void callback_port8_fall(void) { int_callback(8, 0); }
+void callback_port9_rise(void) { int_callback(9, 1); }
+void callback_port9_fall(void) { int_callback(9, 0); }
+
+
+//This function is attached to an interrupt pin for external clock reset
+void callback_clockReset(void) {
+    if (timeKeeper > 100) {
+        LPC_TIM2->TCR = 0x02;    // reset timer
+        timeKeeper = 0;
+        pc.printf("%d Clock reset\r\n", timeKeeper);
+    }      
+}
+
+
+int main() {
+    timeKeeper = 0; //set main clock to 0;
+    sWav.reset(); 
+    pc.baud(115200);
+//    device.baud(4800);
+    //pc.baud(9600);
+   
+    for (int i = 0; i <NUMPORTS+1; i++) {
+        portVector[i] = NULL;
+    }
+    //We keep portVector 1-based to eliminate confusion
+    portVector[1] = &port1;
+    portVector[2] = &port2;
+    portVector[3] = &port3;
+    portVector[4] = &port4;
+    portVector[5] = &port5;
+    portVector[6] = &port6;
+    portVector[7] = &port7;
+    portVector[8] = &port8;
+    portVector[9] = &port9;
+    portVector[10] = &port10;
+    portVector[11] = &port11;  
+   
+    //Callback to update the main clock 
+    //timeTick1.attach_us(&incrementTime, 100);
+    
+    timer0_init();
+    
+    
+    //Set up callbacks for the port interrupts   
+    int1.rise(&callback_port1_rise);
+    int1.fall(&callback_port1_fall);
+    int2.rise(&callback_port2_rise);
+    int2.fall(&callback_port2_fall);
+    int3.rise(&callback_port3_rise);
+    int3.fall(&callback_port3_fall);
+    int4.rise(&callback_port4_rise);
+    int4.fall(&callback_port4_fall);
+    int5.rise(&callback_port5_rise);
+    int5.fall(&callback_port5_fall);
+    int6.rise(&callback_port6_rise);
+    int6.fall(&callback_port6_fall);
+    int7.rise(&callback_port7_rise);
+    int7.fall(&callback_port7_fall);
+    int8.rise(&callback_port8_rise);
+    int8.fall(&callback_port8_fall);
+    int9.rise(&callback_port9_rise);
+    int9.fall(&callback_port9_fall);
+    
+    //clockResetInt.rise(&callback_clockReset);
+    //clockResetInt.mode(PullDown);
+    
+    clockExternalIncrement.mode(PullDown);
+      
+    //The inputs are set for pull-up mode (might need to change this)
+    in1.mode(PullDown);
+    in2.mode(PullDown);
+    in3.mode(PullDown);
+    in4.mode(PullDown);
+    in5.mode(PullDown);
+    in6.mode(PullDown);
+    in7.mode(PullDown);
+    in8.mode(PullDown);
+    in9.mode(PullDown);
+     
+    //Set up input buffer for the serial port
+    //char buffer[128];
+    int bufferPos = 0;
+    eraseBuffer(buffer,128);
+    
+    ostringstream timeConvert;   // stream used for the conversion
+    ostringstream stateConvert; 
+    char junkChar;
+    int tmpChar;
+    
+    //while (pc.readable()) {
+    while (pc.readable()) {
+        junkChar = pc.getc();
+    }   
+         
+    FILE *fp = fopen("/local/STARTUP.TXT", "r");
+    if (fp != NULL) {
+        pc.printf("Executing startup script...\r\n");  
+        do { 
+            tmpChar = fgetc(fp);
+            if ((tmpChar >= 32) && (tmpChar <= 126)) {
+                buffer[bufferPos] = tmpChar;
+                bufferPos++;
+            }
+            if ((tmpChar == 13) || (tmpChar == 10)) { //carrriage return
+                parser.addLineToCurrentBlock(buffer);                          
+                bufferPos = 0;
+                eraseBuffer(buffer,128);             
+            }            
+            //pc.putc(tmpChar);
+        } while (tmpChar != EOF);
+        
+        buffer[bufferPos] = 59;
+        parser.addLineToCurrentBlock(buffer);
+        eraseBuffer(buffer,128);  
+        fclose(fp);
+    } else {
+        pc.printf("No startup script found.\r\n"); 
+    }
+    
+    //main loop
+    while(1) {
+       //check the main event queue to see if anything needs to be done
+       mainQueue.check();
+       
+       //https://developer.mbed.org/handbook/Serial
+        //if(device.readable()) {
+//            pc.putc(device.getc());
+//        }
+       //check if anything has been written to the serial input
+       //if (pc.readable()) {
+       if (pc.readable()) {
+                
+            buffer[bufferPos] = pc.getc();
+            bufferPos++;
+            
+            //'Return' key pressed
+            if ((buffer[bufferPos-1] == 13) || (buffer[bufferPos-1] == 10)) {
+                //pc.printf("\r\n");
+                buffer[bufferPos-1] = '\0';
+                parser.addLineToCurrentBlock(buffer);              
+                bufferPos = 0;
+                eraseBuffer(buffer,128);
+                
+            } else {
+                //pc.putc(buffer[bufferPos-1]);
+                //Backspace was pressed
+                if (((buffer[bufferPos-1] == 127)||(buffer[bufferPos-1] == 8)) && (bufferPos > 0)) {                                                  
+                    
+                    bufferPos = bufferPos-2;                   
+                } 
+            }
+       }
+       
+      // __disable_irq();
+       
+       
+       //Check all the digital ports to see if anything has changed. In the update routine, the port's
+       //script callbacks are called if the port was triggered 
+       digitalInChanged = false;
+       digitalOutChanged = false;
+       changeTime = timeKeeper;
+       for (int i = 0; i < NUMPORTS; i++) {
+             if (portVector[i+1]->update()) {
+                digitalInChanged = true;
+                changeTime = min(changeTime,portVector[i+1]->lastChangeTime);
+                
+                //The input state of all the ports in condensed into one number (each bit contains the info)
+                if (portVector[i+1]->getLastChangeState() == 1) {
+                    currentDIOstate[0] = currentDIOstate[0] | (1 << i);
+                } else {
+                    currentDIOstate[0] = currentDIOstate[0] & (255^(1 << i));
+                }
+             }
+             if (portVector[i+1]->outStateChanged) {
+                digitalOutChanged = true;
+                changeTime = min(changeTime,portVector[i+1]->lastOutChangeTime);
+                //The out state of all the ports in condensed into one number (each bit contains the info)
+                if (portVector[i+1]->outState == 1) {
+                    currentDIOstate[1] = currentDIOstate[1] | (1 << i);
+                } else {
+                    currentDIOstate[1] = currentDIOstate[1] & (255^(1 << i));
+                }
+                portVector[i+1]->outStateChanged = false;
+             }
+       }
+           
+       //If anything changed, we write the new values to the serial port (this can be turned off 
+       //with broadCastStateChanges)
+       if ( (digitalInChanged||digitalOutChanged) && broadCastStateChanges) {
+            timeConvert << changeTime; //broadcast the earliest timestamp when a change occured
+            //stateConvert << currentDIOstate[0] << " " << currentDIOstate[1];
+            stateConvert << currentDIOstate[0] << " " << currentDIOstate[1] << "       ";
+            textDisplay.send(timeConvert.str() + " " + stateConvert.str() + "\r\n");
+            timeConvert.clear();
+            timeConvert.seekp(0);
+            stateConvert.clear();
+            stateConvert.seekp(0);
+            digitalInChanged = false;
+            digitalOutChanged = false;
+       }
+       
+       //We use a buffer to send text via the serial port.  For every loop
+       //in the main loop, we send one character if there is enything to send.
+       //This way, outputting text to serial does not hold up other time-sensitive
+       //things in the event queue
+       if ((textDisplay.unsentData) && (textStreaming)) {
+            pc.printf("%c", textDisplay.getNextChar());
+       }
+       
+       //Here is how we toggle between standalone and slave mode for the clock updating.
+       if (changeToSlave) {
+            //timeTick1.detach();
+            NVIC_DisableIRQ(TIMER2_IRQn); // Disable the interrupt
+            clockExternalIncrement.rise(&callback_clockExternalIncrement);
+            clockSlave = true;
+            changeToSlave = false;
+            changeToStandAlone = false;
+       } else if (changeToStandAlone) {
+            //timeTick1.attach_us(&incrementTime, 100);
+            timer0_init();         
+            clockExternalIncrement.rise(NULL); //remove the callback to the external interrupt
+            clockSlave = false;
+            changeToSlave = false;
+            changeToStandAlone = false;
+       }
+                    
+       //__enable_irq();
+       
+    }
+}
diff -r 000000000000 -r 9d97f34c6f46 mbed.bld
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Mon May 18 01:18:45 2015 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/078e4b97a13e
diff -r 000000000000 -r 9d97f34c6f46 soundControl.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/soundControl.cpp	Mon May 18 01:18:45 2015 +0000
@@ -0,0 +1,71 @@
+#include "soundControl.h"
+
+extern SMARTWAV sWav;
+extern Serial pc;
+
+soundControl::soundControl(void):
+    fileNameExists(false),
+    volumePtr(NULL),
+    volume(-1),
+    play(true),
+    reset(false) {
+        
+}
+
+void soundControl::setFile(string fileNameIn) {
+    for (int i = 0; i < 20; i++) {
+        fileName[i] = NULL;
+    }
+    std::size_t length = fileNameIn.size();
+    if (length <= 20) {
+        fileNameIn.copy(fileName, length, 0);
+        fileNameExists = true;
+    }       
+}
+void soundControl::setVolume(int volumeIn) {
+    
+    if ((volumeIn >= 0) && (volumeIn < 256)) {
+        volume = volumeIn;
+        volumePtr = NULL;
+    }
+}
+
+void soundControl::setVolume(int* volumeIn) {
+      
+    volume = -1;
+    volumePtr = volumeIn;
+     
+}
+
+void soundControl::setPlayback(bool playIn) {
+    play = playIn;
+}
+
+void soundControl::setReset() {
+    reset = true;
+}
+
+void soundControl::execute() {
+
+    if (reset) {
+        sWav.reset(); 
+    } else if (!play) {
+        sWav.stopTrack();
+    } else {
+        if (volume > -1) {
+            sWav.volume(volume);
+        } else if (volumePtr != NULL) {
+            sWav.volume(*volumePtr);
+        }
+        
+        if (fileNameExists) {
+            //sWav.playTracks();
+            sWav.stopTrack();
+            wait_ms(30);\\ANDY
+            sWav.playTrackName(fileName);                
+        }
+    }
+}
+
+
+
diff -r 000000000000 -r 9d97f34c6f46 soundControl.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/soundControl.h	Mon May 18 01:18:45 2015 +0000
@@ -0,0 +1,30 @@
+#include "mbed.h"
+#include "SMARTWAV.h"
+#include <stdint.h>
+#include <string.h>
+#include <string>
+#include <vector>
+#include <queue>
+
+
+class soundControl {
+
+public:
+    soundControl(void);
+    void setFile(string fileNameIn);
+    void setVolume(int* volumeIn);
+    void setVolume(int volumeIn);
+    void setPlayback(bool playIn);
+    void setReset();
+    void execute();
+
+private:
+    char fileName[21];
+    bool fileNameExists;
+    int* volumePtr;
+    int volume;
+    bool play;
+    bool reset;
+    
+    
+};
\ No newline at end of file