Button press debounce on wake

Posted on
  • I'm aware of debounce within in the setWatch function, and its default value of 25 for buttons. However, in the source code in function

    void btnHandlerCommon(int button, bool state, IOEventFlags flags)

    It doesn't propagate the button press event if its waking up the display and it includes code to catch the keyUp/release, to not propagate. Considering the nature of keyUps and KeyDowns that i've witnessed with debounce set to 0, is it not true that there will be instances where key events ARE propagated because of the debounce issue when a button is pressed to wake from LCDOff state?

    I'm saying all this because I think i am noticing some sort of inconsistencies with whether my app processes the key press from wake or not. Eg. PizzaTimer app, if i set a long timer (eg. 1 hour) then half way through it press the middle button, it seems to stop the timer at some point.

    Another example of inconsistency can be observed in the 'launch' app menu. If i go into that menu, allow the screen to turn off/timeout and then press 'down'/BTN3, the menu will have gone down one entry, but if you try it again, it doesn't do that behaviour. You have to relaunch the 'lauch'/launcher app and repeat, to see it again.

    Just curious. (For the time being I make sure I press BTN1 not BTN2 when waking my watch during a long timer with 'PizzaTimer' App)

    EDIT:: I can recreate it, its not related to 'time' .. its related to how fast I press the button mb. When i press it fast in and fast out, it sometimes propagates to the app.

    Conclusion: I think the LCDTimeout wake feature should properly 'consume' key presses, handling any issues with debounce, so that the behaviour is consistent.

  • is it not true that there will be instances where key events ARE propagated because of the debounce issue when a button is pressed to wake from LCDOff state?

    That's true... So yes, this could cause an issue. I guess the cheap fix would be to suspend transferring of other button presses until 25ms after the button is pressed?

  • I tested it a bit further.

     (function() {
      clearWatch();
      setWatch(() => {
        console.log("Rising/Pressed...");
      },BTN1,{repeat:true,edge:'rising',deboun­ce: 0});
      setWatch(() => {
        console.log("Falling/Released...");
      },BTN1,{repeat:true,edge:'falling',debou­nce: 0});
    })();
    
    
    Rising/Pressed...
    Rising/Pressed...
    Falling/Released...
    

    This is the output that seems to cause the issue. So imagine these sequence of events are handled by the firmware. The second time of 'pressed' :

    line 685 jswrap_bangle.c

    if (!lcdPowerOn && state) {
            bangleTasks |= JSBT_LCD_ON;
            lcdWakeButton = button;
            return; // don't push button event if the LCD is off
          }
    

    It won't return here, because lcdPowerOn is already On? So then it propagates this '2nd' press.

    line 1614 jswrap_bangle.c:

    if (bangleTasks & JSBT_LCD_ON) jswrap_banglejs_setLCDPower(1);
    

    which is part of function : jswrap_banglejs_idle
    which translates to : jswIdle() in line 2155 of jsinteractive.c

    So if the sequence is press -> press -> release or rising -> rising -> falling, I'm arguing that the second rising does get propagated because the function can't return because the lcdPowerOn variable is true. Its just a theory that seems probable.

    Temporary solution could be to move the screen turning on 'action' , to the keyUp event instead of KeyDown. This way the lcdPowerOn will not be true and those keyDowns can be properly consumed/blocked from propagating.

  • That's true... So yes, this could cause an issue. I guess the cheap
    fix would be to suspend transferring of other button presses until
    25ms after the button is pressed?

    That would work too. So the moment it receives 'rising' or 'state=true' to that handler, it must not propagate ( should consume/return from function ) all future signals until 25 ms has past. Including future falling signals and including future rising signals.

  • move the screen turning on 'action' , to the keyUp event

    To be fair, buttons can easily bounce more than once - so even that might not stop it (although I'm sure it'd be better).

  • Ye i know what you mean, its just that i saw a pattern of recurring. In the real world there might be a slight chance it breaks that pattern and does some other weird behaviour so your solution seems more 'official'

  • Would it better if I make an issue on the github espruino, to ensure this doesn't get buried? Also, if you are super busy and can't get this done, I could attempt a pull request if you'd like, up to you.

  • Just committed a fix for this. Although in future yes, it might be better to have this sort of thing as a GitHub issue

  • I have a similar problem on the Bangle.js 2:

    I am creating a special countdown app fot football referees. So the button has to start / stop the stopwatch. But right now I have to press the button twice (wake up the watch and then start the clock). Can this be done in one step? Or what would be best practice in this case?

  • If you want this, best bet is just not to let the screen lock. Bangle.setLCDTimeout(0);Bangle.setLocked­(0). If you don't want the backlight on you can set the brightness to 0

  • Maybe just disable locking in your app?
    Perhaps a Bangle.setLockTimeout like Bangle.setLCDTimeout would be useful?

    Right now you could do:
    Bangle.on("lock", (state) => {if (state) Bangle.setLocked(false);});

  • Thank you.

    Really LCD and LockScreen both prevent the button from executing it's 'primary' event?

    I hope the battery will last with this settings for a game or a tournament. I will give it a try this evening.

    Will these settings be restored after the user is exiting the app to his preferences?

  • Really LCD and LockScreen both prevent the button from executing it's 'primary' event?

    Just the screen lock. Actually try setOptions: http://www.espruino.com/Reference#l_Bang­le_setOptions

    Bangle.setOptions({lockTimeout:0})

    So you can set locking independent of the LCD.

    Will these settings be restored after the user is exiting the app to his preferences?

    Yes.

  • So you can set locking independent of the LCD.

    Oh, that is much easier. Somehow I assumed that Bangle.setOptions would actually write the new settings like the Settings app does.

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

Button press debounce on wake

Posted by Avatar for d3nd3-o0 @d3nd3-o0

Actions