/*
example in how to implement the menu library for and ESP32 and Adafruit libraries. This is an example that
uses both menu types
1) a simple selection menu (ItemMenu) where the user can scroll up/down and select
an item and some action be performed such as drawing a screen or activating a sub menu
2) an menu with in-line where the user can scroll up/down the list and select an item
however the difference is that move/up down on a selected item will scroll the values of that
menu item and NOT scroll the list, selecing a selected item will restor control to moving up/down
3) a EditMenu menu with in-line an no icons (down and dirty)
highlights
1. menu items exceeds screen size but library handles wrapping
2. each item selection has a range, increment and decimal readout
3. items can also be read from a char array
ESP32 display
3v3 VCC
GND GND
10 TFT_CS
25 TFT_RESET
2 TFT_DC
23 MOSI
18 SCK
3v3 LED
19 MISO
ESP32 Encoder
32 select button 1
GND select button 2
27 encoder direction 1
33 encoder direction 2
GND encoder dir ground
*/
// required libraries
#include "Adafruit_GFX.h"
#include <Adafruit_ILI9341.h>
#include "Adafruit_ILI9341_Menu.h"
// found in \Arduino\libraries\Adafruit-GFX-Library-master
#include "FreeSans9pt7b.h"
#include "FreeSans12pt7b.h"
#include "FreeSans18pt7b.h"
#include <Encoder.h> // https://github.com/madhephaestus/ESP32Encoder
#define ROW_HEIGHT 35
#define ROWS 5
#define DATA_COLUMN 200
#define TFT_DC 11
#define TFT_CS 10
#define TFT_RST 6
#define EN1_PIN A0
#define EN2_PIN A1
#define SE_PIN A2
// pins for LED and select button on encoder
#define LED_PIN A4
// easy way to include fonts but change globally
#define FONT_SMALL FreeSans9pt7b // font for menus
#define FONT_ITEM FreeSans12pt7b // font for menus
#define FONT_TITLE FreeSans18pt7b // font for all headings
#define DEBOUNCE 150
int MenuOption = 0;
// must have variables for each menu item
// best to have these global so you can use them in processing functions
int MenuOption1 = 0, MenuOption2 = 0, MenuOption3 = 0, MenuOption4 = 0;
int MenuMaisOption1 = 0, MenuMaisOption2 = 0;
int TestMenuOption1 = 0, TestMenuOption2 = 0, TestMenuOption3 = 0, TestMenuOption4 = 0;
int ConfigMenuOption1 = 0, ConfigMenuOption2 = 0, ConfigMenuOption3 = 0, ConfigMenuOption4 = 0,
ConfigMenuOption5 = 0, ConfigMenuOption6 = 0, ConfigMenuOption7 = 0, ConfigMenuOption8 = 0;
int OptionOption1 = 0, OptionOption2 = 0, OptionOption3 = 0, OptionOption4 = 0, OptionOption5 = 0;
int OptionOption6 = 0, OptionOption7 = 0, OptionOption8 = 0, OptionOption9 = 0;
// variables to store some of the options, you will probably want a var for each
// note the menu code ONLY supports floats
// if you want to edit an int in the menu, still pass in a float and set decimal readout to 0
// the recast the float to an int upon menu comletion processing
float Temp1Adj = 0.2, Temp2Adj = -.3, AlarmVal = 1;
// encoder stuff
long Position = 0, oldPosition = 0;
//itens seleção configuração menu
const char *pontoAlarmesItems[] = {"0.1 PPM","0.2 PPM","0.3 PPM","0.4 PPM","0.5 PPM","0.6 PPM","0.7 PPM",
"0.8 PPM","0.9 PPM","1.0 PPM","1.1 PPM","1.2 PPM","1.3 PPM","1.4 PPM",
"1.5 PPM","1.6 PPM","1.7 PPM","1.8 PPM","1.9 PPM","2.0 PPM","2.1 PPM",
"2.2 PPM","2.3 PPM","2.4 PPM","2.5 PPM","2.6 PPM","2.7 PPM","2.8 PPM",
"2.9 PPM", "3.0 PPM"
};
const double pontoAlarmesValores[] = {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0,
1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8,1.9,2.0,
2.1,2.2,2.3,2.4,2.5,2.6,2.7,2.8,2.9,3.0
};
const char *pontoPerigoItems[] = {"3.0 PPM","3.1 PPM","3.2 PPM","3.3 PPM","3.4 PPM","3.5 PPM","3.6 PPM",
"3.7 PPM","3.8 PPM","3.9 PPM","4.0 PPM","4.1 PPM","4.2 PPM","4.3 PPM",
"4.4 PPM","4.5 PPM","4.6 PPM","4.7 PPM","4.8 PPM","4.9 PPM","5.0 PPM"
};
const double pontoPerigoValores[] = {3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9,
4.0, 4.1, 4.2, 4.3, 4.4, 4.5, 4.6, 4.7, 4.8, 4.9, 5.0
};
const char *pontoHistereseItems[] = {"0 seg","1 seg","2 seg","3 seg","4 seg","5 seg","6 seg","7 seg",
"8 seg","9 seg","10 seg","11 seg","12 seg","13 seg","14 seg",
"15 seg","30 seg","45 seg","60 seg"
};
const double pontoHistereseValores[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,30,45, 60};
const char *pontoAtualizacaoItems[] = {"2 Hz","1 Hz","0.5 Hz", "0.25 Hz"
};
const double pontoAtualizacaoValores[] = {500,1000,2000,4000};
const char *OffOnItems[] = {"Off", "On"
};
// OK i'm going crazy with examples, but this will help show more processing when an int is needed but a float returned
// from the menu code
const char *C_NAMES[] = {"White",
"Black",
"Grey",
"Blue",
"Red",
"Green",
"Cyan",
"Magenta",
"Yellow",
"Teal",
"Orange",
"Pink",
"Purple",
"Lt Grey",
"Lt Blue",
"Lt Red",
"Lt Green",
"Lt Cyan", "Lt Magenta", "Lt Yellow", "Lt Teal", "Lt Orange", "Lt Pink", "Lt Purple",
"Medium Grey", "Medium Blue", "Medium Red", "Medium Green", "Medium Cyan", "Medium Magenta", "Medium Yellow", "Medium Teal",
"Medium Orange", "Medium Pink", "Medium Purple", "Dk Grey", "Dk Blue", "Dk Red", "Dk Green", "Dk Cyan",
"Dk Magenta", "Dk Yellow", "Dk Teal", "Dk Orange", "Dk Pink", "Dk Purple"
};
const uint16_t C_VALUES[] = { 0XFFFF, 0X0000, 0XC618, 0X001F, 0XF800, 0X07E0, 0X07FF, 0XF81F, //7
0XFFE0, 0X0438, 0XFD20, 0XF81F, 0X801F, 0XE71C, 0X73DF, 0XFBAE, //15
0X7FEE, 0X77BF, 0XFBB7, 0XF7EE, 0X77FE, 0XFDEE, 0XFBBA, 0XD3BF, //23
0X7BCF, 0X1016, 0XB000, 0X0584, 0X04B6, 0XB010, 0XAD80, 0X0594, //31
0XB340, 0XB00E, 0X8816, 0X4A49, 0X0812, 0X9000, 0X04A3, 0X0372, //39
0X900B, 0X94A0, 0X0452, 0X92E0, 0X9009, 0X8012 //45
};
// set default colors
uint16_t MENU_TEXT = 0x0000;
uint16_t MENU_BACKGROUND = C_VALUES[0];
uint16_t MENU_HIGHLIGHTTEXT = C_VALUES[1];
uint16_t MENU_HIGHLIGHT = C_VALUES[21];
uint16_t MENU_HIGHBORDER = C_VALUES[10];
uint16_t MENU_SELECTTEXT = C_VALUES[0];
uint16_t MENU_SELECT = C_VALUES[4];
uint16_t MENU_SELECTBORDER = C_VALUES[37];
uint16_t MENU_DISABLE = C_VALUES[2];
uint16_t TITLE_TEXT = C_VALUES[13];
uint16_t TITLE_BACK = C_VALUES[36];
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// real code starts here
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// you know the drill
Adafruit_ILI9341 Display = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);
// required, you must create either an Item menu (no inline editing) or an EditMenu (allows inline editing)
//ClassName YourMenuName(&DisplayObject, True=Touch input, False(Default)=mechanical input);
ItemMenu MainMenu(&Display);
ItemMenu MenuMais(&Display);
// since we're showing both menu types, create an object for each where the item menu is the main and calls edit menus
// you can have an item menu call other item menus an edit menu can call an edit menu but in a round about way--not recommended
//ClassName YourMenuName(&DisplayObject, True=Touch input, False(Default)=mechanical input);
//EditMenu OptionMenu(&Display); // default is false, need not specify
//EditMenu ColorMenu(&Display, false); // or you can still call false to force mechanical input selection
EditMenu ConfigMenu(&Display);
EditMenu TestMenu(&Display);
Encoder myEnc(EN1_PIN, EN2_PIN);
void setup() {
Serial.begin(115200);
// disableCore0WDT();
// button in the encoder
pinMode(SE_PIN, INPUT_PULLUP);
// I use a digital pin to control LED brightness
pinMode(LED_PIN, OUTPUT);
delay(10);
digitalWrite(LED_PIN, HIGH);
// fire up the display
Display.begin();
Display.setRotation(1);
Display.setFont(&FONT_TITLE);
// initialize the MainMenu object
// note ROW_HEIGHT is row height and needs to be larger that font height
// the ROWS is max rows to be displayed (remember, library handles wraparound
/*
init(TextColor, BackgroundColor, HighLtTextColor, HighLtColor,
ItemRowHeight, MaxRowsPerScreen, TitleText, ItemFont, TitleFont);
*/
MainMenu.init(MENU_TEXT, MENU_BACKGROUND, MENU_HIGHLIGHTTEXT, MENU_HIGHLIGHT, 64, 3, "Detector Cloro Gas", FONT_TITLE, FONT_TITLE);
// now add each item, text is what's displayed for each menu item, there are no other arguements
// there are 3 add types
// 1. addNI for no icon
// 2. addMono for simple 1 color icon each item
// 3. add565 for displaying a color icon for each item
// note the return value for each item will be it's returned itemid an dwill be > 0
// a return of 0 is reserved for the exit item
// the exit item is actually the title bar--if user moves selector to the title bar
// it's temporarily renamed to "Exit"
/*
addNI(ItemLabel);
addMono(ItemLabel, MonoBitmap, BitmapWidth, BitmapHeight );
add565(ItemLabel, ColorBitmap, uint8_t BitmapWidth, uint8_t BitmapHeight);
*/
MenuOption1 = MainMenu.addNI("Sensor M1:");
MenuOption2 = MainMenu.addNI("Sensor M2:");
MenuOption3 = MainMenu.addNI("Mais");
MainMenu.disable(MenuOption1);
MainMenu.disable(MenuOption2);
// setTitleColors(TitleTextColor, TitleFillColor);
MainMenu.setTitleColors(TITLE_TEXT, TITLE_BACK);
// setTitleBarSize(TitleTop, TitleLeft, TitleWith, TitleHeight);
MainMenu.setTitleBarSize(0, 0, 320, 40);
// setTitleTextMargins(LeftMargin, TopMargin);
MainMenu.setTitleTextMargins(15, 32);
// optional but you can set the left margin and top to scoot the icon over and down
// only needed if you are using icons in your menu items
// setIconMargins(LeftMargin, TopMargin);
MainMenu.setIconMargins(0, 0);
// optional but you can set the left margin and top to scoot the menu highLt over and down
// not needed but recommended so you can better control where the text is placed
// the library will not determine font height and such and adjust--that will be on you
// setMenuBarMargins(LeftMargin, Width, BorderRadius, BorderThickness);
MainMenu.setMenuBarMargins(10, 310, 5, 4);
// optional but you can set the menu highLt special colors (disable text color and border color)
// not needed if you dont plan on disabling menu items
// the library will not determine font height and such and adjust--that will be on you
// setItemColors(DisableTextColor, BorderColor);
MainMenu.setItemColors(MENU_DISABLE, MENU_HIGHBORDER);
// setItemTextMargins(LeftMargin, TopMargin, MarginBetweenTitleBarAndMenu);
MainMenu.setItemTextMargins(10, 38, 5);
// end of ItemMenu setup
// this example includes both menu types, the first (above was a menu where items have not editing)
// this menu type EditMenu allows changes for each items value--basically in-line editing
// more capability? more arguements...
/*
init(TextColor, BackgroundColor, HighLtTextColor, HighLtColor, SelectedTextColor, SelectedColor,
MenuColumn, ItemRowHeight,MaxRowsPerScreen, TitleText, ItemFont, TitleFont);
*/
MenuMais.init(MENU_TEXT, MENU_BACKGROUND, MENU_HIGHLIGHTTEXT, MENU_HIGHLIGHT, 64, 3, "Escolha opcao", FONT_TITLE, FONT_TITLE);
// note the return value for each item will be it's returned itemid an dwill be > 0
// a return of 0 is reserved for the exit item
// the exit item is actually the title bar--if user moves selector to the title bar
// it's temporarily renamed to "Exit"
/*
addNI(ItemLabel);
addMono(ItemLabel, MonoBitmap, BitmapWidth, BitmapHeight );
add565(ItemLabel, ColorBitmap, uint8_t BitmapWidth, uint8_t BitmapHeight);
*/
MenuMaisOption1 = MenuMais.addNI("Configuracoes...");
MenuMaisOption2 = MenuMais.addNI("Testes...");
// setTitleColors(TitleTextColor, TitleFillColor);
MenuMais.setTitleColors(TITLE_TEXT, TITLE_BACK);
// setTitleBarSize(TitleTop, TitleLeft, TitleWith, TitleHeight);
MenuMais.setTitleBarSize(0, 0, 320, 40);
// setTitleTextMargins(LeftMargin, TopMargin);
MenuMais.setTitleTextMargins(20, 30);
// setMenuBarMargins(LeftMargin, Width, BorderRadius, BorderThickness);
MenuMais.setMenuBarMargins(10, 310, 5, 3);
// setItemColors(DisableTextColor, BorderColor);
MenuMais.setItemColors(MENU_DISABLE, MENU_HIGHBORDER);
// setItemTextMargins(LeftMargin, TopMargin, MarginBetweenTitleBarAndMenu);
MenuMais.setItemTextMargins(20, 35, 5);
TestMenu.init(MENU_TEXT, MENU_BACKGROUND, MENU_HIGHLIGHTTEXT, MENU_HIGHLIGHT, MENU_SELECTTEXT, MENU_SELECT,
DATA_COLUMN, ROW_HEIGHT, ROWS, "Menu Testes", FONT_ITEM, FONT_TITLE);
TestMenuOption1 = TestMenu.addNI("Teste M1 Alarme", 0, 0, sizeof(OffOnItems) / sizeof(OffOnItems[0]), 1, 0, OffOnItems);
TestMenuOption2 = TestMenu.addNI("Teste M1 Perigo", 0, 0, sizeof(OffOnItems) / sizeof(OffOnItems[0]), 1, 0, OffOnItems);
TestMenuOption3 = TestMenu.addNI("Teste M2 Alarme", 0, 0, sizeof(OffOnItems) / sizeof(OffOnItems[0]), 1, 0, OffOnItems);
TestMenuOption4 = TestMenu.addNI("Teste M2 Alarme", 0, 0, sizeof(OffOnItems) / sizeof(OffOnItems[0]), 1, 0, OffOnItems);
// setTitleColors(TitleTextColor, TitleFillColor);
TestMenu.setTitleColors(TITLE_TEXT, TITLE_BACK);
// setTitleBarSize(TitleTop, TitleLeft, TitleWith, TitleHeight);
TestMenu.setTitleBarSize(0, 0, 320, 40);
// setTitleTextMargins(LeftMargin, TopMargin);
TestMenu.setTitleTextMargins(50, 30);
// setMenuBarMargins(LeftMargin, Width, BorderRadius, BorderThickness);
TestMenu.setMenuBarMargins(10, 305,4,2);
// setItemColors(DisableTextColor, BorderColor);
TestMenu.setItemColors(MENU_DISABLE, MENU_HIGHBORDER);
// setItemTextMargins(LeftMargin, TopMargin, MarginBetweenTitleBarAndMenu);
TestMenu.setItemTextMargins(16,20,5);
// optional but you can set the speed in which press and hold the up / down arrows increments the values
// default is 50ms and while snappy, can be hard to stop on the desired value
TestMenu.setIncrementDelay(100);
// now add each item, text is what's displayed for each menu item, there are no other arguements
// there are 3 add types
// 1. addNI for no icon
// 2. addMono for simple 1 color icon each item
// 3. add565 for displaying a color icon for each item
// note the return value for each item will be it's returned itemid an dwill be > 0
// a return of 0 is reserved for the exit item
// the exit item is actually the title bar--if user moves selector to the title bar
// it's temporarily renamed to "Exit" while the selector is on the menu bar
// the edit can be either by cycling through a range of values (low to high by some increment value
// example, set a voltage divider calibration value 4000 to 10000 in increments of 100
// or cycle through an array list
// example, choose your favorite pet from a list ("cat", "dog", "bird", "fish")
// you still enter a lower and high limit and are the array bounds (0 to 3 in the above example)
// your Data is the initial array value so you can still have say "bird" be the initial value)
// in either case you can have icons none, mono or color
// the example below for OptionOption1, notice the menu value is a variable (AllowColorMenu)
// this allows you to make sure the menu matches actual current settings. Idea: store settings in the eeprom
// read at startup, populate the menu items, upon menu completion, store the value back in the eeprom
/*
addNI(ItemText, InitalDisplayData, LowLimit, HighLimit, IncrementValue, DisplayDecimalPlaces, ItemMenuText);
addMono(ItemText, Data, LowLimit, HighLimit, Increment, DecimalPlaces, ItemMenuText,
Bitmap, BitmapWidth, BitmapHeight);
add565(ItemText, Data, LowLimit, HighLimit, Increment, DecimalPlaces, ItemMenuText,
Bitmap, BitmapWidth, BitmapHeight);
*/
// OptionOption1 = OptionMenu.addNI("Alarme M1",0,0,20,1,1,0);
/*
OptionOption1 = OptionMenu.add565("Colors", AllowColorMenu, 0, sizeof(OffOnItems) / sizeof(OffOnItems[0]), 1, 0, OffOnItems, epd_bitmap_Temp1, 32, 32);
OptionOption2 = OptionMenu.add565("Temp Adj.", Temp2Adj, -1.0, 1.0 , .05, 2, NULL, epd_bitmap_Temp2, 32, 32);
OptionOption3 = OptionMenu.add565("Readout", 2, 0, sizeof(ReadoutItems) / sizeof(ReadoutItems[0]), 1, 0, ReadoutItems, epd_bitmap_readout, 32, 32);
OptionOption4 = OptionMenu.add565("Tune", 0, 0, 20 , 1, 0, NULL, epd_bitmap_Tune, 32, 32);
OptionOption5 = OptionMenu.add565("Alarm", AlarmVal, 0, sizeof(OffOnItems) / sizeof(OffOnItems[0]), 1, 0, OffOnItems, epd_bitmap_Alarm, 32, 32);
OptionOption6 = OptionMenu.add565("Precision", 0, 0, sizeof(PrecisionItems) / sizeof(PrecisionItems[0]), 1, 0, PrecisionItems, epd_bitmap_Precision, 32, 32);
OptionOption7 = OptionMenu.add565("Refresh", 0, 0.0, sizeof(RefreshItems) / sizeof(RefreshItems[0]), 1, 0, RefreshItems, epd_bitmap_Update, 32, 32);
*/
// again all these calls are optional, but you most likely will want to set margins
// optional but you can store a setting such as a calibration value in EEPROM, read at startup
// and populate with SetItemValue(), even though the item data was set in the add method, you can change it later
// SetItemValue(ItemID, ItemValue){
/*OptionMenu.SetItemValue(OptionOption1, 0.12);
OptionMenu.SetItemValue(OptionOption3, 1); // the 2nd element in the ReadoutItems array
// optional but can can set the title colors
// setTitleColors(TitleTextColor, TitleFillColor);
OptionMenu.setTitleColors(TITLE_TEXT, TITLE_BACK);
// optional but you can set the size of the title bar
// setTitleBarSize(TitleTop, TitleLeft, TitleWith, TitleHeight);
OptionMenu.setTitleBarSize(0, 0, 320, 40);
// optional but you can set the margins in how the text in the title bar is centered
// setTitleTextMargins(LeftMargin, TopMargin);
OptionMenu.setTitleTextMargins(60, 30);
// optional but you can scoot the icon over and down
// setIconMargins(LeftMargin, TopMargin);
OptionMenu.setIconMargins(5, 0);
// optional but you can set the margins and size of the text in the menu bar
// setItemTextMargins(LeftMargin, TopMargin, MarginBetweenTitleBarAndMenu);
OptionMenu.setItemTextMargins(7, 25, 10);
// optional but you can change colors other that in the init method
// colors such as disable text and border color (if you display a border of course)
// setItemColors(DisableTextColor, HighLt, EditSelectBorderColor);
OptionMenu.setItemColors(MENU_DISABLE, MENU_HIGHBORDER, MENU_SELECTBORDER);
*/
// i'm now just going to rip through creating the color menu, again take note or arg 2--it's the initial menu item value
// since colors are in arrays we can't simply put MENU_TEXT for the first add method--MENU_TEXT is the corresponding hex value
// gotta put it's index, the library knows you are using array and will take the passed index and show the correct text
// remember...
// C_NAMES[1] = "White"
// C_VALUES[1] = { 0XFFFF,
// MENU_TEXT = C_VALUES[1]; // white
/*
init(TextColor, BackgroundColor, HighLtTextColor, HighLtColor, SelectedTextColor, SelectedColor,
MenuColumn, ItemRowHeight,MaxRowsPerScreen, TitleText, ItemFont, TitleFont);
*/
// optional but showing how you can have several small items and not large pretty icons
ConfigMenu.init(MENU_TEXT, MENU_BACKGROUND, ILI9341_WHITE, ILI9341_BLUE, MENU_SELECTTEXT, MENU_SELECT,
DATA_COLUMN, 25, 8, "Menu Config", FONT_SMALL, FONT_ITEM);
/*
addNI(ItemText, InitalDisplayData, LowLimit, HighLimit, IncrementValue, DisplayDecimalPlaces, ItemMenuText);
*/
ConfigMenuOption1 = ConfigMenu.addNI("Qtde sensores:", 1, 1, 2, 1, 0);
ConfigMenuOption2 = ConfigMenu.addNI("Histerese:", 1, 0, sizeof(pontoHistereseItems) / sizeof(pontoHistereseItems[0]), 1, 0, pontoHistereseItems);
ConfigMenuOption3 = ConfigMenu.addNI("Tx Atualizacao:", 1, 0, sizeof(pontoAtualizacaoItems) / sizeof(pontoAtualizacaoItems[0]), 1, 0, pontoAtualizacaoItems);
ConfigMenuOption4 = ConfigMenu.addNI("M1 Alarme", 14, 0, sizeof(pontoAlarmesItems) / sizeof(pontoAlarmesItems[0]), 1, 0, pontoAlarmesItems);
ConfigMenuOption5 = ConfigMenu.addNI("M1 Perigo", 0, 0, sizeof(pontoPerigoItems) / sizeof(pontoAlarmesItems[0]), 1, 0, pontoPerigoItems);
ConfigMenuOption6 = ConfigMenu.addNI("M2 Alarme", 14, 0, sizeof(pontoAlarmesItems) / sizeof(pontoAlarmesItems[0]), 1, 0, pontoAlarmesItems);
ConfigMenuOption7 = ConfigMenu.addNI("M2 Perigo", 0, 0, sizeof(pontoPerigoItems) / sizeof(pontoAlarmesItems[0]), 1, 0, pontoPerigoItems);
ConfigMenu.setTitleTextMargins(50, 30);
// setItemTextMargins(LeftMargin, TopMargin, MarginBetweenTitleBarAndMenu);
ConfigMenu.setItemTextMargins(16, 20, 5);
ConfigMenu.setMenuBarMargins(10, 305, 4, 2);
// I'm so not a fan on my API for setting select border color... this arguement should have been in the menubar thingy...
// code is implemented in probably millions of projects around the world so no sense breaking them :)
ConfigMenu.setItemColors(MENU_DISABLE, MENU_HIGHBORDER, MENU_SELECTBORDER);
ConfigMenu.setTitleColors(TITLE_TEXT, TITLE_BACK);
// optional but you can set the speed in which press and hold the up / down arrows increments the values
// default is 50ms and while snappy, can be hard to stop on the desired value
ConfigMenu.setIncrementDelay(150);
// you can simplay call the draw method on a menu object, but you will need to add processing
// here's how I recommend doing that, have a function that draws the main menu and processes the selections
// ideally you will probably have a "setting" button in your UI that will call the "ProcessMainMenu"
// you can simplay call the draw method on a menu object, but you will need to add processing
// here's how I recommend doing that, have a function that draws the main menu and processes the selections
// ideally you will probably have a "setting" button in your UI that will call the "ProcessMainMenu"
ProcessMainMenu();
// menu code done, now proceed to your code
Display.fillScreen(MENU_BACKGROUND);
}
void loop() {
// this is just a processor for when you exit the top level menu
Display.setCursor(10, 100);
Display.setFont(&FONT_TITLE);
Display.setTextColor(ILI9341_RED, ILI9341_WHITE);
Display.print(F("Done"));
delay(500);
Display.setCursor(10, 100);
Display.setFont(&FONT_TITLE);
Display.setTextColor(ILI9341_BLUE, ILI9341_BLUE);
Display.print(F("Done"));
delay(500);
// and example on how you can call menu while in a loop
// of course you will probably have a button to launch ProcessMainMenu
if (Serial.available()) {
if (Serial.read() >= 32) {
ProcessMainMenu();
Display.fillScreen(MENU_BACKGROUND);
}
}
}
// function to process main menu iteraction
// ideally this implementation makes it easy to launch your menu from anywhere in th
void ProcessMainMenu() {
// set an inital flag that will be used to store what menu item the user exited on
int MainMenuOption = 1;
// blank out the screen
Display.fillScreen(MENU_BACKGROUND);
// draw the main menu
MainMenu.draw();
// run the processing loop until user move selector to title bar (which becomes exit, i.e. 0 return val)
// and selectes it
// note menu code can return - 1 for errors so run unitl non zero
while (MainMenuOption != 0)
{
// standard encoder read
Position = myEnc.read();
// attempt to debouce these darn things...
if ((Position - oldPosition) > 0) {
delay(DEBOUNCE);
while (oldPosition != Position) {
oldPosition = Position;
Position = myEnc.read();
}
// once encoder calms down and is done cycling, move selector up
// since encoder reads are increasing
// any menu wrapping is handled in the library
MainMenu.MoveUp();
}
// attempt to debouce these darn things...
if ((Position - oldPosition) < 0) {
delay(DEBOUNCE);
while (oldPosition != Position) {
oldPosition = Position;
Position = myEnc.read();
}
// once encoder calms down and is done cycling, move selector up
// since encoder reads are decreasing
// any menu wrapping is handled in the library
MainMenu.MoveDown();
}
// but wait...the user pressed the button on the encoder
if (digitalRead(SE_PIN) == LOW) {
// debounce the button press
while (digitalRead(SE_PIN) == LOW) {
delay(DEBOUNCE);
}
// get the row the selector is on
MainMenuOption = MainMenu.selectRow();
// here is where you process accordingly
// remember on pressing button on title bar 0 is returned and will exit the loop
if (MainMenuOption == MenuOption3) {
ProcessMaisMenu();
Display.fillScreen(MENU_BACKGROUND);
MainMenu.draw();
}
}
}
// at this point MenuOption better be 0...
}
// menu to handle processing for a sub-menu
// since this menu will be a menu that allows edits (EditMenu object type)
// process is exactly the same as an ItemMenu
// meaning you simply use the same MoveUp, MoveDown and the library will know if you are
// wanting to move the selector or cycle through a range
/*
void ProcessOptionMenu() {
// the entire menu processing are basically 3 calls
// YourMenu.MoveUp();
// YourMenu.MoveDown();
// EditMenuOption = YourMenu.selectRow();
// set an inital flag that will be used to store what menu item the user exited on
int EditMenuOption = 1;
// blank out the screen
Display.fillScreen(MENU_BACKGROUND);
// draw the main menu
OptionMenu.draw();
// run the processing loop until user move selector to title bar (which becomes exit)
// and selectes it
while (EditMenuOption != 0) {
// standard encoder read
Position = encoder.getCount();
// attempt to debouce these darn things...
if ((Position - oldPosition) > 0) {
delay(DEBOUNCE);
while (oldPosition != Position) {
oldPosition = Position;
Position = encoder.getCount();
}
// once encoder calms down and is done cycling, move selector up
// since encoder reads are increasing
// any menu wrapping is handled in the library
// the EditMenu object type is special cased
// 1. if a row was NOT selected, MoveUp / MoveDown will cycle throuh menu items
// 2. if a row IS selected, MoveUp / MoveDown will cycle throuh the range of values withing the item
OptionMenu.MoveUp();
}
if ((Position - oldPosition) < 0) {
delay(DEBOUNCE);
while (oldPosition != Position) {
oldPosition = Position;
Position = encoder.getCount();
}
// once encoder calms down and is done cycling, move selector up
// since encoder reads are decreasing
// any menu wrapping is handled in the library
// the EditMenu object type is special cased
// 1. if a row was NOT selected, MoveUp / MoveDown will cycle throuh menu items
// 2. if a row IS selected, MoveUp / MoveDown will cycle throuh the range of values withing the item
OptionMenu.MoveDown();
}
if (digitalRead(SE_PIN) == LOW) {
// debounce the selector button
while (digitalRead(SE_PIN) == LOW) {
delay(DEBOUNCE);
}
// use the selectRow to
// 1. select a row for editing
// a. when a row is selected, moveup, movedown will then scroll through the editable values (values or a list)
// 2. unselect a row when editing is done
// 3. when selector is on the title bar annd selecRow is called a 0 is returned
EditMenuOption = OptionMenu.selectRow();
// this next section is purely optional and shows how data change can be used
// the EditMenu object type is special cased where if you select a menu item
// the library consideres that a desire to start editing the item
// the menu bar color changes and any MoveUp / MoveDown will then be directed
// to editing the item value itself
// once user Selects the selected row, the library will consider editign done
// and restore menu selection with MoveUp / MoveDown
// watch the YouTube video for a demo
// to modify other values
if (EditMenuOption == OptionOption5) { // budget item
if (OptionMenu.value[OptionOption5] == 0) {
OptionMenu.disable(OptionOption4);
OptionMenu.setItemText(OptionOption4, "Tune (Alarm OFF)");
OptionMenu.drawRow(OptionOption4);
}
else {
OptionMenu.enable(OptionOption4);
OptionMenu.setItemText(OptionOption4, "Tune");
OptionMenu.drawRow(OptionOption4);
}
}
}
}
// user must have pressed the encorder select button while on the title bar (which returns 0)
// hence exiting the loop
// now you can process / store / display the menu selections
// remember this is from the EditMenu and has associated value property with each menu item
Serial.println("Option Menu Selections ");
Serial.println("______________________________");
Serial.print("Color Adj "); Serial.println(OptionMenu.value[OptionOption1]);
Serial.print("Temp2 Adj "); Serial.println(OptionMenu.value[OptionOption2]);
Serial.print("Readout "); Serial.println(ReadoutItems[(int)OptionMenu.value[OptionOption3]]);
Serial.print("Tune "); Serial.println(TuneItems[(int)OptionMenu.value[OptionOption4]]);
Serial.print("Alarm "); Serial.println(OffOnItems[(int)OptionMenu.value[OptionOption5]]);
Serial.print("Precision "); Serial.println(PrecisionItems[(int)OptionMenu.value[OptionOption6]]);
Serial.print("Refresh "); Serial.println(OptionMenu.value[OptionOption7]);
// an example of how to set other menu values based on selection here
// remember all menu values passed in or returned are floats
// so recast to int if you need to
AllowColorMenu = (int) OptionMenu.value[OptionOption1];
if (AllowColorMenu == 0) {
MainMenu.disable(MenuOption2);
}
else {
MainMenu.enable(MenuOption2);
}
}
void ProcessOptionMenu() {
// the entire menu processing are basically 3 calls
// YourMenu.MoveUp();
// YourMenu.MoveDown();
// EditMenuOption = YourMenu.selectRow();
// set an inital flag that will be used to store what menu item the user exited on
int EditMenuOption = 1;
// blank out the screen
Display.fillScreen(MENU_BACKGROUND);
// draw the main menu
OptionMenu.draw();
// run the processing loop until user move selector to title bar (which becomes exit)
// and selectes it
while (EditMenuOption != 0) {
// standard encoder read
Position = myEnc.read();
// attempt to debouce these darn things...
if ((Position - oldPosition) > 0) {
delay(DEBOUNCE);
while (oldPosition != Position) {
oldPosition = Position;
Position = myEnc.read();
}
// once encoder calms down and is done cycling, move selector up
// since encoder reads are increasing
// any menu wrapping is handled in the library
// the EditMenu object type is special cased
// 1. if a row was NOT selected, MoveUp / MoveDown will cycle throuh menu items
// 2. if a row IS selected, MoveUp / MoveDown will cycle throuh the range of values withing the item
OptionMenu.MoveUp();
}
if ((Position - oldPosition) < 0) {
delay(DEBOUNCE);
while (oldPosition != Position) {
oldPosition = Position;
Position = myEnc.read();
}
// once encoder calms down and is done cycling, move selector up
// since encoder reads are decreasing
// any menu wrapping is handled in the library
// the EditMenu object type is special cased
// 1. if a row was NOT selected, MoveUp / MoveDown will cycle throuh menu items
// 2. if a row IS selected, MoveUp / MoveDown will cycle throuh the range of values withing the item
OptionMenu.MoveDown();
}
if (digitalRead(SE_PIN) == LOW) {
// debounce the selector button
while (digitalRead(SE_PIN) == LOW) {
delay(DEBOUNCE);
}
// use the selectRow to
// 1. select a row for editing
// a. when a row is selected, moveup, movedown will then scroll through the editable values (values or a list)
// 2. unselect a row when editing is done
// 3. when selector is on the title bar annd selecRow is called a 0 is returned
EditMenuOption = OptionMenu.selectRow();
// this next section is purely optional and shows how data change can be used
// the EditMenu object type is special cased where if you select a menu item
// the library consideres that a desire to start editing the item
// the menu bar color changes and any MoveUp / MoveDown will then be directed
// to editing the item value itself
// once user Selects the selected row, the library will consider editign done
// and restore menu selection with MoveUp / MoveDown
// watch the YouTube video for a demo
// to modify other values
if (EditMenuOption == OptionOption5) { // budget item
if (OptionMenu.value[OptionOption5] == 0) {
OptionMenu.disable(OptionOption4);
OptionMenu.setItemText(OptionOption4, "Tune (Alarm OFF)");
OptionMenu.drawRow(OptionOption4);
}
else {
OptionMenu.enable(OptionOption4);
OptionMenu.setItemText(OptionOption4, "Tune");
OptionMenu.drawRow(OptionOption4);
}
}
}
}
// user must have pressed the encorder select button while on the title bar (which returns 0)
// hence exiting the loop
// now you can process / store / display the menu selections
// remember this is from the EditMenu and has associated value property with each menu item
Serial.println("Option Menu Selections ");
Serial.println("______________________________");
Serial.print("Color Adj "); Serial.println(OptionMenu.value[OptionOption1]);
Serial.print("Temp2 Adj "); Serial.println(OptionMenu.value[OptionOption2]);
Serial.print("Readout "); Serial.println(ReadoutItems[(int)OptionMenu.value[OptionOption3]]);
Serial.print("Tune "); Serial.println(TuneItems[(int)OptionMenu.value[OptionOption4]]);
Serial.print("Alarm "); Serial.println(OffOnItems[(int)OptionMenu.value[OptionOption5]]);
Serial.print("Precision "); Serial.println(PrecisionItems[(int)OptionMenu.value[OptionOption6]]);
Serial.print("Refresh "); Serial.println(OptionMenu.value[OptionOption7]);
// an example of how to set other menu values based on selection here
// remember all menu values passed in or returned are floats
// so recast to int if you need to
AllowColorMenu = (int) OptionMenu.value[OptionOption1];
if (AllowColorMenu == 0) {
MainMenu.disable(MenuOption2);
}
else {
MainMenu.enable(MenuOption2);
}
}*/
/*
void ProcessColorMenu() {
// the entire menu processing are basically 3 calls
// YourMenu.MoveUp();
// YourMenu.MoveDown();
// EditMenuOption = YourMenu.selectRow();
// set an inital flag that will be used to store what menu item the user exited on
int EditMenuOption = 1;
// blank out the screen
Display.fillScreen(MENU_BACKGROUND);
// draw the main menu
ColorMenu.draw();
// run the processing loop until user move selector to title bar (which becomes exit)
// and selectes it
while (EditMenuOption != 0) {
delay(50);
Position = encoder.getCount();
if ((Position - oldPosition) > 0) {
delay(DEBOUNCE);
while (oldPosition != Position) {
oldPosition = Position;
Position = encoder.getCount();
}
ColorMenu.MoveUp();
}
if ((Position - oldPosition) < 0) {
delay(DEBOUNCE);
while (oldPosition != Position) {
oldPosition = Position;
Position = encoder.getCount();
}
ColorMenu.MoveDown();
}
if (digitalRead(SE_PIN) == LOW) {
// debounce the selector button
while (digitalRead(SE_PIN) == LOW) {
delay(DEBOUNCE);
}
EditMenuOption = ColorMenu.selectRow();
}
}
// out of menu now time for processing
// set global back color
Serial.print("back color");
Serial.println(C_VALUES[ (int) ColorMenu.value[ColorOption2]]);
MENU_BACKGROUND = C_VALUES[ (int) ColorMenu.value[ColorOption2]];
// set Option menu colors
MainMenu.SetAllColors(C_VALUES[ (int) ColorMenu.value[ColorOption1]],
C_VALUES[ (int) ColorMenu.value[ColorOption2]],
C_VALUES[ (int) ColorMenu.value[ColorOption3]],
C_VALUES[ (int) ColorMenu.value[ColorOption4]],
C_VALUES[ (int) ColorMenu.value[ColorOption8]],
C_VALUES[ (int) ColorMenu.value[ColorOption9]],
C_VALUES[ (int) ColorMenu.value[ColorOption10]],
C_VALUES[ (int) ColorMenu.value[ColorOption11]]);
OptionMenu.SetAllColors(C_VALUES[ (int) ColorMenu.value[ColorOption1]],
C_VALUES[ (int) ColorMenu.value[ColorOption2]],
C_VALUES[ (int) ColorMenu.value[ColorOption3]],
C_VALUES[ (int) ColorMenu.value[ColorOption4]],
C_VALUES[ (int) ColorMenu.value[ColorOption5]],
C_VALUES[ (int) ColorMenu.value[ColorOption6]],
C_VALUES[ (int) ColorMenu.value[ColorOption7]],
C_VALUES[ (int) ColorMenu.value[ColorOption8]],
C_VALUES[ (int) ColorMenu.value[ColorOption9]],
C_VALUES[ (int) ColorMenu.value[ColorOption10]],
C_VALUES[ (int) ColorMenu.value[ColorOption11]]);
// set color menu colors
ColorMenu.SetAllColors(C_VALUES[ (int) ColorMenu.value[ColorOption1]],
C_VALUES[ (int) ColorMenu.value[ColorOption2]],
C_VALUES[ (int) ColorMenu.value[ColorOption3]],
C_VALUES[ (int) ColorMenu.value[ColorOption4]],
C_VALUES[ (int) ColorMenu.value[ColorOption5]],
C_VALUES[ (int) ColorMenu.value[ColorOption6]],
C_VALUES[ (int) ColorMenu.value[ColorOption7]],
C_VALUES[ (int) ColorMenu.value[ColorOption8]],
C_VALUES[ (int) ColorMenu.value[ColorOption9]],
C_VALUES[ (int) ColorMenu.value[ColorOption10]],
C_VALUES[ (int) ColorMenu.value[ColorOption11]]);
// set color menu colors
ConfigMenu.SetAllColors(C_VALUES[ (int) ColorMenu.value[ColorOption1]],
C_VALUES[ (int) ColorMenu.value[ColorOption2]],
C_VALUES[ (int) ColorMenu.value[ColorOption3]],
C_VALUES[ (int) ColorMenu.value[ColorOption4]],
C_VALUES[ (int) ColorMenu.value[ColorOption5]],
C_VALUES[ (int) ColorMenu.value[ColorOption6]],
C_VALUES[ (int) ColorMenu.value[ColorOption7]],
C_VALUES[ (int) ColorMenu.value[ColorOption8]],
C_VALUES[ (int) ColorMenu.value[ColorOption9]],
C_VALUES[ (int) ColorMenu.value[ColorOption10]],
C_VALUES[ (int) ColorMenu.value[ColorOption11]]);
}
void ProcessColorMenu() {
// the entire menu processing are basically 3 calls
// YourMenu.MoveUp();
// YourMenu.MoveDown();
// EditMenuOption = YourMenu.selectRow();
// set an inital flag that will be used to store what menu item the user exited on
int EditMenuOption = 1;
// blank out the screen
Display.fillScreen(MENU_BACKGROUND);
// draw the main menu
ColorMenu.draw();
// run the processing loop until user move selector to title bar (which becomes exit)
// and selectes it
while (EditMenuOption != 0) {
delay(50);
Position = myEnc.read();
if ((Position - oldPosition) > 0) {
delay(DEBOUNCE);
while (oldPosition != Position) {
oldPosition = Position;
Position = myEnc.read();
}
ColorMenu.MoveUp();
}
if ((Position - oldPosition) < 0) {
delay(DEBOUNCE);
while (oldPosition != Position) {
oldPosition = Position;
Position = myEnc.read();
}
ColorMenu.MoveDown();
}
if (digitalRead(SE_PIN) == LOW) {
// debounce the selector button
while (digitalRead(SE_PIN) == LOW) {
delay(DEBOUNCE);
}
EditMenuOption = ColorMenu.selectRow();
}
}
// out of menu now time for processing
// set global back color
Serial.print("back color");
Serial.println(C_VALUES[ (int) ColorMenu.value[ColorOption2]]);
MENU_BACKGROUND = C_VALUES[ (int) ColorMenu.value[ColorOption2]];
// set Option menu colors
MainMenu.SetAllColors(C_VALUES[ (int) ColorMenu.value[ColorOption1]],
C_VALUES[ (int) ColorMenu.value[ColorOption2]],
C_VALUES[ (int) ColorMenu.value[ColorOption3]],
C_VALUES[ (int) ColorMenu.value[ColorOption4]],
C_VALUES[ (int) ColorMenu.value[ColorOption8]],
C_VALUES[ (int) ColorMenu.value[ColorOption9]],
C_VALUES[ (int) ColorMenu.value[ColorOption10]],
C_VALUES[ (int) ColorMenu.value[ColorOption11]]);
OptionMenu.SetAllColors(C_VALUES[ (int) ColorMenu.value[ColorOption1]],
C_VALUES[ (int) ColorMenu.value[ColorOption2]],
C_VALUES[ (int) ColorMenu.value[ColorOption3]],
C_VALUES[ (int) ColorMenu.value[ColorOption4]],
C_VALUES[ (int) ColorMenu.value[ColorOption5]],
C_VALUES[ (int) ColorMenu.value[ColorOption6]],
C_VALUES[ (int) ColorMenu.value[ColorOption7]],
C_VALUES[ (int) ColorMenu.value[ColorOption8]],
C_VALUES[ (int) ColorMenu.value[ColorOption9]],
C_VALUES[ (int) ColorMenu.value[ColorOption10]],
C_VALUES[ (int) ColorMenu.value[ColorOption11]]);
// set color menu colors
ColorMenu.SetAllColors(C_VALUES[ (int) ColorMenu.value[ColorOption1]],
C_VALUES[ (int) ColorMenu.value[ColorOption2]],
C_VALUES[ (int) ColorMenu.value[ColorOption3]],
C_VALUES[ (int) ColorMenu.value[ColorOption4]],
C_VALUES[ (int) ColorMenu.value[ColorOption5]],
C_VALUES[ (int) ColorMenu.value[ColorOption6]],
C_VALUES[ (int) ColorMenu.value[ColorOption7]],
C_VALUES[ (int) ColorMenu.value[ColorOption8]],
C_VALUES[ (int) ColorMenu.value[ColorOption9]],
C_VALUES[ (int) ColorMenu.value[ColorOption10]],
C_VALUES[ (int) ColorMenu.value[ColorOption11]]);
// set color menu colors
ConfigMenu.SetAllColors(C_VALUES[ (int) ColorMenu.value[ColorOption1]],
C_VALUES[ (int) ColorMenu.value[ColorOption2]],
C_VALUES[ (int) ColorMenu.value[ColorOption3]],
C_VALUES[ (int) ColorMenu.value[ColorOption4]],
C_VALUES[ (int) ColorMenu.value[ColorOption5]],
C_VALUES[ (int) ColorMenu.value[ColorOption6]],
C_VALUES[ (int) ColorMenu.value[ColorOption7]],
C_VALUES[ (int) ColorMenu.value[ColorOption8]],
C_VALUES[ (int) ColorMenu.value[ColorOption9]],
C_VALUES[ (int) ColorMenu.value[ColorOption10]],
C_VALUES[ (int) ColorMenu.value[ColorOption11]]);
}*/
/*
void ProcessConfigMenu() {
int EditMenuOption = 1;
Display.fillScreen(MENU_BACKGROUND);
ConfigMenu.draw();
while (EditMenuOption != 0) {
delay(50);
Position = encoder.getCount();
if ((Position - oldPosition) > 0) {
oldPosition = Position;
ConfigMenu.MoveUp();
}
if ((Position - oldPosition) < 0) {
oldPosition = Position;
ConfigMenu.MoveDown();
}
if (digitalRead(SE_PIN) == LOW) {
// debounce the selector button
while (digitalRead(SE_PIN) == LOW) {
delay(DEBOUNCE);
}
EditMenuOption = ConfigMenu.selectRow();
}
}
}*/
void ProcessMaisMenu() {
int MenuMaisOption = 1;
Display.fillScreen(MENU_BACKGROUND);
MenuMais.draw();
while (MenuMaisOption != 0) {
delay(50);
Position = myEnc.read();
if ((Position - oldPosition) > 0) {
oldPosition = Position;
MenuMais.MoveUp();
}
if ((Position - oldPosition) < 0) {
oldPosition = Position;
MenuMais.MoveDown();
}
if (digitalRead(SE_PIN) == LOW) {
// debounce the selector button
while (digitalRead(SE_PIN) == LOW) {
delay(DEBOUNCE);
}
MenuMaisOption = MenuMais.selectRow();
if (MenuMaisOption == MenuMaisOption1) {
// item 1 was the Option menu
//ProcessOptionMenu();
ProcessConfigMenu();
// when done processing that menu, return here
// clear display and redraw this main menu
Display.fillScreen(MENU_BACKGROUND);
MenuMais.draw();
}
if (MenuMaisOption == MenuMaisOption2) {
//ImTooLazyToWriteAnotherExampe();
ProcessTestMenu();
Display.fillScreen(MENU_BACKGROUND);
MenuMais.draw();
}
}
}
}
void ProcessConfigMenu() {
int EditMenuOption = 1;
Display.fillScreen(MENU_BACKGROUND);
ConfigMenu.draw();
while (EditMenuOption != 0) {
delay(50);
Position = myEnc.read();
if ((Position - oldPosition) > 0) {
oldPosition = Position;
ConfigMenu.MoveUp();
}
if ((Position - oldPosition) < 0) {
oldPosition = Position;
ConfigMenu.MoveDown();
}
if (digitalRead(SE_PIN) == LOW) {
// debounce the selector button
while (digitalRead(SE_PIN) == LOW) {
delay(DEBOUNCE);
}
EditMenuOption = ConfigMenu.selectRow();
}
}
}
void ProcessTestMenu() {
int EditMenuTest = 1;
Display.fillScreen(MENU_BACKGROUND);
TestMenu.draw();
while (EditMenuTest != 0) {
delay(50);
Position = myEnc.read();
if ((Position - oldPosition) > 0) {
oldPosition = Position;
TestMenu.MoveUp();
}
if ((Position - oldPosition) < 0) {
oldPosition = Position;
TestMenu.MoveDown();
}
if (digitalRead(SE_PIN) == LOW) {
// debounce the selector button
while (digitalRead(SE_PIN) == LOW) {
delay(DEBOUNCE);
}
EditMenuTest = TestMenu.selectRow();
}
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// end of example
//////////////////////////////////////////////////////////////////////////////////////////////////