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
main.cpp
- Committer:
- mehatfie
- Date:
- 2014-09-23
- Revision:
- 5:e36e0538a903
- Parent:
- 4:86d0d04cc055
- Child:
- 6:d1594fd2ec5a
File content as of revision 5:e36e0538a903:
#include "mbed.h" #include "LocalPinNames.h" #include "BridgeDriver.h" #include "FrontPanelButtons.h" #include "TextLCD.h" #include "SDFileSystem.h" #include "Initialization.hpp" #include "TextFile.h" #include <stdio.h> #include <string> #include <stdlib.h> #include <fstream> #include <vector> using std::string; FrontPanelButtons buttons(&i2c); //extern "C" void mbed_reset(); //enable software reset of code int interpretCommand(FILE *, LineData &); int loopCommand(FILE *, LineData &); /**********************************************************************************************************************************/ /**********************************************************************************************************************************/ /*************************** <FUNCTION: resetLineData> **************************/ /**********************************************************************************************************************************/ /**********************************************************************************************************************************/ void resetLineData(LineData &lineData){ //lineData.fullLine.clear(); lineData.lineNumber = 0; lineData.numWords = 0; lineData.lineAddress = 0; } /**********************************************************************************************************************************/ /**********************************************************************************************************************************/ /************************ <FUNCTION: cyclePrograms> *****************************/ /**********************************************************************************************************************************/ /**********************************************************************************************************************************/ int cyclePrograms(vector<string> files, int SIZE, int currIndex, int direction){ int nextIndex = 0; switch(direction){ case 0: //Cycle Back one File if ((currIndex - 1) < 0) nextIndex = SIZE - 1; else nextIndex = currIndex - 1; break; case 1: //Cycle Forward one File if ((currIndex + 1) >= SIZE) nextIndex = 0; else nextIndex = currIndex + 1; break; case -1: //set the selectedFile to the currIndex (used for initialization) nextIndex = currIndex; break; } //Output file on Display lcd.setAddress(0,3); 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]); return nextIndex; // Return the file index in the Array } /**********************************************************************************************************************************/ /**********************************************************************************************************************************/ /************************** <FUNCTION: conditionCommand> *****************************/ /**********************************************************************************************************************************/ /**********************************************************************************************************************************/ //Create an enum map of the positble conditions enum ConditionType{xAND, AND, xOR, OR, NONE}; //static const enum ConditionType Condition_Map[] = {xAND, AND, xOR, OR}; struct ConditionOp{ int value; //returned value of the interpret function: 1 = meets criteria, 0 = criteria not met, -1 = failed to interpret ConditionType op; //operator that follows the given parameter: x val 2 AND y val 3, if this ConditionOp is for x, then the value will be AND }; int conditionCommand(FILE *selectedFile, LineData &lineData){ //Get the number of condition parameters string numConditionVals = lineData.word[1]; int numConditionValues = 0; sscanf(numConditionVals.c_str(), "%d", &numConditionValues); //LineData tempLineData; LineData param[15]; //vector<LineData> param; vector<ConditionOp> paramCondition; /* int val1, val2, val3, val4; LineData temp; temp.numWords = 3; temp.word[1] = "val"; temp.word[2] = "1"; while (true){ temp.word[0] = "pin1"; val1 = interpretCommand(selectedFile, temp); temp.word[0] = "pin2"; val2 = interpretCommand(selectedFile, temp); temp.word[0] = "pin3"; val3 = interpretCommand(selectedFile, temp); temp.word[0] = "pin4"; val4 = interpretCommand(selectedFile, temp); lcd.cls(); //clear the display lcd.setAddress(0,0); lcd.printf("Pin1: %d", val1); lcd.setAddress(0,1); lcd.printf("Pin2: %d", val2); lcd.setAddress(0,2); lcd.printf("Pin3: %d", val3); lcd.setAddress(0,3); lcd.printf("Pin4: %d", val4); wait(0.2); }*/ //Fill the param Vector with Line structs of each individual device, this way we can send the Line struct to the appropriate interpret function without modification within the function itself int i = 2, numParam = 0, paramNumWords = 0; for (i = 2; i < lineData.numWords; i++){ lcd.setAddress(0,3); lcd.printf("Test2"); /*lcd.setAddress(0,2); lcd.printf("i: %d, nW-1: %d ", i, (lineData.numWords - 1)); wait(2);*/ // if the word is not an AND or an OR, it must mean it's for the specific function // set the current parameter's next word to be equal to the current word we're checking // increase number of words that the parameter has if (lineData.word[i] != "AND" && lineData.word[i] != "xAND" && lineData.word[i] != "OR" && lineData.word[i] != "xOR"){ // lcd.setAddress(0,3); // lcd.printf("%dlD[%d]: %s", numParam, i, lineData.word[i]); // wait(2); //tempLineData.word[paramNumWords] = lineData.word[i]; param[numParam].word[paramNumWords] = lineData.word[i]; paramNumWords++; //if this is the last word in the line.... if(i == (lineData.numWords - 1)){ param[numParam].numWords = paramNumWords; paramCondition[numParam].op = NONE; numParam++; } } // if the word is an AND or an OR, it must mean the last function has been completely identified // set the parameters number of Words value to the calculated value // increase the number of Parameters (the current parameter function we're filling) else if (lineData.word[i].compare("AND") == 0 || lineData.word[i].compare("xAND") == 0 || lineData.word[i].compare("OR") == 0 || lineData.word[i].compare("xOR") == 0){ //tempLineData.numWords = paramNumWords; param[numParam].numWords = paramNumWords; paramCondition.push_back(ConditionOp()); if (lineData.word[i].compare("AND") == 0) paramCondition[numParam].op = AND; else if (lineData.word[i].compare("xAND") == 0) paramCondition[numParam].op = xAND; else if (lineData.word[i].compare("OR") == 0) paramCondition[numParam].op = OR; else if (lineData.word[i].compare("xOR") == 0) paramCondition[numParam].op = xOR; //param.push_back(LineData()); //param[numParam] = tempLineData; //param.push_back(tempLineData); //add it to the vector list of parameters //tempLineData = LineData(); //reset numParam++; // increase the index of param paramNumWords = 0; // reset the number of words } } vector<ConditionOp> combinedCondition; ConditionOp tempCombinedCondition; int j = 0, k = 0, returnValue = -1; for (j = 0; j < numParam; j++){ paramCondition[j].value = interpretCommand(selectedFile, param[j]); } //create the combined Condition vector (take care of this xAND and xOR statements and combine them into one so that the whole vector is just AND's and OR's) //this should make the xAND's / xOR's into a single member of the combinedCondition vector enum ConditionType prevCondition = NONE; int first = 1, last = 0; for (k = 0; k < numParam; k++){ /* lcd.setAddress(0,3); lcd.printf("k: %d ", k); wait(1);*/ if (k == numParam - 1) last = 1; if (!last && (prevCondition != AND || prevCondition != OR)){ if (paramCondition[k].op != xAND && paramCondition[k].op != xOR && paramCondition[k + 1].op != xAND && paramCondition[k + 1].op != xOR){ /* lcd.setAddress(0,3); lcd.printf("Test 0.1 "); wait(1);*/ //AND if (paramCondition[k].op == AND){ if (!first && prevCondition != xAND && prevCondition != xOR){ /* lcd.setAddress(0,3); lcd.printf("Test 1.6 "); wait(1);*/ combinedCondition.back().value = combinedCondition.back().value && paramCondition[k + 1].value; } else if (first || prevCondition == xAND || prevCondition == xOR){ /* lcd.setAddress(0,3); lcd.printf("Test 1.5 "); wait(1);*/ tempCombinedCondition.value = paramCondition[k].value && paramCondition[k + 1].value; combinedCondition.push_back(tempCombinedCondition); first = 0; } prevCondition = AND; } //OR else if (paramCondition[k].op == OR){ if (!first && prevCondition != xAND && prevCondition != xOR){ combinedCondition.back().value = combinedCondition.back().value || paramCondition[k + 1].value; /*lcd.setAddress(0,3); lcd.printf("Test 1.1 "); wait(1);*/ }else if (first || prevCondition == xAND || prevCondition == xOR){ /* lcd.setAddress(0,3); lcd.printf("Test 1.2 "); wait(1);*/ tempCombinedCondition.value = paramCondition[k].value || paramCondition[k + 1].value; combinedCondition.push_back(tempCombinedCondition); first = 0; } prevCondition = OR; } } else{ /*lcd.setAddress(0,3); lcd.printf("Test 0.2 "); wait(1);*/ //xAND if (paramCondition[k].op == xAND && prevCondition == xAND){ /*lcd.setAddress(0,3); lcd.printf("Test 2 "); wait(1);*/ combinedCondition.back().value = combinedCondition.back().value && paramCondition[k + 1].value; prevCondition = xAND; } else if (paramCondition[k].op == xAND && prevCondition != xAND){ /*lcd.setAddress(0,3); lcd.printf("Test 1 "); wait(1);*/ tempCombinedCondition.value = paramCondition[k].value && paramCondition[k + 1].value; combinedCondition.push_back(tempCombinedCondition); prevCondition = xAND; } /*else if (paramCondition[k].op != xAND && prevCondition == xAND){ combinedCondition.back().op = paramCondition[k].op; prevCondition = xAND; }*/ //xOR else if (paramCondition[k].op == xOR && prevCondition == xOR){ /*lcd.setAddress(0,3); lcd.printf("Test 1.3 "); wait(1);*/ combinedCondition.back().value = combinedCondition.back().value || paramCondition[k + 1].value; prevCondition = xOR; } else if (paramCondition[k].op == xOR && prevCondition != xOR){ /* lcd.setAddress(0,3); lcd.printf("Test 1.4 "); wait(1);*/ tempCombinedCondition.value = paramCondition[k].value || paramCondition[k + 1].value; combinedCondition.push_back(tempCombinedCondition); prevCondition = xOR; } /*else if (paramCondition[k].op != xOR && prevCondition == xOR){ combinedCondition.back().op = paramCondition[k].op; prevCondition = xOR; }*/ // Since the k + 1 value is included in the xAND or xOR exclusively, skip checking that value, and add the appropriate AND / OR as the // operator of this exclusive xAND / xOR set if ((paramCondition[k + 1].op == AND || paramCondition[k + 1].op == OR) && (prevCondition == xAND || prevCondition == xOR)){ /*lcd.setAddress(0,3); lcd.printf("Test 3 "); wait(1);*/ combinedCondition.back().op = paramCondition[k + 1].op; k++; } } } //the last value was not included in any combination, since directly before the last value was an xAND / xOR set that // included the very last AND / OR as the set's operator else{ /*lcd.setAddress(0,3); lcd.printf("Test 5 "); wait(1);*/ tempCombinedCondition.value = paramCondition[k].value; tempCombinedCondition.op = NONE; combinedCondition.push_back(tempCombinedCondition); } //reset the tempCombinedCondition variable tempCombinedCondition = ConditionOp(); } // run through all values in the combined Condition vector, AND'ing / OR'ing as appropriate // in the end, the last value in the array should be the final condition of the Condition statement... whether it was successful or failed for (i = 0; i < (combinedCondition.size() - 1); i++){ if (combinedCondition[i].op == AND) combinedCondition[i + 1].value = combinedCondition[i].value && combinedCondition[i + 1].value; else if (combinedCondition[i].op == OR) combinedCondition[i + 1].value = combinedCondition[i].value || combinedCondition[i + 1].value; } int conditionSuccess = combinedCondition.back().value; //value is the success(1) or failure(0) of the condition statement int checkEnd = 0; if (!conditionSuccess){ lcd.setAddress(0,3); lcd.printf("CONDITION FAILURE"); wait(1); while (checkEnd != 4){ getNextLine(selectedFile, lineData); if (lineData.word[0].compare("end") == 0) checkEnd = interpretCommand(selectedFile, lineData); if (checkEnd == 4) // custom return value for this function return 0; } } lcd.setAddress(0,3); lcd.printf("CONDITION SUCCESS"); wait(1); int returnValue2 = 1; // Return success as the function either met the condition and will continue from the next line, or // failed to meet the condition and ran through the lines inside the condition until "end condition" was found, therefore // the program will proceed from the line after the "end condition" line return returnValue2; } /* for (k = 0; k < numParam; k++){ if (paramCondition[k].op == AND){ if (paramCondition[k + 1].op != xAND && paramCondition[k + 1].op != xOR) tempCombinedCondition.value = paramCondition[k].value && paramCondition[k + 1].value; else tempCombinedCondition.value = paramCondition[k].value; tempCombinedCondition.op = AND; combinedCondition.push_back(tempCombinedCondition); prevCondition = AND; } else if (paramCondition[k].op == OR){ if (paramCondition[k + 1].op != xAND && paramCondition[k + 1].op != xOR) tempCombinedCondition.value = paramCondition[k].value || paramCondition[k + 1].value; else tempCombinedCondition.value = paramCondition[k].value; tempCombinedCondition.op = OR; combinedCondition.push_back(tempCombinedCondition); prevCondition = OR; } else if (paramCondition[k].op == xAND){ if (prevCondition == xAND) // if previous one was also xAND, that means we already have a vector member for this (this last member) combinedCondition.back().value = combinedCondition.back().value && paramCondition[k + 1].value; else{ // if the prevCondition was not xAND, then we need to add a new member to the vector tempCombinedCondition.value = paramCondition[k].value && paramCondition[k + 1].value; combinedCondition.push_back(tempCombinedCondition); } prevCondition = xAND; } else if (paramCondition[k].op == xOR){ tempCombinedCondition.value = paramCondition[k].value || paramCondition[k + 1].value; prevCondition = xOR; } } return 1;*/ /**********************************************************************************************************************************/ /**********************************************************************************************************************************/ /************************** <FUNCTION: loopCommand> *****************************/ /**********************************************************************************************************************************/ /**********************************************************************************************************************************/ int loopCommand(FILE *selectedFile, LineData &lineData){ //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 loopStartAddress = 0, loopLineNumber = 0, firstLineOfLoop = 1; int counter = 0, checkEnd = 0; while (counter < loopConditionValue){ /*lcd.setAddress(0,3); lcd.printf("BcheckEnd: %d ", checkEnd); wait(1);*/ getNextLine(selectedFile, lineData); //Must get the address before entering the interpret command // if a Condition command is immediately after, and the condition fails, then // the interpret command will return the line at the "end condition" line, and therefore // set the loop's first line to be the "end condition" line, if interpretCommand is called BEFORE setting the first loop line address if (firstLineOfLoop){ loopStartAddress = lineData.lineAddress; //Save the Line Address loopLineNumber = lineData.lineNumber; //Save the Line Number firstLineOfLoop = 0; } checkEnd = interpretCommand(selectedFile, lineData); /*lcd.setAddress(0,3); lcd.printf("AcheckEnd: %d ", checkEnd); wait(1);*/ /* lcd.setAddress(0,3); lcd.printf("checkEnd: %d ", checkEnd); wait(2);*/ //Increase the loop counter and go back to the beginning of the loop if (checkEnd == 3){ counter++; lcd.setAddress(0,2); lcd.printf("Loop Cycle %d of %d", counter, loopConditionValue); fseek(selectedFile, loopStartAddress, SEEK_SET); lineData.lineNumber = loopLineNumber - 2; checkEnd = 0; } } return 1; } /**********************************************************************************************************************************/ /**********************************************************************************************************************************/ /************************* <FUNCTION: interpretCommand> *************************/ /**********************************************************************************************************************************/ /**********************************************************************************************************************************/ int interpretCommand(FILE *selectedFile, LineData &lineData){ if (lineData.word[0].compare("device") == 0){ int i = 0, deviceFound = -1; for (i = 0; i < numDevices; i++){ if (lineData.word[2].compare(DeviceNames[i]) == 0){ 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 ************************* } //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]; } } else if (lineData.word[0].compare("delay") == 0){ string duration = lineData.word[1]; int durationValue = 0; sscanf(duration.c_str(), "%d", &durationValue); if (durationValue){ 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 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("condition") == 0){ int checkLoopEnd = conditionCommand(selectedFile, lineData); if (checkLoopEnd == 1) return 2; } // end with custom return value for specific function else if (lineData.word[0].compare("end") == 0){ if (lineData.word[1].compare("program") == 0){ return 2; } else if (lineData.word[1].compare("loop") == 0){ return 3; } else if (lineData.word[1].compare("condition") == 0){ return 4; } } //not a keyword so check if it's a localName for a device else{ int i = 0, deviceFound = -1; for (i = 0; i < devices.size(); i++){ if (lineData.word[0].compare(devices[i]->name) == 0) deviceFound = i; } //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); } //Local Name matches a device, send line to that device in order to process the functionality else{ //addDevice(deviceFound); return devices[deviceFound]->interpret(lineData); } } return -1; } /**********************************************************************************************************************************/ /**********************************************************************************************************************************/ /****************************** <FUNCTION: main> ********************************/ /**********************************************************************************************************************************/ /**********************************************************************************************************************************/ int main() { fullInit(); //Initialize anything that's required to run the code (LCD) struct 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); /******************************************************************************/ /*** <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); uint8_t lastButState; lcd.setCursor(TextLCD::CurOn_BlkOn); //turn blinking cursor on 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()); /******************************************************************************/ /*** <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); } while(1){ resetLineData(lineData); 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; while (!endOfFile){ getNextLine(selectedFile, lineData); int checkEnd = interpretCommand(selectedFile, lineData); if (checkEnd == 0) endOfFile = 1; } lcd.cls(); //clear the display lcd.setAddress(0,0); lcd.printf("END OF PROGRAM"); lcd.setAddress(0,2); lcd.printf("To Restart..."); lcd.setAddress(0,3); lcd.printf("Press BACK"); while(!buttons.readBack()); lcd.setAddress(0,1); //rewind(selectedFile); } } /***** 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