[Logo] TCC discussion forum
  [Search] Search   [Recent Topics] Recent Topics   [Hottest Topics] Hottest Topics   [Top Downloads] Top Downloads   [Groups] Back to home page 
[Register] Register /  [Login] Login 


This forum is read only and new users cannot register, please ask all new questions either using GitHub discussions, or in Arduino forum tagging @davetcc.

render.setResetCallback only works once (trying to implement a screensaver) RSS feed
Forum Index » tcMenu Arduinio library
Author Message
Mr.Robot


Joined: Sep 3, 2021
Messages: 8
Offline
Hi,

I have a question regarding renderer.setResetCallback. I want to use it in order to implement some kind of inactivity splash screen (like a screensaver). So, whenever the user is not pushing a button for a pre specified time, I want the splash screen to appear. Once a button is pressed, the plash screen shall disappear and the inactivity timer / counter shall be restarted. My problem is that the first appearance of the splash screen works fine as well as letting it disappear by a press of a button. The thing is, it never reappears in case the user is inactive subsequently. I am probably misunderstanding the logic behind the render reset and giveBackDisplay. Can you give me hint what I am doing wrong?

Here is my code.

In setup() of main.cpp

// register screensaver
  renderer.setResetIntervalTimeSeconds(SCREENSAVER_START_INTERVAL);
  renderer.setResetCallback([] {
    renderer.takeOverDisplay(Screen::screenSaverCallback);
  });


and the code of the callback method (within the Screen class):

int Screen::takeOverMenuCounter = 0;

void Screen::screenSaverCallback(unsigned int encoderValue, RenderPressMode clicked) {
  // in case this is the first call to the function, display the screensaver splash screen
  if (Screen::takeOverMenuCounter == 0)
    showScreenSaver();

  // in case the A button was pressed, give control back to tcmenu and restart the screensaver intervall timer
  if(clicked) {
    renderer.giveBackDisplay();
    Screen::takeOverMenuCounter = 0;
    renderer.setResetIntervalTimeSeconds(SCREENSAVER_START_INTERVAL);
    renderer.setResetCallback([] {
        renderer.takeOverDisplay(Screen::screenSaverCallback);
    });
  }

  Screen::takeOverMenuCounter++;
}

/*
 * Displays a splash screen as screensaver. Image is loaded from SPIFFS as bmp
 */ 
void Screen::showScreenSaver() {
  gfx.fillScreen(ST77XX_BLACK);
  gfx.setTextColor(ST77XX_BLACK);
  SPIFFS_ImageReader reader;
  reader.drawBMP("/system/splashscreen.bmp",gfx,0,0);
  gfx.setCursor(30, 225);
  gfx.println("<press A to continue>");
}


I also tried the same code without re-setting the timer interval within the callback (line 12) - unfortunately with the same result.

As background info (but probably doesn't matter):
I am using tcmenu on an ESP32 with an ST7789 attached to it.


---
Offtopic:
Since this is my first post some additional words. TcMenu really rocks! It takes a bit to figure out all of its functionality but it is really a time saver in order to implement nice menus. Thanks a lot for having written TcMenu in the first place and maintaining it with high quality documentation!
davetcc


Joined: Jan 19, 2019
Messages: 686
Offline
Thanks for the feedback BTW, always good to know how it's used.

When you give the display back you shouldn't need to register the reset callback, the callback remains active until it's replaced again.

This seems like it's maybe an edge case bug, where the countdown doesn't restart until something is edited. Let me test it myself later today and feedback. If it is a bug, it should be trivial to fix, and can probably go into the 2.2 release BETA that's due imminently.
davetcc


Joined: Jan 19, 2019
Messages: 686
Offline
I've actually tried this locally with the takeOverDisplay example and cannot recreate. It goes to screen saver and then back repeatedly just by clicking to exit the screensaver.

I recommend that you remove the setResetIntervalTimeSeconds and setResetCallback from the if(clicked) block. It is not needed as the values are persistent once set.

I'll try it later on a few other boards, to ensure it's not specific to a board, as I'm doing some testing anyway.
Mr.Robot


Joined: Sep 3, 2021
Messages: 8
Offline
Thank you for your feedback!

I removed setResetIntervalTimeSeconds and setResetCallback from the if(clicked block) as you suggested. Running the code again, it seems that the callback is never called again.

Well, it only seems. After debugging a bit further I owe you an apology. Nothing wrong with your code. The callback is called again. My counter, however, issn't rest to 0 - which is why the splash screen isn't shown again. I have takeOverMenuCounter = 0 in my if(clicked) block but it seems that I am messing something up with all the static functions and variables.

So, sorry for bothering you and thanks for looking into it anyway!

---

Follow up question: Does anyone know a good site / tutorial which gives me some insight on how to use static methods & variables of a class properly? Any suggestions how to fix my code are, of course, welcome as well. smilie

EDIT (a few minutes later):

Well, here we go. Its facepalm time. smilie

image



Have a look at my code and closely watch the takeOverMenuCounter:

void Screen::screenSaverCallback(unsigned int encoderValue, RenderPressMode clicked) {
  // in case this is the first call to the function, display the screensaver splash screen
  if (takeOverMenuCounter == 0)
    showScreenSaver();

  // in case the A button was pressed, give control back to tcmenu and restart the screensaver intervall timer
  if(clicked) {
    renderer.giveBackDisplay();
    takeOverMenuCounter = 0;
  }

  takeOverMenuCounter++;
}


Did you notice that I increase it imidiatly after it is set to zero? That means, whenever the callback is called a second time, the counter is already at 1. Hence the splash screen not appearing again. Here ist the correct code (in case someone is looking for a similar functionality) and it is working like a charm:

void Screen::screenSaverCallback(unsigned int encoderValue, RenderPressMode clicked) {
  // in case this is the first call to the function, display the screensaver splash screen
  if (takeOverMenuCounter == 0) {
    showScreenSaver();
    takeOverMenuCounter++;
  }

  // in case the A button was pressed, give control back to tcmenu
  if(clicked) {
    takeOverMenuCounter = 0;
    renderer.giveBackDisplay();
   } 
}

davetcc


Joined: Jan 19, 2019
Messages: 686
Offline
Great that you found it.

To avoid trying to determine if you are starting up you can use the OO CustomDrawing class:

https://www.thecoderscorner.com/products/arduino-libraries/tc-menu/renderer-take-over-display/#object-oriented-approach-to-display-management

https://www.thecoderscorner.com/ref-docs/tcmenu/html/class_custom_drawing.html

EDIT Side note: Actually, I've tried it now on wide range of boards, and I was also able to find one board / example where the take-over display didn't appear to work properly (MKR example). I'll investigate, it could be completely unrelated. This was actually a problem between the user and the keyboard. I had not added the reset handler!
 
Forum Index » tcMenu Arduinio library
Go to:   
Mobile view
Powered by JForum 2.7.0 © 2020 JForum Team • Maintained by Andowson Chang and Ulf Dittmer

This site uses cookies to analyse traffic, serve ads by Google AdSense (non-personalized in EEA/UK), and to record consent. We also embed Twitter, Youtube and Disqus content on some pages, these companies have their own privacy policies.

Our privacy policy applies to all pages on our site

Should you need further guidance on how to proceed: External link for information about cookie management.