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
Diff: main.cpp
- Revision:
- 11:bc9cd2869f95
- Parent:
- 10:e8db892fbc52
- Child:
- 12:2e3e86714243
--- 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");