ImpulseAdventure / GUIslice

GUIslice drag & drop embedded GUI in C for touchscreen TFT on Arduino, Raspberry Pi, ARM, ESP8266 / ESP32 / M5stack using Adafruit-GFX / TFT_eSPI / UTFT / SDL
https://www.impulseadventure.com/elec/guislice-gui.html
MIT License
1.17k stars 209 forks source link

Detect a button press in a while loop #509

Closed ee-boi closed 1 year ago

ee-boi commented 1 year ago

Is there a way to detect a button press in a while loop? I don't meant the main polling loop() function, for my application I have a separate while loop running periodically to do an action, although obviously while this is going on it blocks guislice from detecting button presses or updating the display.

Is there a way to add something in to my while loops that would allow detection and display update?

Also - this is not per-se an issue with Guislice, but I also didn't know where else to reach out for help.

Thank you.

Pconti31 commented 1 year ago

@ee-boi Well, your description is rather vague but maybe you could do it like so by adding setting a global flag on each type of button clicks then testing inside your loop() function. Using ex_bld_btn_txt common callback as an example;

bool bButtonClick = false;

bool CbBtnCommon(void* pvGui,void *pvElemRef,gslc_teTouch eTouch,int16_t nX,int16_t nY)
{
  gslc_tsElemRef* pElemRef = (gslc_tsElemRef*)(pvElemRef);
  gslc_tsElem* pElem = gslc_GetElemFromRef(&m_gui,pElemRef);

  // Determine what type of event occurred on the button
  // - In this case we're just looking for the user releasing
  //   a touch over the button.  if ( eTouch == GSLC_TOUCH_UP_IN ) {
  if ( eTouch == GSLC_TOUCH_UP_IN ) {
    // From the element's ID we can determine which button was pressed.
    switch (pElem->nId) {
//<Button Enums !Start!>
      case E_ELEM_BTN_QUIT:
        // Output a message when the button is pressed
        Serial.println("Quit button pressed");
        // Set a variable flag that we can use elsewhere        m_bQuit = true;
        bButtonClick = true;
        break;
//<Button Enums !End!>
        default:
        break;
    }
  }
  return true;
}

void loop()
  if (bButtonClick) {
    //TODO add code for whatever you want
    bButtonClick = false;
  }

}

Paul--

Pconti31 commented 1 year ago

@ee-boi I should also mention that if you need all types of touches not just button callbacks it more complex. I have a general example inside my GUIsliceSolutions repository for a screen saver implementation that uses routines I put together that I called ScreenManager and guislice_touchAny() that might also be useful to you. It supports you supplying callbacks when touches happen before GUIslice sees them. Since you don't need screen saver you might need to comment out code inside ScreenManager.cpp like for example lines 92,93, and 94. Paul--

ee-boi commented 1 year ago

I do actually have a use for a screen saver (ha!) and was going to try to figure out how to implement myself, so that would also actually be very helpful to me! I will check out your repo.

Also apologies for the vagueness of my initial inquiry. What I am currently doing is running a homing routine for a stepper motor. When a button ont he touchscreen is pressed, it calls a homing function. This function has multiple while() loops in it to move the motor (using the Accelstepper library) to where a switch engages, then disengages, then calls that position home. When inside a while() loop during a movement the touchscreen is non-responsive entirely (which should be true, as a while() loop is blocking). What I was wondering is if there was something from guislice that I could put in the while() loops of the homing routine function, that would poll the screen once per loop to see if anything was touched/update the screen. This would be outside of the main loop() function.

In any case if there is not or if it is very complex to do so, I made a workaround that homes using the main polling loop() function, although I think the original while() loop variant is a better implementation. I adapted the initial homing routine from this code if you want to see what I am talking about a little more clearly (although I moved all of that code out of the main loop() into its own function).

ee-boi commented 1 year ago

