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

Revision:
5:e36e0538a903
Parent:
4:86d0d04cc055
Child:
6:d1594fd2ec5a
--- a/main.cpp	Fri Sep 19 01:54:00 2014 +0000
+++ b/main.cpp	Tue Sep 23 18:24:19 2014 +0000
@@ -6,11 +6,6 @@
 #include "TextLCD.h"
 #include "SDFileSystem.h"
 #include "Initialization.hpp"
-//#include "DeviceClasses.h"
-//#include "Device.hpp"
-#include "Motor.hpp"
-#include "VoltageDriver.hpp"
-#include "PinIN.hpp"
 #include "TextFile.h"
 #include <stdio.h>
 #include <string>
@@ -19,33 +14,21 @@
 #include <vector>
 using std::string;
 
-//const int MAX_LINE_LENGTH = 100;
-//struct Line lineData;
-
-
-//DeviceData devices[15];
-
 FrontPanelButtons buttons(&i2c);
 
 //extern "C" void mbed_reset(); //enable software reset of code
-/*
-http://stackoverflow.com/questions/3081289/how-to-read-a-line-from-a-text-file-in-c-c
-http://stackoverflow.com/questions/12475915/rewind-stream-pointer-to-the-line-back
-
-recurrsive
-*/
 
 
 
-int interpretCommand(FILE *, Line &);
-int loopCommand(FILE *, Line &);
+int interpretCommand(FILE *, LineData &);
+int loopCommand(FILE *, LineData &);
 
 /**********************************************************************************************************************************/
 /**********************************************************************************************************************************/
 /***************************                        <FUNCTION: resetLineData>                            **************************/
 /**********************************************************************************************************************************/
 /**********************************************************************************************************************************/
