// File: menu_with_buttons.ino
#include "U8g2lib.h"
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0);
// 'item_sel_outline', 128x21px
const unsigned char bitmap_item_sel_outline [] PROGMEM = {
0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C,
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0C, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x02, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C,
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0C, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x02, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C,
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0C, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x02, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C,
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0C, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x02, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C,
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0C, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x02, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C,
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0C, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xF8, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03,
};
// Button pins
#define BUTTON_UP_PIN 12
#define BUTTON_DOWN_PIN 4
#define BUTTON_OK_PIN 8
// Button state variables
unsigned long lastDebounceTimeUp = 0;
unsigned long lastDebounceTimeDown = 0;
unsigned long lastDebounceTimeOk = 0;
unsigned long debounceDelay = 50; // 50 ms debounce delay
unsigned long okPressStartTime = 0; // Track OK button long press
bool okLongPressActive = false;
// Menu variables
const int MENU_ITEM_HEIGHT = 16-1;
const int SCREEN_WIDTH = 128;
const int SCREEN_HEIGHT = 64;
int currentMenu = 0; // Track the current menu
int totalMenus = 5; // Track max menus
int previousMenu = -1; // Track the last menu for return
int selectedItem = 0; // Currently selected menu item
// Menus
const char* mainMenu[] = {"Calib. pH", "Seteo Temp", "Seteo Rango", "Info"};
const int mainMenuItems = sizeof(mainMenu) / sizeof(mainMenu[0]);
const char* subMenu1[] = {"Calib. 4", "Calib. 7", "Calib. 10", "Borrar Calib.", "Valores Calib."};
const int subMenu1Items = sizeof(subMenu1) / sizeof(subMenu1[0]);
const char* subMenu2[] = {"Resolucion 10b", "Offset +0.0 C", "Temp: 25.0 C"};
const int subMenu2Items = sizeof(subMenu2) / sizeof(subMenu2[0]);
const char* subMenu3[] = {"Minimo 6.5", "Maximo 7.5"};
const int subMenu3Items = sizeof(subMenu3) / sizeof(subMenu3[0]);
const char* subMenu4[] = {"Revision 1.0", "IP 192.168.101.79"};
const int subMenu4Items = sizeof(subMenu4) / sizeof(subMenu4[0]);
/**
* Function to render a menu dynamically
*/
void renderMenu(const char* menuItems[], int numItems, int selectedItem) {
int previousItem = (selectedItem - 1 + numItems) % numItems;
int nextItem = (selectedItem + 1) % numItems;
u8g2.clearBuffer();
// Draw the selected item background
u8g2.setDrawColor(1);
//u8g2.drawBox(0, MENU_ITEM_HEIGHT, SCREEN_WIDTH, MENU_ITEM_HEIGHT);
// selected item background
u8g2.drawXBMP(0, 22, 128, 21, bitmap_item_sel_outline);
// Draw the previous item
//u8g2.setDrawColor(1);
u8g2.setFont(u8g2_font_7x14_tf);
u8g2.drawStr(25, MENU_ITEM_HEIGHT, menuItems[previousItem]);
// Draw the selected item
//u8g2.setDrawColor(0);
u8g2.drawStr(25, MENU_ITEM_HEIGHT + 22, menuItems[selectedItem]);
// Draw the next item
//u8g2.setDrawColor(1);
u8g2.drawStr(25, MENU_ITEM_HEIGHT + 44, menuItems[nextItem]);
// Scrollbar
int scrollbarHeight = SCREEN_HEIGHT / numItems;
int scrollbarPosition = scrollbarHeight * selectedItem;
u8g2.drawBox(SCREEN_WIDTH - 5, scrollbarPosition, 3, scrollbarHeight);
u8g2.sendBuffer();
}
/**
* Function to handle button presses
*/
void handleButtonPress(const char* menuItems[], int numItems) {
// Handle UP button
if (digitalRead(BUTTON_UP_PIN) == LOW && (millis() - lastDebounceTimeUp) > debounceDelay) {
lastDebounceTimeUp = millis();
selectedItem = (selectedItem - 1 + numItems) % numItems;
}
// Handle DOWN button
if (digitalRead(BUTTON_DOWN_PIN) == LOW && (millis() - lastDebounceTimeDown) > debounceDelay) {
lastDebounceTimeDown = millis();
selectedItem = (selectedItem + 1) % numItems;
}
// Handle OK button (short press)
if (digitalRead(BUTTON_OK_PIN) == LOW && !okLongPressActive) {
if (okPressStartTime == 0) {
okPressStartTime = millis();
} else if (millis() - okPressStartTime > 3000) {
okLongPressActive = true;
if (previousMenu != -1) {
currentMenu = previousMenu; // Return to the previous menu
selectedItem = 0; // Reset selection
okPressStartTime = 0; // Reset timer
}
}
} else if (digitalRead(BUTTON_OK_PIN) == HIGH) {
if (!okLongPressActive && okPressStartTime > 0) {
// Handle short press
previousMenu = currentMenu;
if (currentMenu == 0) {
currentMenu = 1; // Navigate to submenu
selectedItem = 0;
} else {
currentMenu = 0; // Return to main menu
selectedItem = 0;
}
}
okPressStartTime = 0;
okLongPressActive = false;
}
}
void setup() {
u8g2.begin();
pinMode(BUTTON_UP_PIN, INPUT_PULLUP);
pinMode(BUTTON_DOWN_PIN, INPUT_PULLUP);
pinMode(BUTTON_OK_PIN, INPUT_PULLUP);
}
void loop() {
// Determine the active menu
if (currentMenu == 0) {
handleButtonPress(mainMenu, mainMenuItems);
renderMenu(mainMenu, mainMenuItems, selectedItem);
} else if (currentMenu == 1) {
handleButtonPress(subMenu1, subMenu1Items);
renderMenu(subMenu1, subMenu1Items, selectedItem);
} else if (currentMenu == 2) {
handleButtonPress(subMenu2, subMenu2Items);
renderMenu(subMenu2, subMenu2Items, selectedItem);
} else if (currentMenu == 3) {
handleButtonPress(subMenu3, subMenu3Items);
renderMenu(subMenu3, subMenu3Items, selectedItem);
}
}