Microcontroller firmware that uses a simple, yet powerful scripting language to control the timing of input and output events with high temporal resolution. Written by Mattias Karlsson

Dependencies:   SMARTWAV mbed

Revision:
7:5fe7329751d4
Parent:
6:6a6761a47951
Child:
8:872b843a3053
diff -r 6a6761a47951 -r 5fe7329751d4 behave.cpp
--- a/behave.cpp	Fri Jun 10 21:22:34 2016 +0000
+++ b/behave.cpp	Tue Feb 07 18:45:25 2017 +0000
@@ -105,14 +105,32 @@
        DIO_DCR = DIO_DCR_IE;       // enable DIO edge interrupts
 #endif
 
-    for (int i = 0; i < NUMPORTS; i++) {
-        //Set up the ports.  Each has two pointers to the harware implementations
-        //of a digital out and digital in.
-        ports[i].init(hardware->getDigitalOutPtr(i),hardware->getDigitalInPtr(i));
+    //Set up the ports.
+    int totalPorts = 0;
+    for (int i = 0; i < NUMDIGINPORTS; i++) {
+        digInPorts[i].init(hardware->getDigitalInPtr(i));
+        ports[totalPorts] = &digInPorts[i];
+        totalPorts++;
+    }
+    for (int i = 0; i < NUMDIGOUTPORTS; i++) {
+        digOutPorts[i].init(hardware->getDigitalOutPtr(i));
+        ports[totalPorts] = &digOutPorts[i];
+        totalPorts++;
     }
-
-
-    parser = new scriptStream(ports, NUMPORTS, &mainQueue, hardware);
+    for (int i = 0; i < NUMANINPORTS; i++) {
+        anInPorts[i].init(hardware->getAnalogInPtr(i));
+        ports[totalPorts] = &anInPorts[i];
+        totalPorts++;
+    }
+    for (int i = 0; i < NUMANOUTPORTS; i++) {
+        anOutPorts[i].init(hardware->getAnalogOutPtr(i));
+        ports[totalPorts] = &anOutPorts[i];
+        totalPorts++;
+    }
+
+
+    //int totalPorts = NUMDIGINPORTS+NUMDIGOUTPORTS+NUMANINPORTS+NUMANOUTPORTS;
+    parser = new scriptStream(ports, totalPorts, &mainQueue, hardware);
 
 }
 
@@ -169,9 +187,9 @@
 #endif
 
     //Get the initial state of all input pins
