Component Test's Software to work with "Universal Controller Box" - Software is an interpreter or "compiler" for programs to be done with a .txt file and read off of the SD Card

Dependencies:   BridgeDriver FrontPanelButtons MCP23017 SDFileSystem TextLCD mbed

Files at this revision

API Documentation at this revision

Comitter:
mehatfie
Date:
Wed Oct 01 18:11:38 2014 +0000
Parent:
10:e8db892fbc52
Child:
12:2e3e86714243
Commit message:
- Latest revision is not a working copy, simply publishing all previous working copies to the server

Changed in this revision

BridgeDriver.lib Show annotated file Show diff for this revision Revisions of this file
Devices/CAN_Device.cpp Show annotated file Show diff for this revision Revisions of this file
Devices/CAN_Device.hpp Show annotated file Show diff for this revision Revisions of this file
Devices/Motor.cpp Show annotated file Show diff for this revision Revisions of this file
Devices/Motor.hpp Show annotated file Show diff for this revision Revisions of this file
Devices/PinIN.cpp Show annotated file Show diff for this revision Revisions of this file
Devices/PinIN.hpp Show annotated file Show diff for this revision Revisions of this file
Devices/TimerDevice.cpp Show annotated file Show diff for this revision Revisions of this file
Devices/TimerDevice.hpp Show annotated file Show diff for this revision Revisions of this file
Devices/VoltageDriver.cpp Show annotated file Show diff for this revision Revisions of this file
Devices/VoltageDriver.hpp Show annotated file Show diff for this revision Revisions of this file
Initialization.cpp Show annotated file Show diff for this revision Revisions of this file
Initialization.hpp Show annotated file Show diff for this revision Revisions of this file
TextFile.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/BridgeDriver.lib	Wed Sep 24 22:54:36 2014 +0000
+++ b/BridgeDriver.lib	Wed Oct 01 18:11:38 2014 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/jason701802/code/BridgeDriver/#397718f9300a
+http://developer.mbed.org/users/mehatfie/code/BridgeDriver/#397718f9300a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Devices/CAN_Device.cpp	Wed Oct 01 18:11:38 2014 +0000
@@ -0,0 +1,177 @@
+//#include "CAN_Device.hpp"
+//
+////Constructor
+//CAN_Device::CAN_Device(LineData lineData){
+//    
+//    //Order of Line: Command, Local_Name, CAN_DEVICE, selectedCAN(1,2), freq
+//    //Since we can't return from a constructor, instead we'll flip a flag, and check it after we've added the device in interpretCommand
+//    if (lineData.numWords != 5)
+//        this->errorFlag = 1;
+//        
+//    string channelstr = lineData.word[3], freqstr = lineData.word[4]; //Parameters are numbers
+//    int tempChannel = -1, tempFreq = -1;
+//    int numValuesFound = sscanf(channelstr.c_str(), "%d", &tempChannel);
+//    if (numValuesFound < 1)
+//        this->errorFlag = 1;
+//       
+//    numValuesFound = sscanf(freqstr.c_str(), "%d", &tempFreq);
+//    if (numValuesFound < 1)
+//        this->errorFlag = 1;
+//    
+//    //channel must be either CAN1 or CAN2
+//    if (tempChannel == 1 || tempChannel == 2){
+//                this->selectedCAN =  tempChannel;
+//    else
+//        this->errorFlag = 1;
+//         
+//    //should have a frequency greater than 0       
+//    if (tempFreq > 0)
+//        this->freq = tempFreq;
+//    else
+//        this->errorFlag = 1;
+//}
+//    
+//    
+//int CAN_Device::getSelectedCAN(){     
+//    return this->selectedCAN;
+//}
+//
+//int CAN_Device::getFreq(){     
+//    return this->freq;
+//}
+//
+////A line consists of [ __(Local_Name)__ __(function)__ __(parameter1)__ __(parameter2)__ __(parameter3)__ ... and so on]
+//int CAN_Device::CAN_Device(LineData &lineData){
+//
+//    //Order of Line: Local_Name, Function_Name, Param1, Param2, Param3,.......
+//    string func = lineData.word[1];
+//        
+//    /******************************************************************************/
+//    /***                       <Func: enableBrake>                              ***/
+//    /******************************************************************************/
+//    if (func.compare("write") == 0){
+//    //line looks like: Local_Name, write, ID_val, byte 
+//        if (lineData.numWords > 5){
+//            ErrorOut("Incorrect number of parameters", lineData.lineNumber);
+//            return -1;
+//        }
+//        
+//        //Initialize and Convert Parameters
+//        string enable = lineData.word[2];
+//        int enableValue = 0;
+//        
+//        int numValuesFound = sscanf(enable.c_str(), "%d", &enableValue);
+//        if (numValuesFound < 1){
+//            ErrorOut("Parameter Unknown, enableBrake value can't be converted", lineData.lineNumber);
+//            return -1;
+//        }
+//        
+//        //All syntax checking done by this point, if Dummy then return success in order to check the code, no need to perform functionality
+//        if (DummyMode)
+//            return 0; //Function operated successfully but doesn't return a value
+//            
+//        bridges.enableBraking(getMotor(), enableValue);
+//    }
+//        
+//    /******************************************************************************/
+//    /***                       <Func: forceBrake>                               ***/
+//    /******************************************************************************/
+//    else if (func.compare("forceBrake") == 0){
+//        
+//        if (lineData.numWords != 2){
+//            ErrorOut("Incorrect number of parameters", lineData.lineNumber);
+//            return -1;
+//        }
+//        
+//        //All syntax checking done by this point, if Dummy then return success in order to check the code, no need to perform functionality
+//        if (DummyMode)
+//            return 0; //Function operated successfully but doesn't return a value
+//            
+//        bridges.forceBrake(getMotor());
+//    }
+//    
+//    
+//    /******************************************************************************/
+//    /***                           <Func: drive>                                ***/
+//    /******************************************************************************/
+//    else if (func.compare("drive") == 0){
+//        
+//        if (lineData.numWords != 4){
+//            ErrorOut("Incorrect number of parameters", lineData.lineNumber);
+//            return -1;
+//        }
+//                
+//        //Initialize Parameters
+//        string speed = lineData.word[2];
+//        string dir = lineData.word[3];
+//        
+//        //Initialize Convertion Variables if needed
+//        float speedValue;
+//        int dirValue = 0;
+//        
+//        //Convert string to usable values
+//        int numValuesFound = sscanf(speed.c_str(), "%f", &speedValue);
+//        if (numValuesFound < 1){
+//            ErrorOut("Parameter Unknown, speed value can't be converted", lineData.lineNumber);
+//            return -1;
+//        }
+//        
+//        //Speed is given as a percentage of 100, so convert it to the value needed for the bridge.drive function
+//        speedValue = speedValue / 100;
+//        
+//        
+//        if (speedValue <= 0 && speedValue > 1.0){
+//            ErrorOut("Speed Value must be between 0 - 100", lineData.lineNumber);
+//            return -1;
+//        }
+//        
+//        if (dir.compare("CC") == 0 || dir.compare("cc") == 0)
+//            dirValue = -1; //Turn Clockwise
+//        else if (dir.compare("C") == 0 || dir.compare("c") == 0)
+//            dirValue = 1; //Turn CounterClockwise
+//            
+//        else{
+//            ErrorOut("Direction Value must be C or CC", lineData.lineNumber);
+//            return -1;
+//        }
+//        
+//        //All syntax checking done by this point, if Dummy then return success in order to check the code, no need to perform functionality
+//        if (DummyMode)
+//            return 0; //Function operated successfully but doesn't return a value
+//            
+//        bridges.drive(getMotor(), dirValue, speedValue); //Turn on the Motor
+//    }
+//    
+//    
+//    /******************************************************************************/
+//    /****                           <Func: off>                                ****/
+//    /******************************************************************************/
+//    else if (func.compare("off") == 0){
+//        
+//        if (lineData.numWords != 2){
+//            ErrorOut("Incorrect number of parameters", lineData.lineNumber);
+//            return -1;
+//        }
+//        
+//        //All syntax checking done by this point, if Dummy then return success in order to check the code, no need to perform functionality
+//        if (DummyMode)
+//            return 0; //Function operated successfully but doesn't return a value
+//            
+//        off();
+//    }
+//    
+//    else {
+//        ErrorOut("Unknown Command for Motor Class", lineData.lineNumber);
+//        return -1;
+//    }
+//    
+//    return 0; //Return success as 0 since no condition had to be met
+//}
+//
+//
+//
+////For stopping the entire system if an error occurs, can be called from main
+//int CAN_Device::off(void){
+//    bridges.drive(getMotor(), 0, 0); //Turn off the Motor
+//    return 0;
+//}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Devices/CAN_Device.hpp	Wed Oct 01 18:11:38 2014 +0000
@@ -0,0 +1,21 @@
+#ifndef CANDEVICE_HPP
+#define CANDEVICE_HPP
+
+#include "Initialization.hpp"
+
+class CAN_Device: public Device{
+    
+    private:
+        int selectedCAN;
+        int freq;
+        vector<CANMessage> messages;
+        
+    public:
+        CAN_Device(LineData);
+        int interpret(LineData&);
+        int off();
+        int getSelectedCAN();
+        int getFreq();
+};
+
+#endif  
\ No newline at end of file
--- a/Devices/Motor.cpp	Wed Sep 24 22:54:36 2014 +0000
+++ b/Devices/Motor.cpp	Wed Oct 01 18:11:38 2014 +0000
@@ -79,6 +79,10 @@
             return 0; //Function operated successfully but doesn't return a value
             
         bridges.forceBrake(getMotor());
+        
+        //Record the settings for Pause and Resume
+        currDir = 0;
+        currSpeed = 0;
     }
     
     
@@ -131,6 +135,10 @@
             return 0; //Function operated successfully but doesn't return a value
             
         bridges.drive(getMotor(), dirValue, speedValue); //Turn on the Motor
+        
+        //Record the settings for Pause and Resume
+        currDir = dirValue;
+        currSpeed = speedValue;
     }
     
     
