From 93e014c152c26bd181555fa76fd743ca453c1e1f Mon Sep 17 00:00:00 2001 From: Felix Kosmalla Date: Thu, 10 Sep 2020 01:28:13 +0200 Subject: [PATCH 01/19] added comment to origin of library --- src/menuIO/liquidCrystalOutI2C.h | 43 ++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 src/menuIO/liquidCrystalOutI2C.h diff --git a/src/menuIO/liquidCrystalOutI2C.h b/src/menuIO/liquidCrystalOutI2C.h new file mode 100644 index 00000000..70ad396c --- /dev/null +++ b/src/menuIO/liquidCrystalOutI2C.h @@ -0,0 +1,43 @@ +/* -*- C++ -*- */ + +//for using I2C LiquidCrystal Library provided by +// https://gitlab.com/tandembyte/LCD_I2C + +#ifndef RSITE_ARDUINO_MENU_LIQUIDCRYSTALOUT + #define RSITE_ARDUINO_MENU_LIQUIDCRYSTALOUT + #include "../menuDefs.h" + #include + + namespace Menu { + + class liquidCrystalOut:public cursorOut { + public: + LiquidCrystal_I2C& device; + inline liquidCrystalOut(LiquidCrystal_I2C& o,idx_t *t,panelsList &p,menuOut::styles s=minimalRedraw) + :cursorOut(t,p,s),device(o) {} + size_t write(uint8_t ch) override {return device.write(ch);} + void clear() override { + device.clear(); + panels.reset(); + } + void setCursor(idx_t x,idx_t y,idx_t panelNr=0) override { + const panel p=panels[panelNr]; + device.setCursor(p.x+x,p.y+y); + } + idx_t startCursor(navRoot& root,idx_t x,idx_t y,bool charEdit,idx_t panelNr=0) override {return 0;} + idx_t endCursor(navRoot& root,idx_t x,idx_t y,bool charEdit,idx_t panelNr=0) override {return 0;} + idx_t editCursor(navRoot& root,idx_t x,idx_t y,bool editing,bool charEdit,idx_t panelNr=0) override { + //text editor cursor + device.noBlink(); + device.noCursor(); + if (editing) { + device.setCursor(x, y); + if (charEdit) device.cursor(); + else device.blink(); + } + return 0; + } + }; + + }//namespace Menu +#endif From 0de1477dcb32770381cb049e97cc60be1174ce65 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Mon, 28 Sep 2020 15:21:00 +0300 Subject: [PATCH 02/19] Bump version to 4.21.4, use the same library name as for the Arduino IDE --- library.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library.json b/library.json index f8bb7cb8..3e19ae5b 100644 --- a/library.json +++ b/library.json @@ -1,5 +1,6 @@ { - "name": "ArduinoMenu", + "name": "ArduinoMenu library", + "version": "4.21.4", "keywords": "menu, display, lcd, tft, buttons, encoder, io, control", "description": "AVR generic menu/interactivity system", "repository": From 6d7dd1c0dc33781ec0702339d4e97ebd49157729 Mon Sep 17 00:00:00 2001 From: Rui Azevedo Date: Tue, 29 Sep 2020 08:47:29 +0000 Subject: [PATCH 03/19] Update .travis.yml remove missing fmalpartida file wget --- .travis.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0c2fd5b7..428df884 100644 --- a/.travis.yml +++ b/.travis.yml @@ -53,8 +53,8 @@ install: - wget https://github.com/neu-rah/AnsiStream/archive/master.zip -O /tmp/AnsiStream-master.zip - unzip /tmp/AnsiStream-master.zip -d /tmp/ - - wget https://bitbucket.org/fmalpartida/new-liquidcrystal/downloads/NewliquidCrystal_1.3.4.zip -O /tmp/NewliquidCrystal_1.3.4.zip - - unzip /tmp/NewliquidCrystal_1.3.4.zip -d /tmp/ + # - wget https://bitbucket.org/fmalpartida/new-liquidcrystal/downloads/NewliquidCrystal_1.3.4.zip -O /tmp/NewliquidCrystal_1.3.4.zip + # - unzip /tmp/NewliquidCrystal_1.3.4.zip -d /tmp/ # - wget https://github.com/adafruit/Adafruit-PCD8544-Nokia-5110-LCD-library/archive/master.zip -O /tmp/Adafruit-PCD8544-Nokia-5110-LCD-library-master.zip # - unzip /tmp/Adafruit-PCD8544-Nokia-5110-LCD-library-master.zip -d /tmp/ @@ -69,4 +69,5 @@ script: # - platformio ci --lib="." --lib="/tmp/SD-master" --board=nanoatmega328 --board=teensy31 # - platformio ci --lib="." --lib="/tmp/Streaming-master" --lib="/tmp/Adafruit-GFX-Library-master" --lib="/tmp/PCINT-master" --lib="/tmp/U8glib_Arduino-master" --lib="/tmp/AnsiStream-master" --lib="/tmp/NewliquidCrystal" --lib="/tmp/Adafruit-PCD8544-Nokia-5110-LCD-library-master" --lib="/tmp/Adafruit-ST7735-Library-master" --board=nanoatmega328 --board=teensy31 --board=due # - platformio ci --lib="." --lib="/tmp/Streaming-master" --lib="/tmp/Adafruit-GFX-Library-master" --lib="/tmp/PCINT-master" --lib="/tmp/U8glib_Arduino-master" --lib="/tmp/AnsiStream-master" --lib="/tmp/NewliquidCrystal" --lib="/tmp/Adafruit-ST7735-Library-master" --board=nanoatmega328 --board=teensy31 --board=due - - platformio ci --lib="." --lib="/tmp/Streaming-master" --lib="/tmp/PCINT-master" --lib="/tmp/U8glib_Arduino-master" --lib="/tmp/AnsiStream-master" --lib="/tmp/NewliquidCrystal" --board=nanoatmega328 --board=teensy31 --board=due + # - platformio ci --lib="." --lib="/tmp/Streaming-master" --lib="/tmp/PCINT-master" --lib="/tmp/U8glib_Arduino-master" --lib="/tmp/AnsiStream-master" --lib="/tmp/NewliquidCrystal" --board=nanoatmega328 --board=teensy31 --board=due + - platformio ci --lib="." --lib="/tmp/Streaming-master" --lib="/tmp/PCINT-master" --lib="/tmp/U8glib_Arduino-master" --lib="/tmp/AnsiStream-master" --board=nanoatmega328 --board=teensy31 --board=due From e09f2ff1b807f739919944492b7f94c69696778d Mon Sep 17 00:00:00 2001 From: Graham Whaley Date: Fri, 20 Nov 2020 17:17:34 +0000 Subject: [PATCH 04/19] groveRGBLCD: Add support for I2C Grove RGB LCD Add support for the Grove RGB LCD: https://wiki.seeedstudio.com/Grove-LCD_RGB_Backlight/ along with example file. This was as simple as replacing a standard 'lcd' element with the correct header and an 'rgb_lcd' object. Tested on a PJRC Teensy 4.0 board with a KY-040 click shaft encoder. Signed-off-by: Graham Whaley --- README.md | 4 + examples/GroveRGB/GroveRGB/GroveRGB.ino | 207 ++++++++++++++++++++++++ src/macros.h | 7 + src/menuIO/groveRGBLCDOut.h | 52 ++++++ 4 files changed, 270 insertions(+) create mode 100644 examples/GroveRGB/GroveRGB/GroveRGB.ino create mode 100644 src/menuIO/groveRGBLCDOut.h diff --git a/README.md b/README.md index 885845b3..ccde5f4e 100644 --- a/README.md +++ b/README.md @@ -283,6 +283,10 @@ https://github.com/neu-rah/AnsiStream - Unix terminal +**Grove RGB LCD I2C 2x16** + +https://wiki.seeedstudio.com/Grove-LCD_RGB_Backlight/ + **Web browser** - ESP8266 (builtin) diff --git a/examples/GroveRGB/GroveRGB/GroveRGB.ino b/examples/GroveRGB/GroveRGB/GroveRGB.ino new file mode 100644 index 00000000..33a57a67 --- /dev/null +++ b/examples/GroveRGB/GroveRGB/GroveRGB.ino @@ -0,0 +1,207 @@ +#include + +/******************** +Sept. 2014 Rui Azevedo - ruihfazevedo(@rrob@)gmail.com +Nov. 2020 Graham Whaley - adapted to Grove RGB LCD + +menu output to Grove RGB LCD I2C +output: GROVERGBLCD : https://wiki.seeedstudio.com/Grove-LCD_RGB_Backlight/ +input: click encoder and Serial +board: PJRC Teensy 4.0 : https://www.pjrc.com/store/teensy40.html +***/ + +#include +#include +#include +#include +#include +#include +#include + +using namespace Menu; + +// LCD, standard Grove I2C devices ///////////// +rgb_lcd lcd; + +// Encoder ///////////////////////////////////// +#define encA 3 +#define encB 2 +//this encoder has a button here +#define encBtn 4 + +ClickEncoder clickEncoder(encA,encB,encBtn,2); +ClickEncoderStream encStream(clickEncoder,1); + +//input from the clickencoder + serial +serialIn serial(Serial); +menuIn* inputsList[]={&encStream,&serial}; +chainStream<2> in(inputsList);//3 is the number of inputs + +#define LEDPIN LED_BUILTIN //Teensy 4.0 LED pin + +result doAlert(eventMask e, prompt &item); + +result showEvent(eventMask e,navNode& nav,prompt& item) { + Serial.print("event: "); + Serial.println(e); + return proceed; +} + +int test=55; + +result action1(eventMask e,navNode& nav, prompt &item) { + Serial.print("action1 event: "); + Serial.print(e); + Serial.println(", proceed menu"); + Serial.flush(); + return proceed; +} + +result action2(eventMask e,navNode& nav, prompt &item) { + Serial.print("action2 event: "); + Serial.print(e); + Serial.print(", quiting menu."); + Serial.flush(); + return quit; +} + +int ledCtrl=LOW; + +result myLedOn() { + ledCtrl=HIGH; + return proceed; +} +result myLedOff() { + ledCtrl=LOW; + return proceed; +} + +TOGGLE(ledCtrl,setLed,"Led: ",doNothing,noEvent,noStyle//,doExit,enterEvent,noStyle + ,VALUE("On",HIGH,doNothing,noEvent) + ,VALUE("Off",LOW,doNothing,noEvent) +); + +int selTest=0; +SELECT(selTest,selMenu,"Select",doNothing,noEvent,noStyle + ,VALUE("Zero",0,doNothing,noEvent) + ,VALUE("One",1,doNothing,noEvent) + ,VALUE("Two",2,doNothing,noEvent) +); + +int chooseTest=-1; +CHOOSE(chooseTest,chooseMenu,"Choose",doNothing,noEvent,noStyle + ,VALUE("First",1,doNothing,noEvent) + ,VALUE("Second",2,doNothing,noEvent) + ,VALUE("Third",3,doNothing,noEvent) + ,VALUE("Last",-1,doNothing,noEvent) +); + +//customizing a prompt look! +//by extending the prompt class +class altPrompt:public prompt { +public: + altPrompt(constMEM promptShadow& p):prompt(p) {} + Used printTo(navRoot &root,bool sel,menuOut& out, idx_t idx,idx_t len,idx_t) override { + return out.printRaw(F("special prompt!"),len);; + } +}; + +MENU(subMenu,"Sub-Menu",showEvent,anyEvent,noStyle + ,OP("Sub1",showEvent,anyEvent) + ,OP("Sub2",showEvent,anyEvent) + ,OP("Sub3",showEvent,anyEvent) + ,altOP(altPrompt,"",showEvent,anyEvent) + ,EXIT(" + #include + + namespace Menu { + + class grovergblcdOut:public cursorOut { + public: + rgb_lcd* device; + inline grovergblcdOut(rgb_lcd* o,idx_t *t,panelsList &p,menuOut::styles s=menuOut::minimalRedraw) + :cursorOut(t,p,s),device(o) {} + size_t write(uint8_t ch) override {return device->write(ch);} + void clear() override { + device->clear(); + panels.reset(); + } + void setCursor(idx_t x,idx_t y,idx_t panelNr=0) override { + const panel p=panels[panelNr]; + device->setCursor(p.x+x,p.y+y); + } + idx_t startCursor(navRoot& root,idx_t x,idx_t y,bool charEdit,idx_t panelNr=0) override {return 0;} + idx_t endCursor(navRoot& root,idx_t x,idx_t y,bool charEdit,idx_t panelNr=0) override {return 0;} + idx_t editCursor(navRoot& root,idx_t x,idx_t y,bool editing,bool charEdit,idx_t panelNr=0) override { + trace(MENU_DEBUG_OUT<<"lcdOut::editCursor "<noBlink(); + device->noCursor(); + if (editing) { + device->setCursor(x, y); + if (charEdit) device->cursor(); + else device->blink(); + } + return 0; + } + + }; + + }//namespace Menu + + #endif +#endif From c7133990948d83d37bfb9a1641248728308efab1 Mon Sep 17 00:00:00 2001 From: AJANYA98 <74367178+AJANYA98@users.noreply.github.com> Date: Fri, 22 Jan 2021 10:50:37 +0530 Subject: [PATCH 05/19] Update platformio.ini --- examples/ESP32/platformio.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/ESP32/platformio.ini b/examples/ESP32/platformio.ini index 25c6616a..35cfa66f 100644 --- a/examples/ESP32/platformio.ini +++ b/examples/ESP32/platformio.ini @@ -7,3 +7,4 @@ board = lolin32 framework=arduino build_flags =-Wno-reorder build_unflags=-Werror=reorder + From b94d456007d558179f883200754f09258325ded9 Mon Sep 17 00:00:00 2001 From: welshcoder Date: Tue, 14 Dec 2021 22:00:48 +0000 Subject: [PATCH 06/19] Add SmartMatrix as output option Adds the ability to use SmartMatrix hardware as a MenuOut device. Requires the SmartMatrix library and a background layer to be set up already. --- src/menuIO/SmartMatrixOut.h | 119 ++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 src/menuIO/SmartMatrixOut.h diff --git a/src/menuIO/SmartMatrixOut.h b/src/menuIO/SmartMatrixOut.h new file mode 100644 index 00000000..3b6e09d0 --- /dev/null +++ b/src/menuIO/SmartMatrixOut.h @@ -0,0 +1,119 @@ +#ifndef RSITE_ARDUINOP_MENU_SM +#define RSITE_ARDUINOP_MENU_SM + +#include +#include "..\menuDefs.h" +#include + +namespace Menu +{ + inline menuOut::styles operator | (menuOut::styles lhs, menuOut::styles rhs) + { + using T = std::underlying_type_t ; + return static_cast(static_cast(lhs) | static_cast(rhs)); + } + + inline menuOut::styles& operator |= (menuOut::styles& lhs, menuOut::styles rhs) + { + lhs = lhs | rhs; + return lhs; + } + + + template + class SmartMatrixOut : public gfxOut + { + + using SMBackground=SMLayerBackground; + + RGB currentColour{0,0,0}; + uint16_t cursorX=0, cursorY=0,line=0; + + public: + SMBackground &gfx; + const colorDef (&colors)[nColors]; + SmartMatrixOut(SMBackground &gfx, const colorDef (&c)[nColors], idx_t *t, panelsList &p, fontChoices font=fontChoices::font5x7, menuOut::styles s=minimalRedraw) + : gfxOut(fontLookup(font)->Width, fontLookup(font)->Height, t, p, s), gfx(gfx), colors(c) + { + gfx.setFont(font); + setCursor(0,0); + } + + virtual ~SmartMatrixOut() {} + + size_t write(uint8_t ch) override + { + if(ch=='\n') + { + setCursor(0,line+1); + } + else if(ch!='\r') + { + gfx.drawChar(cursorX,cursorY,currentColour,ch); + cursorX+=resX; + } + + return 1; + } + + inline RGB getColor(colorDefs color = bgColor, bool selected = false, status stat = enabledStatus, bool edit = false) const + { + return memWord(&(stat == enabledStatus ? colors[color].enabled[selected + edit] : colors[color].disabled[selected])); + } + + void setColor(colorDefs c, bool selected = false, status s = enabledStatus, bool e = false) override + { + currentColour=getColor(c,selected,s,e); + } + + void clearLine(idx_t ln, idx_t panelNr = 0, colorDefs color = bgColor, bool selected = false, status stat = enabledStatus, bool edit = false) override + { + const panel p = panels[panelNr]; + gfx.fillRectangle(p.x * resX, (p.y + ln) * resY + fontMarginY, (p.x+p.w) * resX, (p.y + ln + 1)*resY, getColor(color, selected, stat, edit)); + //setCursor(0,ln); + } + void clear() override + { + panels.reset(); + gfx.fillScreen(getColor(bgColor, false, enabledStatus, false)); + setCursor(0, 0); + setColor(fgColor); + } + + void box(idx_t panelNr, idx_t x, idx_t y, idx_t w = 1, idx_t h = 1, colorDefs c = bgColor, bool selected = false, status stat = enabledStatus, bool edit = false) override + { + const panel p = panels[panelNr]; + gfx.drawRectangle((p.x + x) * resX, (p.y + y) * resY + fontMarginY, (p.x + x + w) * resX, (p.y + y + h) * resY, getColor(c, selected, stat, edit)); + } + + void rect(idx_t panelNr, idx_t x, idx_t y, idx_t w = 1, idx_t h = 1, colorDefs c = bgColor, bool selected = false, status stat = enabledStatus, bool edit = false) override + { + const panel p = panels[panelNr]; + gfx.fillRectangle((p.x + x) * resX, (p.y + y) * resY + fontMarginY, (p.x + x + w) * resX, (p.y + y + h) * resY, getColor(c, selected, stat, edit)); + } + + void clear(idx_t panelNr) override + { + const panel p = panels[panelNr]; + gfx.fillRectangle(p.x * resX, p.y * resY, (p.x+p.w) * resX, (p.y+p.h) * resY, getColor(bgColor, false, enabledStatus, false)); + panels.nodes[panelNr] = NULL; + } + + void setCursor(idx_t x, idx_t y, idx_t panelNr = 0) override + { + line=y; + const panel p = panels[panelNr]; + cursorX=(p.x + x) * resX; + cursorY= (p.y + line) * resY + fontMarginY; + } + + void drawCursor(idx_t ln, bool selected, status stat, bool edit = false, idx_t panelNr = 0) override + { + const panel p = panels[panelNr]; + // gfxOut::drawCursor(ln,selected,stat); + gfx.drawRectangle(p.x * resX, (p.y + ln) * resY + fontMarginY, (p.x+p.w) * resX, (p.y + ln +1) * resY, getColor(cursorColor, selected, enabledStatus, false)); + } + }; + +}; //namespace adaGfxOut +#endif From 0b3cc286288b6abd81e068c59186187f65ce0434 Mon Sep 17 00:00:00 2001 From: Nagarjun Redla Date: Sun, 26 Dec 2021 02:37:21 +0530 Subject: [PATCH 07/19] Added flags and libs for ESP32 WebMenu support --- src/macros.h | 4 ++-- src/menuIO/esp8266Out.h | 32 +++++++++++++++++++++++++++++--- src/menuIO/esp8266Out.hpp | 2 +- src/menuIo.cpp | 2 +- src/menuIo.h | 2 +- 5 files changed, 34 insertions(+), 8 deletions(-) diff --git a/src/macros.h b/src/macros.h index 18b83ddd..112ed0eb 100644 --- a/src/macros.h +++ b/src/macros.h @@ -10,12 +10,12 @@ #define MENU_USERAM #endif #endif -#if defined(ESP8266) +#if defined(ESP8266) || defined(ESP32) #define MENU_ASYNC #define MENU_FMT_WRAPS #define MENU_IDLE_BKGND #endif -#if defined(ESP8266) | defined(CORE_TEENSY) +#if defined(ESP8266) || defined(CORE_TEENSY) || defined(ESP32) #define typeof(x) __typeof__(x) #endif #if defined(USE_PGM) || (defined(pgm_read_ptr_near) && !defined(MENU_USERAM)) diff --git a/src/menuIO/esp8266Out.h b/src/menuIO/esp8266Out.h index 3dbdb810..de6ca37c 100644 --- a/src/menuIO/esp8266Out.h +++ b/src/menuIO/esp8266Out.h @@ -2,14 +2,19 @@ #ifndef RSITE_ARDUINO_MENU_ESP8266OUT #define RSITE_ARDUINO_MENU_ESP8266OUT - #ifdef ESP8266 + #if defined(ESP8266) || defined(ESP32) #include "../menuDefs.h" + #ifdef ESP8266 #include + #include + #elif defined(ESP32) + #include + #include + #endif // based on WebServer: // https://github.com/esp8266/Arduino/tree/master/libraries/ESP8266WebServer // https://github.com/Links2004/arduinoWebSockets #include - #include #include #include "xmlFmt.h" @@ -61,6 +66,7 @@ class esp8266_WebServerOut:public esp8266BufferedOut { public: +#ifdef ESP8266 ESP8266WebServer &server; //using esp8266Out::esp8266Out; esp8266_WebServerOut( @@ -69,18 +75,38 @@ idx_t* t, panelsList& p ):esp8266BufferedOut(t,p),server(srv) {} +#elif defined(ESP32) + WebServer &server; + //using esp8266Out::esp8266Out; + esp8266_WebServerOut( + WebServer &srv, + /*const colorDef (&c)[nColors],*/ + idx_t* t, + panelsList& p + ):esp8266BufferedOut(t,p),server(srv) {} +#endif size_t write(uint8_t ch) override {response<<(char)ch;return 1;} // template inline esp8266_WebServerOut& operator<<(T t) {response< menuOut& menuOut::operator<<(T o) {(*(Stream*)this)<<(o);return *this;} #endif diff --git a/src/menuIo.h b/src/menuIo.h index 6d9a9840..cd2ae280 100644 --- a/src/menuIo.h +++ b/src/menuIo.h @@ -83,7 +83,7 @@ idx_t printText(const char* at,idx_t len); #if defined(MENU_DEBUG) || defined(MENU_ASYNC) virtual menuOut& operator<<(prompt const &p); - #ifdef ESP8266 + #if defined(ESP8266) || defined(ESP32) template menuOut& operator<<(T o); #endif #endif From 6a6c0f0d3ddaf04b24c6e38bda364a1c02962294 Mon Sep 17 00:00:00 2001 From: Nagarjun Redla Date: Sun, 26 Dec 2021 18:28:50 +0530 Subject: [PATCH 08/19] Updated esp8266_WebMenu example to work with ESP32 --- examples/esp8266_WebMenu/WebMenu/WebMenu.ino | 121 ++++++++++--------- 1 file changed, 67 insertions(+), 54 deletions(-) diff --git a/examples/esp8266_WebMenu/WebMenu/WebMenu.ino b/examples/esp8266_WebMenu/WebMenu/WebMenu.ino index f7fcde2b..1b21df57 100644 --- a/examples/esp8266_WebMenu/WebMenu/WebMenu.ino +++ b/examples/esp8266_WebMenu/WebMenu/WebMenu.ino @@ -43,10 +43,19 @@ so don't forget to change it. #endif //#include //to send javascript thru web socket (live update) #include +#ifdef ESP8266 #include extern "C" { #include "user_interface.h" } +#elif defined(ESP32) +#include + +// Use external analogWrite library for ESP32 (optional) +// for compatibility with older versions of espressif/arduino-esp32 +// https://github.com/Dlloydev/ESP32-ESP32S2-AnalogWrite +#include +#endif using namespace Menu; @@ -105,7 +114,11 @@ const char* serverName="192.168.1.79"; #define HTTP_PORT 80 #define WS_PORT 81 #define USE_SERIAL Serial +#ifdef ESP8266 ESP8266WebServer server(80); +#elif defined(ESP32) +WebServer server(80); +#endif WebSocketsServer webSocket(81); #define MAX_DEPTH 2 @@ -245,60 +258,60 @@ navRoot wsNav(mainMenu, ws_cursors, MAX_DEPTH, none, ws_out); //config myOptions('*','-',defaultNavCodes,false); -void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) { - switch(type) { - case WStype_DISCONNECTED: - //USE_SERIAL.printf("[%u] Disconnected!\n", num); - break; - case WStype_CONNECTED: { - IPAddress ip = webSocket.remoteIP(num); - //USE_SERIAL.printf("[%u] Connected from %d.%d.%d.%d url: %s\n", num, ip[0], ip[1], ip[2], ip[3], payload); - webSocket.sendTXT(num, "console.log('ArduinoMenu Connected')"); - } - break; - case WStype_TEXT: { - //USE_SERIAL.printf("[%u] get Text: %s\n", num, payload); - // nav.async((const char*)payload);//this is slow!!!!!!!! - __trace(Serial.printf("[%u] get Text: %s\n", num, payload)); - char*s=(char*)payload; - _trace(Serial<<"serve websocket menu"< Date: Thu, 2 Jun 2022 11:08:38 -0400 Subject: [PATCH 09/19] Typo fix --- src/menu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/menu.cpp b/src/menu.cpp index c3ff1641..2e7b5a56 100644 --- a/src/menu.cpp +++ b/src/menu.cpp @@ -15,7 +15,7 @@ result Menu::inaction(menuOut& o,idleEvent) { result Menu::maxDepthError(menuOut& o,idleEvent e) { trace(MENU_DEBUG_OUT<<"maxDepthError"< Date: Sat, 24 Sep 2022 07:13:16 +0200 Subject: [PATCH 10/19] serialIn arrow keys --- src/nav.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/nav.cpp b/src/nav.cpp index 743f12f5..b8d840e9 100644 --- a/src/nav.cpp +++ b/src/nav.cpp @@ -20,11 +20,26 @@ idx_t panelsList::maxY() const { // //////////////////////////////////////////////////////////////////////////////// +static uint8_t escaped = 0; + navCmd navNode::navKeys(char ch) { trace(MENU_DEBUG_OUT<<"navNode::navKeys"<useAccel&&strchr(numericChars,ch)) { return navCmd(idxCmd,ch-'1'); } + if ((escaped == 0) && (ch == '\e')) {escaped = 1; return noCmd;} + else if ((escaped == 1) && (ch == '[')) {escaped = 2; return noCmd;} + else if (escaped == 1) {escaped = 0; return noCmd;} + else if (escaped == 2) { + escaped = 0; + switch (ch) { + case 'A': return(downCmd); break; + case 'B': return(upCmd); break; + case 'C': return(enterCmd); break; + case 'D': return(escCmd); break; + default: return(noCmd); break; + } + } for(uint8_t i=0;inavCodes)/sizeof(navCode);i++) if (options->navCodes[i].ch==ch) return options->navCodes[i].cmd; return noCmd; From 131095dfd90dd0560103367256d9bcf9842f0885 Mon Sep 17 00:00:00 2001 From: Eric Devolder Date: Wed, 22 Mar 2023 17:19:02 +0000 Subject: [PATCH 11/19] fix for issue #412 --- src/menuIO/rotaryEventIn.h | 122 ++++++++++++++++++------------------- 1 file changed, 61 insertions(+), 61 deletions(-) diff --git a/src/menuIO/rotaryEventIn.h b/src/menuIO/rotaryEventIn.h index a2f09653..33c667f7 100644 --- a/src/menuIO/rotaryEventIn.h +++ b/src/menuIO/rotaryEventIn.h @@ -18,13 +18,13 @@ Generic Rotary/Button input // not sure where to put this.. -template inline T operator~ (T a) { return (T)~(int)a; } -template inline T operator| (T a, T b) { return (T)((int)a | (int)b); } -template inline T operator& (T a, T b) { return (T)((int)a & (int)b); } -template inline T operator^ (T a, T b) { return (T)((int)a ^ (int)b); } -template inline T& operator|= (T& a, T b) { return (T&)((int&)a |= (int)b); } -template inline T& operator&= (T& a, T b) { return (T&)((int&)a &= (int)b); } -template inline T& operator^= (T& a, T b) { return (T&)((int&)a ^= (int)b); } +template constexpr inline T operator~ (T a) { return (T)~(int)a; } +template constexpr inline T operator| (T a, T b) { return (T)((int)a | (int)b); } +template constexpr inline T operator& (T a, T b) { return (T)((int)a & (int)b); } +template constexpr inline T operator^ (T a, T b) { return (T)((int)a ^ (int)b); } +template constexpr inline T& operator|= (T& a, T b) { return (T&)((int&)a |= (int)b); } +template constexpr inline T& operator&= (T& a, T b) { return (T&)((int&)a &= (int)b); } +template constexpr inline T& operator^= (T& a, T b) { return (T&)((int&)a ^= (int)b); } #ifndef __rotaryEventIn_h__ @@ -37,60 +37,60 @@ template inline T& operator^= (T& a, T b) { return (T&)((int&)a ^= (int public: - enum EventType { - BUTTON_CLICKED = 1 << 0, - BUTTON_DOUBLE_CLICKED = 1 << 1, - BUTTON_LONG_PRESSED = 1 << 2, - - ROTARY_CW = 1 << 3, - ROTARY_CCW = 1 << 4, - }; - - EventType config; - EventType events; // we could do a fifo if we miss events - - RotaryEventIn(EventType c) - :config(c) { - // config for future use. we could raise if - // we are missing essential stuff - // and we need to absorb an arg anyway... - } - - void registerEvent(EventType e) { - events |= e; // add it to the current events - } - - int peek(void) override { return events; } - int available(void) override {return peek() != 0;} - - int read() override { - // enterCmd - if (events & EventType::BUTTON_CLICKED) { - events &= ~EventType::BUTTON_CLICKED; // remove from events - return options->navCodes[enterCmd].ch; - } - // escCmd - else if (events & (EventType::BUTTON_DOUBLE_CLICKED|EventType::BUTTON_LONG_PRESSED)) { - events &= ~(EventType::BUTTON_DOUBLE_CLICKED|EventType::BUTTON_LONG_PRESSED); // remove - return options->navCodes[escCmd].ch; - } - // downCmd - else if (events & EventType::ROTARY_CW) { - events &= ~EventType::ROTARY_CW; // remove from events - return options->navCodes[upCmd].ch; // down sends up on menu? bug? - } - // upCmd - else if (events & EventType::ROTARY_CCW) { - events &= ~EventType::ROTARY_CCW; // remove from events - return options->navCodes[downCmd].ch; // up sends down on menu? bug? - } - - else - return -1; - } - - void flush() override {} - size_t write(uint8_t v) override {return 0;} + enum EventType { + BUTTON_CLICKED = 1 << 0, + BUTTON_DOUBLE_CLICKED = 1 << 1, + BUTTON_LONG_PRESSED = 1 << 2, + + ROTARY_CW = 1 << 3, + ROTARY_CCW = 1 << 4, + }; + + EventType config; + EventType events; // we could do a fifo if we miss events + + RotaryEventIn(EventType c) + :config(c) { + // config for future use. we could raise if + // we are missing essential stuff + // and we need to absorb an arg anyway... + } + + void registerEvent(EventType e) { + events |= e; // add it to the current events + } + + int peek(void) override { return events; } + int available(void) override {return peek() != 0;} + + int read() override { + // enterCmd + if (events & EventType::BUTTON_CLICKED) { + events &= ~EventType::BUTTON_CLICKED; // remove from events + return options->navCodes[enterCmd].ch; + } + // escCmd + else if (events & (EventType::BUTTON_DOUBLE_CLICKED|EventType::BUTTON_LONG_PRESSED)) { + events &= ~(EventType::BUTTON_DOUBLE_CLICKED|EventType::BUTTON_LONG_PRESSED); // remove + return options->navCodes[escCmd].ch; + } + // downCmd + else if (events & EventType::ROTARY_CW) { + events &= ~EventType::ROTARY_CW; // remove from events + return options->navCodes[upCmd].ch; // down sends up on menu? bug? + } + // upCmd + else if (events & EventType::ROTARY_CCW) { + events &= ~EventType::ROTARY_CCW; // remove from events + return options->navCodes[downCmd].ch; // up sends down on menu? bug? + } + + else + return -1; + } + + void flush() override {} + size_t write(uint8_t v) override {return 0;} }; // class From 9ef1e267639140925add8a46dd8a12ec932d3b3d Mon Sep 17 00:00:00 2001 From: Rui Azevedo Date: Sun, 21 Jan 2024 18:12:01 -0100 Subject: [PATCH 12/19] Update README.md --- README.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/README.md b/README.md index ccde5f4e..cfdab2fa 100644 --- a/README.md +++ b/README.md @@ -16,12 +16,6 @@ Optionally the system can be operated in semi-automated mode, issuing navigation See the [wiki](https://github.com/neu-rah/ArduinoMenu/wiki) -### COVID-19 note - -**If you need this menu for any device covid-19 related, be my guest, I grant you free usage even if you going to sell the device** - -This menu system has the advantage of being long tested and supporting many interface devices so that makers don't be restricted in hardware. - ## Simple Example ```c++ #include From a9badfc6830132ce2ad74ccbd3c315917c0c5f71 Mon Sep 17 00:00:00 2001 From: cemik1 <100765359+cemik1@users.noreply.github.com> Date: Thu, 1 Aug 2024 10:12:45 +0200 Subject: [PATCH 13/19] Update rotaryEventIn.h fix for issue #414 --- src/menuIO/rotaryEventIn.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/menuIO/rotaryEventIn.h b/src/menuIO/rotaryEventIn.h index 33c667f7..29aa4195 100644 --- a/src/menuIO/rotaryEventIn.h +++ b/src/menuIO/rotaryEventIn.h @@ -42,9 +42,14 @@ template constexpr inline T& operator^= (T& a, T b) { return (T&)((int& BUTTON_DOUBLE_CLICKED = 1 << 1, BUTTON_LONG_PRESSED = 1 << 2, - ROTARY_CW = 1 << 3, + ROTARY_CW = 1 << 5, // fix for issue #414 ROTARY_CCW = 1 << 4, }; +/* +EventType values should be different for codes defined as: +const navCodesDef Menu::defaultNavCodes (menuBase.cpp file) +and special cases in textField::parseInput (items.cpp file) function +*/ EventType config; EventType events; // we could do a fifo if we miss events From ca689063029e414a86109e9329b774ec14f59726 Mon Sep 17 00:00:00 2001 From: Rui Azevedo Date: Mon, 4 Nov 2024 07:23:32 -0100 Subject: [PATCH 14/19] Update library.json (bump version after fix) for issue #414 --- library.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.json b/library.json index 3e19ae5b..43516f06 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "ArduinoMenu library", - "version": "4.21.4", + "version": "4.21.5", "keywords": "menu, display, lcd, tft, buttons, encoder, io, control", "description": "AVR generic menu/interactivity system", "repository": From 6fcfc5c0acce3b9a77c0e6a3417f7de7ff45cba3 Mon Sep 17 00:00:00 2001 From: Rui Azevedo Date: Wed, 1 Jul 2026 22:33:46 +0000 Subject: [PATCH 15/19] Create arduinomenu-funding.json for project funding Added funding information for ArduinoMenu project, including maintainer details and project description. --- arduinomenu-funding.json | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 arduinomenu-funding.json diff --git a/arduinomenu-funding.json b/arduinomenu-funding.json new file mode 100644 index 00000000..85232d65 --- /dev/null +++ b/arduinomenu-funding.json @@ -0,0 +1,33 @@ +{ + "$schema": "https://fundingjson.org/schema/v1.1.0.json", + "version": "v1.1.0", + "entity": { + "type": "individual", + "role": "maintainer", + "name": "Rui Azevedo", + "email": "ruihfazevedo@gmail.com", + "phone": "", + "description": "Freelance embedded systems engineer with 35+ years of experience, based in the Azores, Portugal. Author of ArduinoMenu and the HAPI (Open Chain Derivation) compile-time composition framework, part of the InternetOfPins open source ecosystem (OneParse, OneMenu, OneChip, and related libraries) aimed at eliminating per-chip-variant fragmentation in embedded/IoT firmware.", + "webpageUrl": { + "url": "https://r-site.net", + "wellKnown": "" + } + }, + "projects": [ + { + "guid": "arduinomenu", + "name": "ArduinoMenu", + "description": "An open source menu/UI library for embedded and IoT devices (AVR, ESP32, STM32, and other MCU targets), used wherever a device needs a navigable on-device UI: buttons, encoders, LCD/OLED/TFT displays, serial terminals, or web interfaces. In production use for over a decade, with 1,000+ GitHub stars and preservation in the GitHub Arctic Code Vault. Funding supports migrating the library onto a newer, zero-overhead compile-time architecture (HAPI, part of the InternetOfPins ecosystem) and resolving a known compiler-diagnostics barrier that discourages less experienced adopters.", + "webpageUrl": { + "url": "https://github.com/neu-rah/ArduinoMenu", + "wellKnown": "" + }, + "repositoryUrl": { + "url": "https://github.com/neu-rah/ArduinoMenu", + "wellKnown": "" + }, + "licenses": ["spdx:LGPL-2.1"], + "tags": ["embedded", "iot", "arduino", "menu", "ui", "cpp", "avr", "esp32", "stm32"] + } + ] +} From 2bb7f1e919906e58798f07af84b0a7333df94c38 Mon Sep 17 00:00:00 2001 From: Rui Azevedo Date: Wed, 1 Jul 2026 22:45:47 +0000 Subject: [PATCH 16/19] Update funding.json with new structure and funding info Removed unnecessary schema reference and updated URLs for consistency. Added funding channels and plans to support ongoing development. --- arduinomenu-funding.json | 51 ++++++++++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/arduinomenu-funding.json b/arduinomenu-funding.json index 85232d65..813c643e 100644 --- a/arduinomenu-funding.json +++ b/arduinomenu-funding.json @@ -1,5 +1,4 @@ { - "$schema": "https://fundingjson.org/schema/v1.1.0.json", "version": "v1.1.0", "entity": { "type": "individual", @@ -9,8 +8,7 @@ "phone": "", "description": "Freelance embedded systems engineer with 35+ years of experience, based in the Azores, Portugal. Author of ArduinoMenu and the HAPI (Open Chain Derivation) compile-time composition framework, part of the InternetOfPins open source ecosystem (OneParse, OneMenu, OneChip, and related libraries) aimed at eliminating per-chip-variant fragmentation in embedded/IoT firmware.", "webpageUrl": { - "url": "https://r-site.net", - "wellKnown": "" + "url": "https://r-site.net" } }, "projects": [ @@ -19,15 +17,48 @@ "name": "ArduinoMenu", "description": "An open source menu/UI library for embedded and IoT devices (AVR, ESP32, STM32, and other MCU targets), used wherever a device needs a navigable on-device UI: buttons, encoders, LCD/OLED/TFT displays, serial terminals, or web interfaces. In production use for over a decade, with 1,000+ GitHub stars and preservation in the GitHub Arctic Code Vault. Funding supports migrating the library onto a newer, zero-overhead compile-time architecture (HAPI, part of the InternetOfPins ecosystem) and resolving a known compiler-diagnostics barrier that discourages less experienced adopters.", "webpageUrl": { - "url": "https://github.com/neu-rah/ArduinoMenu", - "wellKnown": "" + "url": "https://github.com/neu-rah/ArduinoMenu" }, "repositoryUrl": { - "url": "https://github.com/neu-rah/ArduinoMenu", - "wellKnown": "" + "url": "https://github.com/neu-rah/ArduinoMenu" }, - "licenses": ["spdx:LGPL-2.1"], - "tags": ["embedded", "iot", "arduino", "menu", "ui", "cpp", "avr", "esp32", "stm32"] + "licenses": [ + "spdx:LGPL-2.1" + ], + "tags": [ + "embedded", + "iot", + "arduino", + "menu", + "ui", + "cpp", + "avr", + "esp32", + "stm32" + ] } - ] + ], + "funding": { + "channels": [ + { + "guid": "paypal", + "type": "payment-provider", + "address": "https://www.paypal.com/paypalme/ruihfazevedo", + "description": "PayPal.Me" + } + ], + "plans": [ + { + "guid": "one-time", + "status": "active", + "name": "One-time donation", + "description": "Support ongoing development", + "amount": 0, + "currency": "EUR", + "frequency": "one-time", + "channels": null + } + ], + "history": [] + } } From baa9266be7b7086d4ac030ea6a6c719dd0849dd3 Mon Sep 17 00:00:00 2001 From: Rui Azevedo Date: Wed, 1 Jul 2026 22:54:49 +0000 Subject: [PATCH 17/19] Rename arduinomenu-funding.json to funding.json --- arduinomenu-funding.json => funding.json | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename arduinomenu-funding.json => funding.json (100%) diff --git a/arduinomenu-funding.json b/funding.json similarity index 100% rename from arduinomenu-funding.json rename to funding.json From 9233daaab28cab223dd4ce9411c61af6e9401f85 Mon Sep 17 00:00:00 2001 From: Rui Azevedo Date: Fri, 3 Jul 2026 02:47:52 +0000 Subject: [PATCH 18/19] Update README with OneMenu/HAPI development info Added section about the successor project OneMenu built on HAPI, including development status and links. --- README.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/README.md b/README.md index cfdab2fa..a31036b8 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,21 @@ Optionally the system can be operated in semi-automated mode, issuing navigation See the [wiki](https://github.com/neu-rah/ArduinoMenu/wiki) +## What's next — OneMenu / HAPI + +A successor is in active development, built on **HAPI**, a zero-overhead +compile-time composition engine (github.com/InternetOfPins/HAPI). Menu +definitions compile down to code indistinguishable from hand-written C — +see it for yourself: [Compiler Explorer demo](https://godbolt.org/z/6srTzdTY7). + +This isn't a release. The core (**OneMenu**) is solid, but a drop-in +compatibility layer for existing AM4 sketches is not done yet — that's the +main blocker before this becomes a real v5. If you're interested in the +architecture, want to help with the compatibility layer, or just want to +follow along, the repo is open: github.com/InternetOfPins/HAPI + +No migration is required right now. AM4 keeps working exactly as it does today. + ## Simple Example ```c++ #include From 5e974292091af1603157c3ca0089ba1974af518d Mon Sep 17 00:00:00 2001 From: neu-rah Date: Wed, 8 Jul 2026 04:15:04 +0000 Subject: [PATCH 19/19] docs: point the OneMenu/HAPI README note at the AM5 branch The drop-in compat layer mentioned here now exists and has real (unmodified) AM4 examples building against it -- link to where the work actually lives instead of just naming it as a future blocker. --- README.md | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index a31036b8..64b2742c 100644 --- a/README.md +++ b/README.md @@ -23,11 +23,16 @@ compile-time composition engine (github.com/InternetOfPins/HAPI). Menu definitions compile down to code indistinguishable from hand-written C — see it for yourself: [Compiler Explorer demo](https://godbolt.org/z/6srTzdTY7). -This isn't a release. The core (**OneMenu**) is solid, but a drop-in -compatibility layer for existing AM4 sketches is not done yet — that's the -main blocker before this becomes a real v5. If you're interested in the -architecture, want to help with the compatibility layer, or just want to -follow along, the repo is open: github.com/InternetOfPins/HAPI +This isn't a release. The core (**OneMenu**) is solid, and a drop-in +compatibility layer for existing AM4 sketches is now in progress on the +**[AM5 branch](https://github.com/neu-rah/ArduinoMenu/tree/AM5)** of this +repo — real, unmodified AM4 examples (Blink, Button, Confirm so far) already +build against it with just a library-dependency swap, at roughly the same +flash/RAM savings as the Compiler Explorer demo above suggests. Still missing +pieces (masked text-field editing, the idle/suspend API, most device +drivers) before it covers AM4's full example set. If you're interested in +the architecture, want to help with the compatibility layer, or just want to +follow along: github.com/InternetOfPins/HAPI No migration is required right now. AM4 keeps working exactly as it does today.