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

Files at this revision

API Documentation at this revision

Comitter:
mkarlsso
Date:
Tue Feb 07 18:45:25 2017 +0000
Parent:
6:6a6761a47951
Child:
8:872b843a3053
Commit message:
Fixed flip command for digital outputs

Changed in this revision

behave.cpp Show annotated file Show diff for this revision Revisions of this file
behave.h Show annotated file Show diff for this revision Revisions of this file
hardwareInterface.cpp Show annotated file Show diff for this revision Revisions of this file
hardwareInterface.h Show annotated file Show diff for this revision Revisions of this file
mbedInterface/mbedInterface.cpp Show annotated file Show diff for this revision Revisions of this file
mbedInterface/mbedInterface.h Show annotated file Show diff for this revision Revisions of this file
--- 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();
     }
 
 
--- a/behave.h	Fri Jun 10 21:22:34 2016 +0000
+++ b/behave.h	Tue Feb 07 18:45:25 2017 +0000
@@ -56,6 +56,89 @@
     bool triggered;
 };*/
 
+class AbstractPort {
+
+public:
+    AbstractPort();
+
+    enum Direction{in,out,none};
+    enum DataType{digital, analog};
+
+    Direction portDir;
+    DataType portType;
+
+    virtual void write(int outVal);
+    virtual int  read() = 0; //Must be defined in inheriting class
+    virtual void setThresh(int threshVal);
+
+    uint32_t lastChangeTime;
+    uint32_t lastOutChangeTime;
+
+    bool update(); //called from the main loop
+    void setTriggerUpEvent(event* eventInput); //attahces a routine to an upward change
+    void setTriggerDownEvent(event* eventInput); //attahces a routine to a downward change
+    void clearTriggerEvents();
+    void setReportUpdates(bool report);
+    int getLastChangeState();
+    uint32_t getTimeSinceLastChange();
+
+    int state;
+    bool outStateChanged;
+
+    event* triggerUpEventPtr;
+    event* triggerDownEventPtr;
+
+protected:
+    virtual bool checkForChange();
+    bool hasTriggerFunction;
+    bool reportUpdates;
+
+    int lastInState;
+    int thresh;
+    uint32_t lastChangeInterval;
+
+private:
+
+};
+
+class AnalogPort: public AbstractPort {
+public:
+    AnalogPort();
+
+    void init(sAnalogIn* IP);
+    void init(sAnalogOut* OP);
+
+    void set(int outVal);
+    int  read();
+    void setThresh(int threshVal);
+    void write(int outVal);
+
+private:
+    sAnalogOut* outPin;
+    sAnalogIn*  inPin;
+
+};
+
+class DigitalPort: public AbstractPort {
+public:
+    DigitalPort();
+
+    void init(sDigitalIn* IP);
+    void init(sDigitalOut* OP);
+
+    void set(int outVal);
+    int  read();
+    void write(int outVal);
+
+protected:
+    bool checkForChange();
+
+private:
+    sDigitalOut* outPin;
+    sDigitalIn*  inPin;
+
+};
+
 
 //The digitalPort object directly controls and keeps data about the port. Each port has
 //one digital out and one digital in.
@@ -98,6 +181,8 @@
 };
 
 
+
+
 //an intVariable contains an integer value and the name of that variable within the script
 class intVariable {
 
@@ -214,7 +299,7 @@
 
 };
 
-//portMessage is an action to change a digital port.  So far, You can only change the digital out (0 or 1)
+//portMessage is an action to change a port state.
 class portMessage {
 public:
 
@@ -222,7 +307,7 @@
     //portMessage(digitalPort* portIn, int whichToSet, int value); //whichToSet: 1 DigitalOut; 2 State
     //void setMessage(digitalPort* portIn, int whichToSet, int value); //whichToSet: 1 DigitalOut; 2 State
     //portMessage(int* portIn, int whichToSet, int value); //whichToSet:
-    void setMessage(int* portIn, int whichToSet, int value, digitalPort* portVector); //whichToSet:
+    void setMessage(int* portIn, int whichToSet, int value, AbstractPort** portVector, int portVectorLength); //whichToSet:
 
     void execute();
     void release();
@@ -232,8 +317,9 @@
     int whichToSet; //hard coded port number
     int* port; //alternative variable port number
     int value;
+    int vectorLength;
 
-    digitalPort* portVector;
+    AbstractPort** portVector;
 
 };
 
