Code Monkey home page Code Monkey logo

gem's People

Contributors

45gfg9 avatar danieltwagner avatar per1234 avatar spirik avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

gem's Issues

Replace/override sprites for menu decorations?

Just making sure I'm not missing something - the sprites for things like leftArrow, rightArrow, and selectArrows are fixed at 6x8 pixels?

My C++ is a little rusty - but I'm thinking that since the sprites are defined as constants, outside of the GEM class (I think they have to be that way, because they have to be PROGMEM?), the only way I can replace them is by editing GEM.cpp (and then not upgrading GEM - or reapplying the changes when I upgrade)? The PROGMEM requirement means they can't be replaced on the fly, either.

I'm using a font that's 14x24 pixels (Adafruit GFX FreeMono12pt7b) - the existing sprites are really small on the screen, so I'd like to replace them with a bigger version of the same sprite.

u8g2, Adafruit GFX libraries

Your menu looks great.
Please, add support for these two major GFX libraries. Or, at least, for u8g2. Thanks in advance.

Limiting float and integer variable

When choosing a variable item I want it to be limited so the user won't be able to increase it more than a maximum or decrease it less than the minimum, how should I implement it?
I used the constrain function but it doesn't work.

Visible or NotVisible function

Hello Alexander,
In my project, I use a check box "Use motor" with a lot of parameter for my motor for exemple "Option 1",....
When "Use motor" is don't check, i use the read only function to lock the parameter but i will be more clean to don't see these parameter with a visible function.
example :
MyMenuItem.visible(false);
....

New val types

For now, only GEM_VAL_INTEGER and GEM_VAL_BYTE are supported. What about adding GEM_VAL_FLOAT?

It would also be very handy to have a GEM_VAL_HEX type, showing int/byte values in hexa, but it may be an option for those 2 types; don't know what is better...

I think the types management could be refactored, to support new types, with there specific edition way. For example, I'm thinking to a GEM_VAL_IP, to edit an IP value. But I guess it is a lot of work.

Add switch to disable splash screen and/or change its display time

I think there should be a possibility to disable splash screen and/or to change display time of it. Something like this (pseudocode):

void GEM::init(bool show_splash, uint32_t delay_ms)
{
    init_stuff_here();
    if(show_splash)
    {
        splash_XBMP_display();
        if(_enableVersion)
        {
            delay(delay_ms/2);
            version_display();
            delay(delay_ms/2);
        }
        else
        {
            delay(delay_ms);
        }
    }
    clear_stuff_here();
}

BTW: using hard-coded delay() or any do_nothing_for_some_time inside library functions are strongly discouraged in embedded software unless they are explicitly named (e.g. init_splash_wait), it could break the whole app, especially those not RTOS-based!

Can´t add a GEMItem to more than one GEMPage?

Hi, im' working on a rather big menu (as for today, about 90 GEMPages, 450 GEMItems), & having issues with ESP32 memory for other tasks. some of that items are references to the same object in struct, but execute different methods ( hence they go on different pages) . if I bind a GEMItem to certain page, i cannot bind it to a different one afterwards.

any hints about this? is it a known limitation? thanks!

Encoder or/and 4x4_over_i2c_multiplexer

Howdy. First of all, this lib is very nice, seems easy to use and I couldn't find many others that can use SPI 128x64 display.

But back on the topic. I wanted to use it in my project with uses quite a lot of pins rn on its own. Soo reusing 7 just for menu when i have already 16 keys on 4x4 keyboard, thats plugged into i2c multiplexer, soo actually it uses 2 pins of micro controler.
I tought using 2 rotary encoders will do the trick, with they didn't becouse of how they work.

Soo i tought if there is a way of doing it, or easy way to implement those funcionalities directlly. Mebe by using something like functions insead of pins. like instead of pin 6 being home/cancel, calling GEM_cancel() would do same.

Thanks in advance.

Switch button behavior for 3-buttons navigations

Hello,

I have a display with only 3 buttons (up, down, enter). I would like to use the library to create menus, but to do so, I have to switch the key behaviour when the menu is in editing mode or in navigation mode.
Is it possible to have the feedback of the menu state to switch behaviour?

Thanks

core 1 panic'ed (loadprohibited) on registerKeyPress

Hello,

I'm using GEM in combination with a rotaryEncoder on a ESP32 board.