-    for (int i = 0; i < NUMPORTS; i++) {
-
-        if (ports[i].getDigitalIn() == 1) {
+    for (int i = 0; i < NUMDIGINPORTS; i++) {
+
+        if (digInPorts[i].read() == 1) {
             currentDIOstate[0] |= (1 << i);
         } else {
             currentDIOstate[0] &= ~(1 << i);
@@ -214,12 +232,52 @@
             }
         }
 
+        //Check all the analog ports to see if anything has changed. In the update routine, the port's
+        //script callbacks are called if the port crossed threshold.
+        for (int i = 0; i < NUMANINPORTS; i++) {
+            anInPorts[i].update();
+        }
+        for (int i = 0; i < NUMANOUTPORTS; i++) {
+            anOutPorts[i].update();
+        }
+
         //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 < NUMDIGINPORTS; i++) {
+
+            if (digInPorts[i].update()) {
+
+                digitalInChanged = true;
+                changeTime = max(changeTime,digInPorts[i].lastChangeTime);
+
+                //The input state of all the ports in condensed into one number (each bit contains the info)
+                if (digInPorts[i].getLastChangeState() == 1) {
+                    currentDIOstate[0] |= (1 << i);
+                } else {
+                    currentDIOstate[0] &= ~(1 << i);
+                }
+            }
+        }
+        for (int i = 0; i < NUMDIGOUTPORTS; i++) {
+
+            if (digOutPorts[i].update()) {
+
+                digitalOutChanged = true;
+                changeTime = max(changeTime,digOutPorts[i].lastChangeTime);
+
+                //The input state of all the ports in condensed into one number (each bit contains the info)
+                if (digOutPorts[i].getLastChangeState() == 1) {
+                    currentDIOstate[1] |= (1 << i);
+                } else {
+                    currentDIOstate[1] &= ~(1 << i);
+                }
+            }
+        }
+        /*
         for (int i = 0; i < NUMPORTS; i++) {
 
             if (ports[i].update()) {
@@ -252,28 +310,18 @@
                 }
                 ports[i].outStateChanged = false;
             }
-        }
-
-        //If anything changed, we write the new values to the serial port (this can be turned off
+        }*/
+
+        //If anything changed in the DIOs, we write the new values to the serial port (this can be turned off
         //with broadCastStateChanges)
         if ( (digitalInChanged||digitalOutChanged) && broadCastStateChanges) {
             textDisplay << changeTime << " " << currentDIOstate[0] << " " << currentDIOstate[1] << "\r\n";
-
-            /*
-            timeConvert << changeTime; //broadcast the earliest timestamp when a change occured
-            //stateConvert << currentDIOstate[0] << " " << currentDIOstate[1];
-            stateConvert << currentDIOstate[0] << " " << currentDIOstate[1] << "       ";
-
-            textDisplay.send(timeConvert.str() + " " + stateConvert.str() + "\r\n");
-            timeConvert.clear();
-            timeConvert.seekp(0);
-            stateConvert.clear();
-            stateConvert.seekp(0);
-            */
             digitalInChanged = false;
             digitalOutChanged = false;
         }
 
+
+
         //We use a buffer to send text via the serial port.  For every loop
         //in the main loop, we send one character if there is enything to send.
         //This way, outputting text to serial does not hold up other time-sensitive
@@ -295,8 +343,10 @@
         //check for shortcut triggers
         numTriggersToProcess = hardware->getPendingFunctionTriggers(shortcutTriggers);
         for (int i = 0; i < numTriggersToProcess; i++) {
-            textDisplay << "Trigger function " << shortcutTriggers[i]+1 << "\r\n";
-            if ((shortcutTriggers[i] < NUMTRIGGERACTIONS) && functionSpotTaken[shortcutTriggers[i]] && functionEventArray[i]->isUsed) {
+            textDisplay << "Trigger function " << shortcutTriggers[i]+1 << " taken: " << (uint16_t)functionSpotTaken[shortcutTriggers[i]] << " isused: " << (uint16_t)functionEventArray[shortcutTriggers[i]]->isUsed<< "\r\n";
+
+            if ((shortcutTriggers[i] < NUMTRIGGERACTIONS) && functionSpotTaken[shortcutTriggers[i]] && functionEventArray[shortcutTriggers[i]]->isUsed) {
+                textDisplay << "Executing trigger function.\r\n";
                 //textDisplay << "Executing function array index " << shortcutTriggers[i] << "\r\n";
                 functionEventArray[shortcutTriggers[i]]->execute();
             }
@@ -376,8 +426,267 @@
         pos = str.find_first_of(delimiters, lastPos);
     }
 }
-
-
+//-----------------------------------------
+AbstractPort::AbstractPort():
+    triggerUpEventPtr(NULL),
+    triggerDownEventPtr(NULL),
+    state(0),
+    portDir(none),
+    thresh(0),
+    lastChangeTime(0),
+    hasTriggerFunction(false),
+    reportUpdates(false) {
+
+}
+
+
+
+void AbstractPort::write(int outVal) {
+    //Default do nothing
+}
+
+void AbstractPort::setThresh(int threshVal) {
+    thresh = threshVal;
+}
+
+
+void AbstractPort::setTriggerUpEvent(event *eventInput) {
+
+    if (triggerUpEventPtr != NULL) {
+        triggerUpEventPtr->release();
+    }
+    triggerUpEventPtr = eventInput;
+    hasTriggerFunction = true;
+}
+
+void AbstractPort::setTriggerDownEvent(event *eventInput) {
+
+    if (triggerDownEventPtr != NULL) {
+        triggerDownEventPtr->release();
+    }
+    triggerDownEventPtr = eventInput;
+    hasTriggerFunction = true;
+}
+
+void AbstractPort::clearTriggerEvents() {
+
+    if (triggerUpEventPtr != NULL) {
+        triggerUpEventPtr->release();
+        triggerUpEventPtr = NULL;
+    }
+    if (triggerDownEventPtr != NULL) {
+        triggerDownEventPtr->release();
+        triggerDownEventPtr = NULL;
+    }
+    hasTriggerFunction = false;
+}
+
+void AbstractPort::setReportUpdates(bool report) {
+    reportUpdates = report;
+}
+
+int AbstractPort::getLastChangeState() {
+    return lastInState;
+}
+uint32_t AbstractPort::getTimeSinceLastChange() {
+    return lastChangeInterval;
+}
+
+bool AbstractPort::checkForChange() {
+    //Default behavior checks if the signal has crossed threshold using sofware
+    //detect change in the software main loop
+    //we read the pin state to see if it is different than the
+    //remembered state.  This is important in order to report both edges of a
+    //fast up-down event.
+
+    state = read();
+    bool changed = ((lastInState < thresh && state >= thresh) || (lastInState >= thresh && state < thresh));
+
+    if (changed) {
+        if (state >= thresh) {
+
+            lastChangeInterval = timeKeeper - lastChangeTime;
+            lastChangeTime = timeKeeper;
+
+            if (triggerUpEventPtr != NULL && triggerUpEventPtr->isUsed) {triggerUpEventPtr->execute();}
+        } else if (state < thresh) {
+
+            lastChangeInterval = timeKeeper - lastChangeTime;
+            lastChangeTime = timeKeeper;
+
+
+            if (triggerDownEventPtr != NULL && triggerDownEventPtr->isUsed){triggerDownEventPtr->execute();}
+        }
+
+        lastInState = state;
+
+    }
+}
+
+bool AbstractPort::update() {
+
+
+    bool changed = false;
+
+    if ((reportUpdates || hasTriggerFunction)&&(timeKeeper - lastChangeTime) > 1) { //prevents flutter triggers when button is pressed
+        changed = checkForChange();
+    } else if (portDir == in) {
+        state = read();
+    }
+
+    return changed;
+}
+
+
+
+//-----------------------------------------
+AnalogPort::AnalogPort():
+    outPin(NULL),
+    inPin(NULL) {
+
+    portType = analog;
+    
+}
+
+void AnalogPort::init(sAnalogIn *IP) {
+
+    portDir = in;
+    inPin = IP;
+    
+}
+
+void AnalogPort::init(sAnalogOut *OP){
+    portDir = out;
+    outPin = OP;
+}
+
+void AnalogPort::write(int outVal) {
+    if (portDir == out) {
+        outPin->write(outVal);
+        if (state != outVal) {
+            outStateChanged = true;
+            lastOutChangeTime = timeKeeper;
+        }
+        //state = outVal;
+        state = outPin->read();
+    }
+}
+
+int AnalogPort::read() {
+    if (portDir == out) {
+        return outPin->read();
+    } else if (portDir == in) {
+        return inPin->read();
+    }
+}
+
+void AnalogPort::setThresh(int threshVal) {
+    thresh = threshVal;
+    //TODO: set thresh for hardware object too
+}
+
+
+//-----------------------------------------
+DigitalPort::DigitalPort():
+    outPin(NULL),
+    inPin(NULL) {
+
+    portType = digital;
+    thresh = 1;
+
+}
+
+void DigitalPort::init(sDigitalIn *IP) {
+
+    portDir = in;
+    inPin = IP;
+
+}
+
+void DigitalPort::init(sDigitalOut *OP){
+    portDir = out;
+    outPin = OP;
+}
+
+void DigitalPort::write(int outVal) {
+     if (portDir == out) {
+        if (outVal == -1) {
+            outVal = 1-state;
+        }
+        outPin->write(outVal);
+        if (state != outVal) {
+            outStateChanged = true;
+            lastOutChangeTime = timeKeeper;
+        }
+        state = outVal;
+    }
+}
+
+int DigitalPort::read() {
+    if (portDir == out) {
+        return outPin->read();
+    } else if (portDir == in) {
+        return inPin->read();
+    }
+}
+
+bool DigitalPort::checkForChange() {
+
+    //Use hardware to detect state change times
+    bool changed = false;
+
+    inPin->setUpdate(true); //Once we get the state of the pin, we buffer any pin changes until we are done checking
+
+    //Every ms, we first check if a hardware trigger occured
+    //in the opposite direction of the last remembered state
+    if (lastInState == 0) {
+        changed = inPin->lastUpEvent.triggered;
+        if (changed) state = 1;
+    } else if (lastInState == 1) {
+        changed = inPin->lastDownEvent.triggered;
+        if (changed) state = 0;
+    }
+
+    //if not, then we read the pin state to see if it is different than the
+    //remembered state.  This is important in order to report both edges of a
+    //fast up-down event.
+    if (!changed) {
+        state = read();
+        changed = (lastInState != state);
+
+    }
+
+
+    //changed = (inPin->lastUpEvent.triggered || inPin->lastDownEvent.triggered);
+    if (changed) {
+        if (state == 1) {
+
+            lastChangeInterval = inPin->lastUpEvent.timeStamp - lastChangeTime;
+            lastChangeTime = inPin->lastUpEvent.timeStamp;
+
+            if (triggerUpEventPtr != NULL && triggerUpEventPtr->isUsed) {triggerUpEventPtr->execute();}
+        } else if (state == 0) {
+
+            lastChangeInterval = inPin->lastDownEvent.timeStamp - lastChangeTime;
+            lastChangeTime = inPin->lastDownEvent.timeStamp;
+
+            if (triggerDownEventPtr != NULL && triggerDownEventPtr->isUsed){triggerDownEventPtr->execute();}
+        }
+
+        lastInState = state;
+        inPin->lastUpEvent.triggered = false;
+        inPin->lastDownEvent.triggered = false;
+
+        inPin->setUpdate(false); //This also checks if there were any buffered changes that occured
+    }
+
+    inPin->setUpdate(false); //This also checks if there were any buffered changes that occured
+
+    return changed;
+}
+
+
+//------------------------------------------
 digitalPort::digitalPort():
 outPin(NULL),
 inPin(NULL),
@@ -455,7 +764,7 @@
     bool execDown = false;
     if ((timeKeeper - lastChangeTime) > 1) { //prevents flutter triggers when button is pressed
 
-        //changed = (lastInState != inState);
+
         inPin->setUpdate(true); //Once we get the state of the pin, we buffer any pin changes until we are done checking
 
         //Every ms, we first check if a hardware trigger occured
@@ -474,6 +783,7 @@
         if (!changed) {
             inState = getDigitalIn();
             changed = (lastInState != inState);
+
         }
 
 
@@ -548,13 +858,13 @@
             inPin->lastUpEvent.triggered = false;
             inPin->lastDownEvent.triggered = false;
 
-            //inPin->setUpdate(false); //This also checks if there were any buffered changes that occured
-            
+            inPin->setUpdate(false); //This also checks if there were any buffered changes that occured
+
 
         }
 
         inPin->setUpdate(false); //This also checks if there were any buffered changes that occured
-        
+
 
     }
 
