Is there a solution for having simultaneous hitted keys be reported in the same sub report.
for now the best i get is:
00 00 00 00 00 00 00 00 <- no input
00 00 00 00 00 00 00 00
00 00 04 00 00 00 00 00 <- three keys stroked exactly at the same time
00 00 04 16 00 00 00 00 <- but interpreted as 3 report
00 00 04 16 07 00 00 00 < - ...
IIRC, it's one key per scan/report. Normally.
I think what you're lookin for is maybe this:
#define QMK_KEYS_PER_SCAN 4
Try adding that to your config.h, and see if it gets what you want.
Not better with this settings.
If i understand correctly each key generate a report, reports are buffered until computer poll ?
another question:
how to change polling rate in hid descriptors (stm32 based keyboard) ?
The host doesn't poll the keyboard, QMK only sends reports when it needs to.
It looks as though action_exec() is called immediately upon finding a changed key state, and I think somewhere down in there the actual report is sent as part of the keycode's action. So I very much doubt there is a way to send multiple keys at once.
If the STM32 boards run ChibiOS then the polling rates will be in tmk_core/protocol/usb_descriptor.c.
Hi, i've narrowed down this bug to this commit, which joins shared Endpoints together.
39bd760faf2666e91d6dc5b199f02fa3206c6acd
First let's talk about expected results.
QMK_KEYS_PER_SCAN = 4
Lets say scanrate = 300hz
Press 4 keys within 10ms
Expected result: 1 to 4 messages within a 10-15ms window.
Actual result: always 4 messages with 5-8ms gap between = 20ms window.
Scanrate = 1000hz
Press 8 keys with 10ms
Expected result: 1 to 8 messages within a 10-15ms window.
Actual result: always 8 messages with 8ms apart, for 64ms total time.
This is especially annoying in rhythm games like osu! mania,
which require you to press 6 keys simultaneously in a 20ms window. Due to the bug, it will always report the keys in 48ms, so half your keys will register fine and the other half wont, even though you are hitting all of them in a 10-20ms window of each other.
I used this program i wrote (note: it's a game that relies on having at least 1000hz frame rate):
https://github.com/alex-ong/UnityInputDelayTester/releases
Before the bug, if i mashed 8 keys, it would report them all within 10ms, usually 4-6 different timestamps. Same timestamp would mean same usb report.
After the bug, it would always report exactly 8 timestamps exactly 8ms apart.
This is even when setting polling speed to 1ms.
Note there are two bugs here:
1) seperate reports even though qmk_keys_per_scan is 4
2) reports have 8ms gap even though it should be more like 1-2ms.
For the endpoint change, you can change some of the config, and that may help:
https://docs.qmk.fm/#/config_options?id=usb-endpoint-limitations
But it may not.
Setting KEYBOARD_SHARED_EP = yes and
KEYBOARD_SHARED_EP = no didn't do anything
Is there anything else i should be looking at?
Try SHARED_EP_ENABLE = no
After the bug, it would always report exactly 8 timestamps exactly 8ms apart.
This is even when setting polling speed to 1ms.
I do not see this. When I change the polling rates in tmk_core/protocol/usb_descriptor.c I see timestamps exactly* 1ms apart (Using the same Unity test program linked above) instead of 8ms.
*#define QMK_KEYS_PER_SCAN 4 slightly changes this behavior. When set to 4, I'll see 4 key presses exactly 1ms apart, then some additional delay (+1 or 2ms) before seeing the next 4 key presses exactly 1ms apart. When set to 2 I see additional delay every 2 keys, etc.
SHARED_EP_ENABLE = no
and
KEYBOARD_SHARED_EP = no
don't appear to have any effect.
I do not see this. When I change the polling rates in
tmk_core/protocol/usb_descriptor.cI see timestamps exactly* 1ms apart (Using the same Unity test program linked above) instead of 8ms.*
#define QMK_KEYS_PER_SCAN 4slightly changes this behavior. When set to 4, I'll see 4 key presses exactly 1ms apart, then some additional delay (+1 or 2ms) before seeing the next 4 key presses exactly 1ms apart. When set to 2 I see additional delay every 2 keys, etc.
Nice; just confirming that you are using FORCE_NKRO and mashing 8+ keys?
My test cases simply latest master (with polling rate changed) and master with 39bd760faf2666e91d6dc5b199f02fa3206c6acd unpatched, on a FORCE_NKRO keyboard.
Before the bug, if i mashed 8 keys, it would report them all within 10ms, usually 4-6 different timestamps. Same timestamp would mean same usb report.
Now that i think about it, QMK sends a usb report after each key change, even if QMK_KEYS_PER_SCAN == 4, so technically what i said about two+ keys on same timestamp shouldnt be possible right?
I'll do a quick retest and see what I get...
just confirming that you are using FORCE_NKRO and mashing 8+ keys?
Yes, though I do see the same behavior without NKRO (minus not seeing all 8 keys).
This issue has been automatically marked as resolved because it has not had activity in the last 90 days. It will be closed in the next 30 days unless it is tagged properly or other activity occurs.
Dear Stale Bot, this message to let you know you're wrong.
This change https://gist.github.com/xyzz/07c7473d0739cac054cb24792bcdbb04 is a quick hack I threw together to have a single report contain multiple keys. With both
#define USB_POLLING_INTERVAL_MS 1
#define QMK_KEYS_PER_SCAN 4
slamming 3 keys 3 times before the change:
diff: 120.115000
diff: 0.831000
diff: 1.012000
diff: 118.124000
diff: 0.853000
diff: 1.101000
diff: 125.053000
diff: 0.914000
diff: 1.000000
every key is sent as its own report at 1ms intervals. After the change:
diff: 125.013000
diff: 0.024000
diff: 0.020000
diff: 121.069000
diff: 0.036000
diff: 0.008000
diff: 114.775000
diff: 0.024000
diff: 0.021000
keys are combined in reports.
Nice!
After reading the code some more, here's the simplified version:
diff --git a/tmk_core/common/action.c b/tmk_core/common/action.c
index 7fbdbd8c3..b5555757a 100644
--- a/tmk_core/common/action.c
+++ b/tmk_core/common/action.c
@@ -771,7 +771,7 @@ void register_code(uint8_t code) {
#endif
{
add_key(code);
- send_keyboard_report();
+ // send_keyboard_report();
}
}
else if
@@ -837,7 +837,7 @@ void unregister_code(uint8_t code) {
else if
IS_KEY(code) {
del_key(code);
- send_keyboard_report();
+ // send_keyboard_report();
}
else if
IS_MOD(code) {
diff --git a/tmk_core/common/keyboard.c b/tmk_core/common/keyboard.c
index 794a9152f..1f2d68c8f 100644
--- a/tmk_core/common/keyboard.c
+++ b/tmk_core/common/keyboard.c
@@ -30,6 +30,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "sendchar.h"
#include "eeconfig.h"
#include "action_layer.h"
+#include "action_util.h"
#ifdef BACKLIGHT_ENABLE
# include "backlight.h"
#endif
@@ -331,6 +332,8 @@ void keyboard_task(void) {
MATRIX_LOOP_END:
+ send_keyboard_report();
+
#ifdef DEBUG_MATRIX_SCAN_RATE
matrix_scan_perf_task();
#endif
This however will break literally everything as so many features depend on register_code and unregister_code sending the report immediately. I'm really not sure if there's a good way to implement this...
While I can get both https://gist.github.com/xyzz/07c7473d0739cac054cb24792bcdbb04 and your simplified version to work (on my board at least), with the simplified version wireshark captures a URB_INTERRUPT every 1ms whereas the first version I only see an interrupt when I press/release a key.
Not sure which is more correct or what could potentially break with this change, but I can confirm it does send multiple keys per report.
Right, you can see in the modification:
MATRIX_LOOP_END:
send_keyboard_report();
this sends a report every time the loop finishes scanning. This would also limit your scanrate to the USB_POLLING_INTERVAL_MS which is at most 1000hz, since send_keyboard_report() is blocking afaik.
While I can get both https://gist.github.com/xyzz/07c7473d0739cac054cb24792bcdbb04 and your simplified version to work (on my board at least), with the simplified version wireshark captures a URB_INTERRUPT every 1ms whereas the first version I only see an interrupt when I press/release a key.
I wish i checked this gist first, because it's exactly what i ended up implementing (send was moved to after MATRIX_LOOP_END, and i check the needs_send inside the send function).
Unfortunately as xyzz said, it breaks everything that requires modifiers etc on my board which uses very minimal feature set, but passes the multiple-keys in same report test
Most helpful comment
Dear Stale Bot, this message to let you know you're wrong.