I've created a main menu with some options and cyclically call the code below:
`

if(menu.readyForKey()) {

      byte keyCode = encoder_status;
   
      menu.registerKeyPress(keyCode);
    }

The encoder_status is initiated = GEM_KEY_NONE.

Whenever a change in the encoder value is detected, I calculate the delta and set the value of encoder_status accordingly:

  • delta > 0 , then encoder_status = GEM_KEY_DOWN
  • delta < 0, then encoder_status = GEM_KEY_UP
  • button pressed, then encoder_status = GEM_KEY_OK

Unfortunately, every time menu.registerKeyPress(keyCode); is called with an input value other than GEM_KEY_NONE, it causes my board to restart with the following trace below. Any tip what could be happening?

Thank you very much for your time.

`
Guru Meditation Error: Core 1 panic'ed (LoadProhibited). Exception was unhandled.
Core 1 register dump:
PC : 0x400014dc PS : 0x00060e30 A0 : 0x800d48e4 A1 : 0x3ffb1e80
A2 : 0x800d3fd7 A3 : 0x800d3fd3 A4 : 0x000000ff A5 : 0x0000ff00
A6 : 0x00ff0000 A7 : 0xff000000 A8 : 0x000000aa A9 : 0x00000040
A10 : 0x00000001 A11 : 0x00000000 A12 : 0x00000000 A13 : 0x0000ffff
A14 : 0x0000ffff A15 : 0x3ffb0060 SAR : 0x00000013 EXCCAUSE: 0x0000001c
EXCVADDR: 0x800d3fd7 LBEG : 0x4000c46c LEND : 0x4000c477 LCOUNT : 0x00000000

ELF file SHA256: 0000000000000000

Backtrace: 0x400014dc:0x3ffb1e80 0x400d48e1:0x3ffb1e90 0x400d4901:0x3ffb1eb0 0x400d339c:0x3ffb1ed0 0x400d39ad:0x3ffb1ef0 0x400d39ee:0x3ffb1f10 0x400d3f7a:0x3ffb1f30 0x400d3fd4:0x3ffb1f50 0x400d0ac1:0x3ffb1f70 0x400d0773:0x3ffb1f90 0x400d4de1:0x3ffb1fb0 0x40089a2e:0x3ffb1fd0

Rebooting...
ets Jul 29 2019 12:21:46

rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1216
ho 0 tail 12 room 4
load:0x40078000,len:10944
load:0x40080400,len:6388
entry 0x400806b4

