Skip to content

Commit

Permalink
Merge pull request #185 from forntoh/issue/#178-menu-command-processo…
Browse files Browse the repository at this point in the history
…r-helpers

Menu command processor helper for rotatory encoder
  • Loading branch information
forntoh authored Sep 10, 2024
2 parents e1a3e9b + fe1b6b5 commit fcce601
Show file tree
Hide file tree
Showing 5 changed files with 214 additions and 4 deletions.
69 changes: 69 additions & 0 deletions examples/InputRotary/InputRotary.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#include <ItemCommand.h>
#include <ItemInput.h>
#include <ItemSubMenu.h>
#include <LcdMenu.h>
#include <SimpleRotary.h>
#include <interface/LiquidCrystalI2CAdapter.h>
#include <utils/RotaryNavConfig.h>

#define LCD_ROWS 2
#define LCD_COLS 16

#define CHARSET_SIZE 26
// Create your charset
char charset[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};
// Active index of the charset
int8_t charsetPosition = -1;

// Declare the call back functions
void inputCallback(char *value);
void clearInput();

extern MenuItem *usernameMenu[];

MAIN_MENU(
ITEM_SUBMENU("Set user", usernameMenu),
ITEM_BASIC("Settings"),
ITEM_BASIC("More Settings"),
ITEM_BASIC("And more Settings"));

SUB_MENU(
usernameMenu,
mainMenu,
ITEM_INPUT("User", inputCallback),
ITEM_COMMAND("Clear", clearInput));

LiquidCrystalI2CAdapter lcdAdapter(0x27, LCD_COLS, LCD_ROWS);
LcdMenu menu(lcdAdapter);

SimpleRotary encoder(2, 3, 4);

RotaryNavConfig menuConfig = {
.encoder = &encoder,
.menu = &menu,
.longPressDuration = 1000,
.charset = charset,
.charsetSize = CHARSET_SIZE,
.charsetPosition = charsetPosition,
};

void setup() {
Serial.begin(9600);
menu.initialize(mainMenu);
}

void loop() {
// Call the handleRotaryMenu function, passing the menuConfig instance
processWithRotaryEncoder(&menuConfig);
}

// Define the callbacks
void inputCallback(char *value) {
// Do stuff with value
Serial.print(F("# "));
Serial.println(value);
}

void clearInput() {
menu[1]->setValue((char *)"");
}
67 changes: 67 additions & 0 deletions examples/SimpleRotary/SimpleRotary.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#include <ItemList.h>
#include <ItemProgress.h>
#include <ItemToggle.h>
#include <LcdMenu.h>
#include <SimpleRotary.h>
#include <interface/LiquidCrystalI2CAdapter.h>
#include <utils/RotaryNavConfig.h>

#define LCD_ROWS 2
#define LCD_COLS 16

// Declare the callbacks
void callback(uint16_t pos);
void colorsCallback(uint16_t pos);
void toggleBacklight(uint16_t isOn);

char *intMapping(uint16_t progress) {
long mapped = mapProgress(progress, 100L, 200L);
static char buffer[10];
itoa(mapped, buffer, 10);
concat(buffer, 'm', buffer);
return buffer;
}

String colors[] = {"Red", "Green", "Blue", "Orange", "Aqua", "Yellow", "Purple", "Pink"};

MAIN_MENU(
ITEM_BASIC("Connect to WiFi"),
ITEM_STRING_LIST("Color", colors, 8, colorsCallback),
ITEM_BASIC("Blink SOS"),
ITEM_PROGRESS("Dist", 10, intMapping, callback),
ITEM_TOGGLE("Backlight", toggleBacklight),
ITEM_BASIC("Blink random"));

LiquidCrystalI2CAdapter lcdAdapter(0x27, LCD_COLS, LCD_ROWS);
LcdMenu menu(lcdAdapter);

SimpleRotary encoder(2, 3, 4);

RotaryNavConfig menuConfig = {
.encoder = &encoder,
.menu = &menu,
.longPressDuration = 1000,
};