-void resetLineData(Line &lineData){
+void resetLineData(LineData &lineData){
     
     //lineData.fullLine.clear();
     lineData.lineNumber = 0;
@@ -93,6 +76,344 @@
 }
             
     
+/**********************************************************************************************************************************/
+/**********************************************************************************************************************************/
+/**************************                        <FUNCTION: conditionCommand>                            *****************************/
+/**********************************************************************************************************************************/
+/**********************************************************************************************************************************/
+
+//Create an enum map of the positble conditions
+enum  ConditionType{xAND, AND, xOR, OR, NONE};                              
+//static const enum ConditionType Condition_Map[] = {xAND, AND, xOR, OR};    
+
+struct ConditionOp{
+    
+    int value;          //returned value of the interpret function: 1 = meets criteria, 0 = criteria not met, -1 = failed to interpret
+    ConditionType op; //operator that follows the given parameter: x val 2 AND y val 3, if this ConditionOp is for x, then the value will be AND
+};
+
+int conditionCommand(FILE *selectedFile, LineData &lineData){
+        
+    //Get the number of condition parameters 
+    string numConditionVals = lineData.word[1];
+    int numConditionValues = 0;
+    sscanf(numConditionVals.c_str(), "%d", &numConditionValues);
+    
+    //LineData tempLineData;
+    LineData param[15];
+    //vector<LineData> param;
+    vector<ConditionOp> paramCondition;
+ 
+/*
+    int val1, val2, val3, val4;
+    LineData temp;
+    temp.numWords = 3;
+    temp.word[1] = "val";
+    temp.word[2] = "1";
+    while (true){
+        
+        temp.word[0] = "pin1";
+        val1 = interpretCommand(selectedFile, temp);
+        
+        temp.word[0] = "pin2";
+        val2 = interpretCommand(selectedFile, temp);
+        
+        temp.word[0] = "pin3";
+        val3 = interpretCommand(selectedFile, temp);
+        
+        temp.word[0] = "pin4";
+        val4 = interpretCommand(selectedFile, temp);
+    
+        lcd.cls(); //clear the display 
+        lcd.setAddress(0,0);
+        lcd.printf("Pin1: %d", val1);
+        lcd.setAddress(0,1);
+        lcd.printf("Pin2: %d", val2);
+        lcd.setAddress(0,2);
+        lcd.printf("Pin3: %d", val3);
+        lcd.setAddress(0,3);
+        lcd.printf("Pin4: %d", val4);
+        wait(0.2);
+    }*/
+    
+    //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
+    int i = 2, numParam = 0, paramNumWords = 0;
+    for (i = 2; i < lineData.numWords; i++){
+           
+           lcd.setAddress(0,3);
+    lcd.printf("Test2");
+    
+        /*lcd.setAddress(0,2);
+        lcd.printf("i: %d, nW-1: %d ", i, (lineData.numWords - 1));
+        wait(2);*/
+        
+        // if the word is not an AND or an OR, it must mean it's for the specific function
+        // set the current parameter's next word to be equal to the current word we're checking
+        // increase number of words that the parameter has
+        if (lineData.word[i] != "AND" && lineData.word[i] != "xAND" && lineData.word[i] != "OR" && lineData.word[i] != "xOR"){
+//            lcd.setAddress(0,3);
+//            lcd.printf("%dlD[%d]: %s", numParam, i, lineData.word[i]);
+//            wait(2);
+            //tempLineData.word[paramNumWords] = lineData.word[i];
+            param[numParam].word[paramNumWords] = lineData.word[i];
+            paramNumWords++;
+            
+            //if this is the last word in the line....
+            if(i == (lineData.numWords - 1)){
+                param[numParam].numWords = paramNumWords;
+                 paramCondition[numParam].op = NONE;
+                numParam++;
+            }
+            
+        }
+            
+        // if the word is an AND or an OR, it must mean the last function has been completely identified
+        // set the parameters number of Words value to the calculated value
+        // increase the number of Parameters (the current parameter function we're filling)
+        else if (lineData.word[i].compare("AND") == 0 || lineData.word[i].compare("xAND") == 0 || lineData.word[i].compare("OR") == 0 || lineData.word[i].compare("xOR") == 0){
+            
+            //tempLineData.numWords = paramNumWords;
+            param[numParam].numWords = paramNumWords;
+            
+            paramCondition.push_back(ConditionOp());
+            if (lineData.word[i].compare("AND") == 0)
+                paramCondition[numParam].op = AND;
+            else if (lineData.word[i].compare("xAND") == 0)
+                paramCondition[numParam].op = xAND;
+            else if (lineData.word[i].compare("OR") == 0)
+                paramCondition[numParam].op = OR;
+            else if (lineData.word[i].compare("xOR") == 0)
+                paramCondition[numParam].op = xOR;
+
+            //param.push_back(LineData()); 
+            //param[numParam] = tempLineData;
+            //param.push_back(tempLineData); //add it to the vector list of parameters
+            //tempLineData = LineData(); //reset
+            numParam++; // increase the index of param
+            paramNumWords = 0; // reset the number of words
+        }    
+    }
+    
+
+    vector<ConditionOp> combinedCondition;
+    ConditionOp tempCombinedCondition;
+    int j = 0, k = 0, returnValue = -1;
+    for (j = 0; j < numParam; j++){
+        paramCondition[j].value = interpretCommand(selectedFile, param[j]);
+    }
+
+    //create the combined Condition vector (take care of this xAND and xOR statements and combine them into one so that the whole vector is just AND's and OR's)
+    //this should make the xAND's / xOR's into a single member of the combinedCondition vector
+    enum ConditionType prevCondition = NONE; 
+    int first = 1, last = 0;
+    for (k = 0; k < numParam; k++){
+/*
+lcd.setAddress(0,3);
+                    lcd.printf("k: %d       ", k);
+                    wait(1);*/
+                    
+        if (k == numParam - 1)
+            last = 1;
+            
+       if (!last && (prevCondition != AND || prevCondition != OR)){
+            if (paramCondition[k].op != xAND && paramCondition[k].op != xOR && paramCondition[k + 1].op != xAND && paramCondition[k + 1].op != xOR){
+                
+               /* lcd.setAddress(0,3);
+                    lcd.printf("Test 0.1     ");
+                    wait(1);*/
+                    
+                //AND
+                if (paramCondition[k].op == AND){
+                    if (!first && prevCondition != xAND && prevCondition != xOR){
+                       /*   lcd.setAddress(0,3);
+                    lcd.printf("Test 1.6     ");
+                    wait(1);*/
+                        combinedCondition.back().value = combinedCondition.back().value && paramCondition[k + 1].value;
+                    }
+                    else if (first || prevCondition == xAND || prevCondition == xOR){
+                        /*  lcd.setAddress(0,3);
+                    lcd.printf("Test 1.5     ");
+                    wait(1);*/
+                        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;
+                        /*lcd.setAddress(0,3);
+                    lcd.printf("Test 1.1     ");
+                    wait(1);*/
+                    }else if (first || prevCondition == xAND || prevCondition == xOR){
+                       /* lcd.setAddress(0,3);
+                    lcd.printf("Test 1.2     ");
+                    wait(1);*/
+                        tempCombinedCondition.value = paramCondition[k].value || paramCondition[k + 1].value; 
+                        combinedCondition.push_back(tempCombinedCondition);
+                        first = 0;
+                    }    
+                    prevCondition = OR;
+                }
+            }
+            
+            else{   
+                      /*lcd.setAddress(0,3);
+                    lcd.printf("Test 0.2     ");
+                    wait(1);*/
+                //xAND
+                if (paramCondition[k].op == xAND && prevCondition == xAND){
+                    /*lcd.setAddress(0,3);
+                    lcd.printf("Test 2     ");
+                    wait(1);*/
+                    combinedCondition.back().value = combinedCondition.back().value && paramCondition[k + 1].value;
+                    prevCondition = xAND;
+                }
+                else if (paramCondition[k].op == xAND && prevCondition != xAND){
+                    /*lcd.setAddress(0,3);
+                    lcd.printf("Test 1     ");
+                    wait(1);*/
+                    tempCombinedCondition.value = paramCondition[k].value && paramCondition[k + 1].value; 
+                    combinedCondition.push_back(tempCombinedCondition);
+                    prevCondition = xAND;
+                }
+                /*else if (paramCondition[k].op != xAND && prevCondition == xAND){
+                    combinedCondition.back().op = paramCondition[k].op;
+                    prevCondition = xAND;
+                }*/
+                
+                //xOR
+                else if (paramCondition[k].op == xOR && prevCondition == xOR){
+                      /*lcd.setAddress(0,3);
+                    lcd.printf("Test 1.3     ");
+                    wait(1);*/
+                    combinedCondition.back().value = combinedCondition.back().value || paramCondition[k + 1].value;
+                    prevCondition = xOR;
+                }
+                else if (paramCondition[k].op == xOR && prevCondition != xOR){
+                     /* lcd.setAddress(0,3);
+                    lcd.printf("Test 1.4     ");
+                    wait(1);*/
+                    tempCombinedCondition.value = paramCondition[k].value || paramCondition[k + 1].value; 
+                    combinedCondition.push_back(tempCombinedCondition);
+                    prevCondition = xOR;
+                }
+                /*else if (paramCondition[k].op != xOR && prevCondition == xOR){
+                    combinedCondition.back().op = paramCondition[k].op;
+                    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)){
+                    /*lcd.setAddress(0,3);
+                    lcd.printf("Test 3     ");
+                    wait(1);*/
+                    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
+        else{
+              /*lcd.setAddress(0,3);
+                lcd.printf("Test 5     ");
+                wait(1);*/
+            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;
+    }
+
+    int conditionSuccess = combinedCondition.back().value; //value is the success(1) or failure(0) of the condition statement
+
+
+
+    int checkEnd = 0;
+    if (!conditionSuccess){
+        lcd.setAddress(0,3);
+        lcd.printf("CONDITION FAILURE");
+        wait(1);
+        while (checkEnd != 4){
+            
+            getNextLine(selectedFile, lineData); 
+            if (lineData.word[0].compare("end") == 0)   
+                checkEnd = interpretCommand(selectedFile, lineData);
+        
+            if (checkEnd == 4) // custom return value for this function
+                return 0;
+        }
+    }
+    
+    lcd.setAddress(0,3);
+    lcd.printf("CONDITION SUCCESS");
+    wait(1);
+    int returnValue2 = 1;
+    // Return success as the function either met the condition and will continue from the next line, or
+    // failed to meet the condition and ran through the lines inside the condition until "end condition" was found, therefore
+    // the program will proceed from the line after the "end condition" line
+    return returnValue2;
+}      
+    /*
+    for (k = 0; k < numParam; k++){
+        if (paramCondition[k].op == AND){
+            if (paramCondition[k + 1].op != xAND && paramCondition[k + 1].op != xOR)
+                tempCombinedCondition.value = paramCondition[k].value && paramCondition[k + 1].value; 
+            else
+                tempCombinedCondition.value = paramCondition[k].value; 
+            
+            tempCombinedCondition.op = AND;
+            combinedCondition.push_back(tempCombinedCondition);
+            prevCondition = AND;
+        }
+        
+        else if (paramCondition[k].op == OR){
+            if (paramCondition[k + 1].op != xAND && paramCondition[k + 1].op != xOR)
+                tempCombinedCondition.value = paramCondition[k].value || paramCondition[k + 1].value; 
+            else
+                tempCombinedCondition.value = paramCondition[k].value; 
+            
+            tempCombinedCondition.op = OR;
+            combinedCondition.push_back(tempCombinedCondition);
+            prevCondition = OR;
+        }
+        
+        else if (paramCondition[k].op == xAND){
+            if (prevCondition == xAND) // if previous one was also xAND, that means we already have a vector member for this (this last member)
+                combinedCondition.back().value = combinedCondition.back().value && paramCondition[k + 1].value;
+            else{ // if the prevCondition was not xAND, then we need to add a new member to the vector
+                tempCombinedCondition.value = paramCondition[k].value && paramCondition[k + 1].value; 
+                combinedCondition.push_back(tempCombinedCondition);
+            }
+            prevCondition = xAND;
+        }
+        else if (paramCondition[k].op == xOR){
+            tempCombinedCondition.value = paramCondition[k].value || paramCondition[k + 1].value;
+            prevCondition = xOR;
+        }
+    }
+    
+    
+    return 1;*/  
+ 
 
 /**********************************************************************************************************************************/
 /**********************************************************************************************************************************/
@@ -100,7 +421,7 @@
 /**********************************************************************************************************************************/
 /**********************************************************************************************************************************/
 
-int loopCommand(FILE *selectedFile, Line &lineData){
+int loopCommand(FILE *selectedFile, LineData &lineData){
         
     //Get the Condition value for number of times to loop
     string loopCondition = lineData.word[1];
@@ -112,17 +433,35 @@
     int counter = 0, checkEnd = 0;
     while (counter < loopConditionValue){
         
-        getNextLine(selectedFile, lineData);    
-        checkEnd = interpretCommand(selectedFile, lineData);
-            
+        /*lcd.setAddress(0,3);
+        lcd.printf("BcheckEnd: %d        ", checkEnd);
+        wait(1);*/
+        
+        getNextLine(selectedFile, lineData); 
+        
+        //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(selectedFile, lineData);
+            
+        /*lcd.setAddress(0,3);
+        lcd.printf("AcheckEnd: %d        ", checkEnd);
+        wait(1);*/
         
+        
+        /*
+        lcd.setAddress(0,3);
+        lcd.printf("checkEnd: %d        ", checkEnd);
+            wait(2);*/
         //Increase the loop counter and go back to the beginning of the loop
-        if (checkEnd == 1){
+        if (checkEnd == 3){
             counter++;
             
             lcd.setAddress(0,2);
@@ -130,6 +469,7 @@
             
             fseek(selectedFile, loopStartAddress, SEEK_SET);
             lineData.lineNumber = loopLineNumber - 2;
+            checkEnd = 0;
         }
     }
                 
@@ -142,7 +482,7 @@
 /**********************************************************************************************************************************/
 /**********************************************************************************************************************************/
 
-int interpretCommand(FILE *selectedFile, Line &lineData){
+int interpretCommand(FILE *selectedFile, LineData &lineData){
         
     if (lineData.word[0].compare("device") == 0){
 
@@ -187,13 +527,22 @@
         if (checkLoopEnd == 1)
             return 1;
     }
-            
+       
+    else if (lineData.word[0].compare("condition") == 0){
+        int checkLoopEnd = conditionCommand(selectedFile, lineData);
+        if (checkLoopEnd == 1)
+            return 2;
+    }     
+    // end with custom return value for specific function
     else if (lineData.word[0].compare("end") == 0){
         if (lineData.word[1].compare("program") == 0){
-            return 0;
+            return 2;
         }
         else if (lineData.word[1].compare("loop") == 0){
-            return 1;
+            return 3;
+        }
+        else if (lineData.word[1].compare("condition") == 0){
+            return 4;
         }
     }
     
@@ -216,7 +565,7 @@
         //Local Name matches a device, send line to that device in order to process the functionality
         else{
             //addDevice(deviceFound);
-            devices[deviceFound]->interpret(lineData);
+            return devices[deviceFound]->interpret(lineData);
         }
     }  
     
@@ -234,7 +583,7 @@
     
     fullInit(); //Initialize anything that's required to run the code (LCD)
     
-    struct Line lineData;
+    struct LineData lineData;
     resetLineData(lineData);
 
         /******************************************************************************/