`

ESP32 use hardware u8g2 i2c cause flash crash

I copied example and just changed

U8G2_KS0108_128X64_1 u8g2(U8G2_R0, 8, 9, 10, 11, 12, 13, 18, 19, /*enable=*/ A0, /*dc=*/ A1, /*cs0=*/ A3, /*cs1=*/ A2, /*cs2=*/ U8X8_PIN_NONE, /* reset=*/ U8X8_PIN_NONE);   // Set R/W to low!

to

U8G2_SSD1327_MIDAS_128X128_F_HW_I2C u8g2(U8G2_R0, /* reset=*/U8X8_PIN_NONE);

Build with -D GEM_DISABLE_GLCD -D GEM_DISABLE_ADAFRUIT_GFX, but it cause an esp32 flash error when uploaded and rebooted, tried two pieces but end with the same result.

rst:0x10 (RTCWDT_RTC_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
flash read err, 1000
ets_main.c 371

Then can not use esptool.py to write or erase flash anymore.

WARNING: Failed to communicate with the flash chip, read/write operations will fail. Try checking the chip connections or removing any other hardware connected to IOs.
A fatal error occurred: Packet content transfer stopped (received 8 bytes)

Setting conditional pages

I'm going to put some variables on the same pages and I want them to be limited, e.g. when setting variable X and pushing the next button it shouldn't be able to get lower than 2 and if so I want to show an error and go back to the page.

Add std::function callbacks feature

Hi there!
Would be really nice to have functional callbacks in menu items. I.e. like here. This is required to use capturing lambda functions or class instance members for menu callbacks.
Thanks!

Use GEM as optionnal menu

Hi!

In my application, I plan to use the screen to display some informations (using u8g2). And, sometimes, I want to switch to GEM menu system to do some configuration and specific tasks, then go back to my own display.

So, I need to enable/disable the menu system on request.

How would you do that?

Thanks,

Editing number value...

Now that we have this working on my Adafruit M0 and Featherwing OLED, I'm having trouble editing the number value... If I set the highest digit ("-" by default) to 0 or blank, the number becomes 512. There doesn't seem to be a way to add the negative value back in except for changing the 5 to a "-", the 1 to a 5, the 2 to a 1, and adding a digit for the 2... or am I missing something? (I have tried adding buttons to the sketch, for instance, left but it doesn't seem like you can move the cursor left to create an additional most significant digit. Thank you so much!

error while trying to compile

In file included from /Users/devnull/Documents/Arduino/libraries/GEM/src/GEM.h:40,
                 from /Users/devnull/Documents/Arduino/libraries/GEM/src/GEM.cpp:34:
/Users/devnull/Documents/Arduino/libraries/AltSerialGraphicLCD/AltSerialGraphicLCD.h:197:25: error: section attribute not allowed for 'crlf'
  197 |     char const PROGMEM *crlf;
      |                         ^~~~
/Users/devnull/Documents/Arduino/libraries/AltSerialGraphicLCD/AltSerialGraphicLCD.h:283:40: error: section attribute not allowed for 's'
  283 |     void putstr_P (const char PROGMEM *s);
      |                    ~~~~~~~~~~~~~~~~~~~~^
/Users/devnull/Documents/Arduino/libraries/AltSerialGraphicLCD/AltSerialGraphicLCD.h:340:42: error: section attribute not allowed for 'data'
  340 |     void write_P (const uint8_t PROGMEM *data, int length);
      |                   ~~~~~~~~~~~~~~~~~~~~~~~^~~~
/Users/devnull/Documents/Arduino/libraries/AltSerialGraphicLCD/AltSerialGraphicLCD.h:568:93: error: section attribute not allowed for 's'
  568 |     void setString_P(uint8_t posX, uint8_t posY, uint8_t justification, const char PROGMEM *s)
      |                                                                         ~~~~~~~~~~~~~~~~~~~~^
/Users/devnull/Documents/Arduino/libraries/AltSerialGraphicLCD/AltSerialGraphicLCD.h:842:59: error: section attribute not allowed for 'sprite'
  842 |     void loadSprite_P (uint8_t id, const uint8_t PROGMEM *sprite)
      |                                    ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~
/Users/devnull/Documents/Arduino/libraries/AltSerialGraphicLCD/AltSerialGraphicLCD.h:857:47: error: section attribute not allowed for 'sprite_pixels'
  857 |                        const uint8_t PROGMEM *sprite_pixels)
      |                        ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~
/Users/devnull/Documents/Arduino/libraries/AltSerialGraphicLCD/AltSerialGraphicLCD.h:871:71: error: section attribute not allowed for 'sprite'
  871 |     void loadSprite_P (uint8_t id, int length, const uint8_t PROGMEM *sprite)
      |                                                ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~
/Users/devnull/Documents/Arduino/libraries/AltSerialGraphicLCD/AltSerialGraphicLCD.h:931:43: error: section attribute not allowed for 'sprite'
  931 |                    const uint8_t PROGMEM *sprite)
      |                    ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~
/Users/devnull/Documents/Arduino/libraries/AltSerialGraphicLCD/AltSerialGraphicLCD.h:948:59: error: section attribute not allowed for 'sprite_pixels'
  948 |                    uint8_t height, const uint8_t PROGMEM *sprite_pixels)
      |                                    ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~
/Users/devnull/Documents/Arduino/libraries/AltSerialGraphicLCD/AltSerialGraphicLCD.h:965:55: error: section attribute not allowed for 'sprite'
  965 |                    int length, const uint8_t PROGMEM *sprite)
      |                                ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~
/Users/devnull/Documents/Arduino/libraries/AltSerialGraphicLCD/AltSerialGraphicLCD.h:990:62: error: section attribute not allowed for 'xylist'
  990 |     void drawPolygon_P (uint8_t mode, const uint8_t PROGMEM *xylist)
      |                                       ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~
/Users/devnull/Documents/Arduino/libraries/AltSerialGraphicLCD/AltSerialGraphicLCD.h:1013:48: error: section attribute not allowed for 'xylist'
 1013 |     void drawPolygon_P (const uint8_t PROGMEM *xylist)
      |                         ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~
/Users/devnull/Documents/Arduino/libraries/AltSerialGraphicLCD/AltSerialGraphicLCD.h:1039:60: error: section attribute not allowed for 'xylist'
 1039 |     void drawLines_P (uint8_t mode, const uint8_t PROGMEM *xylist)
      |                                     ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~
/Users/devnull/Documents/Arduino/libraries/AltSerialGraphicLCD/AltSerialGraphicLCD.h:1062:46: error: section attribute not allowed for 'xylist'
 1062 |     void drawLines_P (const uint8_t PROGMEM *xylist)
      |                       ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~
In file included from /Users/devnull/Documents/Arduino/libraries/GEM/src/GEM.cpp:34:
/Users/devnull/Documents/Arduino/libraries/GEM/src/GEM.h:97:43: error: section attribute not allowed for 'sprite'
   97 |     void setSplash(const uint8_t PROGMEM *sprite);       // Set custom sprite displayed as the splash screen when GEM is being initialized. Should be called before GEM::init().
      |                    ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~
/Users/devnull/Documents/Arduino/libraries/GEM/src/GEM.h:138:28: error: section attribute not allowed for '_splash'
  138 |     const uint8_t PROGMEM *_splash;
      |                            ^~~~~~~
/Users/devnull/Documents/Arduino/libraries/GEM/src/GEM.cpp:123:44: error: section attribute not allowed for 'sprite'
  123 | void GEM::setSplash(const uint8_t PROGMEM *sprite) {
      |                     ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~
exit status 1
Error compiling for board NodeMCU 1.0 (ESP-12E Module).

AltSerialGraphicLCD v1.38

Gem 1.2.2 (itoa and settitle for pageitem)

Hello,
I put your new release (1.2.2) tonight and itoa is not define with my configuration (stm32 core).
i need to add this
`
#include <Arduino.h>
#include "GEM_u8g2.h"
#include <itoa.h>