@@ -164,75 +172,22 @@
 //For stopping the entire system if an error occurs, can be called from main
 int Motor::off(void){
     bridges.drive(getMotor(), 0, 0); //Turn off the Motor
+    
+    //Record the settings for Pause and Resume, and exit
+    currDir = 0;
+    currSpeed = 0;
     return 0;
 }
 
 
-/*
-int Motor::enableBrake(){
-  
-    if (lineData.numWords != 4){
-         //Error Check, incorrect number of parameter, error out
-        return 0;
-    }
-    
-    //Initialize and Convert Parameters
-    char *enable = lineData.word[2];
-    int enableValue = atoi(enable);
-    
-    //If the atoi returned anything besides 0, it worked properly
-    if (enableValue) 
-        bridges.enableBraking(getMotor(), enableValue);
-    else{
-         //Error Check, incorrect number of parameter, error out
-        return 0;
-    }
-    
-    return 1;
+//Stop the motor without changing the previous known settings, so that it will be saved on resume
+int Motor::pause(void){
+    bridges.drive(getMotor(), 0, 0); //Turn off the Motor
+    return 0;
 }
 
-int Motor::forceBrake(){
-
-    if (lineData.numWords != 3){
-         //Error Check, incorrect number of parameter, error out
-        return 0;
-    }
-    
-    bridges.forceBrake(getMotor());
+//Resume the motor using its previously known settings
+int Motor::resume(void){
+    bridges.drive(getMotor(), this->currDir, this->currSpeed); //Resume Motor from it's last known state
+    return 0;
 }
-    
-int Motor::drive(){
-        
-            if (lineData.numWords != 4){
-                 //Error Check, incorrect number of parameter, error out
-                return 0;
-            }
-                        
-            //Initialize Parameters
-            char *speed = lineData.word[2];
-            char *dir = lineData.word[3];
-            
-            //Initialize Convertion Variables if needed
-            float speedValue;
-            int dirValue = 0;
-    
-            //Convert string to usable values
-            //NOTE both atof and atoi functions return 0 if no valid conversion could be performed
-            speedValue = atof(speed) / 100;
-            
-            if (speedValue <= 0)
-                return 0; //Error Out because a value gives no functionality or is wrong
-            
-            if (strncmp(dir,"CC", 2) == 0 || strncmp(dir,"cc", 2) == 0)
-                dirValue = -1; //Turn Clockwise
-            else if (strncmp(dir,"C", 1) == 0 || strncmp(dir,"c", 1) == 0)
-                dirValue = 1; //Turn CounterClockwise
-            else
-                return 0; //Error Out since the parameter is incorrect
-                
-            bridges.drive(getMotor(), dirValue, speedValue); //Turn on the Motor
-}    
-*/
-
-
-        
\ No newline at end of file
--- a/Devices/Motor.hpp	Wed Sep 24 22:54:36 2014 +0000
+++ b/Devices/Motor.hpp	Wed Oct 01 18:11:38 2014 +0000
@@ -6,13 +6,16 @@
 class Motor: public Device{
     
     private:
-        enum BridgeDriver::Motors motor;
-        
+        enum BridgeDriver::Motors motor;    //Keeps track of which Motor Enum the Motor was initialized to
+        int currDir;                        //Keeps track of what the current direction of the motor is
+        float currSpeed;                    //Keeps track of what the current speed of the motor is
     public:
         Motor(LineData);
         int interpret(LineData&);
         int off();
         enum BridgeDriver::Motors getMotor();
+        int pause();
+        int resume();
         //void enableBrake();
         //int forceBrake();
         //int forceFloat();
--- a/Devices/PinIN.cpp	Wed Sep 24 22:54:36 2014 +0000
+++ b/Devices/PinIN.cpp	Wed Oct 01 18:11:38 2014 +0000
@@ -143,8 +143,19 @@
             return 0; //Function operated successfully but doesn't return a value
             
         //Return one if value meets the wanted pin value, return 0 if it doesn't
-        if(signal.read() == checkValue_Value)
-            return 1;
+        if(signal.read() == checkValue_Value){
+            //Debounce check to ensure the value is still correct, if incorrect after debounce time, return 0, since it's a false truth
+            if (signal.read() == checkValue_Value){
+                Timer debounceTimer;
+                debounceTimer.reset();
+                debounceTimer.start();
+                while (debounceTimer.read_ms() < 40);
+                if (signal.read() == checkValue_Value)
+                    return 1;
+                else
+                    return 0;
+            }
+        }
         else
             return 0;
     }
@@ -156,8 +167,3 @@
             
     return 0; //Return success as 0 since no condition had to be met
 }
-
-int PinIN::off(void){
-    //Do Nothing as you don't need to turn a Pin off
-    return 0;
-}
\ No newline at end of file
--- a/Devices/PinIN.hpp	Wed Sep 24 22:54:36 2014 +0000
+++ b/Devices/PinIN.hpp	Wed Oct 01 18:11:38 2014 +0000
@@ -12,7 +12,9 @@
     public:
         PinIN(LineData);
         int interpret(LineData&);
-        int off();
+        int off(){return 0;}        //Do Nothing as you don't need to turn a Pin off
+        int pause(){return 0;}      //Do Nothing as you don't need to pause a Pin
+        int resume(){return 0;}     //Do Nothing as you don't need to resume a Pin
 };
 
 #endif  
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Devices/TimerDevice.cpp	Wed Oct 01 18:11:38 2014 +0000
@@ -0,0 +1,146 @@
+#include "TimerDevice.hpp"
+
+//Constructor
+TimerDevice::TimerDevice(LineData lineData){
+    //No Constructor needed... functionality already exists in mBed library
+}
+
+
+//A line consists of [ __(Local_Name)__ __(function)__ __(parameter1)__ __(parameter2)__ __(parameter3)__ ... and so on]
+int TimerDevice::interpret(LineData &lineData){
+
+
+            
+    //Order of line: local_name, function_name, param1, param2, param3,.......
+    string func = lineData.word[1];
+
+    /******************************************************************************/
+    /***                          <func: start>                                 ***/
+    /******************************************************************************/
+    if (func.compare("start") == 0){
+        
+        if (lineData.numWords != 2){
+            ErrorOut("Incorrect number of parameters", lineData.lineNumber);
+            return -1;
+        }
+        
+        //All syntax checking done by this point, if Dummy then return success in order to check the code, no need to perform functionality
+        if (DummyMode)
+            return 0; //Function operated successfully but doesn't return a value
+            
+        this->Timer.start();
+    }
+    
+    
+    /******************************************************************************/
+    /***                           <func: stop>                                 ***/
+    /******************************************************************************/
+    else if (func.compare("stop") == 0){
+    
+        if (lineData.numWords != 2){
+            ErrorOut("Incorrect number of parameters", lineData.lineNumber);
+            return -1;
+        }
+        
+        //All syntax checking done by this point, if Dummy then return success in order to check the code, no need to perform functionality
+        if (DummyMode)
+            return 0; //Function operated successfully but doesn't return a value
+            
+        this->Timer.stop();
+    }
+    
+    /******************************************************************************/
+    /***                          <func: reset>                                 ***/
+    /******************************************************************************/
+    else if (func.compare("reset") == 0){
+  
+        if (lineData.numWords != 2){
+            ErrorOut("Incorrect number of parameters", lineData.lineNumber);
+            return -1;
+        }
+
+        //All syntax checking done by this point, if Dummy then return success in order to check the code, no need to perform functionality
+        if (DummyMode)
+            return 0; //Function operated successfully but doesn't return a value
+              
+        this->Timer.stop();
+        this->Timer.reset();            
+        this->Timer.start();
+    }
+    
+    /******************************************************************************/
+    /****                           <func: val>                                ****/
+    /******************************************************************************/
+    else if (func.compare("val") == 0){
+
+        //line looks like: local_name, val, comparison_characteristics (<, >, =)
+        if (lineData.numWords != 4){
+            ErrorOut("Incorrect number of parameters", lineData.lineNumber);
+            return -1;
+        }
+        
+        string cmpChar = lineData.word[2];  //Get the comparison characteristic value
+        
+        string timestr = lineData.word[3];  //Parameter is a number
+        int timeValue = 0;                  //Time value to compare in ms
+        int numValuesFound = sscanf(timestr.c_str(), "%d", &timeValue);
+        if (numValuesFound < 1){
+            ErrorOut("Parameter Unknown,  time value can't be converted", lineData.lineNumber);
+            return -1;
+        }
+
+        //Error check comparision characteristic
+        if (cmpChar.compare("<") != 0 && cmpChar.compare(">") != 0 && cmpChar.compare("=") != 0){
+            ErrorOut("Parameter Unknown,  comparison character can't be converted", lineData.lineNumber);
+            return -1;
+        }
+
+        //All syntax checking done by this point, if Dummy then return success in order to check the code, no need to perform functionality
+        if (DummyMode)
+            return 0; //Function operated successfully but doesn't return a value
+            
+        if (cmpChar.compare("<") == 0){
+            if (this->Timer.read_ms() < timeValue)
+                return 1; //met condition
+        }
+        else if (cmpChar.compare(">") == 0){
+            if (this->Timer.read_ms() > timeValue)
+                return 1; //met condition
+        }
+        else if (cmpChar.compare("=") == 0){
+            if (this->Timer.read_ms() == timeValue)
+                return 1; //met condition
+        }
+        
+    }
+    
+    
+    else {
+        ErrorOut("Unknown Command for Voltage Driver Class", lineData.lineNumber);
+        return -1;
+    }  
+            
+    return 0; //Return success as 0 since no condition had to be met
+}
+
+
+//For stopping the entire system if an error occurs, can be called from main
+int TimerDevice::off(void){
+    this->Timer.stop();
+    return 0;
+}
+
+
+//Pause the timer
+int TimerDevice::pause(void){
+    this->Timer.stop();
+    return 0;
+}
+
+//Resume the timer
+int TimerDevice::resume(void){
+    this->Timer.start();
+    return 0;
+}
+
+        
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Devices/TimerDevice.hpp	Wed Oct 01 18:11:38 2014 +0000
@@ -0,0 +1,24 @@
+#ifndef TIMERDEVICE_HPP
+#define TIMERDEVICE_HPP
+
+#include "Initialization.hpp"
+
+class TimerDevice: public Device{
+    
+    private:
+        Timer Timer;
+        
+    public:
+        TimerDevice(LineData);
+        int interpret(LineData&);
+        int off();
+        int getChannel();
+        int pause();
+        int resume();
+        //void enableBrake();
+        //int forceBrake();
+        //int forceFloat();
+        //float drive();
+};
+
+#endif
\ No newline at end of file
--- a/Devices/VoltageDriver.cpp	Wed Sep 24 22:54:36 2014 +0000
+++ b/Devices/VoltageDriver.cpp	Wed Oct 01 18:11:38 2014 +0000
@@ -1,7 +1,4 @@
 #include "VoltageDriver.hpp"