void setup() {
Serial.begin(9600);
menu.initialize(mainMenu);
}

void loop() {
// Call the handleRotaryMenu function, passing the menuConfig instance
processWithRotaryEncoder(&menuConfig);
}

// Define the callbacks
void toggleBacklight(uint16_t isOn) {
lcdAdapter.lcd.setBacklight(isOn);
}

void callback(uint16_t pos) {
Serial.println(pos);
}

void colorsCallback(uint16_t pos) {
Serial.println(colors[pos]);
}
1 change: 1 addition & 0 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ lib_deps =
marcoschwartz/LiquidCrystal_I2C@^1.1.4
arduino-libraries/LiquidCrystal @ ^1.0.7
feilipu/FreeRTOS@^11.0.1-5
mprograms/SimpleRotary@^1.1.3
4 changes: 0 additions & 4 deletions src/LcdMenu.h
Original file line number Diff line number Diff line change
Expand Up @@ -461,10 +461,6 @@ class LcdMenu {
uint8_t lb = strlen(item->getText()) + 2;
uint8_t ub = lb + length;
ub = constrain(ub, lb, maxCols - 2);
printCmd(F("TYPE-CHAR-l"), length);
printCmd(F("TYPE-CHAR-lb"), lb);
printCmd(F("TYPE-CHAR-ub"), ub);
printCmd(F("TYPE-CHAR-bl"), lcd.blinkerPosition);
//
// update text
//
Expand Down
77 changes: 77 additions & 0 deletions src/utils/RotaryNavConfig.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#pragma once

#include <LcdMenu.h>
#include <SimpleRotary.h>

/**
* @brief Configuration for rotary encoder navigation in the LCD menu.
*
* @param encoder Pointer to the rotary encoder instance
* @param menu Pointer to the LCD menu instance
* @param longPressDuration Duration (ms) to consider a long press
* @param charset Pointer to the character set
* @param charsetSize Size of the character set
* @param charsetPosition Position in the character set
*/
struct RotaryNavConfig {
SimpleRotary *encoder;
LcdMenu *menu;
uint16_t longPressDuration;
#ifdef ItemInput_H
const char *charset;
uint8_t charsetSize;
int8_t charsetPosition;
#endif
};

/**
* @brief Handles rotary encoder navigation in the LCD menu.
*
* @param config Pointer to the RotaryNavConfig struct
*/
void processWithRotaryEncoder(RotaryNavConfig *config) {
// Handle rotary encoder rotation
uint8_t rotation = config->encoder->rotate();
if (rotation == 1) {
if (config->menu->lcd.getEditModeEnabled()) {
#ifdef ItemInput_H
if (config->charset) {
config->charsetPosition =
(config->charsetPosition + 1) % config->charsetSize;
config->menu->drawChar(
config->charset[config->charsetPosition]);
} else
#endif
config->menu->right(); // Call RIGHT action in edit mode
} else if (!config->menu->lcd.getEditModeEnabled()) {
config->menu->down(); // Call DOWN action in normal mode
}
} else if (rotation == 2) {
if (config->menu->lcd.getEditModeEnabled()) {
#ifdef ItemInput_H
if (config->charset) {
config->charsetPosition = constrain(config->charsetPosition - 1, 0, config->charsetSize - 1);
config->menu->drawChar(
config->charset[config->charsetPosition]);
} else
#endif
config->menu->left(); // Call LEFT action in edit mode
} else if (!config->menu->lcd.getEditModeEnabled()) {
config->menu->up(); // Call UP action in normal mode
}
}

// Handle button press (short and long press)
uint8_t pressType = config->encoder->pushType(config->longPressDuration);
if (pressType == 1) {
#ifdef ItemInput_H
if (config->charsetPosition != -1) {
config->menu->type(config->charset[config->charsetPosition]);
config->charsetPosition = -1;
}
#endif
config->menu->enter(); // Call ENTER action (short press)
} else if (pressType == 2) {
config->menu->back(); // Call BACK action (long press)
}
}

0 comments on commit fcce601

Please sign in to comment.