#ifdef GEM_ENABLE_U8G2_VERSION
`

This release is perfect, with the possibility to change the resolution for float.
I use the setTitle for change the lang of the menu but it's impossble tu change the name of a pageitem !
a small video :
https://www.youtube.com/watch?v=-S_ZRFjv2ss

Great job and thankyou

Readonly items

What about:

  • skip readonly items when navigating the menu;
  • extend this feature to all items, but GEM_ITEM_BACK.

.drawMenu() leads to blinking screen

Hi

Thanks for this absolute blast of a library! I really appreciate the extensive documentation.

I'm trying to make a menu with GEM_adafruit_gfx.h on this screen and want to display a value that automatically updates (e.g. the runtime millis()) as a MenuItem. My problem is now that the value does not update unless I press one of the buttons. I tried to call menu.drawMenu every certain time interval, but this leads to extensive blinking of the screen (i.e. going to black and then correctly displaying the Menu).

Obviously there must be a way to update the screen without blinking, as this happens when a key is pressed. I tried to understand what exactly happens when pressing a button, but could find nothing else but .drawMenu(). What am I missing?
How can I update the screen (or displayed values), without the blinking?

Cheers,
gerberli

License not suitable for code?

Looks like nice library, well-designed and clean code!

However, you've selected the CC license for it. That license is not intended to apply to code. I believe it will work, but there are other more specific licenses, such as the GPL (which should be similar in terms with CC-SA, not sure about its attribution requirements). Did you intentionally choose CC, despite of this? Or should you perhaps reconsider the license?

Supports setting single one menu attributes

When I want to setting only one or a a little attributes, it need to fill complete instance here. Do you want to support a set function like setMenuItemHeight etc.?

before:

GEM_u8g2 menu(u8g2, /*menuPointerType_=*/GEM_POINTER_ROW,
              /*menuItemsPerScreen_=*/GEM_ITEMS_COUNT_AUTO,
              /*menuItemHeight_=*/12,
              /*menuPageScreenTopOffset_=*/10, /*menuValuesLeftOffset_=*/86);

after:

GEM_u8g2 menu(u8g2);
menu.setMenuItemHeight(12);

Context Loop only triggers on input

So, I'm working on an incredibly silly mp3 player, and things are going fairly smooth.

I've set up a menuContextLoop which displays a "now playing screen". It's a static screen for now, so I didn't notice, but the loop is only triggering when a button is pressed, or the rotary encoder turns. I'm working off the "Party Hard" sketch, and it looks like I've set it up the same way, but it's just not running continuously. I have a progress bar, for example, that should update every second, but it never fires unless I turn the dial. The rest of the program works, but without the loop triggering as expected, I can't check if playback has stopped.

#include <Arduino.h>
#include <string.h>
#include <FastLED.h>
#include <U8g2lib.h>
#include <DYPlayerArduino.h>
#include <SD.h>
#include "bitmaps.h"
#include <GEM_u8g2.h>
#include "gemproxy.h"
#include "main.h"
#include <Encoder.h>
#include <Automaton.h>
#include "healzone.h"
#include "sg02.h"


#define HAS_HARDWARE_SERIAL

#define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0]))

#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif

#define NUM_LEDS 16
#define LED_DATA_PIN 4

#define BTN_A 20
#define BTN_B 19

#define BEEPER 23

#define ENC_A 5
#define ENC_B 6
#define ENC_BTN 22

#define DY_TX 0 // on the RX1 pin
#define DY_RX 1 
#define DY_BUSY 2 

#define SD_CS 10
#define SD_MOSI 11
#define SD_SCK 13
#define SD_MISO 12

#define LCD_CS 9
#define LCD_CLOCK 14
#define LCD_DATA 7

#define GEM_DISABLE_GLCD
#define GEM_DISABLE_ADAFRUIT_GFX

#define ENC_SLOWDOWN 2

using namespace DY;


U8G2_ST7920_128X64_F_SW_SPI lcd(U8G2_R0, LCD_CLOCK, LCD_DATA, LCD_CS);

Player mp3(&Serial1);


Encoder dial(5,6);

Atm_button dial_btn;
Atm_button a_btn;
Atm_button b_btn;

CRGBArray<NUM_LEDS> leds;
CRGBSet bottombar(leds(0,7));
CRGBSet topbar(leds(8,15));

void lcd_prepare(void) {
  lcd.setFont(u8g2_font_6x10_tf);
  lcd.setFontRefHeightExtendedText();
  lcd.setDrawColor(1);
  lcd.setFontPosTop();
  lcd.setFontDirection(0);
}


GEMProxy menu = GEMProxy(lcd, GEM_POINTER_DASH);

bool playback_state = false;
uint8_t next_song;
uint8_t current_song;
uint8_t ghue = 0;
long next_frame; 
long oldposition = -999;

void songContextEnter();
void songContextExit();
void songContextLoop();
void playSong(GEMCallbackData);

void bpm()
{
  if(playback_state) { 
  // colored stripes pulsing at a defined Beats-Per-Minute (BPM)
  uint8_t BeatsPerMinute = 64;
  CRGBPalette16 palette = RainbowColors_p;
  uint8_t beat = beatsin8( BeatsPerMinute, 16, 255);

  for( int i = 0; i <8; i++) { //9948
    topbar[i] = ColorFromPalette(palette, ghue+(i*20), beat-ghue+(i*30));
    bottombar[i] = ColorFromPalette(palette, ghue+(i*25), beat-ghue+(i*15));
  } 
  } else { 
    leds.fadeToBlackBy(64);
  }
}

song songlist[] = { 
  {"Turbo Killer", "Carpenter Brut", 209000, 144},
  {"Anarchy Road", "Carpenter Brut", 213000, 108},
  {"This FFFire", "Edgerunners OST", 224000, 144},
  {"I Really Wan..", "Edgerunners OST",  246000, 123},
  {"Clutch", "STRLGHT", 157000, 63},
  {"U Got That", "Halogen", 172000, 123},
  {"Full Bodied", "GHOST DATA",248000, 117},
  {"Projekt Melody", "GHOST DATA", 234000, 161},
  {"KNEEL", "Moxi Floxi", 192000, 129}
};


void check_playback() { 
  int busy = digitalRead(DY_BUSY);
  playback_state = !busy;
}

void progress_bar(uint8_t max, uint8_t current, uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t rounded = 0) { 
  // draws a progress bar 
  // bar is 2px inset of the W/H to look good - so 4 px smaller
  uint8_t max_length = w-4;
  uint8_t max_height = h-4;
  uint8_t mapped = map(current, 0, max, 0, max_length);
  if(rounded) { 
    lcd.drawRFrame(x,y,w,h,3);
    lcd.drawRBox(x+2,y+2,mapped, max_height, 1);
  } else { 
    lcd.drawFrame(x,y,w,h); 
    lcd.drawBox(x+2,y+2,mapped, max_height);
  }
}


GEMPageProxy menuPageMain("SONG PICKER");

void menuSetup() { 
  for(uint8_t i=0; i <ARRAY_SIZE(songlist); i++) { 
      menuPageMain.addMenuItem(new GEMItem(songlist[i].SongName, playSong, i+1));
  }
}

void clickHandler (int v, int btn) { 
  // handle the clicks, depending on context 1 = dial, 2 = A, 3 = B

  switch(btn) { 
    case 1:
    // dial
    if(!playback_state) { 
      if(v == 1) { 
        // longpress to stop
       // songContextExit();
         menu.context.exit();
      }
    }
    else { 
      if (v == 1) { 
        menu.registerKeyPress(GEM_KEY_OK);
      }
      if (v == 2) { 
        menu.registerKeyPress(GEM_KEY_CANCEL);
      }
    }
  }
}



void songContextEnter() { 
  lcd.clear();
  lcd.setFont(healzone);
  // just a demo for now!
  lcd.drawStr(-5,0,"! NOW *&*");
  lcd.drawStr(2,20,"PLAYING");
  lcd.setFont(sg02);
  lcd.drawStr(10,42, songlist[current_song].SongName);
  lcd.drawStr(10,51, songlist[current_song].Artist);
}

void songContextLoop() { 

  //Serial.println("song loop");
  if(playback_state) { 
    Serial.println("playing");
    lcd.drawDisc(120,8,8,U8G2_DRAW_ALL);
  }
  if(!playback_state) { 
    Serial.println("not playing");
    lcd.drawBox(116,4,124,12);
    //menu.context.exit();
  }


  lcd.sendBuffer();
}

void songContextExit() { 
  mp3.stop();
  menu.reInit();
  menu.drawMenu();
  menu.clearContext();
}

void playSong(GEMCallbackData data) { 
  char fname[16];
  sprintf(fname, "/%05d.MP3", data.valInt);
  current_song = (data.valInt -1);
  mp3.playSpecifiedDevicePath(Device::Sd, fname);
  // start playback animation here, with 
  menu.context.loop = songContextLoop;
  menu.context.enter = songContextEnter;
  menu.context.exit = songContextExit;
  menu.context.allowExit = false;
  menu.context.enter();
}


void setup() {
  Serial.begin(9600);
  Serial.println("coming online....");
  FastLED.addLeds<NEOPIXEL, LED_DATA_PIN>(leds, NUM_LEDS);
  FastLED.setBrightness(16);
  lcd.begin();
  lcd_prepare();
  lcd.clearBuffer();
  mp3.begin();
  delay(100);
  mp3.setVolume(20); // leave it at 20
  menuSetup();

  oldposition = dial.read();
  dial_btn.begin(ENC_BTN)
    .longPress(2,500)
    .onPress( [] (int idx, int v, int up) {
      switch(v) { 
        case 1:
          clickHandler(1, 1);
          return;
        case 2:
          songContextExit();
          return;
      }
    });

  a_btn.begin(BTN_A)
    .longPress(2,500)
    .onPress( [] (int idx, int v, int up) {
      clickHandler(v, 2);
    });

  a_btn.begin(BTN_B)
    .longPress(2,500)
    .onPress( [] (int idx, int v, int up) {
      clickHandler(v,3);
    });

  menu.setSplash(onosendai_width,onosendai_height,onosendai_bits)
      .hideVersion()
      .setMenuPageCurrent(menuPageMain)
      .init();
      menu.drawMenu();

}

void loop() {

  // do input checks! Separate function?
  long newposition = dial.read();
  automaton.run();

  if(newposition != oldposition) { 
    if(abs(newposition - oldposition) > ENC_SLOWDOWN) { 
      if(newposition > oldposition) { 
        menu.registerKeyPress(GEM_KEY_DOWN);
      } else if(newposition < oldposition) { 
        menu.registerKeyPress(GEM_KEY_UP);
      }
    }
    oldposition = newposition;
    playback_state = !digitalRead(2);
  }

  lcd.sendBuffer();
  
}

Simpler create layout way and chain operations

Inspired by m5ez and Qt, maybe any void functions can return instance for chain operations.

Before:

GEM_u8g2 menu(u8g2);

GEMPage menuPageMain("Main Menu");

int number = -512;
boolean enablePrint = false;

GEMItem menuItemInt("Number:", number);
GEMItem menuItemBool("Enable print:", enablePrint);

GEMPage menuPageSystemSettings("SYSTEM SETTINGS");
GEMItem menuItemSystemSettings("System Settings", menuPageSystemSettings);

void setup() {
  // ...
  menu.setSplash(logo_width, logo_height, logo_bits);
  menu.hideVersion();
  menu.enableCyrillic();

  menuPageSystemSettings.setParentMenuPage(menuPageMain);

  menuPageMain.addMenuItem(menuItemInt);
  menuPageMain.addMenuItem(menuItemBool);
  menuPageMain.addMenuItem(menuItemSystemSettings);

  menu.setMenuPageCurrent(menuPageMain);

  menu.init();
  // ...
}

After:

int number = -512;
boolean enablePrint = false;

GEMPage menuPageSystemSettings("SYSTEM SETTINGS")
    .setXXX(...);

GEMPage menuPageMain("Main Menu")
    .addMenuItem("Number:", number)
    .addMenuItem("Enable print:", enablePrint);
    .addMenuItem("System Settings", menuPageSystemSettings);

GEM_u8g2 menu(u8g2)
    .setSplash(logo_width, logo_height, logo_bits)
    .hideVersion()
    .enableCyrillic()
    .setMenuPageCurrent(menuPageMain);

void setup() {
  // ...
  menu.init();
  // ...
}

Scrolling item

Hello Alexander,
The last for today !
If the text of a item is too long, Automatic scroll the text to see all the information.
Exemple :
Item title : "Parameters of the motor"
item view : "Parameters of the mot"

I want view (50ms step for example):
"Parameters of the mot" --> "arameters of the moto" --> "rameters of the motor" --> ...

Redraw the menu after a button action

Hello,
I have a button with a text : “push to save”
It’s possible when the button is pressed to change the text with “save ok” and update the screen ( without use a context )
Thanks a lot for your work ! , my project use your library ( I add the float support ).

GEM_VAL_CHAR edition DEC HEXA

Howto Add a parameter to limit caractere value ?

Normal all code

DEC 0 to 9
HEXA 0 to F

bonus
TEXT a to Z

Thanks for the job !!!

JF

Не отображается значение в пункте меню на дисплее HX1230

Дисплей с контроллером HX1230 (или же STE2007, типа Nokia 1220)
ESP32-WROOM-32 (с гравировкой QR кода) на собственной плате
GEM 1.4.6
U8g2 2.34.22
Arduino IDE 2.2.1

Не могу понять, почему не отображаются значение в пунктах меню?
В названии пункта числа отображаются, а в значении - нет

Загружаю примеры с кириллицей - ничего, не с кириллицей - тоже ничего, в чём может быть причина?
Делаю список опций - не работает, вывожу просто значение с помощью GEMItem digit("Цифра", cyfra); и всё так же нет значения cyfra - int, пробовал int, byte, через GEMSelect - тоже ничего.

20231127_154257

Floating point

In a page in menus I need to set floating point numbers, my main problem can be defined this way: "after setting the number to a N digit number I can't set the number to a N+1 digit number". How can I resolve this?

Add the 32bits float support

Hello,

I use your library for a project, thanks a lot. I need to modifiy 32bits float number. I you can add this format in the library. Thanks a lot.

GEM_VAL_INTEGER/GEM_VAL_CHAR edition

Ok, I continue my suggestions ;o)

When the user enters edit mode, the cursor should be set to the lower digit. Up/down buttons should increment/decrement the digit, as it is done now, but overflow/underflow should be taken into account, and increment/decrement the left digit (and so on). Left/right buttons should select digit, as it is done now.

This way, when you are on the lower digit, you have the best resolution, but you can increment the entire value as high as you want without changing digit. And when selecting other digits, you can increment the entire value even faster (10/100/1000... times faster, depending on the digit).

This is how Agilent/HP lab instruments work, and this is very handy.

This would need to recompute the value at each key press, not only when leaving edit mode. This would be very handy, especially with rotary encoders.

Another nice feature would be to associate min/max/inc params with the item, to limit the amplitude and change it faster. Rollover or not should be an option.

menuItemNext being a wild pointer in certain circumstances

I'm working on an ESP32 project where everything GEM-related is dynamically allocated.
However LoadProhibited fatal error occurs when menu.drawMenu() is called. Turns out that pointer menuItemNext defined in GEMItem.h is wild and the issue disappears if menuItemNext is initialized with nullptr.

    GEMPage* parentPage = nullptr;  
    GEMPage* linkedPage;  
    GEMItem* menuItemNext = nullptr;  // <- Here
    void (*buttonAction)();

I wonder if this is because that all objects are dynamically allocated or just that I'm retarded (I did not dig too deep into the code).
Code can be provided if required. :)

item title for a button with a submenu too short

Hello,

I see that the title displayed for a button with a sub menu is 17 char max before trimming and can be 18 normally.
Just a remark .
I use the normal size for the menu and GEM 1.2.3

Best regards

Compilation errors with LilyGo TTGO T-Display

I'm trying to build the Example-01_Basic.ino for the LilyGo TTGO T-Display. When compiling I get a lot of errors such as the following:

~/Documents/Arduino/libraries/GEM/src/GEMItem.cpp: In constructor 'GEMItem::GEMItem(const char*, byte&, GEMSelect&, void (*)(GEMCallbackData))':
~/Documents/Arduino/libraries/GEM/src/GEMItem.cpp:96:38: error: either all initializer clauses should be designated or none of them should be
   96 |   , callbackData{ .pMenuItem = this, { 0 } }
      |                                      ^

The failing compile command is (likely) as follows:

~/Library/Arduino15/packages/esp32/tools/esp-x32/2302/bin/xtensa-esp32-elf-g++ -MMD -c @~/Library/Arduino15/packages/esp32/tools/esp32-arduino-libs/idf-release_v5.1-bd2b9390ef/esp32/flags/cpp_flags -w -Os -DF_CPU=240000000L -DARDUINO=10607 -DARDUINO_LILYGO_T_DISPLAY -DARDUINO_ARCH_ESP32 "-DARDUINO_BOARD=\"LILYGO_T_DISPLAY\"" "-DARDUINO_VARIANT=\"lilygo_t_display\"" -DARDUINO_PARTITION_default "-DARDUINO_HOST_OS=\"macosx\"" "-DARDUINO_FQBN=\"esp32:esp32:lilygo_t_display:UploadSpeed=921600,CPUFreq=240,FlashFreq=80,FlashMode=qio,FlashSize=16M,PartitionScheme=default,DebugLevel=none,PSRAM=disabled,LoopCore=1,EventsCore=1,EraseFlash=none\"" -DESP32 -DCORE_DEBUG_LEVEL=0 -DARDUINO_RUNNING_CORE=1 -DARDUINO_EVENT_RUNNING_CORE=1 -DARDUINO_USB_CDC_ON_BOOT=0 @~/Library/Arduino15/packages/esp32/tools/esp32-arduino-libs/idf-release_v5.1-bd2b9390ef/esp32/flags/defines -I~/Documents/Projects/Code/nutrient_mixer -iprefix ~/Library/Arduino15/packages/esp32/tools/esp32-arduino-libs/idf-release_v5.1-bd2b9390ef/esp32/include/ @~/Library/Arduino15/packages/esp32/tools/esp32-arduino-libs/idf-release_v5.1-bd2b9390ef/esp32/flags/includes -I~/Library/Arduino15/packages/esp32/tools/esp32-arduino-libs/idf-release_v5.1-bd2b9390ef/esp32/qio_qspi/include -I~/Library/Arduino15/packages/esp32/hardware/esp32/3.0.2/cores/esp32 -I~/Library/Arduino15/packages/esp32/hardware/esp32/3.0.2/variants/lilygo_t_display -I~/Documents/Arduino/libraries/KeyDetector/src -I~/Documents/Arduino/libraries/Ai_Esp32_Rotary_Encoder/src -I~/Documents/Arduino/libraries/Adafruit_ST7735_and_ST7789_Library -I~/Documents/Arduino/libraries/Adafruit_GFX_Library -I~/Documents/Arduino/libraries/Adafruit_BusIO -I~/Library/Arduino15/packages/esp32/hardware/esp32/3.0.2/libraries/Wire/src -I~/Library/Arduino15/packages/esp32/hardware/esp32/3.0.2/libraries/SPI/src -I~/Documents/Arduino/libraries/GEM/src -I~/Documents/Arduino/libraries/U8g2/src @/private/var/folders/mt/pp6hn_fx1j5b67vzkvxk217h0000gn/T/arduino/sketches/23D5DF54B931F69BDFF8D10FC97C386F/build_opt.h @/private/var/folders/mt/pp6hn_fx1j5b67vzkvxk217h0000gn/T/arduino/sketches/23D5DF54B931F69BDFF8D10FC97C386F/file_opts ~/Documents/Arduino/libraries/GEM/src/GEMItem.cpp -o /private/var/folders/mt/pp6hn_fx1j5b67vzkvxk217h0000gn/T/arduino/sketches/23D5DF54B931F69BDFF8D10FC97C386F/libraries/GEM/GEMItem.cpp.o

The error seems like it could be caused by the use of a different compiler or a different version of the compiler. Has anyone else had similar issues or know what could cause such errors?

"Increment" Item type

Key, @Spirik ! I'm very much enjoying GEM - thank you for putting this library together and maintaining it. It's turning out to be very easy to use vs. the other options out there.

I had a thought for a new Item type - basically, an Item where in edit mode, it increments or decrements the full value, rather than one character position at a time. This would really just be making a convenience option vs. doing it with a GEMSelect, since I think I can get the same effect with a GEMSelect - it just takes a big SelectOptionsInt[] to hold the values between min/max for the field (say, from 0 to 200).

I'm attempting to implement a menu using three buttons (basically, the Adafruit ESP32-S3 Feather Reverse TFT, with the buttons that come onboard), and an Item type like that would make the user experience a little easier for editing integers, and make it easier on the programmer to code vs. a GEMSelect option.

The basic way it could work is, in edit mode, passing GEM_KEY_UP essentially does value++ and displays it, and GEM_KEY_DOWN does value--. We'd need a way to define min/max values. Internally, it could work a lot like a GEMSelect, potentially?

The advantage here vs. a normal MenuItem is that I don't need to worry about figuring out how to go to the next character position. Right now, I'm doing a long press of the 2nd and 3rd buttons to emulate GEM_KEY_LEFT and GEM_KEY_RIGHT. With something like this, I can just do UP/DOWN and I can use key auto-repeat easily to move quickly through the values.

Use with Rotary Encoder?

Hi there,

Trying to find examples of using GEM using a single push-button rotary encoder. Do you have any examples of this?

Cheers

freezing on RP2040

Hi, I have an RP2040-Plus board (which is pin compatible with a Pi Pico).
I'm using the arduino-pico core, ssd1306 OLED, internal 2MB flash
I noticed that when entering a context all works fine, but when I try to exit the program freezes up.
I took the party hard example and changed the u8g2 declaration to
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE, /* clock=*/ 5, /* data=*/ 4); // ESP32 Thing, HW I2C with pin remapping
and the u8g2.begin() part to
u8g2.begin(/*Select/OK=*/ 26, /*Right/Next=*/ 21, /*Left/Prev=*/ 17, /*Up=*/ 19, /*Down=*/ 22, /*Home/Cancel=*/ 20);
the rest is the same
Tried to change compiler optimization flags but no success.
also without removing float edit support it won't allow me to edit all other types, just simple checkboxes

Problem with floats

Hi, thank you very much for your library. I am trying to implement it in a small project.

-I have problems setting a float in the menu.
I would like to set the boiler temperature between 85 and 96 degrees C in 0.1 degree steps
So I call it as follows:

float BoilerTemp =92.0;


void validateBoilerTemp();
GEMItem menuItemBoilerTemp("Temp degC:", BoilerTemp, validateBoilerTemp);

  menuPageSettings.addMenuItem(menuItemBoilerTemp);


void validateBoilerTemp() {
  
  // Check if mtime variable is within allowable range (i.e. 10..60)
  if (BoilerTemp < 85.0) {
    BoilerTemp = 85.0;
  }
  if (BoilerTemp > 96.0) {
    BoilerTemp = 96.0;
  }

When I go into the settings menu, the line reads "Temp degC 882.7" or after I enter the second time "Temp degC -242.0", far outside of the validated range from 85.0 to 96.0.

If I change it, sometimes it sets to 85, but as soon as I leave and reenter the menu, it's back at 882.7.

-Btw, How can I call the method setPrecision for floats? At the moment I manually set it to 1 digit in config.h, but I don't need all the floatsI want to represent only with 1 digits

Thank you very much for your help, if you need any more info, code, let me know.

Refresh GEM when not using internel key scrutation

Hi!

I'm using an I2cNavKey to navigate the menu. This system has an interrupt pin when a key changes, so I only call registerKeyPress() in this case.

But in order to GEM to refresh its loop(s), it seems that readForKey() as to be called very often. Am I right? So, can I call it even if I don't have any key binded to GEM nor u8g2? Or is there another method to call to refresh GEM internals?

Thanks,

UTF8 with u8g2

Hi Alex!

It's me again! The design and structure of GEM is truly excellent! I love it!

When I try to enable UTF8 print like the u8g2 example, but seems can't works.

https://github.com/olikraus/U8g2_Arduino/blob/dd729c5253eb85d907f0f84a1c53074bffb7a43a/examples/page_buffer/PrintUTF8/PrintUTF8.ino#L338

My codes:

GEMItem menuItemInt("数字:", number);

void setup() {
  Serial.begin(115200);

  u8g2.begin();
  u8g2.enableUTF8Print();
  // https://github.com/larryli/u8g2_wqy
  u8g2.setFont(u8g2_font_wqy12_t_gb2312);

  menu.init();
  setupMenu();
  menu.drawMenu();
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.