Hey there Alan :-)

Very cool and useful idea! I did something like this long time ago in
pure assembly and C but it was returning press time and based on that
actions were performed by the handling routine.

In NuttX this would work on various platforms where different
capabilities (i.e. irq, timers, etc) may be used for hardware
acceleration, but I think generic approach based on system timer that
would work on everything could be the first step :-)

Good self-explanatory name for such module would be nice to have, what
do you think about "Single Button Actions" or similar? Singe Button
tells only one button is used to perform various Actions.

Thanks :-)
Tomek


On Wed, Jul 9, 2025 at 3:17 PM Alan C. Assis <acas...@gmail.com> wrote:
>
> Hi Everyone,
>
> Some years ago a customer asked me to develop a project with NuttX for this
> board that used a small OLED display and a single button.
> That button should be used to navigate in the menu, as a side note:
> initially he suggested: quick press and release will work as a ENTER and
> long press will work as TAB (move to other option),
> but while testing the application I released the was faster if quick press
> work as TAB and long press as enter.
>
> This video implements the same idea on a ESP32-Devkit board that also has
> only a single button: https://www.youtube.com/shorts/vfQLW-a2JhA
>
> The daemon that detect the button and define the type of input is something
> like this:
>
>   /* Define the notifications events */
>
>   btnevents.bn_press   = supported;
>   btnevents.bn_release = supported;
>
>   btnevents.bn_event.sigev_notify = SIGEV_SIGNAL;
>   btnevents.bn_event.sigev_signo  = CONFIG_INPUT_BUTTONS_SIGNO;
>
>   /* Register to receive a signal when buttons are pressed/released */
>
>   ret = ioctl(fd, BTNIOC_REGISTER,
>               (unsigned long)((uintptr_t)&btnevents));
>   if (ret < 0)
>     {
>       int errcode = errno;
>       printf("button_daemon: ERROR: ioctl(BTNIOC_SUPPORTED) failed: %d\n",
>              errcode);
>       goto errout_with_fd;
>     }
>
>   /* Ignore the default signal action */
>
>   signal(CONFIG_INPUT_BUTTONS_SIGNO, SIG_IGN);
>
>   /* Now loop forever, waiting BUTTONs events */
>
>   for (; ; )
>     {
>       struct siginfo value;
>       sigset_t set;
>
>       bool timeout;
>       int nbytes;
>
>       /* Wait for a signal */
>
>       sigemptyset(&set);
>       sigaddset(&set, CONFIG_INPUT_BUTTONS_SIGNO);
>       ret = sigwaitinfo(&set, &value);
>       if (ret < 0)
>         {
>           int errcode = errno;
>           printf("ERROR: sigwaitinfo() failed: %d\n", errcode);
>           goto errout_with_fd;
>         }
>
>       sample = (btn_buttonset_t)value.si_value.sival_int;
>
>       if (sample & 0x01)
>         {
>           /* Button pressed, start measuring time */
>
>           clock_gettime(CLOCK_REALTIME, &start);
>         }
>       else
>         {
>           /* Button released, calculate the elapsed time */
>
>           clock_gettime(CLOCK_REALTIME, &curr);
>
>           elapsed.tv_sec  = curr.tv_sec - start.tv_sec;
>           if (curr.tv_nsec >= start.tv_nsec)
>             {
>               elapsed.tv_nsec = curr.tv_nsec - start.tv_nsec;
>             }
>           else
>             {
>               unsigned long borrow = 1000000000 - start.tv_nsec;
>               elapsed.tv_sec--;
>               elapsed.tv_nsec = curr.tv_nsec + borrow;
>             }
>
>  unsigned long ftime = (elapsed.tv_sec * 1000000000) + elapsed.tv_nsec;
>
>  /*printf("Elapsed miliseconds = %d\n", ftime / 1000000);*/
>  if (ftime < 500000000)
>             {
>               input_event(INPUT_TAB);
>             }
>  else
>             {
>               input_event(INPUT_ENTER);
>             }
>         }
>
>       /* Make sure that everything is displayed */
>
>       fflush(stdout);
>
>       usleep(1000);
>     }
>
> But today while taking a shower and thinking about other subjects that fact
> came to mind and I asked myself: how to develop that thing in a more
> standard way to avoid the "kludge" above? (in fact it is not kludge, but we
> can improve, right?)
>
> So, I realized it would be nice to have a kind of "action button" driver
> that generates this kind of event (detecting long press and short press)
> automatically returning INPUT_ENTER or INPUT_TAB.
>
> In fact the driver will be more similar to djoystick.c than the ordinary
> buttons driver itself (for simplicity).
>
> Please let me know if someone already implemented something similar or
> other suggestions before I implement it.
>
> BR,
>
> Alan



-- 
CeDeROM, SQ7MHZ, http://www.tomek.cedro.info

Reply via email to