stateScript for Nucleo-F401RE board

Dependencies:   SOMO_II mbed

Files at this revision

API Documentation at this revision

Comitter:
alustig3
Date:
Mon Feb 08 18:56:09 2016 +0000
Commit message:
initial commit

Changed in this revision

SOMO_II.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
hardwareInterface.cpp Show annotated file Show diff for this revision Revisions of this file
hardwareInterface.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
nucleoInterface/nucleoInterface.cpp Show annotated file Show diff for this revision Revisions of this file
nucleoInterface/nucleoInterface.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r ecf80f0172d0 SOMO_II.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SOMO_II.lib	Mon Feb 08 18:56:09 2016 +0000
@@ -0,0 +1,1 @@
+https://developer.mbed.org/users/alustig3/code/SOMO_II/#a4f14eadd0df
diff -r 000000000000 -r ecf80f0172d0 behave.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/behave.cpp	Mon Feb 08 18:56:09 2016 +0000
@@ -0,0 +1,5592 @@
+#include "behave.h"
+#include "hardwareInterface.h"
+#include <ctype.h>
+#include <sstream>
+//#include <string.h>
+//#include <cstdlib>
+
+using namespace std;
+
+int16_t randomSeedCounter;  //used for seeding random numbers
+
+//digitalPort* portVector[NUMPORTS+1]; //a list of pointers to the digital ports
+
+//Main event queue
+eventQueue mainQueue;
+
+//The script parser
+//scriptStream parser(portVector, NUMPORTS, &mainQueue);
+
+//globals defined in hardwareInterface.cpp
+extern uint32_t timeKeeper; //the master clock
+extern bool resetTimer;
+extern bool clockSlave;
+extern bool changeToSlave;
+extern bool changeToStandAlone;
+extern outputStream textDisplay;
+
+//extern int currentDIOstate[2];
+bool broadCastStateChanges;
+bool textStreaming;
+
+
+
+//These items may be placed in hardware-specific parts of memory
+
+#ifdef MBEDHARDWARE
+//__attribute((section("AHBSRAM0"),aligned)) outputStream textDisplay(512);
+__attribute((section("AHBSRAM0"),aligned)) char buffer[256];
+__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];
+__attribute((section("AHBSRAM0"),aligned)) triggerFunctionAction triggerFunctionActionBlock[NUMTRIGGERACTIONS];
+#endif
+
+#if defined(FPGAHARDWARE) || defined(NUCLEOHARDWARE)
+
+char buffer[256];
+event eventBlock[NUMEVENTS];
+condition conditionBlock[NUMCONDITIONS];
+intCompare intCompareBlock[NUMINTCOMPARE];
+action actionBlock[NUMACTIONS];
+portMessage portMessageBlock[NUMPORTMESSAGES];
+intOperation intOperationBlock[NUMINTOPERATIONS];
+displayAction displayActionBlock[NUMDISPLAYACTIONS];
+triggerFunctionAction triggerFunctionActionBlock[NUMTRIGGERACTIONS];
+#endif
+
+
+
+
+event* functionEventArray[NUMFUNCTIONS];
+bool   functionSpotTaken[NUMFUNCTIONS];
+
+
+//-----------------------------------------------
+//This is the main loop of the program
+mainLoop::mainLoop(){
+
+
+}
+
+void mainLoop::init() {
+    currentDIOstate[0] = 0;
+    currentDIOstate[1] = 0;
+    digitalInChanged = false;
+    digitalOutChanged = false;
+    textStreaming = true;
+    eraseBuffer();
+    broadCastStateChanges = true;
+
+
+
+//section for MBED hardware
+#ifdef MBEDHARDWARE
+    hardware = new MBEDSystem();
+    hardware->timerinit();
+    pc = new MBEDSerialPort();
+    pc->init();
+    textDisplay.setSerial(pc);
+
+#endif
+
+#ifdef FPGAHARDWARE
+       pc = new FPGASerialPort();
+       pc->init();
+
+       hardware = new FPGASystem();
+       hardware->timerinit();
+
+       textDisplay.setSerial(pc);
+
+       DIO_DCR = DIO_DCR_IE;       // enable DIO edge interrupts
+#endif
+
+#ifdef FPGAHARDWARE
+       pc = new NUCLEOSerialPort();
+       pc->init();
+
+       hardware = new MBEDSystem();
+       Ticker keeptime;
+       keeptime.attach_us(&hardware,&MBEDSystem::tick,1000);
+
+       textDisplay.setSerial(pc);
+
+       DIO_DCR = DIO_DCR_IE;       // enable DIO edge interrupts
+#endif
+
+    for (int i = 0; i < NUMPORTS; i++) {
+        //Set up the ports.  Each has two pointers to the harware implementations
+        //of a digital out and digital in.
+        ports[i].init(hardware->getDigitalOutPtr(i),hardware->getDigitalInPtr(i));
+    }
+
+
+    parser = new scriptStream(ports, NUMPORTS, &mainQueue, hardware);
+
+}
+
+void mainLoop::exec() {
+    bool digitalInChanged = false;
+    bool digitalOutChanged = false;
+    bool *ignoreUpdatePorts = hardware->getIgnoreUpdates();
+    uint32_t changeTime;
+    timeKeeper = 0; //set main clock to 0;
+
+    int bufferPos = 0;
+
+    //ostringstream timeConvert;   // stream used for the conversion
+    //ostringstream stateConvert;
+    int tmpChar;
+    int junkChar;
+
+    uint16_t shortcutTriggers[PENDINGTRIGGERBUFFERSIZE];
+    int numTriggersToProcess;
+
+    while (pc->readable()) {
+        junkChar = pc->readChar();
+    }
+
+#ifdef MBEDHARDWARE
+    LocalFileSystem local("local");
+
+    FILE *fp = fopen("/local/STARTUP.TXT", "r");
+    if (fp != NULL) {
+
+        textDisplay.send("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();
+            }
+            //pc.putc(tmpChar);
+        } while (tmpChar != EOF);
+
+        buffer[bufferPos] = 59;
+        parser->addLineToCurrentBlock(buffer);
+        eraseBuffer();
+        fclose(fp);
+    } else {
+        textDisplay.send("No startup script found.\r\n");
+    }
+#endif
+
+    //Get the initial state of all input pins
+    for (int i = 0; i < NUMPORTS; i++) {
+
+        if (ports[i].getDigitalIn() == 1) {
+            currentDIOstate[0] |= (1 << i);
+        } else {
+            currentDIOstate[0] &= ~(1 << i);
+        }
+    }
+
+
+    //main loop
+    while(1) {
+        //check the main event queue to see if anything needs to be done
+
+        mainQueue.check();
+
+        //check if anything has been written to the serial input
+        while (pc->readable()) {
+
+            buffer[bufferPos] = pc->readChar();
+            bufferPos++;
+
+
+            //'Return' key pressed
+            if ((buffer[bufferPos-1] == 13) || (buffer[bufferPos-1] == 10)) {
+
+                buffer[bufferPos-1] = '\0';
+
+                parser->addLineToCurrentBlock(buffer);
+                bufferPos = 0;
+                eraseBuffer();
+
+            } else {
+
+                //Backspace was pressed
+                if (((buffer[bufferPos-1] == 127)||(buffer[bufferPos-1] == 8))) {
+                    if (bufferPos > 1) {
+                        bufferPos = bufferPos-2; //erase the backspace char plus the one before
+                    } else {
+                        bufferPos = bufferPos-1; //beginning of line, so nothing to erase
+                    }
+                }
+            }
+        }
+
+        //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 (ports[i].update()) {
+
+                if (!ignoreUpdatePorts[i]) {
+                    //Only trigger an output update to the serial port if ignore is false
+                    digitalInChanged = true;
+                }
+                changeTime = min(changeTime,ports[i].lastChangeTime);
+
+
+                //The input state of all the ports in condensed into one number (each bit contains the info)
+                if (ports[i].getLastChangeState() == 1) {
+                    currentDIOstate[0] |= (1 << i);
+                } else {
+                    currentDIOstate[0] &= ~(1 << i);
+                }
+            }
+            if (ports[i].outStateChanged) {
+                if (!ignoreUpdatePorts[i]) {
+                     //Only trigger an output update to the serial port if ignore is false
+                    digitalOutChanged = true;
+                }
+                changeTime = min(changeTime,ports[i].lastOutChangeTime);
+                //The out state of all the ports is condensed into one number (each bit contains the info)
+                if (ports[i].outState == 1) {
+                    currentDIOstate[1] |= (1 << i);
+                } else {
+                    currentDIOstate[1] &= ~(1 << i);
+                }
+                ports[i].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) {
+            textDisplay << changeTime << " " << currentDIOstate[0] << " " << currentDIOstate[1] << "\r\n";
+
+            /*
+            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->writeChar(textDisplay.getNextChar());
+        }
+
+        //Here is how we toggle between standalone and slave mode for the clock updating.
+        if (changeToSlave) {
+            hardware->setSlaveClock();
+        } else if (changeToStandAlone) {
+           hardware->setStandAloneClock();
+        }
+
+        //anything extra to do, defined by the hardware
+        hardware->mainLoopToDo();
+
+        //check for shortcut triggers
+        numTriggersToProcess = hardware->getPendingFunctionTriggers(shortcutTriggers);
+        for (int i = 0; i < numTriggersToProcess; i++) {
+            textDisplay << "Trigger function " << shortcutTriggers[i]+1 << "\r\n";
+            if ((shortcutTriggers[i] < NUMTRIGGERACTIONS) && functionSpotTaken[shortcutTriggers[i]] && functionEventArray[i]->isUsed) {
+                //textDisplay << "Executing function array index " << shortcutTriggers[i] << "\r\n";
+                functionEventArray[shortcutTriggers[i]]->execute();
+            }
+        }
+
+    }
+
+}
+
+void mainLoop::eraseBuffer() {
+    for (int i = 0; i < 256; i++) {
+        buffer[i] = NULL;
+    }
+}
+
+//-------------------------------------------------
+
+//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) {
+    textDisplay << "Available slots left in memory\r\n";
+    textDisplay << "  Blocks: " << countUnUsed(eventBlock, NUMEVENTS) << "\r\n";
+    textDisplay << "  Condition containers: " << countUnUsed(conditionBlock, NUMCONDITIONS) << "\r\n";
+    textDisplay << "  Int compare conditions: " << countUnUsed(intCompareBlock, NUMINTCOMPARE) << "\r\n";
+    textDisplay << "  Command containers: " << countUnUsed(actionBlock, NUMACTIONS) << "\r\n";
+    textDisplay << "  Port commands: "<< countUnUsed(portMessageBlock, NUMPORTMESSAGES) << "\r\n";
+    textDisplay << "  Integer operater commands: " << countUnUsed(intOperationBlock, NUMINTOPERATIONS) << "\r\n";
+    textDisplay << "  Text display commands: " << countUnUsed(displayActionBlock, NUMDISPLAYACTIONS) << "\r\n";
+}
+
+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():
+outPin(NULL),
+inPin(NULL),
+outState(0){
+
+}
+
+void digitalPort::init(sDigitalOut *DOP, sDigitalIn *DIP) {
+    outPin = DOP;
+    inPin = DIP;
+    lastInState = getDigitalIn();
+    inState = getDigitalIn();
+    lastChangeTime = 0;
+    lastOutChangeTime = 0;
+    lastChangeInterval = 0;
+    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 = timeKeeper;
+    }
+    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;
+    bool execUp = false;
+    bool execDown = false;
+    if ((timeKeeper - lastChangeTime) > 1) { //prevents flutter triggers when button is pressed
+
+        //changed = (lastInState != inState);
+
+        changed = (inPin->lastUpEvent.triggered || inPin->lastDownEvent.triggered);
+        if (changed) {
+            inPin->setUpdate(true); //Once we get the state of the pin, we buffer any pin changes until we are done checking
+
+            inState = getDigitalIn();
+
+            //We need to ignore flutter when levers/beam breaks are triggered. So
+            //if the current state if different than the last logged state, we only
+            //consider the first edge that brough us to the current state
+            if (lastInState != inState) {
+
+                if (inState == 1) {
+
+                    lastChangeInterval = inPin->lastUpEvent.timeStamp - lastChangeTime;
+                    lastChangeTime = inPin->lastUpEvent.timeStamp;
+
+                    /*
+                    if (inPin->lastUpEvent.triggered) {
+                        //there were hardware triggers since the last main loop.  We use that time
+                        lastChangeInterval = inPin->lastUpEvent.timeStamp - lastChangeTime;
+                        lastChangeTime = inPin->lastUpEvent.timeStamp;
+                    } else {
+                        //otherwise we use the current time
+                        lastChangeInterval = timeKeeper - lastChangeTime;
+                        lastChangeTime = timeKeeper;
+                    }
+                    */
+                    if (triggerUpEventPtr != NULL && triggerUpEventPtr->isUsed) {triggerUpEventPtr->execute();}
+                } else if (inState == 0) {
+
+                    lastChangeInterval = inPin->lastDownEvent.timeStamp - lastChangeTime;
+                    lastChangeTime = inPin->lastDownEvent.timeStamp;
+
+                    /*
+                    if (inPin->lastDownEvent.triggered) {
+                        lastChangeInterval = inPin->lastDownEvent.timeStamp - lastChangeTime;
+                        lastChangeTime = inPin->lastDownEvent.timeStamp;
+                    } else {
+                        lastChangeInterval = timeKeeper - lastChangeTime;
+                        lastChangeTime = timeKeeper;
+                    }*/
+
+                    if (triggerDownEventPtr != NULL && triggerDownEventPtr->isUsed){triggerDownEventPtr->execute();}
+                }
+            } else if (lastInState == inState) {
+
+                //Both up and down triggers must have happened, so we consider both
+                if (inState == 1) {
+
+                    lastChangeInterval = inPin->lastUpEvent.timeStamp - inPin->lastDownEvent.timeStamp;
+                    lastChangeTime = inPin->lastUpEvent.timeStamp;
+
+                    if (triggerDownEventPtr != NULL && triggerDownEventPtr->isUsed) {triggerDownEventPtr->execute();}
+                    if (triggerUpEventPtr != NULL && triggerUpEventPtr->isUsed) {triggerUpEventPtr->execute();}
+                } else if (inState == 0) {
+
+                    lastChangeInterval = inPin->lastDownEvent.timeStamp - inPin->lastUpEvent.timeStamp;
+                    lastChangeTime = inPin->lastDownEvent.timeStamp;
+
+                    if (triggerUpEventPtr != NULL && triggerUpEventPtr->isUsed) {triggerUpEventPtr->execute();}
+                    if (triggerDownEventPtr != NULL && triggerDownEventPtr->isUsed) {triggerDownEventPtr->execute();}
+                }
+            }
+
+            lastInState = inState;
+            inPin->lastUpEvent.triggered = false;
+            inPin->lastDownEvent.triggered = false;
+
+            inPin->setUpdate(false); //This also checks if there were any buffered changes that occured
+
+
+        }
+
+
+
+    }
+
+    return changed;
+}
+
+int digitalPort::getLastChangeState() {
+    return lastInState;
+}
+uint32_t digitalPort::getTimeSinceLastChange() {
+    return lastChangeInterval;
+
+}
+
+intVariable::intVariable():
+value(0) {
+    isUsed = false;
+}
+
+intVariable::intVariable(std::string& tagInput, int initialValue):
+value(initialValue)
+{
+    strncpy(tag,tagInput.data(),MAXVARNAMESIZE);
+    isUsed = true;
+}
+
+void intVariable::set(std::string& tagInput, int initialValue) {
+    value = initialValue;
+    //tag = string(tagInput);
+    strncpy(tag,tagInput.data(),MAXVARNAMESIZE);
+    isUsed = true;
+}
+
+displayAction::displayAction():
+dText(string("--------------------------------------------------")){
+    dVariable = NULL;
+    isUsed = false;
+}
+
+void displayAction::release() {
+    dText = "--------------------------------------------------";
+    dVariable = NULL;
+    isUsed = false;
+}
+
+
+void displayAction::set(int* variable, string varNameInput) {
+    dVariable = variable;
+    dText = varNameInput;
+    isUsed = true;
+
+}
+
+void displayAction::set(string text) {
+    dText = text;
+    dVariable = NULL;
+    isUsed = true;
+}
+
+void displayAction::execute() {
+
+    if (dVariable != NULL) {
+        textDisplay << timeKeeper << " " << dText.c_str() << " = " << *dVariable << "\r\n";
+    } else {
+        textDisplay << timeKeeper << " " << dText.c_str() << "\r\n";
+    }
+}
+
+triggerFunctionAction::triggerFunctionAction():
+functionNum(0) {
+    isUsed = false;
+}
+
+triggerFunctionAction::triggerFunctionAction(int funcNum):
+functionNum(funcNum) {
+
+    isUsed = true;
+
+}
+
+void triggerFunctionAction::set(int funcNum) {
+    functionNum = funcNum;
+    isUsed = true;
+}
+
+void triggerFunctionAction::execute() {
+
+    if (functionSpotTaken[functionNum] && functionEventArray[functionNum]->isUsed) {
+        functionEventArray[functionNum]->execute();
+    }
+
+}
+
+void triggerFunctionAction::release() {
+    isUsed = false;
+}
+
+
+
+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;
+    isClockAssign = false;
+    inputsFlipped = 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::setRandOp(int randParam, const char* cmpString, int cmpValInput, bool flipped) {
+    randHigh = randParam;
+    cmpVal = new int(cmpValInput);
+    intVal = NULL;
+    opPtr = NULL;
+    cmpValGlobal = false;
+    isUsed = true;
+    inputsFlipped = flipped;
+    if (strcmp(cmpString, "+") == 0) {
+        executePtr = &intOperation::add;
+    }else if (strcmp(cmpString, "-") == 0) {
+        executePtr = &intOperation::subtract;
+    }else if (strcmp(cmpString, "=") == 0) {
+        executePtr = &intOperation::equals;
+    }
+
+}
+
+void intOperation::setRandOp(int randParam, const char* cmpString, int* cmpIntVarInput, bool flipped) {
+    randHigh = randParam;
+    cmpVal = cmpIntVarInput;
+    intVal = NULL;
+    opPtr = NULL;
+    cmpValGlobal = true;
+    isUsed = true;
+    inputsFlipped = flipped;
+    if (strcmp(cmpString, "+") == 0) {
+        executePtr = &intOperation::add;
+    }else if (strcmp(cmpString, "-") == 0) {
+        executePtr = &intOperation::subtract;
+    }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;
+
+}
+
+void intOperation::setClockOp(int* intVarInput) {
+    //used to assign current clock to variable
+    intVal = intVarInput;
+    cmpVal = NULL;
+    randHigh = -1;
+    opPtr = NULL;
+    cmpValGlobal = false;
+    isUsed = true;
+    isClockAssign = true;
+    executePtr = &intOperation::equals;
+
+}
+
+void intOperation::setClockOp(const char* cmpString, int cmpValInput, bool flip) {
+    //used to add an integer to the current clock value
+
+    intVal = NULL;
+    cmpVal = new int(cmpValInput);
+    randHigh = -1;
+    opPtr = NULL;
+    cmpValGlobal = false;
+    isUsed = true;
+    isClockAssign = true;
+    inputsFlipped = flip;
+    if (strcmp(cmpString, "+") == 0) {
+        executePtr = &intOperation::add;
+    }else if (strcmp(cmpString, "-") == 0) {
+        executePtr = &intOperation::subtract;
+    }
+}
+
+void intOperation::setClockOp(const char* cmpString, int* cmpIntVarInput, bool flip) {
+    //used to add a variable to the current clock value
+
+    cmpVal = cmpIntVarInput;
+    intVal = NULL;
+    randHigh = -1;
+    opPtr = NULL;
+    isClockAssign = true;
+    cmpValGlobal = true;
+    isUsed = true;
+    inputsFlipped = flip;
+    if (strcmp(cmpString, "+") == 0) {
+        executePtr = &intOperation::add;
+    }else if (strcmp(cmpString, "-") == 0) {
+        executePtr = &intOperation::subtract;
+    }
+}
+
+
+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;
+    isClockAssign = false;
+    cmpValGlobal = false;
+    isUsed = false;
+}
+
+
+int intOperation::execute() {
+
+    return (this->*executePtr)();
+
+
+}
+
+int intOperation::add() {
+
+    if ((intVal != NULL) && (!isClockAssign)) {
+        return (*intVal + *cmpVal);
+    } else if ((intVal == NULL) && (isClockAssign)) {
+        return (timeKeeper + *cmpVal);
+    } else {
+        //srand(time(NULL));
+        srand(timeKeeper);
+        return (rand() % (randHigh+1)) + *cmpVal;
+        //return (port->getState() + *cmpVal);
+    }
+}
+
+int intOperation::subtract() {
+    if ((intVal != NULL) && (!isClockAssign)) {
+        return (*intVal - *cmpVal);
+    } else if ((intVal == NULL) && (isClockAssign)) {
+        if (inputsFlipped) {
+            return (*cmpVal-timeKeeper);
+        } else {
+            return (timeKeeper - *cmpVal);
+        }
+    } else {
+        srand(timeKeeper);
+        if (inputsFlipped) {
+            return (*cmpVal-(rand() % (randHigh+1)));
+        } else {
+            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) && (!isClockAssign)) {
+        *intVal = *cmpVal;
+        return *intVal;
+    } else if ((intVal != NULL) && (opPtr != NULL)) {
+
+        *intVal = opPtr->execute();
+        return *intVal;
+    } else if ((intVal != NULL) && (opPtr == NULL) && (isClockAssign)) {
+        *intVal = timeKeeper; //assign the current time to the variable
+        return *intVal;
+    } else if ((cmpVal != NULL)&& (!isClockAssign)){
+
+        srand(timeKeeper+randomSeedCounter);
+        randomSeedCounter++; //for seeding the next rand call, just in case it happens before the clock advances
+        *cmpVal = (rand() % (randHigh+1)); //this is how we assign a random number to variable
+        return *cmpVal;
+
+    }
+    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) {
+
+        result = (intCmp->isTrue)();
+    } else if (conditionType == AND_CONDITION) {
+
+        result = conditionPtrs[0]->isTrue() && conditionPtrs[1]->isTrue();
+    } else if (conditionType == OR_CONDITION) {
+
+        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, digitalPort* portVectorIn) {
+    whichToSet = whichToSetIn;
+    value = valueIn;
+    port = portIn;
+    portVector = portVectorIn;
+    isUsed = true;
+}
+
+void portMessage::execute() {
+
+    if (port != NULL) {
+        if ((*port > 0) && (*port <= NUMPORTS)) {
+            portVector[*port-1].setDigitalOut(value);
+        } else {
+            textDisplay << "Error: port index assigned by variable does not exist.\r\n";
+        }
+    } else {
+        portVector[whichToSet-1].setDigitalOut(value);
+    }
+
+}
+
+action::action():
+actionType(0) {
+    op = NULL;
+    message = NULL;
+    eventToCreate = NULL;
+    displayActionPtr = NULL;
+    //eventDelay = 0;
+    sound = NULL;
+    triggerFunc = 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();
+    if (triggerFunc != NULL) triggerFunc->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;
+    triggerFunc = NULL;
+    sysCommand = -1;
+    isUsed = false;
+}
+
+action::action(intOperation* opInput):
+actionType(1) {
+    op = opInput;
+    message = NULL;
+    eventToCreate = NULL;
+    displayActionPtr= NULL;
+    //eventDelay = 0;
+    sound = NULL;
+    triggerFunc = NULL;
+    sysCommand = -1;
+    isUsed = true;
+}
+
+action::action(portMessage* messageInput):
+actionType(2) {
+    op = NULL;
+    eventToCreate = NULL;
+    message = messageInput;
+    displayActionPtr= NULL;
+    //eventDelay = 0;
+    sound = NULL;
+    triggerFunc = NULL;
+    sysCommand = -1;
+    isUsed = true;
+
+}
+
+action::action(event* eventInput):
+actionType(3) {
+    op = NULL;
+    message = NULL;
+    eventToCreate = eventInput;
+    displayActionPtr= NULL;
+    sound = NULL;
+    triggerFunc = 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;
+    triggerFunc = NULL;
+    displayActionPtr = displayInput;
+    //eventDelay = 0;
+    sysCommand = -1;
+    isUsed = true;
+}
+
+action::action(sSound* soundInput):
+actionType(5) {
+    op = NULL;
+    message = NULL;
+    eventToCreate = NULL;
+    sound = soundInput;
+    triggerFunc = NULL;
+    displayActionPtr = NULL;
+    //eventDelay = 0;
+    sysCommand = -1;
+    isUsed = true;
+}
+
+action::action(triggerFunctionAction* triggerFuncInput):
+actionType(7) {
+    op = NULL;
+    message = NULL;
+    eventToCreate = NULL;
+    sound = NULL;
+    triggerFunc = triggerFuncInput;
+    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(sSound* soundInput) {
+    actionType = 5;
+    sound = soundInput;
+    isUsed = true;
+}
+
+void action::set(triggerFunctionAction* triggerFuncInput) {
+
+    actionType = 7;
+    triggerFunc = triggerFuncInput;
+    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(timeKeeper); //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;
+        }
+
+    } else if (actionType == 7) {
+        triggerFunc->execute(); //execute function
+    }
+}
+
+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 - (timeKeeper-blockExecTime);
+        } else {
+            newDelay = *eventToCreate->timeLagVar - (timeKeeper-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-timeKeeper < 0) && (eventToCreate->isConditionTrue()) ) {
+                    eventToCreate->execute();
+                    newDelay = newDelay + tmpPeriod;
+
+                }
+                newDelay = newDelay-timeKeeper;
+                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;
+        }
+    } else if (actionType == 7) {
+
+        textDisplay.flush();
+        triggerFunc->execute(); //operate sound device
+    }
+}
+
+eventQueue::eventQueue() {
+
+    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 = timeKeeper + 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 = timeKeeper;
+    //*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-timeKeeper <= 0) && (events[i].eventPtr->isConditionTrue())) {
+                        events[i].eventPtr->execute();
+                        nextTime = nextTime+tmpPeriod;
+
+                    }
+                    nextTime = nextTime - timeKeeper;
+                    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')
+    bool result = true;
+
+    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 = timeKeeper;
+    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;
+}
+
+blockBuffer::blockBuffer() {
+    bufferWritePos = 0;
+    bufferReadPos = 0;
+    _linesAvailable = 0;
+
+}
+
+bool blockBuffer::addLine(char *input, int numChars) {
+
+    if (bufferWritePos+numChars >= INPUTCHARBUFFERSIZE) {
+        return false;
+    }
+    for(int i=0;i<numChars;i++) {
+        charBuffer[bufferWritePos] = input[i];
+        bufferWritePos++;
+    }
+    _linesAvailable++;
+    return true;
+}
+
+string blockBuffer::getNextLine() {
+
+    string outputLine;
+    int endOfLinePos = bufferReadPos;
+    bool endOfLineFound = false;
+
+    if (_linesAvailable > 0) {
+        //Find the end of the next line
+
+        while (endOfLinePos < INPUTCHARBUFFERSIZE) {
+
+            if (charBuffer[endOfLinePos] == '\0') {
+                endOfLineFound = true;
+                break;
+            }
+            endOfLinePos++;
+        }
+
+        //If the end was found, copy to output string
+        if (endOfLineFound) {
+
+            outputLine.append(charBuffer+bufferReadPos,endOfLinePos-bufferReadPos);
+            bufferReadPos = endOfLinePos+1;
+            _linesAvailable--;
+        } else {
+            textDisplay << "Error: No end of line found!";
+            textDisplay.flush();
+        }
+    }
+    if (_linesAvailable == 0) {
+        //we have read out all of the lines, so reset the buffer for the next block.
+        resetBuffer();
+    }
+    return outputLine;
+
+}
+
+int16_t blockBuffer::linesAvailable() {
+    return _linesAvailable;
+}
+
+void blockBuffer::resetBuffer() {
+    _linesAvailable = 0;
+    bufferReadPos = 0;
+    bufferWritePos = 0;
+}
+
+bool blockBuffer::empty() {
+    return (_linesAvailable == 0);
+}
+
+
+scriptStream::scriptStream(digitalPort* portVectorInput, int numPortsInput, eventQueue* queueInput, sSystem *system):
+    portVector(portVectorInput),
+    numPorts(numPortsInput),
+    queuePtr(queueInput),
+    system(system) {
+
+    currentPort = -1;
+    currentTriggerPort = -1;
+    currentTriggerDir = 1;
+    currentFunction = -1;
+
+    randomSeedCounter = 0;  //used for seeding random numbers
+
+    lineError = false;
+    blockDepth = 0;
+    ifBlockInit = false;
+    whileBlockInit = false;
+    expectingDoStatement = false;
+    elseFlag = false;
+    thenFlag = false;
+    currentDelay = 0;
+
+    for (int i = 0; i < NUMFUNCTIONS; i++) {
+        functionSpotTaken[i] = false;
+        functionEventArray[i] = NULL;
+    }
+
+
+}
+
+
+void scriptStream::addLineToCurrentBlock(char* lineInput) {
+
+    bool compile = false;
+    bool keep = false;
+    int numCharInLine = 0;
+    //A line ending with ';' then carriage return initiates the compile sequence
+    //Otherwise, add the line to the buffer and compile later
+    for (int i = 0; i < 256; i++) {
+        numCharInLine++;
+        if (lineInput[i] == ';') {
+            compile = true;
+        } else if (lineInput[i] == ' ') {
+            continue;
+        } else if (lineInput[i] == '\0') {
+            break;
+        } else {
+            keep = true;
+            compile = false;
+        }
+
+    }
+
+    //if (keep) currentBlock.insert(currentBlock.begin(),string(lineInput));
+    if (keep) {
+        if (!currentBlock.addLine(lineInput,numCharInLine)) {
+            textDisplay << "Error: script input buffer full. The block is too long.\r\n";
+            currentBlock.resetBuffer();
+            compile = false;
+        }
+    }
+    if (compile) {
+        parseBlock();
+    }
+
+}
+
+
+//SCRIPT PARSING - all script commands are defined here.
+//-------------------------------------------------------
+void scriptStream::parseBlock() {
+
+    tmpEvent = NULL;
+    lineError = false;
+    blockDepth = 0;
+    ifBlockInit = false;
+    whileBlockInit = false;
+    expectingDoStatement = false;
+    elseFlag = false;
+    thenFlag = false;
+    currentDelay = 0;
+
+
+    std::size_t stringInd = 0;
+
+    bool wholeLineEvaluated = false;
+
+    while (!currentBlock.empty()) {
+
+        wholeLineEvaluated = false;
+        //tmpLine = currentBlock.back();
+        tmpLine = currentBlock.getNextLine();
+
+        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++) {
+
+
+
+            //end statement signals the end of a block-----------------------------------------
+            if (tokens[i].compare("end") == 0) { //ends the current block
+
+                if (ifBlockInit || whileBlockInit || expectingDoStatement) {
+                    textDisplay << "Error: expected a 'do' statement\r\n";
+                    lineError = true;
+                }
+
+                ifBlockInit = false;
+                whileBlockInit = false;
+                expectingDoStatement = false;
+                elseFlag = false;
+
+                if (blockDepth > 0) {
+                    textDisplay.debug("End statement\r\n");
+                    if (blockDepth == 1) {
+
+
+                        currentTriggerPort = -1;
+                        currentFunction = -1;
+
+
+
+                        blockDepth = 0;
+                    } else if (blockDepth > 1) {
+                        blockDepth = blockDepth - 1;
+                    }
+
+                    while ((tmpEventPtrArray.back()->blockType == 3) || (tmpEventPtrArray.back()->blockType == 4) || (tmpEventPtrArray.back()->blockType == 6) || (tmpEventPtrArray.back()->blockType == 7) || (tmpEventPtrArray.back()->blockType == 8)){
+                        tmpEventPtrArray.pop_back(); //recursively remove the pointers to all else blocks
+                    }
+                    tmpEventPtrArray.pop_back(); //remove the pointer to the finished block
+
+                } else {
+                    textDisplay << "Error: End statement without block\r\n";
+                    lineError = true;
+                }
+
+
+
+                //sound statement used to play wave files------------------------------------------------
+                //example: sound('soundfile')
+                //         sound(stop)
+                //         sound(s03)
+            } else if (tokens[i].find("sound(") != std::string::npos) {
+                if (ifBlockInit || whileBlockInit || elseFlag || expectingDoStatement) {
+                    textDisplay << "Error: expected a 'do' statement\r\n";
+                    lineError = true;
+                }
+                wholeLineEvaluated = true;
+                int pos1 = tmpLine.find("sound(")+6;
+                int pos2 = tmpLine.find_first_of(")",pos1);
+                if (pos2 == std::string::npos) {
+                    textDisplay << "Syntax error: expected a ')'\r\n";
+                    lineError = true;
+                }
+                if (!lineError) {
+                    string dispVar = tmpLine.substr(pos1,pos2-pos1);
+                    int* tmpVar = findIntVariable(dispVar);
+                    bool isText = false;
+                    bool stopSignal = false;
+                    bool resetSignal = false;
+                    unsigned char sendTrack = 0;
+                    if (tmpVar == NULL) {
+                        if ((tmpLine.compare(pos1,1,"'")==0) && (tmpLine.compare(pos2-1,1,"'")==0)) {
+                            isText = true;
+//                            textDisplay <<"command= "<<tmpLine.substr(pos1+1,pos2-pos1-2)<<"\r\n";
+                        } else if (tmpLine.compare(pos1,1,"s")==0 && dispVar.length()==3) {
+                            sendTrack = (dispVar[1]-48)*10 + dispVar[2]-48;
+                        } else if (dispVar.compare("stop") == 0) {
+                            stopSignal = true;
+                        } else if (dispVar.compare("reset") == 0) {
+                            resetSignal = true;
+                        } else {
+                            textDisplay << "Error: variable input to sound() does not exist\r\n";
+                            lineError = true;
+                        }
+                    }
+                    action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);
+                    if (tmpAction == NULL) {
+                        textDisplay << "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) {
+                            sSound* S = system->createNewSoundAction();
+                            S->setPlayback(false);
+                            S->execute();
+                            delete S;
+                        } else if (resetSignal) {
+                            sSound* S = system->createNewSoundAction();
+                            S->setReset();
+                            S->execute();
+                            delete S;
+                        } else if (sendTrack>0 && sendTrack<100){ //track number must be 1-99
+                            sSound* S = system->createNewSoundAction();
+//                            textDisplay<<"sent:"<<sendTrack;
+                            S->setFile(sendTrack);
+                            S->execute();
+                            delete S;                            
+                        } else if (isText) {
+                            if (pos2-pos1-2 <= 20) {
+                                sSound* S = system->createNewSoundAction();
+                                S->setFile(tmpLine.substr(pos1+1,pos2-pos1-2));
+                                S->execute();
+                                delete S;
+                            } else {
+                                textDisplay << "Error: sound file names must be 20 characters or less.\r\n";
+                                lineError = true;
+                            }
+                        } else {
+                            textDisplay << "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
+                        textDisplay.debug("Sound statement\r\n");
+                        if (stopSignal) {
+                            sSound* sPtr = system->createNewSoundAction();
+                            sPtr->setPlayback(false);
+                            //action* tmpAction = new action(sPtr);
+                            tmpAction->set(sPtr);
+                            tmpEventPtrArray.back()->addAction(tmpAction);
+                        }else if (resetSignal) {
+                            sSound* sPtr = system->createNewSoundAction();
+                            sPtr->setReset();
+                            //action* tmpAction = new action(sPtr);
+                            tmpAction->set(sPtr);
+                            tmpEventPtrArray.back()->addAction(tmpAction);
+                        }else if (sendTrack>0 && sendTrack<100){
+                            sSound* sPtr = system->createNewSoundAction();
+                            sPtr->setFile(sendTrack);
+                            tmpAction->set(sPtr);
+                            tmpEventPtrArray.back()->addAction(tmpAction);
+                        }else if (isText) {
+                            if (pos2-pos1-2 <= 20) {
+                                sSound* sPtr = system->createNewSoundAction();
+                                sPtr->setFile(tmpLine.substr(pos1+1,pos2-pos1-2));
+                                //action* tmpAction = new action(sPtr);
+                                tmpAction->set(sPtr);
+                                tmpEventPtrArray.back()->addAction(tmpAction);
+                            } else {
+                                textDisplay << "Error: sound file names must be 20 characters or less.\r\n";
+                                lineError = true;
+                            }
+                        } else {
+                            textDisplay << "Error: variable input to sound() not yet supported.  Enter a string in single quotes.\r\n";
+                            lineError = true;
+                        }
+                    }
+                }
+
+            } else if (tokens[i].find("volume(") != std::string::npos) {
+                if (ifBlockInit || whileBlockInit || elseFlag || expectingDoStatement) {
+                    textDisplay << "Error: expected a 'do' statement\r\n";
+                    lineError = true;
+                }
+                wholeLineEvaluated = true;
+                int pos1 = tmpLine.find("volume(")+7;
+                int pos2 = tmpLine.find_first_of(")",pos1);
+                if (pos2 == std::string::npos) {
+                    textDisplay << "Syntax error: expected a ')'\r\n";
+                    lineError = true;
+                }
+                if (!lineError) {
+                    string dispVar = tmpLine.substr(pos1,pos2-pos1);
+
+                    int* tmpVar = findIntVariable(dispVar);
+                    bool isText = false;
+                    if (tmpVar == NULL) {
+                        if (isNumber(dispVar)) {
+                            isText = true;
+                        } else {
+                            textDisplay << "Error: variable input to volume() does not exist\r\n";
+                            lineError = true;
+                        }
+                    }
+                    action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);
+                    if (tmpAction == NULL) {
+                        textDisplay << "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)) { // for SOMO II it should be between 0 and 30, but I'm not sure how to let this code know whether the SOMO or the smartWAV is being used
+                                sSound* S = system->createNewSoundAction();
+//                                textDisplay << "new vol=" <<newVolume;
+                                S->setVolume(newVolume);
+                                S->execute();
+                                delete S;
+                            } else {
+                                textDisplay << "Error: sound volume must be between 0 and 255 .\r\n"; 
+                                lineError = true;
+                            }
+                        } else {
+                            sSound* S = system->createNewSoundAction();
+                            S->setVolume(tmpVar);
+                            S->execute();
+                            delete S;
+                        }
+
+                    } else if (!lineError && (blockDepth > 0) ){
+                        //the disp function was put inside a block
+                        textDisplay.debug("Volume statement\r\n");
+                        if (isText) {
+                            int newVolume = atoi(dispVar.data());
+
+                            sSound* sPtr = system->createNewSoundAction();
+                            sPtr->setVolume(newVolume);
+
+                            //action* tmpAction = new action(sPtr);
+                            tmpAction->set(sPtr);
+                            tmpEventPtrArray.back()->addAction(tmpAction);
+
+                        } else {
+                            sSound* sPtr = system->createNewSoundAction();
+                            sPtr->setVolume(tmpVar);
+                            //action* tmpAction = new action(sPtr);
+                            tmpAction->set(sPtr);
+                            tmpEventPtrArray.back()->addAction(tmpAction);
+                        }
+
+
+                    }
+                }
+                //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 || expectingDoStatement) {
+                    textDisplay << "Error: expected a 'do' statement\r\n";
+                    lineError = true;
+                }
+                if (blockDepth > 0) {
+                    textDisplay << "Error: clock commands only allowed outside of block structure\r\n";
+                    lineError = true;
+                }
+                int pos1 = tmpLine.find("clock(")+6;
+                int pos2 = tmpLine.find_first_of(")",pos1);
+                if (pos2 == std::string::npos) {
+                    textDisplay << "Syntax Error: expected a ')'\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"));
+
+                        } else if (dispVar.compare("slave") == 0) {
+                            if (!clockSlave) {
+                                changeToSlave = true;
+                                textDisplay.send(string("Slave mode\r\n"));
+
+                            }
+                        } else if (dispVar.compare("standalone") == 0) {
+                            if (clockSlave) {
+                                changeToStandAlone = true;
+                                textDisplay.send(string("Standalone mode\r\n"));
+
+                            }
+                        } else if (dispVar.compare("") == 0) {
+                            //The user needs the current time displayed.
+
+                            //textDisplay.send(string("Current Clock\r\n"));
+                            textDisplay << timeKeeper << " current time\r\n";
+                        } else {
+                            textDisplay << "Error: 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 || expectingDoStatement) {
+                    textDisplay <<"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);
+                if (pos2 == std::string::npos) {
+                    textDisplay <<"Syntax error: expected a ')'\r\n";
+                    lineError = true;
+                }
+
+                if (!lineError) {
+                    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 {
+                            textDisplay << "Error: variable to display does not exist\r\n";
+                            lineError = true;
+                        }
+                    }
+                    displayAction* dPtr = findFirstUnUsed(displayActionBlock, NUMDISPLAYACTIONS);
+                    if (dPtr == NULL) {
+                        textDisplay << "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));
+                            dPtr->execute();
+                            //delete dPtr;
+                            dPtr->release();
+                        } else {
+                            //displayAction* dPtr = new displayAction(tmpVar, dispVar, pcPtr);
+                            dPtr->set(tmpVar, dispVar);
+                            dPtr->execute();
+                            //delete dPtr;
+                            dPtr->release();
+                        }
+
+                    } else if (!lineError && (blockDepth > 0) ){
+                        //the disp function was put inside a block
+                        textDisplay.debug("Display statement\r\n");
+                        action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);
+                        if (tmpAction == NULL) {
+                            textDisplay <<"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));
+                            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);
+                            tmpAction->set(dPtr);
+                            //action* tmpAction = new action(dPtr);
+                            tmpEventPtrArray.back()->addAction(tmpAction);
+                        }
+
+
+                    }
+                }
+                //----------------------------------------------
+                //The trigger command is used like this:
+                //trigger(n)
+                //Where n is an integer corresponding to a "function n" block
+                //When "trigger" is called, the corresponding function is executed.
+            } else if (tokens[i].find("trigger(") != std::string::npos) { //trigger a function
+
+                if (ifBlockInit || whileBlockInit || elseFlag || expectingDoStatement) {
+                    textDisplay << "Error: expected a 'do' statement\r\n";
+                    lineError = true;
+                }
+
+
+                wholeLineEvaluated = true;
+                int pos1 = tmpLine.find("trigger(")+8;
+                int pos2 = tmpLine.find_first_of(")",pos1);
+                if (pos2 == std::string::npos) {
+                    textDisplay << "Syntax error: expected a ')'\r\n";
+                    lineError = true;
+                }
+
+                if (!lineError) {
+                    int funcNum = atoi(tmpLine.substr(pos1,pos2-pos1).data());
+                    if ((funcNum > 0) && (funcNum < NUMFUNCTIONS+1)) {
+                        if (functionSpotTaken[funcNum-1] && functionEventArray[funcNum-1]->isUsed) {
+
+
+                        } else {
+                            textDisplay << "Error: function number does not exist\r\n";
+                            lineError = true;
+                        }
+                    } else {
+                        textDisplay << "Error: not a valid function number\r\n";
+                        lineError = true;
+                    }
+
+                    funcNum--;  //change to 0-based index
+                    if (!lineError && (blockDepth == 0)) {
+                        //we are not inside a block structure, so execute function now
+                        //textDisplay << "Exectuting function";
+                        //textDisplay.flush();
+
+                        functionEventArray[funcNum]->execute();
+
+                    } else if (!lineError && (blockDepth > 0) ){
+                        //the trigger function was put inside a block, so we need to create a new action
+                        textDisplay.debug("Trigger statement\r\n");
+                        triggerFunctionAction* tPtr = findFirstUnUsed(triggerFunctionActionBlock, NUMTRIGGERACTIONS);
+                        if (tPtr == NULL) {
+                            textDisplay << "Error: no memory slots available.\r\n";
+                            lineError = true;
+                        }
+
+                        if (!lineError) {
+                            //we only give provide it the function number, instead
+                            //of a pointer to the event.  That way, if the user modifies
+                            //the function (which would change the pointer), all callbacks
+                            //still using that function number will use the new function.
+                            tPtr->set(funcNum);
+                            action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);
+                            if (tmpAction == NULL) {
+                                textDisplay << "Error: no memory slots available.\r\n";
+                                lineError = true;
+                            }
+                            if (!lineError) {
+
+                                tmpAction->set(tPtr);
+                                tmpEventPtrArray.back()->addAction(tmpAction);
+                            }
+                        }
+
+
+                    }
+
+                }
+
+
+                //int is used to decalar new variables.  Only allowed outside of callbacks-------------------
+                //example: int a;  int b = 9
+            }else if(tokens[i].compare("kaboom") == 0){//send "kaboom;" to reset mbed
+//                mbed_reset();            
+            }else if (tokens[i].compare("int") == 0) { //define a new integer variable
+                textDisplay.debug("Int statement\r\n");
+                if (ifBlockInit || whileBlockInit || expectingDoStatement) {
+                    textDisplay << "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) {
+                    textDisplay << "Error: Variables can only be first declared outside of callbacks.\r\n";
+                    lineError = true;
+                }
+
+                if ((!lineError) && (spacesBeforeEqualSign > 1)) {
+                    textDisplay << "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 ((stringInd != std::string::npos) && (stringInd > MAXVARNAMESIZE)) {
+                            textDisplay << "Error: variable names must be under 30 characters.\r\n";
+                            lineError = true;
+                        } else if (createIntVariable(tmpString.substr(0,stringInd))) {
+                            textDisplay.debug("Created new variable\r\n");
+                            variableCreated = true;
+                        } else {
+                            textDisplay.debug("Attempting to use existing variable\r\n");
+                            int* tmpVar = findIntVariable(tmpString.substr(0,stringInd));
+                            *tmpVar = 0;
+                            //lineError = true;
+                        }
+                    } else {
+                        textDisplay << "Error: variable declaration not understood.\r\n";
+                        lineError = true;
+                    }
+                }
+                if ((!lineError) && (stringInd != std::string::npos)) { //evaluate the expression
+                    //action* tmpAction = evaluateAssignmentForAction(tmpString);
+                    action* tmpAction = evaluateAssignmentForAction(tmpString.data());
+                    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 || expectingDoStatement) {
+                    textDisplay << "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 {
+                        textDisplay << "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) {
+                            textDisplay << "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) {
+                            textDisplay << "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
+                //examples: updates on 3; updates off 3
+            } else if (tokens[i].compare("updates") == 0) {
+                if (ifBlockInit || whileBlockInit || elseFlag || expectingDoStatement) {
+                    textDisplay << "Error: expected a 'do' statement\r\n";
+                    lineError = true;
+                }
+                bool stream = true;
+                int specifiedPort = -1;
+                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 {
+                        textDisplay << "Error: 'updates' useage: 'updates on' or 'updates off'\r\n";
+                        lineError = true;
+                    }
+                }
+                if ((!lineError) && (i+2 < sz)) {
+                    //There is a port specified
+                    //int pos1 = tmpLine.find("trigger(")+8;
+                    //int pos2 = tmpLine.find_first_of(")",pos1);
+                    int tempPort = atoi(tokens[i+2].data());
+                    if (tempPort > 0) {
+                        specifiedPort = tempPort-1;
+                    } else {
+                        textDisplay << "Error: 'updates' useage: 'updates on [port]' or 'updates off [port]'\r\n";
+                        lineError = true;
+                    }
+                    i++;
+                }
+                i++;
+                if ((!lineError) && (blockDepth == 0)) {
+                    if (stream) {
+                        //applies to all;
+                        broadCastStateChanges = true;
+                        if (specifiedPort > -1) {
+                            system->setPortUpdatesOn(specifiedPort);
+                        } else {
+                            for (int i=0;i<NUMPORTS;i++) {
+                                system->setPortUpdatesOn(i);
+                            }
+                        }
+                    } else {
+                        if (specifiedPort > -1) {
+                            system->setPortUpdatesOff(specifiedPort);
+                        } else {
+                            //applies to all
+                            //broadCastStateChanges = false;
+                            for (int i=0;i<NUMPORTS;i++) {
+                                system->setPortUpdatesOff(i);
+                            }
+                        }
+
+                    }
+                } else if ((!lineError) && (blockDepth > 0)) {
+                    //Inside a block-- current no support here to specify a port
+
+                    if (stream) {
+                        //action* tmpAction = new action(3); //code 3 = turn on updates
+                        action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);
+                        if (tmpAction == NULL) {
+                            textDisplay << "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) {
+                            textDisplay << "Error: no memory slots available.\r\n";
+                            lineError = true;
+                        } else {
+                            tmpAction->set(4);
+                            tmpEventPtrArray.back()->addAction(tmpAction);
+                        }
+
+                    }
+                }
+
+            } else if (tokens[i].compare("memory") == 0) {
+                if (ifBlockInit || whileBlockInit || elseFlag || expectingDoStatement) {
+                    textDisplay << "Error: expected a 'do' statement\r\n";
+                    lineError = true;
+                }
+                if ((!lineError) && (blockDepth > 0)) {
+                    textDisplay << "Error: memory statement is not allowed inside a block.\r\n";
+                    lineError = true;
+                }
+                if (!lineError) {
+                    displayMemoryLeft();
+                }
+
+
+            //clear is used to clear things from memory---------------------------------
+            //examples: clear all; clear callbacks; clear queue
+
+            } else if (tokens[i].compare("clear") == 0) { //delete all created events and variables
+                if (ifBlockInit || whileBlockInit || elseFlag || expectingDoStatement) {
+                    textDisplay << "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 {
+                        textDisplay << "Error: clear what: all, blocks, or queue? \r\n";
+                        lineError = true;
+                    }
+                } else {
+                    textDisplay << "Error: clear what: all, blocks, or queue? \r\n";
+                    lineError = true;
+                }
+
+
+                if ((!lineError) && (clearMode < 3) && (blockDepth > 0)) {
+                    textDisplay << "Error: 'clear all' and 'clear blocks' only allowed outside of block structures\r\n";
+                    lineError = true;
+                }
+                if (!lineError) {
+                    //i++;
+                    //clear variables
+
+                    if (clearMode == 1) {
+                        //Clears everything
+                        int sendClearMode = 0;
+                        sendClearMode |= BLOCKMEMORYTYPES;
+                        sendClearMode |= VARIABLEMEMORYTYPES;
+                        sendClearMode |= ENVSETTINGSMEMORYTYPES;
+
+                        clearEnvironmentVariables(sendClearMode);
+
+                    } else if  (clearMode == 2) {
+                        //Clear just varaibles
+                        int sendClearMode = 0;
+                        sendClearMode |= VARIABLEMEMORYTYPES;
+                        clearEnvironmentVariables(sendClearMode);
+
+                    } else if (clearMode == 3) {
+                        //Clear the current event queue (can itself be a queued action)
+                        if (blockDepth > 0) { //we are inside a block
+                            action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);
+                            if (tmpAction == NULL) {
+                                textDisplay << "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();
+                        }
+                    }
+                    wholeLineEvaluated = true;
+
+
+                }
+
+                //do starts a block---------------------------------------------------------
+                //example:  do in 500
+                //              ...
+                //          end
+
+            } else if (tokens[i].compare("do") == 0) { //the start of a block
+
+                if (!ifBlockInit && !whileBlockInit) {
+
+                    if ((currentTriggerPort > 0) || (currentFunction > -1)) { //check to make sure we are inside a trigger block
+
+
+                    } else {
+                        textDisplay << "Error: a statement block must be placed inside a callback or function.\r\n";
+                        lineError = true;
+                    }
+
+                }
+                expectingDoStatement = false;
+                tmpEvent = findFirstUnUsed(eventBlock, NUMEVENTS);
+                action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);
+                bool eventReserved = false;
+                if ((tmpEvent == NULL)||(tmpAction == NULL)) {
+                    textDisplay << "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]))) {
+                        textDisplay.debug("Do in number statement\r\n");
+                        currentDelay = atoi(tokens[i+2].data());
+                        if (currentDelay < 0) {
+                            textDisplay <<"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
+                            }
+
+                        } 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());
+
+                            }
+
+
+                        }
+
+                    } else if ((!lineError) && (tokens[i+1].compare("in") == 0) && (findIntVariable(tokens[i+2])!=NULL)) {
+                        textDisplay.debug("Do in VAR statement\r\n");
+                        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
+                            }
+
+                        } 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());
+
+                            }
+
+
+                        }
+
+                    } else {
+                        textDisplay << "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
+                    textDisplay.debug("Do statement\r\n");
+                    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
+                    }
+
+                } 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());
+                    }
+
+                }
+                if (lineError && eventReserved) {
+                    tmpEvent->release();
+                }
+                //close block initiation
+                ifBlockInit = false;
+                whileBlockInit = false;
+                wholeLineEvaluated = true;
+                elseFlag = false;
+                thenFlag = false;
+
+                //currently, there are two types of root-level blocks: functions and callbacks
+                //
+                //A function can be triggered with a command, a callback is tied to a hardware event
+            } else if (tokens[i].compare("function") == 0) { //a new function block
+                if (ifBlockInit || whileBlockInit || elseFlag || expectingDoStatement) {
+                    textDisplay << "Error: expected a 'do' statement\r\n";
+                    lineError = true;
+                }
+                if (blockDepth != 0)  {
+                    textDisplay <<"Error: Can't declare a function block within another block\r\n";
+                    lineError = true;
+                }
+                if (!lineError) {
+                    textDisplay.debug("Function statement\r\n");
+                    wholeLineEvaluated = true;
+                    if (i+1 < sz) {
+                        int tempFuncNum = atoi(tokens[i+1].data());
+                        if ((tempFuncNum > 0) && (tempFuncNum < NUMFUNCTIONS+1)) {
+                            currentFunction = tempFuncNum-1;
+                        } else {
+                            textDisplay << "Error: not a valid function number\r\n";
+                            lineError = true;
+                        }
+                    } else {
+                        if (!lineError) textDisplay << "Error: Not enough arguments for function statement\r\n";
+                        lineError = true;
+                    }
+                    if (sz > 2) {
+                        if (!((sz == 3) && (tokens[i+2].compare("do") == 0))) {
+                            textDisplay << "Error: Too many arguments in function statement\r\n";
+                            lineError = true;
+                        }
+                    }
+
+                    tmpEvent = findFirstUnUsed(eventBlock, NUMEVENTS);
+                    if (tmpEvent != NULL) {
+                        tmpEvent->isUsed = true;
+
+                    } else {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        lineError = true;
+                    }
+                    if (!lineError) {
+
+                        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 (functionSpotTaken[currentFunction]) {
+                            functionEventArray[currentFunction]->release();
+                        }
+                        functionEventArray[currentFunction] = tmpEvent;
+                        functionSpotTaken[currentFunction] = true;
+
+                    }
+                }
+
+
+                //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 || expectingDoStatement) {
+                    textDisplay << "Error: expected a 'do' statement\r\n";
+                    lineError = true;
+                }
+                if (blockDepth != 0)  {
+                    textDisplay << "Error: Can't declare a callback block within another block\r\n";
+                    lineError = true;
+                }
+                if (!lineError) {
+                    textDisplay.debug("Callback statement\r\n");
+                    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;
+                                textDisplay << "Error: Not a valid port number\r\n";
+                                lineError = true;
+                            }
+                        } else {
+                            textDisplay << "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 {
+                            textDisplay << "Error: No trigger direction given\r\n";
+                            lineError = true;
+                        }
+
+                    } else {
+                        if (!lineError) textDisplay << "Error: Not enough arguments for callback statement\r\n";
+                        lineError = true;
+                    }
+                    if (sz > 3) {
+                        if (!((sz == 4) && (tokens[i+3].compare("do") == 0))) {
+                            textDisplay << "Error: Too many arguments in callback statement\r\n";
+                            lineError = true;
+                        }
+                    }
+
+                    tmpEvent = findFirstUnUsed(eventBlock, NUMEVENTS);
+                    if (tmpEvent != NULL) {
+                        tmpEvent->isUsed = true;
+
+                    } else {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        lineError = true;
+                    }
+                    if (!lineError) {
+
+                        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-1].setTriggerUpEvent(tmpEventPtrArray.back());
+                        } else {
+
+                            portVector[currentTriggerPort-1].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) {
+                    textDisplay << "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 {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    lineError = true;
+                }
+                if (!lineError) {
+                    textDisplay.debug("If statement\r\n");
+                    //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 || expectingDoStatement) {
+                    textDisplay << "Error: expected a 'do' statement\r\n";
+                    lineError = true;
+                }
+                textDisplay.debug("Else statement\r\n");
+                //callbacks can't have else conditions
+                if ((!lineError) && (blockDepth < 2) && ((currentTriggerPort > -1)||(currentFunction > -1))) {
+                    textDisplay << "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
+                    textDisplay << "Error: else statement can only occur in an 'if' block\r\n";
+                    lineError = true;
+                }
+                if (!lineError) {
+                    elseFlag = true;
+                    expectingDoStatement = true;
+
+                }
+            } else if (tokens[i].compare("then") == 0) { //a then block
+                if (ifBlockInit || whileBlockInit) {
+                    textDisplay << "Error: expected a 'do' statement\r\n";
+                    lineError = true;
+                }
+
+                //trigger blocks can't have else conditions
+                if ((!lineError) && (blockDepth < 2) && (currentTriggerPort > -1)) {
+                    textDisplay << "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
+                    textDisplay << "Error: 'then' statement can only occur in a 'while' block\r\n";
+                    lineError = true;
+                }
+                if (!lineError) {
+                    thenFlag = true;
+                    expectingDoStatement = 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) {
+                    textDisplay << "Error: expected a 'do' statement\r\n";
+                    lineError = true;
+                }
+                textDisplay.debug("While statement\r\n");
+
+                if ((currentTriggerPort > 0) || (currentFunction > -1)) { //check to make sure we are inside a trigger block
+
+
+                } else {
+                    textDisplay << "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 {
+                    textDisplay << "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) {
+
+
+                                    //tmpEvent->whileLoopPeriod = period;
+                                    tmpEvent->setWhileLoopPeriod(period);
+                                    if (!elseFlag) {
+                                        tmpEvent->blockType = 5; //this is a while block
+
+                                        action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);
+                                        if (tmpAction == NULL) {
+                                            textDisplay << "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 {
+                                    textDisplay << "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) {
+                                        textDisplay << "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 {
+                            textDisplay << "Error: expected a 'do every' statement\r\n";
+                            lineError = true;
+                        }
+                    } else {
+                        textDisplay << "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 || expectingDoStatement) {
+                    textDisplay << "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) {
+                    textDisplay << "Error: Variable can't have a space in it.\r\n";
+                    lineError = true;
+                }
+
+                if (!lineError) {
+                    if (blockDepth > 0) {
+                        textDisplay.debug("Variable assignment statement\r\n");
+                        //action* tmpAction = evaluateAssignmentForAction(tmpString);
+                        action* tmpAction = evaluateAssignmentForAction(tmpString.data());
+                        if (tmpAction != NULL) {
+                            tmpEventPtrArray.back()->addAction(tmpAction);
+
+                        } else {
+                            lineError = true;
+                        }
+
+                    } else { //assignment was written outside of any block structure, so execute now
+
+
+                        //action* tmpAction = evaluateAssignmentForAction(tmpString);
+                        action* tmpAction = evaluateAssignmentForAction(tmpString.data());
+
+                        if (tmpAction != NULL) {
+                            tmpAction->execute();
+
+                            //delete tmpAction;
+                            tmpAction->release();
+                        } else {
+                            lineError = true;
+                        }
+                    }
+                }
+            } else {
+                //if there was no match to any of the above, an error is given
+                textDisplay << "Error: statement not understood.\r\n";
+                lineError = true;
+            }
+
+            if (lineError) {
+                 textDisplay.flush();
+                 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) {
+
+            textDisplay << "Line text: ";
+            /*
+            while (!tokens.empty()) {
+                textDisplay << tokens.front()<< " ";
+                //tokens.erase(tokens.begin());
+            }*/
+
+            //Display the line with the syntax error
+            for (int tokInd = 0; tokInd < tokens.size(); tokInd++) {
+                textDisplay << tokens.at(tokInd) << " ";
+            }
+            textDisplay << "\r\n";
+            textDisplay.flush();
+
+            currentBlock.resetBuffer();
+
+            //Clear the line tokens
+            while (!tokens.empty()) {
+                tokens.pop_back();
+            }
+
+            if (tmpEventPtrArray.size() > 0) {
+                tmpEventPtrArray.at(0)->release(); //release the unfinished block (and all children)
+            }
+            while (tmpEventPtrArray.size() > 0){
+                tmpEventPtrArray.pop_back();
+            }
+
+
+            //delete tmpEvent;
+            /*
+            if (tmpEvent != NULL) {
+                tmpEvent->release();
+            }
+            */
+        } else {
+
+            //Clear the line tokens
+            while (!tokens.empty()) {
+                tokens.pop_back();
+            }
+            //currentBlock.pop_back();
+
+        }
+
+    }
+
+    //make sure that all blocks have a matching end statement
+
+
+    if ((!lineError)&&(blockDepth > 0)) {
+        textDisplay << "Error: Missing 1 or more end statements\r\n";
+        lineError = true;
+        currentBlock.resetBuffer();
+    }
+
+    if ((!lineError)&&(blockDepth == 0)) {
+        textDisplay.send("~~~\r\n");
+    }
+
+    //displayMemoryLeft();
+    //DisplayRAMBanks();
+
+}
+
+
+//used to return a pointer to a variable, if it exists
+int* scriptStream::findIntVariable(string nameInput) {
+
+    textDisplay.debug("Finding variable: ");
+    textDisplay.debug(nameInput.data());
+    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-1].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-1].inState;
+            foundIt = true;
+        }
+    }
+
+    if (!foundIt) {
+        std::vector<intVariable*>::size_type sz = globalVariables.size();
+        int start = 0;
+        int end = nameInput.length()-1;
+
+        for (unsigned i = 0; i < sz; i++) {
+
+
+            if ((findStringLoc(nameInput.data(),globalVariables[i]->tag,start,end) != -1) && (strlen(globalVariables[i]->tag)==(end-start+1))) {
+                outPtr = &globalVariables[i]->value;
+                break;
+            }
+            /*
+            if (nameInput.compare(globalVariables[i]->tag) == 0) {
+                outPtr = &globalVariables[i]->value;
+                break;
+            }*/
+        }
+    }
+    textDisplay.debug("...done\r\n");
+
+    return outPtr;
+}
+
+
+//used to return a pointer to a variable, if it exists
+int* scriptStream::findIntVariable(const char* nameInput, int start, int end) {
+
+    textDisplay.debug("Finding variable...");
+    int* outPtr = NULL;
+    bool foundIt = false;
+
+    if (findStringLoc(nameInput,"portout[",start,end) != -1) {
+        int pos1 = findStringLoc(nameInput,"portout[",start,end)+8;
+        int pos2 = findStringLoc(nameInput, "]",pos1,end);
+        if ((pos1 == -1)||(pos2 == -1)) {
+            //syntax error
+            return NULL;
+        }
+
+        //int portnum = atoi(nameInput.substr(pos1,pos2-pos1).data());
+        long int portnum = strtol(nameInput+pos1,NULL,10);
+        if ((portnum > 0) && (portnum <= numPorts)) {
+            outPtr = &portVector[(int)portnum-1].outState;
+            foundIt = true;
+        }
+    } else if (findStringLoc(nameInput,"portin[",start,end) != -1) {
+        int pos1 = findStringLoc(nameInput,"portin[",start,end)+7;
+        int pos2 = findStringLoc(nameInput, "]",pos1,end);
+        if ((pos1 == -1)||(pos2 == -1)) {
+            //syntax error
+            return NULL;
+        }
+        long int portnum = strtol(nameInput+pos1,NULL,10);
+
+        if ((portnum > 0) && (portnum <= numPorts)) {
+            outPtr = &portVector[(int)portnum-1].inState;
+            foundIt = true;
+        }
+    }
+
+    if (!foundIt) {
+        std::vector<intVariable*>::size_type sz = globalVariables.size();
+        for (unsigned i = 0; i < sz; i++) {
+            //const char* varName = globalVariables[i]->tag.data();
+            if ((findStringLoc(nameInput,globalVariables[i]->tag,start,end) != -1) && (strlen(globalVariables[i]->tag)==(end-start+1))) {
+                outPtr = &globalVariables[i]->value;
+                break;
+            }
+        }
+    }
+    textDisplay.debug("done\r\n");
+
+    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(const char* expression) {
+
+    //action* tmpAction = new action(); //create a new action
+    action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);
+    if (tmpAction == NULL) {
+        textDisplay << "Error: no action memory slots available.\r\n";
+        return NULL;
+    }
+    int stringInd;
+    int stringInd2;
+    int afterEqualLoc;
+    int beforeEqualLoc;
+    int lastCharLoc = strlen(expression)-1;
+    int multiplierInt = 1;
+    //string afterEqual;
+    //string beforeEqual;
+    //The expression might have up to three variables
+    int* tmpVar;
+    int* tmpVar2;
+    int* tmpVar3;
+
+    stringInd = findStringLoc(expression,"=",0,strlen(expression)-1); //location of = sign, if it exists
+    if (stringInd == -1) {
+        //Make sure there is an equal sign
+        return NULL;
+    }
+
+    beforeEqualLoc = stringInd-1;
+    afterEqualLoc = stringInd+1;
+
+    //location of +/- sign (only one allowed)
+    stringInd2 = findStringLoc(expression,"+",afterEqualLoc,strlen(expression)-1);
+    if (stringInd2 == -1) {
+        stringInd2 = findStringLoc(expression,"-",afterEqualLoc,strlen(expression)-1);
+        multiplierInt = -1;
+
+    }
+
+    tmpVar = findIntVariable(expression,0,beforeEqualLoc); //returns pointer to the variable
+    if (findStringLoc(expression,"portout[",0,beforeEqualLoc) != -1) {  //set the output of a digital port
+        textDisplay.debug("Portout assignment\r\n");
+        int pos1 = findStringLoc(expression,"portout[",0,beforeEqualLoc)+8;
+        int pos2 = findStringLoc(expression,"]",pos1,beforeEqualLoc)-1;
+        if (pos2 < pos1) {
+            textDisplay << "Error: expected a ] character\r\n";
+            return NULL;
+        }
+
+        int portnum = -1;
+        if (isNum(expression,pos1,pos2)) {
+            portnum = atoi(expression+pos1);
+        }
+        int* tmpVar = findIntVariable(expression, pos1,pos2); //returns pointer to the variable, if given
+        int portVal = 0;
+        if ((tmpVar != NULL)||((portnum > 0) && (portnum <= numPorts))) {
+            if (isNum(expression,afterEqualLoc,lastCharLoc)) { //a simple numeric assign
+                portVal = atoi(expression+afterEqualLoc);
+                if ((portVal == 0) || (portVal == 1)) {
+                    //portMessage* tmpMessage = new portMessage(portVector[portnum],1,portVal);
+                    portMessage* tmpMessage = findFirstUnUsed(portMessageBlock, NUMPORTMESSAGES);
+                    if (tmpMessage == NULL) {
+                        textDisplay << "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,portVector);
+                        } else {
+                            tmpMessage->setMessage(tmpVar,0,portVal,portVector);
+                        }
+                    }
+
+
+                    tmpAction->set(tmpMessage);
+
+                } else {
+                    textDisplay << "Error: portouts can only be directly assigned a 1, 0 or 'flip'\r\n";
+                    //delete tmpAction;
+                    tmpAction->release();
+                    return NULL;
+                }
+            } else if (findStringLoc(expression,"flip",afterEqualLoc,lastCharLoc)!=-1) {
+                //portMessage* tmpMessage = new portMessage(portVector[portnum],1,-1);
+                portMessage* tmpMessage = findFirstUnUsed(portMessageBlock, NUMPORTMESSAGES);
+                if (tmpMessage == NULL) {
+                    textDisplay << "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,portVector);
+                    } else {
+                        tmpMessage->setMessage(tmpVar,0,-1,portVector);
+                    }
+                }
+                tmpAction->set(tmpMessage);
+            } else {
+                textDisplay << "Error: portouts can only be directly assigned a 1, 0, or 'flip'\r\n";
+                //delete tmpAction;
+                tmpAction->release();
+                return NULL;
+            }
+        } else {
+            textDisplay << "Port number not found (must be between 1 and " << numPorts << " or an existing variable)\r\n";
+            //delete tmpAction;
+            tmpAction->release();
+            return NULL;
+        }
+    } else if (findStringLoc(expression,"portin",0,stringInd)!=-1) {
+        textDisplay << "Error: portins can not be set\r\n";
+        //delete tmpAction;
+        tmpAction->release();
+        return NULL;
+    } else if (tmpVar != NULL) {
+        intOperation* tmpOp;
+        intOperation* tmpOp2;
+        if (isNum(expression,afterEqualLoc,lastCharLoc)) { //a simple numeric assign
+            textDisplay.debug("Numeric assignment\r\n");
+            //tmpOp = new intOperation(tmpVar, "=", atoi(afterEqual.data()));
+            tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+            if (tmpOp == NULL) {
+                textDisplay << "Error: no memory slots available.\r\n";
+                tmpAction->release();
+                return NULL;
+            } else {
+                tmpOp->set(tmpVar, "=", atoi(expression+afterEqualLoc));
+            }
+            tmpAction->set(tmpOp);
+
+        } else if ((stringInd2 == -1)&&(findStringLoc(expression,"random",afterEqualLoc,lastCharLoc)!=-1)) {
+            //assign random number
+            //no +/- detected, so its a simple assign
+            textDisplay.debug("Random number assignment\r\n");
+            int highVal = getRandomParam(expression,afterEqualLoc,lastCharLoc);
+
+            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) {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    tmpAction->release();
+                    return NULL;
+                } else {
+                    tmpOp->setRandOp(highVal, "=", tmpVar, false);
+                }
+                tmpAction->set(tmpOp);
+
+            } else {
+                //delete tmpAction;
+                tmpAction->release();
+                return NULL;
+            }
+        } else if ((stringInd2 == -1)&&(findStringLoc(expression,"clock()",afterEqualLoc,lastCharLoc)!=-1)) {
+            //assign clock value
+            //no +/- detected, so its a simple assign
+            textDisplay.debug("Clock assignment to variable\r\n");
+            tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+            if (tmpOp == NULL) {
+                textDisplay << "Error: no memory slots available.\r\n";
+                tmpAction->release();
+                return NULL;
+            } else {
+                tmpOp->setClockOp(tmpVar); //assigns the current clock value to tmpVar
+            }
+            tmpAction->set(tmpOp);
+
+        } else if (stringInd2 != -1) { //a +/- operation is there
+            textDisplay.debug("equation assignment\r\n");
+            //string multiplier("+");
+            char multiplier[3];
+            if (multiplierInt==1) {
+                strcpy(multiplier,"+");
+            } else {
+                strcpy(multiplier,"-");
+            }
+
+            /*
+            if (afterEqual[stringInd2] == '-') {
+                multiplier = "-";
+                multiplierInt = -1;
+            }*/
+            tmpVar2 = findIntVariable(expression,afterEqualLoc,stringInd2-1); //before the +/- sign
+            tmpVar3 = findIntVariable(expression,stringInd2+1,lastCharLoc); //after the +/- sign
+
+            if ((tmpVar2 != NULL) && isNum(expression,stringInd2+1,lastCharLoc)) { //variable +/- number
+                if (tmpVar2 == tmpVar) {
+                    //final sign is += or -=
+                    if (multiplierInt==1) {
+                        strcpy(multiplier,"+=");
+                    } else {
+                        strcpy(multiplier,"-=");
+                    }
+
+                    tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (tmpOp == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp->set(tmpVar, multiplier, atoi(expression+stringInd2+1));
+                    }
+                    tmpAction->set(tmpOp);
+
+                } else {
+
+                    tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (tmpOp2 == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+
+                        tmpOp2->set(tmpVar2,multiplier, atoi(expression+stringInd2+1));
+                        //tmpOp->set(tmpVar, tmpOp2);
+                    }
+
+                    tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (tmpOp == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpOp2->release();
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp->set(tmpVar, tmpOp2);
+                    }
+
+                    tmpAction->set(tmpOp);
+
+                }
+
+            } else if ((tmpVar3 != NULL) && isNum(expression,afterEqualLoc,stringInd2-1)) { //number +/- variable
+                if (tmpVar3 == tmpVar) {
+                    //final sign is += or -=
+                    if (multiplierInt==1) {
+                        strcpy(multiplier,"+=");
+                    } else {
+                        strcpy(multiplier,"-=");
+                    }
+
+                    tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (tmpOp == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp->set(tmpVar, multiplier, atoi(expression+afterEqualLoc));
+                    }
+                    tmpAction->set(tmpOp);
+
+                } else {
+
+                    tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (tmpOp2 == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp2->set(tmpVar3, multiplier, atoi(expression+afterEqualLoc));
+                    }
+                    tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+
+                    if (tmpOp == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpOp2->release();
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp->set(tmpVar, tmpOp2);
+                    }
+                    tmpAction->set(tmpOp);
+
+                }
+
+            } else if ((tmpVar2 != NULL) && (tmpVar3 != NULL)) { //variable +/- variable
+
+                tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                if (tmpOp2 == NULL) {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    tmpAction->release();
+                    return NULL;
+                } else {
+                    tmpOp2->set(tmpVar2, multiplier, tmpVar3);
+                }
+                tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+
+                if (tmpOp == NULL) {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    tmpOp2->release();
+                    tmpAction->release();
+                    return NULL;
+                } else {
+
+                    tmpOp->set(tmpVar, tmpOp2);
+                }
+                tmpAction->set(tmpOp);
+
+            } else if ( isNum(expression,stringInd2+1,lastCharLoc) && isNum(expression,afterEqualLoc,stringInd2-1) ) { //number +/- number
+                tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                if (tmpOp == NULL) {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    tmpAction->release();
+                    return NULL;
+                } else {
+                    tmpOp->set(tmpVar, "=", atoi(expression+afterEqualLoc) + (multiplierInt * atoi(expression+stringInd2+1)) );
+                }
+                tmpAction->set(tmpOp);
+
+            } else if ((findStringLoc(expression,"random", afterEqualLoc,stringInd2-1)!=-1)  && isNum(expression,stringInd2+1,lastCharLoc)) { //random +/- number
+                int highVal = getRandomParam(expression,afterEqualLoc,stringInd2-1);
+
+                if (highVal > 0) {
+
+
+                    tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (tmpOp2 == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp2->setRandOp(highVal, multiplier, atoi(expression+stringInd2+1),false);
+                    }
+                    tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+
+                    if (tmpOp == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpOp2->release();
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp->set(tmpVar, tmpOp2);
+                    }
+                    tmpAction->set(tmpOp);
+
+                } else {
+                    //delete tmpAction;
+                    tmpAction->release();
+                    return NULL;
+                }
+            } else if ((findStringLoc(expression,"random",afterEqualLoc,stringInd2-1)!=-1) && (tmpVar3 != NULL)) { //random +/- variable
+                int highVal = getRandomParam(expression,afterEqualLoc,stringInd2-1);
+
+                if (highVal > 0) {
+
+
+                    tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (tmpOp2 == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp2->setRandOp(highVal, multiplier, tmpVar3, false);
+                    }
+                    tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (tmpOp == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpOp2->release();
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp->set(tmpVar, tmpOp2);
+                    }
+                    tmpAction->set(tmpOp);
+
+                } else {
+                    //delete tmpAction;
+                    tmpAction->release();
+                    return NULL;
+                }
+
+
+            } else if ((findStringLoc(expression,"random",stringInd2+1,lastCharLoc)!=-1) && isNum(expression,afterEqualLoc,stringInd2-1)) { //number +/- random
+                int highVal = getRandomParam(expression,stringInd2+1,lastCharLoc);
+
+                if (highVal > 0) {
+
+
+                    tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (tmpOp2 == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+
+                        tmpOp2->setRandOp(highVal, multiplier, atoi(expression+afterEqualLoc),true); //the "true" signifies that the rand value came last
+                    }
+                    tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (tmpOp == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpOp2->release();
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp->set(tmpVar, tmpOp2);
+                    }
+                    tmpAction->set(tmpOp);
+
+                } else {
+                    //delete tmpAction;
+                    tmpAction->release();
+                    return NULL;
+                }
+            } else if ((findStringLoc(expression,"random",stringInd2+1,lastCharLoc)!=-1) && (tmpVar2 != NULL)) { //variable +/- random
+                int highVal = getRandomParam(expression,stringInd2+1,lastCharLoc);
+
+                if (highVal > 0) {
+
+
+                    tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (tmpOp2 == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+
+                        tmpOp2->setRandOp(highVal, multiplier, tmpVar2, true); //the "true" signifies that the rand value came last
+                    }
+                    tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (tmpOp == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpOp2->release();
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp->set(tmpVar, tmpOp2);
+                    }
+                    tmpAction->set(tmpOp);
+
+                } else {
+                    //delete tmpAction;
+                    tmpAction->release();
+                    return NULL;
+                }
+            }
+
+
+            else if ((findStringLoc(expression,"clock()",afterEqualLoc,stringInd2-1)!=-1) && isNum(expression,stringInd2+1,lastCharLoc)) { //clock() +/- number
+
+                tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                if (tmpOp2 == NULL) {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    tmpAction->release();
+                    return NULL;
+                } else {
+                    tmpOp2->setClockOp(multiplier, atoi(expression+stringInd2+1),false);
+                }
+                tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+
+                if (tmpOp == NULL) {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    tmpOp2->release();
+                    tmpAction->release();
+                    return NULL;
+                } else {
+                    tmpOp->set(tmpVar, tmpOp2);
+                }
+                tmpAction->set(tmpOp);
+
+
+            } else if ((findStringLoc(expression,"clock()",afterEqualLoc,stringInd2-1)!=-1) && (tmpVar3 != NULL)) { //clock() +/- variable
+
+
+
+                tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                if (tmpOp2 == NULL) {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    tmpAction->release();
+                    return NULL;
+                } else {
+                    tmpOp2->setClockOp(multiplier, tmpVar3, false);
+                }
+                tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                if (tmpOp == NULL) {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    tmpOp2->release();
+                    tmpAction->release();
+                    return NULL;
+                } else {
+                    tmpOp->set(tmpVar, tmpOp2);
+                }
+                tmpAction->set(tmpOp);
+
+            } else if ((findStringLoc(expression,"clock()",stringInd2+1,lastCharLoc)!=-1) && isNum(expression,afterEqualLoc,lastCharLoc)) { //number +/- clock()
+
+                tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                if (tmpOp2 == NULL) {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    tmpAction->release();
+                    return NULL;
+                } else {
+
+                    tmpOp2->setClockOp(multiplier, atoi(expression+afterEqualLoc), true); //the "true" signifies that clock() came last
+                }
+                tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                if (tmpOp == NULL) {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    tmpOp2->release();
+                    tmpAction->release();
+                    return NULL;
+                } else {
+                    tmpOp->set(tmpVar, tmpOp2);
+                }
+                tmpAction->set(tmpOp);
+
+
+            } else if ((findStringLoc(expression,"clock()",stringInd2+1,lastCharLoc)!=-1) && (tmpVar2 != NULL)) { //variable +/- clock()
+
+
+                tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                if (tmpOp2 == NULL) {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    tmpAction->release();
+                    return NULL;
+                } else {
+
+                    tmpOp2->setClockOp(multiplier, tmpVar2, true); //the "true" signifies that clock() came last
+                }
+                tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                if (tmpOp == NULL) {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    tmpOp2->release();
+                    tmpAction->release();
+                    return NULL;
+                } else {
+                    tmpOp->set(tmpVar, tmpOp2);
+                }
+                tmpAction->set(tmpOp);
+
+
+            }
+
+            else {
+                textDisplay << "Expression not understood: " << expression << "\r\n";
+                //delete tmpAction;
+                tmpAction->release();
+                return NULL;
+            }
+
+        } else if (findIntVariable(expression,afterEqualLoc,lastCharLoc) != NULL) { //assign value of another variable
+            tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+            if (tmpOp == NULL) {
+                textDisplay << "Error: no memory slots available.\r\n";
+                tmpAction->release();
+                return NULL;
+            } else {
+                tmpOp->set(tmpVar, "=", findIntVariable(expression,afterEqualLoc,lastCharLoc));
+            }
+            tmpAction->set(tmpOp);
+
+        } else {
+            textDisplay << "Variable not found: " << expression+afterEqualLoc << "\r\n";
+            tmpAction->release();
+            return NULL;
+        }
+
+    } else {
+        textDisplay << "Variable not found\r\n";
+        tmpAction->release();
+        return NULL;
+    }
+    textDisplay.debug("Assignment successful\r\n");
+    return tmpAction;
+}
+
+action* scriptStream::evaluateAssignmentForAction(string expression) {
+
+    //action* tmpAction = new action(); //create a new action
+    action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);
+    if (tmpAction == NULL) {
+        textDisplay << "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
+        textDisplay.debug("Portout assignment\r\n");
+        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) {
+                        textDisplay << "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,portVector);
+                        } else {
+                            tmpMessage->setMessage(tmpVar,0,portVal,portVector);
+                        }
+                    }
+
+
+                    tmpAction->set(tmpMessage);
+
+                } else {
+                    textDisplay << "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) {
+                    textDisplay << "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,portVector);
+                    } else {
+                        tmpMessage->setMessage(tmpVar,0,-1,portVector);
+                    }
+                }
+                tmpAction->set(tmpMessage);
+            } else {
+                textDisplay << "Error: portouts can only be directly assigned a 1, 0, or 'flip'\r\n";
+                //delete tmpAction;
+                tmpAction->release();
+                return NULL;
+            }
+        } else {
+            textDisplay << "Port number not found (must be between 1 and " << numPorts << " or an existing variable)\r\n";
+            //delete tmpAction;
+            tmpAction->release();
+            return NULL;
+        }
+    } else if (beforeEqual.find("portin") != std::string::npos) {
+        textDisplay << "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
+            textDisplay.debug("Numeric assignment\r\n");
+            //tmpOp = new intOperation(tmpVar, "=", atoi(afterEqual.data()));
+            tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+            if (tmpOp == NULL) {
+                textDisplay << "Error: no memory slots available.\r\n";
+                tmpAction->release();
+                return NULL;
+            } else {
+                tmpOp->set(tmpVar, "=", atoi(afterEqual.data()));
+            }
+            tmpAction->set(tmpOp);
+
+        } else if ((stringInd2 == std::string::npos)&&(afterEqual.find("random") != std::string::npos)) {
+            //assign random number
+            //no +/- detected, so its a simple assign
+            textDisplay.debug("Random number assignment\r\n");
+            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) {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    tmpAction->release();
+                    return NULL;
+                } else {
+                    tmpOp->setRandOp(highVal, "=", tmpVar, false);
+                }
+                tmpAction->set(tmpOp);
+
+            } else {
+                //delete tmpAction;
+                tmpAction->release();
+                return NULL;
+            }
+        } else if ((stringInd2 == std::string::npos)&&(afterEqual.find("clock()") != std::string::npos)) {
+            //assign clock value
+            //no +/- detected, so its a simple assign
+            textDisplay.debug("Clock assignment to variable\r\n");
+            tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+            if (tmpOp == NULL) {
+                textDisplay << "Error: no memory slots available.\r\n";
+                tmpAction->release();
+                return NULL;
+            } else {
+                tmpOp->setClockOp(tmpVar); //assigns the current clock value to tmpVar
+            }
+            tmpAction->set(tmpOp);
+
+        } else if (stringInd2 != std::string::npos) { //a +/- operation is there
+            textDisplay.debug("equation assignment\r\n");
+            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) {
+                        textDisplay << "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);
+
+                } else {
+
+                    tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (tmpOp2 == NULL) {
+                        textDisplay << "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) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpOp2->release();
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp->set(tmpVar, tmpOp2);
+                    }
+
+                    tmpAction->set(tmpOp);
+
+                }
+
+            } 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) {
+                        textDisplay << "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);
+
+                } else {
+
+                    tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (tmpOp2 == NULL) {
+                        textDisplay << "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) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpOp2->release();
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp->set(tmpVar, tmpOp2);
+                    }
+                    tmpAction->set(tmpOp);
+
+                }
+
+            } else if ((tmpVar2 != NULL) && (tmpVar3 != NULL)) { //variable +/- variable
+
+                tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                if (tmpOp2 == NULL) {
+                    textDisplay << "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) {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    tmpOp2->release();
+                    tmpAction->release();
+                    return NULL;
+                } else {
+
+                    tmpOp->set(tmpVar, tmpOp2);
+                }
+                tmpAction->set(tmpOp);
+
+            } else if ( isNumber(afterEqual.substr(stringInd2+1,std::string::npos)) && isNumber(afterEqual.substr(0,stringInd2)) ) { //number +/- number
+                tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                if (tmpOp == NULL) {
+                    textDisplay << "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);
+
+            } 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) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp2->setRandOp(highVal, multiplier.data(), atoi(afterEqual.substr(stringInd2+1,std::string::npos).data()),false);
+                    }
+                    tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+
+                    if (tmpOp == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpOp2->release();
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp->set(tmpVar, tmpOp2);
+                    }
+                    tmpAction->set(tmpOp);
+
+                } 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) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp2->setRandOp(highVal, multiplier.data(), tmpVar3, false);
+                    }
+                    tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (tmpOp == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpOp2->release();
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp->set(tmpVar, tmpOp2);
+                    }
+                    tmpAction->set(tmpOp);
+
+                } 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))) { //number +/- random
+                int highVal = getRandomParam(afterEqual.substr(stringInd2+1,std::string::npos));
+
+                if (highVal > 0) {
+
+
+                    tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (tmpOp2 == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+
+                        tmpOp2->setRandOp(highVal, multiplier.data(), atoi(afterEqual.substr(0, stringInd2).data()),true); //the "true" signifies that the rand value came last
+                    }
+                    tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (tmpOp == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpOp2->release();
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp->set(tmpVar, tmpOp2);
+                    }
+                    tmpAction->set(tmpOp);
+
+                } else {
+                    //delete tmpAction;
+                    tmpAction->release();
+                    return NULL;
+                }
+            } else if ((afterEqual.substr(stringInd2+1,std::string::npos).find("random") != std::string::npos) && (tmpVar2 != NULL)) { //variable +/- random
+                int highVal = getRandomParam(afterEqual.substr(stringInd2+1,std::string::npos));
+
+                if (highVal > 0) {
+
+
+                    tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (tmpOp2 == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+
+                        tmpOp2->setRandOp(highVal, multiplier.data(), tmpVar2, true); //the "true" signifies that the rand value came last
+                    }
+                    tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (tmpOp == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpOp2->release();
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp->set(tmpVar, tmpOp2);
+                    }
+                    tmpAction->set(tmpOp);
+
+                } else {
+                    //delete tmpAction;
+                    tmpAction->release();
+                    return NULL;
+                }
+            }
+
+
+
+
+
+            else if ((afterEqual.substr(0,stringInd2).find("clock()") != std::string::npos) && isNumber(afterEqual.substr(stringInd2+1,std::string::npos))) { //clock() +/- number
+
+
+
+                tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                if (tmpOp2 == NULL) {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    tmpAction->release();
+                    return NULL;
+                } else {
+                    tmpOp2->setClockOp(multiplier.data(), atoi(afterEqual.substr(stringInd2+1,std::string::npos).data()),false);
+                }
+                tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+
+                if (tmpOp == NULL) {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    tmpOp2->release();
+                    tmpAction->release();
+                    return NULL;
+                } else {
+                    tmpOp->set(tmpVar, tmpOp2);
+                }
+                tmpAction->set(tmpOp);
+
+
+            } else if ((afterEqual.substr(0,stringInd2).find("clock()") != std::string::npos) && (tmpVar3 != NULL)) { //clock() +/- variable
+
+
+
+                tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                if (tmpOp2 == NULL) {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    tmpAction->release();
+                    return NULL;
+                } else {
+                    tmpOp2->setClockOp(multiplier.data(), tmpVar3, false);
+                }
+                tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                if (tmpOp == NULL) {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    tmpOp2->release();
+                    tmpAction->release();
+                    return NULL;
+                } else {
+                    tmpOp->set(tmpVar, tmpOp2);
+                }
+                tmpAction->set(tmpOp);
+
+
+
+
+            } else if ((afterEqual.substr(stringInd2+1,std::string::npos).find("clock()") != std::string::npos) && isNumber(afterEqual.substr(0,stringInd2))) { //number +/- clock()
+
+
+
+                tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                if (tmpOp2 == NULL) {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    tmpAction->release();
+                    return NULL;
+                } else {
+
+                    tmpOp2->setClockOp(multiplier.data(), atoi(afterEqual.substr(0, stringInd2).data()),true); //the "true" signifies that clock() came last
+                }
+                tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                if (tmpOp == NULL) {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    tmpOp2->release();
+                    tmpAction->release();
+                    return NULL;
+                } else {
+                    tmpOp->set(tmpVar, tmpOp2);
+                }
+                tmpAction->set(tmpOp);
+
+
+            } else if ((afterEqual.substr(stringInd2+1,std::string::npos).find("clock()") != std::string::npos) && (tmpVar2 != NULL)) { //variable +/- clock()
+
+
+                tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                if (tmpOp2 == NULL) {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    tmpAction->release();
+                    return NULL;
+                } else {
+
+                    tmpOp2->setClockOp(multiplier.data(), tmpVar2, true); //the "true" signifies that clock() came last
+                }
+                tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                if (tmpOp == NULL) {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    tmpOp2->release();
+                    tmpAction->release();
+                    return NULL;
+                } else {
+                    tmpOp->set(tmpVar, tmpOp2);
+                }
+                tmpAction->set(tmpOp);
+
+
+            }
+
+            else {
+                textDisplay << "Expression not understood: " << afterEqual << "\r\n";
+                //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) {
+                textDisplay << "Error: no memory slots available.\r\n";
+                tmpAction->release();
+                return NULL;
+            } else {
+                tmpOp->set(tmpVar, "=", findIntVariable(afterEqual));
+            }
+            tmpAction->set(tmpOp);
+
+        } else {
+            textDisplay << "Variable not found: " << afterEqual << "\r\n";
+            //delete tmpAction;
+            tmpAction->release();
+            return NULL;
+        }
+
+    } else {
+        textDisplay << "Variable not found\r\n";
+        //delete tmpAction;
+        tmpAction->release();
+        return NULL;
+    }
+    textDisplay.debug("Assignment successful\r\n");
+    return tmpAction;
+}
+
+/*
+bool scriptStream::isOutsideParenth(string& expression,std::size_t foundItem) {
+
+    int pDepth = 0;  // How many nested parentheses
+
+    if (foundItem < expression.length()) {
+        for (int i = 0; i <= foundItem; i++) {
+            if (expression[i] == '(') {
+                pDepth++;
+            } else if (expression[i] == ')') {
+                pDepth--;
+            }
+        }
+        if (pDepth<=0) {
+
+            return true;
+        } else {
+
+            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.
+
+
+
+    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;
+
+    found = findFirstOrOutsideParenth(expression);
+    if (found==std::string::npos) { //no or conditions outside parentheses found, so we look for AND conditions
+        currentOperator = 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] == ')')) {
+
+            expression = expression.substr(1,expression.length()-2);
+            removedParenth = true;
+        }
+        if (removedParenth) { //we removed parentheses, so try again
+            textDisplay.debug("Condition: parenth removed\r\n");
+            return parseConditions(expression);
+        } else {
+            singleCondition = true; //we assume that the condition is non-compound, i.e., a>b
+        }
+    }
+
+    if (singleCondition) { //no compound conditions found
+        textDisplay.debug("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 = "==";
+            textDisplay.debug("==\r\n");
+        } else if ((equalStringInd == std::string::npos) && (greaterOrEqualStringInd != std::string::npos) &&
+                   (lessThanOrEqualStringInd == std::string::npos) && (notEqualStringInd == std::string::npos)){
+
+            generalCompareStringInd = greaterOrEqualStringInd;
+            compareString = ">=";
+            textDisplay.debug(">=\r\n");
+        } else if ((equalStringInd == std::string::npos) && (greaterOrEqualStringInd == std::string::npos) &&
+                   (lessThanOrEqualStringInd != std::string::npos) && (notEqualStringInd == std::string::npos)){
+
+            generalCompareStringInd = lessThanOrEqualStringInd;
+            compareString = "<=";
+            textDisplay.debug("<=\r\n");
+        } else if ((equalStringInd == std::string::npos) && (greaterOrEqualStringInd == std::string::npos) &&
+                   (lessThanOrEqualStringInd == std::string::npos) && (notEqualStringInd != std::string::npos)){
+
+            generalCompareStringInd = notEqualStringInd;
+            compareString = "!=";
+            textDisplay.debug("!=\r\n");
+        } 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;
+            textDisplay.debug(">\r\n");
+        } 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;
+            textDisplay.debug("<\r\n");
+
+        }else {
+            textDisplay << "Condition not understood: " << expression << "\r\n";
+            return 0;
+        }
+        textDisplay.debug("Allocating memory for condition...");
+        intCompare* newCompare = findFirstUnUsed(intCompareBlock, NUMINTCOMPARE);
+
+        if (newCompare == NULL) {
+            textDisplay << "Error: No memory slots available.";
+            return NULL;
+        }
+        newCondition = findFirstUnUsed(conditionBlock, NUMCONDITIONS);
+        if (newCondition == NULL) {
+            textDisplay << "Error: No memory slots available.";
+            return NULL;
+        }
+        textDisplay.debug("success.\r\n");
+        beforeComparator.reserve(tmpCondition.length());
+        textDisplay << beforeComparator.capacity();
+        textDisplay.flush();
+
+        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));
+                textDisplay.debug("Compare variable to variable\r\n");
+                newCompare->set(tmpVar,compareString.data(),tmpVar2);
+                newCondition->set(newCompare);
+
+
+            } else if (isNumber(afterComparator)) {
+                //intCompare* newCompare = new intCompare(tmpVar,compareString.data(),atoi(afterComparator.data()));
+                //currentEvent->addCondition(new condition(newCompare));
+                textDisplay.debug("Compare variable to number\r\n");
+                newCompare->set(tmpVar,compareString.data(),atoi(afterComparator.data()));
+                newCondition->set(newCompare);
+
+
+            } //more here
+
+        } else {
+            textDisplay << "Condition not understood: " << expression << "\r\n";
+
+            return NULL;
+        }
+
+    } else { //this is a compound condition (with either && or ||)
+        textDisplay.debug("Compound condition\r\n");
+        afterComparator = expression.substr(found+2,std::string::npos);
+        beforeComparator = expression.substr(0,found);
+        newCondition = findFirstUnUsed(conditionBlock, NUMCONDITIONS);
+        if (newCondition == NULL) {
+            textDisplay << "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::isOutsideParenth(const char* expression,int foundItem,int start, int end) {
+
+    int pDepth = 0;  // How many nested parentheses
+
+    if ((foundItem >= start)&&(foundItem<=end)&&(foundItem < strlen(expression))&&(end < strlen(expression))&&(start <= end)&&(start>=0)) {
+        for (int i = start; i <= foundItem; i++) {
+            if (expression[i] == '(') {
+                pDepth++;
+            } else if (expression[i] == ')') {
+                pDepth--;
+            }
+        }
+        if (pDepth<=0) {
+
+            return true;
+        } else {
+
+            return false;
+        }
+    } else {
+        //error handling defaults in a true condition
+        return true;
+    }
+
+}
+
+int scriptStream::findFirstOrOutsideParenth(const char* expression,int start, int end) {
+
+    int foundItem = findStringLoc(expression,"||",start,end);
+    while (foundItem != -1) {
+        if (isOutsideParenth(expression,foundItem,start,end)) {
+            //it's out side of ()
+            break;
+        }
+        //not outside ()
+        foundItem = findStringLoc(expression,"||",foundItem+1,end);
+    }
+    return foundItem;
+}
+
+int scriptStream::findFirstAndOutsideParenth(const char* expression,int start, int end) {
+
+    int foundItem = findStringLoc(expression,"&&",start,end);
+    while (foundItem != -1) {
+        if (isOutsideParenth(expression,foundItem,start,end)){
+            break;
+        }
+        foundItem = findStringLoc(expression,"||",foundItem+1,end);
+    }
+    return foundItem;
+}
+
+
+condition* scriptStream::parseConditions(const char* expression,int start, int end) {
+
+
+    //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.
+
+
+
+    condition* newCondition = NULL;
+    bool singleCondition = false; //no compound conditions
+    //string afterComparator;
+    //string beforeComparator;
+    int afterComparatorLoc;
+    int beforeComparatorLoc;
+
+
+
+    int 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;
+
+    found = findFirstOrOutsideParenth(expression,start,end);
+    if (found==-1) { //no or conditions outside parentheses found, so we look for AND conditions
+        currentOperator = AND_CONDITION;
+
+        found = findFirstAndOutsideParenth(expression,start,end);
+    }
+    if (found==-1) { //no or/and conditions outside parentheses found
+        //if the expression is encapsulated in parentheses, remove the parentheses
+        bool removedParenth = false;
+        if ((expression[start] == '(') && (expression[end] == ')')) {
+
+            start++;
+            end--;
+
+            //expression = expression.substr(1,expression.length()-2);
+            removedParenth = true;
+        }
+        if (removedParenth) { //we removed parentheses, so try again
+            textDisplay.debug("Condition: parenth removed\r\n");
+            return parseConditions(expression,start,end);
+        } else {
+            singleCondition = true; //we assume that the condition is non-compound, i.e., a>b
+        }
+    }
+
+    if (singleCondition) { //no compound conditions found
+        textDisplay.debug("Single condition: ");
+        int equalStringInd;
+        int greaterOrEqualStringInd;
+        int lessThanOrEqualStringInd;
+        int notEqualStringInd;
+        int greaterThanStringInd;
+        int lessThanStringInd;
+        int generalCompareStringInd;
+
+
+        //string tmpCondition = expression;
+        char compareString[3];
+        //The expression might have up to three variables
+        int* tmpVar;
+        int* tmpVar2;
+        //int* tmpVar3;
+
+        int offset = 0;
+        equalStringInd = findStringLoc(expression,"==",start,end);  //location of comparator
+        greaterOrEqualStringInd = findStringLoc(expression,">=",start,end); //location of comparator
+        lessThanOrEqualStringInd = findStringLoc(expression,"<=",start,end); //location of comparator
+        notEqualStringInd = findStringLoc(expression,"!=",start,end); //location of comparator
+        greaterThanStringInd = findStringLoc(expression,">",start,end); //location of comparator
+        lessThanStringInd = findStringLoc(expression,"<",start,end); //location of comparator
+
+        if ((equalStringInd != -1) && (greaterOrEqualStringInd == -1) &&
+            (lessThanOrEqualStringInd == -1) && (notEqualStringInd == -1)){
+
+            generalCompareStringInd = equalStringInd;
+            strcpy(compareString,"==");
+            //compareString = "==";
+            textDisplay.debug("==\r\n");
+        } else if ((equalStringInd == -1) && (greaterOrEqualStringInd != -1) &&
+                   (lessThanOrEqualStringInd == -1) && (notEqualStringInd == -1)){
+
+            generalCompareStringInd = greaterOrEqualStringInd;
+            strcpy(compareString,">=");
+            //compareString = ">=";
+            textDisplay.debug(">=\r\n");
+        } else if ((equalStringInd == -1) && (greaterOrEqualStringInd == -1) &&
+                   (lessThanOrEqualStringInd != -1) && (notEqualStringInd == -1)){
+
+            generalCompareStringInd = lessThanOrEqualStringInd;
+            strcpy(compareString,"<=");
+            //compareString = "<=";
+            textDisplay.debug("<=\r\n");
+        } else if ((equalStringInd == -1) && (greaterOrEqualStringInd == -1) &&
+                   (lessThanOrEqualStringInd == -1) && (notEqualStringInd != -1)){
+
+            generalCompareStringInd = notEqualStringInd;
+            strcpy(compareString,"!=");
+            //compareString = "!=";
+            textDisplay.debug("!=\r\n");
+        } else if ((equalStringInd == -1) && (greaterOrEqualStringInd == -1) &&
+                   (lessThanOrEqualStringInd == -1) && (notEqualStringInd == -1) &&
+                   (greaterThanStringInd != -1) && (lessThanStringInd == -1)){
+
+            generalCompareStringInd = greaterThanStringInd;
+            strcpy(compareString,">");
+            //compareString = ">";
+            offset = 1;
+            textDisplay.debug(">\r\n");
+        } else if ((equalStringInd == -1) && (greaterOrEqualStringInd == -1) &&
+                   (lessThanOrEqualStringInd == -1) && (notEqualStringInd == -1) &&
+                   (greaterThanStringInd == -1) && (lessThanStringInd != -1)){
+
+            generalCompareStringInd = lessThanStringInd;
+            strcpy(compareString,"<");
+            //compareString = "<";
+            offset = 1;
+            textDisplay.debug("<\r\n");
+
+        }else {
+            textDisplay << "Condition not understood: " << expression << "\r\n";
+            return 0;
+        }
+        textDisplay.debug("Allocating memory for condition...");
+        intCompare* newCompare = findFirstUnUsed(intCompareBlock, NUMINTCOMPARE);
+
+        if (newCompare == NULL) {
+            textDisplay << "Error: No memory slots available.";
+            return NULL;
+        }
+        newCondition = findFirstUnUsed(conditionBlock, NUMCONDITIONS);
+        if (newCondition == NULL) {
+            textDisplay << "Error: No memory slots available.";
+            return NULL;
+        }
+        textDisplay.debug("success.\r\n");
+        //beforeComparator.reserve(tmpCondition.length());
+        //textDisplay << beforeComparator.capacity();
+        //textDisplay.flush();
+
+        afterComparatorLoc = generalCompareStringInd+2-offset;
+        beforeComparatorLoc = generalCompareStringInd-1;
+
+        //afterComparator = tmpCondition.substr(generalCompareStringInd+2-offset,std::string::npos);
+        //beforeComparator = tmpCondition.substr(0,generalCompareStringInd);
+
+        //tmpVar = findIntVariable(beforeComparator); //returns pointer to the variable
+        tmpVar = findIntVariable(expression,start,beforeComparatorLoc);
+
+        if (tmpVar != NULL) { //before the comparator is a single variable
+            tmpVar2 = findIntVariable(expression, afterComparatorLoc, end); //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));
+                textDisplay.debug("Compare variable to variable\r\n");
+                newCompare->set(tmpVar,compareString,tmpVar2);
+                newCondition->set(newCompare);
+
+
+            } else if (isNum(expression, afterComparatorLoc, end)) {
+                //intCompare* newCompare = new intCompare(tmpVar,compareString.data(),atoi(afterComparator.data()));
+                //currentEvent->addCondition(new condition(newCompare));
+                textDisplay.debug("Compare variable to number\r\n");
+                newCompare->set(tmpVar,compareString,atoi(expression+afterComparatorLoc));
+                newCondition->set(newCompare);
+
+
+            } else {
+                textDisplay << "Condition not understood: " << expression << "\r\n";
+                return NULL;
+            }//more here
+
+        } else {
+            textDisplay << "Condition not understood: " << expression << "\r\n";
+
+            return NULL;
+        }
+
+    } else { //this is a compound condition (with either && or ||)
+        textDisplay.debug("Compound condition\r\n");
+        afterComparatorLoc = found+2;
+        beforeComparatorLoc = found-1;
+        //afterComparator = expression.substr(found+2,std::string::npos);
+        //beforeComparator = expression.substr(0,found);
+        newCondition = findFirstUnUsed(conditionBlock, NUMCONDITIONS);
+        if (newCondition == NULL) {
+            textDisplay << "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(expression,start,beforeComparatorLoc);
+        if (cond1 == NULL) {
+            newCondition->release();
+            return NULL;
+        }
+        condition* cond2 = parseConditions(expression,afterComparatorLoc,end);
+        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);
+    newCondition = parseConditions(expression.data(),0,expression.length()-1);
+    if (newCondition == NULL) {
+        return false;
+    } else {
+        currentEvent->addCondition(newCondition);
+        return true;
+    }
+}
+
+int scriptStream::getRandomParam(const char* expression,int start, int end) {
+
+    int pos1 = findStringLoc(expression,"random(",start,end)+7;
+    int pos2 = findStringLoc(expression,")",pos1,end);
+    if (pos2 == -1) {
+        textDisplay << "Error: bad syntax\r\n";
+        return 0;
+    }
+
+    int highVal = atoi(expression+pos1);
+
+    if ((highVal > 0)) {
+        return highVal;
+    } else {
+        textDisplay << "Error: random parameter must be 1 or more\r\n";
+        return 0;
+    }
+}
+
+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 {
+        textDisplay << "Error: random parameter must be 1 or more\r\n";
+        return 0;
+    }
+}
+
+int scriptStream::findStringLoc(const char *refString, const char *findString,int start,int end) {
+    //look for 'findString' inside 'refString', only considering characters in between 'start' and 'end'
+    //return -1 if not found
+
+    if ((start < strlen(refString))&&(end < strlen(refString))&&(end >= start)) {
+        const char* charPtr = strstr(refString+start,findString);
+        //if found, make sure it was containted within the start and end bounds
+        if ((charPtr != NULL) && ((int)(charPtr-refString) <= (end-strlen(findString)+1))) {
+            return (int)(charPtr-refString);
+        }
+    }
+    return -1;
+}
+
+bool scriptStream::isNum(const char *expression, int start, int end) {
+
+    if ((start>0)&&(end<strlen(expression))&&(start<=end)) {
+
+        bool outcome = true;
+        while (start <= end) {
+            //look for any digit, or a - sign
+            if (!((expression[start] >= 45) && (expression[start] <= 57) && (expression[start] != 46) && (expression[start] != 47))) {
+                outcome = false;
+                break;
+            }
+            start++;
+        }
+        return outcome;
+    }
+    return false;
+}
+
+bool scriptStream::areStringsSame(const char *str1, const char *str2, int start, int end) {
+    if ((findStringLoc(str1,str2,start,end) != -1) && (strlen(str2)==(end-start+1))) {
+        return true;
+    } else {
+        return false;
+    }
+
+
+}
+
+void scriptStream::clearEnvironmentVariables(int clearMode) {
+    //Modes:
+
+    //clear callbacks, functions, and queue
+    if (clearMode & BLOCKMEMORYTYPES) {
+        for (int pNum = 0; 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;
+
+        }
+        for (int i = 0; i < NUMFUNCTIONS; i++) {
+            functionSpotTaken[i] = false;
+            functionEventArray[i] = NULL;
+        }
+        for (int i = 0; i < NUMEVENTS; i++) {
+            eventBlock[i].release();
+        }
+        for (int i = 0; i < NUMCONDITIONS; i++) {
+            conditionBlock[i].release();
+        }
+        for (int i = 0; i < NUMINTCOMPARE; i++) {
+            intCompareBlock[i].release();
+        }
+        for (int i = 0; i < NUMACTIONS; i++) {
+            actionBlock[i].release();
+        }
+        for (int i = 0; i < NUMPORTMESSAGES; i++) {
+            portMessageBlock[i].release();
+        }
+        for (int i = 0; i < NUMINTOPERATIONS; i++) {
+            intOperationBlock[i].release();
+        }
+        for (int i = 0; i < NUMDISPLAYACTIONS; i++) {
+            displayActionBlock[i].release();
+        }
+        for (int i = 0; i <NUMTRIGGERACTIONS; i++) {
+            triggerFunctionActionBlock[i].release();
+        }
+
+        queuePtr->eraseQueue();
+    }
+
+    if (clearMode & VARIABLEMEMORYTYPES) {
+        while (!globalVariables.empty()) {
+            delete globalVariables.back();
+            globalVariables.pop_back();
+        }
+    }
+
+    if (clearMode & ENVSETTINGSMEMORYTYPES) {
+        //set all environment settings to default values
+        broadCastStateChanges = true;
+        for (int i=0;i<NUMPORTS;i++) {
+            system->setPortUpdatesOn(i);
+        }
+    }
+
+
+
+}
+
diff -r 000000000000 -r ecf80f0172d0 behave.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/behave.h	Mon Feb 08 18:56:09 2016 +0000
@@ -0,0 +1,571 @@
+//#include "mbed.h"
+#include <stdint.h>
+#include <string.h>
+#include <string>
+#include <vector>
+#include <list>
+#include <deque>
+#include <queue>
+#include "hardwareInterface.h"
+
+
+//#define MBEDHARDWARE  //here is where we define which platform we are compiling for
+//#define FPGAHARDWARE
+#define NUCLEOHARDWARE
+
+#define MAXVARNAMESIZE 30 //The maximum number of characters of a variable name
+
+#ifdef MBEDHARDWARE
+    #include "mbedInterface.h"
+#endif
+#ifdef FPGAHARDWARE
+    #include "fpgaInterface.h"
+#endif
+#ifdef NUCLEOHARDWARE
+    #include "nucleoInterface.h"
+#endif
+
+#define BLOCKMEMORYTYPES 1
+#define VARIABLEMEMORYTYPES 2
+#define ENVSETTINGSMEMORYTYPES 4
+
+
+/*
+#define NUMEVENTS 50
+#define NUMCONDITIONS 150
+#define NUMINTCOMPARE 150
+#define NUMACTIONS 150
+#define NUMPORTMESSAGES 150
+#define NUMINTOPERATIONS 150
+#define NUMDISPLAYACTIONS 30
+#define NUMTRIGGERACTIONS 30
+#define NUMFUNCTIONS 50
+#define INPUTCHARBUFFERSIZE 3072
+*/
+
+#define ARITHMATIC_CONDITION    0
+#define OR_CONDITION    1
+#define AND_CONDITION    2
+
+extern "C" void mbed_reset();//reset mbed through software
+
+
+
+using namespace std;
+
+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();
+    //digitalPort(sDigitalOut* DOP, sDigitalIn* DIP);
+    void init(sDigitalOut* DOP, sDigitalIn* DIP);
+    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:
+
+    sDigitalOut* outPin;
+    sDigitalIn*  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(std::string& tagInput, int initialValue);
+    void set(std::string& tagInput, int initialValue);
+    int value;
+    //string tag;
+    char tag[MAXVARNAMESIZE+1];
+    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();
+    void set(int* variable, string varNameInput);
+    void set(string text);
+    bool isUsed;
+    void execute();
+    void release();
+
+private:
+    int* dVariable;
+    string dText;
+
+};
+
+class triggerFunctionAction {
+
+public:
+    triggerFunctionAction();
+    triggerFunctionAction(int functionNum);
+    void set(int functionNum);
+    bool isUsed;
+    void execute();
+    void release();
+private:
+    int functionNum;
+
+
+};
+
+//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();
+
+    //Supported operations with rand:
+    //a = rand(x)
+    //a = rand(x) + 3
+    //a = rand(x) + b
+    void setRandOp(int randParam, const char* cmpString, int cmpValInput, bool flipped);
+    void setRandOp(int randParam, const char* cmpString, int* cmpIntVarInput, bool flipped);
+
+    //Supported regular operations
+    //a = 5
+    //a = b
+    //a = b + 6
+    //a = b + c
+    void set(int* intVarInput, const char* cmpString, int cmpValInput);
+    void set(int* intVarInput, const char* cmpString, int* cmpIntVarInput);
+    void set(int* intVarInput, intOperation* operationInput);
+
+
+    //Supported operations with clock()
+    //a = clock()
+    //a = clock() + 5
+    //a = clock() + b
+    void setClockOp(int* intVarInput);
+    void setClockOp(const char* cmpString, int cmpValInput, bool flip);
+    void setClockOp(const char* cmpString, int* cmpIntVarInput, bool flip);
+
+    void release();
+    bool isUsed;
+    int execute();
+
+private:
+    int randHigh;
+    int* cmpVal;
+    int* intVal;
+    intOperation* opPtr;
+    bool cmpValGlobal;
+    bool isClockAssign; //if the current clock value is part of the operation
+    bool inputsFlipped;
+    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, digitalPort* portVector); //whichToSet:
+
+    void execute();
+    void release();
+    bool isUsed;
+
+private:
+    int whichToSet; //hard coded port number
+    int* port; //alternative variable port number
+    int value;
+
+    digitalPort* portVector;
+
+};
+
+//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(sSound* soundInput);
+    action(triggerFunctionAction* triggerFuncInput);
+    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(sSound* soundInput);
+    void set(triggerFunctionAction* triggerFuncInput);
+    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;
+    sSound* sound;
+    triggerFunctionAction* triggerFunc;
+    //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();
+    void addEventToQueue(event* eventInput, uint32_t delay);
+    void eraseQueue(); //clear all future events
+    void check(void);
+
+private:
+    std::vector<queueItem> events;
+    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.  Not currently in use.
+class functionItem {
+public:
+    functionItem(action* actionInput, string tagInput);
+    ~functionItem();
+    string tag;
+    action* actionPtr;
+};
+
+class blockBuffer {
+
+public:
+    blockBuffer();
+    bool addLine(char* input, int numChars);
+    string getNextLine();
+    int16_t linesAvailable();
+    bool empty();
+    void resetBuffer();
+
+private:
+#ifdef MBEDHARDWARE
+    //On the MBED, we need to put this on a different memory bank
+    __attribute((section("AHBSRAM1"),aligned)) char charBuffer[INPUTCHARBUFFERSIZE];
+#else
+    char charBuffer[INPUTCHARBUFFERSIZE];
+#endif
+    int16_t bufferWritePos;
+    int16_t bufferReadPos;
+    int16_t _linesAvailable;
+
+};
+
+//Parser for the incoming text.  The parser is called when a line terminates with a semicolon (;).
+//Only the final line in a callback block should have a semicolon.
+class scriptStream {
+public:
+    scriptStream(digitalPort* portVectorInput, int numPortsInput, eventQueue* queueInput, sSystem* system);
+    void parseBlock(); //Parses everything since the last semicolon was found
+    void addLineToCurrentBlock(char* lineInput); // if the line did not end with a semicolon, add it to the current block
+
+private:
+
+    int* findIntVariable(string nameInput); //used to retrieve the pointer to the designated variable if it exists
+    int* findIntVariable(const char* nameInput); //used to retrieve the pointer to the designated variable if it exists
+    int* findIntVariable(const char* nameInput, int start, int end); //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)
+    action* evaluateAssignmentForAction(const char* 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(const char* expression,int start, int end); //parses a condition statement (a == b && c > d)
+    int findFirstOrOutsideParenth(const char* expression, int start, int end);
+    int findFirstAndOutsideParenth(const char* expression, int start, int end);
+    bool isOutsideParenth(const char* expression,int foundItem, int start, int end);
+    bool isNum(const char* expression, int start, int end);
+    bool areStringsSame(const char* str1, const char* str2, int start, int end);
+    int getRandomParam(string expression);
+    int getRandomParam(const char* expression,int start,int end);
+    int findStringLoc(const char* refString,const char* findString,int start, int end);
+    void clearEnvironmentVariables(int mode);
+
+    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;
+    bool expectingDoStatement;
+    int currentDelay;
+    event* tmpEvent;
+    string tmpString;
+
+    vector<intVariable*> globalVariables;
+    vector<event*> tmpEventPtrArray;
+    //event* functionEventArray[NUMFUNCTIONS];
+    //bool   functionSpotTaken[NUMFUNCTIONS];
+
+    //vector<functionItem*> functionArray; //any blocks declared outsite callback blocks are stored here
+    //list<string> currentBlock;
+    blockBuffer currentBlock;
+    digitalPort* portVector;
+    sSystem* system;
+
+
+
+    int numPorts;
+    eventQueue* queuePtr;
+
+};
+
+
+class mainLoop
+
+{
+public:
+    mainLoop();
+    void init();
+    void exec();
+private:
+    void eraseBuffer();
+    uint32_t currentDIOstate[2];
+    bool digitalInChanged;
+    bool digitalOutChanged;
+    scriptStream *parser;
+    sSystem *hardware; //hardware interface
+    sSerialPort *pc; //communication to computer
+    char buffer[256];
+    digitalPort ports[NUMPORTS];
+
+
+
+};
diff -r 000000000000 -r ecf80f0172d0 hardwareInterface.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hardwareInterface.cpp	Mon Feb 08 18:56:09 2016 +0000
@@ -0,0 +1,340 @@
+#include "hardwareInterface.h"
+//#include <ostream>
+#include <sstream>
+
+using namespace std;
+
+//In debug mode, debug messages output to the screen
+#ifdef DEBUGOUTPUT
+bool debugOut = true;
+#else
+bool debugOut = false;
+#endif
+
+uint32_t timeKeeper; //the main clock (updated every ms)
+bool resetTimer;
+bool clockSlave;
+bool changeToSlave;
+bool changeToStandAlone;
+
+
+#ifdef MBEDHARDWARE
+
+//On the MBED, this needs to be put on a defined bank of memory, or else we run out of memory
+__attribute((section("AHBSRAM0"),aligned)) outputStream textDisplay(512);
+
+#else
+outputStream textDisplay(256);
+
+#endif
+
+
+//---------------------------------------------------------
+
+sSystem::sSystem() {
+    for (int i=0;i<32;i++) {
+        ignorePortUpdates[i] = false;
+    }
+}
+
+//The user can toggle whether a particular port triggers a state update report every time it changes
+//This is useful for inputs that toggle continuously.
+void sSystem::setPortUpdatesOff(int portNum) {
+    ignorePortUpdates[portNum] = true;
+}
+
+void sSystem::setPortUpdatesOn(int portNum) {
+    ignorePortUpdates[portNum] = false;
+}
+
+bool* sSystem::getIgnoreUpdates() {
+    return ignorePortUpdates;
+}
+
+void sSystem::immediateClockReset() {
+    //For external clock reset
+    timeKeeper = 0;
+    textDisplay << timeKeeper << " Clock reset\r\n";
+}
+
+void sSystem::mainLoopToDo() {
+
+}
+
+void sSystem::pauseInterrupts() {
+
+}
+
+void sSystem::resumeInterrupts() {
+
+}
+
+int sSystem::getPendingFunctionTriggers(uint16_t *bufferPtr) {
+    return 0;
+}
+
+uint32_t sSystem::getDigitalOutputChangeFlags() {
+
+}
+
+uint32_t sSystem::getDigitalInputChangeFlags() {
+
+}
+
+//------------------------------------------------------
+sDigitalOut::sDigitalOut() {
+
+}
+
+//----------------------------------------------------
+sDigitalIn::sDigitalIn() {
+    lastDownEvent.triggered = false;
+    lastUpEvent.triggered = false;
+    bufferedDownEvent.triggered = false;
+    bufferedUpEvent.triggered = false;
+    updating = false;
+}
+
+void sDigitalIn::addStateChange(int newState, uint32_t timeStamp) {
+
+    //With levers and beam breaks, there will be flutter when triggers happen.
+    //The goal is to capture the initial event time, so we ignore extra triggers
+    //until it has been processed
+    if (!updating) {
+        if ((newState == 0) && (!lastDownEvent.triggered)){
+            lastDownEvent.timeStamp = timeStamp;
+            lastDownEvent.triggered = true;
+        } else if ((newState == 1) && (!lastUpEvent.triggered)) {
+            lastUpEvent.timeStamp = timeStamp;
+            lastUpEvent.triggered = true;
+        }
+    } else {
+        //If we are currently checking this input, then we buffer the trigger and deal with it after
+        if (newState == 0){
+            bufferedDownEvent.timeStamp = timeStamp;
+            bufferedDownEvent.triggered = true;
+        } else if (newState == 1) {
+            bufferedUpEvent.timeStamp = timeStamp;
+            bufferedUpEvent.triggered = true;
+        }
+    }
+    /*
+    if ((newState == 0) && (!lastDownEvent.triggered)){
+        lastDownEvent.timeStamp = timeStamp;
+        lastDownEvent.triggered = true;
+    } else if ((newState == 1) && (!lastUpEvent.triggered)) {
+        lastUpEvent.timeStamp = timeStamp;
+        lastUpEvent.triggered = true;
+    }*/
+}
+
+void sDigitalIn::setUpdate(bool state) {
+    updating = state; //If true, then we buffer any trigger events until the update check is done.
+    if (!updating) {
+        if (bufferedUpEvent.triggered) {
+            lastUpEvent = bufferedUpEvent;
+        }
+        if (bufferedDownEvent.triggered) {
+            lastDownEvent = bufferedDownEvent;
+        }
+        bufferedDownEvent.triggered = false;
+        bufferedUpEvent.triggered = false;
+    }
+}
+
+//-----------------------------------------------------
+sSerialPort::sSerialPort() {
+
+}
+
+//------------------------------------------------------
+
+sSound::sSound(void):
+    fileNameExists(false),
+    fileNum(0),
+    volumePtr(NULL),
+    volume(-1),
+    play(true),
+    reset(false) {
+}
+
+void sSound::setFile(string fileNameIn) {
+    for (int i = 0; i < 20; i++) {
+        fileName[i] = NULL;
+    }
+    size_t length = fileNameIn.size();
+    if (length <= 20) {
+        fileNameIn.copy(fileName, length, 0);
+        fileNameExists = true;
+    }
+}
+
+void sSound::setFile(unsigned char filenNumIn) { //overload setFile to work with SOMO module
+    fileNum = filenNumIn;
+}
+
+void sSound::setVolume(int volumeIn) {
+
+    if ((volumeIn >= 0) && (volumeIn < 256)) {
+        volume = volumeIn;
+        volumePtr = NULL;
+    }
+}
+
+void sSound::setVolume(int* volumeIn) {
+
+    volume = -1;
+    volumePtr = volumeIn;
+
+}
+
+void sSound::setPlayback(bool playIn) {
+    play = playIn;
+}
+
+void sSound::setReset() {
+    reset = true;
+}
+
+
+//-----------------------------------------------------
+outputStream::outputStream(int bufferSizeIn):
+    readHead(0),
+    writeHead(0),
+    totalWriteHead(0),
+    totalReadHead(0),
+    bufferSize(bufferSizeIn),
+    unsentData(false),
+    serialPtr(NULL) {
+
+    outputBuffer = new char[bufferSize];
+
+}
+
+outputStream::~outputStream() {
+    delete[] outputBuffer;
+}
+
+void outputStream::setSerial(sSerialPort *s) {
+    serialPtr = s;
+}
+
+//used to immediately write to serial port
+void outputStream::flush() {
+    if (serialPtr != NULL) {
+        while(unsentData) {
+            serialPtr->writeChar(getNextChar());
+        }
+    }
+}
+
+//adds text to the buffer
+void outputStream::send(const string &outputString) {
+    int strLen = outputString.size();
+
+    int total = 0;
+    int chunk = 0;
+    if (totalWriteHead+strLen > (totalReadHead + bufferSize)) {
+        //We don't have enough space in the buffer, so flush it
+        flush();
+    }
+    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;
+        }
+    }
+}
+
+//adds text to the buffer
+void outputStream::send(const char *s) {
+    int strLen = strlen(s);
+
+    int total = 0;
+    //int chunk = 0;
+    if (totalWriteHead+strLen > (totalReadHead + bufferSize)) {
+        //We don't have enough space in the buffer, so flush it
+        flush();
+    }
+    if (!(totalWriteHead+strLen > (totalReadHead + bufferSize))) {
+        while (strLen - total > 0) {
+            strncpy(outputBuffer + writeHead, s+total,1);
+            total++;
+            writeHead = (writeHead + 1) % bufferSize;
+            totalWriteHead += 1;
+
+            /*
+            chunk = min((bufferSize - writeHead), strLen - total);
+            strncpy(outputBuffer + writeHead,);
+            outputString.copy(outputBuffer + writeHead, chunk, total);
+            writeHead = (writeHead + chunk) % bufferSize;
+            totalWriteHead += chunk;
+            total += chunk;
+            */
+        }
+        if (total > 0) {
+            unsentData = true;
+        }
+    }
+}
+
+void outputStream::debug(const char *s) {
+    //send to serial immediately, but only if debugOut is true
+    if (debugOut) {
+        string tmpString = string(s);
+        send(tmpString);
+        flush();
+    }
+}
+
+//Overloaded << operator to for debugging output.  This eliminates the
+//need for printf statements
+outputStream& outputStream::operator<<(const string &outputString) {
+    send(outputString);
+
+    return *this;
+}
+
+outputStream& outputStream::operator<<(const char* s) {
+    //string tmpString = string(s);
+    //send(tmpString);
+    send(s);
+    return *this;
+}
+
+outputStream& outputStream::operator<<(int outputNum) {
+    ostringstream varConvert;
+    varConvert << outputNum;
+    send(varConvert.str());
+    return *this;
+}
+
+outputStream& outputStream::operator<<(uint32_t outputNum) {
+    ostringstream varConvert;
+    varConvert << outputNum;
+    send(varConvert.str());
+    return *this;
+}
+//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;
+
+}
+
+
diff -r 000000000000 -r ecf80f0172d0 hardwareInterface.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hardwareInterface.h	Mon Feb 08 18:56:09 2016 +0000
@@ -0,0 +1,173 @@
+#ifndef HARDWARWEINTERFACE_H
+#define HARDWARWEINTERFACE_H
+
+#include <stdint.h>
+#include <string>
+#include <cstdlib>
+#include <string.h>
+
+#define PENDINGTRIGGERBUFFERSIZE 10
+
+//#define NUMPORTS 8 //the number of ports available on the hardware
+
+using namespace std;
+
+//for debugging output
+//#define DEBUGOUTPUT
+
+//used to organize digital change events
+struct changeEvent {
+    uint32_t timeStamp;
+    bool triggered;
+};
+
+class sDigitalOut
+{
+public:
+    sDigitalOut();
+
+    virtual void init(int pin) = 0;
+    virtual void write(int value) = 0;
+    virtual int read() = 0;
+protected:
+
+};
+
+class sDigitalIn
+{
+public:
+    sDigitalIn();
+
+    virtual void init(int pin) = 0;
+    virtual int read() = 0;
+    virtual void interrupt_up_callback() = 0;
+    virtual void interrupt_down_callback() = 0;
+    void setUpdate(bool);
+
+    changeEvent lastUpEvent;
+    changeEvent lastDownEvent;
+
+protected:
+
+    bool updating;
+    changeEvent bufferedUpEvent;
+    changeEvent bufferedDownEvent;
+    void addStateChange(int newState, uint32_t timeStamp);
+
+};
+
+class sSerialPort
+{
+public:
+    sSerialPort();
+
+    virtual void init() = 0;
+    virtual bool readable() = 0;
+    virtual char readChar() = 0;
+    virtual void writeChar(char s)= 0;
+    virtual int  requestToWriteString(char *s, int numBytes) = 0;
+
+protected:
+
+
+};
+
+class sSound
+{
+public:
+    sSound();
+    void setFile(string fileNameIn);
+    void setFile(unsigned char fileNumIn);
+    void setVolume(int* volumeIn);
+    void setVolume(int volumeIn);
+    void setPlayback(bool playIn);
+    void setReset();
+    virtual void execute() = 0;
+
+protected:
+    char fileName[21];
+    bool fileNameExists;
+    unsigned char fileNum;
+    bool givenTrackNum;
+    int* volumePtr;
+    int volume;
+    bool play;
+    bool reset;
+};
+
+class sSystem
+{
+public:
+    sSystem();
+    virtual void timerinit() = 0;
+    virtual void setStandAloneClock() = 0;
+    virtual void setSlaveClock() = 0;
+    virtual sDigitalOut* getDigitalOutPtr(int portNum) = 0;
+    virtual sDigitalIn* getDigitalInPtr(int portNum) = 0;
+    virtual sSound* createNewSoundAction() = 0;
+    virtual void externalClockReset() = 0; //needs to reset harware timer before calling immediateClockReset();
+    virtual void incrementClock() = 0;
+    virtual void mainLoopToDo();
+    virtual void pauseInterrupts();
+    virtual void resumeInterrupts();
+    virtual int getPendingFunctionTriggers(uint16_t *bufferPtr); //Returns the number of pending shortcut triggers
+    virtual uint32_t getDigitalOutputChangeFlags();
+    virtual uint32_t getDigitalInputChangeFlags();
+    void setPortUpdatesOn(int portNum);
+    void setPortUpdatesOff(int portNum);
+    bool* getIgnoreUpdates();
+
+
+
+protected:
+
+    //virtual void timerInterrupt() = 0;
+
+    void immediateClockReset();   
+    int currentDINPin;
+    int currentDOUTPin;
+    uint32_t currentDigitalOuputStates;
+    uint32_t currentDigitalInputStates;
+    bool ignorePortUpdates[32];
+
+
+
+
+};
+
+
+//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 setSerial(sSerialPort *s);
+    void send(const string &outputString);
+    void send(const char* s);
+    void debug(const char* s);
+    outputStream &operator<<(const string &outputString);
+    outputStream &operator<<(int outputNum);
+    outputStream &operator<<(uint32_t outputNum);
+    outputStream &operator<<(const char* s);
+    char getNextChar();
+    bool unsentData;
+    void flush();
+
+private:
+    int readHead;
+    int writeHead;
+    int totalWriteHead;
+    int totalReadHead;
+    int bufferSize;
+    char tmpOut;
+    char* outputBuffer;
+    sSerialPort* serialPtr;
+};
+
+
+
+#endif // HARDWARWEINTERFACE_H
diff -r 000000000000 -r ecf80f0172d0 main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Mon Feb 08 18:56:09 2016 +0000
@@ -0,0 +1,9 @@
+#include "behave.h"
+
+using namespace std;
+
+int main() {
+    mainLoop m;
+    m.init();
+    m.exec();
+}
diff -r 000000000000 -r ecf80f0172d0 mbed.bld
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Mon Feb 08 18:56:09 2016 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/f141b2784e32
\ No newline at end of file
diff -r 000000000000 -r ecf80f0172d0 nucleoInterface/nucleoInterface.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nucleoInterface/nucleoInterface.cpp	Mon Feb 08 18:56:09 2016 +0000
@@ -0,0 +1,483 @@
+#include "nucleoInterface.h"
+#include "mbed.h"
+#define EPHYSRIG //!!!!!!make sure to change NUMPORTS, NUMINPORTS, and NUMOUTPORTS in the mbedInterface.h file!!!!!!!!!
+//#define TRAINRIG //!!!!!!make sure to change NUMPORTS, NUMINPORTS, and NUMOUTPORTS in the mbedInterface.h file!!!!!!!!!
+
+
+//--------------------------------------------------------------
+//--------------------------------------------------------------
+//This section is required for all custom harware interfaces
+
+//globals defined in hardwareInterface.cpp
+extern uint32_t timeKeeper; //the master clock
+uint32_t uSec_SinceLastClockInc = 0;
+uint32_t uSec_SinceLastReset = 0;
+
+extern bool resetTimer;
+extern bool clockSlave;
+extern bool changeToSlave;
+extern bool changeToStandAlone;
+extern outputStream textDisplay;
+
+int externalIncrementMod = 1;
+int externalIncrementCounter = 0;
+
+
+
+#ifdef MBED_RF
+//We are listening to an RF signal for hardware syncing----------------------------------------
+//Uses DB9->RJ45 connector to map the following channels:
+//1: P28    Clock Signal In
+//2: P27    Data Signal In
+//3: P20    FiberLED Out Signal
+//4: 5V
+//5: GND
+//6: P6     NC
+//7: P7     NC
+//8: P8     NC
+
+DigitalOut mainLED(LED1);
+DigitalOut secondaryLED(LED2);
+
+bool lightOn = false;
+bool lightOn2 = false;
+int pulseCounter = 0;
+uint32_t lastPulse = 0;
+uint32_t currentRFTime = 0;
+uint32_t lastRFTime = 0;
+uint32_t timeKeeperAtCurrentRFTime = 0;
+uint32_t timeKeeperAtLastRFTime = 0;
+int RFSyncCounter = 0;
+bool RFSyncReadable = false;
+bool RFSyncWritable = true;
+
+//Recieve clock signal from RF system
+InterruptIn RFClock(PC_9);
+DigitalIn RFData(PB_8);
+
+
+void callback_RFClock(void) {
+
+    //if this amount of time has passed since the last pulse, we have a new timestamp
+    if ((timeKeeper-lastPulse) > 4) {
+
+        //make sure the previous timestamp was 32 pulses
+        //if so, update lastRFTime
+        //we only process every 100th stamp (once every 10 seconds with 10 Hz timestamps)
+        if ((pulseCounter == 31) && (RFSyncCounter == 99)){
+            if (RFSyncWritable) {
+                lastRFTime = currentRFTime;
+                timeKeeperAtLastRFTime = timeKeeperAtCurrentRFTime;
+                RFSyncReadable = true;
+                RFSyncWritable = false;
+            }
+        }
+
+        pulseCounter = 0;
+        currentRFTime = 0;
+        timeKeeperAtCurrentRFTime = timeKeeper;
+        RFSyncCounter = (RFSyncCounter+1)%100;
+
+
+        if (lightOn) {
+            mainLED = 0;
+            lightOn = false;
+        } else {
+            mainLED = 1;
+            lightOn = true;
+        }
+    } else {
+        if (pulseCounter < 32) {
+            currentRFTime = (currentRFTime | ( RFData.read() << pulseCounter));
+            pulseCounter++;
+        }
+    }
+    lastPulse = timeKeeper;
+}
+
+//------------------------------------------------------------
+#endif
+
+void externalClockIncDown() {
+
+    //The external clock increment signal pulse has come back down.  If the pulse was long
+    //enough, then we condsider it a valid pulse (the pulses should be 0.5 ms long)
+    if ((clockSlave)&&(uSec_SinceLastClockInc >= 300)) {
+        uSec_SinceLastClockInc = 0;
+        timeKeeper++;
+
+        //Clock resets happen upon update so we dont get a partial first ms
+        if (resetTimer) {
+            uSec_SinceLastReset = 0;
+            timeKeeper = 0;
+            resetTimer = false;
+        }
+    }
+
+}
+
+void externalResetDown() {
+
+    //The external clock reset signal pulse has come back down.  If the pulse was long
+    //enough, then we condsider it a valid pulse (the pulses should be 1 ms long)
+    /*
+    textDisplay << uSec_SinceLastReset;
+    if ((clockSlave)&&(uSec_SinceLastReset >= 700)) {
+        uSec_SinceLastReset = 0;
+        timeKeeper = 1; //It has been 1ms since the reset pulse went up
+        textDisplay << timeKeeper << " Clock reset\r\n";
+    }*/
+}
+
+//------------------------------------------------------------------------
+//------------------------------------------------------------------------
+
+//MBED-specific stuff
+//---------------------------------------------------------------------
+
+//translate pin numbers to hardware pins
+PinName outPins[NUMPORTS] = {PB_9,PA_5,PA_6,PA_7,PB_6,PC_7,PA_9,PA_8,PB_10}; //9 outports
+PinName inPins[NUMPORTS]  = {PB_4,PB_5,PB_3,PA_10,PA_2,PA_3,PC_0,PC_1,PB_0}; //9 inports
+
+
+//The sound output uses a SmartWav device and their simple serial library
+//SMARTWAV audio(p28,p27,p19);   //(TX,RX,Reset);
+SOMO audio(PA_4,PA_1);        //(TX,RX,Reset)
+
+//This is the callback for the MBED timer
+//extern "C" void TIMER0_IRQHandler (void) {
+//
+//    /*if (clockSlave) {
+//
+//        //The function is called every 100 us
+//        if((LPC_TIM0->IR & 0x01) == 0x01) {  // if MR0 interrupt, proceed
+//
+//            LPC_TIM0->IR |= 1 << 0;         // Clear MR0 interrupt flag
+//            uSec_SinceLastClockInc = uSec_SinceLastClockInc+100;
+//            uSec_SinceLastReset = uSec_SinceLastReset+100;
+//
+//        }
+//
+//
+//    } else {*/
+//        //The function is called every 1 ms
+//        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;
+//            }
+//        }
+//    //}
+//}
+//-----------------------------------------------------------------------
+
+
+
+MBEDSystem::MBEDSystem():
+    clockResetInt(PA_0),
+    clockExternalIncrement(PD_2) {
+
+    clockResetInt.rise(this, &MBEDSystem::externalClockReset);
+    clockResetInt.fall(&externalResetDown);
+    clockResetInt.mode(PullDown);
+
+    clockExternalIncrement.mode(PullDown);
+
+    #ifdef MBED_RF
+    //Karpova version-------------
+    //Set up callbacks for RF clock signal
+    RFClock.rise(&callback_RFClock);
+    RFClock.mode(PullDown);
+    #endif
+
+    //-------------------------------
+
+    for (int i=0; i < NUMPORTS; i++) {
+        dIn[i].init(i);
+        dOut[i].init(i);
+    }
+
+
+    audio.reset();
+
+}
+
+void MBEDSystem::tick(){
+    timeKeeper++;
+    if (resetTimer){
+        timeKeeper = 0;
+        resetTimer = false;
+    }
+}
+
+void MBEDSystem::timerinit() {
+//    //intiatiation of timer (specific to the LPC17xx chip). This is used in
+//    //standalone mode to increment the clock every ms.
+//    //----------------------------------------------------
+//    //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
+//    //--------------------------------------------------------------
+    
+}
+
+void MBEDSystem::pauseInterrupts() {
+    __disable_irq();
+}
+
+void MBEDSystem::resumeInterrupts() {
+    __enable_irq();
+}
+
+void MBEDSystem::mainLoopToDo() {
+    #ifdef MBED_RF
+    //Karpova version--------------------------
+    //Karpova lab RF addition. Print out time sync.
+    if (RFSyncReadable) {
+           /*
+           ostringstream RFTimeConvert;
+           RFTimeConvert << timeKeeperAtLastRFTime << " " << "RFsync " << lastRFTime << "         "; //broadcast the earliest timestamp when a change occured
+
+           textDisplay.send(RFTimeConvert.str() + "\r\n");
+           RFTimeConvert.clear();
+           RFTimeConvert.seekp(0);
+           */
+
+           textDisplay << timeKeeperAtLastRFTime << " RFsync " << lastRFTime << "\r\n";
+
+           RFSyncReadable = false;
+           RFSyncWritable = true;
+    }
+    //------------------------------------------------------------
+    #endif
+}
+
+sDigitalOut* MBEDSystem::getDigitalOutPtr(int portNum){
+    if (portNum < NUMPORTS) {
+        return &dOut[portNum];
+    } else {
+        return NULL;
+    }
+}
+
+sDigitalIn* MBEDSystem::getDigitalInPtr(int portNum) {
+    if (portNum < NUMPORTS) {
+        return &dIn[portNum];
+    } else {
+        return NULL;
+    }
+}
+
+sSound* MBEDSystem::createNewSoundAction() {
+    MBEDSound *tmpSound = new MBEDSound();
+    return tmpSound;
+}
+
+
+void MBEDSystem::externalClockReset() {
+
+    //The pulse has gone high.  When the pulse comes down we will check to see if it was long enough to be valid.
+    uSec_SinceLastReset = 0;
+
+
+
+    if (clockSlave) {
+//        LPC_TIM0->TCR = 0x02;    // reset timer //ANDY
+        externalIncrementCounter = 0;
+
+        immediateClockReset();
+    }
+
+}
+
+void MBEDSystem::setStandAloneClock() {
+    clockSlave = false;
+//    NVIC_DisableIRQ(TIMER0_IRQn); // Disable the interrupt //ANDY
+    timerinit(); //set up and enable interrupt
+    clockExternalIncrement.rise(NULL); //remove the callback to the external interrupt
+    //clockExternalIncrement.fall(NULL);
+    changeToSlave = false;
+    changeToStandAlone = false;
+}
+
+void MBEDSystem::setSlaveClock() {
+    clockSlave = true;
+//    NVIC_DisableIRQ(TIMER0_IRQn); // Disable the interrupt //ANDY
+    //timerinit(); //set up and enable interrupt
+    clockExternalIncrement.rise(this, &MBEDSystem::incrementClock);
+    //clockExternalIncrement.fall(&externalClockIncDown);
+    clockSlave = true;
+    changeToSlave = false;
+    changeToStandAlone = false;
+}
+
+void MBEDSystem::incrementClock() {
+
+    if (clockSlave) {
+        //The pulse has gone high.  When the pulse comes down we will check to see if it was long enough to be valid.
+        //uSec_SinceLastClockInc = 0;
+
+
+        //The clock is incremented
+
+        externalIncrementCounter = (externalIncrementCounter+1) % externalIncrementMod;
+        if (externalIncrementCounter==0) {
+            timeKeeper++;
+        }
+
+    } else {
+        timeKeeper++;
+    }
+    //Clock resets happen upon update so we dont get a partial first ms
+    /*
+    if (resetTimer) {
+        uSec_SinceLastReset = 0;
+        timeKeeper = 0;
+        resetTimer = false;
+    }*/
+}
+
+//-----------------------------------------------------
+
+MBEDSound::MBEDSound() {
+
+}
+
+void MBEDSound::execute() {
+    if (reset) {
+        audio.reset();
+    } else if (!play) {
+        audio.stopTrack();
+    } else if (fileNum){
+        audio.playTrackNum(fileNum);
+    } else {
+        if (volume > -1) {
+            audio.volume(volume);
+        } else if (volumePtr != NULL) {
+            audio.volume(*volumePtr);
+        }
+        if (fileNameExists) {
+            audio.stopTrack();
+            wait_ms(30); //without this delay, smartWAV shield tends to freeze up
+            audio.playTrackName(fileName);
+        }
+    }
+}
+
+//-----------------------------------------------------
+MBEDDigitalOut::MBEDDigitalOut() {
+    pinExists = false;
+}
+
+void MBEDDigitalOut::init(int pin) {
+    if (pin < NUMOUTPORTS) {
+        outpin = new DigitalOut(outPins[pin]);
+        pinExists = true;
+    }
+}
+
+int MBEDDigitalOut::read() {
+    if (pinExists) {
+        return outpin->read();
+    } else {
+        return 0;
+    }
+}
+
+void MBEDDigitalOut::write(int value) {
+    if (pinExists) {
+
+        outpin->write(value);
+    }
+}
+//--------------------------------------------------------
+
+MBEDDigitalIn::MBEDDigitalIn() {
+    pinExists = false;
+}
+
+void MBEDDigitalIn::init(int pin) {
+
+    if (pin < NUMINPORTS) {
+        inpin = new DigitalIn(inPins[pin]);
+        inpin_interrupt = new InterruptIn(inPins[pin]);
+        inpin->mode(PullDown);
+        //Set up callbacks for the port interrupts
+        inpin_interrupt->rise(this, &MBEDDigitalIn::interrupt_up_callback);
+        inpin_interrupt->fall(this, &MBEDDigitalIn::interrupt_down_callback);
+        pinExists = true;
+    }
+}
+
+int MBEDDigitalIn::read() {
+    if (pinExists) {
+        return inpin->read();
+    } else {
+        return 0;
+    }
+}
+
+void MBEDDigitalIn::interrupt_up_callback() {
+    addStateChange(1, timeKeeper);
+}
+
+void MBEDDigitalIn::interrupt_down_callback() {
+    addStateChange(0, timeKeeper);
+}
+
+//----------------------------------------------------------
+MBEDSerialPort::MBEDSerialPort() {
+
+}
+
+void MBEDSerialPort::init() {
+    //Initialize serial communication
+    serialToPC = new Serial(USBTX, USBRX); // tx, rx
+    serialToPC->baud(115200);
+
+
+}
+
+bool MBEDSerialPort::readable() {
+    return serialToPC->readable();
+}
+
+char MBEDSerialPort::readChar() {
+    return serialToPC->getc();
+}
+
+void MBEDSerialPort::writeChar(char s) {
+    serialToPC->printf("%c", s);
+}
+
+int MBEDSerialPort::requestToWriteString(char *s, int numBytesRequested) {
+    //request to print a string to the serial output buffer
+    //function returns the number of chars actually accepted for output
+    int numBytesAccepted = 0;
+    while (numBytesAccepted < numBytesRequested) {
+
+        writeChar(*(s+numBytesAccepted));
+        numBytesAccepted++;
+    }
+
+    return numBytesAccepted;
+}
diff -r 000000000000 -r ecf80f0172d0 nucleoInterface/nucleoInterface.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nucleoInterface/nucleoInterface.h	Mon Feb 08 18:56:09 2016 +0000
@@ -0,0 +1,149 @@
+#ifndef NUCLEOINTERFACE_H
+#define NUCLEOINTERFACE_H
+
+#include "hardwareInterface.h"
+#include "mbed.h"
+#include <stdint.h>
+//#include "SMARTWAV.h"
+#include "SOMO.h"
+#include <string.h>
+#include <string>
+#include <vector>
+#include <queue>
+#include <sstream>
+
+
+#define MBED_RF
+
+
+#define NUMPORTS 9 //the number of ports available on this hardware
+#define NUMINPORTS 9
+#define NUMOUTPORTS 9
+
+#define NUMEVENTS 50
+#define NUMCONDITIONS 150
+#define NUMINTCOMPARE 150
+#define NUMACTIONS 150
+#define NUMPORTMESSAGES 150
+#define NUMINTOPERATIONS 150
+#define NUMDISPLAYACTIONS 30
+#define NUMTRIGGERACTIONS 30
+#define NUMFUNCTIONS 50
+#define INPUTCHARBUFFERSIZE 3072
+
+
+
+/*
+class MBEDTimer : public sTimer
+{
+public:
+    sTimer();
+    virtual void init() = 0;
+    virtual void timeout_callback() = 0;
+
+};
+
+class MBEDExternalSync : public sExternalSync
+{
+public:
+    MBEDExternalSync();
+    void init();
+    void interrupt_callback();
+    void reset_callback();
+
+};*/
+
+
+
+class MBEDDigitalOut : public sDigitalOut
+{
+public:
+    MBEDDigitalOut();
+
+    void init(int pin);
+    void write(int value);
+    int read();
+
+private:
+    DigitalOut *outpin;
+    bool pinExists;
+
+};
+
+class MBEDDigitalIn : public sDigitalIn
+{
+public:
+    MBEDDigitalIn();
+
+    void init(int pin);
+    int read();
+    void interrupt_up_callback();
+    void interrupt_down_callback();
+protected:
+
+
+
+private:
+    DigitalIn *inpin;
+    InterruptIn *inpin_interrupt;
+    bool pinExists;
+
+};
+
+class MBEDSerialPort : public sSerialPort
+{
+public:
+    MBEDSerialPort();
+
+    void init();
+    bool readable();
+    char readChar();
+    void writeChar(char s);
+    int  requestToWriteString(char *s, int numBytes);
+    Serial *serialToPC;
+
+private:
+    //Serial communication
+
+
+};
+
+class MBEDSound: public sSound
+{
+public:
+    MBEDSound();
+    void execute();
+
+private:
+
+};
+
+class MBEDSystem: public sSystem
+{
+public:
+    MBEDSystem();
+    void timerinit();
+    void setStandAloneClock();
+    void setSlaveClock();
+    sDigitalOut* getDigitalOutPtr(int portNum);
+    sDigitalIn* getDigitalInPtr(int portNum);
+    sSound* createNewSoundAction();
+    void pauseInterrupts();
+    void resumeInterrupts();
+    void incrementClock();
+    void externalClockReset(); //needs to reset harware timer before calling immediateClockReset();
+    void mainLoopToDo();
+    void tick();
+
+protected:
+
+    //Pins for clock syncing
+    InterruptIn clockResetInt;
+    InterruptIn clockExternalIncrement;
+
+private:
+    MBEDDigitalIn dIn[NUMPORTS];
+    MBEDDigitalOut dOut[NUMPORTS];
+};
+
+#endif // MBEDINTERFACE_H