Skip to content

Instantly share code, notes, and snippets.

@Spirik
Created June 13, 2022 08:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Spirik/191fafd4095627cea7460ec47ae8a954 to your computer and use it in GitHub Desktop.
Save Spirik/191fafd4095627cea7460ec47ae8a954 to your computer and use it in GitHub Desktop.
GEM - Create menu items with user-defined callback argument in a loop.
/*
Create menu items with user-defined callback argument in a loop.
*/
#include <GEM_adafruit_gfx.h>
#include <KeyDetector.h>
// Hardware-specific library for ST7735.
// Include library that matches your setup (see https://learn.adafruit.com/adafruit-gfx-graphics-library for details)
#include <Adafruit_ST7735.h>
// Pins the buttons are connected to
const byte downPin = 2;
const byte leftPin = 3;
const byte rightPin = 4;
const byte upPin = 5;
const byte cancelPin = 6;
const byte okPin = 7;
// Array of Key objects that will link GEM key identifiers with dedicated pins
Key keys[] = {{GEM_KEY_UP, upPin}, {GEM_KEY_RIGHT, rightPin}, {GEM_KEY_DOWN, downPin}, {GEM_KEY_LEFT, leftPin}, {GEM_KEY_CANCEL, cancelPin}, {GEM_KEY_OK, okPin}};
// Create KeyDetector object
KeyDetector myKeyDetector(keys, sizeof(keys)/sizeof(Key));
// To account for switch bounce effect of the buttons (if occur) you may want to specify debounceDelay
// as the third argument to KeyDetector constructor:
// KeyDetector myKeyDetector(keys, sizeof(keys)/sizeof(Key), 10);
// Macro constants (aliases) for the pins TFT display is connected to. Please update the pin numbers according to your setup
#define TFT_CS A2
#define TFT_RST -1 // Set to -1 and connect to Arduino RESET pin
#define TFT_DC A3
// Create an instance of the Adafruit GFX library.
// Use constructor that matches your setup (see https://learn.adafruit.com/adafruit-gfx-graphics-library for details).
// ST7735 based display is used in the example.
// This instance is used to call all the subsequent Adafruit GFX functions (internally from GEM library,
// or manually in your sketch if it is required)
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
// Declaration of Switch type
struct Switch {
const char* title; // Title of the button
const char* id; // ID of the button
};
// Array of switches
Switch switches[] = {{"Kitchen", "light.kitchen_light" }, {"Porch", "switch.porch_button"}, {"Loft","switch.stairs_button"}};
// Callback function that triggers when button is pressed. We will write (define) this function later.
// However, we should forward-declare it in order to pass to GEMItem constructor
void pressButton(GEMCallbackData callbackData); // Forward declaration
// Create an array of menu buttons (technincally, pointers to GEMItem).
// It will be populated later, in a setupMenu() function
GEMItem* menuItemButtons[sizeof(switches)/sizeof(Switch)];
// Create menu page object of class GEMPage. Menu page holds menu items (GEMItem) and represents menu level.
// Menu can have multiple menu pages (linked to each other) with multiple menu items each
GEMPage menuPageMain("Switches");
// Create menu object of class GEM_adafruit_gfx. Supply its constructor with reference to tft object we created earlier
GEM_adafruit_gfx menu(tft, GEM_POINTER_ROW, GEM_ITEMS_COUNT_AUTO);
void setup() {
// Push-buttons pin modes
pinMode(downPin, INPUT);
pinMode(leftPin, INPUT);
pinMode(rightPin, INPUT);
pinMode(upPin, INPUT);
pinMode(cancelPin, INPUT);
pinMode(okPin, INPUT);
// Serial communications setup
Serial.begin(115200);
// Use this initializer if using a 1.8" TFT screen:
tft.initR(INITR_BLACKTAB); // Init ST7735S chip, black tab
// OR use this initializer if using a 1.8" TFT screen with offset such as WaveShare:
// tft.initR(INITR_GREENTAB); // Init ST7735S chip, green tab
// See more options in Adafruit GFX library documentation
// Menu init, setup and draw
menu.init();
setupMenu();
menu.drawMenu();
}
void setupMenu() {
// Add buttons to menu page in a loop
for (int i = 0; i < sizeof(switches)/sizeof(Switch); i++) {
// Create instance of a button.
// Pass button title, callback function, and a callback argument (button ID in this case) to constructor
menuItemButtons[i] = new GEMItem(switches[i].title, pressButton, switches[i].id);
// Add menu item to menu page
menuPageMain.addMenuItem(*menuItemButtons[i]);
}
// Add menu page to menu and set it as current
menu.setMenuPageCurrent(menuPageMain);
}
void loop() {
// If menu is ready to accept button press...
if (menu.readyForKey()) {
// ...detect key press using KeyDetector library
myKeyDetector.detect();
// Pass pressed button to menu
// (pressed button ID is stored in trigger property of KeyDetector object)
menu.registerKeyPress(myKeyDetector.trigger);
}
}
void pressButton(GEMCallbackData callbackData) {
Serial.print("Button ID: ");
Serial.print(callbackData.valChar); // Accessing user-defined callback argument
Serial.print(" | Button title: ");
Serial.println(callbackData.pMenuItem->getTitle()); // Accessing menu item title
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment