### Debugging the Aurora Sweep Keyboard Issue: "res" Outputs as "rse" You're experiencing an issue with your Aurora Sweep keyboard where typing the sequence "r", "e", "s" quickly results in "rse" instead of the intended "res". This problem seems tied to the interaction between custom keycodes (like `R_4` and `E_3`) and standard keycodes (like `KC_S`), especially during fast typing. Let’s break this down step-by-step based on your code and logs, identify the root cause, and propose a solution. --- #### Understanding the Problem From your logs, when you type "r", "e", "s" quickly: ``` KEY-DOWN - QMK: KC_R KEY-UP - QMK: KC_R in 9.500ms KEY-DOWN - QMK: KC_S KEY-DOWN - QMK: KC_E KEY-UP - QMK: KC_E in 42.900ms KEY-UP - QMK: KC_S in 64.900ms ``` - **Physical sequence**: You press `KC_R` (custom key `R_4`), release it after 9.5ms, press `KC_S` (standard key), then press `KC_E` (custom key `E_3`) while `KC_S` is still held, release `KC_E` after 42.9ms, and finally release `KC_S` after 64.9ms. - **Intended output**: "res" (`r` from `R_4`, `e` from `E_3`, `s` from `KC_S`), based on the order you intended: `r` first, `e` second, `s` third. - **Actual output**: "rse" (`r`, then `s`, then `e`), suggesting the key events are being sent out of order. However, the log shows `KC_S` pressed before `KC_E`, yet the output places `e` before `s`. This mismatch indicates that the issue lies not in the physical press order but in how QMK processes and sends these keycodes to the host. --- #### Analyzing the Code Your keyboard uses custom keycodes (`R_4`, `E_3`, etc.) with tap-hold functionality, where a tap sends a letter (e.g., `KC_R` for `R_4`) and a hold sends a number (e.g., `KC_4` for `R_4`). Here’s how this is handled: 1. **Custom Keycode Processing** (`process_record_user`): - **Key Press**: When a custom key like `R_4` is pressed, it sets `is_custom_key_pressed = true`, records the timer with `timer_read()`, and marks it as not tapped yet. - **Key Release**: On release, if the press duration is less than `TAPPING_TERM` (typically 200ms) and it hasn’t been marked as tapped, it sends the letter keycode: ```c register_code(custom_keys[keyIndex][0]); // e.g., KC_R wait_ms(35); unregister_code(custom_keys[keyIndex][0]); ``` The `wait_ms(35)` ensures the key is "held" for 35ms before releasing. - **Hold Check**: `matrix_scan_user` checks if the press exceeds `TAPPING_TERM`. If so, it sends the number keycode (e.g., `KC_4`) and marks it tapped. 2. **Standard Key Processing**: - Keys like `KC_S` are processed immediately by QMK’s default mechanisms, sending `KC_S` down on press and up on release without additional delays. 3. **Key Event Timing**: - For `R_4`, pressed and released in 9.5ms (less than `TAPPING_TERM`), the release triggers `KC_R` down, a 35ms delay, then `KC_R` up. - During this 35ms delay, other key events (e.g., `KC_S` down) may be detected but not processed until the delay completes, because `wait_ms(35)` blocks execution in `process_record_user`. --- #### Reconstructing the Sequence Let’s simulate the "r, e, s" sequence using your log timings: - **t=0ms**: `KC_R` down (physical press of `R_4`). - **t=9.5ms**: `KC_R` up (physical release). Since 9.5ms < `TAPPING_TERM`, `process_record_user` sends: - `KC_R` down at t=9.5ms. - Waits 35ms (blocks until t=44.5ms). - `KC_R` up at t=44.5ms. - **t=10ms** (assume `KC_S` pressed shortly after `KC_R` release, e.g., 0.5ms later): `KC_S` down is detected by the matrix scan, but `process_record_user` is still in `wait_ms(35)` for `R_4`, so it’s queued. - **t=20ms** (assume `KC_E` pressed 10ms after `KC_S`): `KC_E` down (from `E_3`) is detected, but also queued behind the `wait_ms(35)`. - **t=44.5ms**: `KC_R` up is sent, and `wait_ms(35)` ends. QMK now processes queued events: - `KC_S` down (standard key, sent immediately after queue clears, e.g., t=44.5ms+). - `KC_E` down (custom key, sets timer but doesn’t send yet). - **t=62.9ms**: `KC_E` up (42.9ms after `KC_E` down at t=20ms). Processing is delayed until after `R_4`’s `wait_ms(35)`, so the timer starts late (e.g., t=44.5ms). Elapsed time = 62.9 - 44.5 = 18.4ms < `TAPPING_TERM`, so it sends: - `KC_E` down at t=62.9ms. - Waits 35ms. - `KC_E` up at t=97.9ms. - **t=64.9ms**: `KC_S` up is sent. **Keycodes sent to the host**: - `KC_R` down (t=9.5ms) - `KC_R` up (t=44.5ms) - `KC_S` down (t=44.5ms+) - `KC_E` down (t=62.9ms) - `KC_S` up (t=64.9ms) - `KC_E` up (t=97.9ms) **Resulting output**: "rse" (`r` from `KC_R`, `s` from `KC_S` down before `KC_E` down, `e` from `KC_E`). **Problem**: You intended "res" (based on pressing `r`, then `e`, then `s`), but the log suggests you pressed `s` before `e` (`KC_S` down before `KC_E` down). However, the output "rse" matches the sent keycode order, not your intended "res". This indicates a disconnect between your typing intent and the log, or a processing delay skewing the order. --- #### Root Cause The `wait_ms(35)` in the custom keycode release handling is the culprit: - **Blocking Behavior**: In QMK, `process_record_user` is called sequentially for each key event. The `wait_ms(35)` blocks processing of subsequent events until it completes. For fast typing (e.g., `KC_R` release at 9.5ms, `KC_S` press at 10ms), `KC_S` down is delayed until after `KC_R`’s 35ms wait (t=44.5ms), skewing the timing. - **Custom vs. Standard Keys**: Custom keys (`R_4`, `E_3`) use `wait_ms(35)` to simulate a 35ms hold, while standard keys (`KC_S`) are sent immediately once processed. This mismatch causes order issues when custom and standard keys are mixed in rapid succession. - **Log vs. Sent Events**: Your log shows physical press times (e.g., `KC_R` up in 9.5ms), not the sent keycode duration (35ms due to `wait_ms`). This explains the "odd" 9ms duration—it’s physical, not logical. When you tested "f, d, s" (all standard keys: `KC_F`, `KC_D`, `KC_S`), the output was correct ("fds" repeated), because no custom keycodes or `wait_ms(35)` delays were involved. The issue is specific to custom keycodes on the top row (`R_4`, `E_3`) interacting with standard keys (`KC_S`). --- #### Solution To fix the out-of-order issue, remove the `wait_ms(35)` delay and use QMK’s `tap_code` function, which sends key down and up events without artificial delays, aligning custom key behavior with standard keys: 1. **Modify `process_record_user`**: Replace: ```c register_code(custom_keys[keyIndex][0]); wait_ms(35); unregister_code(custom_keys[keyIndex][0]); ``` With: ```c tap_code(custom_keys[keyIndex][0]); ``` **Why**: `tap_code(key)` is equivalent to `register_code(key); unregister_code(key);` without a delay, relying on QMK’s natural timing (typically a few milliseconds), which matches standard key behavior and avoids blocking. 2. **Updated Code Snippet**: ```c if (!custom_keys_tapped[keyIndex] && timer_elapsed(custom_keys_timer[keyIndex]) < TAPPING_TERM) { tap_code(custom_keys[keyIndex][0]); // Send letter keycode immediately } ``` 3. **Apply to Other Custom Keys**: Ensure `KC_MEH_SPC` and similar keys also avoid `wait_ms(35)` if possible, though your primary issue is with the top-row custom keycodes. --- #### Verification After making this change: - **Sequence "r, e, s"**: - `KC_R` press → release in 9.5ms → `tap_code(KC_R)` sends `KC_R` down and up instantly. - `KC_E` press → release → `tap_code(KC_E)` sends `KC_E` down and up. - `KC_S` press → release → sends `KC_S` down and up. - No blocking delays → events are sent in the order processed, matching your physical input (assuming `r`, then `e`, then `s`). - **Test**: Type "r, e, s" quickly and check if it outputs "res". If the log showed `KC_S` before `KC_E` due to your typing (not the code), adjust your timing or confirm your intent. - **Add Debugging**: To confirm the sent keycode order, add logs: ```c if (!custom_keys_tapped[keyIndex] && timer_elapsed(custom_keys_timer[keyIndex]) < TAPPING_TERM) { dprintf("Sending tap: %u\n", custom_keys[keyIndex][0]); tap_code(custom_keys[keyIndex][0]); } ``` For standard keys: ```c if (!is_custom_keycode) { if (record->event.pressed) { dprintf("Sending key down: %u\n", keycode); } else { dprintf("Sending key up: %u\n", keycode); } } ``` Compile with `DEBUG` enabled and check the output in a QMK console. --- #### Additional Notes - **Why `wait_ms(35)` was added**: Your code comments suggest it was to match standard key timing (~35ms) and fix prior out-of-order issues. However, it overcompensated, introducing new delays that misalign with fast typing. - **TAPPING_TERM**: If issues persist, consider lowering `TAPPING_TERM` (e.g., from 200ms to 150ms) via `get_tapping_term`, though this is secondary to removing `wait_ms`. - **Intent vs. Log**: If you meant `r`, then `e`, then `s`, but typed `r`, `s`, `e` (as the log suggests), the "rse" output is correct for the input. Clarify your typing sequence to confirm. --- #### Final Recommendation Update your firmware with `tap_code`, reflash your Aurora Sweep, and test "res" in various editors. This should resolve the out-of-order issue by eliminating the blocking delay, ensuring key events reflect your input sequence accurately. If "rse" persists, your typing may indeed be `r`, `s`, `e`—use the debug logs to verify.