tmk_keyboard
tmk_keyboard copied to clipboard
How to Implement This: Repeatedly Sending a Keypress While a Key is Held
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.
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);
}
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?
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
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.
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.
Yes, that wait_us()
on ChibiOS is exactly what I refer and the issue was filed now at #479. Thanks for the info.