Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Revision 0:ecf80f0172d0, committed 2016-02-08
- Comitter:
- alustig3
- Date:
- Mon Feb 08 18:56:09 2016 +0000
- Commit message:
- initial commit
Changed in this revision
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