![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
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