@@ -664,7 +974,7 @@
     isUsed = false;
 
 }
-intCompare::intCompare(digitalPort* portInput, const char* cmpString, int cmpValInput, int whichToUse):
+intCompare::intCompare(AbstractPort* portInput, const char* cmpString, int cmpValInput, int whichToUse):
 port(portInput) {
     cmpVal = new int(cmpValInput);
     cmpValGlobal = false;
@@ -673,13 +983,13 @@
     setPointer(cmpString);
     isUsed = true;
     if (whichToUse == 1) {
-        portValPtr = &port->inState;
+        portValPtr = &port->state;
     } else {
-        portValPtr = &port->outState;
+        portValPtr = &port->state;
     }
 }
 
-intCompare::intCompare(digitalPort* portInput, const char* cmpString, int* cmpIntVarInput, int whichToUse):
+intCompare::intCompare(AbstractPort* portInput, const char* cmpString, int* cmpIntVarInput, int whichToUse):
 port(portInput),
 cmpVal(cmpIntVarInput) {
     cmpValGlobal = true;
@@ -688,9 +998,9 @@
     setPointer(cmpString);
     isUsed = true;
     if (whichToUse == 1) {
-        portValPtr = &port->inState;
+        portValPtr = &port->state;
     } else {
-        portValPtr = &port->outState;
+        portValPtr = &port->state;
     }
 }
 
@@ -727,7 +1037,7 @@
     setPointer_operation(cmpString);
 }
 