@@ -291,19 +377,19 @@
 
 public:
     intCompare();
-    intCompare(digitalPort* portInput, const char* cmpString, int cmpValInput, int whichToUse);
-    intCompare(digitalPort* portInput, const char* cmpString, int* cmpIntVarInput, int whichToUse);
+    intCompare(AbstractPort* portInput, const char* cmpString, int cmpValInput, int whichToUse);
+    intCompare(AbstractPort* 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);
+    intCompare(AbstractPort* 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(AbstractPort* portInput, const char* cmpString, int cmpValInput, int whichToUse);
+    void set(AbstractPort* 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 set(AbstractPort* portInput, const char* cmpString, intOperation* cmpIntOpInput, int whichToUse);
 
     void release();
 
@@ -312,7 +398,7 @@
     bool isUsed;
 
 private:
-    digitalPort* port;
+    AbstractPort* port;
     int* portValPtr;
     int* cmpVal;
     int* intVal;
@@ -480,7 +566,7 @@
 //Only the final line in a callback block should have a semicolon.
 class scriptStream {
 public:
-    scriptStream(digitalPort* portVectorInput, int numPortsInput, eventQueue* queueInput, sSystem* system);
+    scriptStream(AbstractPort** portVectorInput, int numPortsInput, eventQueue* queueInput, sSystem* system);
     void parseBlock(); //Parses everything since the last semicolon was found
     void addLineToCurrentBlock(char* lineInput); // if the line did not end with a semicolon, add it to the current block
 
@@ -531,12 +617,27 @@
     //vector<functionItem*> functionArray; //any blocks declared outsite callback blocks are stored here
     //list<string> currentBlock;
     blockBuffer currentBlock;
-    digitalPort* portVector;
     sSystem* system;
 
+    AbstractPort** portVector;
+    int numPorts;
 
+    AbstractPort* digInPortVector[NUMDIGINPORTS];
+    uint8_t digInLookup[NUMDIGINPORTS];
+    int numDigInPorts;
 
-    int numPorts;
+    AbstractPort* digOutPortVector[NUMDIGOUTPORTS];
+    uint8_t digOutLookup[NUMDIGOUTPORTS];
+    int numDigOutPorts;
+
+    AbstractPort* anInPortVector[NUMANINPORTS];
+    uint8_t anInLookup[NUMANINPORTS];
+    int numAnInPorts;
+
+    AbstractPort* anOutPortVector[NUMANOUTPORTS];
+    uint8_t anOutLookup[NUMANOUTPORTS];
+    int numAnOutPorts;
+
     eventQueue* queuePtr;
 
 };
@@ -558,8 +659,13 @@
     sSystem *hardware; //hardware interface
     sSerialPort *pc; //communication to computer
     char buffer[256];
-    digitalPort ports[NUMPORTS];
+    //digitalPort ports[NUMPORTS];
 
+    DigitalPort digInPorts[NUMDIGINPORTS];
+    DigitalPort digOutPorts[NUMDIGOUTPORTS];
+    AnalogPort anInPorts[NUMANINPORTS];
+    AnalogPort anOutPorts[NUMANOUTPORTS];
 
+    AbstractPort* ports[NUMDIGINPORTS+NUMDIGOUTPORTS+NUMANINPORTS+NUMANOUTPORTS];
 
 };
--- a/hardwareInterface.cpp	Fri Jun 10 21:22:34 2016 +0000
+++ b/hardwareInterface.cpp	Tue Feb 07 18:45:25 2017 +0000
@@ -33,7 +33,7 @@
 
 sSystem::sSystem() {
     for (int i=0;i<32;i++) {
-        ignorePortUpdates[i] = false;
+        ignorePortUpdates[i] = true; //by default, all digital port changes are not automatically reported.
     }
 }
 
@@ -65,6 +65,10 @@
 
 }
 
