// HERE IS PART#1
#define ROOT_MENU_CNT 3
#define SUB_MENU1_CNT 4
#define SUB_MENU2_CNT 5
#define SUB_MENU3_CNT 2
// setup the emum with all the menu pages options
enum pageType {ROOT_MENU, SUB_MENU1, SUB_MENU2, SUB_MENU3};
// holds which page is currently selected
enum pageType currPage = ROOT_MENU;
// selected item pointer for the root menu
uint8_t root_Pos = 1;
// constants holding port addresses
const int BTN_ACCEPT = A0;
const int BTN_UP = A2;
const int BTN_DOWN = A1;
const int BTN_CANCEL = A3;
// =======================================================================================
// || SETUP ||
// =======================================================================================
void setup() {
// init the serial port to be used as a display return
Serial.begin(115200);
// setup the basic I/O's
pinMode(BTN_ACCEPT, INPUT_PULLUP);
pinMode(BTN_UP, INPUT_PULLUP);
pinMode(BTN_DOWN, INPUT_PULLUP);
pinMode(BTN_CANCEL, INPUT_PULLUP);
}
// =======================================================================================
// || MAIN LOOP ||
// =======================================================================================
void loop() {
switch (currPage){
case ROOT_MENU: page_RootMenu(); break;
case SUB_MENU1: page_SubMenu1(); break;
case SUB_MENU2: page_SubMenu2(); break;
case SUB_MENU3: page_SubMenu3(); break;
}
}
// =======================================================================================
// || PAGE - ROOT MENU ||
// =======================================================================================
void page_RootMenu(void) {
//flag for updating the display
boolean updateDisplay = true;
// tracks when entered top of loop
uint32_t loopStartMs;
//tracks button states
boolean btn_Up_WasDown = false;
boolean btn_Down_WasDown = false;
boolean btn_Accept_WasDown = false;
//inner loop
while (true){
// capture start time
loopStartMs = millis();
// print the display
if (updateDisplay){
// clear the update flag
updateDisplay = false;
//clear the display
clearScreen();
//menu title
Serial.println(F("[ MAIN MENU ]"));
//print a divider line
printDivider();
// print the items
printSelected(1, root_Pos); Serial.println(F("Sub Menu One"));
printSelected(2, root_Pos); Serial.println(F("Sub Menu Two"));
printSelected(3, root_Pos); Serial.println(F("Sub Menu Three"));
Serial.println();
Serial.println();
//print a divider line
printDivider();
}
// capture the button down states
if (btnIsDown(BTN_UP)) {btn_Up_WasDown = true;}
if (btnIsDown(BTN_DOWN)) {btn_Down_WasDown = true;}
if (btnIsDown(BTN_ACCEPT)) {btn_Accept_WasDown = true;}
//move the pointer down
if (btn_Down_WasDown && btnIsUp(BTN_DOWN)){
if (root_Pos == ROOT_MENU_CNT) {root_Pos = 1;} else {root_Pos++;}
updateDisplay = true;
btn_Down_WasDown = false;
}
//move the pointer Up
if (btn_Up_WasDown && btnIsUp(BTN_UP)){
if (root_Pos == 1) {root_Pos = ROOT_MENU_CNT;} else {root_Pos--;}
updateDisplay = true;
btn_Up_WasDown = false;
}
//move to the selected page
if (btn_Accept_WasDown && btnIsUp(BTN_ACCEPT)){
switch (root_Pos) {
case 1: currPage = SUB_MENU1; return;
case 2: currPage = SUB_MENU2; return;
case 3: currPage = SUB_MENU3; return;
}
}
// keep a specific pace
while (millis() - loopStartMs < 25) {delay(2);}
}
}
// =======================================================================================
// || PAGE - SUB MENU1 ||
// =======================================================================================
void page_SubMenu1(void) {
//flag for updating the display
boolean updateDisplay = true;
// tracks when entered top of loop
uint32_t loopStartMs;
//tracks button states
boolean btn_Up_WasDown = false;
boolean btn_Down_WasDown = false;
boolean btn_Cancel_WasDown = false;
// selected item pointer
uint8_t sub_Pos = 1;
//inner loop
while (true){
// capture start time
loopStartMs = millis();
// print the display
if (updateDisplay){
// clear the update flag
updateDisplay = false;
//clear the display
clearScreen();
//menu title
Serial.println(F("[ SUB MENU #1 ]"));
//print a divider line
printDivider();
// print the items
printSelected(1, sub_Pos); Serial.println(F("The First Item"));
printSelected(2, sub_Pos); Serial.println(F("The Second Item"));
printSelected(3, sub_Pos); Serial.println(F("The Third Item"));
printSelected(4, sub_Pos); Serial.println(F("The Forth Item"));
Serial.println();
//print a divider line
printDivider();
}
// capture the button down states
if (btnIsDown(BTN_UP)) {btn_Up_WasDown = true;}
if (btnIsDown(BTN_DOWN)) {btn_Down_WasDown = true;}
if (btnIsDown(BTN_CANCEL)) {btn_Cancel_WasDown = true;}
//move the pointer down
if (btn_Down_WasDown && btnIsUp(BTN_DOWN)){
if (sub_Pos == SUB_MENU1_CNT) {sub_Pos = 1;} else {sub_Pos++;}
updateDisplay = true;
btn_Down_WasDown = false;
}
//move the pointer Up
if (btn_Up_WasDown && btnIsUp(BTN_UP)){
if (sub_Pos == 1) {sub_Pos = SUB_MENU1_CNT;} else {sub_Pos--;}
updateDisplay = true;
btn_Up_WasDown = false;
}
//move to the go to the root menu
if (btn_Cancel_WasDown && btnIsUp(BTN_CANCEL)){currPage = ROOT_MENU; return;}
// keep a specific pace
while (millis() - loopStartMs < 25) {delay(2);}
}
}
// =======================================================================================
// || PAGE - SUB MENU2 ||
// =======================================================================================
void page_SubMenu2(void) {
//flag for updating the display
boolean updateDisplay = true;
// tracks when entered top of loop
uint32_t loopStartMs;
//tracks button states
boolean btn_Up_WasDown = false;
boolean btn_Down_WasDown = false;
boolean btn_Cancel_WasDown = false;
// selected item pointer
uint8_t sub_Pos = 1;
//inner loop
while (true){
// capture start time
loopStartMs = millis();
// print the display
if (updateDisplay){
// clear the update flag
updateDisplay = false;
//clear the display
clearScreen();
//menu title
Serial.println(F("[ SUB MENU #2 ]"));
//print a divider line
printDivider();
// print the items
printSelected(1, sub_Pos); Serial.println(F("The First Item"));
printSelected(2, sub_Pos); Serial.println(F("The Second Item"));
printSelected(3, sub_Pos); Serial.println(F("The Third Item"));
printSelected(4, sub_Pos); Serial.println(F("The Forth Item"));
printSelected(5, sub_Pos); Serial.println(F("The Fifth Item"));
//print a divider line
printDivider();
}
// capture the button down states
if (btnIsDown(BTN_UP)) {btn_Up_WasDown = true;}
if (btnIsDown(BTN_DOWN)) {btn_Down_WasDown = true;}
if (btnIsDown(BTN_CANCEL)) {btn_Cancel_WasDown = true;}
//move the pointer down
if (btn_Down_WasDown && btnIsUp(BTN_DOWN)){
if (sub_Pos == SUB_MENU2_CNT) {sub_Pos = 1;} else {sub_Pos++;}
updateDisplay = true;
btn_Down_WasDown = false;
}
//move the pointer Up
if (btn_Up_WasDown && btnIsUp(BTN_UP)){
if (sub_Pos == 1) {sub_Pos = SUB_MENU2_CNT;} else {sub_Pos--;}
updateDisplay = true;
btn_Up_WasDown = false;
}
//move to the go to the root menu
if (btn_Cancel_WasDown && btnIsUp(BTN_CANCEL)){currPage = ROOT_MENU; return;}
// keep a specific pace
while (millis() - loopStartMs < 25) {delay(2);}
}
}
//HERE IS PART#2
// =======================================================================================
// || PAGE - SUB MENU3 ||
// =======================================================================================
void page_SubMenu3(void) {
//flag for updating the display
boolean updateDisplay = true;
// tracks when entered top of loop
uint32_t loopStartMs;
//tracks button states
boolean btn_Up_WasDown = false;
boolean btn_Down_WasDown = false;
boolean btn_Cancel_WasDown = false;
// selected item pointer
uint8_t sub_Pos = 1;
//inner loop
while (true){
// capture start time
loopStartMs = millis();
// print the display
if (updateDisplay){
// clear the update flag
updateDisplay = false;
//clear the display
clearScreen();
//menu title
Serial.println(F("[ SUB MENU #3 ]"));
//print a divider line
printDivider();
// print the items
printSelected(1, sub_Pos); Serial.println(F("The First Item"));
printSelected(2, sub_Pos); Serial.println(F("The Second Item"));
Serial.println();
Serial.println();
Serial.println();
//print a divider line
printDivider();
}
// capture the button down states
if (btnIsDown(BTN_UP)) {btn_Up_WasDown = true;}
if (btnIsDown(BTN_DOWN)) {btn_Down_WasDown = true;}
if (btnIsDown(BTN_CANCEL)) {btn_Cancel_WasDown = true;}
//move the pointer down
if (btn_Down_WasDown && btnIsUp(BTN_DOWN)){
if (sub_Pos == SUB_MENU3_CNT) {sub_Pos = 1;} else {sub_Pos++;}
updateDisplay = true;
btn_Down_WasDown = false;
}
//move the pointer Up
if (btn_Up_WasDown && btnIsUp(BTN_UP)){
if (sub_Pos == 1) {sub_Pos = SUB_MENU3_CNT;} else {sub_Pos--;}
updateDisplay = true;
btn_Up_WasDown = false;
}
//move to the go to the root menu
if (btn_Cancel_WasDown && btnIsUp(BTN_CANCEL)){currPage = ROOT_MENU; return;}
// keep a specific pace
while (millis() - loopStartMs < 25) {delay(2);}
}
}
// =======================================================================================
// || TOOLS - DISPLAY ||
// =======================================================================================
void printSelected(uint8_t p1, uint8_t p2){
if(p1 == p2){
Serial.print(F("--> "));
}
else {
Serial.print(F(" "));
}
}
void clearScreen(void){
for (uint8_t i = 0; i < 100; i++) {Serial.println();}
}
void printDivider(void){
for (uint8_t i = 0; i < 40; i++) {Serial.print("-");}
Serial.println();
}
// =======================================================================================
// || TOOLS - BUTTON PRESSING ||
// =======================================================================================
boolean btnIsDown(int btn){
return digitalRead(btn) == LOW && digitalRead(btn) == LOW;
}
boolean btnIsUp(int btn){
return digitalRead(btn) == HIGH && digitalRead(btn) == HIGH;
}