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:
12:2e3e86714243
Parent:
11:bc9cd2869f95
Child:
13:899db9d635e5
--- a/main.cpp	Wed Oct 01 18:11:38 2014 +0000
+++ b/main.cpp	Wed Oct 01 19:31:02 2014 +0000
@@ -330,21 +330,143 @@
 }      
 
 
-   cycleWatch
+   
 /**********************************************************************************************************************************/
 /**********************************************************************************************************************************/
 /**************************                       <FUNCTION: cycleCommand>                            *****************************/
 /**********************************************************************************************************************************/
 /**********************************************************************************************************************************/
 
-int loopCommand(LineData &lineData){
+Timer cycleTimer;
+CycleWatch cycleWatch;
+int cycleCommand(LineData &lineData, int cycleState){
+
+    // if cycleState is 1, then initialize the cycle
+    if (cycleState == 1){
+                
+        //Get the Condition value for number of times to loop
+        string numCycles = lineData.word[1];
+        int numValuesFound = sscanf(numCycles.c_str(), "%d", &cycleWatch.numCycles);
+        if (numValuesFound < 1){
+            ErrorOut("Parameter Unknown, loopCondition 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 loop again
+        if (DummyMode)
+            return 0; //Function operated successfully but doesn't return a value
+            
+            
+        //****************//
+        //Get the person to dynamically select what number of cycles they'd like to do, starting with the read value as the base value
+        //****************//
+        lcd.cls(); //clear the display
+        lcd.setAddress ( 0, 2 );
+        lcd.printf( "<<ACTION REQUIRED>>" );
+        lcd.setAddress ( 0, 3 );
+        lcd.printf( "<Press Sel to start>" );
+        while (!buttons.readSel()){
+            if(buttons.readUp() && cycleWatch.numCycles < 999999 ){
+                cycleWatch.numCycles++;
+                wait(0.05); //so that the speed of changing the numbers is more controllable, should mean you can move 20 digits per second
+            }
+            else if (buttons.readDown() && cycleWatch.numCycles > 0 ){
+                cycleWatch.numCycles--;
+                wait(0.05); //so that the speed of changing the numbers is more controllable, should mean you can move 20 digits per second
+            }
+            lcd.setAddress ( 0, 0 );
+            lcd.printf( "<Num Cycles: %d >" , cycleWatch.numCycles );
+        }
+        
+        //Initialize the counter variable of the struct, and start the cycle timer
+        cycleWatch.counter = 0;
+        cycleTimer.start();
+        
+        //Update the LCD to display the desired data
+        lcd.cls(); //clear the display            
+        //Output the Avg Cycle Time
+        cycleTimer.stop(); 
+        cycleWatch.totalCycleTime += cycleTimer.read();
+        lcd.setAddress(0,1);
+        lcd.printf("Avg t(sec): 0.000");
+        
+        //Output Cycle Number
+        cycleWatch.counter++;
+        lcd.setAddress(0,0);
+        lcd.printf("Cycle %d of %d", cycleWatch.counter, cycleWatch.numCycles);
+
+
+        //get the next line in order to get the line address to return to 
+        int returnValue = getNextLine(selectedFile, lineData);     
+        //if getNextLine returned an error, then error out
+        if (returnValue == -1)
+            return -1;
+        
+        //save the staring location of this cycle loop 
+        cycleWatch.startAddress = lineData.lineAddress;
+        cycleWatch.startLineNumber = lineData.lineNumber; 
+        
+        //seek back a line, so once this function returns, the next line reteived is that of the next line that should be processed.... basically... so we don't skip a line
+        lineData.lineNumber = cycleWatch.startLineNumber - 1;
+        int seekFailure = fseek(selectedFile, cycleWatch.startAddress, SEEK_SET); //fseek returns 0 on success
+        if (seekFailure){
+            ErrorOut("Init Cycle    Failed to seek line", lineData.lineNumber); //Spaces make it look nice on the LCD
+            return -1;
+        }
+    }
     
-    int thisLoopMain = 0;
-    if (mainLoopFlag == 0){
-        thisLoopMain = 1;
-        mainLoopFlag = 1;
+    
+    
+    
+    // if cycleState is 1, then check for ending conditions
+    else if (cycleState == 0){
+    
+        //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(); 
+        cycleWatch.totalCycleTime += cycleTimer.read();
+        lcd.setAddress(0,1);
+        lcd.printf("Avg t(sec): %1.3f", (cycleWatch.totalCycleTime / cycleWatch.counter));
+        
+        //Output Cycle Number
+        cycleWatch.counter++;
+        lcd.setAddress(0,0);
+        lcd.printf("Cycle %d of %d", cycleWatch.counter, cycleWatch.numCycles);
+
+        
+        if (cycleWatch.counter <= cycleWatch.numCycles){
+            
+            //seek back to the start of the cycle loop
+            lineData.lineNumber = cycleWatch.startLineNumber - 1;
+            int seekFailure = fseek(selectedFile, cycleWatch.startAddress, SEEK_SET); //fseek returns 0 on success
+            if (seekFailure){
+                ErrorOut("In Cycle      Failed to seek line", lineData.lineNumber); //Spaces make it look nice on the LCD
+                return -1;
+            }
+                
+            //Restart the timer for the next cycle
+            cycleTimer.reset();
+            cycleTimer.start();
+        }
     }
     
+    return 0; //Return Success, no value is being sent so don't return 1
+ }   
+ 
+ 
+ 
+/**********************************************************************************************************************************/
+/**********************************************************************************************************************************/
+/**************************                        <FUNCTION: loopCommand>                            *****************************/
+/**********************************************************************************************************************************/
+/**********************************************************************************************************************************/
+
+int loopCommand(LineData &lineData){
+    
     //Get the Condition value for number of times to loop
     string loopCondition = lineData.word[1];
     int loopConditionValue = 0;
@@ -385,19 +507,8 @@
         }
     }
     
-
+    
     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;
     
 
@@ -458,27 +569,6 @@
             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);
@@ -500,220 +590,13 @@
             }
 
             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
- }   
- 
- 
- 
-/**********************************************************************************************************************************/
-/**********************************************************************************************************************************/
-/**************************                        <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;
+            checkEnd = 0;    
         }
         
-        //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
+        else if (checkEnd == -1)  //if interpretCommand returned an error, then return 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
  }   
 
@@ -772,7 +655,7 @@
         }
       
         if (numError){
-            char errorMsg[100] = "ERROR!!!       Item: ";
+            char errorMsg[100] = "errorWatch!  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
@@ -782,14 +665,18 @@
             for(i = 0; i < devices.size(); i++)
                 devices[i]->pause();
             
+            cycleTimer.stop(); //pause the cycle timer
+            
             //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();
             
+            cycleTimer.start(); //start the cycle timer
+            
             lcd.cls(); //clear the display  
         }
     }
@@ -1044,7 +931,7 @@
     /***                       <Functionality: cycle>                           ***/
     /******************************************************************************/
     else if (lineData.word[0].compare("cycle") == 0)
-       return cycleCommand(selectedFile, lineData, 1); //Sending 1 means it's initializing
+       return cycleCommand(lineData, 1); //Sending 1 means it's initializing
        
        
     /******************************************************************************/
@@ -1059,7 +946,7 @@
         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
+            cycleCommand(lineData, 0); //Sending 0 means it's checking for the ending
             return 5;
         }