+void sSystem::reset() {
+
+}
+
 void sSystem::resumeInterrupts() {
 
 }
@@ -80,6 +84,16 @@
 uint32_t sSystem::getDigitalInputChangeFlags() {
 
 }
+//-----------------------------------------------------
+sAnalogOut::sAnalogOut() {
+
+}
+
+//------------------------------------------------------
+sAnalogIn::sAnalogIn() {
+
+}
+
 
 //------------------------------------------------------
 sDigitalOut::sDigitalOut() {
@@ -112,10 +126,10 @@
         //If we are currently checking this input, then we buffer the trigger and deal with it after
         if (newState == 0){
             bufferedDownEvent.timeStamp = timeStamp;
-            //bufferedDownEvent.triggered = true;
+            bufferedDownEvent.triggered = true;
         } else if (newState == 1) {
             bufferedUpEvent.timeStamp = timeStamp;
-            //bufferedUpEvent.triggered = true;
+            bufferedUpEvent.triggered = true;
         }
     }
     /*
--- a/hardwareInterface.h	Fri Jun 10 21:22:34 2016 +0000
+++ b/hardwareInterface.h	Tue Feb 07 18:45:25 2017 +0000
@@ -33,6 +33,34 @@
 
 };
 
+class sAnalogIn
+{
+public:
+    sAnalogIn();
+
+    virtual void init(int pin) = 0;
+    virtual int read() = 0;
+
+
+protected:
+
+
+};
+
+class sAnalogOut
+{
+public:
+    sAnalogOut();
+
+    virtual void init(int pin) = 0;
+    virtual void write(int value) = 0;
+    virtual int read() = 0;
+protected:
+
+};
+
+
+
 class sDigitalIn
 {
 public:
@@ -101,12 +129,15 @@
     virtual void setSlaveClock() = 0;
     virtual sDigitalOut* getDigitalOutPtr(int portNum) = 0;
     virtual sDigitalIn* getDigitalInPtr(int portNum) = 0;
+    virtual sAnalogOut* getAnalogOutPtr(int portNum) = 0;
+    virtual sAnalogIn* getAnalogInPtr(int portNum) = 0;
     virtual sSound* createNewSoundAction() = 0;
     virtual void externalClockReset() = 0; //needs to reset harware timer before calling immediateClockReset();
     virtual void incrementClock() = 0;
     virtual void mainLoopToDo();
     virtual void pauseInterrupts();
     virtual void resumeInterrupts();
+    virtual void reset();
     virtual int getPendingFunctionTriggers(uint16_t *bufferPtr); //Returns the number of pending shortcut triggers
     virtual uint32_t getDigitalOutputChangeFlags();
     virtual uint32_t getDigitalInputChangeFlags();
--- a/mbedInterface/mbedInterface.cpp	Fri Jun 10 21:22:34 2016 +0000
+++ b/mbedInterface/mbedInterface.cpp	Tue Feb 07 18:45:25 2017 +0000
@@ -134,10 +134,17 @@
 //---------------------------------------------------------------------
 
 //translate pin numbers to hardware pins
-PinName outPins[NUMOUTPORTS] = {p11,p13,p15,p18,p21,p23,p25,p29,p20,p6}; //Old board output pins
-//PinName outPins[NUMPORTS] = {p18,p15,p13,p11,p29,p25,p23,p21,p20}; //New board output pins
-PinName inPins[NUMINPORTS] = {p12,p14,p16,p17,p22,p24,p26,p30,p7};
+//PinName dOutPins[NUMDIGOUTPORTS] = {p11,p13,p15,p18,p21,p23,p25,p29,p20,p6}; //Old board output pins
 
+//PinName dOutPins[NUMDIGOUTPORTS] = {p18,p15,p13,p11,p29,p25,p23,p21,p20}; //New board output pins
+//PinName dInPins[NUMDIGINPORTS] = {p12,p14,p16,p17,p22,p24,p26,p30,p7};
+//PinName aInPins[NUMANINPORTS] = {};
+//PinName aOutPins[NUMANOUTPORTS] = {};
+
+PinName dOutPins[NUMDIGOUTPORTS] = {p7,p15,p13,p11,p29,p25,p23,p21}; //With analog pins
+PinName dInPins[NUMDIGINPORTS] = {p12,p14,p16,p17,p22,p24,p26,p30};
+PinName aInPins[NUMANINPORTS] = {p20};
+PinName aOutPins[NUMANOUTPORTS] = {p18};
 
 
 //The sound output uses a SmartWav device and their simple serial library
@@ -196,10 +203,19 @@
 
     //-------------------------------
 
-    for (int i=0; i < NUMPORTS; i++) {
+    for (int i=0; i < NUMDIGINPORTS; i++) {
         dIn[i].init(i);
+    }
+    for (int i=0; i < NUMDIGOUTPORTS; i++) {
         dOut[i].init(i);
     }
+    for (int i=0; i < NUMANINPORTS; i++) {
+        aIn[i].init(i);
+    }
+    for (int i=0; i < NUMANOUTPORTS; i++) {
+        aOut[i].init(i);
+    }
+
 
 
     sWav.reset();
@@ -263,7 +279,7 @@
 }
 
 sDigitalOut* MBEDSystem::getDigitalOutPtr(int portNum){
-    if (portNum < NUMPORTS) {
+    if (portNum < NUMDIGOUTPORTS) {
         return &dOut[portNum];
     } else {
         return NULL;
@@ -271,13 +287,29 @@
 }
 
 sDigitalIn* MBEDSystem::getDigitalInPtr(int portNum) {
-    if (portNum < NUMPORTS) {
+    if (portNum < NUMDIGINPORTS) {
         return &dIn[portNum];
     } else {
         return NULL;
     }
 }
 
+sAnalogOut* MBEDSystem::getAnalogOutPtr(int portNum){
+    if (portNum < NUMANOUTPORTS) {
+        return &aOut[portNum];
+    } else {
+        return NULL;
+    }
+}
+
+sAnalogIn* MBEDSystem::getAnalogInPtr(int portNum) {
+    if (portNum < NUMANINPORTS) {
+        return &aIn[portNum];
+    } else {
+        return NULL;
+    }
+}
+
 sSound* MBEDSystem::createNewSoundAction() {
     MBEDSound *tmpSound = new MBEDSound();
     return tmpSound;
@@ -374,13 +406,70 @@
 }
 
 //-----------------------------------------------------
+MBEDAnalogOut::MBEDAnalogOut() {
+
+}
+
+void MBEDAnalogOut::init(int pin) {
+    if (pin < NUMANOUTPORTS) {
+        outpin = new AnalogOut(aOutPins[pin]);
+        pinExists = true;
+    }
+}
+
+int MBEDAnalogOut::read() {
+
+    if (pinExists) {
+        return outpin->read()*3300.0; //read value is a fload between 0 and 1.0 (max voltage).  Convert to mV integer value.
+
+    } else {
+        return 0;
+    }
+
+}
+
+void MBEDAnalogOut::write(int value) {
+
+    if (pinExists) {
+
+        outpin->write((float)value / 3300.0);//should be a float input (percentage).  We convert from integer mV value.
+    }
+
+
+}
+//--------------------------------------------------------
+
+MBEDAnalogIn::MBEDAnalogIn() {
+
+}
+
+void MBEDAnalogIn::init(int pin) {
+
+    if (pin < NUMANINPORTS) {
+        inpin = new AnalogIn(aInPins[pin]);
+        pinExists = true;
+    }
+
+}
+
+int MBEDAnalogIn::read() {
+
+    if (pinExists) {
+        return inpin->read()*3300; //read value is a fload between 0 and 1.0 (max voltage).  Convert to mV integer value.
+    } else {
+        return 0;
+    }
+}
+
+
+//-----------------------------------------------------
 MBEDDigitalOut::MBEDDigitalOut() {
     pinExists = false;
 }
 
 void MBEDDigitalOut::init(int pin) {
-    if (pin < NUMOUTPORTS) {
-        outpin = new DigitalOut(outPins[pin]);
+    if (pin < NUMDIGOUTPORTS) {
+        outpin = new DigitalOut(dOutPins[pin]);
         pinExists = true;
     }
 }
@@ -407,9 +496,9 @@
 
 void MBEDDigitalIn::init(int pin) {
 
-    if (pin < NUMINPORTS) {
-        inpin = new DigitalIn(inPins[pin]);
-        inpin_interrupt = new InterruptIn(inPins[pin]);
+    if (pin < NUMDIGINPORTS) {
+        inpin = new DigitalIn(dInPins[pin]);
+        inpin_interrupt = new InterruptIn(dInPins[pin]);
         inpin->mode(PullDown);
         //Set up callbacks for the port interrupts
         inpin_interrupt->rise(this, &MBEDDigitalIn::interrupt_up_callback);
--- a/mbedInterface/mbedInterface.h	Fri Jun 10 21:22:34 2016 +0000
+++ b/mbedInterface/mbedInterface.h	Tue Feb 07 18:45:25 2017 +0000
@@ -15,9 +15,11 @@
 //#define MBED_RF
 
 
-#define NUMPORTS 10 //the number of ports available on this hardware
-#define NUMINPORTS 9
-#define NUMOUTPORTS 10
+//#define NUMPORTS 10 //the number of ports available on this hardware
+#define NUMDIGINPORTS 8
+#define NUMDIGOUTPORTS 8
+#define NUMANINPORTS 1
+#define NUMANOUTPORTS 1
 
 #define NUMEVENTS 50
 #define NUMCONDITIONS 150
@@ -52,7 +54,40 @@
 
 };*/
 
