tmk_keyboard icon indicating copy to clipboard operation
tmk_keyboard copied to clipboard

How to Implement This: Repeatedly Sending a Keypress While a Key is Held

Open thomas-profitt opened this issue 7 years ago • 6 comments

This is a request for help.

I'm building a gamepad, and I'd like to implement an "auto fire" layer, on which keypresses are repeatedly sent, very quickly, as long as the key is held.

What are some ways in which this could be implemented? Are there any existing implementations out there? If not specifically of "auto fire", of "run x arbitrary code repeatedly while this key is held", or "repeatedly execute this macro while this key is held"? Are there caveats I should be aware of?

Any guidance is appreciated.

thomas-profitt avatar Jun 14 '17 01:06 thomas-profitt

I think you would be happier with using other existent firmware for gamepad or writing it yourself. This keyboard firmware won't be very useful to make gamepad, unfortunately no function like autofire or something.

That being said, I think it is possible to implement it by writing some amount of codes, using timer interrupt would be needed. The code looks like kind of this.

static bool auto_fire = false;

void action_function(keyrecord_t *record, uint8_t id, uint8_t opt)
{
    switch (id) {
        case AUTO_FIRE:
            if (record->event.pressed) {
                auto_fire = true;
            } else {
                auto_fire = false;
            }
            break;
    }       
}               
            
// called every XXms
ISR(TIMER_blah_blah)
{
    static bool press = false;

    if (!auto_fire) return;
    if (toggle)
        register_code(KC_SPACE);
    else
        unregister_code(KC_SPACE);
} 

tmk avatar Jun 14 '17 02:06 tmk

Thanks! I think I'm on the right track now.

I'll add another comment once I have this implemented, for any future Googlers.

ISR() isn't working for me, though. I'm using a Teensy LC and ChibiOS. Do I just need to pass the right timer to this ISR() call, do I need a different implementation of an ISR, or do I need to use an abstracted software timer in ChibiOS for this, something like this? Where can I go to get enough information to make sense of this?

thomas-profitt avatar Jun 14 '17 17:06 thomas-profitt

I guess you need your own timer handler instead of ChibiOS timers. I think ChibiOS(and other RTOSs?) doesn't provide good resolution in timer related API for your requirement. But trying those ChibiOS timers first before making your own timer handler would be good idea. I don't know much about ChibiOS and Cortex-Ms, to be honest.

With gcc-arm to define interrupt handler you will need to use other gcc attribute then AVR's ISR(). https://gcc.gnu.org/onlinedocs/gcc/ARM-Function-Attributes.html

tmk avatar Jun 15 '17 03:06 tmk

It seems like I had wrong memory on ChibiOS timers. I think tens of milliseconds resolution is enough for your auto fire, in this case it will work well. I had problem when I need to tens of microseconds wait with ChibiOS but this won't bother you.

I think you can go with ChibiOS timer functions.

tmk avatar Jun 15 '17 03:06 tmk

Yeah. That's what it looked like to me, too.

Tens-of-milliseconds resolution is just fine; measuring how quickly I can tap a key, I only got upto about 10/sec., so the bar for "human tapping key" is very low.

In fact, "as slow as a human" might be ideal. With multiple fingers and multiple keys, I'm able to tap fast enough to choke up whatever is used to by my terminal emulator to read input (on GNOME w/ Wayland, so libinput I guess?), so tapping way quicker than a human is probably something that some software won't handle anyway.

Still stumbling through implementation of ChibiOS' timers, event handling and such as time, not-so-great ChibiOS documentation, and a very limited knowledge of C and C idioms, allows me. Go, Github code search!

I think I know the problems you're talking about, with the low-resolution delays in ChibiOS; I've read about some of that here, and I've seen di0ib's tmk_keyboard fork hack around the "round microseconds upto the nearest millisecond" behavior here (gruesome!), which he's written about here. I don't know if that's still a problem in tmk_keyboard with ChibiOS; if it is, I think I have enough information now to fix it and submit a PR.

thomas-profitt avatar Jun 15 '17 16:06 thomas-profitt

Yes, that wait_us() on ChibiOS is exactly what I refer and the issue was filed now at #479. Thanks for the info.

tmk avatar Jun 15 '17 22:06 tmk