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:
- 9:5a0c4c6e39c7
- Parent:
- 8:e9f836163229
- Child:
- 10:e8db892fbc52
--- a/main.cpp Wed Sep 24 01:46:02 2014 +0000
+++ b/main.cpp Wed Sep 24 22:23:00 2014 +0000
@@ -5,6 +5,7 @@
#include "TextLCD.h"
#include "SDFileSystem.h"
#include "Initialization.hpp"
+//#include "mainFunctions.hpp"
#include "TextFile.h"
#include <stdio.h>
#include <string>
@@ -17,26 +18,26 @@
//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> **************************/
-/**********************************************************************************************************************************/
-/**********************************************************************************************************************************/
+/******************************************************************************/
+/*** <Function: resetLineData> ***/
+/******************************************************************************/
+
void resetLineData(LineData &lineData){
- //lineData.fullLine.clear();
lineData.lineNumber = 0;
lineData.numWords = 0;
lineData.lineAddress = 0;
}
-
-
/**********************************************************************************************************************************/
/**********************************************************************************************************************************/
/************************ <FUNCTION: cyclePrograms> *****************************/
@@ -82,45 +83,39 @@
/**********************************************************************************************************************************/
//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};
+enum ConditionType{xAND, AND, xOR, OR, NONE};
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
+ 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;
+ //Initialize variables
LineData param[15];
- //vector<LineData> param;
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
- int i = 2, numParam = 0, paramNumWords = 0;
- for (i = 2; i < lineData.numWords; i++){
+ //this line reads: Condition, data_for_param1, CONDTITION_OP1, data_for_param2, CONDTITION_OP2, data_for_param3......
+ //Staring index of first data parameter is the 2nd word, therefore 1
+ int i = 1, numParam = 0, paramNumWords = 0;
+ for (i = 1; i < lineData.numWords; i++){
// 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"){
- //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;
+ paramCondition[numParam].op = NONE;
numParam++;
}
@@ -131,7 +126,6 @@
// 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());
@@ -144,26 +138,29 @@
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;
+
+ //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]);
+
+ //error out if the interpretted command returned an error
+ if (paramCondition[j].value == -1)
+ return -1;
}
+
//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;
+ vector<ConditionOp> combinedCondition;
+ ConditionOp tempCombinedCondition;
int first = 1, last = 0;
for (k = 0; k < numParam; k++){
@@ -289,26 +286,32 @@
int conditionSuccess = combinedCondition.back().value; //value is the success(1) or failure(0) of the condition statement
- int checkEnd = 0;
+ int checkEnd = 0, returnValue;
if (!conditionSuccess){
while (checkEnd != 4){
- getNextLine(selectedFile, lineData);
+ 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(selectedFile, lineData);
if (checkEnd == 4) // custom return value for this function
- return 0;
+ 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;
}
}
// 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 1;
+ return 0; //Function operated successfully but doesn't return a value
}
@@ -323,23 +326,32 @@
//Get the Condition value for number of times to loop
string loopCondition = lineData.word[1];
int loopConditionValue = 0;
- sscanf(loopCondition.c_str(), "%d", &loopConditionValue);
+
+ int numValuesFound = sscanf(loopCondition.c_str(), "%d", &loopConditionValue);
+ if (numValuesFound < 1){
+ ErrorOut("Parameter Unknown, loopCondition Value can't be converted", lineData.lineNumber);
+ return -1;
+ }
int loopStartAddress = 0, loopLineNumber = 0, firstLineOfLoop = 1;
lcd.setAddress(0,0);
lcd.printf("Cycle 1 of %d", loopConditionValue);
+ float totalLoopTime = 0;
Timer cycleTimer;
- float totalLoopTime = 0;
cycleTimer.reset();
cycleTimer.start();
- int counter = 1, checkEnd = 0;
+ int counter = 1, checkEnd = 0, returnValue;
while (counter <= loopConditionValue){
- getNextLine(selectedFile, lineData);
+ 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
@@ -367,17 +379,24 @@
lcd.setAddress(0,0);
lcd.printf("Cycle %d of %d", counter, loopConditionValue);
- fseek(selectedFile, loopStartAddress, SEEK_SET);
- lineData.lineNumber = loopLineNumber - 2;
+ 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;
}
- return 1;
+ return 0; //Return Success, no value is being sent so don't return 1
}
/**********************************************************************************************************************************/
@@ -396,57 +415,66 @@
deviceFound = i;
}
}
-
+
//if the device type does not match any known type, error out
if (deviceFound == -1){
- //Error Out since the device Name was not matched with anything *************************
+ ErrorOut("No device match found in the system", lineData.lineNumber); //Spaces make it look nice on LCD
+ return -1;
}
//Add device to the array of devices and initialize it
else{
devices.push_back(Device::newDevice(deviceFound, lineData.word[1], lineData));
- devices.back()->name = lineData.word[1];
+ devices.back()->name = lineData.word[1];
+
+ //since the constructor cannot return a value, it will trip the error Flag if something is wrong, check that flag, and return error if it has been tripped
+ if (devices.back()->errorFlag == 1){
+ ErrorOut("Error initializing device", lineData.lineNumber);
+ return -1;
+ }
}
}
else if (lineData.word[0].compare("delay") == 0){
string duration = lineData.word[1];
int durationValue = 0;
- sscanf(duration.c_str(), "%d", &durationValue);
+ int numValuesFound = sscanf(duration.c_str(), "%d", &durationValue);
- if (durationValue){
+ if (numValuesFound < 1){
+ ErrorOut("Parameter Unknown, Duration Value can't be converted", lineData.lineNumber);
+ return -1;
+ }
+
+ if (durationValue > 0){
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{
- //Error Out
+ ErrorOut("Duration value is less than 0", lineData.lineNumber);
return -1;
}
}
- else if (lineData.word[0].compare("loop") == 0){
- int checkLoopEnd = loopCommand(selectedFile, lineData);
- if (checkLoopEnd == 1)
- return 1;
- }
+ else if (lineData.word[0].compare("loop") == 0)
+ return loopCommand(selectedFile, lineData); //Process the loop command and return the value that it returns
- else if (lineData.word[0].compare("condition") == 0){
- int checkLoopEnd = conditionCommand(selectedFile, lineData);
- if (checkLoopEnd == 1)
+ else if (lineData.word[0].compare("condition") == 0)
+ return conditionCommand(selectedFile, lineData); //Process the condition command and return the value that it returns
+
+ //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)
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 2;
- }
- else if (lineData.word[1].compare("loop") == 0){
+ else if (lineData.word[1].compare("loop") == 0)
return 3;
- }
- else if (lineData.word[1].compare("condition") == 0){
+ else if (lineData.word[1].compare("condition") == 0)
return 4;
+
+ else{
+ ErrorOut("Unknown function ending", lineData.lineNumber);
+ return -1;
}
}
@@ -461,19 +489,16 @@
//no device was found that matched the local name, and this is also the last error check, meaning it can match no other potential keywords
if (deviceFound == -1){
- lcd.setAddress(0,3);
- lcd.printf("Final ERROR!");
- wait(10);
+ ErrorOut("No device match found in the system", lineData.lineNumber); //Spaces make it look nice on LCD
+ return -1;
}
//Local Name matches a device, send line to that device in order to process the functionality
- else{
- //addDevice(deviceFound);
- return devices[deviceFound]->interpret(lineData);
- }
+ else
+ return devices[deviceFound]->interpret(lineData); //call the device specific interpret command, and return the value it returns
}
- return -1;
+ return 0; //Return Success, no value is being sent so don't return 1
}
@@ -490,92 +515,119 @@
LineData lineData;
resetLineData(lineData);
- /******************************************************************************/
- /*** <Get all the Potential Programs> ***/
- /******************************************************************************/
- int numTextFiles = 0;
- vector<string> textFiles; //Assuming Maximum of 25 txt files will be on the SD Card
- vector<string> filenames = readFileNames("/sd");
- numTextFiles = getFileNamesWithoutExt(textFiles, filenames);
-
+ /******************************************************************************/
+ /*** <Get all the Potential Programs> ***/
+ /******************************************************************************/
+ int numTextFiles = 0;
+ vector<string> textFiles; //Assuming Maximum of 25 txt files will be on the SD Card
+ vector<string> filenames = readFileNames("/sd");
+
+ //Error check whether the SD Card exists and was able to be accessed.... or if there's no files on the SD Card
+ if (filenames.size() == 0){
+ ErrorOut("No Files Found, or Directory can't be accessed", 0); //Spaces make it look nice on LCD
+ return -1; //End program by returning in the main()
+ }
+
+ numTextFiles = getFileNamesWithoutExt(textFiles, filenames);
- /******************************************************************************/
- /*** <Select the Program txt File> ***/
- /******************************************************************************/
- int fileSelected = 0, selectedFileIndex = 0;
+ //Error check whether the SD Card has any txt files in it's first directory
+ if (numTextFiles == 0){
+ ErrorOut("No Program (.txt) Files Found in first Directory", 0); //Spaces make it look nice on LCD
+ return -1; //End program by returning in the main()
+ }
- lcd.cls(); //clear the display
- lcd.setAddress(0,1);
- lcd.printf("Select Your Program");
- lcd.setAddress(0,2);
- lcd.printf("Num Programs = %d", numTextFiles);
-
- uint8_t lastButState = 0;
- lcd.setCursor(TextLCD::CurOn_BlkOn); //turn blinking cursor on
+ /******************************************************************************/
+ /*** <Select the Program txt File> ***/
+ /******************************************************************************/
+ int fileSelected = 0, selectedFileIndex = 0;
+
+ lcd.cls(); //clear the display
+ lcd.setAddress(0,1);
+ lcd.printf("Select Your Program");
+ lcd.setAddress(0,2);
+ lcd.printf("Num Programs = %d", numTextFiles);
- selectedFileIndex = cyclePrograms(textFiles, numTextFiles, selectedFileIndex, -1); //Initialize the first file to the screen
- while(!fileSelected) {
-
- uint8_t curButState = buttons.readBus();
- if(curButState != lastButState){
- lastButState = curButState;
- if(buttons.readRight())
- selectedFileIndex = cyclePrograms(textFiles, numTextFiles, selectedFileIndex, 1);
- else if(buttons.readLeft())
- selectedFileIndex = cyclePrograms(textFiles, numTextFiles, selectedFileIndex, 0);
- else if(buttons.readSel())
- fileSelected = 1;
- }
- }
-
- char selectedFileName[50];
- strcpy(selectedFileName, textFiles[selectedFileIndex].c_str());
+ uint8_t lastButState = 0;
+ lcd.setCursor(TextLCD::CurOn_BlkOn); //turn blinking cursor on
+
+ selectedFileIndex = cyclePrograms(textFiles, numTextFiles, selectedFileIndex, -1); //Initialize the first file to the screen
+ while(!fileSelected) {
- /******************************************************************************/
- /*** <Open the Program txt File> ***/
- /******************************************************************************/
-
- //Create the string of the full directory and path to the program txt file
- char selectedFileFullName[100] = "/sd/"; //Assuming that no directory and file name will be longer than 100 characters
- strcat(selectedFileFullName, selectedFileName);
- strcat(selectedFileFullName, ".txt");
-
- FILE *selectedFile = fopen(selectedFileFullName, "r");
-
- lcd.cls(); //clear the display
-
- if(selectedFile == NULL) {
- lcd.setAddress(0,0);
- lcd.printf("Invalid");
- wait(10);
+ uint8_t curButState = buttons.readBus();
+ if(curButState != lastButState){
+ lastButState = curButState;
+ if(buttons.readRight())
+ selectedFileIndex = cyclePrograms(textFiles, numTextFiles, selectedFileIndex, 1);
+ else if(buttons.readLeft())
+ selectedFileIndex = cyclePrograms(textFiles, numTextFiles, selectedFileIndex, 0);
+ else if(buttons.readSel())
+ fileSelected = 1;
}
+ }
+
+ lcd.setCursor(TextLCD::CurOn_BlkOff); //turn blinking cursor off
+
+ char selectedFileName[50];
+ strcpy(selectedFileName, textFiles[selectedFileIndex].c_str());
+
+ /******************************************************************************/
+ /*** <Open the Program txt File> ***/
+ /******************************************************************************/
+
+ //Create the string of the full directory and path to the program txt file
+ char selectedFileFullName[100] = "/sd/"; //Assuming that no directory and file name will be longer than 100 characters
+ strcat(selectedFileFullName, selectedFileName);
+ strcat(selectedFileFullName, ".txt");
+
+ FILE *selectedFile = fopen(selectedFileFullName, "r");
+
+ //Error out of attempt to open the selected file was unsuccessful
+ if(selectedFile == NULL) {
+ ErrorOut("Unable to Open Selected File", 0); //Spaces make it look nice on LCD
+ return -1; //End program by returning in the main()
+ }
+ /******************************************************************************/
+ /*** <Start Running through the Program txt File Lines> ***/
+ /******************************************************************************/
+
while(1){
- resetLineData(lineData);
-
+ resetLineData(lineData); //Reset the values in the struct that holds the Line Data, in preparation for a new line read
lcd.cls(); //clear the display
- lcd.setAddress(0,0);
- //lcd.printf("Program: %s", selectedFileName);
-
- /******************************************************************************/
- /*** <Start Running through the Program txt File Lines> ***/
- /******************************************************************************/
-
- int endOfFile = 0;
+ int endOfFile = 0, error = 0, returnValue, checkEnd;
while (!endOfFile){
-
- getNextLine(selectedFile, lineData);
- int checkEnd = interpretCommand(selectedFile, lineData);
+
+ //Re-initialize variables
+ returnValue = 0;
+ checkEnd = 0;
+
+ returnValue = getNextLine(selectedFile, lineData); //get the next line of data
+
+ //if getNextLine returned an error, then return error in main
+ if (returnValue == -1)
+ error = 1;
+
+ checkEnd = interpretCommand(selectedFile, lineData); //interpret the line data
if (checkEnd == 2)
endOfFile = 1;
+ else if (checkEnd == -1) //if interpretCommand returned an error, then return error in main
+ error = 1;
+
+ //Before erroring out, turn all devices off so that they power down
+ if (error){
+ for(vector<Device*>::iterator it=devices.begin(); it < devices.end(); it++)
+ (*it)->off();
+
+ return -1;
+ }
+
}
-
lcd.cls(); //clear the display
lcd.setAddress(0,0);
lcd.printf("END OF PROGRAM");
@@ -592,127 +644,4 @@
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- /***** Cycle through txt lines and remember last lines ******/
- /*
- int running = 0, selectedFile = 0;
- int locCount = 0, tempSpot = 0;
- int loc[4];
- char line[32];
- uint8_t lastButState;
-
-
- while(1){
- lcd.setCursor(TextLCD::CurOn_BlkOn); //turn blinking cursor on
- while(!running) {
- uint8_t curButState = buttons.readBus();
-
- if(curButState != lastButState){
- switch(lastButState = curButState){
- case 0x1F: //right
-
- loc[locCount] = ftell(fp);
-
- if (locCount >= 3)
- locCount = 0;
- else
- locCount++;
-
- //tempSpot = ftell(fp);
- fgets(line, 32, fp);
-
- lcd.setAddress(0,1);
- lcd.printf("L: %s", line);
- wait(0.2);
- break;
- case 0x2F: //left
-
- if (locCount == 0) {
- locCount = 3;
- fseek(fp, loc[locCount], SEEK_SET);
- }
- else {
- fseek(fp, loc[locCount - 1], SEEK_SET);
- locCount--;
- }
- fgets(line, 32, fp);
- lcd.setAddress(0,1);
- lcd.printf("L: %s", line);
- wait(0.2);
- break;
- }
- }
- }
- }
- */
-
-
-
- /******* Select the Program txt File ***********/
- /*
- int numTextFiles = 0;
- string tempTextFiles[25]; //Assuming Maximum of 25 txt files will be on the SD Card
- lcd.cls(); //clear the display
- readFileNames("/sd");
- numTextFiles = getFileNamesWithoutExt(tempTextFiles);
-
- string *textFiles = resize_StringArr(tempTextFiles, numTextFiles); //Resize Array
- //delete [] tempTextFiles; //free previous array
-
-
- int running = 0, selectedFile = 0;
-
- lcd.cls(); //clear the display
- lcd.setAddress(0,1);
- lcd.printf("Select Your Program");
- lcd.setAddress(0,2);
- lcd.printf("Num Programs = %d", numTextFiles);
-
- uint8_t lastButState;
- while(1){
- lcd.setCursor(TextLCD::CurOn_BlkOn); //turn blinking cursor on
- while(!running) {
- uint8_t curButState = buttons.readBus();
-
- if(curButState != lastButState){
- switch(lastButState = curButState){
- case 0x1F: //right
- selectedFile = cyclePrograms(textFiles, numTextFiles, selectedFile, 1);
- break;
- case 0x2F: //left
- selectedFile = cyclePrograms(textFiles, numTextFiles, selectedFile, 0);
- break;
- }
- }
- }
- }
-
- */
-
- /*float speed = 0.5;
- while(1){
- bridges.drive(1, -1*speed);
- wait(2);
- bridges.drive(1, speed);
- wait(2);
- }*/
-
-//BridgeDriver::MOTOR_A
\ No newline at end of file
+
\ No newline at end of file