-intCompare::intCompare(digitalPort* portInput, const char* cmpString, intOperation* cmpIntOpInput, int whichToUse):
+intCompare::intCompare(AbstractPort* portInput, const char* cmpString, intOperation* cmpIntOpInput, int whichToUse):
 port(portInput) {
     cmpVal = NULL;
     intVal = NULL;
@@ -736,15 +1046,15 @@
     setPointer_operation(cmpString);
     isUsed = true;
     if (whichToUse == 1) {
-        portValPtr = &port->inState;
+        portValPtr = &port->state;
     } else {
-        portValPtr = &port->outState;
+        portValPtr = &port->state;
     }
 }
 
 
 
-void intCompare::set(digitalPort* portInput, const char* cmpString, int cmpValInput, int whichToUse) {
+void intCompare::set(AbstractPort* portInput, const char* cmpString, int cmpValInput, int whichToUse) {
     port = portInput;
     cmpVal = new int(cmpValInput);
     cmpValGlobal = false;
@@ -753,13 +1063,13 @@
     setPointer(cmpString);
     isUsed = true;
     if (whichToUse == 1) {
-        portValPtr = &port->inState;
+        portValPtr = &port->state;
     } else {
-        portValPtr = &port->outState;
+        portValPtr = &port->state;
     }
 }
 
-void intCompare::set(digitalPort* portInput, const char* cmpString, int* cmpIntVarInput, int whichToUse) {
+void intCompare::set(AbstractPort* portInput, const char* cmpString, int* cmpIntVarInput, int whichToUse) {
     port = portInput;
     cmpVal = cmpIntVarInput;
     cmpValGlobal = true;
@@ -768,9 +1078,9 @@
     setPointer(cmpString);
     isUsed = true;
     if (whichToUse == 1) {
-        portValPtr = &port->inState;
+        portValPtr = &port->state;
     } else {
-        portValPtr = &port->outState;
+        portValPtr = &port->state;
     }
 }
 
@@ -807,7 +1117,7 @@
     isUsed = true;
 }
 
-void intCompare::set(digitalPort* portInput, const char* cmpString, intOperation* cmpIntOpInput, int whichToUse) {
+void intCompare::set(AbstractPort* portInput, const char* cmpString, intOperation* cmpIntOpInput, int whichToUse) {
     port = portInput;
     cmpVal = NULL;
     intVal = NULL;
@@ -816,9 +1126,9 @@
     setPointer_operation(cmpString);
     isUsed = true;
     if (whichToUse == 1) {
-        portValPtr = &port->inState;
+        portValPtr = &port->state;
     } else {
-        portValPtr = &port->outState;
+        portValPtr = &port->state;
     }
 }
 
@@ -1428,47 +1738,25 @@
     isUsed = false;
 }
 
-/*
- portMessage::portMessage(digitalPort* portIn, int whichToSetIn, int valueIn):
- whichToSet(whichToSetIn),
- value(valueIn),
- port(portIn) {
- isUsed = true;
- }
-
- void portMessage::setMessage(digitalPort* portIn, int whichToSetIn, int valueIn) {
- whichToSet = whichToSetIn;
- value = valueIn;
- port = portIn;
- isUsed = true;
- }*/
-
-/*
-portMessage::portMessage(int* portIn, int whichToSetIn, int valueIn):
-whichToSet(whichToSetIn),
-value(valueIn),
-port(portIn) {
-    isUsed = true;
-}*/
-
-void portMessage::setMessage(int* portIn, int whichToSetIn, int valueIn, digitalPort* portVectorIn) {
+void portMessage::setMessage(int* portIn, int whichToSetIn, int valueIn, AbstractPort** portVectorIn, int portVectorLength) {
     whichToSet = whichToSetIn;
     value = valueIn;
     port = portIn;
     portVector = portVectorIn;
     isUsed = true;
+    vectorLength = portVectorLength;
 }
 
 void portMessage::execute() {
 
     if (port != NULL) {
-        if ((*port > 0) && (*port <= NUMPORTS)) {
-            portVector[*port-1].setDigitalOut(value);
+        if ((*port > 0) && (*port <= vectorLength)) {
+            portVector[*port-1]->write(value);
         } else {
             textDisplay << "Error: port index assigned by variable does not exist.\r\n";
         }
     } else {
-        portVector[whichToSet-1].setDigitalOut(value);
+        portVector[whichToSet-1]->write(value);
     }
 
 }
@@ -2170,12 +2458,45 @@
 }
 
 
-scriptStream::scriptStream(digitalPort* portVectorInput, int numPortsInput, eventQueue* queueInput, sSystem *system):
+scriptStream::scriptStream(AbstractPort** portVectorInput, int numPortsInput, eventQueue* queueInput, sSystem *system):
     portVector(portVectorInput),
     numPorts(numPortsInput),
     queuePtr(queueInput),
     system(system) {
 
+    numAnInPorts = 0;
+    numDigInPorts = 0;
+    numAnOutPorts = 0;
+    numDigOutPorts = 0;
+
+    for (int i=0;i<numPortsInput;i++) {
+        if ((portVectorInput[i]->portType == AbstractPort::analog)&&(portVectorInput[i]->portDir == AbstractPort::in)) {
+            if(numAnInPorts < NUMANINPORTS) {
+                anInPortVector[numAnInPorts] = portVectorInput[i];
+                anInLookup[numAnInPorts] = i;
+                numAnInPorts++;
+            }
+        } else if ((portVectorInput[i]->portType == AbstractPort::analog)&&(portVectorInput[i]->portDir == AbstractPort::out)) {
+            if(numAnOutPorts < NUMANOUTPORTS) {
+                anOutPortVector[numAnOutPorts] = portVectorInput[i];
+                anOutLookup[numAnOutPorts] = i;
+                numAnOutPorts++;
+            }
+        } else if ((portVectorInput[i]->portType == AbstractPort::digital)&&(portVectorInput[i]->portDir == AbstractPort::in)) {
+            if(numDigInPorts < NUMDIGINPORTS) {
+                digInPortVector[numDigInPorts] = portVectorInput[i];
+                digInLookup[numDigInPorts] = i;
+                numDigInPorts++;
+            }
+        } else if ((portVectorInput[i]->portType == AbstractPort::digital)&&(portVectorInput[i]->portDir == AbstractPort::out)) {
+            if(numDigOutPorts < NUMDIGOUTPORTS) {
+                digOutPortVector[numDigOutPorts] = portVectorInput[i];
+                digOutLookup[numDigOutPorts] = i;
+                numDigOutPorts++;
+            }
+        }
+    }
+
     currentPort = -1;
     currentTriggerPort = -1;
     currentTriggerDir = 1;
@@ -2666,11 +2987,11 @@
                 if (!lineError) {
                     int funcNum = atoi(tmpLine.substr(pos1,pos2-pos1).data());
                     if ((funcNum > 0) && (funcNum < NUMFUNCTIONS+1)) {
-                        if (functionSpotTaken[funcNum-1] && functionEventArray[funcNum]->isUsed) {
+                        if (functionSpotTaken[funcNum-1] && functionEventArray[funcNum-1]->isUsed) {
 
 
                         } else {
-                            textDisplay << "Error: function number does not exist\r\n";
+                            textDisplay << "Error: function number does not exist\r\n";                           
                             lineError = true;
                         }
                     } else {
@@ -2856,7 +3177,7 @@
                     } else if (tokens[i+1].compare("off") == 0) {
                         stream = false;
                     } else {
-                        textDisplay << "Error: 'updates' useage: 'updates on' or 'updates off'\r\n";
+                        textDisplay << "Error: 'updates' usage: 'updates on' or 'updates off'\r\n";
                         lineError = true;
                     }
                 }
@@ -2868,7 +3189,7 @@
                     if (tempPort > 0) {
                         specifiedPort = tempPort-1;
                     } else {
-                        textDisplay << "Error: 'updates' useage: 'updates on [port]' or 'updates off [port]'\r\n";
+                        textDisplay << "Error: 'updates' usage: 'updates on [port]' or 'updates off [port]'\r\n";
                         lineError = true;
                     }
                     i++;
@@ -2878,21 +3199,25 @@
                     if (stream) {
                         //applies to all;
                         broadCastStateChanges = true;
-                        if (specifiedPort > -1) {
-                            system->setPortUpdatesOn(specifiedPort);
+                        if ((specifiedPort > -1) && (specifiedPort < NUMDIGINPORTS)) {
+                            //system->setPortUpdatesOn(specifiedPort);
+                            digInPortVector[specifiedPort]->setReportUpdates(true);
                         } else {
-                            for (int i=0;i<NUMPORTS;i++) {
-                                system->setPortUpdatesOn(i);
+                            for (int i=0;i<NUMDIGINPORTS;i++) {
+                                //system->setPortUpdatesOn(i);
+                                digInPortVector[i]->setReportUpdates(true);
                             }
                         }
                     } else {
-                        if (specifiedPort > -1) {
-                            system->setPortUpdatesOff(specifiedPort);
+                        if ((specifiedPort > -1) && (specifiedPort < NUMDIGINPORTS)) {
+                            //system->setPortUpdatesOff(specifiedPort);
+                            digInPortVector[specifiedPort]->setReportUpdates(false);
                         } else {
                             //applies to all
                             //broadCastStateChanges = false;
-                            for (int i=0;i<NUMPORTS;i++) {
-                                system->setPortUpdatesOff(i);
+                            for (int i=0;i<NUMDIGINPORTS;i++) {
+                                //system->setPortUpdatesOff(i);
+                                digInPortVector[i]->setReportUpdates(false);
                             }
                         }
 
@@ -3020,7 +3345,7 @@
 
                 if (!ifBlockInit && !whileBlockInit) {
 
-                    if ((currentTriggerPort > 0) || (currentFunction > -1)) { //check to make sure we are inside a trigger block
+                    if ((currentTriggerPort > -1) || (currentFunction > -1)) { //check to make sure we are inside a trigger block
 
 
                     } else {
@@ -3276,10 +3601,12 @@
                             int pos2 = tokens[i+1].find_first_of("]",pos1);
                             currentTriggerPort = atoi(tokens[i+1].substr(pos1,pos2-pos1).data());
 
-                            if (currentTriggerPort <= 0) {
+                            if (currentTriggerPort <= 0 || currentTriggerPort > NUMDIGINPORTS) {
                                 currentTriggerPort = -1;
-                                textDisplay << "Error: Not a valid port number\r\n";
+                                textDisplay << "Error: Not a valid port number.\r\n";
                                 lineError = true;
+                            } else {
+                                currentTriggerPort = digInLookup[currentTriggerPort-1];
                             }
                         } else {
                             textDisplay << "Error: Not a valid callback input\r\n";
@@ -3322,10 +3649,10 @@
                         tmpEventPtrArray.push_back(tmpEvent);
                         if (currentTriggerDir == 1) {
 
-                            portVector[currentTriggerPort-1].setTriggerUpEvent(tmpEventPtrArray.back());
+                            portVector[currentTriggerPort]->setTriggerUpEvent(tmpEventPtrArray.back());
                         } else {
 
-                            portVector[currentTriggerPort-1].setTriggerDownEvent(tmpEventPtrArray.back());
+                            portVector[currentTriggerPort]->setTriggerDownEvent(tmpEventPtrArray.back());
                         }
 
                     }
@@ -3444,7 +3771,7 @@
                 }
                 textDisplay.debug("While statement\r\n");
 
-                if ((currentTriggerPort > 0) || (currentFunction > -1)) { //check to make sure we are inside a trigger block
+                if ((currentTriggerPort > -1) || (currentFunction > -1)) { //check to make sure we are inside a trigger block
 
 
                 } else {
@@ -3701,13 +4028,15 @@
     textDisplay.debug(nameInput.data());
     int* outPtr = NULL;
     bool foundIt = false;
+
+    //First check if the variable is the state of a port
     if (nameInput.find("portout") != std::string::npos) {
         int pos1 = nameInput.find("portout[")+8;
         int pos2 = nameInput.find_first_of("]",pos1);
         int portnum = atoi(nameInput.substr(pos1,pos2-pos1).data());
         int portVal = 0;
-        if ((portnum > 0) && (portnum <= numPorts)) {
-            outPtr = &portVector[portnum-1].outState;
+        if ((portnum > 0) && (portnum <= numDigOutPorts)) {
+            outPtr = &digOutPortVector[portnum-1]->state;
             foundIt = true;
         }
     } else if (nameInput.find("portin") != std::string::npos) {
@@ -3715,12 +4044,31 @@
         int pos2 = nameInput.find_first_of("]",pos1);
         int portnum = atoi(nameInput.substr(pos1,pos2-pos1).data());
         int portVal = 0;
-        if ((portnum > 0) && (portnum <= numPorts)) {
-            outPtr = &portVector[portnum-1].inState;
+        if ((portnum > 0) && (portnum <= numDigInPorts)) {
+            outPtr = &digInPortVector[portnum-1]->state;
+            foundIt = true;
+        }
+    } else if (nameInput.find("analogout") != std::string::npos) {
+        int pos1 = nameInput.find("analogout[")+10;
+        int pos2 = nameInput.find_first_of("]",pos1);
+        int portnum = atoi(nameInput.substr(pos1,pos2-pos1).data());
+        int portVal = 0;
+        if ((portnum > 0) && (portnum <= numAnOutPorts)) {
+            outPtr = &anOutPortVector[portnum-1]->state;
+            foundIt = true;
+        }
+    } else if (nameInput.find("analogin") != std::string::npos) {
+        int pos1 = nameInput.find("analogin[")+9;
+        int pos2 = nameInput.find_first_of("]",pos1);
+        int portnum = atoi(nameInput.substr(pos1,pos2-pos1).data());
+        int portVal = 0;
+        if ((portnum > 0) && (portnum <= numAnInPorts)) {
+            outPtr = &anInPortVector[portnum-1]->state;
             foundIt = true;
         }
     }
 
+    //Then check if it is a defined int variable
     if (!foundIt) {
         std::vector<intVariable*>::size_type sz = globalVariables.size();
         int start = 0;
@@ -3753,6 +4101,7 @@
     int* outPtr = NULL;
     bool foundIt = false;
 
+    //First check if the variable is the current state of a port
     if (findStringLoc(nameInput,"portout[",start,end) != -1) {
         int pos1 = findStringLoc(nameInput,"portout[",start,end)+8;
         int pos2 = findStringLoc(nameInput, "]",pos1,end);
@@ -3763,8 +4112,8 @@
 
         //int portnum = atoi(nameInput.substr(pos1,pos2-pos1).data());
         long int portnum = strtol(nameInput+pos1,NULL,10);
-        if ((portnum > 0) && (portnum <= numPorts)) {
-            outPtr = &portVector[(int)portnum-1].outState;
+        if ((portnum > 0) && (portnum <= numDigOutPorts)) {
+            outPtr = &digOutPortVector[(int)portnum-1]->state;
             foundIt = true;
         }
     } else if (findStringLoc(nameInput,"portin[",start,end) != -1) {
@@ -3776,8 +4125,35 @@
         }
         long int portnum = strtol(nameInput+pos1,NULL,10);
 
-        if ((portnum > 0) && (portnum <= numPorts)) {
-            outPtr = &portVector[(int)portnum-1].inState;
+        if ((portnum > 0) && (portnum <= numDigInPorts)) {
+            outPtr = &digOutPortVector[(int)portnum-1]->state;
+            foundIt = true;
+        }
+    } else if (findStringLoc(nameInput,"analogout[",start,end) != -1) {
+        int pos1 = findStringLoc(nameInput,"analogout[",start,end)+10;
+        int pos2 = findStringLoc(nameInput, "]",pos1,end);
+        if ((pos1 == -1)||(pos2 == -1)) {
+            //syntax error
+            return NULL;
+        }
+
+        //int portnum = atoi(nameInput.substr(pos1,pos2-pos1).data());
+        long int portnum = strtol(nameInput+pos1,NULL,10);
+        if ((portnum > 0) && (portnum <= numAnOutPorts)) {
+            outPtr = &anOutPortVector[(int)portnum-1]->state;
+            foundIt = true;
+        }
+    } else if (findStringLoc(nameInput,"analogin[",start,end) != -1) {
+        int pos1 = findStringLoc(nameInput,"portin[",start,end)+9;
+        int pos2 = findStringLoc(nameInput, "]",pos1,end);
+        if ((pos1 == -1)||(pos2 == -1)) {
+            //syntax error
+            return NULL;
+        }
+        long int portnum = strtol(nameInput+pos1,NULL,10);
+
+        if ((portnum > 0) && (portnum <= numAnInPorts)) {
+            outPtr = &anOutPortVector[(int)portnum-1]->state;
             foundIt = true;
         }
     }
@@ -3860,7 +4236,7 @@
         }
         int* tmpVar = findIntVariable(expression, pos1,pos2); //returns pointer to the variable, if given
         int portVal = 0;
-        if ((tmpVar != NULL)||((portnum > 0) && (portnum <= numPorts))) {
+        if ((tmpVar != NULL)||((portnum > 0) && (portnum <= numDigOutPorts))) {
             if (isNum(expression,afterEqualLoc,lastCharLoc)) { //a simple numeric assign
                 portVal = atoi(expression+afterEqualLoc);
                 if ((portVal == 0) || (portVal == 1)) {
@@ -3873,9 +4249,9 @@
                     } else {
                         //tmpMessage->setMessage(portVector[portnum],1,portVal);
                         if (tmpVar == NULL) { //a constant port number was given
-                            tmpMessage->setMessage(NULL,portnum,portVal,portVector);
+                            tmpMessage->setMessage(NULL,portnum,portVal,digOutPortVector,numDigOutPorts);
                         } else {
-                            tmpMessage->setMessage(tmpVar,0,portVal,portVector);
+                            tmpMessage->setMessage(tmpVar,0,portVal,digOutPortVector,numDigOutPorts);
                         }
                     }
 
@@ -3898,9 +4274,9 @@
                 } else {
                     //tmpMessage->setMessage(portVector[portnum],1,-1);
                     if (tmpVar == NULL) { //a constant port number was given
-                        tmpMessage->setMessage(NULL,portnum,-1,portVector);
+                        tmpMessage->setMessage(NULL,portnum,-1,digOutPortVector,numDigOutPorts);
                     } else {
-                        tmpMessage->setMessage(tmpVar,0,-1,portVector);
+                        tmpMessage->setMessage(tmpVar,0,-1,digOutPortVector,numDigOutPorts);
                     }
                 }
                 tmpAction->set(tmpMessage);
@@ -3911,7 +4287,62 @@
                 return NULL;
             }
         } else {
-            textDisplay << "Port number not found (must be between 1 and " << numPorts << " or an existing variable)\r\n";
+            textDisplay << "Port number not found (must be between 1 and " << numDigOutPorts << " or an existing variable)\r\n";
+            //delete tmpAction;
+            tmpAction->release();
+            return NULL;
+        }
+    } else if (findStringLoc(expression,"analogout[",0,beforeEqualLoc) != -1) {  //set the output of an analog port
+        textDisplay.debug("Portout assignment\r\n");
+        int pos1 = findStringLoc(expression,"analogout[",0,beforeEqualLoc)+10;
+        int pos2 = findStringLoc(expression,"]",pos1,beforeEqualLoc)-1;
+        if (pos2 < pos1) {
+            textDisplay << "Error: expected a ] character\r\n";
+            return NULL;
+        }
+
+        int portnum = -1;
+        if (isNum(expression,pos1,pos2)) {
+            portnum = atoi(expression+pos1);
+        }
+        int* tmpVar = findIntVariable(expression, pos1,pos2); //returns pointer to the variable, if given
+        int portVal = 0;
+        if ((tmpVar != NULL)||((portnum > 0) && (portnum <= numAnOutPorts))) {
+            if (isNum(expression,afterEqualLoc,lastCharLoc)) { //a simple numeric assign
+                portVal = atoi(expression+afterEqualLoc);
+                if ((portVal >= 0) || (portVal <= 3700)) {
+                    //portMessage* tmpMessage = new portMessage(portVector[portnum],1,portVal);
+                    portMessage* tmpMessage = findFirstUnUsed(portMessageBlock, NUMPORTMESSAGES);
+                    if (tmpMessage == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        //tmpMessage->setMessage(portVector[portnum],1,portVal);
+                        if (tmpVar == NULL) { //a constant port number was given
+                            tmpMessage->setMessage(NULL,portnum,portVal,anOutPortVector,numAnOutPorts);
+                        } else {
+                            tmpMessage->setMessage(tmpVar,0,portVal,anOutPortVector,numAnOutPorts);
+                        }
+                    }
+
+
+                    tmpAction->set(tmpMessage);
+
+                } else {
+                    textDisplay << "Error: analogouts can only be directly assigned a value between 0 and 3700 mV\r\n";
+                    //delete tmpAction;
+                    tmpAction->release();
+                    return NULL;
+                }
+            } else {
+                textDisplay << "Error: analogouts can only be directly assigned a value between 0 and 3700 mV\r\n";
+                //delete tmpAction;
+                tmpAction->release();
+                return NULL;
+            }
+        } else {
+            textDisplay << "Port number not found (must be between 1 and " << numAnOutPorts << " or an existing variable)\r\n";
             //delete tmpAction;
             tmpAction->release();
             return NULL;
@@ -3921,6 +4352,11 @@
         //delete tmpAction;
         tmpAction->release();
         return NULL;
+    } else if (findStringLoc(expression,"analogin",0,stringInd)!=-1) {
+        textDisplay << "Error: analog ins can not be set\r\n";
+        //delete tmpAction;
+        tmpAction->release();
+        return NULL;
     } else if (tmpVar != NULL) {
         intOperation* tmpOp;
         intOperation* tmpOp2;
@@ -4400,7 +4836,7 @@
         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 ((tmpVar != NULL)||((portnum > 0) && (portnum <= numDigOutPorts))) {
             if (isNumber(afterEqual)) { //a simple numeric assign
                 portVal = atoi(afterEqual.data());
                 if ((portVal == 0) || (portVal == 1)) {
@@ -4413,9 +4849,9 @@
                     } else {
                         //tmpMessage->setMessage(portVector[portnum],1,portVal);
                         if (tmpVar == NULL) { //a constant port number was given
-                            tmpMessage->setMessage(NULL,portnum,portVal,portVector);
+                            tmpMessage->setMessage(NULL,portnum,portVal,digOutPortVector,numDigOutPorts);
                         } else {
-                            tmpMessage->setMessage(tmpVar,0,portVal,portVector);
+                            tmpMessage->setMessage(tmpVar,0,portVal,digOutPortVector,numDigOutPorts);
                         }
                     }
 
@@ -4438,9 +4874,9 @@
                 } else {
                     //tmpMessage->setMessage(portVector[portnum],1,-1);
                     if (tmpVar == NULL) { //a constant port number was given
-                        tmpMessage->setMessage(NULL,portnum,-1,portVector);
+                        tmpMessage->setMessage(NULL,portnum,-1,digOutPortVector,numDigOutPorts);
                     } else {
-                        tmpMessage->setMessage(tmpVar,0,-1,portVector);
+                        tmpMessage->setMessage(tmpVar,0,-1,digOutPortVector,numDigOutPorts);
                     }
                 }
                 tmpAction->set(tmpMessage);
@@ -4451,7 +4887,54 @@
                 return NULL;
             }
         } else {
-            textDisplay << "Port number not found (must be between 1 and " << numPorts << " or an existing variable)\r\n";
+            textDisplay << "Port number not found (must be between 1 and " << numDigOutPorts << " or an existing variable)\r\n";
+            //delete tmpAction;
+            tmpAction->release();
+            return NULL;
+        }
+    } else if (beforeEqual.find("analogout[") != std::string::npos) { //set the output of a digital port
+        textDisplay.debug("Portout assignment\r\n");
+        int pos1 = beforeEqual.find("analogout[")+10;
+        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 <= numAnOutPorts))) {
+            if (isNumber(afterEqual)) { //a simple numeric assign
+                portVal = atoi(afterEqual.data());
+                if ((portVal >= 0) || (portVal <= 3700)) {
+                    //portMessage* tmpMessage = new portMessage(portVector[portnum],1,portVal);
+                    portMessage* tmpMessage = findFirstUnUsed(portMessageBlock, NUMPORTMESSAGES);
+                    if (tmpMessage == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        //tmpMessage->setMessage(portVector[portnum],1,portVal);
+                        if (tmpVar == NULL) { //a constant port number was given
+                            tmpMessage->setMessage(NULL,portnum,portVal,anOutPortVector,numAnOutPorts);
+                        } else {
+                            tmpMessage->setMessage(tmpVar,0,portVal,anOutPortVector,numAnOutPorts);
+                        }
+                    }
+
+
+                    tmpAction->set(tmpMessage);
+
+                } else {
+                    textDisplay << "Error: analogouts can only be directly assigned a value between 0 and 3700 mV \r\n";
+                    //delete tmpAction;
+                    tmpAction->release();
+                    return NULL;
+                }
+            } else {
+                textDisplay << "Error: analogouts can only be directly assigned a value between 0 and 3700 mV\r\n";
+                //delete tmpAction;
+                tmpAction->release();
+                return NULL;
+            }
+        } else {
+            textDisplay << "Port number not found (must be between 1 and " << numAnOutPorts << " or an existing variable)\r\n";
             //delete tmpAction;
             tmpAction->release();
             return NULL;
@@ -4461,6 +4944,11 @@
         //delete tmpAction;
         tmpAction->release();
         return NULL;
+    } else if (beforeEqual.find("analogin") != std::string::npos) {
+        textDisplay << "Error: analog ins can not be set\r\n";
+        //delete tmpAction;
+        tmpAction->release();
+        return NULL;
     } else if (tmpVar != NULL) {
         intOperation* tmpOp;
         intOperation* tmpOp2;
@@ -5522,18 +6010,18 @@
 
     //clear callbacks, functions, and queue
     if (clearMode & BLOCKMEMORYTYPES) {
-        for (int pNum = 0; pNum < NUMPORTS; pNum++) {
+        for (int pNum = 0; pNum < NUMDIGINPORTS+NUMDIGOUTPORTS+NUMANINPORTS+NUMANOUTPORTS; pNum++) {
             //delete portVector[pNum]->triggerUpEventPtr;
-            if (portVector[pNum].triggerUpEventPtr != NULL) {
-                portVector[pNum].triggerUpEventPtr->release();
+            if (portVector[pNum]->triggerUpEventPtr != NULL) {
+                portVector[pNum]->triggerUpEventPtr->release();
             }
-            portVector[pNum].triggerUpEventPtr = NULL;
+            portVector[pNum]->triggerUpEventPtr = NULL;
 
             //delete portVector[pNum]->triggerDownEventPtr;
-            if (portVector[pNum].triggerDownEventPtr != NULL) {
-                portVector[pNum].triggerDownEventPtr->release();
+            if (portVector[pNum]->triggerDownEventPtr != NULL) {
+                portVector[pNum]->triggerDownEventPtr->release();
             }
-            portVector[pNum].triggerDownEventPtr = NULL;
+            portVector[pNum]->triggerDownEventPtr = NULL;
 
         }
         for (int i = 0; i < NUMFUNCTIONS; i++) {
@@ -5577,10 +6065,12 @@
 
     if (clearMode & ENVSETTINGSMEMORYTYPES) {
         //set all environment settings to default values
-        broadCastStateChanges = true;
-        for (int i=0;i<NUMPORTS;i++) {
-            system->setPortUpdatesOn(i);
+        broadCastStateChanges = false;
+        for (int i=0;i<NUMDIGINPORTS;i++) {
+            //system->setPortUpdatesOff(i);
+            digInPortVector[i]->setReportUpdates(false);
         }
+        system->reset();
     }