I have another separate issue I was looking for clarity on, involving using flash memory for elements. (compilation failure: "looking for pgmspace.h dependency" when I turn on #define GSLC_USE_PROGMEM 1)

Better if I just ask the question here on this thread or post a separate one with a different title?

Pconti31 commented 1 year ago

@ee-boi GSLC_USE_PROGMEM issue depends upon what micro-controller you are using. If arduino uno or mega than you need GSLC_USE_PROGMEM set to 1 otherwise for most micros, likw esp32 etc... The flash is simply accessed like any other memory just defined as const so it not writable at runtime. In this case GSLC_USE_PROGMEM can be set 0 unless some library is using the PROGMEM feature in which case all of the PROGMEM features are actaully set to null implementations since again there is no difference between flash and ram except one is writable and one is not. If this doesn't make any sense to you please post what micro controller you are using, ay complier errors messages and a zip of your config file.

For your homing routine I expect you might get away with some small mods to my screen saver example. Say, by modifying the

void my_display() {
  // digitalRainAnim doesn't really loop
  // but just paints one frame then returns
  digitalRainAnim.loop();
}
and 
void my_pause() {
  digitalRainAnim.pause();
}

to check a boolean for your stepper homing or not then either calling your homing loop or the screen saver loop or reseting either of them. Just a thought.

Paul--

ee-boi commented 1 year ago

@Pconti31 appreciate the detailed responses & your work with guislice and the builder.

For the PROGMEM issue - I am using a adafruit metro M0 express board for development. When I set #define GSLC_USE_PROGMEM to 1 I get the below compiler issue (and for XKEYPAD.c.o, XGlowball.c.o, XGraph.c.o, XGauge.c.o, and XCheckbox.c.o).

Although if I interpret what you responded with correctly, it sounds like I don't need to set #define GSLC_USE_PROGMEM to 1 and can leave it at 0 for the metro m0. I only did this because when I compile it seemed like it used a lot of SRAM, when in the builder I tried to intentionally put as many static things in FLASH, and also when I looked at the .h file generated by the builder I saw the #define for MAX_ELEM_MAIN_PAGE as 0 //no Elems in Flash. Attached is the config file I made for the metro m0 express.

*** [.pio/build/adafruit_metro_m0/lib200/GUIslice/elem/XKeyPad.c.o] Error 1
.pio/libdeps/adafruit_metro_m0/GUIslice/src/elem/XKeyPad_Alpha.c:48:14: fatal error: pgmspace.h: No such file or directory

******************************************************************
* Looking for pgmspace.h dependency? Check our library registry!
*
* CLI  > platformio lib search "header:pgmspace.h"
* Web  > https://registry.platformio.org/search?q=header:pgmspace.h
*
******************************************************************

   48 |     #include <pgmspace.h>
      |              ^~~~~~~~~~~~
compilation terminated.
*** [.pio/build/adafruit_metro_m0/lib200/GUIslice/elem/XKeyPad_Alpha.c.o] Error 1
===================================================== [FAILED] Took 4.91 seconds =====================================================

ard-adagfx-ili9341-simple-m0express.zip

When I compiled, I saw this and thought it should have been using more flash...but maybe not...

Checking size .pio/build/adafruit_metro_m0/firmware.elf
Advanced Memory Usage is available via "PlatformIO Home > Project Inspect"
RAM:   [=======   ]  67.6% (used 22152 bytes from 32768 bytes)
Flash: [===       ]  34.8% (used 91180 bytes from 262144 bytes)

As for the homing function, will go through your screensaver example and see if I can adapt. Very much appreciate it, your responses, work and for guislice & the builder. Would not have even come this far without them.

Pconti31 commented 1 year ago

@ee-boi Ugh! Now that I see you are using the adafruit metro M0 express which only has 32kb ram things get a little more complicated.

If you're used to AVR, you've probably used PROGMEM to let the compiler know you'd like to put a variable or string in flash memory to save on RAM. On the ARM or SAM, its a little easier, you simply add const before the variable name:

const char str[] = "My very long string";

That string is now in FLASH. You can manipulate the string just like RAM data, the compiler will automatically read from FLASH so you don't need special progmem-knowledgeable functions.

All well and good. Now however since you are using a MCU with limited ram it isn't a bad idea to tell GUIslice to store some UI elements in flash instead of ram. These elements so marked can't be modified at runtime. Looking at guislice/examples/builder/ex04_bld_ctrls.prj a number of controls can be marked for flash while a few should not be.

Compiling my ex04 example normally using your config file with GSLC_USE_PROGMEM 0 Gives us a memory usage of: C:\Users\Paul\AppData\Local\Temp\arduino_build_633823/ex04_bld_ctrls.ino.elf : section size addr .text 57316 8192 .data 304 536870912 .bss 6040 536871216

where .text + .data is flash and .bss is ram. so here flash is 57316 + 304 = 57620. and ram is 6040

Now our problem here is that GUIslice hasn't been modified to understand that flash based PROGMEM functions are not needed to use flash on certain MCU's like yours and I'm not up to the task of modifying guislice to be smarter. Luckly there is a simple solution thanks to Hristo Gochkov who came up with a NULL version of pgmspace.h for the raspberry pi. I have attached a zip file of this version. '

pgmspace.zip

Just dump it into guislice/src folder and you should be good to go using GSLC_USE_PROGMEM 1

I went into the Builder and marked most UI elements but the ones below as flash based and also turn off callbacks for the checkboxes and radio buttons since flash can't support that feature.

Must be RAM based because they will be modified at runtime. E_ELEM_TXT_COUNT E_ELEM_TXT_SLIDER E_ELEM_BTN_QUIT

After a compile I get the following:

Flash based

C:\Users\Paul\AppData\Local\Temp\arduino_build_537013/ex04_bld_ctrls.ino.elf : section size addr .text 57780 8192 .data 304 536870912 .bss 4664 536871216

Now flash store has increased to 57780+304=58084. and ram storage decreased to 4664.

I should also point out the flash based UI elements are not heavily used so bugs may pop up...

Paul--

ee-boi commented 1 year ago

@Pconti31 very very much appreciate your support and detailed response, it also helps me to learn what is going on with the hardware/code.

Ok, so I took the pgmspace.h file in the .zip you attached and dumped it into the GUIslice/src/ directory per your instruction and changed GSLC_USE_PROGMEM to 1. I now get a strange compilation failure where it appears the compiler can't find "Adafruit_I2CDevice.h" (error posted below). The strange thing is when I remove the pgmspace.h and change back to 0 it compiles fine. I do have the "ADAfruit BUSIO" library installed with "Adafruit_I2CDevice.h" in it...hmmm...

Compilation error message:

Processing adafruit_metro_m0 (platform: atmelsam; board: adafruit_metro_m0; framework: arduino)
---------------------------------------------------------------------------------------------------------------------------------------
Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/atmelsam/adafruit_metro_m0.html
PLATFORM: Atmel SAM (8.1.0) > Adafruit Metro M0 Expresss
HARDWARE: SAMD21G18A 48MHz, 32KB RAM, 256KB Flash
DEBUG: Current (atmel-ice) External (atmel-ice, blackmagic, jlink)
PACKAGES: 
 - framework-arduino-samd-adafruit @ 1.7.10 
 - framework-cmsis @ 2.50400.181126 (5.4.0) 
 - framework-cmsis-atmel @ 1.2.2 
 - toolchain-gccarmnoneeabi @ 1.90301.200702 (9.3.1)
LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ deep, Compatibility ~ soft
Found 18 compatible libraries
Scanning dependencies...
Dependency Graph
|-- AccelStepper @ 1.64.0
|-- Adafruit GFX Library @ 1.11.5
|-- Adafruit ILI9341 @ 1.5.12
|-- GUIslice @ 0.17.0
Building in release mode
Compiling .pio/build/adafruit_metro_m0/lib790/Adafruit ILI9341/Adafruit_ILI9341.cpp.o
In file included from .pio/libdeps/adafruit_metro_m0/Adafruit ILI9341/Adafruit_ILI9341.h:39,
                 from .pio/libdeps/adafruit_metro_m0/Adafruit ILI9341/Adafruit_ILI9341.cpp:49:
.pio/libdeps/adafruit_metro_m0/Adafruit GFX Library/Adafruit_GFX.h:12:10: fatal error: Adafruit_I2CDevice.h: No such file or directory

****************************************************************************
* Looking for Adafruit_I2CDevice.h dependency? Check our library registry!
*
* CLI  > platformio lib search "header:Adafruit_I2CDevice.h"
* Web  > https://registry.platformio.org/search?q=header:Adafruit_I2CDevice.h
*
****************************************************************************

   12 | #include <Adafruit_I2CDevice.h>
      |          ^~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
Compiling .pio/build/adafruit_metro_m0/lib200/GUIslice/GUIslice_drv_adagfx.cpp.o
Compiling .pio/build/adafruit_metro_m0/lib200/GUIslice/GUIslice_drv_utft.cpp.o
Compiling .pio/build/adafruit_metro_m0/lib200/GUIslice/elem/XCheckbox.c.o
Compiling .pio/build/adafruit_metro_m0/lib200/GUIslice/elem/XGauge.c.o
Compiling .pio/build/adafruit_metro_m0/lib200/GUIslice/elem/XGlowball.c.o
In file included from .pio/libdeps/adafruit_metro_m0/GUIslice/src/GUIslice_drv_adagfx.cpp:57:
.pio/libdeps/adafruit_metro_m0/Adafruit GFX Library/Adafruit_GFX.h:12:10: fatal error: Adafruit_I2CDevice.h: No such file or directory

****************************************************************************
* Looking for Adafruit_I2CDevice.h dependency? Check our library registry!
*
* CLI  > platformio lib search "header:Adafruit_I2CDevice.h"
* Web  > https://registry.platformio.org/search?q=header:Adafruit_I2CDevice.h
*
****************************************************************************

   12 | #include <Adafruit_I2CDevice.h>
      |          ^~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
Compiling .pio/build/adafruit_metro_m0/lib200/GUIslice/elem/XGraph.c.o
*** [.pio/build/adafruit_metro_m0/lib790/Adafruit ILI9341/Adafruit_ILI9341.cpp.o] Error 1
*** [.pio/build/adafruit_metro_m0/lib200/GUIslice/GUIslice_drv_adagfx.cpp.o] Error 1
Compiling .pio/build/adafruit_metro_m0/lib200/GUIslice/elem/XKeyPad.c.o
.pio/libdeps/adafruit_metro_m0/GUIslice/src/elem/XKeyPad.c: In function 'gslc_XKeyPadTouch':
.pio/libdeps/adafruit_metro_m0/GUIslice/src/elem/XKeyPad.c:852:20: warning: unused variable 'nIndLast' [-Wunused-variable]
  852 |   int8_t nIndFirst,nIndLast;
      |                    ^~~~~~~~
.pio/libdeps/adafruit_metro_m0/GUIslice/src/elem/XKeyPad.c:852:10: warning: unused variable 'nIndFirst' [-Wunused-variable]
  852 |   int8_t nIndFirst,nIndLast;
      |          ^~~~~~~~~
.pio/libdeps/adafruit_metro_m0/GUIslice/src/elem/XKeyPad.c:851:20: warning: unused variable 'nMaxCols' [-Wunused-variable]
  851 |   uint8_t nMaxRows,nMaxCols;
      |                    ^~~~~~~~
.pio/libdeps/adafruit_metro_m0/GUIslice/src/elem/XKeyPad.c:851:11: warning: unused variable 'nMaxRows' [-Wunused-variable]
  851 |   uint8_t nMaxRows,nMaxCols;
      |           ^~~~~~~~
===================================================== [FAILED] Took 3.38 seconds =====================================================

 *  The terminal process "platformio 'run'" terminated with exit code: 1. 
 *  Terminal will be reused by tasks, press any key to close it. 
Pconti31 commented 1 year ago

@ee-boi That is odd. Could be an issue with PIO IDE not copying all of your dependences.
Your display I believe is SPI not IC2 so it shouldn't even need that file.

Check your projectname.pio\build and make sure Adafruit_BusIO and all of its contents are there. I noted that its not listed in the dependency graph you posted.

My platformio.ini has these lines:

; Default environments to load
default_envs =
    Arduino-ILI9341-STMPE610
; ---------------------------------------------------------
; Display: Adafruit/Adafruit_ILI9341

[env]
; GUIslice compilation more straightforward in "deep" LDF mode
lib_ldf_mode = deep
; To enable inspect/cppcheck w/o LTO1 error, disable LTO
build_unflags =
;   -flto

; ---------------------------------------------------------
; NOTE:
; - Need to use lib_ldf_mode=deep otherwise the Adafruit
;   libraries report "no such file" compilation errors on
;   "Adafruit_I2CDevice.h"
[disp-ILI9341]
lib_deps =
    SPI
    Wire
    adafruit/Adafruit BusIO
    adafruit/Adafruit GFX Library
    adafruit/Adafruit ILI9341
    adafruit/Adafruit STMPE610
build_flags =

Otherwise, I'm at a lost as to the problem. Paul--

ee-boi commented 1 year ago

@Pconti31 ...interesting. you are correct my touschreen uses SPI and not I2C. Although when I installed adafruit GFX library it automatically pulled in several others (BusIO, STMPE610). I checked my platform.ini file to see if it explicitly had adafruit/Adafruit BusIO and it did not. So using platformio I explicitly added it to my project and it did add it to the platformio.ini file, but compilation failed the same way when adding pgmspace.h file to GUIslice/src directory.

here is my platoform.ini file (now):

; PlatformIO Project Configuration File
;
;   Build options: build flags, source filter
;   Upload options: custom upload port, speed and extra flags
;   Library options: dependencies, extra library storages
;   Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html

[env:adafruit_metro_m0]
platform = atmelsam
board = adafruit_metro_m0
framework = arduino
lib_deps = 
    waspinator/AccelStepper@^1.64
    adafruit/Adafruit GFX Library@^1.11.5
    adafruit/Adafruit ILI9341@^1.5.12
    impulseadventure/GUIslice@^0.17.0
    adafruit/Adafruit BusIO@^1.14.1
monitor_speed = 115200
monitor_filters = send_on_enter
monitor_echo = yes
lib_ldf_mode = deep
build_unflags =

platformiolibs

Pconti31 commented 1 year ago

@ee-boi Did you Check your projectname.pio\build and make sure Adafruit_BusIO and all of its contents are there. Yes or No? I expect No, as in its not present, not that you didn't look.

I also suspect the issue is with PIO Library Dependency Python script ignoring C's preprocessor syntax that is kicking in when GSLC_USE_PROGMEM is set to 1

A simple fix should be either lib_ldf_mode = deep+ or lib_ldf_mode = chain+

If deep+ or chain+ works please post so I can add it to our FAQ. Paul--

ee-boi commented 1 year ago

@Pconti31 hmm alright this probably shows my beginner to intermediate status within this realm. I do see Adafruit_BusIO in the projectname/.pio/libdeps (as show in previous attached image). When I look in projectname/.pio/build I also see it but not sure how to verify all the contents are there? Attached is an image of what I see in the projectname/.pio/build directories.

projectname/.pio/build/adafruit_metro_m0/libc1f/Adafruit BusIO: Screenshot_20230512_121504

I will also try your other solution for "lib_ldf_mode = deep+ or lib_ldf_mode = chain+" and report back.

ee-boi commented 1 year ago

Happy to report back that changing lib_ldf_mode = deep to lib_ldf_mode = deep+ in the platformio.ini appears to have resolved the issue. This is far beyond my knowledge level of what it actually did, but it does compile now and shows less RAM usage (compare below to previous post).

Steps to reproduce:

  1. drop pgmspace.h file you attached previously into libdeps/GUIslice/src/
  2. update board config in GUIslice/configs to #define GSLC_USE_PROGMEM 1 (from 0)
  3. explicitly install Adafruit BusIO library via platformio
  4. update platformio.ini file from lib_ldf_mode = deep to lib_ldf_mode = deep+ (I also tried chain+ and it seemed to compile as well

RAM usage dropped from ~68% to 48% for my project, interestingly though the Flash usage did not change and is still at 34.8%...not sure if this is an issue. I would try flashing it to the board but I fried it last night (whoops) and am waiting for a new one to arrive.

 *  Executing task in folder GUIslice_PIO_Test: platformio run 

Processing adafruit_metro_m0 (platform: atmelsam; board: adafruit_metro_m0; framework: arduino)
-------------------------------------------------------------------------------------------------------------------------
Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/atmelsam/adafruit_metro_m0.html
PLATFORM: Atmel SAM (8.1.0) > Adafruit Metro M0 Expresss
HARDWARE: SAMD21G18A 48MHz, 32KB RAM, 256KB Flash
DEBUG: Current (atmel-ice) External (atmel-ice, blackmagic, jlink)
PACKAGES: 
 - framework-arduino-samd-adafruit @ 1.7.10 
 - framework-cmsis @ 2.50400.181126 (5.4.0) 
 - framework-cmsis-atmel @ 1.2.2 
 - toolchain-gccarmnoneeabi @ 1.90301.200702 (9.3.1)
LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ deep, Compatibility ~ soft
Found 18 compatible libraries
Scanning dependencies...
Dependency Graph
|-- AccelStepper @ 1.64.0
|-- Adafruit GFX Library @ 1.11.5
|-- Adafruit ILI9341 @ 1.5.12
|-- GUIslice @ 0.17.0
Building in release mode
Checking size .pio/build/adafruit_metro_m0/firmware.elf
Advanced Memory Usage is available via "PlatformIO Home > Project Inspect"
RAM:   [=====     ]  48.1% (used 15752 bytes from 32768 bytes)
Flash: [===       ]  34.8% (used 91144 bytes from 262144 bytes)
============================================== [SUCCESS] Took 2.60 seconds ==============================================
 *  Terminal will be reused by tasks, press any key to close it.
Pconti31 commented 1 year ago

@ee-boi Congratulations! I'll add this info to the FAQ. As for the flash it did change it went from 91180 to 91144, That is weird.

Maybe try using arm-none-eabi-size -A .pio/build/adafruit_metro_m0/firmware.elf Although finding the arm-none-eabi-size utility may be challenging on your system. Remember if you do this that flash will be .text + .data

You can close this now. I can't since I only have access to my repository GUIsliceBuilder. Paul--

ee-boi commented 1 year ago

Confirmed this works, got my new dev board in and compiled an uploaded fine. So far no bugs.

Closing. Appreciate all the help @Pconti31 !!!! You are awesome, and I hope GUIslice continues to grow, as it is one of the most useful things I have come across in my short time developing.