+class MBEDAnalogOut : public sAnalogOut
+{
+public:
+    MBEDAnalogOut();
 
+    void init(int pin);
+    void write(int value);
+    int read();
+
+private:
+    //define the hardware output pin
+    uint8_t pinNumber;
+    AnalogOut *outpin;
+    bool pinExists;
+
+};
+
+class MBEDAnalogIn : public sAnalogIn
+{
+public:
+    MBEDAnalogIn();
+
+    void init(int pin);
+    int read();
+
+protected:
+
+private:
+    uint8_t pinNumber;
+    AnalogIn *inpin;
+    bool pinExists;
+
+
+};
 
 class MBEDDigitalOut : public sDigitalOut
 {
@@ -126,6 +161,8 @@
     void setSlaveClock();
     sDigitalOut* getDigitalOutPtr(int portNum);
     sDigitalIn* getDigitalInPtr(int portNum);
+    sAnalogOut* getAnalogOutPtr(int portNum);
+    sAnalogIn* getAnalogInPtr(int portNum);
     sSound* createNewSoundAction();
     void pauseInterrupts();
     void resumeInterrupts();
@@ -140,8 +177,10 @@
     InterruptIn clockExternalIncrement;
 
 private:
-    MBEDDigitalIn dIn[NUMPORTS];
-    MBEDDigitalOut dOut[NUMPORTS];
+    MBEDDigitalIn dIn[NUMDIGINPORTS];
+    MBEDDigitalOut dOut[NUMDIGOUTPORTS];
+    MBEDAnalogIn aIn[NUMANINPORTS];
+    MBEDAnalogOut aOut[NUMANOUTPORTS];
 };
 
 #endif // MBEDINTERFACE_H