statescriptMP
Dependencies: SMARTWAV USBDevice mbed
Revision 0:9d97f34c6f46, committed 2015-05-18
- Comitter:
- alustig3
- Date:
- Mon May 18 01:18:45 2015 +0000
- Commit message:
- statescript MP
Changed in this revision
diff -r 000000000000 -r 9d97f34c6f46 SMARTWAV.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SMARTWAV.lib Mon May 18 01:18:45 2015 +0000 @@ -0,0 +1,1 @@ +https://mbed.org/users/emmanuelchio/code/SMARTWAV/#d3cb5755b201
diff -r 000000000000 -r 9d97f34c6f46 USBDevice.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBDevice.lib Mon May 18 01:18:45 2015 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/USBDevice/#335f2506f422
diff -r 000000000000 -r 9d97f34c6f46 behave.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/behave.cpp Mon May 18 01:18:45 2015 +0000 @@ -0,0 +1,3733 @@ +#include "behave.h" +#include <ctype.h> +#include <sstream> + +// These external symbols are maintained by the linker to indicate the +// location of various regions in the device's memory. They will be used by +// DisplayRAMBanks() to dump the size of each RAM bank to stdout. +extern unsigned int Image$$RW_IRAM1$$Base; +extern unsigned int Image$$RW_IRAM1$$ZI$$Limit; +extern unsigned int Image$$RW_IRAM2$$Base; +extern unsigned int Image$$RW_IRAM2$$ZI$$Limit; +extern unsigned int Image$$RW_IRAM3$$Base; +extern unsigned int Image$$RW_IRAM3$$ZI$$Limit; + +uint32_t* globalTimeKeeperPtr; //this is a pointer to the slave timer (do not change this directly) +extern eventQueue mainQueue; +extern digitalPort* portVector[]; + +extern Serial pc; +extern bool resetTimer; +extern bool clockSlave; +extern bool changeToSlave; +extern bool changeToStandAlone; +extern outputStream textDisplay; +extern int currentDIOstate[2]; +extern bool broadCastStateChanges; +extern bool textStreaming; + + +//static pools of memory for each object type +extern event eventBlock[NUMEVENTS]; +extern condition conditionBlock[NUMCONDITIONS]; +extern intCompare intCompareBlock[NUMINTCOMPARE]; +extern action actionBlock[NUMACTIONS]; +extern portMessage portMessageBlock[NUMPORTMESSAGES]; +extern intOperation intOperationBlock[NUMINTOPERATIONS]; +extern displayAction displayActionBlock[NUMDISPLAYACTIONS]; + +//used to find the first available object in the staticly defined pools of memory +template<class T> T* findFirstUnUsed(T a[], const int arrayLength) { + + T* returnPtr = NULL; + for (int i = 0; i < arrayLength; i++) { + if (!a[i].isUsed) { + returnPtr = &a[i]; + break; + } + } + return returnPtr; +} + +//used to count the number of available objects in the memory pool +template<class T> int countUnUsed(T a[], const int arrayLength) { + + int count = 0; + for (int i = 0; i < arrayLength; i++) { + if (!a[i].isUsed) { + count++; + } + } + return count; +} + + +void displayMemoryLeft(void) { + pc.printf("Available slots left in memory\r\n"); + pc.printf(" Blocks: %d\r\n", countUnUsed(eventBlock, NUMEVENTS)); + pc.printf(" Condition containers: %d\r\n", countUnUsed(conditionBlock, NUMCONDITIONS)); + pc.printf(" Int compare conditions: %d\r\n", countUnUsed(intCompareBlock, NUMINTCOMPARE)); + pc.printf(" Command containers: %d\r\n", countUnUsed(actionBlock, NUMACTIONS)); + pc.printf(" Port commands: %d\r\n", countUnUsed(portMessageBlock, NUMPORTMESSAGES)); + pc.printf(" Integer operater commands: %d\r\n", countUnUsed(intOperationBlock, NUMINTOPERATIONS)); + pc.printf(" Text display commands: %d\r\n", countUnUsed(displayActionBlock, NUMDISPLAYACTIONS)); +} + +// Displays the size of static allocations for each RAM bank as indicated by +// ARM linker to stdout. +static void DisplayRAMBanks(void) { + + pc.printf("Static RAM bank allocations\r\n"); + pc.printf(" Main RAM = %u\r\n", (unsigned int)&Image$$RW_IRAM1$$ZI$$Limit - + (unsigned int)&Image$$RW_IRAM1$$Base); + pc.printf(" RAM0 = %u\r\n", (unsigned int)&Image$$RW_IRAM2$$ZI$$Limit - + (unsigned int)&Image$$RW_IRAM2$$Base); + pc.printf(" RAM1 = %u\r\n", (unsigned int)&Image$$RW_IRAM3$$ZI$$Limit - + (unsigned int)&Image$$RW_IRAM3$$Base); +} + + +bool isNumber(const std::string& s) { + std::string::const_iterator it = s.begin(); + while (it != s.end() && isdigit(*it)) ++it; + return !s.empty() && it == s.end(); +} + +void tokenize(const string& str, + vector<string>& tokens, + const string& delimiters = " ") +{ + // Skip delimiters at beginning. + string::size_type lastPos = str.find_first_not_of(delimiters, 0); + // Find first "non-delimiter". + string::size_type pos = str.find_first_of(delimiters, lastPos); + + while (string::npos != pos || string::npos != lastPos) + { + // Found a token, add it to the vector. + tokens.push_back(str.substr(lastPos, pos - lastPos)); + // Skip delimiters. Note the "not_of" + lastPos = str.find_first_not_of(delimiters, pos); + // Find next "non-delimiter" + pos = str.find_first_of(delimiters, lastPos); + } +} + + +digitalPort::digitalPort(DigitalOut* DOP, DigitalIn* DIP): + outPin(DOP), + inPin(DIP), + outState(0){ + + lastInState = getDigitalIn(); + inState = getDigitalIn(); + lastChangeTime = 0; + lastOutChangeTime = 0; + lastChangeInterval = 0; + lastDownEvent.triggered = false; + lastUpEvent.triggered = false; + triggerUpEventPtr = NULL; + triggerDownEventPtr = NULL; + outStateChanged = false; +} +digitalPort::digitalPort(DigitalOut* DOP): //ANDY + outPin(DOP), + outState(0){ + + lastChangeTime = 0; + lastOutChangeTime = 0; + lastChangeInterval = 0; + lastDownEvent.triggered = false; + lastUpEvent.triggered = false; + triggerUpEventPtr = NULL; + triggerDownEventPtr = NULL; + outStateChanged = false; +} + +void digitalPort::setTriggerUpEvent(event* eventInput) { + if (triggerUpEventPtr != NULL) { + //delete triggerUpEventPtr; + triggerUpEventPtr->release(); + } + triggerUpEventPtr = eventInput; +} + +void digitalPort::setTriggerDownEvent(event* eventInput) { + if (triggerDownEventPtr != NULL) { + //delete triggerDownEventPtr; + triggerDownEventPtr->release(); + + } + triggerDownEventPtr = eventInput; +} + + +int digitalPort::getDigitalIn() { + return inPin->read(); +} + + +void digitalPort::setDigitalOut(int outVal) { + if (outVal == -1) { + outVal = 1-outState; + } + outPin->write(outVal); + if (outState != outVal) { + outStateChanged = true; + lastOutChangeTime = *globalTimeKeeperPtr; + } + outState = outVal; +} + +//called when a digital in gets triggered +void digitalPort::addStateChange(int newState, uint32_t timeStamp) { + + if ((newState == 0) && (!lastDownEvent.triggered)){ + lastDownEvent.timeStamp = timeStamp; + lastDownEvent.triggered = true; + } else if ((newState == 1) && (!lastUpEvent.triggered)) { + lastUpEvent.timeStamp = timeStamp; + lastUpEvent.triggered = true; + } +} + +bool digitalPort::update() { + + bool changed = false; + if ((*globalTimeKeeperPtr - lastChangeTime) > 1) { //prevents flutter triggers when button is pressed + inState = getDigitalIn(); + changed = (lastInState != inState); + if (changed) { + if (inState == 1) { + if (lastUpEvent.triggered) { + //there were hardware triggered since the last main loop. We use that time + lastChangeInterval = lastUpEvent.timeStamp - lastChangeTime; + lastChangeTime = lastUpEvent.timeStamp; + } else { + //otherwise we use the current time + lastChangeInterval = *globalTimeKeeperPtr - lastChangeTime; + lastChangeTime = *globalTimeKeeperPtr; + } + if (triggerUpEventPtr != NULL) {triggerUpEventPtr->execute();} + } else if (inState == 0) { + if (lastDownEvent.triggered) { + lastChangeInterval = lastDownEvent.timeStamp - lastChangeTime; + lastChangeTime = lastDownEvent.timeStamp; + } else { + lastChangeInterval = *globalTimeKeeperPtr - lastChangeTime; + lastChangeTime = *globalTimeKeeperPtr; + } + if (triggerDownEventPtr != NULL) {triggerDownEventPtr->execute();} + } + + } + + lastInState = inState; + + } + lastUpEvent.triggered = false; + lastDownEvent.triggered = false; + return changed; +} + +int digitalPort::getLastChangeState() { + return lastInState; +} +uint32_t digitalPort::getTimeSinceLastChange() { + return lastChangeInterval; + +} + +intVariable::intVariable(): + value(0), + tag(string("--------------------")) { + isUsed = false; +} + +intVariable::intVariable(string tagInput, int initialValue): + value(initialValue), + tag(string(tagInput)) { + isUsed = true; +} + +void intVariable::set(string tagInput, int initialValue) { + value = initialValue; + tag = string(tagInput); + isUsed = true; +} + +displayAction::displayAction(): + dText(string("--------------------------------------------------")), + pcPtr(NULL) { + dVariable = NULL; + isUsed = false; +} + +void displayAction::release() { + dText = "--------------------------------------------------"; + pcPtr = NULL; + dVariable = NULL; + isUsed = false; +} + +displayAction::displayAction(int* variable, string varNameInput, Serial* pcPtrInput): + dVariable(variable), + dText(varNameInput), + pcPtr(pcPtrInput) { + isUsed = true; + +} + +displayAction::displayAction(string text, Serial* pcPtrInput): + dText(text), + pcPtr(pcPtrInput) { + dVariable = NULL; + isUsed = true; +} + +void displayAction::set(int* variable, string varNameInput, Serial* pcPtrInput) { + dVariable = variable; + dText = varNameInput; + pcPtr = pcPtrInput; + isUsed = true; + +} + +void displayAction::set(string text, Serial* pcPtrInput) { + dText = text; + pcPtr = pcPtrInput; + dVariable = NULL; + isUsed = true; +} + +void displayAction::execute() { + + ostringstream convert; // stream used for the conversion + convert << *globalTimeKeeperPtr; // insert the textual representation of 'Number' in the characters in the stream + + if (dVariable != NULL) { + ostringstream varConvert; + varConvert << *dVariable; + //pcPtr->printf("%d %s = %d\r\n",*globalTimeKeeperPtr, dText.data(),*dVariable); + textDisplay.send(convert.str() + " " + dText + " = " + varConvert.str() + "\r\n"); + } else { + //pcPtr->printf("%d %s\r\n",*globalTimeKeeperPtr, dText.data()); + textDisplay.send(convert.str() + " " + dText + "\r\n"); + + } +} + +intCompare::intCompare(): + port(NULL) { + cmpVal = NULL; + cmpValGlobal = false; + intVal = NULL; + intOp = NULL; + portValPtr = NULL; + isUsed = false; + +} +intCompare::intCompare(digitalPort* portInput, const char* cmpString, int cmpValInput, int whichToUse): + port(portInput) { + cmpVal = new int(cmpValInput); + cmpValGlobal = false; + intVal = NULL; + intOp = NULL; + setPointer(cmpString); + isUsed = true; + if (whichToUse == 1) { + portValPtr = &port->inState; + } else { + portValPtr = &port->outState; + } +} + +intCompare::intCompare(digitalPort* portInput, const char* cmpString, int* cmpIntVarInput, int whichToUse): + port(portInput), + cmpVal(cmpIntVarInput) { + cmpValGlobal = true; + intVal = NULL; + intOp = NULL; + setPointer(cmpString); + isUsed = true; + if (whichToUse == 1) { + portValPtr = &port->inState; + } else { + portValPtr = &port->outState; + } +} + +intCompare::intCompare(int* intVarInput, const char* cmpString, int* cmpIntVarInput): + cmpVal(cmpIntVarInput), + intVal(intVarInput) { + cmpValGlobal = true; + port = NULL; + intOp = NULL; + portValPtr = NULL; + isUsed = true; + setPointer(cmpString); +} + +intCompare::intCompare(int* intVarInput, const char* cmpString, int cmpValInput): + intVal(intVarInput){ + cmpVal = new int(cmpValInput); + cmpValGlobal = false; + port = NULL; + intOp = NULL; + portValPtr = NULL; + isUsed = true; + setPointer(cmpString); +} + +intCompare::intCompare(int* intVarInput, const char* cmpString, intOperation* cmpIntOpInput): + intVal(intVarInput) { + cmpVal = NULL; + port = NULL; + portValPtr = NULL; + cmpValGlobal = true; + intOp = cmpIntOpInput; + isUsed = true; + setPointer_operation(cmpString); +} + +intCompare::intCompare(digitalPort* portInput, const char* cmpString, intOperation* cmpIntOpInput, int whichToUse): + port(portInput) { + cmpVal = NULL; + intVal = NULL; + cmpValGlobal = true; + intOp = cmpIntOpInput; + setPointer_operation(cmpString); + isUsed = true; + if (whichToUse == 1) { + portValPtr = &port->inState; + } else { + portValPtr = &port->outState; + } +} + + + +void intCompare::set(digitalPort* portInput, const char* cmpString, int cmpValInput, int whichToUse) { + port = portInput; + cmpVal = new int(cmpValInput); + cmpValGlobal = false; + intVal = NULL; + intOp = NULL; + setPointer(cmpString); + isUsed = true; + if (whichToUse == 1) { + portValPtr = &port->inState; + } else { + portValPtr = &port->outState; + } +} + +void intCompare::set(digitalPort* portInput, const char* cmpString, int* cmpIntVarInput, int whichToUse) { + port = portInput; + cmpVal = cmpIntVarInput; + cmpValGlobal = true; + intVal = NULL; + intOp = NULL; + setPointer(cmpString); + isUsed = true; + if (whichToUse == 1) { + portValPtr = &port->inState; + } else { + portValPtr = &port->outState; + } +} + +void intCompare::set(int* intVarInput, const char* cmpString, int* cmpIntVarInput) { + cmpVal = cmpIntVarInput; + intVal = intVarInput; + cmpValGlobal = true; + port = NULL; + intOp = NULL; + portValPtr = NULL; + setPointer(cmpString); + isUsed = true; +} + +void intCompare::set(int* intVarInput, const char* cmpString, int cmpValInput) { + intVal = intVarInput; + cmpVal = new int(cmpValInput); + cmpValGlobal = false; + port = NULL; + intOp = NULL; + portValPtr = NULL; + setPointer(cmpString); + isUsed = true; +} + +void intCompare::set(int* intVarInput, const char* cmpString, intOperation* cmpIntOpInput) { + intVal = intVarInput; + cmpVal = NULL; + port = NULL; + portValPtr = NULL; + cmpValGlobal = true; + intOp = cmpIntOpInput; + setPointer_operation(cmpString); + isUsed = true; +} + +void intCompare::set(digitalPort* portInput, const char* cmpString, intOperation* cmpIntOpInput, int whichToUse) { + port = portInput; + cmpVal = NULL; + intVal = NULL; + cmpValGlobal = true; + intOp = cmpIntOpInput; + setPointer_operation(cmpString); + isUsed = true; + if (whichToUse == 1) { + portValPtr = &port->inState; + } else { + portValPtr = &port->outState; + } +} + + + +intCompare::~intCompare() { + if (!cmpValGlobal) delete cmpVal; //we only delete the intCompare object if it was created locally + delete intOp; +} + +void intCompare::release() { + if (!cmpValGlobal) delete cmpVal; //we only delete the intCompare object if it was created locally + if (intOp != NULL) { + intOp->release(); + } + port = NULL; + cmpVal = NULL; + cmpValGlobal = false; + intVal = NULL; + intOp = NULL; + portValPtr = NULL; + isUsed = false; +} + + +void intCompare::setPointer(const char* cmpString) { + if (strcmp(cmpString, ">") == 0) { + isTruePtr = &intCompare::greaterThan; + }else if (strcmp(cmpString, ">=") == 0) { + isTruePtr = &intCompare::greaterOrEqual; + }else if (strcmp(cmpString, "<") == 0) { + isTruePtr = &intCompare::lessThan; + }else if (strcmp(cmpString, "<=") == 0) { + isTruePtr = &intCompare::lessOrEqual; + }else if (strcmp(cmpString, "==") == 0) { + isTruePtr = &intCompare::equal; + }else if (strcmp(cmpString, "!=") == 0) { + isTruePtr = &intCompare::notEqual; + } +} + +void intCompare::setPointer_operation(const char* cmpString) { + if (strcmp(cmpString, ">") == 0) { + isTruePtr = &intCompare::greaterThan_op; + }else if (strcmp(cmpString, ">=") == 0) { + isTruePtr = &intCompare::greaterOrEqual_op; + }else if (strcmp(cmpString, "<") == 0) { + isTruePtr = &intCompare::lessThan_op; + }else if (strcmp(cmpString, "<=") == 0) { + isTruePtr = &intCompare::lessOrEqual_op; + }else if (strcmp(cmpString, "==") == 0) { + isTruePtr = &intCompare::equal_op; + }else if (strcmp(cmpString, "!=") == 0) { + isTruePtr = &intCompare::notEqual_op; + } +} + +bool intCompare::isTrue() { + return (this->*isTruePtr)(); + +} + +bool intCompare::notEqual() { + if (intVal != NULL) { + return (*intVal != *cmpVal); + } else { + return (*portValPtr != *cmpVal); + } +} + +bool intCompare::greaterThan() { + if (intVal != NULL) { + return (*intVal > *cmpVal); + } else { + return (*portValPtr > *cmpVal); + } +} + +bool intCompare::greaterOrEqual() { + if (intVal != NULL) { + return (*intVal >= *cmpVal); + } else { + return (*portValPtr >= *cmpVal); + } +} + +bool intCompare::lessThan() { + if (intVal != NULL) { + return (*intVal < *cmpVal); + } else { + return (*portValPtr < *cmpVal); + } +} + +bool intCompare::lessOrEqual() { + if (intVal != NULL) { + return (*intVal <= *cmpVal); + } else { + return (*portValPtr <= *cmpVal); + } +} + +bool intCompare::equal() { + if (intVal != NULL) { + return (*intVal == *cmpVal); + } else { + return (*portValPtr == *cmpVal); + } +} + +bool intCompare::notEqual_op() { + if (intVal != NULL) { + return (*intVal != intOp->execute()); + } else { + return (*portValPtr != intOp->execute()); + } +} + +bool intCompare::greaterThan_op() { + if (intVal != NULL) { + return (*intVal > intOp->execute()); + } else { + return (*portValPtr > intOp->execute()); + } +} + +bool intCompare::greaterOrEqual_op() { + if (intVal != NULL) { + return (*intVal >= intOp->execute()); + } else { + return (*portValPtr >= intOp->execute()); + } +} + +bool intCompare::lessThan_op() { + if (intVal != NULL) { + return (*intVal < intOp->execute()); + } else { + return (*portValPtr < intOp->execute()); + } +} + +bool intCompare::lessOrEqual_op() { + if (intVal != NULL) { + return (*intVal <= intOp->execute()); + } else { + return (*portValPtr <= intOp->execute()); + } +} + +bool intCompare::equal_op() { + if (intVal != NULL) { + return (*intVal == intOp->execute()); + } else { + return (*portValPtr == intOp->execute()); + } +} + +intOperation::intOperation(): + randHigh(-1) { + cmpVal = NULL; + intVal = NULL; + opPtr = NULL; + executePtr = NULL; + cmpValGlobal = false; + isUsed = false; + +} + +intOperation::intOperation(int randParam, const char* cmpString, int cmpValInput): + randHigh(randParam) { + cmpVal = new int(cmpValInput); + intVal = NULL; + opPtr = NULL; + cmpValGlobal = false; + isUsed = true; + if (strcmp(cmpString, "+") == 0) { + executePtr = &intOperation::add; + }else if (strcmp(cmpString, "-") == 0) { + executePtr = &intOperation::subtract; + }else if (strcmp(cmpString, "+=") == 0) { + executePtr = &intOperation::addAndStore; + }else if (strcmp(cmpString, "-=") == 0) { + executePtr = &intOperation::subtractAndStore; + }else if (strcmp(cmpString, "=") == 0) { + executePtr = &intOperation::equals; + } + +} + +intOperation::intOperation(int randParam, const char* cmpString, int* cmpIntVarInput): + randHigh(randParam), + cmpVal(cmpIntVarInput) { + intVal = NULL; + opPtr = NULL; + cmpValGlobal = true; + isUsed = true; + if (strcmp(cmpString, "+") == 0) { + executePtr = &intOperation::add; + }else if (strcmp(cmpString, "-") == 0) { + executePtr = &intOperation::subtract; + }else if (strcmp(cmpString, "+=") == 0) { + executePtr = &intOperation::addAndStore; + }else if (strcmp(cmpString, "-=") == 0) { + executePtr = &intOperation::subtractAndStore; + }else if (strcmp(cmpString, "=") == 0) { + executePtr = &intOperation::equals; + } +} + +intOperation::intOperation(int* intVarInput, const char* cmpString, int cmpValInput): + intVal(intVarInput) { + cmpVal = new int(cmpValInput); + randHigh = -1; + opPtr = NULL; + cmpValGlobal = false; + isUsed = true; + if (strcmp(cmpString, "+") == 0) { + executePtr = &intOperation::add; + }else if (strcmp(cmpString, "-") == 0) { + executePtr = &intOperation::subtract; + }else if (strcmp(cmpString, "+=") == 0) { + executePtr = &intOperation::addAndStore; + }else if (strcmp(cmpString, "-=") == 0) { + executePtr = &intOperation::subtractAndStore; + }else if (strcmp(cmpString, "=") == 0) { + executePtr = &intOperation::equals; + } +} + +intOperation::intOperation(int* intVarInput, const char* cmpString, int* cmpIntVarInput): + cmpVal(cmpIntVarInput), + intVal(intVarInput) { + randHigh = -1; + opPtr = NULL; + cmpValGlobal = true; + isUsed = true; + if (strcmp(cmpString, "+") == 0) { + executePtr = &intOperation::add; + }else if (strcmp(cmpString, "-") == 0) { + executePtr = &intOperation::subtract; + }else if (strcmp(cmpString, "+=") == 0) { + executePtr = &intOperation::addAndStore; + }else if (strcmp(cmpString, "-=") == 0) { + executePtr = &intOperation::subtractAndStore; + }else if (strcmp(cmpString, "=") == 0) { + executePtr = &intOperation::equals; + } +} + +intOperation::intOperation(int* intVarInput, intOperation* operationInput): + intVal(intVarInput) { + cmpVal = NULL; + randHigh = -1; + opPtr = operationInput; + executePtr = &intOperation::equals; + isUsed = true; +} + +void intOperation::set(int randParam, const char* cmpString, int cmpValInput) { + randHigh = randParam; + cmpVal = new int(cmpValInput); + intVal = NULL; + opPtr = NULL; + cmpValGlobal = false; + isUsed = true; + if (strcmp(cmpString, "+") == 0) { + executePtr = &intOperation::add; + }else if (strcmp(cmpString, "-") == 0) { + executePtr = &intOperation::subtract; + }else if (strcmp(cmpString, "+=") == 0) { + executePtr = &intOperation::addAndStore; + }else if (strcmp(cmpString, "-=") == 0) { + executePtr = &intOperation::subtractAndStore; + }else if (strcmp(cmpString, "=") == 0) { + executePtr = &intOperation::equals; + } + +} + +void intOperation::set(int randParam, const char* cmpString, int* cmpIntVarInput) { + randHigh = randParam; + cmpVal = cmpIntVarInput; + intVal = NULL; + opPtr = NULL; + cmpValGlobal = true; + isUsed = true; + if (strcmp(cmpString, "+") == 0) { + executePtr = &intOperation::add; + }else if (strcmp(cmpString, "-") == 0) { + executePtr = &intOperation::subtract; + }else if (strcmp(cmpString, "+=") == 0) { + executePtr = &intOperation::addAndStore; + }else if (strcmp(cmpString, "-=") == 0) { + executePtr = &intOperation::subtractAndStore; + }else if (strcmp(cmpString, "=") == 0) { + executePtr = &intOperation::equals; + } +} + +void intOperation::set(int* intVarInput, const char* cmpString, int cmpValInput) { + + intVal = intVarInput; + cmpVal = new int(cmpValInput); + randHigh = -1; + opPtr = NULL; + cmpValGlobal = false; + isUsed = true; + if (strcmp(cmpString, "+") == 0) { + executePtr = &intOperation::add; + }else if (strcmp(cmpString, "-") == 0) { + executePtr = &intOperation::subtract; + }else if (strcmp(cmpString, "+=") == 0) { + executePtr = &intOperation::addAndStore; + }else if (strcmp(cmpString, "-=") == 0) { + executePtr = &intOperation::subtractAndStore; + }else if (strcmp(cmpString, "=") == 0) { + executePtr = &intOperation::equals; + } +} + +void intOperation::set(int* intVarInput, const char* cmpString, int* cmpIntVarInput) { + cmpVal = cmpIntVarInput; + intVal =intVarInput; + randHigh = -1; + opPtr = NULL; + cmpValGlobal = true; + isUsed = true; + if (strcmp(cmpString, "+") == 0) { + executePtr = &intOperation::add; + }else if (strcmp(cmpString, "-") == 0) { + executePtr = &intOperation::subtract; + }else if (strcmp(cmpString, "+=") == 0) { + executePtr = &intOperation::addAndStore; + }else if (strcmp(cmpString, "-=") == 0) { + executePtr = &intOperation::subtractAndStore; + }else if (strcmp(cmpString, "=") == 0) { + executePtr = &intOperation::equals; + } +} + +void intOperation::set(int* intVarInput, intOperation* operationInput) { + + intVal = intVarInput; + cmpVal = NULL; + randHigh = -1; + opPtr = operationInput; + executePtr = &intOperation::equals; + isUsed = true; + +} + + +intOperation::~intOperation() { + if (!cmpValGlobal) delete cmpVal; + delete opPtr; +} + +void intOperation::release() { + if (!cmpValGlobal) delete cmpVal; + if (opPtr != NULL) { + opPtr->release(); + } + randHigh = -1; + cmpVal = NULL; + intVal = NULL; + opPtr = NULL; + executePtr = NULL; + cmpValGlobal = false; + isUsed = false; +} + + +int intOperation::execute() { + + return (this->*executePtr)(); + + +} + +int intOperation::add() { + + if (intVal != NULL) { + return (*intVal + *cmpVal); + } + else { + //srand(time(NULL)); + srand(*globalTimeKeeperPtr); + return (rand() % (randHigh+1)) + *cmpVal; + //return (port->getState() + *cmpVal); + } +} + +int intOperation::subtract() { + if (intVal != NULL) { + return (*intVal - *cmpVal); + } + else { + srand(*globalTimeKeeperPtr); + return (rand() % (randHigh+1)) - *cmpVal; + //return (port->getState() - *cmpVal); + } +} + +int intOperation::addAndStore() { + if (intVal != NULL) { + *intVal = *intVal + *cmpVal; + return *intVal; + } + else { + + //Doesn't happen + return 0; + //port->setState(port->getState() + *cmpVal); + //return port->getState(); + } + +} + +int intOperation::subtractAndStore() { + if (intVal != NULL) { + *intVal = *intVal - *cmpVal; + return *intVal; + } else { + //doesn't happen + return 0; + //port->setState(port->getState() - *cmpVal); + //return port->getState(); + } +} + +int intOperation::equals() { + if ((intVal != NULL) && (opPtr == NULL)) { + *intVal = *cmpVal; + return *intVal; + } else if ((intVal != NULL) && (opPtr != NULL)) { + + *intVal = opPtr->execute(); + return *intVal; + } else if (cmpVal != NULL){ + + srand(*globalTimeKeeperPtr); + *cmpVal = (rand() % (randHigh+1)); //this is how we assign a random number to variable + return *cmpVal; + + } + return -1; +} + +condition::condition() { + intCmp = NULL; + conditionPtrs[0] = NULL; + conditionPtrs[1] = NULL; + isUsed = false; + conditionType = ARITHMATIC_CONDITION; +} + +condition::condition(intCompare* compareInput) { + + intCmp = compareInput; + conditionPtrs[0] = NULL; + conditionPtrs[1] = NULL; + + isUsed = true; + conditionType = ARITHMATIC_CONDITION; + +} + +condition::condition(condition* condition1, char condType, condition* condition2) { + intCmp = NULL; + conditionPtrs[0] = condition1; + conditionPtrs[1] = condition2; + isUsed = true; + conditionType = condType; +} + +condition::~condition() { + if (intCmp != NULL) { + delete intCmp; + } +} + +void condition::release() { + if (intCmp != NULL) { + intCmp->release(); + intCmp=NULL; + } + if (conditionPtrs[0] != NULL) { + conditionPtrs[0]->release(); + conditionPtrs[1]->release(); + conditionPtrs[0]=NULL; + conditionPtrs[1]=NULL; + } + isUsed = false; +} + +void condition::set(intCompare* compareInput) { + release(); + intCmp = compareInput; + conditionPtrs[0] = NULL; + conditionPtrs[1] = NULL; + isUsed = true; + conditionType = ARITHMATIC_CONDITION; +} + +void condition::set(condition* condition1, char condType, condition* condition2) { + release(); + intCmp = NULL; + conditionPtrs[0] = condition1; + conditionPtrs[1] = condition2; + isUsed = true; + conditionType = condType; +} + +bool condition::isTrue() { + + + bool result = true; + if (conditionType == ARITHMATIC_CONDITION) { + //pc.printf("Evauating arithmatic condition \r\n"); + result = (intCmp->isTrue)(); + } else if (conditionType == AND_CONDITION) { + //pc.printf("Evauating AND condition \r\n"); + result = conditionPtrs[0]->isTrue() && conditionPtrs[1]->isTrue(); + } else if (conditionType == OR_CONDITION) { + //pc.printf("Evauating OR condition \r\n"); + result = conditionPtrs[0]->isTrue() || conditionPtrs[1]->isTrue(); + } + return result; + +} + +portMessage::portMessage(): + whichToSet(0), + value(0), + port(NULL) { + isUsed = false; +} + +void portMessage::release() { + + whichToSet = 0; + value = 0; + port = NULL; + isUsed = false; +} + +/* +portMessage::portMessage(digitalPort* portIn, int whichToSetIn, int valueIn): + whichToSet(whichToSetIn), + value(valueIn), + port(portIn) { + isUsed = true; +} + +void portMessage::setMessage(digitalPort* portIn, int whichToSetIn, int valueIn) { + whichToSet = whichToSetIn; + value = valueIn; + port = portIn; + isUsed = true; +}*/ + +portMessage::portMessage(int* portIn, int whichToSetIn, int valueIn): + whichToSet(whichToSetIn), + value(valueIn), + port(portIn) { + isUsed = true; +} + +void portMessage::setMessage(int* portIn, int whichToSetIn, int valueIn) { + whichToSet = whichToSetIn; + value = valueIn; + port = portIn; + isUsed = true; +} + +void portMessage::execute() { + + if (port != NULL) { + if ((*port > 0) && (*port <= NUMPORTS)) { + portVector[*port]->setDigitalOut(value); + } else { + pc.printf("Error: port index assigned by variable does not exist."); + } + } else { + portVector[whichToSet]->setDigitalOut(value); + } + + /* + if (whichToSet == 1) { + port->setDigitalOut(value); + } else if (whichToSet == 2) { + //port->setState(value); + }*/ +} + +action::action(): + actionType(0) { + op = NULL; + message = NULL; + eventToCreate = NULL; + displayActionPtr = NULL; + //eventDelay = 0; + sound = NULL; + sysCommand = -1; + isUsed = false; + +} + +action::~action() { + if (eventToCreate != NULL) delete eventToCreate; + if (op != NULL) delete op; + if (message != NULL) delete message; + delete displayActionPtr; + delete sound; +} + +void action::release() { + if (eventToCreate != NULL) eventToCreate->release(); + if (op != NULL) op->release(); + if (message != NULL) message->release(); + if (displayActionPtr != NULL) displayActionPtr->release(); + delete sound; //still need to make a static soundControl array + + actionType = 0; + op = NULL; + message = NULL; + eventToCreate = NULL; + displayActionPtr = NULL; + //eventDelay = 0; + sound = NULL; + sysCommand = -1; + isUsed = false; +} + +action::action(intOperation* opInput): + actionType(1) { + op = opInput; + message = NULL; + eventToCreate = NULL; + displayActionPtr= NULL; + //eventDelay = 0; + sound = NULL; + sysCommand = -1; + isUsed = true; +} + +action::action(portMessage* messageInput): + actionType(2) { + op = NULL; + eventToCreate = NULL; + message = messageInput; + displayActionPtr= NULL; + //eventDelay = 0; + sound = NULL; + sysCommand = -1; + isUsed = true; + +} + +action::action(event* eventInput): + actionType(3) { + op = NULL; + message = NULL; + eventToCreate = eventInput; + displayActionPtr= NULL; + sound = NULL; + + //eventDelay = eventInput->timeLag; + + + sysCommand = -1; + isUsed = true; +} + +/* +action::action(event* eventInput, uint32_t delay): + actionType(3) { + op = NULL; + message = NULL; + eventToCreate = eventInput; + displayActionPtr= NULL; + sound = NULL; + eventDelay = delay; + sysCommand = -1; + isUsed = true; + +}*/ + + + +action::action(displayAction* displayInput): + actionType(4) { + op = NULL; + message = NULL; + eventToCreate = NULL; + sound = NULL; + displayActionPtr = displayInput; + //eventDelay = 0; + sysCommand = -1; + isUsed = true; +} + +action::action(soundControl* soundInput): + actionType(5) { + op = NULL; + message = NULL; + eventToCreate = NULL; + sound = soundInput; + displayActionPtr = NULL; + //eventDelay = 0; + sysCommand = -1; + isUsed = true; +} + +action::action(int8_t sysCommandInput): + actionType(6) { + op = NULL; + message = NULL; + eventToCreate = NULL; + sound = NULL; + displayActionPtr = NULL; + //eventDelay = 0; + sysCommand = sysCommandInput; + isUsed = true; +} + +void action::set(intOperation* opInput) { + actionType = 1; + op = opInput; + //eventDelay = 0; + isUsed = true; + +} + +void action::set(portMessage* messageInput) { + actionType = 2; + message = messageInput; + //eventDelay = 0; + isUsed = true; + +} + +void action::set(event* eventInput) { + actionType = 3; + eventToCreate = eventInput; + //eventDelay = eventInput->timeLag; + + isUsed = true; + +} + +/* +void action::set(event* eventInput, uint32_t delay) { + actionType = 3; + eventToCreate = eventInput; + eventDelay = delay; + isUsed = true; + +}*/ + + + +void action::set(displayAction* displayInput) { + actionType = 4; + displayActionPtr = displayInput; + isUsed = true; +} + +void action::set(soundControl* soundInput) { + actionType = 5; + sound = soundInput; + isUsed = true; +} + +void action::set(int8_t sysCommandInput) { + actionType = 6; + sysCommand = sysCommandInput; + isUsed = true; +} + +void action::execute() { + + if (actionType == 1) { + op->execute(); + } else if (actionType == 2) { + message->execute(); + } else if (actionType == 3) { + this->execute(*globalTimeKeeperPtr); //route to the other overloaded method + } else if (actionType == 4) { + displayActionPtr->execute(); //send text via serial + } else if (actionType == 5) { + sound->execute(); //operate sound device + } else if (actionType == 6) { + switch(sysCommand) { + case 0: + mainQueue.eraseQueue(); + break; + case 1: + textStreaming = true; + break; + case 2: + textStreaming = false; + break; + case 3: + broadCastStateChanges = true; + break; + case 4: + broadCastStateChanges = false; + break; + } + + } +} + +void action::execute(uint32_t blockExecTime) { + + if (actionType == 1) { + op->execute(); + } else if (actionType == 2) { + message->execute(); + } else if (actionType == 3) { //an event block + //Because time will pass from the begining of the block, any defined delays should be updated + + //int newDelay = eventDelay-(*globalTimeKeeperPtr-blockExecTime); + int newDelay; + if (eventToCreate->timeLagIsConstant) { + newDelay = eventToCreate->timeLag - (*globalTimeKeeperPtr-blockExecTime); + } else { + newDelay = *eventToCreate->timeLagVar - (*globalTimeKeeperPtr-blockExecTime); + } + if (newDelay < 0) {newDelay = 0;} + eventToCreate->addToQueue(newDelay); //add the event to the queue to be executed later + + if (eventToCreate->hasWhileLoop) { //this is a while loop + if (eventToCreate->isConditionTrue()) { + //newDelay = (blockExecTime + eventToCreate->whileLoopPeriod) - *globalTimeKeeperPtr; + int tmpPeriod; + if (eventToCreate->whileLoopPeriodIsConstant) { //constant while loop period + newDelay = (blockExecTime + eventToCreate->whileLoopPeriod); + tmpPeriod = eventToCreate->whileLoopPeriod; + } else { + tmpPeriod = *eventToCreate->whileLoopPeriodVar; + if (tmpPeriod < 0) { + tmpPeriod = 0; + } + newDelay = (blockExecTime + tmpPeriod); + } + while ( (newDelay-*globalTimeKeeperPtr < 0) && (eventToCreate->isConditionTrue()) ) { + eventToCreate->execute(); + newDelay = newDelay + tmpPeriod; + + } + newDelay = newDelay-*globalTimeKeeperPtr; + if (newDelay > 0) { + eventToCreate->addToQueue(newDelay); + } else { + eventToCreate->addToQueue(1); + } + } else if (eventToCreate->nextElseEventPtr != NULL) { + eventToCreate->nextElseEventPtr->addToQueue(); + + } + } + } else if (actionType == 4) { + displayActionPtr->execute(); //send text via serial + } else if (actionType == 5) { + sound->execute(); //operate sound device + } else if (actionType == 6) { + switch(sysCommand) { + case 0: + mainQueue.eraseQueue(); + break; + case 1: + textStreaming = true; + break; + case 2: + textStreaming = false; + break; + case 3: + broadCastStateChanges = true; + break; + case 4: + broadCastStateChanges = false; + break; + } + } +} + +eventQueue::eventQueue(digitalPort** portVectorInput, uint32_t* timeKeeperSlaveInput): + portVector(portVectorInput), + timeKeeperPtr(timeKeeperSlaveInput){ + + globalTimeKeeperPtr = timeKeeperPtr; + queueItem blankEvent; + blankEvent.timeToExecute = 0; + blankEvent.eventPtr = NULL; + queueSize = 100; + events.resize(queueSize,blankEvent); + + +} + +void eventQueue::addEventToQueue(event* eventInput, uint32_t delay) { + //*updateSlavePtr = false; + uint32_t eventTime = *timeKeeperPtr + delay; + //*updateSlavePtr = true; + //std::vector<queueItem>::size_type sz = events.size(); + //Look for the first empty slot in the queue and place the event there. + //This means that the events in the queue are out of order, but + //it prevents us from having to push_pack and pop off all the time. + for (unsigned i = 0; i < queueSize; i++) { + if (events[i].eventPtr == NULL) { + events[i].eventPtr = eventInput; + events[i].timeToExecute = eventTime; + break; + } + } +} + +void eventQueue::eraseQueue() { + //Erase all events in the queue + std::vector<queueItem>::size_type sz = events.size(); + for (unsigned i = 0; i < sz; i++) { + events[i].eventPtr = NULL; + + } +} + + +//check if any of the events in the queue are up for execution +void eventQueue::check(void) { + + //*updateSlavePtr = false; + uint32_t currentTime = *timeKeeperPtr; + //*updateSlavePtr = true; + //std::vector<queueItem>::size_type sz = events.size(); + for (unsigned i = 0; i < queueSize; i++) { + if (events[i].eventPtr != NULL) { + if(events[i].timeToExecute <= currentTime) { + if (!events[i].eventPtr->hasWhileLoop) { + //this is not a while loop, so no need to check if the condition is still true + events[i].eventPtr->execute(); + } else if (events[i].eventPtr->isConditionTrue()){ + //The event is part of a while loop, so recheck the condition before executing + events[i].eventPtr->execute(); + //if (events[i].eventPtr->isConditionTrue()) { //is the condition still true? + int nextTime; + int tmpPeriod; + if (events[i].eventPtr->whileLoopPeriodIsConstant) { + nextTime = (events[i].timeToExecute + events[i].eventPtr->whileLoopPeriod); + tmpPeriod = events[i].eventPtr->whileLoopPeriod; + } else { + tmpPeriod = *events[i].eventPtr->whileLoopPeriodVar; + if (tmpPeriod < 0) { + tmpPeriod = 0; + } + nextTime = (events[i].timeToExecute + tmpPeriod); + + } + //Just in case we are not keeping up, execute the event until we have cought up + while ((nextTime-*timeKeeperPtr <= 0) && (events[i].eventPtr->isConditionTrue())) { + events[i].eventPtr->execute(); + nextTime = nextTime+tmpPeriod; + + } + nextTime = nextTime - *timeKeeperPtr; + if (nextTime > 0) { + //we add the event to the queue (but the condition is rechecked first) + //if the condition is false, the 'then' statement is added to the queue instead + events[i].eventPtr->addToQueue(nextTime); + } else { + //if we are having trouble keeping up, just add the next event in 1 ms + events[i].eventPtr->addToQueue(1); + } + /* + } else { + if (events[i].eventPtr->nextElseEventPtr != NULL) { + events[i].eventPtr->nextElseEventPtr->addToQueue(); + } + }*/ + + } else { + if (events[i].eventPtr->nextElseEventPtr != NULL) { + events[i].eventPtr->nextElseEventPtr->addToQueue(); + } + } + events[i].eventPtr = NULL; + } + } + } +} + + +event::event(): + timeLag(0), + queuePtr(&mainQueue) { + nextElseEventPtr = NULL; + conditionToCheck = NULL; + blockType = 0; + whileLoopPeriod = 0; + numConditions = 0; + numActions = 0; + isUsed = false; + timeLagVar = NULL; + timeLagIsConstant = true; + whileLoopPeriodIsConstant = true; + hasWhileLoop = false; + whileLoopPeriodVar = NULL; + + } + +event::event(eventQueue* queueInput): + timeLag(0), + queuePtr(&mainQueue) { + nextElseEventPtr = NULL; + conditionToCheck = NULL; + blockType = 0; + whileLoopPeriod = 0; + numConditions = 0; + numActions = 0; + isUsed = true; + timeLagVar = NULL; + timeLagIsConstant = true; + whileLoopPeriodIsConstant = true; + hasWhileLoop = false; + whileLoopPeriodVar = NULL; + + } + + event::~event() { + /* + while (!conditionArray.empty()) + { + delete conditionArray.back(); + conditionArray.pop_back(); + } + + while (!actionArray.empty()) + { + delete actionArray.back(); + actionArray.pop_back(); + } + + delete nextElseEventPtr; + */ + + } + +void event::release() { + + for (int i = 0; i < numActions; i++) { + actionArray[i]->release(); + } + + if (conditionToCheck != NULL) { + conditionToCheck->release(); + conditionToCheck = NULL; + } + + if (nextElseEventPtr != NULL) { + nextElseEventPtr->release(); + } + timeLag = 0; + nextElseEventPtr = NULL; + blockType = 0; + whileLoopPeriod = 0; + numConditions = 0; + numActions = 0; + isUsed = false; + timeLagVar = NULL; + timeLagIsConstant = true; + whileLoopPeriodIsConstant = true; + hasWhileLoop = false; + whileLoopPeriodVar = NULL; + } + + void event::setTimeLag(uint32_t timeLagInput) { + timeLag = timeLagInput; + timeLagIsConstant = true; + } + + void event::setTimeLag(int* timeLagInput) { + timeLagVar = timeLagInput; + timeLagIsConstant = false; //time lag is not defined by a constant + } + + void event::setWhileLoopPeriod(uint32_t period) { + whileLoopPeriodIsConstant = true; + hasWhileLoop = true; + whileLoopPeriod = period; + + } + + void event::setWhileLoopPeriod(int* period) { + whileLoopPeriodIsConstant = false; + hasWhileLoop = true; + whileLoopPeriodVar = period; + + } + + void event::addCondition(condition* conditionInput) { + if (conditionToCheck != NULL) { + conditionToCheck->release(); + } + conditionToCheck = conditionInput; + + //conditionArray.push_back(conditionInput); + } + + void event::addAction(action* actionInput) { + actionArray[numActions] = actionInput; + numActions++; + //actionArray.push_back(actionInput); + } + + bool event::isConditionTrue(void) { + //if statement (can be left empty, which is interpreted as 'true') + //queuePtr->pcPtr->printf("Checking condition...\r\n"); + bool result = true; + /* + std::vector<condition*>::size_type sz = conditionArray.size(); + for (unsigned i = 0; i < sz; i++) { + if (!conditionArray[i]->isTrue()) { + result = false; + //queuePtr->pcPtr->printf("Consition false\r\n"); + } //else {queuePtr->pcPtr->printf("Consition true\r\n");} + } + */ + + if ((conditionToCheck!=NULL)&&(!conditionToCheck->isTrue())) { + result = false; + } + + return result; + } + + void event::execute(void) { + //called from the event queue. The condition is bypassed because it was already checked + + + uint32_t timeAtStartExec = *globalTimeKeeperPtr; + //std::vector<action*>::size_type sz = actionArray.size(); + + /* + std::deque<action*>::size_type sz = actionArray.size(); + + for (unsigned i = 0; i < sz; i++) { + actionArray[i]->execute(timeAtStartExec); + + } + */ + for (unsigned i = 0; i < numActions; i++) { + actionArray[i]->execute(timeAtStartExec); + + } + + } + + //Attach an 'else' statement to the event + void event::setNextElseEvent(event* eventInput) { + nextElseEventPtr = eventInput; + } + + + //When we we call addToQueue() the condition is checked. If true, the event is added + //to the queue, otherwise we check if there was an 'else' statement attached to the event. + void event::addToQueue(void) { + if (isConditionTrue()) { + if ((timeLagIsConstant)&&(timeLag == 0)) { + execute(); + + } else if (timeLagIsConstant) { + queuePtr->addEventToQueue(this, this->timeLag); + } else if ((!timeLagIsConstant)&&(*timeLagVar <= 0)) { + execute(); + } else { + queuePtr->addEventToQueue(this, *timeLagVar); + } + } else if ((this->nextElseEventPtr != NULL)&&(whileLoopPeriod == 0)) { + this->nextElseEventPtr->addToQueue(); + } + } + + //We can override the timeLag field and use another delay + void event::addToQueue(uint32_t delay) { + if (this->isConditionTrue()) { + //if ((delay == 0) && (whileLoopPeriod == 0)) { + if ((delay == 0)) { + this->execute(); + } else { + queuePtr->addEventToQueue(this, delay); + } + } else if ((this->nextElseEventPtr != NULL)) { //&&(!hasWhileLoop)) { + this->nextElseEventPtr->addToQueue(); + } + } + + + + functionItem::functionItem(action* actionInput, string tagInput): + tag(tagInput), + actionPtr(actionInput) { + } + + functionItem::~functionItem() { + delete actionPtr; + } + + scriptStream::scriptStream(Serial* serialInput, digitalPort** portVectorInput, int numPortsInput, eventQueue* queueInput): + portVector(portVectorInput), + numPorts(numPortsInput), + pcPtr(serialInput), + queuePtr(queueInput) { + + currentPort = -1; + currentTriggerPort = -1; + currentTriggerDir = 1; + currentFunction = -1; + + lineError = false; + blockDepth = 0; + ifBlockInit = false; + whileBlockInit = false; + elseFlag = false; + currentDelay = 0; + + } + + void scriptStream::addLineToCurrentBlock(char* lineInput) { + + bool compile = false; + bool keep = false; + for (int i = 0; i < 128; i++) { + if (lineInput[i] == ';') { + compile = true; + } else if (lineInput[i] == ' ') { + continue; + } else if (lineInput[i] == '\0') { + break; + } else { + keep = true; + compile = false; + } + } + if (keep) currentBlock.insert(currentBlock.begin(),string(lineInput)); + if (compile) parseBlock(); + + } + + + //SCRIPT PARSING - all script commands are defined here. + //------------------------------------------------------- + void scriptStream::parseBlock() { + + lineError = false; + blockDepth = 0; + ifBlockInit = false; + whileBlockInit = false; + elseFlag = false; + thenFlag = false; + currentDelay = 0; + + std::size_t stringInd = 0; + + bool wholeLineEvaluated = false; + + //pcPtr->printf("\r\n"); + while (!currentBlock.empty()) { + wholeLineEvaluated = false; + tmpLine = currentBlock.back(); + lineError = false; + //remove tabs + std::size_t found = tmpLine.find_first_of(9); //tab + while (found!=std::string::npos) { + tmpLine[found]= ' '; + found=tmpLine.find_first_of(9,found+1); + } + + found = tmpLine.find_first_of(37); //% for commenting + if (found!=std::string::npos) { + for (int p=found; p<tmpLine.size() ;p++) { + tmpLine[p]= ' '; + } + } + + //break up the line into tokens separated by spaces + tokenize(tmpLine,tokens," ;"); + + std::vector<string>::size_type sz = tokens.size(); + + for (unsigned i = 0; i < sz; i++) { + //pcPtr->printf("%s", tokens[i].c_str()); + + + //end statement signals the end of a block----------------------------------------- + if (tokens[i].compare("end") == 0) { //ends the current block + + if (ifBlockInit || whileBlockInit) { + pcPtr->printf("Error: expected a 'do' statement\r\n"); + lineError = true; + } + + ifBlockInit = false; + whileBlockInit = false; + elseFlag = false; + + if (blockDepth > 0) { + if (blockDepth == 1) { + + + //pcPtr->printf("Close trigger block for port %d\r\n",currentTriggerPort); + currentTriggerPort = -1; + + + + blockDepth = 0; + } else if (blockDepth > 1) { + //pcPtr->printf("Close block\r\n"); + blockDepth = blockDepth - 1; + } + + while ((tmpEventPtrArray.back()->blockType == 3) || (tmpEventPtrArray.back()->blockType == 4)){ + tmpEventPtrArray.pop_back(); //recursively remove the pointers to all else blocks + } + tmpEventPtrArray.pop_back(); //remove the pointer to the finished block + } else { + pcPtr->printf("Error: End statement without block\r\n"); + lineError = true; + } + + + + //sound statement used to play wave files------------------------------------------------ + //example: sound('soundfile') + // sound(stop) + } else if (tokens[i].find("sound(") != std::string::npos) { + if (ifBlockInit || whileBlockInit || elseFlag) { + pcPtr->printf("Error: expected a 'do' statement\r\n"); + lineError = true; + } + wholeLineEvaluated = true; + int pos1 = tmpLine.find("sound(")+6; + int pos2 = tmpLine.find_first_of(")",pos1); + string dispVar = tmpLine.substr(pos1,pos2-pos1); + + int* tmpVar = findIntVariable(dispVar); + bool isText = false; + bool stopSignal = false; + bool resetSignal = false; + if (tmpVar == NULL) { + if ((tmpLine.compare(pos1,1,"'")==0) && (tmpLine.compare(pos2-1,1,"'")==0)) { + isText = true; + } else if (dispVar.compare("stop") == 0) { + stopSignal = true; + } else if (dispVar.compare("reset") == 0) { + resetSignal = true; + } else { + pcPtr->printf("Error: variable input to sound() does not exist\r\n"); + lineError = true; + } + } + action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS); + if (tmpAction == NULL) { + pcPtr->printf("Error: no memory slots available.\r\n"); + lineError = true; + } + if (!lineError && (blockDepth == 0)) { + //we are not inside a block structure, so play sound now + if (stopSignal) { + soundControl S; + S.setPlayback(false); + S.execute(); + } else if (resetSignal) { + soundControl S; + S.setReset(); + S.execute(); + } else if (isText) { + if (pos2-pos1-2 <= 20) { + soundControl S; + S.setFile(tmpLine.substr(pos1+1,pos2-pos1-2)); + S.setPlayback(true);//ANDY + S.execute(); + } else { + pcPtr->printf("Error: sound file names must be 20 characters or less.\r\n"); + lineError = true; + } + } else { + pcPtr->printf("Error: variable input to sound() not yet supported. Enter a string in single quotes.\r\n"); + lineError = true; + } + + } else if (!lineError && (blockDepth > 0) ){ + //the disp function was put inside a block + if (stopSignal) { + soundControl* sPtr = new soundControl(); + sPtr->setPlayback(false); + //action* tmpAction = new action(sPtr); + tmpAction->set(sPtr); + tmpEventPtrArray.back()->addAction(tmpAction); + } else if (resetSignal) { + soundControl* sPtr = new soundControl(); + sPtr->setReset(); + //action* tmpAction = new action(sPtr); + tmpAction->set(sPtr); + tmpEventPtrArray.back()->addAction(tmpAction); + } else if (isText) { + + if (pos2-pos1-2 <= 20) { + soundControl* sPtr = new soundControl(); + sPtr->setFile(tmpLine.substr(pos1+1,pos2-pos1-2)); + //action* tmpAction = new action(sPtr); + tmpAction->set(sPtr); + tmpEventPtrArray.back()->addAction(tmpAction); + } else { + pcPtr->printf("Error: sound file names must be 20 characters or less.\r\n"); + lineError = true; + } + } else { + pcPtr->printf("Error: variable input to sound() not yet supported. Enter a string in single quotes.\r\n"); + lineError = true; + } + + //pcPtr->printf("Sound action\r\n"); + } + + } else if (tokens[i].find("volume(") != std::string::npos) { + if (ifBlockInit || whileBlockInit || elseFlag) { + pcPtr->printf("Error: expected a 'do' statement\r\n"); + lineError = true; + } + wholeLineEvaluated = true; + int pos1 = tmpLine.find("volume(")+7; + int pos2 = tmpLine.find_first_of(")",pos1); + string dispVar = tmpLine.substr(pos1,pos2-pos1); + + int* tmpVar = findIntVariable(dispVar); + bool isText = false; + if (tmpVar == NULL) { + if (isNumber(dispVar)) { + isText = true; + } else { + pcPtr->printf("Error: variable input to volume() does not exist\r\n"); + lineError = true; + } + } + action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS); + if (tmpAction == NULL) { + pcPtr->printf("Error: no memory slots available.\r\n"); + lineError = true; + } + if (!lineError && (blockDepth == 0)) { + //we are not inside a block structure, so play sound now + if (isText) { + int newVolume = atoi(dispVar.data()); + if ((newVolume >=0)&&(newVolume <= 255)) { + soundControl S; + S.setVolume(newVolume); + S.execute(); + } else { + pcPtr->printf("Error: sound volume must be between 0 and 255 .\r\n"); + lineError = true; + } + } else { + soundControl S; + S.setVolume(tmpVar); + S.execute(); + } + + } else if (!lineError && (blockDepth > 0) ){ + //the disp function was put inside a block + if (isText) { + int newVolume = atoi(dispVar.data()); + + soundControl* sPtr = new soundControl(); + sPtr->setVolume(newVolume); + + //action* tmpAction = new action(sPtr); + tmpAction->set(sPtr); + tmpEventPtrArray.back()->addAction(tmpAction); + + } else { + soundControl* sPtr = new soundControl(); + sPtr->setVolume(tmpVar); + //action* tmpAction = new action(sPtr); + tmpAction->set(sPtr); + tmpEventPtrArray.back()->addAction(tmpAction); + } + + //pcPtr->printf("Volume action\r\n"); + } + //clock statement used to is used to control the clock------------------------- + //example: clock(reset); clock(slave); clock(standalone) + } else if (tokens[i].find("clock(") != std::string::npos) { //clock commands + if (ifBlockInit || whileBlockInit || elseFlag) { + pcPtr->printf("Error: expected a 'do' statement\r\n"); + lineError = true; + } + if (blockDepth > 0) { + pcPtr->printf("Error: clock commands only allowed outside of block structure\r\n"); + lineError = true; + } + + if (!lineError) { + int pos1 = tmpLine.find("clock(")+6; + int pos2 = tmpLine.find_first_of(")",pos1); + string dispVar = tmpLine.substr(pos1,pos2-pos1); + + + if (blockDepth == 0) { + if (dispVar.compare("reset") == 0) { + resetTimer = true; + queuePtr->eraseQueue(); + textDisplay.send(string("Clock reset to 0\r\n")); + //pcPtr->printf("Clock reset to 0\r\n"); + } else if (dispVar.compare("slave") == 0) { + if (!clockSlave) { + changeToSlave = true; + textDisplay.send(string("Slave mode\r\n")); + //pcPtr->printf("Slave mode\r\n"); + } + } else if (dispVar.compare("standalone") == 0) { + if (clockSlave) { + changeToStandAlone = true; + textDisplay.send(string("Standalone mode\r\n")); + //pcPtr->printf("Standalone mode\r\n"); + } + } else { + pcPtr->printf("Clock control statement not understood\r\n"); + lineError = true; + } + } + } + + //disp command used to display text via serial--------------------------------------- + //example: disp('hello'); disp(myVar) + } else if (tokens[i].find("disp(") != std::string::npos) { //display value of variable + + if (ifBlockInit || whileBlockInit || elseFlag) { + pcPtr->printf("Error: expected a 'do' statement\r\n"); + lineError = true; + } + + //int pos1 = tokens[i].find("disp(")+5; + //int pos2 = tokens[i].find_first_of(")",pos1); + //string dispVar = tokens[i].substr(pos1,pos2-pos1); + + wholeLineEvaluated = true; + int pos1 = tmpLine.find("disp(")+5; + int pos2 = tmpLine.find_first_of(")",pos1); + string dispVar = tmpLine.substr(pos1,pos2-pos1); + + int* tmpVar = findIntVariable(dispVar); + bool isText = false; + if (tmpVar == NULL) { + if ((tmpLine.compare(pos1,1,"'")==0) && (tmpLine.compare(pos2-1,1,"'")==0)) { + isText = true; + } else { + pcPtr->printf("Error: variable to display does not exist\r\n"); + lineError = true; + } + } + displayAction* dPtr = findFirstUnUsed(displayActionBlock, NUMDISPLAYACTIONS); + if (dPtr == NULL) { + pcPtr->printf("Error: no memory slots available.\r\n"); + lineError = true; + } + if (!lineError && (blockDepth == 0)) { + //we are not inside a block structure, so display now + + if (isText) { + //displayAction* dPtr = new displayAction(tmpLine.substr(pos1+1,pos2-pos1-2), pcPtr); + dPtr->set(tmpLine.substr(pos1+1,pos2-pos1-2), pcPtr); + dPtr->execute(); + //delete dPtr; + dPtr->release(); + } else { + //displayAction* dPtr = new displayAction(tmpVar, dispVar, pcPtr); + dPtr->set(tmpVar, dispVar, pcPtr); + dPtr->execute(); + //delete dPtr; + dPtr->release(); + } + + } else if (!lineError && (blockDepth > 0) ){ + //the disp function was put inside a block + action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS); + if (tmpAction == NULL) { + pcPtr->printf("Error: no memory slots available.\r\n"); + lineError = true; + } + if (!lineError && isText) { + //displayAction* dPtr = new displayAction(tmpLine.substr(pos1+1,pos2-pos1-2), pcPtr); + dPtr->set(tmpLine.substr(pos1+1,pos2-pos1-2), pcPtr); + tmpAction->set(dPtr); + //action* tmpAction = new action(dPtr); + tmpEventPtrArray.back()->addAction(tmpAction); + } else if (!lineError) { + //displayAction* dPtr = new displayAction(tmpVar, dispVar, pcPtr); + dPtr->set(tmpVar, dispVar, pcPtr); + tmpAction->set(dPtr); + //action* tmpAction = new action(dPtr); + tmpEventPtrArray.back()->addAction(tmpAction); + } + + //pcPtr->printf("Display action\r\n"); + } + + + //int is used to decalar new variables. Only allowed outside of callbacks------------------- + //example: int a; int b = 9 + } else if (tokens[i].compare("int") == 0) { //define a new integer variable + + if (ifBlockInit || whileBlockInit) { + pcPtr->printf("Error: expected a 'do' statement\r\n"); + lineError = true; + } + tmpString = ""; + wholeLineEvaluated = true; + int spacesBeforeEqualSign = 0; + bool countSpaces = true; + //combine the tokens without whitespaces + for (unsigned j = i+1; j < sz; j++) { + tmpString.append(tokens[j]); + if (tokens[j].find_first_of("=") != std::string::npos) { + if (tokens[j].find_first_of("=") > 0) spacesBeforeEqualSign++; + countSpaces = false; + } else if (countSpaces) { + spacesBeforeEqualSign++; + } + } + + if (blockDepth > 0) { + pcPtr->printf("Error: Variables can only be first declared outside of callbacks.\r\n"); + lineError = true; + } + + if ((!lineError) && (spacesBeforeEqualSign > 1)) { + pcPtr->printf("Error: Variable can't have a space in it.\r\n"); + lineError = true; + } + stringInd = tmpString.find_first_of("="); + + bool variableCreated = false; + if (!lineError) { + if (((stringInd == std::string::npos) && (sz == 2)) || (stringInd != std::string::npos)) { + if (createIntVariable(tmpString.substr(0,stringInd))) { + //pcPtr->printf("Created variable: %s\r\n", tmpString.substr(0,stringInd).data()); + variableCreated = true; + } else { + int* tmpVar = findIntVariable(tmpString.substr(0,stringInd)); + *tmpVar = 0; + //pcPtr->printf("Reset variable %s to 0\r\n", tmpString.substr(0,stringInd).data()); + //lineError = true; + } + } else { + pcPtr->printf("Error: variable declaration not understood.\r\n", tmpString.substr(0,stringInd).data()); + lineError = true; + } + } + + if ((!lineError) && (stringInd != std::string::npos)) { //evaluate the expression + action* tmpAction = evaluateAssignmentForAction(tmpString); + if (tmpAction != NULL) { + tmpAction->execute(); + //delete tmpAction; + tmpAction->release(); + } else { + lineError = true; + if (variableCreated) { + delete globalVariables.back(); + globalVariables.pop_back(); + } + } + } + + //serial command is used to toggle whether or not to buffer up output text---------------- + //examples: serial buffer; serial send + } else if (tokens[i].compare("serial") == 0) { + if (ifBlockInit || whileBlockInit || elseFlag) { + pcPtr->printf("Error: expected a 'do' statement\r\n"); + lineError = true; + } + bool stream = true; + if ((!lineError)&&(i+1 < sz)){ + if (tokens[i+1].compare("buffer") == 0) { + stream = false; + } else if (tokens[i+1].compare("send") == 0) { + stream = true; + } else { + pcPtr->printf("Error: 'serial' useage: 'serial buffer' or 'serial send'\r\n"); + lineError = true; + } + } + i++; + if ((!lineError) && (blockDepth == 0)) { + if (stream) { + textStreaming = true; + } else { + textStreaming = false; + } + } else if ((!lineError) && (blockDepth > 0)) { + if (stream) { + //action* tmpAction = new action(1); //code 1 = turn on text streaming + action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS); + if (tmpAction == NULL) { + pcPtr->printf("Error: no memory slots available.\r\n"); + lineError = true; + } else { + tmpAction->set(1); + tmpEventPtrArray.back()->addAction(tmpAction); + } + + } else { + //action* tmpAction = new action(2); //code 2 = turn on text buffering + action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS); + if (tmpAction == NULL) { + pcPtr->printf("Error: no memory slots available.\r\n"); + lineError = true; + } else { + tmpAction->set(2); + tmpEventPtrArray.back()->addAction(tmpAction); + } + } + } + + //updates command toggles the DIO update messages upon a change------------------ + //examples: updates on; updates off + } else if (tokens[i].compare("updates") == 0) { + if (ifBlockInit || whileBlockInit || elseFlag) { + pcPtr->printf("Error: expected a 'do' statement\r\n"); + lineError = true; + } + bool stream = true; + if ((!lineError)&&(i+1 < sz)){ + if (tokens[i+1].compare("on") == 0) { + stream = true; + } else if (tokens[i+1].compare("off") == 0) { + stream = false; + } else { + pcPtr->printf("Error: 'updates' useage: 'updates on' or 'updates off'\r\n"); + lineError = true; + } + } + i++; + if ((!lineError) && (blockDepth == 0)) { + if (stream) { + broadCastStateChanges = true; + } else { + broadCastStateChanges = false; + } + } else if ((!lineError) && (blockDepth > 0)) { + if (stream) { + //action* tmpAction = new action(3); //code 3 = turn on updates + action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS); + if (tmpAction == NULL) { + pcPtr->printf("Error: no memory slots available.\r\n"); + lineError = true; + } else { + tmpAction->set(3); + tmpEventPtrArray.back()->addAction(tmpAction); + } + } else { + //action* tmpAction = new action(4); //code 4 = turn off updates + action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS); + if (tmpAction == NULL) { + pcPtr->printf("Error: no memory slots available.\r\n"); + lineError = true; + } else { + tmpAction->set(4); + tmpEventPtrArray.back()->addAction(tmpAction); + } + + } + } + + //clear is used to clear things from memory--------------------------------- + //examples: clear all; clear callbacks; clear queue + } else if (tokens[i].compare("ram") == 0) { + if (ifBlockInit || whileBlockInit || elseFlag) { + pcPtr->printf("Error: expected a 'do' statement\r\n"); + lineError = true; + } + if ((!lineError) && (blockDepth > 0)) { + pcPtr->printf("Error: ram statement is not allowed inside a block.\r\n"); + lineError = true; + } + if (!lineError) { + DisplayRAMBanks(); + } + } else if (tokens[i].compare("memory") == 0) { + if (ifBlockInit || whileBlockInit || elseFlag) { + pcPtr->printf("Error: expected a 'do' statement\r\n"); + lineError = true; + } + if ((!lineError) && (blockDepth > 0)) { + pcPtr->printf("Error: memory statement is not allowed inside a block.\r\n"); + lineError = true; + } + if (!lineError) { + displayMemoryLeft(); + } + + + } else if (tokens[i].compare("clear") == 0) { //delete all created events and variables + if (ifBlockInit || whileBlockInit || elseFlag) { + pcPtr->printf("Error: expected a 'do' statement\r\n"); + lineError = true; + } + int clearMode = 0; + if ((!lineError)&&(i+1 < sz)){ + if (tokens[i+1].compare("all") == 0) { + clearMode = 1; + } else if (tokens[i+1].compare("blocks") == 0) { + clearMode = 2; + } else if (tokens[i+1].compare("queue") == 0) { + clearMode = 3; + } else { + pcPtr->printf("Error: clear what: all, blocks, or queue? \r\n"); + lineError = true; + } + } else { + pcPtr->printf("Error: clear what: all, blocks, or queue? \r\n"); + lineError = true; + } + + + if ((!lineError) && (clearMode < 3) && (blockDepth > 0)) { + pcPtr->printf("Error: 'clear all' and 'clear blocks' only allowed outside of block structures\r\n"); + lineError = true; + } + if (!lineError) { + i++; + //clear variables + if (clearMode == 1) { + while (!globalVariables.empty()) { + globalVariables.pop_back(); + } + } + + //clear callbacks, functions, and queue + if (clearMode < 3) { + for (int pNum = 1; pNum <= numPorts; pNum++) { + //delete portVector[pNum]->triggerUpEventPtr; + if (portVector[pNum]->triggerUpEventPtr != NULL) { + portVector[pNum]->triggerUpEventPtr->release(); + } + portVector[pNum]->triggerUpEventPtr = NULL; + + //delete portVector[pNum]->triggerDownEventPtr; + if (portVector[pNum]->triggerDownEventPtr != NULL) { + portVector[pNum]->triggerDownEventPtr->release(); + } + portVector[pNum]->triggerDownEventPtr = NULL; + while (!functionArray.empty()) { + delete functionArray.back(); + functionArray.pop_back(); + } + } + + queuePtr->eraseQueue(); + } + + if (clearMode == 4) { + if (blockDepth > 0) { //we are inside a block + action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS); + if (tmpAction == NULL) { + pcPtr->printf("Error: no memory slots available.\r\n"); + lineError = true; + } else { + + int8_t code = 0; + tmpAction->set(code); + //action* tmpAction = new action(code); //code 0 = clear queue + tmpEventPtrArray.back()->addAction(tmpAction); + } + } else { + //clear queue now + queuePtr->eraseQueue(); + } + } + + + } + + //do starts a block--------------------------------------------------------- + //example: do in 500 + // ... + // end + + }else if(tokens[i].compare("kaboom") == 0){//MAX ANDY + mbed_reset(); + } + + + + + else if (tokens[i].compare("do") == 0) { //the start of a block + + if (!ifBlockInit && !whileBlockInit) { + + if ((currentTriggerPort > 0) || (currentFunction > 0)) { //check to make sure we are inside a trigger block + //pcPtr->printf("Start new block\r\n"); + + } else { + pcPtr->printf("Error: a statement block must be placed inside a callback or function.\r\n"); + lineError = true; + } + + } + tmpEvent = findFirstUnUsed(eventBlock, NUMEVENTS); + action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS); + bool eventReserved = false; + if ((tmpEvent == NULL)||(tmpAction == NULL)) { + pcPtr->printf("Error: no memory slots available.\r\n"); + lineError = true; + + } else { + + + } + + if (i+2 < sz) { //a time delay in the block + + if ((!lineError) && (tokens[i+1].compare("in") == 0) && (isNumber(tokens[i+2]))) { + + currentDelay = atoi(tokens[i+2].data()); + if (currentDelay < 0) { + pcPtr->printf("Error: block delay time must be a positive integer\r\n"); + lineError = true; + } else if (!ifBlockInit) { //a standalone do block + //tmpEvent = new event(queuePtr); + tmpEvent->isUsed = true; + eventReserved = true; + tmpEvent->setTimeLag(currentDelay); + + if ((!elseFlag) && ((!thenFlag))) { + //tmpEventPtrArray.back()->addAction(new action(tmpEvent)); + tmpAction->set(tmpEvent); + tmpEventPtrArray.back()->addAction(tmpAction); + tmpEventPtrArray.push_back(tmpEvent); + tmpEventPtrArray.back()->blockType = 2; //this is a do block + blockDepth = blockDepth+1; + } else if (elseFlag) { + tmpEventPtrArray.back()->setNextElseEvent(tmpEvent); + tmpEventPtrArray.push_back(tmpEvent); + tmpEventPtrArray.back()->blockType = 4; //an else block + } else if (thenFlag) { + + tmpEventPtrArray.back()->setNextElseEvent(tmpEvent); + tmpEventPtrArray.push_back(tmpEvent); + tmpEventPtrArray.back()->blockType = 8; //a then block + } + //pcPtr->printf("Block delay: %d\r\n", tmpEventPtrArray.back()->timeLag); + } else { //an if block + tmpEventPtrArray.back()->setTimeLag(currentDelay); + + if (!elseFlag && !thenFlag) { + if (blockDepth > 1) { //this is a nested block, so add it as an action to the parent block + tmpAction->set(tmpEventPtrArray.back()); + tmpEventPtrArray.at(tmpEventPtrArray.size()-2)->addAction(tmpAction); + //tmpEventPtrArray.at(tmpEventPtrArray.size()-2)->addAction(new action(tmpEventPtrArray.back())); + } + } else if (elseFlag){ + tmpEventPtrArray.at(tmpEventPtrArray.size()-2)->setNextElseEvent(tmpEventPtrArray.back()); + } else if (thenFlag){ + tmpEventPtrArray.at(tmpEventPtrArray.size()-2)->setNextElseEvent(tmpEventPtrArray.back()); + + } + //pcPtr->printf("Block delay: %d\r\n", tmpEventPtrArray.back()->timeLag); + + } + + } else if ((!lineError) && (tokens[i+1].compare("in") == 0) && (findIntVariable(tokens[i+2])!=NULL)) { + + int* delayVar = findIntVariable(tokens[i+2]); + //currentDelay = atoi(tokens[i+2].data()); + if (!ifBlockInit) { //a standalone do block + //tmpEvent = new event(queuePtr); + tmpEvent->isUsed = true; + eventReserved = true; + tmpEvent->setTimeLag(delayVar); + + if ((!elseFlag) && ((!thenFlag))) { + //tmpEventPtrArray.back()->addAction(new action(tmpEvent)); + tmpAction->set(tmpEvent); + tmpEventPtrArray.back()->addAction(tmpAction); + tmpEventPtrArray.push_back(tmpEvent); + tmpEventPtrArray.back()->blockType = 2; //this is a do block + blockDepth = blockDepth+1; + } else if (elseFlag) { + tmpEventPtrArray.back()->setNextElseEvent(tmpEvent); + tmpEventPtrArray.push_back(tmpEvent); + tmpEventPtrArray.back()->blockType = 4; //an else block + } else if (thenFlag) { + + tmpEventPtrArray.back()->setNextElseEvent(tmpEvent); + tmpEventPtrArray.push_back(tmpEvent); + tmpEventPtrArray.back()->blockType = 8; //a then block + } + //pcPtr->printf("Block delay: %d\r\n", tmpEventPtrArray.back()->timeLag); + } else { //an if block + tmpEventPtrArray.back()->setTimeLag(delayVar); + + if (!elseFlag && !thenFlag) { + if (blockDepth > 1) { //this is a nested block, so add it as an action to the parent block + tmpAction->set(tmpEventPtrArray.back()); + tmpEventPtrArray.at(tmpEventPtrArray.size()-2)->addAction(tmpAction); + //tmpEventPtrArray.at(tmpEventPtrArray.size()-2)->addAction(new action(tmpEventPtrArray.back())); + } + } else if (elseFlag){ + tmpEventPtrArray.at(tmpEventPtrArray.size()-2)->setNextElseEvent(tmpEventPtrArray.back()); + } else if (thenFlag){ + tmpEventPtrArray.at(tmpEventPtrArray.size()-2)->setNextElseEvent(tmpEventPtrArray.back()); + + } + //pcPtr->printf("Block delay: %d\r\n", tmpEventPtrArray.back()->timeLag); + + } + + } else { + pcPtr->printf("Error: block delay time must be a positive integer or a variable\r\n"); + lineError = true; + } + } else if (!lineError && !ifBlockInit) { //no time delay given, standalone do + currentDelay = 0; + //tmpEvent = new event(queuePtr); + tmpEvent->isUsed = true; + eventReserved = true; + tmpEvent->setTimeLag(currentDelay); + if (!elseFlag && !thenFlag) { + tmpAction->set(tmpEvent); + tmpEventPtrArray.back()->addAction(tmpAction); + //tmpEventPtrArray.back()->addAction(new action(tmpEvent)); + tmpEventPtrArray.push_back(tmpEvent); + blockDepth = blockDepth+1; + } else if (elseFlag) { + tmpEventPtrArray.back()->setNextElseEvent(tmpEvent); + tmpEventPtrArray.push_back(tmpEvent); + tmpEventPtrArray.back()->blockType = 4; //an else block + } else if (thenFlag) { + tmpEventPtrArray.back()->setNextElseEvent(tmpEvent); + tmpEventPtrArray.push_back(tmpEvent); + tmpEventPtrArray.back()->blockType = 8; //a then block + } + //pcPtr->printf("Block delay: %d\r\n", tmpEventPtrArray.back()->timeLag); + } else if (!lineError) { //no time delay, if block + + currentDelay = 0; + tmpEventPtrArray.back()->setTimeLag(currentDelay); + + + if (!elseFlag && !thenFlag) { + if (blockDepth > 1) { + tmpAction->set(tmpEventPtrArray.back()); + tmpEventPtrArray.at(tmpEventPtrArray.size()-2)->addAction(tmpAction); + //tmpEventPtrArray.at(tmpEventPtrArray.size()-2)->addAction(new action(tmpEventPtrArray.back())); + } + } else { + tmpEventPtrArray.at(tmpEventPtrArray.size()-2)->setNextElseEvent(tmpEventPtrArray.back()); + } + + + //pcPtr->printf("Block delay: %d\r\n", tmpEventPtrArray.back()->timeLag); + } + if (lineError && eventReserved) { + tmpEvent->release(); + } + //close block initiation + ifBlockInit = false; + whileBlockInit = false; + wholeLineEvaluated = true; + elseFlag = false; + thenFlag = false; + + //callback starts a callback block------------------------------------------ + //exmaple: callback portin(1) down + // ... + // end + } else if (tokens[i].compare("callback") == 0) { //a new callback block + if (ifBlockInit || whileBlockInit || elseFlag) { + pcPtr->printf("Error: expected a 'do' statement\r\n"); + lineError = true; + } + if (blockDepth != 0) { + pcPtr->printf("Error: Can't declare a callback block within another block\r\n"); + lineError = true; + } + if (!lineError) { + wholeLineEvaluated = true; + if (i+2 < sz) { + if ((tokens[i+1].find("portin[") != std::string::npos) && (tokens[i+1].size() > 8) ) { //callback for a digital port + int pos1 = tokens[i+1].find("portin[")+7; + int pos2 = tokens[i+1].find_first_of("]",pos1); + currentTriggerPort = atoi(tokens[i+1].substr(pos1,pos2-pos1).data()); + + if (currentTriggerPort <= 0) { + currentTriggerPort = -1; + pcPtr->printf("Error: Not a valid port number\r\n"); + lineError = true; + } + } else { + pcPtr->printf("Error: Not a valid callback input\r\n"); + lineError = true; + } + if (tokens[i+2].compare("up") == 0) { + currentTriggerDir = 1; + } else if (tokens[i+2].compare("down") == 0) { + currentTriggerDir = -1; + } else { + pcPtr->printf("Error: No trigger direction given\r\n"); + lineError = true; + } + + } else { + if (!lineError) pcPtr->printf("Error: Not enough arguments for callback statement\r\n"); + lineError = true; + } + if (sz > 3) { + if (!((sz == 4) && (tokens[i+3].compare("do") == 0))) { + pcPtr->printf("Error: Too many arguments in callback statement\r\n"); + lineError = true; + } + } + + tmpEvent = findFirstUnUsed(eventBlock, NUMEVENTS); + if (tmpEvent != NULL) { + tmpEvent->isUsed = true; + + } else { + pcPtr->printf("Error: no memory slots available.\r\n"); + lineError = true; + } + if (!lineError) { + //pcPtr->printf("Current port: %d\r\n", currentTriggerPort); + blockDepth = 1; + i = i+2; + //create new event and attach it to the port + //tmpEventPtrArray.push_back(new event(queuePtr)); + tmpEventPtrArray.push_back(tmpEvent); + if (currentTriggerDir == 1) { + + portVector[currentTriggerPort]->setTriggerUpEvent(tmpEventPtrArray.back()); + } else { + + portVector[currentTriggerPort]->setTriggerDownEvent(tmpEventPtrArray.back()); + } + + } + } + + //if starts an if block---------------------------------------------- + //examples: if x < 10 && y == 1 do; if a==1 do in 1000 + } else if (tokens[i].compare("if") == 0) { //a new if block + if (ifBlockInit || whileBlockInit) { + pcPtr->printf("Error: expected a 'do' statement\r\n"); + lineError = true; + } + + ifBlockInit = true; + currentDelay = 0; + bool eventDefined = false; + tmpEvent = findFirstUnUsed(eventBlock, NUMEVENTS); + if (tmpEvent != NULL) { + tmpEvent->isUsed = true; + eventDefined = true; + } else { + pcPtr->printf("Error: no memory slots available.\r\n"); + lineError = true; + } + if (!lineError) { + //this is a regular event + //tmpEventPtrArray.push_back(new event(queuePtr)); + tmpEventPtrArray.push_back(tmpEvent); + + if ((!elseFlag) && ((!thenFlag))) { + tmpEventPtrArray.back()->blockType = 1; //this is an if block + blockDepth = blockDepth + 1; + } else if (elseFlag) { + tmpEventPtrArray.back()->blockType = 3; //this is an else if block + } else if (thenFlag) { + tmpEventPtrArray.back()->blockType = 7; //this is a then if block + } + } + + if (!lineError) { + //combine the condition tokens without whitespaces + tmpString = ""; + for (unsigned j = i+1; j < sz; j++) { + if (tokens[j].compare("do") != 0) { + i++; + tmpString.append(tokens[j]); + } else { + break; + } + } + //adds the conditions to the current event + + if (!evaluateConditions(tmpString, tmpEventPtrArray.back())) lineError = true; + } + + if (lineError && eventDefined) { + tmpEvent->release(); + } + + + //else starts an else block------------------------------------- + //examples: else do in 500; else if x==7 do + } else if (tokens[i].compare("else") == 0) { //an else block + if (ifBlockInit || whileBlockInit) { + pcPtr->printf("Error: expected a 'do' statement\r\n"); + lineError = true; + } + + //trigger blocks can't have else conditions + if ((!lineError) && (blockDepth < 2) && (currentTriggerPort > -1)) { + pcPtr->printf("Error: else statement can not occur after a trigger block or outside a block\r\n"); + lineError = true; + } + + //check to make sure we are in an 'if' block + if ((!lineError) && (tmpEventPtrArray.back()->blockType != 1) && (tmpEventPtrArray.back()->blockType != 3)) { //not currently in an 'if' or 'else if' block + pcPtr->printf("Error: else statement can only occur in an 'if' block\r\n"); + lineError = true; + } + if (!lineError) { + elseFlag = true; + + } + } else if (tokens[i].compare("then") == 0) { //a then block + if (ifBlockInit || whileBlockInit) { + pcPtr->printf("Error: expected a 'do' statement\r\n"); + lineError = true; + } + + //trigger blocks can't have else conditions + if ((!lineError) && (blockDepth < 2) && (currentTriggerPort > -1)) { + pcPtr->printf("Error: 'then' statement can only occur after a 'while' block\r\n"); + lineError = true; + } + + //check to make sure we are in a 'while' block + if ((!lineError) && (tmpEventPtrArray.back()->blockType != 5)) { //not currently in a while block + pcPtr->printf("Error: 'then' statement can only occur in a 'while' block\r\n"); + lineError = true; + } + if (!lineError) { + thenFlag = true; + + } + //while starts a while block---------------------------------------- + //example: while x<10 do every 100 + // ... + // end + } else if (tokens[i].compare("while") == 0) { //a new while block + if (ifBlockInit || whileBlockInit) { + pcPtr->printf("Error: expected a 'do' statement\r\n"); + lineError = true; + } + + if ((currentTriggerPort > 0) || (currentFunction > 0)) { //check to make sure we are inside a trigger block + //pcPtr->printf("Start new block\r\n"); + + } else { + pcPtr->printf("Error: a statement block must be placed inside a callback or function.\r\n"); + lineError = true; + } + //whileBlockInit = true; + currentDelay = 0; + + tmpEvent = findFirstUnUsed(eventBlock, NUMEVENTS); + if (tmpEvent != NULL) { + tmpEvent->isUsed = true; + tmpEvent->setTimeLag(currentDelay); + } else { + pcPtr->printf("Error: no memory slots available.\r\n"); + lineError = true; + } + + //tmpEvent = new event(queuePtr); + + + if (!lineError) { + //combine the condition tokens without whitespaces + tmpString = ""; + for (unsigned j = i+1; j < sz; j++) { + if (tokens[j].compare("do") != 0) { + i++; + tmpString.append(tokens[j]); + } else { + break; + } + } + //adds the conditions to the current event + if (!evaluateConditions(tmpString, tmpEvent)) lineError = true; + } + + if (!lineError) { + if ((i+3) < sz) { + if ((tokens[i+1].compare("do") == 0) && (tokens[i+2].compare("every") == 0)) { + + if (isNumber(tokens[i+3])) { + uint32_t period = atoi(tokens[i+3].data()); + if (period > 0) { + //pcPtr->printf("While block\r\n"); + + //tmpEvent->whileLoopPeriod = period; + tmpEvent->setWhileLoopPeriod(period); + if (!elseFlag) { + tmpEvent->blockType = 5; //this is a while block + + action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS); + if (tmpAction == NULL) { + pcPtr->printf("Error: no memory slots available.\r\n"); + lineError = true; + } else { + tmpAction->set(tmpEvent); + } + //tmpEventPtrArray.back()->addAction(new action(tmpEvent)); + tmpEventPtrArray.back()->addAction(tmpAction); + + tmpEventPtrArray.push_back(tmpEvent); + blockDepth = blockDepth+1; + } else { + tmpEvent->blockType = 6; //this is an else while block + tmpEventPtrArray.back()->setNextElseEvent(tmpEvent); + tmpEventPtrArray.push_back(tmpEvent); + } + wholeLineEvaluated = true; + } else { + pcPtr->printf("Error: loop period must be a positive integer.\r\n"); + lineError = true; + } + } else if (findIntVariable(tokens[i+3])!=NULL) { + + int* period = findIntVariable(tokens[i+3]); + //tmpEvent->whileLoopPeriodVar = period; + tmpEvent->setWhileLoopPeriod(period); + if (!elseFlag) { + tmpEvent->blockType = 5; //this is a while block + + action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS); + if (tmpAction == NULL) { + pcPtr->printf("Error: no memory slots available.\r\n"); + lineError = true; + } else { + tmpAction->set(tmpEvent); + } + //tmpEventPtrArray.back()->addAction(new action(tmpEvent)); + tmpEventPtrArray.back()->addAction(tmpAction); + + tmpEventPtrArray.push_back(tmpEvent); + blockDepth = blockDepth+1; + } else { + tmpEvent->blockType = 6; //this is an else while block + tmpEventPtrArray.back()->setNextElseEvent(tmpEvent); + tmpEventPtrArray.push_back(tmpEvent); + } + wholeLineEvaluated = true; + } + } else { + pcPtr->printf("Error: expected a 'do every' statement\r\n"); + lineError = true; + } + } else { + pcPtr->printf("Error: expected a 'do every' statement\r\n"); + lineError = true; + } + } + + //if the line contains an '=' sign,the equality is evaulated------------------------- + //examples: a = 1; a = b + 5; a = random(100); portout[2] = 1; portout[2] = flip + } else if ((tmpLine.find_first_of("=") != std::string::npos) ) { //an expression + if (ifBlockInit || whileBlockInit || elseFlag) { + pcPtr->printf("Error: expected a 'do' statement\r\n"); + lineError = true; + } + + wholeLineEvaluated = true; + tmpString = ""; + int spacesBeforeEqualSign = 0; + bool countSpaces = true; + //combine the tokens without whitespaces + for (unsigned j = i; j < sz; j++) { + tmpString.append(tokens[j]); + if (tokens[j].find_first_of("=") != std::string::npos) { + if (tokens[j].find_first_of("=") > 0) spacesBeforeEqualSign++; + countSpaces = false; + } else if (countSpaces) { + spacesBeforeEqualSign++; + } + } + if (!lineError && spacesBeforeEqualSign > 1) { + pcPtr->printf("Error: Variable can't have a space in it.\r\n"); + lineError = true; + } + + if (!lineError) { + if (blockDepth > 0) { + action* tmpAction = evaluateAssignmentForAction(tmpString); + if (tmpAction != NULL) { + tmpEventPtrArray.back()->addAction(tmpAction); + //pcPtr->printf("Added action with delay: %d\r\n", tmpEventPtrArray.back()->timeLag); + + } else { + lineError = true; + } + + } else { //assignment was written outside of any block structure, so execute now + + + action* tmpAction = evaluateAssignmentForAction(tmpString); + + if (tmpAction != NULL) { + tmpAction->execute(); + + //delete tmpAction; + tmpAction->release(); + } else { + lineError = true; + } + } + } + } + ////ANDY +// else if (tokens[i].find("opto(") != std::string::npos) { +// wholeLineEvaluated = true; +// int pos1 = tmpLine.find("opto(")+5; +// int pos2 = tmpLine.find_first_of(")",pos1); +// string dispVar = tmpLine.substr(pos1,pos2-pos1); +// device.printf(dispVar.c_str()); +// } + + else { + //if there was no match to any of the above, an error is given + pcPtr->printf("Error: statement not understood.\r\n"); + lineError = true; + } + + if (lineError) break; //stop parsing the rest of the line if an error was detected + + if (wholeLineEvaluated) { //some of the tokens forces the whole line to be avaluated at once + i = sz; //skip ahead to end of the line + } + + } + + //if there was an error, we quit compiling the code + if (lineError) { + pcPtr->printf("Line text: "); + while (!tokens.empty()) { + pcPtr->printf("%s ",tokens.front().data()); + tokens.erase(tokens.begin()); + } + pcPtr->printf("\r\n"); + while (!currentBlock.empty()) { + currentBlock.pop_back(); + } + delete tmpEvent; + } else { + + while (!tokens.empty()) { + tokens.pop_back(); + } + currentBlock.pop_back(); + } + + } + + //make sure that all blocks have a matching end statement + if ((!lineError)&&(blockDepth > 0)) { + pcPtr->printf("Error: Missing 1 or more end statements\r\n"); + lineError = true; + } + //pcPtr->printf("~~~\r\n"); //signals that the code was compiled + textDisplay.send("~~~\r\n"); + //displayMemoryLeft(); + //DisplayRAMBanks(); + +} + + +//used to return a pointer to a variable, if it exists +int* scriptStream::findIntVariable(string nameInput) { + + int* outPtr = NULL; + bool foundIt = false; + + if (nameInput.find("portout") != std::string::npos) { + int pos1 = nameInput.find("portout[")+8; + int pos2 = nameInput.find_first_of("]",pos1); + int portnum = atoi(nameInput.substr(pos1,pos2-pos1).data()); + int portVal = 0; + if ((portnum > 0) && (portnum <= numPorts)) { + outPtr = &portVector[portnum]->outState; + foundIt = true; + } + } else if (nameInput.find("portin") != std::string::npos) { + int pos1 = nameInput.find("portin[")+7; + int pos2 = nameInput.find_first_of("]",pos1); + int portnum = atoi(nameInput.substr(pos1,pos2-pos1).data()); + int portVal = 0; + if ((portnum > 0) && (portnum <= numPorts)) { + outPtr = &portVector[portnum]->inState; + foundIt = true; + } + } + + if (!foundIt) { + std::vector<intVariable*>::size_type sz = globalVariables.size(); + for (unsigned i = 0; i < sz; i++) { + if (nameInput.compare(globalVariables[i]->tag) == 0) { + outPtr = &globalVariables[i]->value; + break; + } + } + } + + return outPtr; +} + +bool scriptStream::createIntVariable(string nameInput) { + if (findIntVariable(nameInput) == NULL) { + globalVariables.push_back(new intVariable(nameInput, 0)); + return true; + } else { + return false; + } +} + + +action* scriptStream::evaluateAssignmentForAction(string expression) { + + //action* tmpAction = new action(); //create a new action + action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS); + if (tmpAction == NULL) { + pcPtr->printf("Error: no action memory slots available.\r\n"); + return NULL; + } + std::size_t stringInd; + std::size_t stringInd2; + string afterEqual; + string beforeEqual; + //The expression might have up to three variables + int* tmpVar; + int* tmpVar2; + int* tmpVar3; + stringInd = expression.find_first_of("="); //location of = sign, if it exists + beforeEqual = expression.substr(0,stringInd); // the string after the = sign + afterEqual = expression.substr(stringInd+1,std::string::npos); // the string after the = sign + stringInd2 = afterEqual.find_first_of("+-"); //location of +/- sign (only one allowed) + tmpVar = findIntVariable(expression.substr(0,stringInd)); //returns pointer to the variable + + if (beforeEqual.find("portout[") != std::string::npos) { //set the output of a digital port + int pos1 = beforeEqual.find("portout[")+8; + int pos2 = beforeEqual.find_first_of("]",pos1); + int portnum = atoi(beforeEqual.substr(pos1,pos2-pos1).data()); + int* tmpVar = findIntVariable(beforeEqual.substr(pos1,pos2-pos1)); //returns pointer to the variable, if given + int portVal = 0; + if ((tmpVar != NULL)||((portnum > 0) && (portnum <= numPorts))) { + if (isNumber(afterEqual)) { //a simple numeric assign + portVal = atoi(afterEqual.data()); + if ((portVal == 0) || (portVal == 1)) { + //portMessage* tmpMessage = new portMessage(portVector[portnum],1,portVal); + portMessage* tmpMessage = findFirstUnUsed(portMessageBlock, NUMPORTMESSAGES); + if (tmpMessage == NULL) { + pcPtr->printf("Error: no memory slots available.\r\n"); + tmpAction->release(); + return NULL; + } else { + //tmpMessage->setMessage(portVector[portnum],1,portVal); + if (tmpVar == NULL) { //a constant port number was given + tmpMessage->setMessage(NULL,portnum,portVal); + } else { + tmpMessage->setMessage(tmpVar,0,portVal); + } + } + + + tmpAction->set(tmpMessage); + //pcPtr->printf("Action: digital port %d set to %d\r\n",portnum,portVal); + } else { + pcPtr->printf("Error: portouts can only be directly assigned a 1, 0 or 'flip'\r\n"); + //delete tmpAction; + tmpAction->release(); + return NULL; + } + } else if (afterEqual.compare("flip") == 0) { + //portMessage* tmpMessage = new portMessage(portVector[portnum],1,-1); + portMessage* tmpMessage = findFirstUnUsed(portMessageBlock, NUMPORTMESSAGES); + if (tmpMessage == NULL) { + pcPtr->printf("Error: no memory slots available.\r\n"); + tmpAction->release(); + return NULL; + } else { + //tmpMessage->setMessage(portVector[portnum],1,-1); + if (tmpVar == NULL) { //a constant port number was given + tmpMessage->setMessage(NULL,portnum,-1); + } else { + tmpMessage->setMessage(tmpVar,0,-1); + } + } + tmpAction->set(tmpMessage); + } else { + pcPtr->printf("Error: portouts can only be directly assigned a 1, 0, or 'flip'\r\n"); + //delete tmpAction; + tmpAction->release(); + return NULL; + } + } else { + pcPtr->printf("Port number not found (must be between 1 and %d, or an existing variable)\r\n", numPorts); + //delete tmpAction; + tmpAction->release(); + return NULL; + } + } else if (beforeEqual.find("portin") != std::string::npos) { + pcPtr->printf("Error: portins can not be set\r\n"); + //delete tmpAction; + tmpAction->release(); + return NULL; + } else if (tmpVar != NULL) { + intOperation* tmpOp; + intOperation* tmpOp2; + if (isNumber(afterEqual)) { //a simple numeric assign + //tmpOp = new intOperation(tmpVar, "=", atoi(afterEqual.data())); + tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS); + if (tmpOp == NULL) { + pcPtr->printf("Error: no memory slots available.\r\n"); + tmpAction->release(); + return NULL; + } else { + tmpOp->set(tmpVar, "=", atoi(afterEqual.data())); + } + tmpAction->set(tmpOp); + //pcPtr->printf("Action: set variable to constant numeric value\r\n"); + } else if ((stringInd2 == std::string::npos)&&(afterEqual.find("random") != std::string::npos)) { + + int highVal = getRandomParam(afterEqual); + + if (highVal > 0) { + //tmpOp = new intOperation(highVal, "=", tmpVar); //for random assignment, we reverse the input order (because of overloading uniqueness) + tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS); + if (tmpOp == NULL) { + pcPtr->printf("Error: no memory slots available.\r\n"); + tmpAction->release(); + return NULL; + } else { + tmpOp->set(highVal, "=", tmpVar); //for random assignment, we reverse the input order (because of overloading uniqueness) + } + tmpAction->set(tmpOp); + //pcPtr->printf("Action: set variable to random value up to %d\r\n", highVal); + } else { + //delete tmpAction; + tmpAction->release(); + return NULL; + } + + } else if (stringInd2 != std::string::npos) { //a +/- operation is there + string multiplier("+"); + int multiplierInt = 1; + if (afterEqual[stringInd2] == '-') { + multiplier = "-"; + multiplierInt = -1; + } + tmpVar2 = findIntVariable(afterEqual.substr(0,stringInd2)); //before the +/- sign + tmpVar3 = findIntVariable(afterEqual.substr(stringInd2+1,std::string::npos)); //after the +/- sign + + if ((tmpVar2 != NULL) && isNumber(afterEqual.substr(stringInd2+1,std::string::npos))) { //variable +/- number + if (tmpVar2 == tmpVar) { + multiplier.append("="); //final sign is += or -= + //tmpOp = new intOperation(tmpVar, multiplier.data(), atoi(afterEqual.substr(stringInd2+1,std::string::npos).data())); + tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS); + if (tmpOp == NULL) { + pcPtr->printf("Error: no memory slots available.\r\n"); + tmpAction->release(); + return NULL; + } else { + tmpOp->set(tmpVar, multiplier.data(), atoi(afterEqual.substr(stringInd2+1,std::string::npos).data())); + } + tmpAction->set(tmpOp); + pcPtr->printf("Action: change variable by constant amount\r\n"); + } else { + + tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS); + if (tmpOp2 == NULL) { + pcPtr->printf("Error: no memory slots available.\r\n"); + tmpAction->release(); + return NULL; + } else { + + tmpOp2->set(tmpVar2,multiplier.data(), atoi(afterEqual.substr(stringInd2+1,std::string::npos).data())); + //tmpOp->set(tmpVar, tmpOp2); + } + + tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS); + if (tmpOp == NULL) { + pcPtr->printf("Error: no memory slots available.\r\n"); + tmpOp2->release(); + tmpAction->release(); + return NULL; + } else { + tmpOp->set(tmpVar, tmpOp2); + } + + tmpAction->set(tmpOp); + //pcPtr->printf("Action: variable equals expression\r\n"); + } + + } else if ((tmpVar3 != NULL) && isNumber(afterEqual.substr(0,stringInd2))) { //number +/- variable + if (tmpVar3 == tmpVar) { + multiplier.append("="); //makes "+=" or "-=" + //tmpOp = new intOperation(tmpVar, multiplier.data(), atoi(afterEqual.substr(0,stringInd2).data())); + tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS); + if (tmpOp == NULL) { + pcPtr->printf("Error: no memory slots available.\r\n"); + tmpAction->release(); + return NULL; + } else { + tmpOp->set(tmpVar, multiplier.data(), atoi(afterEqual.substr(0,stringInd2).data())); + } + tmpAction->set(tmpOp); + //pcPtr->printf("Action: change variable by constant amount\r\n"); + } else { + + tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS); + if (tmpOp2 == NULL) { + pcPtr->printf("Error: no memory slots available.\r\n"); + tmpAction->release(); + return NULL; + } else { + tmpOp2->set(tmpVar3, multiplier.data(), atoi(afterEqual.substr(0, stringInd2).data())); + } + tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS); + + if (tmpOp == NULL) { + pcPtr->printf("Error: no memory slots available.\r\n"); + tmpOp2->release(); + tmpAction->release(); + return NULL; + } else { + tmpOp->set(tmpVar, tmpOp2); + } + tmpAction->set(tmpOp); + //pcPtr->printf("Action: variable equals expression\r\n"); + } + + } else if ((tmpVar2 != NULL) && (tmpVar3 != NULL)) { //variable +/- variable + + tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS); + if (tmpOp2 == NULL) { + pcPtr->printf("Error: no memory slots available.\r\n"); + tmpAction->release(); + return NULL; + } else { + tmpOp2->set(tmpVar2, multiplier.data(), tmpVar3); + } + tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS); + + if (tmpOp == NULL) { + pcPtr->printf("Error: no memory slots available.\r\n"); + tmpOp2->release(); + tmpAction->release(); + return NULL; + } else { + + tmpOp->set(tmpVar, tmpOp2); + } + tmpAction->set(tmpOp); + //pcPtr->printf("Action: set variable to operation involving two variables\r\n"); + //tmpVar->value = tmpVar2->value + (multiplier * tmpVar3->value); + } else if ( isNumber(afterEqual.substr(stringInd2+1,std::string::npos)) && isNumber(afterEqual.substr(0,stringInd2)) ) { //number +/- number + //tmpOp = new intOperation(tmpVar, "=", atoi(afterEqual.substr(0,stringInd2).data()) + (multiplierInt * atoi(afterEqual.substr(stringInd2+1,std::string::npos).data()))); + tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS); + if (tmpOp == NULL) { + pcPtr->printf("Error: no memory slots available.\r\n"); + tmpAction->release(); + return NULL; + } else { + tmpOp->set(tmpVar, "=", atoi(afterEqual.substr(0,stringInd2).data()) + (multiplierInt * atoi(afterEqual.substr(stringInd2+1,std::string::npos).data()))); + } + tmpAction->set(tmpOp); + //pcPtr->printf("Action: set variable to constant numeric value\r\n"); + + } else if ((afterEqual.substr(0,stringInd2).find("random") != std::string::npos) && isNumber(afterEqual.substr(stringInd2+1,std::string::npos))) { //random +/- number + int highVal = getRandomParam(afterEqual.substr(0,stringInd2)); + + if (highVal > 0) { + + + tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS); + if (tmpOp2 == NULL) { + pcPtr->printf("Error: no memory slots available.\r\n"); + tmpAction->release(); + return NULL; + } else { + tmpOp2->set(highVal, multiplier.data(), atoi(afterEqual.substr(stringInd2+1,std::string::npos).data())); + } + tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS); + + if (tmpOp == NULL) { + pcPtr->printf("Error: no memory slots available.\r\n"); + tmpOp2->release(); + tmpAction->release(); + return NULL; + } else { + tmpOp->set(tmpVar, tmpOp2); + } + tmpAction->set(tmpOp); + //pcPtr->printf("Action: set variable to random value plus number %d\r\n", highVal); + } else { + //delete tmpAction; + tmpAction->release(); + return NULL; + } + } else if ((afterEqual.substr(0,stringInd2).find("random") != std::string::npos) && (tmpVar3 != NULL)) { //random +/- variable + int highVal = getRandomParam(afterEqual.substr(0,stringInd2)); + + if (highVal > 0) { + + + tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS); + if (tmpOp2 == NULL) { + pcPtr->printf("Error: no memory slots available.\r\n"); + tmpAction->release(); + return NULL; + } else { + tmpOp2->set(highVal, multiplier.data(), tmpVar3); + } + tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS); + if (tmpOp == NULL) { + pcPtr->printf("Error: no memory slots available.\r\n"); + tmpOp2->release(); + tmpAction->release(); + return NULL; + } else { + tmpOp->set(tmpVar, tmpOp2); + } + tmpAction->set(tmpOp); + //pcPtr->printf("Action: set variable to random value plus number %d\r\n", highVal); + } else { + //delete tmpAction; + tmpAction->release(); + return NULL; + } + + + } else if ((afterEqual.substr(stringInd2+1,std::string::npos).find("random") != std::string::npos) && isNumber(afterEqual.substr(0,stringInd2))) { //random +/- number + int highVal = getRandomParam(afterEqual.substr(stringInd2+1,std::string::npos)); + + if (highVal > 0) { + + + tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS); + if (tmpOp2 == NULL) { + pcPtr->printf("Error: no memory slots available.\r\n"); + tmpAction->release(); + return NULL; + } else { + tmpOp2->set(highVal, multiplier.data(), atoi(afterEqual.substr(0, stringInd2).data())); + } + tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS); + if (tmpOp == NULL) { + pcPtr->printf("Error: no memory slots available.\r\n"); + tmpOp2->release(); + tmpAction->release(); + return NULL; + } else { + tmpOp->set(tmpVar, tmpOp2); + } + tmpAction->set(tmpOp); + //pcPtr->printf("Action: set variable to random value plus number %d\r\n", highVal); + } else { + //delete tmpAction; + tmpAction->release(); + return NULL; + } + } else if ((afterEqual.substr(stringInd2+1,std::string::npos).find("random") != std::string::npos) && (tmpVar2 != NULL)) { //random +/- number + int highVal = getRandomParam(afterEqual.substr(stringInd2+1,std::string::npos)); + + if (highVal > 0) { + + + tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS); + if (tmpOp2 == NULL) { + pcPtr->printf("Error: no memory slots available.\r\n"); + tmpAction->release(); + return NULL; + } else { + tmpOp2->set(highVal, multiplier.data(), tmpVar2); + } + tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS); + if (tmpOp == NULL) { + pcPtr->printf("Error: no memory slots available.\r\n"); + tmpOp2->release(); + tmpAction->release(); + return NULL; + } else { + tmpOp->set(tmpVar, tmpOp2); + } + tmpAction->set(tmpOp); + //pcPtr->printf("Action: set variable to random value plus number %d\r\n", highVal); + } else { + //delete tmpAction; + tmpAction->release(); + return NULL; + } + } else { + pcPtr->printf("Expression not understood: %s\r\n",afterEqual.data()); + //delete tmpAction; + tmpAction->release(); + return NULL; + } + + } else if (findIntVariable(afterEqual) != NULL) { //assign value of another variable + //tmpOp = new intOperation(tmpVar, "=", findIntVariable(afterEqual)); + tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS); + if (tmpOp == NULL) { + pcPtr->printf("Error: no memory slots available.\r\n"); + tmpAction->release(); + return NULL; + } else { + tmpOp->set(tmpVar, "=", findIntVariable(afterEqual)); + } + tmpAction->set(tmpOp); + //pcPtr->printf("Action: set variable to value of another\r\n"); + } else { + pcPtr->printf("Variable not found: %s\r\n",afterEqual.data()); + //delete tmpAction; + tmpAction->release(); + return NULL; + } + + } else { + pcPtr->printf("Variable not found\r\n"); + //delete tmpAction; + tmpAction->release(); + return NULL; + } + return tmpAction; +} + +bool scriptStream::isOutsideParenth(string expression,std::size_t foundItem) { + + int pDepth = 0; // How many nested parentheses + //pcPtr->printf("Check outside parentheses..."); + if (foundItem < expression.length()) { + for (int i = 0; i <= foundItem; i++) { + if (expression[i] == '(') { + pDepth++; + } else if (expression[i] == ')') { + pDepth--; + } + } + if (pDepth<=0) { + //pcPtr->printf("yes."); + return true; + } else { + //pcPtr->printf("no."); + return false; + } + } else { + return true; + } + +} + +std::size_t scriptStream::findFirstOrOutsideParenth(string expression) { + + std::size_t foundItem = expression.find("||"); + while (foundItem != std::string::npos) { + if (isOutsideParenth(expression,foundItem)) { + break; + } + foundItem = expression.find("||",foundItem+1); + } + return foundItem; +} + +std::size_t scriptStream::findFirstAndOutsideParenth(string expression) { + + std::size_t foundItem = expression.find("&&"); + while (foundItem != std::string::npos) { + if (isOutsideParenth(expression,foundItem)){ + break; + } + foundItem = expression.find("&&",foundItem+1); + } + return foundItem; +} + +condition* scriptStream::parseConditions(string expression) { + //This function is used to parse a condition string + //such as (x < y && x != z) || (y == 2) + //This function first identifies the root node of the logic tree + //based on operator precedence ( () > && > || ), and then recursively calls itself + //to find the nodes of the branches. The basic building blocks of + //the final condition object are arithmatic comparitors (a > b) and + //other condition objects. + + + //pcPtr->printf("Parsing condition: %s\r\n", expression.data()); + condition* newCondition = NULL; + bool singleCondition = false; //no compound conditions + string afterComparator; + string beforeComparator; + + std::size_t found; + + //To make a parse tree, we start by looking for operators with the lowest precendence + //so we look for OR conditions first + char currentOperator = OR_CONDITION; + //pcPtr->printf("Looking for OR condition..."); + found = findFirstOrOutsideParenth(expression); + if (found==std::string::npos) { //no or conditions outside parentheses found, so we look for AND conditions + currentOperator = AND_CONDITION; + //pcPtr->printf("Looking for AND condition..."); + found = findFirstAndOutsideParenth(expression); + } + if (found==std::string::npos) { //no or/and conditions outside parentheses found + //if the expression is encapsulated in parentheses, remove the parentheses + bool removedParenth = false; + if ((expression[0] == '(') && (expression[expression.length()-1] == ')')) { + //pcPtr->printf("Remove parentheses"); + expression = expression.substr(1,expression.length()-2); + removedParenth = true; + } + if (removedParenth) { //we removed parentheses, so try again + return parseConditions(expression); + } else { + singleCondition = true; //we assume that the condition is non-compound, i.e., a>b + } + } + + if (singleCondition) { //no compound conditions found + //pcPtr->printf("Single condition"); + std::size_t equalStringInd; + std::size_t greaterOrEqualStringInd; + std::size_t lessThanOrEqualStringInd; + std::size_t notEqualStringInd; + std::size_t greaterThanStringInd; + std::size_t lessThanStringInd; + std::size_t generalCompareStringInd; + + + string tmpCondition = expression; + string compareString; + //The expression might have up to three variables + int* tmpVar; + int* tmpVar2; + int* tmpVar3; + + int offset = 0; + equalStringInd = tmpCondition.find("=="); //location of comparator + greaterOrEqualStringInd = tmpCondition.find(">="); //location of comparator + lessThanOrEqualStringInd = tmpCondition.find("<="); //location of comparator + notEqualStringInd = tmpCondition.find("!="); //location of comparator + greaterThanStringInd = tmpCondition.find_first_of(">"); //location of comparator + lessThanStringInd = tmpCondition.find_first_of("<"); //location of comparator + + if ((equalStringInd != std::string::npos) && (greaterOrEqualStringInd == std::string::npos) && + (lessThanOrEqualStringInd == std::string::npos) && (notEqualStringInd == std::string::npos)){ + + generalCompareStringInd = equalStringInd; + compareString = "=="; + } else if ((equalStringInd == std::string::npos) && (greaterOrEqualStringInd != std::string::npos) && + (lessThanOrEqualStringInd == std::string::npos) && (notEqualStringInd == std::string::npos)){ + + generalCompareStringInd = greaterOrEqualStringInd; + compareString = ">="; + } else if ((equalStringInd == std::string::npos) && (greaterOrEqualStringInd == std::string::npos) && + (lessThanOrEqualStringInd != std::string::npos) && (notEqualStringInd == std::string::npos)){ + + generalCompareStringInd = lessThanOrEqualStringInd; + compareString = "<="; + } else if ((equalStringInd == std::string::npos) && (greaterOrEqualStringInd == std::string::npos) && + (lessThanOrEqualStringInd == std::string::npos) && (notEqualStringInd != std::string::npos)){ + + generalCompareStringInd = notEqualStringInd; + compareString = "!="; + } else if ((equalStringInd == std::string::npos) && (greaterOrEqualStringInd == std::string::npos) && + (lessThanOrEqualStringInd == std::string::npos) && (notEqualStringInd == std::string::npos) && + (greaterThanStringInd != std::string::npos) && (lessThanStringInd == std::string::npos)){ + + generalCompareStringInd = greaterThanStringInd; + compareString = ">"; + offset = 1; + } else if ((equalStringInd == std::string::npos) && (greaterOrEqualStringInd == std::string::npos) && + (lessThanOrEqualStringInd == std::string::npos) && (notEqualStringInd == std::string::npos) && + (greaterThanStringInd == std::string::npos) && (lessThanStringInd != std::string::npos)){ + + generalCompareStringInd = lessThanStringInd; + compareString = "<"; + offset = 1; + + }else { + pcPtr->printf("Condition not understood: %s\r\n", expression.data()); + return 0; + } + + intCompare* newCompare = findFirstUnUsed(intCompareBlock, NUMINTCOMPARE); + if (newCompare == NULL) { + pcPtr->printf("Error: No memory slots available."); + return NULL; + } + newCondition = findFirstUnUsed(conditionBlock, NUMCONDITIONS); + if (newCondition == NULL) { + pcPtr->printf("Error: No memory slots available."); + return NULL; + } + afterComparator = tmpCondition.substr(generalCompareStringInd+2-offset,std::string::npos); + + beforeComparator = tmpCondition.substr(0,generalCompareStringInd); + tmpVar = findIntVariable(beforeComparator); //returns pointer to the variable + if (tmpVar != NULL) { //before the comparator is a single variable + tmpVar2 = findIntVariable(afterComparator); //returns pointer to the variable + if (tmpVar2 != NULL) { //we are comapring a single variable to another + //intCompare* newCompare = new intCompare(tmpVar,compareString.data(),tmpVar2); + //currentEvent->addCondition(new condition(newCompare)); + newCompare->set(tmpVar,compareString.data(),tmpVar2); + newCondition->set(newCompare); + + //pcPtr->printf("Var vs. Var condition added: %s\r\n", tmpCondition.data()); + } else if (isNumber(afterComparator)) { + //intCompare* newCompare = new intCompare(tmpVar,compareString.data(),atoi(afterComparator.data())); + //currentEvent->addCondition(new condition(newCompare)); + newCompare->set(tmpVar,compareString.data(),atoi(afterComparator.data())); + newCondition->set(newCompare); + + //pcPtr->printf("Var vs. Int condition added: %s\r\n", tmpCondition.data()); + } //more here + + } else { + pcPtr->printf("Condition not understood: %s\r\n", expression.data()); + + return NULL; + } + + } else { //this is a compound condition (with either && or ||) + //pcPtr->printf("Compound condition"); + afterComparator = expression.substr(found+2,std::string::npos); + beforeComparator = expression.substr(0,found); + newCondition = findFirstUnUsed(conditionBlock, NUMCONDITIONS); + if (newCondition == NULL) { + pcPtr->printf("Error: No memory slots available."); + return NULL; + } else { + newCondition->isUsed = true; //reserve the condition slot; + } + //recursively call this function to parse the sub conditions + condition* cond1 = parseConditions(beforeComparator); + if (cond1 == NULL) { + newCondition->release(); + return NULL; + } + condition* cond2 = parseConditions(afterComparator); + if (cond2 == NULL) { + newCondition->release(); + cond1->release(); + return NULL; + } + newCondition->set(cond1,currentOperator, cond2); + + } + + return newCondition; //all went well, so return the newly made condition + +} + +bool scriptStream::evaluateConditions(string expression, event* currentEvent) { + //calls the function to parse the condition string. The condition pointer is then + //attached to the event + + condition* newCondition = NULL; + newCondition = parseConditions(expression); + if (newCondition == NULL) { + return false; + } else { + currentEvent->addCondition(newCondition); + return true; + } +} + +int scriptStream::getRandomParam(string expression) { + + int pos1 = expression.find("random(")+7; + int pos2 = expression.find_first_of(")",pos1); + int highVal = atoi(expression.substr(pos1,pos2-pos1).data()); + + if ((highVal > 0)) { + return highVal; + } else { + pcPtr->printf("Error: random parameter must be 1 or more\r\n"); + return 0; + } + } + + + outputStream::outputStream(int bufferSizeIn): + readHead(0), + writeHead(0), + totalWriteHead(0), + totalReadHead(0), + bufferSize(bufferSizeIn), + unsentData(false) { + + outputBuffer = new char[bufferSize]; + + } + + outputStream::~outputStream() { + delete[] outputBuffer; + } + + //adds text to the buffer + void outputStream::send(string outputString) { + int strLen = outputString.size(); + + int total = 0; + int chunk = 0; + if (!(totalWriteHead+strLen > (totalReadHead + bufferSize))) { + while (strLen - total > 0) { + chunk = min((bufferSize - writeHead), strLen - total); + outputString.copy(outputBuffer + writeHead, chunk, total); + writeHead = (writeHead + chunk) % bufferSize; + totalWriteHead += chunk; + total += chunk; + } + if (total > 0) { + unsentData = true; + } + } + } + + //the main loop gets one character per loop and write it to the serial port + char outputStream::getNextChar() { + + + if (totalReadHead < totalWriteHead) { + tmpOut = *(outputBuffer+readHead); + readHead = (readHead+1) % bufferSize; + totalReadHead++; + if (totalReadHead >= totalWriteHead) { + unsentData = false; + } + } + return tmpOut; + + } + \ No newline at end of file
diff -r 000000000000 -r 9d97f34c6f46 behave.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/behave.h Mon May 18 01:18:45 2015 +0000 @@ -0,0 +1,462 @@ +#include "mbed.h" +#include <stdint.h> +#include <string.h> +#include <string> +#include <vector> +#include <list> +#include <deque> +#include <queue> +#include "soundControl.h" + + +#define NUMEVENTS 50 +#define NUMCONDITIONS 150 +#define NUMINTCOMPARE 150 +#define NUMACTIONS 150 +#define NUMPORTMESSAGES 150 +#define NUMINTOPERATIONS 150 +#define NUMDISPLAYACTIONS 30 + +#define ARITHMATIC_CONDITION 0 +#define OR_CONDITION 1 +#define AND_CONDITION 2 + +#define NUMPORTS 10 + +extern "C" void mbed_reset();//MAX and ANDY +class event; //we foreward declare this because of class interdependencies + +//used in the digital port class to organize digital change events +struct changeEvent { + uint32_t timeStamp; + bool triggered; +}; + +//The digitalPort object directly controls and keeps data about the port. Each port has +//one digital out and one digital in. +class digitalPort { +public: + digitalPort(DigitalOut* DOP, DigitalIn* DIP); + digitalPort(DigitalOut* DOP); + void setDigitalOut(int outVal); + //int getDigitalOut(); + int getDigitalIn(); + int getLastChangeState(); + uint32_t getTimeSinceLastChange(); + uint32_t lastChangeTime; + uint32_t lastOutChangeTime; + + void setTriggerUpEvent(event* eventInput); //attahces a routine to an upward change + void setTriggerDownEvent(event* eventInput); //attahces a routine to a downward change + void addStateChange(int newState, uint32_t timeStamp); + + bool update(); //called from the main loop + + int inState; + int outState; + + bool outStateChanged; + + event* triggerUpEventPtr; + event* triggerDownEventPtr; + +private: + + DigitalOut* outPin; + DigitalIn* inPin; + int lastInState; + uint32_t lastChangeInterval; + + changeEvent lastUpEvent; + changeEvent lastDownEvent; +}; + + +//an intVariable contains an integer value and the name of that variable within the script +class intVariable { + +public: + intVariable(); + intVariable(string tagInput, int initialValue); + void set(string tagInput, int initialValue); + int value; + string tag; + bool isUsed; + +}; + + +//ACTION SECTION-- an 'action' is a command in the script. It can be a single command, +//or a block containing a set of actions +//------------------------------------------------------------------------------------ + +//display actions are used to output text messages via the serial port. The user can display +//either a static text string or the value of a single variable. +class displayAction { + +public: + displayAction(); + displayAction(int* variable, string varNameInput, Serial* pcPtrInput); + displayAction(string text, Serial* pcPtrInput); + void set(int* variable, string varNameInput, Serial* pcPtrInput); + void set(string text, Serial* pcPtrInput); + bool isUsed; + void execute(); + void release(); + +private: + int* dVariable; + string dText; + Serial* pcPtr; +}; + +//intOpertaion is an action that does addition or subtraction of integers and returns/stores the result +//these operation are very limited so far (only + or - allowed, and only one operation per object, +//for example a = b + b works but a = b + c + d does not. The output value can also be set to a random number. +class intOperation { + +public: + intOperation(); + intOperation(int randParam, const char* cmpString, int cmpValInput); + intOperation(int randParam, const char* cmpString, int* cmpIntVarInput); + intOperation(int* intVarInput, const char* cmpString, int cmpValInput); + intOperation(int* intVarInput, const char* cmpString, int* cmpIntVarInput); + intOperation(int* intVarInput, intOperation* operationInput); + + ~intOperation(); + + void set(int randParam, const char* cmpString, int cmpValInput); + void set(int randParam, const char* cmpString, int* cmpIntVarInput); + void set(int* intVarInput, const char* cmpString, int cmpValInput); + void set(int* intVarInput, const char* cmpString, int* cmpIntVarInput); + void set(int* intVarInput, intOperation* operationInput); + void release(); + bool isUsed; + int execute(); + +private: + int randHigh; + int* cmpVal; + int* intVal; + intOperation* opPtr; + bool cmpValGlobal; + int (intOperation::*executePtr)(); + int addAndStore(); + int subtractAndStore(); + int add(); + int subtract(); + int equals(); + +}; + +//portMessage is an action to change a digital port. So far, You can only change the digital out (0 or 1) +class portMessage { +public: + + portMessage(); + //portMessage(digitalPort* portIn, int whichToSet, int value); //whichToSet: 1 DigitalOut; 2 State + //void setMessage(digitalPort* portIn, int whichToSet, int value); //whichToSet: 1 DigitalOut; 2 State + portMessage(int* portIn, int whichToSet, int value); //whichToSet: + void setMessage(int* portIn, int whichToSet, int value); //whichToSet: + + void execute(); + void release(); + bool isUsed; + +private: + int whichToSet; //hard coded port number + int* port; //alternative variable port number + int value; + //digitalPort* port; + +}; + +//holder class for all possible actions. This include general system commands. +class action { +public: + + action(); + ~action(); + action(intOperation* opInput); + action(portMessage* messageInput); + action(event* eventInput); + //action(event* eventInput, uint32_t delay); + action(displayAction* displayInput); + action(soundControl* soundInput); + action(int8_t sysCommandInput); //for general system commands + + void set(intOperation* opInput); + void set(portMessage* messageInput); + void set(event* eventInput); + //void set(event* eventInput, uint32_t delay); + + void set(displayAction* displayInput); + void set(soundControl* soundInput); + void set(int8_t sysCommandInput); + void execute(); + void execute(uint32_t blockExecTime); + void release(); + bool isUsed; + +private: + intOperation* op; + portMessage* message; + event* eventToCreate; + displayAction* displayActionPtr; + soundControl* sound; + //uint32_t eventDelay; + int8_t sysCommand; + char actionType; + +}; +//----------------------------------------------------- + +//CONDITION SECTION-- a 'condition' is used in the beginning of a block (if-else blocks or while blocks) +//If the condition is true, the block is exectuted during a callback +//------------------------------------------------------------------------------------ + + +//intCompare is a condition class that compares the state value of a port or +//an integer variable to another integer variable or operation output +class intCompare { + +public: + intCompare(); + intCompare(digitalPort* portInput, const char* cmpString, int cmpValInput, int whichToUse); + intCompare(digitalPort* portInput, const char* cmpString, int* cmpIntVarInput, int whichToUse); + intCompare(int* intVarInput, const char* cmpString, int cmpValInput); + intCompare(int* intVarInput, const char* cmpString, int* cmpIntVarInput); + intCompare(int* intVarInput, const char* cmpString, intOperation* cmpIntOpInput); + intCompare(digitalPort* portInput, const char* cmpString, intOperation* cmpIntOpInput, int whichToUse); + + void set(digitalPort* portInput, const char* cmpString, int cmpValInput, int whichToUse); + void set(digitalPort* portInput, const char* cmpString, int* cmpIntVarInput, int whichToUse); + void set(int* intVarInput, const char* cmpString, int cmpValInput); + void set(int* intVarInput, const char* cmpString, int* cmpIntVarInput); + void set(int* intVarInput, const char* cmpString, intOperation* cmpIntOpInput); + void set(digitalPort* portInput, const char* cmpString, intOperation* cmpIntOpInput, int whichToUse); + + void release(); + + ~intCompare(); + bool isTrue(); + bool isUsed; + +private: + digitalPort* port; + int* portValPtr; + int* cmpVal; + int* intVal; + intOperation* intOp; + void setPointer(const char* cmpString); + void setPointer_operation(const char* cmpString); + bool (intCompare::*isTruePtr)(); + bool cmpValGlobal; + bool greaterThan(); + bool greaterOrEqual(); + bool lessThan(); + bool lessOrEqual(); + bool equal(); + bool notEqual(); + bool greaterThan_op(); + bool greaterOrEqual_op(); + bool lessThan_op(); + bool lessOrEqual_op(); + bool equal_op(); + bool notEqual_op(); +}; + + +//holder class for all possible conditions (so far only intCompare) +class condition { +public: + + condition(); + condition(intCompare* compareInput); + condition(condition* condition1, char condType, condition* condition2); + ~condition(); + void set(intCompare* compareInput); + void set(condition* condition1, char condType, condition* condition2); + bool isTrue(); + bool isUsed; + void release(); //called when the event is no longer being used; +private: + + //char conditionType; //1 for intCompare + intCompare* intCmp; + condition* conditionPtrs[2]; + char conditionType; + + +}; +//-------------------------------------------- + + +//queueItem connects a pre-defined event with an exectution time. +//They are placed in the eventQueue +struct queueItem { + uint32_t timeToExecute; + event* eventPtr; +}; + + +//Organizes events in a temporal queue. check() is called from the main loop. +//If the execution time of the event has passed, then the event is exectuted. +class eventQueue { +public: + eventQueue(digitalPort** portVectorInput, uint32_t* timeKeeperSlaveInput); + void addEventToQueue(event* eventInput, uint32_t delay); + void eraseQueue(); //clear all future events + void check(void); + +private: + std::vector<queueItem> events; + digitalPort** portVector; + uint32_t* timeKeeperPtr; + int queueSize; + +}; + +//An 'event' is a block of 'actions' that can be gated with a boolean 'condition' set. All +//conditions in the set must be true for the block of actions to be executed. Right now, +//there is no OR logic (||), only AND (&&). +//The entire event is placed on the event queue to be executed at a given delay. +//At that future time, the condition is checked and if true, the block of actions +//is exectuted. Note: an 'action' can be another event (or even the parent event), allowing +//nested 'if' and 'while' statements. +class event { +public: + + event(); + event(eventQueue* queueInput); + ~event(); + void setTimeLag(uint32_t timeLagInput); //the event will be exectuted at this time from now + void setTimeLag(int* timeLagInput); //the event will be exectuted at this time from now + void setWhileLoopPeriod(uint32_t period); + void setWhileLoopPeriod(int* period); + void addCondition(condition* conditionInput); //contains a set of conditions to check and a truth table + bool isConditionTrue(void); //checks if the condition is true + void addAction(action* actionInput); //called during script parsing, when the block is being defined + void addToQueue(void); //places the event on the event queue with default time lag. When the time + //lag has expired, the the block is executed + void addToQueue(uint32_t delay); + void execute(void); //Execute without checking the condition. Called only from the event queue + void setNextElseEvent(event* eventInput); //allows for else event block + uint32_t timeLag; //default time from now when the event will be executed (this is ignored once placed in event queue) + int* timeLagVar; //exectution time lab defined by a variable + eventQueue* queuePtr; + void release(); //called when the event is no longer being used; + + char blockType; //0 callback + //1 if ... do block (with conditions) + //2 do block (no conditions) + //3 else if ... do block + //4 else do (no conditions) + //5 while ... do every ... block + //6 else while ... do every ... block + //7 then if ... do block + //8 then do (no conditions) + + uint32_t whileLoopPeriod; //if non-zero, the block is a while loop (executed at regular intervals) + int* whileLoopPeriodVar; + event* nextElseEventPtr; + bool isUsed; + bool timeLagIsConstant; + bool whileLoopPeriodIsConstant; + bool hasWhileLoop; + +private: + int numConditions; + int numActions; + condition* conditionToCheck; + action* actionArray[20]; + + //if statement (can be left empty, which is interpreted as 'true') + //std::vector<condition*> conditionArray; + //std::deque<action*> actionArray; + +}; + +//each functionItem help a poiter to an action, and the name of the function +class functionItem { +public: + functionItem(action* actionInput, string tagInput); + ~functionItem(); + string tag; + action* actionPtr; +}; + +//Parser for the incoming text. The parser is called when a line terminates with a semicolon (;). +//Only the final line in a callback block should have a semicolon. +class scriptStream { +public: + scriptStream(Serial* serialInput, digitalPort** portVectorInput, int numPortsInput, eventQueue* queueInput); + void parseBlock(); + void addLineToCurrentBlock(char* lineInput); // if the line did not end with a semicolon, add it to the current block + int* findIntVariable(string nameInput); //used to retrieve the pointer to the designated variable if it exists + bool createIntVariable(string nameInput); // creates a new interger variable + action* evaluateAssignmentForAction(string expression); //parses a numerical assignment or operation (a = b - c) + bool evaluateConditions(string expression, event* currentEvent); //parses a condition statement (a == b && c > d) + condition* parseConditions(string expression); //parses a condition statement (a == b && c > d) + std::size_t findFirstOrOutsideParenth(string expression); + std::size_t findFirstAndOutsideParenth(string expression); + bool isOutsideParenth(string expression,std::size_t foundItem); + + int getRandomParam(string expression); + +private: + + int currentTriggerPort; + int currentTriggerDir; + int currentPort; + int currentFunction; + + string tmpLine; + vector<string> tokens; + + bool lineError; + int blockDepth; + bool ifBlockInit; + bool whileBlockInit; + bool elseFlag; + bool thenFlag; + int currentDelay; + event* tmpEvent; + string tmpString; + + vector<intVariable*> globalVariables; + vector<event*> tmpEventPtrArray; + vector<functionItem*> functionArray; //any blocks declared outsite callback blocks are stored here + list<string> currentBlock; + digitalPort** portVector; + + + int numPorts; + Serial* pcPtr; + eventQueue* queuePtr; + +}; + + +//Used to buffer output text. Used mainly for 'display' commands within the script, +//and alloed the reset of the block to execute quickly instead. The text is then streamed out +//slowly via serial (one character per main loop execution). outputStream is a simple circular +//buffer that cannot be resized after initiation. +class outputStream { + +public: + outputStream(int bufferSizeIn); + ~outputStream(); + void send(string outputString); + char getNextChar(); + bool unsentData; + +private: + int readHead; + int writeHead; + int totalWriteHead; + int totalReadHead; + int bufferSize; + char tmpOut; + char* outputBuffer; +}; \ No newline at end of file
diff -r 000000000000 -r 9d97f34c6f46 main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Mon May 18 01:18:45 2015 +0000 @@ -0,0 +1,513 @@ +#include "mbed.h" +#include <stdint.h> +#include "behave.h" +#include <string.h> +#include <sstream> +#include "SMARTWAV.h" +#include "USBSerial.h" + + +uint32_t timeKeeper; //the main clock (updated every ms) +bool resetTimer = false; //if true, the clock is reset +bool clockSlave = false; //slave mode +bool changeToSlave = false; +bool changeToStandAlone = false; + +//static char buf1[0x2000] __attribute__((section("AHBSRAM0"))); +__attribute((section("AHBSRAM0"),aligned)) outputStream textDisplay(512); +__attribute((section("AHBSRAM0"),aligned)) char buffer[128]; + + +__attribute((section("AHBSRAM1"),aligned)) event eventBlock[NUMEVENTS]; + +__attribute((section("AHBSRAM1"),aligned)) condition conditionBlock[NUMCONDITIONS]; + +__attribute((section("AHBSRAM1"),aligned)) intCompare intCompareBlock[NUMINTCOMPARE]; + +__attribute((section("AHBSRAM0"),aligned)) action actionBlock[NUMACTIONS]; + +__attribute((section("AHBSRAM0"),aligned)) portMessage portMessageBlock[NUMPORTMESSAGES]; + +//__attribute((section("AHBSRAM1"),aligned)) intVariable intVariableBlock[10]; + +__attribute((section("AHBSRAM0"),aligned)) intOperation intOperationBlock[NUMINTOPERATIONS]; + +__attribute((section("AHBSRAM0"),aligned)) displayAction displayActionBlock[NUMDISPLAYACTIONS]; + + + +Ticker clockBroadCast; //timer used when sending out timestamps on a GPIO +uint32_t currentBroadcastTime; +int currentBroadcastBit = 0; +bool broadcastHigh = false; + +int currentDIOstate[2] = {0,0}; //the first number is a bit-wise representaion of the digital inputs, the 2nd is for the outputs +bool digitalInChanged = false; +bool digitalOutChanged = false; +bool broadCastStateChanges = true; +bool textStreaming = true; +uint32_t changeTime; + +LocalFileSystem local("local"); + +digitalPort* portVector[NUMPORTS+1]; //create the digital ports + +float brightness = 0.0; + +//Define the digial ports + +//Pins for clock syncing +//InterruptIn clockResetInt(p24); +DigitalOut clockOutSync(p19); +DigitalOut clockOutSignal(p29); +InterruptIn clockExternalIncrement(p30); + + +//Pins for digital ports. Each port has 1 out and 1 in +//DigitalOut out1(LED1); //route to LED for debugging +//1A,1B +DigitalOut out1(p5); +DigitalIn in1(p6); +InterruptIn int1(p6); +__attribute((section("AHBSRAM0"),aligned)) digitalPort port1(&out1, &in1); +//1C,1D +DigitalOut out2(p7); +DigitalIn in2(p8); +InterruptIn int2(p8); +__attribute((section("AHBSRAM0"),aligned)) digitalPort port2(&out2, &in2); +//2A,2B +DigitalOut out3(p17); +DigitalIn in3(p18); +InterruptIn int3(p18); +__attribute((section("AHBSRAM0"),aligned)) digitalPort port3(&out3, &in3); +//2C,2D +DigitalOut out4(p11); +DigitalIn in4(p12); +InterruptIn int4(p12); +__attribute((section("AHBSRAM0"),aligned)) digitalPort port4(&out4, &in4); +//3A,3B +DigitalOut out5(p21); +DigitalIn in5(p22); +InterruptIn int5(p22); +__attribute((section("AHBSRAM0"),aligned)) digitalPort port5(&out5, &in5); +//3C,3D +DigitalOut out6(p15); +DigitalIn in6(p16); +InterruptIn int6(p16); +__attribute((section("AHBSRAM0"),aligned)) digitalPort port6(&out6, &in6); +//4A,4B +DigitalOut out7(p9); +DigitalIn in7(p10); +InterruptIn int7(p10); +__attribute((section("AHBSRAM0"),aligned)) digitalPort port7(&out7, &in7); +//5A,5B +DigitalOut out8(p13); +DigitalIn in8(p14); +InterruptIn int8(p14); +__attribute((section("AHBSRAM0"),aligned)) digitalPort port8(&out8, &in8); +//6A,6B +DigitalOut out9(p23); +DigitalIn in9(p24); +InterruptIn int9(p24); +__attribute((section("AHBSRAM0"),aligned)) digitalPort port9(&out9, &in9); +//Pump1 +DigitalOut out10(p25); +__attribute((section("AHBSRAM0"),aligned)) digitalPort port10(&out10); +//Pump2 +DigitalOut out11(p26); +__attribute((section("AHBSRAM0"),aligned)) digitalPort port11(&out11); + + + +//Serial communication +Serial pc(USBTX, USBRX); // tx, rx +//USBSerial pc; + + +//Main event queue +eventQueue mainQueue(portVector, &timeKeeper); + +//The script parser +scriptStream parser(&pc, portVector, NUMPORTS, &mainQueue); + +//The sound output uses a SmartWav device and their simple serial library +SMARTWAV sWav(p28,p27,p20); //(TX,RX,Reset); +//Serial device(p9,p10); +//Erases the input buffer for serial input +void eraseBuffer(char* buffer,int numToErase) { + for (int i = 0; i < numToErase; i++) { + buffer[i] = NULL; + } +} + + +//Called by clockBroadCast timer to output a 32-bit timestamp. When the timestmap has been +//sent, the function is detached from the timer. +void broadcastNextBit() { + + if (currentBroadcastBit < 32) { + broadcastHigh = !broadcastHigh; //flip the sync signal + if (broadcastHigh) { + clockOutSync = 1; + clockOutSignal = (currentBroadcastTime & ( 1 << currentBroadcastBit)) >> currentBroadcastBit; + + } else { + clockOutSync = 0; + clockOutSignal = 0; + currentBroadcastBit++; + } + } +} + + +//intiatiation of timer2 (specific to the LPC17xx chip). This is used in +//standalone mode to increment the clock every ms. +//we use lower-lever code here to get better control over the timer if we reset it +void timer0_init(void) +{ + //LPC_SC->PCLKSEL1 &= (3 << 12); //mask + //LPC_SC->PCLKSEL1 |= (1 << 12); //sets it to 1*SystemCoreClock - table 42 (page 57 in user manual) + + //LPC_SC->PCLKSEL0 &= (3 << 3); //mask + //LPC_SC->PCLKSEL0 |= (1 << 3); //sets it to 1*SystemCoreClock - table 42 (page 57 in user manual) + LPC_SC->PCONP |=1<1; //timer0 power on + LPC_TIM0->MR0 = 23980; //1 msec + //LPC_TIM0->PR = (SystemCoreClock / 1000000); //microsecond steps + //LPC_TIM0->MR0 = 1000; //100 msec + //LPC_TIM0->MR0 = (SystemCoreClock / 1000000); //microsecond steps + LPC_TIM0->MCR = 3; //interrupt and reset control + //3 = Interrupt & reset timer0 on match + //1 = Interrupt only, no reset of timer0 + NVIC_EnableIRQ(TIMER0_IRQn); //enable timer0 interrupt + LPC_TIM0->TCR = 1; //enable Timer0 + + + /* + LPC_SC->PCONP |= (0x1<<22); // turn on power for timer 2 + LPC_TIM2->TCR = 0x02; // reset timer + LPC_TIM2->PR = (SystemCoreClock / 1000000); //microsecond steps + LPC_TIM2->MR0 = 1000; // 1000 microsecond interval interrupts + LPC_TIM2->IR = 0x3f; // reset all interrrupts + LPC_TIM2->MCR = 0x03; // reset timer on match and generate interrupt (MR0) + LPC_TIM2->TCR = 0x01; // start timer + + NVIC_EnableIRQ(TIMER2_IRQn); // Enable the interrupt + */ + //pc.printf("Done timer_init\n\r"); +} + +//This is the callback for timer2 +extern "C" void TIMER0_IRQHandler (void) { + + if((LPC_TIM0->IR & 0x01) == 0x01) { // if MR0 interrupt, proceed + + LPC_TIM0->IR |= 1 << 0; // Clear MR0 interrupt flag + timeKeeper++; + + if (resetTimer) { + timeKeeper = 0; + resetTimer = false; + } + + if (currentBroadcastBit > 31) { + clockBroadCast.detach(); + currentBroadcastBit = 0; + } + + //Every second, we broadcast out the current time + if ((timeKeeper % 1000) == 0) { + currentBroadcastTime = timeKeeper; + clockOutSync = 1; + + currentBroadcastBit = 0; + + clockOutSignal = (currentBroadcastTime & ( 1 << currentBroadcastBit)) >> currentBroadcastBit; + broadcastHigh = true; + clockBroadCast.attach_us(&broadcastNextBit, 1000); + } + } +} + + +//In slave mode, the clock is updated with an external trigger every ms. No need for +//100us resolution. +void callback_clockExternalIncrement(void) { + + timeKeeper++; + + if (resetTimer) { + timeKeeper = 0; + resetTimer = false; + } + + if (currentBroadcastBit > 31) { + clockBroadCast.detach(); + currentBroadcastBit = 0; + } + + //Every second, we broadcast out the current time + if ((timeKeeper % 1000) == 0) { + currentBroadcastTime = timeKeeper; + clockOutSync = 1; + + currentBroadcastBit = 0; + + clockOutSignal = (currentBroadcastTime & ( 1 << currentBroadcastBit)) >> currentBroadcastBit; + broadcastHigh = true; + clockBroadCast.attach_us(&broadcastNextBit, 1000); + } +} + +//Every digital port's in pin has a hardware interrupt. We use a callback stub for each port +//that routes the int_callback. +void int_callback(int portNum, int direction) { + portVector[portNum]->addStateChange(direction, timeKeeper); +} + +//Callback stubs +void callback_port1_rise(void) { int_callback(1, 1); } +void callback_port1_fall(void) { int_callback(1, 0); } +void callback_port2_rise(void) { int_callback(2, 1); } +void callback_port2_fall(void) { int_callback(2, 0); } +void callback_port3_rise(void) { int_callback(3, 1); } +void callback_port3_fall(void) { int_callback(3, 0); } +void callback_port4_rise(void) { int_callback(4, 1); } +void callback_port4_fall(void) { int_callback(4, 0); } +void callback_port5_rise(void) { int_callback(5, 1); } +void callback_port5_fall(void) { int_callback(5, 0); } +void callback_port6_rise(void) { int_callback(6, 1); } +void callback_port6_fall(void) { int_callback(6, 0); } +void callback_port7_rise(void) { int_callback(7, 1); } +void callback_port7_fall(void) { int_callback(7, 0); } +void callback_port8_rise(void) { int_callback(8, 1); } +void callback_port8_fall(void) { int_callback(8, 0); } +void callback_port9_rise(void) { int_callback(9, 1); } +void callback_port9_fall(void) { int_callback(9, 0); } + + +//This function is attached to an interrupt pin for external clock reset +void callback_clockReset(void) { + if (timeKeeper > 100) { + LPC_TIM2->TCR = 0x02; // reset timer + timeKeeper = 0; + pc.printf("%d Clock reset\r\n", timeKeeper); + } +} + + +int main() { + timeKeeper = 0; //set main clock to 0; + sWav.reset(); + pc.baud(115200); +// device.baud(4800); + //pc.baud(9600); + + for (int i = 0; i <NUMPORTS+1; i++) { + portVector[i] = NULL; + } + //We keep portVector 1-based to eliminate confusion + portVector[1] = &port1; + portVector[2] = &port2; + portVector[3] = &port3; + portVector[4] = &port4; + portVector[5] = &port5; + portVector[6] = &port6; + portVector[7] = &port7; + portVector[8] = &port8; + portVector[9] = &port9; + portVector[10] = &port10; + portVector[11] = &port11; + + //Callback to update the main clock + //timeTick1.attach_us(&incrementTime, 100); + + timer0_init(); + + + //Set up callbacks for the port interrupts + int1.rise(&callback_port1_rise); + int1.fall(&callback_port1_fall); + int2.rise(&callback_port2_rise); + int2.fall(&callback_port2_fall); + int3.rise(&callback_port3_rise); + int3.fall(&callback_port3_fall); + int4.rise(&callback_port4_rise); + int4.fall(&callback_port4_fall); + int5.rise(&callback_port5_rise); + int5.fall(&callback_port5_fall); + int6.rise(&callback_port6_rise); + int6.fall(&callback_port6_fall); + int7.rise(&callback_port7_rise); + int7.fall(&callback_port7_fall); + int8.rise(&callback_port8_rise); + int8.fall(&callback_port8_fall); + int9.rise(&callback_port9_rise); + int9.fall(&callback_port9_fall); + + //clockResetInt.rise(&callback_clockReset); + //clockResetInt.mode(PullDown); + + clockExternalIncrement.mode(PullDown); + + //The inputs are set for pull-up mode (might need to change this) + in1.mode(PullDown); + in2.mode(PullDown); + in3.mode(PullDown); + in4.mode(PullDown); + in5.mode(PullDown); + in6.mode(PullDown); + in7.mode(PullDown); + in8.mode(PullDown); + in9.mode(PullDown); + + //Set up input buffer for the serial port + //char buffer[128]; + int bufferPos = 0; + eraseBuffer(buffer,128); + + ostringstream timeConvert; // stream used for the conversion + ostringstream stateConvert; + char junkChar; + int tmpChar; + + //while (pc.readable()) { + while (pc.readable()) { + junkChar = pc.getc(); + } + + FILE *fp = fopen("/local/STARTUP.TXT", "r"); + if (fp != NULL) { + pc.printf("Executing startup script...\r\n"); + do { + tmpChar = fgetc(fp); + if ((tmpChar >= 32) && (tmpChar <= 126)) { + buffer[bufferPos] = tmpChar; + bufferPos++; + } + if ((tmpChar == 13) || (tmpChar == 10)) { //carrriage return + parser.addLineToCurrentBlock(buffer); + bufferPos = 0; + eraseBuffer(buffer,128); + } + //pc.putc(tmpChar); + } while (tmpChar != EOF); + + buffer[bufferPos] = 59; + parser.addLineToCurrentBlock(buffer); + eraseBuffer(buffer,128); + fclose(fp); + } else { + pc.printf("No startup script found.\r\n"); + } + + //main loop + while(1) { + //check the main event queue to see if anything needs to be done + mainQueue.check(); + + //https://developer.mbed.org/handbook/Serial + //if(device.readable()) { +// pc.putc(device.getc()); +// } + //check if anything has been written to the serial input + //if (pc.readable()) { + if (pc.readable()) { + + buffer[bufferPos] = pc.getc(); + bufferPos++; + + //'Return' key pressed + if ((buffer[bufferPos-1] == 13) || (buffer[bufferPos-1] == 10)) { + //pc.printf("\r\n"); + buffer[bufferPos-1] = '\0'; + parser.addLineToCurrentBlock(buffer); + bufferPos = 0; + eraseBuffer(buffer,128); + + } else { + //pc.putc(buffer[bufferPos-1]); + //Backspace was pressed + if (((buffer[bufferPos-1] == 127)||(buffer[bufferPos-1] == 8)) && (bufferPos > 0)) { + + bufferPos = bufferPos-2; + } + } + } + + // __disable_irq(); + + + //Check all the digital ports to see if anything has changed. In the update routine, the port's + //script callbacks are called if the port was triggered + digitalInChanged = false; + digitalOutChanged = false; + changeTime = timeKeeper; + for (int i = 0; i < NUMPORTS; i++) { + if (portVector[i+1]->update()) { + digitalInChanged = true; + changeTime = min(changeTime,portVector[i+1]->lastChangeTime); + + //The input state of all the ports in condensed into one number (each bit contains the info) + if (portVector[i+1]->getLastChangeState() == 1) { + currentDIOstate[0] = currentDIOstate[0] | (1 << i); + } else { + currentDIOstate[0] = currentDIOstate[0] & (255^(1 << i)); + } + } + if (portVector[i+1]->outStateChanged) { + digitalOutChanged = true; + changeTime = min(changeTime,portVector[i+1]->lastOutChangeTime); + //The out state of all the ports in condensed into one number (each bit contains the info) + if (portVector[i+1]->outState == 1) { + currentDIOstate[1] = currentDIOstate[1] | (1 << i); + } else { + currentDIOstate[1] = currentDIOstate[1] & (255^(1 << i)); + } + portVector[i+1]->outStateChanged = false; + } + } + + //If anything changed, we write the new values to the serial port (this can be turned off + //with broadCastStateChanges) + if ( (digitalInChanged||digitalOutChanged) && broadCastStateChanges) { + timeConvert << changeTime; //broadcast the earliest timestamp when a change occured + //stateConvert << currentDIOstate[0] << " " << currentDIOstate[1]; + stateConvert << currentDIOstate[0] << " " << currentDIOstate[1] << " "; + textDisplay.send(timeConvert.str() + " " + stateConvert.str() + "\r\n"); + timeConvert.clear(); + timeConvert.seekp(0); + stateConvert.clear(); + stateConvert.seekp(0); + digitalInChanged = false; + digitalOutChanged = false; + } + + //We use a buffer to send text via the serial port. For every loop + //in the main loop, we send one character if there is enything to send. + //This way, outputting text to serial does not hold up other time-sensitive + //things in the event queue + if ((textDisplay.unsentData) && (textStreaming)) { + pc.printf("%c", textDisplay.getNextChar()); + } + + //Here is how we toggle between standalone and slave mode for the clock updating. + if (changeToSlave) { + //timeTick1.detach(); + NVIC_DisableIRQ(TIMER2_IRQn); // Disable the interrupt + clockExternalIncrement.rise(&callback_clockExternalIncrement); + clockSlave = true; + changeToSlave = false; + changeToStandAlone = false; + } else if (changeToStandAlone) { + //timeTick1.attach_us(&incrementTime, 100); + timer0_init(); + clockExternalIncrement.rise(NULL); //remove the callback to the external interrupt + clockSlave = false; + changeToSlave = false; + changeToStandAlone = false; + } + + //__enable_irq(); + + } +}
diff -r 000000000000 -r 9d97f34c6f46 mbed.bld --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Mon May 18 01:18:45 2015 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/078e4b97a13e
diff -r 000000000000 -r 9d97f34c6f46 soundControl.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/soundControl.cpp Mon May 18 01:18:45 2015 +0000 @@ -0,0 +1,71 @@ +#include "soundControl.h" + +extern SMARTWAV sWav; +extern Serial pc; + +soundControl::soundControl(void): + fileNameExists(false), + volumePtr(NULL), + volume(-1), + play(true), + reset(false) { + +} + +void soundControl::setFile(string fileNameIn) { + for (int i = 0; i < 20; i++) { + fileName[i] = NULL; + } + std::size_t length = fileNameIn.size(); + if (length <= 20) { + fileNameIn.copy(fileName, length, 0); + fileNameExists = true; + } +} +void soundControl::setVolume(int volumeIn) { + + if ((volumeIn >= 0) && (volumeIn < 256)) { + volume = volumeIn; + volumePtr = NULL; + } +} + +void soundControl::setVolume(int* volumeIn) { + + volume = -1; + volumePtr = volumeIn; + +} + +void soundControl::setPlayback(bool playIn) { + play = playIn; +} + +void soundControl::setReset() { + reset = true; +} + +void soundControl::execute() { + + if (reset) { + sWav.reset(); + } else if (!play) { + sWav.stopTrack(); + } else { + if (volume > -1) { + sWav.volume(volume); + } else if (volumePtr != NULL) { + sWav.volume(*volumePtr); + } + + if (fileNameExists) { + //sWav.playTracks(); + sWav.stopTrack(); + wait_ms(30);\\ANDY + sWav.playTrackName(fileName); + } + } +} + + +
diff -r 000000000000 -r 9d97f34c6f46 soundControl.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/soundControl.h Mon May 18 01:18:45 2015 +0000 @@ -0,0 +1,30 @@ +#include "mbed.h" +#include "SMARTWAV.h" +#include <stdint.h> +#include <string.h> +#include <string> +#include <vector> +#include <queue> + + +class soundControl { + +public: + soundControl(void); + void setFile(string fileNameIn); + void setVolume(int* volumeIn); + void setVolume(int volumeIn); + void setPlayback(bool playIn); + void setReset(); + void execute(); + +private: + char fileName[21]; + bool fileNameExists; + int* volumePtr; + int volume; + bool play; + bool reset; + + +}; \ No newline at end of file