diff --git a/DisplayESP32_SSD1306.h b/DisplayESP32_SSD1306.h new file mode 100644 index 0000000..b7d27a3 --- /dev/null +++ b/DisplayESP32_SSD1306.h @@ -0,0 +1,23 @@ +#define MAX_OPTIONS 10 //Maximum number of options for each menu +#define MAX_MENUS 3 +#define MAX_GRAPHS 3 +#define MAX_MODIFIERS 3 +#define DISP_WIDTH 128 // OLED display width +#define DISP_HEIGHT 64 // OLED display height +#define REFRESH 10 //Refresh time in ms + +//The following constants are used to configure the behaviour of the interface +// MAX_OPTIONS defines the maximum number of options a menu can hold +// MAX_MENUS declares the maximum number of menu screens in the interface +// MAX_GRAPHS is the maximum number of graphs to create +// DISP_WIDTH and DISP_HEIGHT are hardware specific (SSD1306) +// REFRESH: is the time in miliseconds the interface will take in refreshing (this time affects the loop, keep that in mind) + +Adafruit_SSD1306 display(DISP_WIDTH, DISP_HEIGHT, &Wire, -1); + +#include "resources/Option.h" +#include "resources/Menu.h" +#include "resources/Graph.h" +#include "resources/Modifier.h" +#include "resources/Screen.h" +#include "resources/Keyboard.h" diff --git a/Simple_Implementation.ino b/Simple_Implementation.ino new file mode 100644 index 0000000..1ecee55 --- /dev/null +++ b/Simple_Implementation.ino @@ -0,0 +1,65 @@ +#include +#include +#include +#include +#define __DEBUG__ + + +#include "DisplayESP32_SSD1306.h" + +int i = 0; +int multiplier = 1; + +Screen screen; +Keyboard keyboard(13, 12, 14, 27, 30, &screen); + +void setup(){ + screen.configure(true, 0x3C); + + screen.createMenu(128, 13); //Menu 0 + screen.createMenu(128, 13); //Menu 1 + + /*String title, char graphType, double xpos, double ypos, double width, double height, + double yminimum, double ymaximum, double xminimum, double xmaximum, double yStepSize, double xStepSize, double digit*/ + + screen.createVGraph("Grafica 1", 25, 60, 40, 40, 0, 100, 10, 0); //Graph 0 + screen.createHGraph("Grafica 2", 10, 40, 100, 20, 0, 100, 10, 0); //Graph 1 + screen.createCGraph("Grafica 3", 30, 50, 75, 30, 0, 100, 0, 1000, 25, 250, 0); //Graph 2 + + screen.createModifier("Modify variable", &multiplier, 5, 1, 1); + + screen.createOption(0, "Vertical graph", 1, 0); + //Creates the first option in Menu 0, directing to a graph (contentType = 1 (Graph)), 0 (Graph 0) + screen.createOption(0, "Horizontal graph", 1, 1); + screen.createOption(0, "Cartesian graph", 1, 2); + screen.createOption(0, "Extra option", 0, 1); + + screen.createOption(1, "Test", 1, 3); + screen.createOption(1, "Working?", 2, 2); + screen.createOption(1, "Modify variable", 2, 0); + +// screen.increasePos(); +// screen.increasePos(); +// screen.goTo(); +// screen.graphAssignValue(2, 50); +// screen.goBack(); +// screen.increasePos(); +// screen.goTo(); +// screen.goBack(); +// screen.decreasePos(); +} + +void loop(){ + screen.control(); //Controls the screen and redraws if needed + keyboard.control(); + + if(i <= 100){ + screen.graphAssignValue(1, i); //Assigning a demo value to Graph 1 + screen.graphAssignValue(2, i); //Assigning a demo value to Graph 2 + i += multiplier; + } + else + i = 0; + + delay(REFRESH); //Refresh time (approx) +} \ No newline at end of file diff --git a/Singleshot_Graph.ino b/Singleshot_Graph.ino new file mode 100644 index 0000000..f560fe2 --- /dev/null +++ b/Singleshot_Graph.ino @@ -0,0 +1,57 @@ +#include +#include +#include +#include +#define __DEBUG__ + + +#include "DisplayESP32_SSD1306.h" + +int i = 0; +int multiplier = 1; +int samples = 1000; + +Screen screen; +Keyboard keyboard(13, 12, 14, 27, 30, &screen); + +void setup(){ + screen.configure(true, 0x3C); + + screen.createMenu(128, 13); //Menu 0 + + screen.createCGraph("Test", 30, 50, 75, 30, 0, 100, 0, 1000, 25, 250, 0); //Graph 0 + + screen.createModifier("Multiplier", &multiplier, 5, 1, 1); //Modifier 0 + screen.createModifier("Samples number", &samples, 1000, 500, 10); //Modifier 1 + + screen.createOption(0, "Adjust multiplier", 2, 0); + screen.createOption(0, "Adjust samples #", 2, 1); + + screen.createOption(0, "Run test", 1, 0); +} + +void loop(){ + while(screen.getCurrentScreen() != 0 || screen.getContentType() != 1){ + screen.control(); //Controls the screen and redraws if needed while not in the test's graph + keyboard.control(); + delay(REFRESH); + } + + for(int j = 0; j <= samples; j++){ + if(i <= 100){ + screen.graphAssignValue(0, i); //Assigning a demo value to Graph 0 + i += multiplier; + } + else + i = 0; + screen.control(); + Serial.println(samples); + delay(REFRESH); + } + + while(screen.getCurrentScreen() == 0 && screen.getContentType() == 1){ + screen.control(); //Controls the screen and redraws if needed while not in the test's graph + keyboard.control(); + delay(REFRESH); + } +} \ No newline at end of file diff --git a/resources/Graph.h b/resources/Graph.h new file mode 100644 index 0000000..b36b623 --- /dev/null +++ b/resources/Graph.h @@ -0,0 +1,245 @@ +class Graph{ //ContentType (1) + private: + + String title; + char graphType; //'a' Vertical Bar, 'b' Horizontal Bar, 'c' Cartesian Graph + + //Assign whatever value in "configure(..." if a parameter is not required for the specified graphType + + double value; //For: Vertical Bar Horizontal Bar Cartesian + double xpos; //For: Vertical Bar Horizontal Bar Cartesian + double ypos; //For: Vertical Bar Horizontal Bar Cartesian + double height; //For: Vertical Bar Horizontal Bar Cartesian + double width; //For: Vertical Bar Horizontal Bar Cartesian + double yminimum; //For: Vertical Bar Cartesian + double ymaximum; //For: Vertical Bar Cartesian + double xminimum; //For: Horizontal Bar Cartesian + double xmaximum; //For: Horizontal Bar Cartesian + double yStepSize; //For: Vertical Bar Cartesian + double xStepSize; //For: Horizontal Bar Cartesian + int digit; //For: Vertical Bar Horizontal Bar Cartesian + double x; + double yrange; + double xrange; + double ox; + double oy; + double count; + double graphScale; + bool redraw = true; + + int previousScreen = 0; + int previousContentType = 0; + + public: + +//This method configures the graph created, defines its parameters according the type of graph selected. + void configure(String title, char graphType, double xpos, double ypos, double width, double height, + double yminimum, double ymaximum, double xminimum, double xmaximum, double yStepSize, double xStepSize, int digit){ + this->title = title; + this->graphType = graphType; + this->yminimum = yminimum; + this->ymaximum = ymaximum; + this->xminimum = xminimum; + this->count = xminimum; + this->xmaximum = xmaximum; + this->height = height; + this->width = width; + this->yStepSize = yStepSize; + this->xStepSize = xStepSize; + this->digit = digit; + this->xpos = xpos; + this->ypos = ypos; + switch(graphType){ + case 'a': + this->yrange = ymaximum - yminimum; + this->graphScale = (yStepSize) * (height / this->yrange) - .001; //Adjusts the scale of the graph, according to the range and the size of the step + break; + + case 'b': + this->xrange = xmaximum - xminimum; + this->graphScale = (xStepSize) * (width / this->xrange) - .001; //Adjusts the scale of the graph, according to the range and the size of the step + break; + + case 'c': + this->yrange = ymaximum - yminimum; + this->xrange = xmaximum - xminimum; + break; + } + } + + void drawGraph(){ + double level, data, i; + switch(graphType){ + case 'a': + double my; + + if (this->redraw) { //Prints the labels + display.clearDisplay(); + this->redraw = false; + display.fillRect(0, 0, 127 , 14, SSD1306_WHITE); + display.setTextColor(SSD1306_BLACK, SSD1306_WHITE); + display.setTextSize(1); + display.setCursor(2, 4); + display.println(this->title); + + for (i = 0; i <= this->height; i += this->graphScale) { + my = this->ypos - this->height + i; + display.drawFastHLine(this->xpos + this->width + 1, my, 5, SSD1306_WHITE); + // draw lables + display.setTextSize(1); + display.setTextColor(SSD1306_WHITE, SSD1306_BLACK); + display.setCursor(this->xpos + this->width + 12, my - 3 ); + data = this->ymaximum - ( i * (this->yStepSize / this->graphScale)); + display.print(data, this->digit); + } + } + // compute level of bar graph that is scaled to the height and the hi and low vals + // this is needed to accompdate for +/- range + level = (this->height * (((this->value - this->yminimum) / (this->yrange)))); + // draw the bar graph + // write a upper and lower bar to minimize flicker cause by blanking out bar and redraw on update + display.drawRect(this->xpos, this->ypos - this->height, this->width, this->height, SSD1306_WHITE); + display.fillRect(this->xpos, this->ypos - this->height, this->width, this->height - level, SSD1306_BLACK); + display.drawRect(this->xpos, this->ypos - this->height, this->width, this->height, SSD1306_WHITE); + display.fillRect(this->xpos, this->ypos - level, this->width, level, SSD1306_WHITE); + // up until now print sends data to a video buffer NOT the screen + // this call sends the data to the screen + display.display(); + break; + + case 'b': + + if (this->redraw) { + display.clearDisplay(); + this->redraw = false; + display.fillRect(0, 0, 127 , 16, SSD1306_WHITE); + display.setTextColor(SSD1306_BLACK, SSD1306_WHITE); + display.setTextSize(1); + display.setCursor(2, 4); + display.println(this->title); + // draw the text + + for (i = 0; i <= this->width; i += this->graphScale) { + display.drawFastVLine(i + this->xpos , this->ypos , 5, SSD1306_WHITE); + // draw lables + display.setTextSize(1); + display.setTextColor(SSD1306_WHITE, SSD1306_BLACK); + display.setCursor(i + this->xpos , this->ypos + 10); + // addling a small value to eliminate round off errors + // this val may need to be adjusted + data = ( i * (this->xStepSize / this->graphScale)) + this->xminimum + 0.00001; + display.print(data, this->digit); + } + } + // compute level of bar graph that is scaled to the width and the hi and low vals + // this is needed to accompdate for +/- range capability + // draw the bar graph + // write a upper and lower bar to minimize flicker cause by blanking out bar and redraw on update + level = (this->width * (((this->value - this->xminimum) / (this->xmaximum - this->xminimum)))); + display.fillRect(this->xpos + level, this->ypos - this->height, this->width - level, this->height, SSD1306_BLACK); + display.drawRect(this->xpos, this->ypos - this->height, this->width, this->height, SSD1306_WHITE); + display.fillRect(this->xpos, this->ypos - this->height, level, this->height, SSD1306_WHITE); + // up until now print sends data to a video buffer NOT the screen + // this call sends the data to the screen + display.display(); + break; + + case 'c': + double temp; + + if (this->redraw == true) { + this->redraw = false; + display.clearDisplay(); + display.fillRect(0, 0, 127 , 16, SSD1306_WHITE); + display.setTextColor(SSD1306_BLACK, SSD1306_WHITE); + display.setTextSize(1); + display.setCursor(2, 4); + display.println(title); + this->ox = (this->count - this->xminimum) * (this->width) / (this->xrange) + this->xpos; + this->oy = (this->value - this->yminimum) * (- this->height) / (this->yrange) + this->ypos; + // draw y scale + display.setTextSize(1); + display.setTextColor(SSD1306_WHITE, SSD1306_BLACK); + for ( i = this->yminimum; i <= this->ymaximum; i += this->yStepSize) { + // compute the transform + // note my transform funcition is the same as the map function, except the map uses long and we need doubles + temp = (i - this->yminimum) * (- this->height) / (this->ymaximum - this->yminimum) + this->ypos; + if (i == 0) { + display.drawFastHLine(this->xpos - 3, temp, this->width + 3, SSD1306_WHITE); + } + else { + display.drawFastHLine(this->xpos - 3, temp, 3, SSD1306_WHITE); + } + display.setCursor(this->xpos - 27, temp - 3); + display.println(i, this->digit); + } + // draw x scale + for (i = this->xminimum; i <= this->xmaximum; i += this->xStepSize) { + // compute the transform + display.setTextSize(1); + display.setTextColor(SSD1306_WHITE, SSD1306_BLACK); + temp = (i - this->xminimum) * (this->width) / (this->xrange) + this->xpos; + if (i == 0) { + display.drawFastVLine(temp, this->ypos - this->height, this->height + 3, SSD1306_WHITE); + } + else { + display.drawFastVLine(temp, this->ypos, 3, SSD1306_WHITE); + } + display.setCursor(temp, this->ypos + 6); + display.println(i, this->digit); + } + } + + // graph drawn now plot the data + // the entire plotting code are these few lines... + + this->x = (this->count - this->xminimum) * (this->width) / (this->xrange) + this->xpos; + this->value = (this->value - this->yminimum) * (- this->height) / (this->yrange) + this->ypos; + display.drawLine(this->ox, this->oy, this->x, this->value, SSD1306_WHITE); + display.drawLine(this->ox, this->oy - 1, this->x, this->value - 1, SSD1306_WHITE); + this->ox = this->x; + this->oy = this->value; + + // up until now print sends data to a video buffer NOT the screen + // this call sends the data to the screen + display.display(); + this->count += 1; + if(this->ox >= (this->xpos + this->width)){ + this->redraw = true; + this->count = xminimum; + } + } + } + + void redrawFlag(){ // Activates the redraw bool to get the graph printed correctly + this->redraw = true; + this->count = xminimum; + } + + void setPreviousScreen(int prev){ + this->previousScreen = prev; + } + + void setPreviousContentType(int prev){ + this->previousContentType = prev; + } + + int getPreviousScreen(){ + int prev = this->previousScreen; + return prev; + } + + int getPreviousContentType(){ + int prev = this->previousContentType; + return prev; + } + + void assignValue(double value){ + this->value = value; + } + + void reset(){ + this->x = 0; + } + +}; diff --git a/resources/Keyboard.h b/resources/Keyboard.h new file mode 100644 index 0000000..77c5929 --- /dev/null +++ b/resources/Keyboard.h @@ -0,0 +1,82 @@ +class Keyboard{ + private: + + byte goTo; + byte goBack; + byte plus; + byte minus; + byte debounceTime; + + Screen *screen; + + public: + +//Keyboard constructor + Keyboard(byte goTo, byte goBack, byte plus, byte minus, byte debounceTime, Screen * screen){ + this->goTo = goTo; + this->goBack = goBack; + this->plus = plus; + this->minus = minus; + this->debounceTime = debounceTime; + + this->screen = screen; + + pinMode(goTo, INPUT_PULLUP); + pinMode(goBack, INPUT_PULLUP); + pinMode(plus, INPUT_PULLUP); + pinMode(minus, INPUT_PULLUP); + } +//Debouncing functions + void checkGoTo(){ + static char cont; + if(digitalRead(this->goTo) == LOW) + cont++; + else + cont = 0; + if(cont == debounceTime/REFRESH){ + this->screen->goTo(); + } + } + + void checkGoBack(){ + static char cont; + if(digitalRead(this->goBack) == LOW){ + cont++; + } + else + cont = 0; + if(cont == debounceTime/REFRESH){ + this->screen->goBack(); + } + } + + void checkPlus(){ + static char cont; + if(digitalRead(this->plus) == LOW) + cont++; + else + cont = 0; + if(cont == debounceTime/REFRESH){ + this->screen->plusAction(); + } + } + + void checkMinus(){ + static char cont; + if(digitalRead(this->minus) == LOW) + cont++; + else + cont = 0; + if(cont == debounceTime/REFRESH){ + this->screen->minusAction(); + } + } + +// All buttons are checked with this method + void control(){ + this->checkGoTo(); + this->checkGoBack(); + this->checkPlus(); + this->checkMinus(); + } +}; diff --git a/resources/Menu.h b/resources/Menu.h new file mode 100644 index 0000000..235cde8 --- /dev/null +++ b/resources/Menu.h @@ -0,0 +1,85 @@ +class Menu{ //ContentType (0) + private: + + int sizex; //X size for each option in the menu + int sizey; //Y size of each option in the menu + int options = 0; //This indicates the number of options created + int pos = 0; //This indicates the position of the cursor + int page = 0; //If the menu is too long, this indicates the page that is being displayed + Option opt[MAX_OPTIONS]; + int optPPage; + + int previousScreen = 0; + int previousContentType = 0; + + public: + + void configure(int sizex, int sizey){ //This method configures the menu created from Screen + this->sizex = sizex; + this->sizey = sizey; + this->optPPage = DISP_HEIGHT / this->sizey; + } + + //The following method is used to created an option for the menu + void createOption(String content, int destinationType, int destinationIndex){ + //The option takes the place in the array defined by the options number variable (options), which is later increased. + this->opt[this->options].configure(content, this->sizex, this->sizey, this->options++, destinationType, destinationIndex); + } + + int extractDestinationType(){ + int destinationType = this->opt[this->pos].getDestinationType(); + return destinationType; + } + + int extractDestinationIndex(){ + int destinationIndex = this->opt[this->pos].getDestinationIndex(); + return destinationIndex; + } + +//The following method draws the whole menu by drawing every option configured within it + void drawMenu(){ + display.clearDisplay(); + this->page = pos/this->optPPage; //The current page is obtained by dividing the position by the number of options per page (only integer) + for(int i = 0; i < options; i++){ + this->opt[i].drawopt(this->page, this->pos, this->optPPage); + } + display.display(); + } + //Methods used by Screen + int extractPos(){ //Gets the current position of the cursor + return(this->pos); + } + + int extractOptNumber(){ //Gets the number of options in the menu + return(this->options); + } + + void increasePos(){ //Increases the position of the cursor + this->pos++; + } + + void decreasePos(){ //Decreases the position of the cursor + this->pos--; + } + +//Both of the following methods store the values of the previous screen passed as parameters by Screen + + void setPreviousScreen(int prev){ + this->previousScreen = prev; + } + + void setPreviousContentType(int prev){ + this->previousContentType = prev; + } + +//Both of the following methods retrieve the values of the screen previous to the menu containing these data. + int getPreviousScreen(){ + int prev = this->previousScreen; + return prev; + } + + int getPreviousContentType(){ + int prev = this->previousContentType; + return prev; + } +}; diff --git a/resources/Modifier.h b/resources/Modifier.h new file mode 100644 index 0000000..bafbc7c --- /dev/null +++ b/resources/Modifier.h @@ -0,0 +1,70 @@ +class Modifier{ //ContentType (2) + private: + + String title; + int *value; + int max; + int min; + int step; + + int previousScreen = 0; + int previousContentType = 0; + + public: + + void configure(String title, int *value, int max, int min, int step){ + this->title = title; + this->value = value; + this->max = max; + this->min = min; + this->step = step; + } + + void drawModifier(){ + display.clearDisplay(); + display.fillRect(0, 0, 127 , 16, SSD1306_WHITE); + display.setTextColor(SSD1306_BLACK, SSD1306_WHITE); + display.setTextSize(1); + display.setCursor(2, 4); + display.println(this->title); + + display.setTextColor(SSD1306_WHITE); + display.setTextSize(3); + display.setCursor(2, ((DISP_HEIGHT - 16 - 15)/2) + 16); + display.println(*this->value); + + display.display(); + + display.setTextSize(1); + } + + void increaseValue(){ + if((*this->value + this->step) <= this->max){ + *this->value += this->step; + } + } + + void decreaseValue(){ + if((*this->value - this->step) >= this->min){ + *this->value -= this->step; + } + } + + void setPreviousScreen(int prev){ + this->previousScreen = prev; + } + + void setPreviousContentType(int prev){ + this->previousContentType = prev; + } + + int getPreviousScreen(){ + int prev = this->previousScreen; + return prev; + } + + int getPreviousContentType(){ + int prev = this->previousContentType; + return prev; + } +}; diff --git a/resources/Option.h b/resources/Option.h new file mode 100644 index 0000000..a284eb4 --- /dev/null +++ b/resources/Option.h @@ -0,0 +1,58 @@ +class Option{ + private: + + int sizex; //Defines the size it will occupy in the x axis (width), this value is gotten from the menu + int sizey; //Defines the height of the option (this value is gotten from the menu it belongs to) + String content; //Text of the option + int pos; //Defines the position it has in the menu + int textSpacing; //According to the height, defines the space for the text, so that it's vertically centered + bool fill = false; //In case an option is not selected this should be false + bool disp = false; //In case an option is not configured, it should be false and, thus hidden + int destinationType; //Defines what the option leads to (another menu, graph, something else) + int destinationIndex; //Defines where the option leads to (index of the destination) + + public: + + //Option(){} + + //Method to configure an option, all attributes are assigned, and disp is true, so the option can be displayed + void configure(String content, int sizex, int sizey, int pos, int destinationType, int destinationIndex){ + this->sizex = sizex; + this->sizey = sizey; + this->content = content; + this->pos = pos; + this->destinationType = destinationType; + this->destinationIndex = destinationIndex; + this->disp = true; + this->textSpacing = ((sizey - 7)/2) + 7; + } + + int getDestinationType(){ + int destinationType = this->destinationType; + return destinationType; + } + + int getDestinationIndex(){ + int destinationIndex = this->destinationIndex; + return destinationIndex; + } + +//This method draws each option + + void drawopt(int page, int pos, int optPPage){ + if(this->disp){ //Checks if the option was configured and, as a result, is displayable + if(this->pos == pos){ //If the position of the option corresponds to the position passed to the function, then it should be selected + display.fillRect(0, (this->sizey)*(this->pos) + 1 - (page*optPPage*this->sizey), this->sizex, this->sizey, WHITE); + display.setTextColor(SSD1306_BLACK); + display.setCursor(5, (this->sizey)*(this->pos + 1) - (page*optPPage*this->sizey) - this->textSpacing); + display.print(this->content); + display.setTextColor(SSD1306_WHITE); + } + else{ //If the option is not selected, the rectangle containing it shouldn't be filled + display.drawRect(0, (this->sizey)*(this->pos) + 1 - (page*optPPage*this->sizey), this->sizex, this->sizey, WHITE); + display.setCursor(5, (this->sizey)*(this->pos + 1) - (page*optPPage*this->sizey) - this->textSpacing); + display.print(this->content); + } + } + } +}; diff --git a/resources/Screen.h b/resources/Screen.h new file mode 100644 index 0000000..15f86b7 --- /dev/null +++ b/resources/Screen.h @@ -0,0 +1,192 @@ +class Screen{ + private: + + Menu menu[MAX_MENUS]; //Array of menus to use + Graph graph[MAX_GRAPHS]; //Array of graphs to use + Modifier modifier[MAX_MODIFIERS]; //Array of modifiers to use + + int counterM = 0; //Number of menus created + int counterG = 0; //Number of graphs created + int counterMod = 0; + bool redraw = true; //Redraw interface for when there is a change of screen + int currentScreen = 0; + int contentType = 0; + + public: + + + void configure(bool fullsetting, char address){ //This method allows the configuration of the display when the parameter is true. Otherwise only prints a greeting message. + if(fullsetting){ + //Adafruit_SSD1306 display(DISP_WIDTH, DISP_HEIGHT, &Wire, -1); + Serial.begin(115200); + if (!display.begin(SSD1306_SWITCHCAPVCC, address)) { + #ifdef __DEBUG__ + Serial.println("Display not found!"); + #endif + while (true); + } + } + display.clearDisplay(); + + // Text size + display.setTextSize(2); + // Text color + display.setTextColor(SSD1306_WHITE); + // Text position + + display.setCursor(25, 20); + display.println("Welcome"); + + + display.setTextSize(1); + + display.display(); + delay(5000); + } + + void createMenu(int sizex, int sizey){ //This method is used for the creation of a menu + this->menu[counterM].configure(sizex, sizey); + this->counterM++; + } + + void createOption(int menuIndex, String content, int destinationType, int destinationIndex){ //this method should be used for creating an option in a menu + this->menu[menuIndex].createOption(content, destinationType, destinationIndex); + } + + void createVGraph(String title, double xpos, double ypos, double width, double height, + double yminimum, double ymaximum, double yStepSize, int digit){ //this method calls the configure() of graph for a vertical graph + this->graph[counterG].configure(title, 'a', xpos, ypos, width, height, yminimum, ymaximum, 0, 0, yStepSize, 0, digit); + this->counterG++; + } + + void createHGraph(String title, double xpos, double ypos, double width, double height, + double xminimum, double xmaximum, double xStepSize, int digit){ //this method calls the configure() of graph for a horizontal graph + this->graph[counterG].configure(title, 'b', xpos, ypos, width, height, 0, 0, xminimum, xmaximum, 0, xStepSize, digit); + counterG++; + } + + void createCGraph(String title, double xpos, double ypos, double width, double height, + double yminimum, double ymaximum, double xminimum, double xmaximum, double yStepSize, double xStepSize, int digit){ //this method calls the configure() of graph for a cartesian chart + this->graph[counterG].configure(title, 'c', xpos, ypos, width, height, yminimum, ymaximum, xminimum, xmaximum, yStepSize, xStepSize, digit); + counterG++; + } + + void createModifier(String title, int *value, int max, int min, int step){ //This method is used for the creation of a menu + this->modifier[counterMod].configure(title, value, max, min, step); + this->counterMod++; + } + +/* + void redrawFlag(){ + this->redraw = true; + } +*/ + +//The following method is used for assingning a value to a graph +//This can be avoided using pointers to the variable to plot in the graph + void graphAssignValue(int graphIndex, double value){ + this->graph[graphIndex].assignValue(value); + if(this->currentScreen == graphIndex && this->contentType == 1) + this->redraw = true; + } + +//This method controls the whole interface, it needs to be called within a loop + void control(){ + if (redraw){ + if (contentType == 0){ + menu[currentScreen].drawMenu(); + } + else if (contentType == 1){ + graph[currentScreen].drawGraph(); + } + else if (contentType == 2){ + modifier[currentScreen].drawModifier(); + } + this->redraw = false; + } + } + +//The following two methods allow the change in position of the cursor + void increasePos(){ + if(this->menu[this->currentScreen].extractPos() < this->menu[this->currentScreen].extractOptNumber() - 1) + this->menu[this->currentScreen].increasePos(); + } + + void decreasePos(){ + if(this->menu[this->currentScreen].extractPos() > 0) + this->menu[this->currentScreen].decreasePos(); + } + +//This method lets the user go into another screen by selecting an option + void goTo(){ + if(this->contentType == 0){ + int newScreen = this->menu[this->currentScreen].extractDestinationIndex(); + int newContentType = this->menu[this->currentScreen].extractDestinationType(); + if (newContentType == 0){ + this->menu[newScreen].setPreviousScreen(this->currentScreen); + this->menu[newScreen].setPreviousContentType(this->contentType); + } + else if(newContentType == 1){ + this->graph[newScreen].setPreviousScreen(this->currentScreen); + this->graph[newScreen].setPreviousContentType(this->contentType); + this->graph[newScreen].reset(); + this->graph[newScreen].redrawFlag(); + } + else if(newContentType == 2){ + this->modifier[newScreen].setPreviousScreen(this->currentScreen); + this->modifier[newScreen].setPreviousContentType(this->contentType); + } + this->contentType = newContentType; + this->currentScreen = newScreen; + this->redraw = true; + } + } + + void goBack(){ + if(contentType == 0){ + //Gets indexes from previous screen saved in actual screen if it is a menu, and sets them as the current indexes + this->currentScreen = this->menu[this->currentScreen].getPreviousScreen(); + this->contentType = this->menu[this->currentScreen].getPreviousContentType(); + } + else if(contentType == 1){ + //Gets indexes from previous screen saved in actual screen if it is a graph, and sets them as the current indexes + this->currentScreen = this->graph[this->currentScreen].getPreviousScreen(); + this->contentType = this->graph[this->currentScreen].getPreviousContentType(); + } + else if(contentType == 2){ + this->currentScreen = this->modifier[this->currentScreen].getPreviousScreen(); + this->contentType = this->modifier[this->currentScreen].getPreviousContentType(); + } + this->redraw = true; + } + +//These methods control the plus and minus button actions + void plusAction(){ + if(contentType == 0){ + increasePos(); + } + else if(contentType == 2){ + this->modifier[currentScreen].increaseValue(); + } + this->redraw = true; + } + + void minusAction(){ + if(contentType == 0){ + decreasePos(); + } + else if(contentType == 2){ + this->modifier[currentScreen].decreaseValue(); + } + this->redraw = true; + } + + int getCurrentScreen(){ + return this->currentScreen; + } + + int getContentType(){ + return this->contentType; + } + +};