-//#include "mbed.h"
-//#include "LocalPinNames.h"
-//#include "BridgeDriver.h"
 
 //Constructor
 VoltageDriver::VoltageDriver(LineData lineData){
@@ -51,7 +48,7 @@
 
 //A line consists of [ __(Local_Name)__ __(function)__ __(parameter1)__ __(parameter2)__ __(parameter3)__ ... and so on]
 int VoltageDriver::interpret(LineData &lineData){
-               
+
     //Order of line: local_name, function_name, param1, param2, param3,.......
     string func = lineData.word[1];
                
@@ -70,6 +67,9 @@
             return 0; //Function operated successfully but doesn't return a value
             
         bridges.forceBrake(channel);
+        
+        //Record the settings for Pause and Resume
+        currState = 0;
     }
     
     
@@ -78,17 +78,20 @@
     /******************************************************************************/
     else if (func.compare("drive") == 0){
         //order of line: local_name, drive
-    
+
         if (lineData.numWords != 2){
             ErrorOut("Incorrect number of parameters", lineData.lineNumber);
             return -1;
         }
-        
+
         //All syntax checking done by this point, if Dummy then return success in order to check the code, no need to perform functionality
         if (DummyMode)
             return 0; //Function operated successfully but doesn't return a value
-               
+ 
         bridges.drive(channel, 1); //turn channel on
+
+        //Record the settings for Pause and Resume
+        currState = 1;
     }
     
     
@@ -122,6 +125,23 @@
 //For stopping the entire system if an error occurs, can be called from main
 int VoltageDriver::off(void){
     bridges.drive(getChannel(), 0); //turn channel off
+    
+    //Record the settings for Pause and Resume, and exit
+    currState = 0;
     return 0;
 }
 
+
+//Stop the driver without changing the previous known settings, so that it will be saved on resume
+int VoltageDriver::pause(void){
+    bridges.drive(getChannel(), 0); //turn channel off
+    return 0;
+}
+
+//Resume the driver using its previously known settings
+int VoltageDriver::resume(void){
+    bridges.drive(getChannel(), this->currState); //turn channel off
+    return 0;
+}
+
+        
--- a/Devices/VoltageDriver.hpp	Wed Sep 24 22:54:36 2014 +0000
+++ b/Devices/VoltageDriver.hpp	Wed Oct 01 18:11:38 2014 +0000
@@ -7,12 +7,15 @@
     
     private:
         int channel;
+        int currState;
         
     public:
         VoltageDriver(LineData);
         int interpret(LineData&);
         int off();
         int getChannel();
+        int pause();
+        int resume();
         //void enableBrake();
         //int forceBrake();
         //int forceFloat();
--- a/Initialization.cpp	Wed Sep 24 22:54:36 2014 +0000
+++ b/Initialization.cpp	Wed Oct 01 18:11:38 2014 +0000
@@ -2,6 +2,7 @@
 #include "Motor.hpp"
 #include "VoltageDriver.hpp"
 #include "PinIN.hpp"
+#include "TimerDevice.hpp"
 
 
 /**********************************************************************************************************************************/
@@ -12,7 +13,7 @@
 
 // ADD YOUR DEVICE NAME THE \\EXACT SAME WAY\\ AS THE ENUM NAME YOU DECLARED IN THE.hpp
 // Must Declare names in reverse order for some reason...., it's the way they're indexed I believe
-const string DeviceNames[] = {"MOTOR", "VOLTAGE_DRIVER", "PIN_IN"}; 
+const string DeviceNames[] = {"MOTOR", "VOLTAGE_DRIVER", "PIN_IN", "TIMER_DEVICE", "CAN_DEVICE"}; 
 
 // ADD YOUR DEVICE TO THE LIST BELOW, CALLING YOUR DEVICE CLASS AS SHOWN
 Device* Device::newDevice(int deviceFound, string _name, LineData lineData){
@@ -21,6 +22,7 @@
         case MOTOR:           return new Motor(lineData);          break;
         case VOLTAGE_DRIVER:  return new VoltageDriver(lineData);  break;
         case PIN_IN:          return new PinIN(lineData);          break;
+        case TIMER_DEVICE:    return new TimerDevice(lineData);    break;
         
         //**********  ADD NEXT DEVICE ABOVE  **************//
         default:  break;
@@ -46,8 +48,15 @@
 
 DigitalIn killSw(KILL);
 
+//Ticker errorWatcher;
+
 const int MAX_LINE_LENGTH = 100;
 int DummyMode = 0; // run through the code without performing actions
+FILE *selectedFile;
+int errorFLAG = 0;
+
+vector<GoToLabel> GoToLabels; //Initialize vector of struct for GoTo Labels
+CycleWatch cycleWatch;
 
 /******************************************************************************/
 /***                     <Function Initializations>                         ***/
@@ -57,6 +66,10 @@
     
     killSw.mode(PullUp);
     initLCD();     
+    
+    //Initialize the Error Watcher Interrupt / Ticker
+    //errorWatcher.attach(&ErrorMonitor, 0.5);
+    
 }
  
 void initLCD(void) {
@@ -87,4 +100,48 @@
 int numDevices = sizeof(DeviceNames)/sizeof(DeviceNames[0]);
 int currNumDevices = 0;
 
-vector<Device*> devices; //create a vector to hold all of the devices
\ No newline at end of file
+vector<Device*> devices; //create a vector to hold all of the devices
+
+
+/******************************************************************************/
+/***                   <Error Monitor Initializations>                      ***/
+/******************************************************************************/
+
+//vector<ErrorCondition> errorMonitors; //Initialize vector of errors to monitor
+//ErrorCondition errorMonitors[15];
+//int numErrorMonitors = 0;
+/*
+//Monitors the conditions to watch for erroring, and pauses system if any of the conditions turn out to be true
+void ErrorMonitor(){ 
+    
+    int i = 0, error = -1, numError = 0;
+    for(i = 0; i < errorMonitors.size(); i++){
+        int checkCondition = 0;
+        checkCondition = interpretCommand(errorMonitors[i].errorToWatch);
+        
+        //if Condition is true, that means the error occurred
+        if (checkCondition == 1){
+            numError++;
+            
+            //if the error has a Fix / Reset command, do it
+            if (errorMonitors[i].hasFix){
+                int returnValue;
+                interpretCommand(errorMonitors[i].errorFix); //Fix / Reset the error based on how the user justified to do so
+            }
+                
+            error = i; //Record index of error, will display only one error, but error will be last error that was true in the list
+        }
+    }
+    
+    if (numError){
+        char errorMsg[100] = "Error Occurred!!!   Item: ";
+        strcat(errorMsg, errorMonitors[error].errorToWatch.word[0].c_str()); //Send the first word of the error condition to help find out what the error was
+        ErrorOut(errorMsg, numError);
+        errorFLAG = 1; //set error flag equal to 1 if error occurred
+    }
+    else
+        errorFLAG = 0; //set error flag equal to 0 if no errors occurred
+        
+}
+*/
+
--- a/Initialization.hpp	Wed Sep 24 22:54:36 2014 +0000
+++ b/Initialization.hpp	Wed Oct 01 18:11:38 2014 +0000
@@ -17,8 +17,8 @@
 /**********************************************************************************************************************************/
 /**********************************************************************************************************************************/
 
-enum  DeviceType{MOTOR, VOLTAGE_DRIVER, PIN_IN};                                //ADD DEVICE NAME
-static const enum DeviceType Device_Map[] = {MOTOR, VOLTAGE_DRIVER, PIN_IN};    //AND HERE ***NOTE TO KEEP SAME ORDER
+enum  DeviceType{MOTOR, VOLTAGE_DRIVER, PIN_IN, TIMER_DEVICE, CAN_DEVICE};                                //ADD DEVICE NAME
+static const enum DeviceType Device_Map[] = {MOTOR, VOLTAGE_DRIVER, PIN_IN, TIMER_DEVICE, CAN_DEVICE};    //AND HERE ***NOTE TO KEEP SAME ORDER
 
 /**************************                              <MUST MODIFY>                                    *************************/
 /**********************************************************************************************************************************/
@@ -39,8 +39,25 @@
 
 extern DigitalIn killSw;
 
+//extern Ticker errorWatcher;
+
 extern const int MAX_LINE_LENGTH;
 extern int DummyMode;
+extern FILE *selectedFile;
+extern int errorFLAG;
+
+/******************************************************************************/
+/***                 <Line Data Struct Initializations>                     ***/
+/******************************************************************************/
+
+struct LineData{
+    
+    int lineNumber;     //current line number in the program txt file that is running
+    string word[50];    //array of words from the line of text, assuming no more than 50 words will be in any given line
+                        //in this initialization there are 15 string (pointers) of size MAX_LINE_LENGTH each
+    int numWords;       //Number of words in the given line
+    int lineAddress;    //current line address in the SD Card
+};
 
 /******************************************************************************/
 /***                     <Function Initializations>                         ***/
@@ -52,25 +69,38 @@
 
 void ErrorOut(string, int); //Outputs error message, line number, and formatting to LCD
 
+int cyclePrograms(vector<string>, int, int, int);
+
+void resetLineData(LineData &); //reset and all variables of the Line Data Struct
+
+int interpretCommand(LineData &);
+
+int loopCommand(LineData &);
+
 /******************************************************************************/
-/***                 <Line Data Struct Initializations>                     ***/
+/***                     <GoTo Label Initializations>                       ***/
 /******************************************************************************/
 
-struct LineData{
-    
-    //string fullLine;          //full line, starting from the beginning
-    int lineNumber;             //current line number in the program txt file that is running
-    //vector<string> word;
-    string word[50];            //array of words from the line of text, assuming no more than 50 words will be in any given line
-                                //in this initialization there are 15 string (pointers) of size MAX_LINE_LENGTH each
-    int numWords;               //Number of words in the given line
-    int lineAddress;
+struct GoToLabel{
+
+    string name;        //name of the GoTo Label
+    int lineNumber;     //line number of the GoTo Label
+    int lineAddress;    //line address of the GoTo Label
 };
 
-//
-//extern struct Line lineData;
+extern vector<GoToLabel> GoToLabels;
 
 
+/******************************************************************************/
+/***                   <Cycle Struct Initializations>                       ***/
+/******************************************************************************/
+
+struct CycleWatch{
+
+    int numCycles;          //number of cycles to go to
+    int startAddress;       //starting address to seek back to on loop
+    int startLineNumber;    //starting line number to reset to
+};
 
 /******************************************************************************/
 /***              <Parent Device Class Initializations>                     ***/
@@ -90,9 +120,27 @@
         static Device* newDevice(int, string, LineData);
         virtual int interpret(LineData&) = 0;
         virtual int off() = 0;
+        virtual int pause() = 0;
+        virtual int resume() = 0;
 };
 
-extern vector<Device*> devices; //Initialize array of devices, initially assume 15 devices will be used (will expand as needed)
+extern vector<Device*> devices; //Initialize vector of devices
 
 
+/******************************************************************************/
+/***                   <Error Monitor Initializations>                      ***/
+/******************************************************************************/
+/*
+struct ErrorCondition{
+    
+    LineData errorToWatch;
+    LineData errorFix;    
+    int hasFix;
+};
+
+//extern vector<ErrorCondition> errorMonitors; //Initialize vector of errors to monitor
+extern ErrorCondition errorMonitors[15];
+extern int numErrorMonitors;*/
+//void ErrorMonitor(); //Monitors the conditions to watch for erroring, and pauses system if any of the conditions turn out to be true
+
 #endif
\ No newline at end of file
--- a/TextFile.h	Wed Sep 24 22:54:36 2014 +0000
+++ b/TextFile.h	Wed Oct 01 18:11:38 2014 +0000
@@ -61,8 +61,7 @@
     
     //Cycle through all files listed in the directoy (strings in the vector list)
     int n = 0;
-    for(vector<string>::iterator it=filenames.begin(); it < filenames.end(); it++)  
-    {
+    for(vector<string>::iterator it=filenames.begin(); it < filenames.end(); it++){
         
         vector<string> fileName; //filename[0] = filename, filename[1] = extension
 
@@ -92,39 +91,47 @@
 
 int getNextLine(FILE *selectedFile, LineData &lineData) {
     
-    lineData.lineAddress = ftell(selectedFile);
-    
-    if (lineData.lineAddress == -1L){
-        ErrorOut("Unable to get address of line, SD Card Removed?", lineData.lineNumber + 1);
-        return -1;
-    }
-    
-    //char *newLine;
-    //getline(selectedFile, newLine);
-    char newLine[MAX_LINE_LENGTH];
-    
-    fgets(newLine, MAX_LINE_LENGTH, selectedFile);
+    int validLine = 0;
+    while (!validLine){
+            
+        lineData.lineAddress = ftell(selectedFile);
+        
+        if (lineData.lineAddress == -1L){
+            ErrorOut("Unable to get address of line, SD Card Removed?", lineData.lineNumber + 1);
+            return -1;
+        }
+        
+        //char *newLine;
+        //getline(selectedFile, newLine);
+        char newLine[MAX_LINE_LENGTH];
+        
+        fgets(newLine, MAX_LINE_LENGTH, selectedFile);
+        
+        if (newLine == NULL){
+            ErrorOut("Unable to get the next line, SD Card Removed?", lineData.lineNumber + 1);
+            return -1;
+        }
+        
+        lineData.lineNumber++; // new line successfully found, increase lineNumber      
+        
+        //pull out each individual word (separated by any white space), and place it in the vector
+        stringstream newLineStrm(newLine);    
+        istream_iterator<string> it(newLineStrm);
+        istream_iterator<string> end;
+        vector<string> results(it, end);
+        
+        //Get the size of the results vector, if it is 0 then while loop will loop again,
+        //if it has a value, then it will accept the line and end looping cycles
+        validLine = results.size();
     
-    if (newLine == NULL){
-        ErrorOut("Unable to get the next line, SD Card Removed?", lineData.lineNumber + 1);
-        return -1;
+        //copy the vector of results into the array of words
+        copy(results.begin(), results.end(), lineData.word);
+        
+        lineData.numWords = results.size(); //Record the number of words in the line
+        
+        results.erase(results.begin(), results.end()); //remove the results vector from memory
     }
     
-    lineData.lineNumber++; // new line successfully found, increase lineNumber      
-    
-    //pull out each individual word (separated by any white space), and place it in the vector
-    stringstream newLineStrm(newLine);    
-    istream_iterator<string> it(newLineStrm);
-    istream_iterator<string> end;
-    vector<string> results(it, end);
-    
-    //copy the vector of results into the array of words
-    copy(results.begin(), results.end(), lineData.word);
-    
-    lineData.numWords = results.size(); //Record the number of words in the line
-    
-    results.erase(results.begin(), results.end()); //remove the results vector from memory
-    
     //Update the Current Line Number
     lcd.setAddress(0,2);
     lcd.printf("Current Line#: %d ", lineData.lineNumber);
@@ -134,7 +141,7 @@
     lcd.printf("                    "); // Clear the Line using Spaces (Emptyness) - Note one line is 20 Characters
     lcd.setAddress(0,3);
     lcd.printf("cmd/dvc: %s", lineData.word[0]);
-    
+
     /*
     lcd.cls(); //clear the display   
     lcd.setAddress(0,0);
@@ -145,7 +152,7 @@
     lcd.printf("wrd3: %s", lineData.word[2]);
     lcd.setAddress(0,3);
     lcd.printf("wrd4: %s", lineData.word[3]);
-    wait(2);*/
+    wait(1);*/
 }
 
 
--- a/main.cpp	Wed Sep 24 22:54:36 2014 +0000
+++ b/main.cpp	Wed Oct 01 18:11:38 2014 +0000
@@ -18,14 +18,6 @@
 
 //extern "C" void mbed_reset(); //enable software reset of code
 
-    
-int cyclePrograms(vector<string>, int, int, int);
-
-void resetLineData(LineData &); //reset and all variables of the Line Data Struct
-
-int interpretCommand(FILE *, LineData &);
-
-int loopCommand(FILE *, LineData &);
 
 /******************************************************************************/
 /***                      <Function: resetLineData>                         ***/
@@ -66,8 +58,10 @@
     }
 
     //Output file on Display 
+    lcd.setAddress(0,0);
+    lcd.printf("                    "); // Clear the Line using Spaces (Emptyness) - Note one line is 20 Characters
     lcd.setAddress(0,3);
-    lcd.printf("                   "); // Clear the Line using Spaces (Emptyness) - Note one line is 20 Characters
+    lcd.printf("                    "); // Clear the Line using Spaces (Emptyness) - Note one line is 20 Characters
     wait(.2);
     lcd.setAddress(0,3);
     lcd.printf("%s", files[nextIndex]);
@@ -94,9 +88,8 @@
 int conditionCommand(FILE *selectedFile, LineData &lineData){
                 
     //Initialize variables    
-    LineData param[15];
+    LineData param[15]; // assume no more than 15 conditions will be needed
     vector<ConditionOp> paramCondition;
- 
     
     //Fill the param Vector with Line structs of each individual device, this way we can send the Line struct to the appropriate interpret function without modification within the function itself
     //this line reads: Condition, data_for_param1, CONDTITION_OP1, data_for_param2, CONDTITION_OP2, data_for_param3......
@@ -114,11 +107,17 @@
             
             //if this is the last word in the line....
             if(i == (lineData.numWords - 1)){
+
                 param[numParam].numWords = paramNumWords;
+                
+                //if numParam = 0 at this point, it means there's only one condition to check... need to add a member to the vector since none have been added yet
+                if (numParam == 0)
+                    paramCondition.push_back(ConditionOp());
+                    
                 paramCondition[numParam].op = NONE;
+
                 numParam++;
-            }
-            
+            }            
         }
             
         // if the word is an AND or an OR, it must mean the last function has been completely identified
@@ -143,12 +142,12 @@
         }    
     }
     
-    
+        
     //send the data parameters in order to get them interpreted by the appropriate device
     //if the value it's checking for meets the criteria you want, the device should return 1, if it doesn't meet the criteria the device should return 0
     int j = 0, k = 0;
     for (j = 0; j < numParam; j++){
-        paramCondition[j].value = interpretCommand(selectedFile, param[j]);
+        paramCondition[j].value = interpretCommand(param[j]);
         
         //error out if the interpretted command returned an error
         if (paramCondition[j].value == -1)
@@ -167,124 +166,134 @@
         if (k == numParam - 1)
             last = 1;
             
-       if (!last){
-            if (paramCondition[k].op != xAND && paramCondition[k].op != xOR && paramCondition[k + 1].op != xAND && paramCondition[k + 1].op != xOR){
-                //AND
-                if (paramCondition[k].op == AND){
-                    if (!first && prevCondition != xAND && prevCondition != xOR)
-                        combinedCondition.back().value = combinedCondition.back().value && paramCondition[k + 1].value;
-                    else if (first || prevCondition == xAND || prevCondition == xOR){
-                        tempCombinedCondition.value = paramCondition[k].value && paramCondition[k + 1].value; 
-                        combinedCondition.push_back(tempCombinedCondition);
-                        first = 0;
-                    }    
-                    prevCondition = AND;
+        //Only one condition to check
+        if (numParam == 1){
+            tempCombinedCondition.value = paramCondition[k].value;
+            tempCombinedCondition.op = NONE; 
+            combinedCondition.push_back(tempCombinedCondition);        
+        }
+        
+        else{
+            if (!last){
+                if (paramCondition[k].op != xAND && paramCondition[k].op != xOR && paramCondition[k + 1].op != xAND && paramCondition[k + 1].op != xOR){
+                    //AND
+                    if (paramCondition[k].op == AND){
+                        if (!first && prevCondition != xAND && prevCondition != xOR)
+                            combinedCondition.back().value = combinedCondition.back().value && paramCondition[k + 1].value;
+                        else if (first || prevCondition == xAND || prevCondition == xOR){
+                            tempCombinedCondition.value = paramCondition[k].value && paramCondition[k + 1].value; 
+                            combinedCondition.push_back(tempCombinedCondition);
+                            first = 0;
+                        }    
+                        prevCondition = AND;
+                    }
+                    
+                    //OR
+                    else if (paramCondition[k].op == OR){
+                        if (!first && prevCondition != xAND && prevCondition != xOR)
+                            combinedCondition.back().value = combinedCondition.back().value || paramCondition[k + 1].value;
+                        else if (first || prevCondition == xAND || prevCondition == xOR){
+                            tempCombinedCondition.value = paramCondition[k].value || paramCondition[k + 1].value; 
+                            combinedCondition.push_back(tempCombinedCondition);
+                            first = 0;
+                        }    
+                        prevCondition = OR;
+                    }
                 }
                 
-                //OR
-                else if (paramCondition[k].op == OR){
-                    if (!first && prevCondition != xAND && prevCondition != xOR)
-                        combinedCondition.back().value = combinedCondition.back().value || paramCondition[k + 1].value;
-                    else if (first || prevCondition == xAND || prevCondition == xOR){
-                        tempCombinedCondition.value = paramCondition[k].value || paramCondition[k + 1].value; 
-                        combinedCondition.push_back(tempCombinedCondition);
-                        first = 0;
-                    }    
-                    prevCondition = OR;
+                // first value is something, not exclusive, but next values are exclusive
+                else if (first && (paramCondition[k].op == AND || paramCondition[k].op == OR) && (paramCondition[k + 1].op == xAND || paramCondition[k + 1].op == xOR)){
+                    tempCombinedCondition.value = paramCondition[k].value;
+                    tempCombinedCondition.op = paramCondition[k].op;
+                    combinedCondition.push_back(tempCombinedCondition);
+                    prevCondition = paramCondition[k].op;
+                    first = 0;
                 }
-            }
-            
-            // first value is something, not exclusive, but next values are exclusive
-            else if (first && (paramCondition[k].op == AND || paramCondition[k].op == OR) && (paramCondition[k + 1].op == xAND || paramCondition[k + 1].op == xOR)){
-                tempCombinedCondition.value = paramCondition[k].value;
-                tempCombinedCondition.op = paramCondition[k].op;
-                combinedCondition.push_back(tempCombinedCondition);
-                prevCondition = paramCondition[k].op;
-                first = 0;
-            }
-            
-            else{   
-                //xAND
-                if (paramCondition[k].op == xAND){
-                    if (combinedCondition.size() == 0){ // No values so start a new combinedCondition
-                        tempCombinedCondition.value = paramCondition[k].value && paramCondition[k + 1].value;
-                        tempCombinedCondition.op = xAND;
-                        combinedCondition.push_back(tempCombinedCondition);
-                        prevCondition = xAND;
-                    }
-                    else{
-                         if (combinedCondition.back().op == xAND){ // AND the value to the back most combinedCondition
-                            combinedCondition.back().value = combinedCondition.back().value && paramCondition[k + 1].value;
-                            prevCondition = xAND;
-                        }
-                        else if (combinedCondition.back().op != xAND){ // Start a new combinedCondition
-                            tempCombinedCondition.value = paramCondition[k].value && paramCondition[k + 1].value; 
+                
+                else{   
+                    //xAND
+                    if (paramCondition[k].op == xAND){
+                        if (combinedCondition.size() == 0){ // No values so start a new combinedCondition
+                            tempCombinedCondition.value = paramCondition[k].value && paramCondition[k + 1].value;
                             tempCombinedCondition.op = xAND;
                             combinedCondition.push_back(tempCombinedCondition);
                             prevCondition = xAND;
                         }
+                        else{
+                             if (combinedCondition.back().op == xAND){ // AND the value to the back most combinedCondition
+                                combinedCondition.back().value = combinedCondition.back().value && paramCondition[k + 1].value;
+                                prevCondition = xAND;
+                            }
+                            else if (combinedCondition.back().op != xAND){ // Start a new combinedCondition
+                                tempCombinedCondition.value = paramCondition[k].value && paramCondition[k + 1].value; 
+                                tempCombinedCondition.op = xAND;
+                                combinedCondition.push_back(tempCombinedCondition);
+                                prevCondition = xAND;
+                            }
+                        }
+                            
                     }
-                        
-                }
-                
-                //xOR
-                else if (paramCondition[k].op == xOR){
-                    if (combinedCondition.size() == 0){ // No values so start a new combinedCondition
-                        tempCombinedCondition.value = paramCondition[k].value || paramCondition[k + 1].value; 
-                        tempCombinedCondition.op = xOR;
-                        combinedCondition.push_back(tempCombinedCondition);
-                        prevCondition = xOR;
-                    }
-                    else{
-                         if (combinedCondition.back().op == xOR){ // OR the value to the back most combinedCondition
-                            combinedCondition.back().value = combinedCondition.back().value || paramCondition[k + 1].value;
-                            prevCondition = xOR;
-                        }
-                        else if (combinedCondition.back().op != xOR){ // Start a new combinedCondition
+                    
+                    //xOR
+                    else if (paramCondition[k].op == xOR){
+                        if (combinedCondition.size() == 0){ // No values so start a new combinedCondition
                             tempCombinedCondition.value = paramCondition[k].value || paramCondition[k + 1].value; 
                             tempCombinedCondition.op = xOR;
                             combinedCondition.push_back(tempCombinedCondition);
                             prevCondition = xOR;
                         }
+                        else{
+                             if (combinedCondition.back().op == xOR){ // OR the value to the back most combinedCondition
+                                combinedCondition.back().value = combinedCondition.back().value || paramCondition[k + 1].value;
+                                prevCondition = xOR;
+                            }
+                            else if (combinedCondition.back().op != xOR){ // Start a new combinedCondition
+                                tempCombinedCondition.value = paramCondition[k].value || paramCondition[k + 1].value; 
+                                tempCombinedCondition.op = xOR;
+                                combinedCondition.push_back(tempCombinedCondition);
+                                prevCondition = xOR;
+                            }
+                        }
+                            
                     }
-                        
-                }
-                
-                // Since the k + 1 value is included in the xAND or xOR exclusively, skip checking that value, and add the appropriate AND / OR as the
-                // operator of this exclusive xAND / xOR set
-                if ((paramCondition[k + 1].op == AND || paramCondition[k + 1].op == OR) && (prevCondition == xAND || prevCondition == xOR)){
-                    combinedCondition.back().op = paramCondition[k + 1].op;
-                    k++;
+                    
+                    // Since the k + 1 value is included in the xAND or xOR exclusively, skip checking that value, and add the appropriate AND / OR as the
+                    // operator of this exclusive xAND / xOR set
+                    if ((paramCondition[k + 1].op == AND || paramCondition[k + 1].op == OR) && (prevCondition == xAND || prevCondition == xOR)){
+                        combinedCondition.back().op = paramCondition[k + 1].op;
+                        k++;
+                    }
+                    
                 }
-                
-            }
-       }
+           }            
             
-        
-        // the last value was not included in any combination, since directly before the last value was an xAND / xOR set that
-        // included the very last AND / OR as the set's operator, yet there is still another value that has not been combined, as it is supposed
-        // to be AND /OR to the exclusive xAND / xOR set
-        else if (last && (prevCondition == xAND || prevCondition == xOR) && (combinedCondition.back().op == AND || combinedCondition.back().op == OR)){
-            tempCombinedCondition.value = paramCondition[k].value;
-            tempCombinedCondition.op = NONE; 
-            combinedCondition.push_back(tempCombinedCondition);
+            // the last value was not included in any combination, since directly before the last value was an xAND / xOR set that
+            // included the very last AND / OR as the set's operator, yet there is still another value that has not been combined, as it is supposed
+            // to be AND /OR to the exclusive xAND / xOR set
+            else if (last && (prevCondition == xAND || prevCondition == xOR) && (combinedCondition.back().op == AND || combinedCondition.back().op == OR)){
+                tempCombinedCondition.value = paramCondition[k].value;
+                tempCombinedCondition.op = NONE; 
+                combinedCondition.push_back(tempCombinedCondition);
+            }
         }
         
         //reset the tempCombinedCondition variable
         tempCombinedCondition = ConditionOp();
     }
         
+          
                 
     // run through all values in the combined Condition vector, AND'ing / OR'ing as appropriate
     // in the end, the last value in the array should be the final condition of the Condition statement... whether it was successful or failed
-    for (i = 0; i < (combinedCondition.size() - 1); i++){
-        if (combinedCondition[i].op == AND)
-            combinedCondition[i + 1].value = combinedCondition[i].value && combinedCondition[i + 1].value;
-        else if (combinedCondition[i].op == OR)
-            combinedCondition[i + 1].value = combinedCondition[i].value || combinedCondition[i + 1].value;
+    if (numParam > 1){
+        for (i = 0; i < (combinedCondition.size() - 1); i++){
+            if (combinedCondition[i].op == AND)
+                combinedCondition[i + 1].value = combinedCondition[i].value && combinedCondition[i + 1].value;
+            else if (combinedCondition[i].op == OR)
+                combinedCondition[i + 1].value = combinedCondition[i].value || combinedCondition[i + 1].value;
+        }
     }
     
-    
     //All syntax checking done by this point, if Dummy then return success in order to check the code within the Condition
     if (DummyMode)
         return 0; //Function operated successfully but doesn't return a value
@@ -305,7 +314,7 @@
             
             // check if the first word is an end command (avoids interpreting functions that perform actions)
             if (lineData.word[0].compare("end") == 0)   
-                checkEnd = interpretCommand(selectedFile, lineData);
+                checkEnd = interpretCommand(lineData);
         
             if (checkEnd == 4) // custom return value for this function
                 return 0; //Function operated successfully but doesn't return a value
@@ -319,60 +328,132 @@
     // the program will proceed from the line after the "end condition" line
     return 0; //Function operated successfully but doesn't return a value
 }      
-   
+
 
+   cycleWatch
 /**********************************************************************************************************************************/
 /**********************************************************************************************************************************/
-/**************************                        <FUNCTION: loopCommand>                            *****************************/
+/**************************                       <FUNCTION: cycleCommand>                            *****************************/
 /**********************************************************************************************************************************/
 /**********************************************************************************************************************************/
 
-int loopCommand(FILE *selectedFile, LineData &lineData){
-        
+int loopCommand(LineData &lineData){
+    
+    int thisLoopMain = 0;
+    if (mainLoopFlag == 0){
+        thisLoopMain = 1;
+        mainLoopFlag = 1;
+    }
+    
     //Get the Condition value for number of times to loop
     string loopCondition = lineData.word[1];
     int loopConditionValue = 0;
+    int loopConditionState = 0; //State 1 = device condtition, State 2 = numerical condition
     
-    int numValuesFound = sscanf(loopCondition.c_str(), "%d", &loopConditionValue);
-    if (numValuesFound < 1){
-        ErrorOut("Parameter Unknown, loopCondition Value can't be converted", lineData.lineNumber);
-        return -1;
+    LineData conditionLine;
+    //if the loop is supposed to happen under specific device conditions
+    if (loopCondition.compare("condition") == 0){
+                
+        loopConditionState = 1;
+        
+        //extract the command condition to be checked each loop
+        int i = 2, funcNumWords = 0;
+        for(i = 2; i < lineData.numWords; i++){
+            conditionLine.word[funcNumWords] = lineData.word[i];
+            funcNumWords++;
+        }
+
+        conditionLine.numWords = funcNumWords;
+        conditionLine.lineAddress = lineData.lineAddress;
+        conditionLine.lineNumber = lineData.lineNumber;  
     }
     
+    //if the second word isn't condition, it means it's a number
+    else{
+        loopConditionState = 2;
+        
+        int numValuesFound = sscanf(loopCondition.c_str(), "%d", &loopConditionValue);
+        if (numValuesFound < 1){
+            ErrorOut("Parameter Unknown, loopCondition Value can't be converted", lineData.lineNumber);
+            return -1;
+        }
+        
+        //loop condition must be greater than 0
+        if (loopConditionValue <= 0){
+            ErrorOut("Loop Condition must be greater than 0", lineData.lineNumber);
+            return -1;
+        }
+    }
+    
+
     int loopStartAddress = 0, loopLineNumber = 0, firstLineOfLoop = 1;
         
-    lcd.setAddress(0,0);
-    lcd.printf("Cycle 1 of %d", loopConditionValue);
-        
+    if (thisLoopMain){
+        lcd.setAddress(0,0);
+        lcd.printf("Cycle 1 of %d", loopConditionValue);
+    }
+    
     float totalLoopTime = 0;
     Timer cycleTimer;
     cycleTimer.reset();
     cycleTimer.start();
        
-    int counter = 1, checkEnd = 0, returnValue;
-    while (counter <= loopConditionValue){
+    int counter = 1, checkEnd = 0, returnValue, conditionMet = 0;
+    
+
+    //Before starting the loop, get the state of the device conditions
+    if (loopConditionState == 1){
+        conditionMet = interpretCommand(conditionLine);
+        if (conditionMet == -1)
+            return -1; //if the interpretCommand returned an error, then error out
+            
+        //condition met, so skip to end of loop
+        if (conditionMet == 1){
+            int checkEnd = 0, returnValue = 0;
+            while (checkEnd != 3){
+            
+            returnValue = getNextLine(selectedFile, lineData);
+            
+            //if getNextLine returned an error, then error out
+            if (returnValue == -1)
+                return -1;
+            
+            // check if the first word is an end command (avoids interpreting functions that perform actions)
+            if (lineData.word[0].compare("end") == 0)   
+                checkEnd = interpretCommand(lineData);
+        
+            if (checkEnd == 4) // custom return value for this function
+                return 0; //Function operated successfully but doesn't return a value
+            else if (checkEnd == -1) //if interpretCommand returned an error, then error out
+                return -1;
+            }
+        }
+    }
+
+    
+    while (!conditionMet){
         
         returnValue = getNextLine(selectedFile, lineData); 
-        
+
         //if getNextLine returned an error, then return error out
         if (returnValue == -1)
             return -1;
-                
+
         //Must get the address before entering the interpret command
         // if a Condition command is immediately after, and the condition fails, then
         // the interpret command will return the line at the "end condition" line, and therefore
         // set the loop's first line to be the "end condition" line, if interpretCommand is called BEFORE setting the first loop line address
-        if (firstLineOfLoop){
+        if (firstLineOfLoop){               
             loopStartAddress = lineData.lineAddress; //Save the Line Address
             loopLineNumber = lineData.lineNumber;    //Save the Line Number
             firstLineOfLoop = 0;
         }
-           
-        checkEnd = interpretCommand(selectedFile, lineData);
+
+        checkEnd = interpretCommand(lineData);
 
         //Increase the loop counter and go back to the beginning of the loop
         if (checkEnd == 3){
-            
+
             //All syntax checking done by this point, if Dummy then return success in order to check the code, no need to loop again
             if (DummyMode)
                 return 0; //Function operated successfully but doesn't return a value
@@ -380,32 +461,259 @@
             //Output the Avg Cycle Time
             cycleTimer.stop(); 
             totalLoopTime += cycleTimer.read();
-            
-            lcd.setAddress(0,1);
-            lcd.printf("Avg t(sec): %1.3f", (totalLoopTime / counter));
-            
-            //Output Cycle Number
-            counter++;
-            lcd.setAddress(0,0);
-            lcd.printf("Cycle %d of %d", counter, loopConditionValue);
-            
-            int seekFailure = fseek(selectedFile, loopStartAddress, SEEK_SET); //fseek returns 0 on success
-            if (seekFailure){
-                ErrorOut("In Loop      Failed to seek line", lineData.lineNumber); //Spaces make it look nice on the LCD
-                return -1;
+                  
+                /*  lcd.setAddress(0,2);
+                lcd.printf("TEST: %d", thisLoopMain);
+                wait(2);*/
+                
+            //if (thisLoopMain == 1){
+                
+                lcd.setAddress(0,1);
+                lcd.printf("Avg t(sec): %1.3f", (totalLoopTime / counter));
+                
+                //Output Cycle Number
+                counter++;
+                lcd.setAddress(0,0);
+                lcd.printf("Cycle %d of %d", counter, loopConditionValue);
+                wait(2);
+            //}
+               
+               
+            //Check whether the we should stop looping based on the state that the loop is based on (device conditional / numerical conditional)
+            if (loopConditionState == 1){
+                conditionMet = interpretCommand(conditionLine);
+                if (conditionMet == -1)
+                    return -1; //if the interpretCommand returned an error, then error out
+            }
+            else if (loopConditionState == 2){                
+                if (counter >= loopConditionValue)
+                     conditionMet = 1;
             }
             
+            //if the condition has not been met, then seek back to the beginning of the loop
+            if (!conditionMet){
+                int seekFailure = fseek(selectedFile, loopStartAddress, SEEK_SET); //fseek returns 0 on success
+                if (seekFailure){
+                    ErrorOut("In Loop      Failed to seek line", lineData.lineNumber); //Spaces make it look nice on the LCD
+                    return -1;
+                }
+            }
+
             lineData.lineNumber = loopLineNumber - 1;
             checkEnd = 0;
-            
+        
             //Restart the timer for the next loop
             cycleTimer.reset();
             cycleTimer.start();
+    
         }
-        else if (checkEnd == -1) //if interpretCommand returned an error, then return error out
+        else if (checkEnd == -1){ //if interpretCommand returned an error, then return error out
                 return -1;
+        }
     }
+      
+      
+    //give the "main loop" classification up to the next loop that wants it
+    if (thisLoopMain == 1){
+        thisLoopMain = 0;
+        mainLoopFlag = 0;
+    }
+    
+    return 0; //Return Success, no value is being sent so don't return 1
+ }   
+ 
+ 
+ 
+/**********************************************************************************************************************************/
+/**********************************************************************************************************************************/
+/**************************                        <FUNCTION: loopCommand>                            *****************************/
+/**********************************************************************************************************************************/
+/**********************************************************************************************************************************/
+
+int mainLoopFlag = 0; //so that we only show cycle count for the main loop
+
+int loopCommand(LineData &lineData){
+    
+    int thisLoopMain = 0;
+    if (mainLoopFlag == 0){
+        thisLoopMain = 1;
+        mainLoopFlag = 1;
+    }
+    
+    //Get the Condition value for number of times to loop
+    string loopCondition = lineData.word[1];
+    int loopConditionValue = 0;
+    int loopConditionState = 0; //State 1 = device condtition, State 2 = numerical condition
+    
+    LineData conditionLine;
+    //if the loop is supposed to happen under specific device conditions
+    if (loopCondition.compare("condition") == 0){
                 
+        loopConditionState = 1;
+        
+        //extract the command condition to be checked each loop
+        int i = 2, funcNumWords = 0;
+        for(i = 2; i < lineData.numWords; i++){
+            conditionLine.word[funcNumWords] = lineData.word[i];
+            funcNumWords++;
+        }
+
+        conditionLine.numWords = funcNumWords;
+        conditionLine.lineAddress = lineData.lineAddress;
+        conditionLine.lineNumber = lineData.lineNumber;  
+    }
+    
+    //if the second word isn't condition, it means it's a number
+    else{
+        loopConditionState = 2;
+        
+        int numValuesFound = sscanf(loopCondition.c_str(), "%d", &loopConditionValue);
+        if (numValuesFound < 1){
+            ErrorOut("Parameter Unknown, loopCondition Value can't be converted", lineData.lineNumber);
+            return -1;
+        }
+        
+        //loop condition must be greater than 0
+        if (loopConditionValue <= 0){
+            ErrorOut("Loop Condition must be greater than 0", lineData.lineNumber);
+            return -1;
+        }
+    }
+    
+
+    int loopStartAddress = 0, loopLineNumber = 0, firstLineOfLoop = 1;
+        
+    if (thisLoopMain){
+        lcd.setAddress(0,0);
+        lcd.printf("Cycle 1 of %d", loopConditionValue);
+    }
+    
+    float totalLoopTime = 0;
+    Timer cycleTimer;
+    cycleTimer.reset();
+    cycleTimer.start();
+       
+    int counter = 1, checkEnd = 0, returnValue, conditionMet = 0;
+    
+
+    //Before starting the loop, get the state of the device conditions
+    if (loopConditionState == 1){
+        conditionMet = interpretCommand(conditionLine);
+        if (conditionMet == -1)
+            return -1; //if the interpretCommand returned an error, then error out
+            
+        //condition met, so skip to end of loop
+        if (conditionMet == 1){
+            int checkEnd = 0, returnValue = 0;
+            while (checkEnd != 3){
+            
+            returnValue = getNextLine(selectedFile, lineData);
+            
+            //if getNextLine returned an error, then error out
+            if (returnValue == -1)
+                return -1;
+            
+            // check if the first word is an end command (avoids interpreting functions that perform actions)
+            if (lineData.word[0].compare("end") == 0)   
+                checkEnd = interpretCommand(lineData);
+        
+            if (checkEnd == 4) // custom return value for this function
+                return 0; //Function operated successfully but doesn't return a value
+            else if (checkEnd == -1) //if interpretCommand returned an error, then error out
+                return -1;
+            }
+        }
+    }
+
+    
+    while (!conditionMet){
+        
+        returnValue = getNextLine(selectedFile, lineData); 
+
+        //if getNextLine returned an error, then return error out
+        if (returnValue == -1)
+            return -1;
+
+        //Must get the address before entering the interpret command
+        // if a Condition command is immediately after, and the condition fails, then
+        // the interpret command will return the line at the "end condition" line, and therefore
+        // set the loop's first line to be the "end condition" line, if interpretCommand is called BEFORE setting the first loop line address
+        if (firstLineOfLoop){               
+            loopStartAddress = lineData.lineAddress; //Save the Line Address
+            loopLineNumber = lineData.lineNumber;    //Save the Line Number
+            firstLineOfLoop = 0;
+        }
+
+        checkEnd = interpretCommand(lineData);
+
+        //Increase the loop counter and go back to the beginning of the loop
+        if (checkEnd == 3){
+
+            //All syntax checking done by this point, if Dummy then return success in order to check the code, no need to loop again
+            if (DummyMode)
+                return 0; //Function operated successfully but doesn't return a value
+                
+            //Output the Avg Cycle Time
+            cycleTimer.stop(); 
+            totalLoopTime += cycleTimer.read();
+                  
+                /*  lcd.setAddress(0,2);
+                lcd.printf("TEST: %d", thisLoopMain);
+                wait(2);*/
+                
+            //if (thisLoopMain == 1){
+                
+                lcd.setAddress(0,1);
+                lcd.printf("Avg t(sec): %1.3f", (totalLoopTime / counter));
+                
+                //Output Cycle Number
+                counter++;
+                lcd.setAddress(0,0);
+                lcd.printf("Cycle %d of %d", counter, loopConditionValue);
+                wait(2);
+            //}
+               
+               
+            //Check whether the we should stop looping based on the state that the loop is based on (device conditional / numerical conditional)
+            if (loopConditionState == 1){
+                conditionMet = interpretCommand(conditionLine);
+                if (conditionMet == -1)
+                    return -1; //if the interpretCommand returned an error, then error out
+            }
+            else if (loopConditionState == 2){                
+                if (counter >= loopConditionValue)
+                     conditionMet = 1;
+            }
+            
+            //if the condition has not been met, then seek back to the beginning of the loop
+            if (!conditionMet){
+                int seekFailure = fseek(selectedFile, loopStartAddress, SEEK_SET); //fseek returns 0 on success
+                if (seekFailure){
+                    ErrorOut("In Loop      Failed to seek line", lineData.lineNumber); //Spaces make it look nice on the LCD
+                    return -1;
+                }
+            }
+
+            lineData.lineNumber = loopLineNumber - 1;
+            checkEnd = 0;
+        
+            //Restart the timer for the next loop
+            cycleTimer.reset();
+            cycleTimer.start();
+    
+        }
+        else if (checkEnd == -1){ //if interpretCommand returned an error, then return error out
+                return -1;
+        }
+    }
+      
+      
+    //give the "main loop" classification up to the next loop that wants it
+    if (thisLoopMain == 1){
+        thisLoopMain = 0;
+        mainLoopFlag = 0;
+    }
+    
     return 0; //Return Success, no value is being sent so don't return 1
  }   
 
@@ -415,8 +723,83 @@
 /**********************************************************************************************************************************/
 /**********************************************************************************************************************************/
 
-int interpretCommand(FILE *selectedFile, LineData &lineData){
+int interprettingErrorFlag = 0;
+
+class ErrorCondition{
+    
+    public:
+        LineData errorToWatch;
+        LineData errorFix;    
+        int hasFix;
+};
+
+//vector<ErrorCondition> errorMonitors; //Initialize vector of errors to monitor
+ErrorCondition errorMonitors[5];
+int numErrorsConditions = 0;
+
+
+int interpretCommand(LineData &lineData){
+
+    //Monitors the conditions to watch for erroring, and pauses system if any of the conditions turn out to be true
+    if (!interprettingErrorFlag){
+        int j = 0, error = -1, numError = 0;
+        for(j = 0; j < numErrorsConditions; j++){
+            int checkCondition = 0;
+            
+            interprettingErrorFlag = 1;   
+            checkCondition = interpretCommand(errorMonitors[j].errorToWatch);
+            interprettingErrorFlag = 0;
+
+            //if Condition is true, that means the error occurred
+            if (checkCondition == 1){
+                numError++;
+
+                //if the error has a Fix / Reset command, do it
+                if (errorMonitors[j].hasFix){
+                    int returnValue;
+                    interprettingErrorFlag = 1;
+                    returnValue = interpretCommand(errorMonitors[j].errorFix); //Fix / Reset the error based on how the user justified to do so
+                    interprettingErrorFlag = 0;
+                    if (returnValue == -1)
+                        return -1;
+                }
+                    
+                error = j; //Record index of error, will display only one error, but error will be last error that was true in the list
+            }
+            
+            else if (checkCondition == -1)
+                return -1;
+        }
+      
+        if (numError){
+            char errorMsg[100] = "ERROR!!!       Item: ";
+            strcat(errorMsg, errorMonitors[error].errorToWatch.word[0].c_str()); //Send the first word of the error condition to help find out what the error was
+            ErrorOut(errorMsg, numError);
+            //errorFLAG = 1; //set error flag equal to 1 if error occurred
+
+            //place all devices into the pause functionality
+            int i = 0;
+            for(i = 0; i < devices.size(); i++)
+                devices[i]->pause();
+            
+            //LCD has already been adjusted with the ErrorMonitor function
+            //Simply wait for the user to press select in order to acknowledge the issue and try to fix it
+            while(!buttons.readSel());
+
+            //place all devices into the resume functionality
+            for(i = 0; i < devices.size(); i++)
+                devices[i]->resume();
+            
+            lcd.cls(); //clear the display  
+        }
+    }
+
         
+    
+    /******************************************************************************/
+    /***                        <Functionality: device>                         ***/
+    /******************************************************************************/
+    
     if (lineData.word[0].compare("device") == 0){
 
         int i = 0, deviceFound = -1;
@@ -445,12 +828,85 @@
         }
     }
     
+    
+    
+    /******************************************************************************/
+    /***                     <Functionality: errorWatch>                        ***/
+    /******************************************************************************/
+
+    else if (lineData.word[0].compare("errorWatch") == 0){
+        //line looks like: error, _Condition_, FIX(?), _Command_
+        //create a temp LineData variable to store the correct information of the error Condition (discluding the first "error" keyword  
+        ErrorCondition tempError;
+        LineData tempLine;
+ 
+        int i = 1, funcNumWords = 0;
+        for (i = 1; i < lineData.numWords; i++){    
+            
+            //if the keyword FIX is not this word, than add it to the LineData
+            if (lineData.word[i].compare("FIX") != 0){
+                tempLine.word[funcNumWords] = lineData.word[i];  
+                funcNumWords++;   
+            }     
+            
+            //if the keyword FIX was found, this means there's a FIX / Reset command if the specified error being monitored occurs
+            else if (lineData.word[i].compare("FIX") == 0){
+                tempError.hasFix = 1;
+                
+                //Save the line as the "Error to Watch" value
+                tempLine.numWords = funcNumWords;
+                tempLine.lineAddress = lineData.lineAddress;
+                tempLine.lineNumber = lineData.lineNumber;
+                tempError.errorToWatch = tempLine;
+                
+                //reset lineData and num words for the command / function in order to process the FIX command into the error condition
+                funcNumWords = 0;
+                tempLine = LineData(); //reset tempLine
+            }                
+        }
+        
+        //if the error has a fix, it means that it already process the "Error to Watch" but needs to process the "Error Fix" into the error condition
+        if (tempError.hasFix){
+            //Save the line as the "Error Fix" value
+            tempLine.numWords = funcNumWords;
+            tempLine.lineAddress = lineData.lineAddress;
+            tempLine.lineNumber = lineData.lineNumber;
+            tempError.errorFix = tempLine;
+        }
+        
+        //if the error does not have a fix, that means it still has to process the "Error to Watch" into the error condition
+        else{
+            //Save the line as the "Error to Watch" value
+            tempLine.numWords = funcNumWords;
+            tempLine.lineAddress = lineData.lineAddress;
+            tempLine.lineNumber = lineData.lineNumber;
+            tempError.errorToWatch = tempLine;
+        }
+
+        //if DummyMode, send error Condition to the interpretCommand so that we can check the syntax
+        if (DummyMode){
+            int returnValue1 = interpretCommand(tempError.errorToWatch);
+            int returnValue2 = interpretCommand(tempError.errorFix);
+            if (returnValue1 == -1 || returnValue2 == -1)
+                return -1;
+        }
+  
+        errorMonitors[numErrorsConditions] = tempError;
+        numErrorsConditions++;
+    }
+    
+    
+    /******************************************************************************/
+    /***                        <Functionality: delay>                          ***/
+    /******************************************************************************/
+    
     else if (lineData.word[0].compare("delay") == 0){
         
-        //All syntax checking done by this point, if Dummy then return success in order to check the code, no need wait for a delay
-        if (DummyMode)
-            return 0; //Function operated successfully but doesn't return a value
-            
+        if (lineData.numWords != 2){
+            ErrorOut("Incorrect number of parameters", lineData.lineNumber);
+            return -1;
+        }
+        
         string duration = lineData.word[1];
         int durationValue = 0;
         int numValuesFound = sscanf(duration.c_str(), "%d", &durationValue);
@@ -461,23 +917,139 @@
         }
         
         if (durationValue > 0){
+            
+            //All syntax checking done by this point, if Dummy then return success in order to check the code, no need wait for a delay
+            if (DummyMode)
+                return 0; //Function operated successfully but doesn't return a value
+            
             timer.reset();
             timer.start();
             while (timer.read_ms() < durationValue); //Do Nothing while the timer has not reached the duration
             timer.stop(); //Stop the Timer
         }
         else{
-            ErrorOut("Duration value is less than 0", lineData.lineNumber);
+            ErrorOut("Duration value is less than or equal to 0", lineData.lineNumber);
             return -1;
         }
     }
     
+    /******************************************************************************/
+    /***                        <Functionality: pause>                          ***/
+    /******************************************************************************/
+    
+    else if (lineData.word[0].compare("pause") == 0){
+        
+        if (lineData.numWords != 1){
+            ErrorOut("Incorrect number of parameters", lineData.lineNumber);
+            return -1;
+        }
+        
+        lcd.cls(); //clear the display
+        lcd.setAddress(0,0);
+        lcd.printf("System Pause");
+        lcd.setAddress(0,2);
+        lcd.printf("Line Number: %d", lineData.lineNumber);
+        lcd.setAddress(0,3);
+        lcd.printf("Press Sel to Resume");
+        while(!buttons.readSel());
+    }
+    
+    /******************************************************************************/
+    /***                         <Functionality: GoTo>                          ***/
+    /******************************************************************************/
+    
+    else if (lineData.word[0].compare("GoTo") == 0){
+        
+        if (lineData.word[1].compare("label") == 0){
+            
+            if (lineData.numWords != 3){
+                ErrorOut("Incorrect number of parameters", lineData.lineNumber);
+                return -1;
+            }
+        
+            int labelExists = 0;
+            for(vector<GoToLabel>::iterator it=GoToLabels.begin(); it < GoToLabels.end(); it++){
+                if (lineData.word[1].compare((*it).name) == 0)
+                    labelExists = 1;
+            }
+
+            //if the label does not exist then add it to the vector
+            //if it turned out to exist then do nothing
+            if (!labelExists){
+                GoToLabel tempLabel;
+                tempLabel.name = lineData.word[2];              //Save the Label Name
+                tempLabel.lineAddress = lineData.lineAddress;   //Save the Line Address
+                tempLabel.lineNumber = lineData.lineNumber;     //Save the Line Number
+                GoToLabels.push_back(tempLabel);
+            }
+        }
+        
+        //if the second word was not "label," then it means the word should correspond to an already created GoTo Label
+        else{
+            
+            if (lineData.numWords != 2){
+                ErrorOut("Incorrect number of parameters", lineData.lineNumber);
+                return -1;
+            }  
+            
+            //All syntax checking done by this point, if Dummy then return success in order to check the code
+            //Unable to continue further checking since an aspect of DummyMode run through is to collect the GoTo Label Locations
+            //so that we have them in address
+            if (DummyMode)
+                return 0; //Function operated successfully but doesn't return a value
+                    
+            int i = 0, labelFound = -1;
+            for(i = 0; i < GoToLabels.size(); i++){
+                if (lineData.word[1].compare(GoToLabels[i].name) == 0){
+                    labelFound = i;
+                }
+            }
+            
+            //if the label was not found then error out
+            if (labelFound == -1){
+                ErrorOut("No label     match found in the  system", lineData.lineNumber); //Spaces make it look nice on LCD
+                return -1;   
+            }
+            
+            //if the label was found, then seek to that GoTo position
+            else{
+                                    
+                int seekFailure = fseek(selectedFile, GoToLabels[labelFound].lineAddress, SEEK_SET); //fseek returns 0 on success
+                if (seekFailure){
+                    ErrorOut("In Loop      Failed to seek line", lineData.lineNumber); //Spaces make it look nice on the LCD
+                    return -1;
+                }
+
+                lineData.lineNumber = GoToLabels[labelFound].lineNumber - 1; //set the lineNumber value                
+            }
+        }
+    }
+    
+    /******************************************************************************/
+    /***                         <Functionality: loop>                          ***/
+    /******************************************************************************/
+    
     else if (lineData.word[0].compare("loop") == 0)
-        return loopCommand(selectedFile, lineData); //Process the loop command and return the value that it returns
+        return loopCommand(lineData); //Process the loop command and return the value that it returns
+       
        
+    /******************************************************************************/
+    /***                     <Functionality: condition>                         ***/
+    /******************************************************************************/
     else if (lineData.word[0].compare("condition") == 0)
        return conditionCommand(selectedFile, lineData); //Process the condition command and return the value that it returns
 
+
+    /******************************************************************************/
+    /***                       <Functionality: cycle>                           ***/
+    /******************************************************************************/
+    else if (lineData.word[0].compare("cycle") == 0)
+       return cycleCommand(selectedFile, lineData, 1); //Sending 1 means it's initializing
+       
+       
+    /******************************************************************************/
+    /***                         <Functionality: end>                           ***/
+    /******************************************************************************/
     //end has custom return value for specific functions, since "end" is a common keyword amongst functions
     else if (lineData.word[0].compare("end") == 0){
         if (lineData.word[1].compare("program") == 0)
@@ -486,6 +1058,10 @@
             return 3;
         else if (lineData.word[1].compare("condition") == 0)
             return 4;
+        else if (lineData.word[1].compare("cycle") == 0){
+            checkCycle(selectedFile, lineData, 0) //Sending 0 means it's checking for the ending
+            return 5;
+        } 
         
         else{
             ErrorOut("Unknown function ending", lineData.lineNumber);
@@ -493,9 +1069,18 @@
         }
     }
     
+    /******************************************************************************/
+    /***                 <Functionality: local_name Checking>                   ***/
+    /******************************************************************************/
+    
     //not a keyword so check if it's a localName for a device
     else{
+
     
+//     lcd.setAddress(0,1);
+//            lcd.printf("wrd1: %s", lineData.word[0]);
+//            wait(1);
+            
         int i = 0, deviceFound = -1;
         for (i = 0; i < devices.size(); i++){
             if (lineData.word[0].compare(devices[i]->name) == 0)
@@ -508,6 +1093,8 @@
             return -1;   
         }
         
+        
+        
         //Local Name matches a device, send line to that device in order to process the functionality
         else
             return devices[deviceFound]->interpret(lineData); //call the device specific interpret command, and return the value it returns
@@ -517,6 +1104,8 @@
 }
 
 
+
+
 /**********************************************************************************************************************************/
 /**********************************************************************************************************************************/
 /******************************                        <FUNCTION: main>                            ********************************/
@@ -594,7 +1183,7 @@
     strcat(selectedFileFullName, selectedFileName);
     strcat(selectedFileFullName, ".txt");
     
-    FILE *selectedFile = fopen(selectedFileFullName, "r");
+    selectedFile = fopen(selectedFileFullName, "r");
     
     //Error out of attempt to open the selected file was unsuccessful
     if(selectedFile == NULL) {
@@ -624,10 +1213,25 @@
         if (returnValue == -1)
             error = 1;
             
-        checkEnd = interpretCommand(selectedFile, lineData); //interpret the line data
+        checkEnd = interpretCommand(lineData); //interpret the line data
                 
-        if (checkEnd == 2)
-            endOfFile = 1;
+        if (checkEnd == 2){            
+            //Dummy Mode will be turned on for the first run through, set it to 0 after the first run through,
+            //as the syntax will be checked without erroring, and therefore it is possible to try and run the .txt file
+            //Seek back to beginning of file
+            if (DummyMode){
+                DummyMode = 0;
+                rewind(selectedFile); //seek to the beginning of the file
+                resetLineData(lineData); //Reset the values in the struct that holds the File / Line Data
+                devices.erase(devices.begin(), devices.end()); //remove the devices vector from memory so that we don't duplicate items on the real run through
+                int k = 0;
+                for (k = 0; k < numErrorsConditions; k++)
+                    errorMonitors[k] = ErrorCondition();
+                numErrorsConditions = 0;
+            }
+            else
+                endOfFile = 1;
+        }
         else if (checkEnd == -1) //if interpretCommand returned an error, then return error in main
             error = 1;
             
@@ -639,18 +1243,13 @@
             }
             
             return -1;
-        }
+        }        
+    }
     
-        //Dummy Mode will be turned on for the first run through, set it to 0 after the first run through,
-        //as the syntax will be checked without erroring, and therefore it is possible to try and run the .txt file
-        //Seek back to beginning of file
-        if (DummyMode){
-            DummyMode = 0;
-            rewind(selectedFile); //seek to the beginning of the file
-            resetLineData(lineData); //Reset the values in the struct that holds the File / Line Data
-        }
-    }
-                
+    //Exit the program and remove needed items from memory
+    GoToLabels.erase(GoToLabels.begin(), GoToLabels.end()); //remove the GoToLabels vector from memory
+    devices.erase(devices.begin(), devices.end()); //remove the devices vector from memory
+    
     lcd.cls(); //clear the display   
     lcd.setAddress(0,0);
     lcd.printf("END OF PROGRAM");