Fix the Shift & Symbol key issue on GPIO-based keyboards#37
Open
tslmy wants to merge 2 commits into
Open
Conversation
…te + pull-ups
Symptom: Shift/Symbol chords with same-row keys (N/M/-) unreliable or dropped.
Root cause: Matrix scan drove non-active columns to LOW (push-pull) instead of
hi-Z. Two keys on the same input row but different columns created a short:
one column driven HIGH (scanning), other column driven LOW (idle), both connected
via their pressed keys to the shared row wire. The row voltage became
indeterminate, masking one or both keys.
Fix in two coordinated parts:
1. Device tree (imx28-brain.dtsi): Enable pull-up resistors on the 8 sense/row
lines (GPIO4_0..7 / ENET0 pins). Pulled-up rows idle at HIGH.
2. Driver (brain-kbd-gpio.c):
- Scan: Drive only the active column LOW; set all other columns to input mode
(hi-Z). This eliminates the short.
- Decode: Remove the leading bitwise NOT (~) to match the new active-low
polarity (pressed key pulls row LOW, reads as 0).
Result: Same-row chords now work. All keys remain fully functional.
Tested on: PW-SH3 (pwsh3) GPIO model.
…hords to work on the row where "Symbol" key sits. If we hold a chord like "Sym + N", where both keys are in the same bank, and let's say we release N but keep holding Sym. We should report N immediately, not waiting for the whole bank, because Sym is still making the bank active.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Disclaimer: I used AI heavily in this fix. I at least ensured that I understood everything it wrote.
Background
For those who came across this PR in the future, here's the context.
Symptom
As noted by Nasubi on Discord (machine-translated):
As written in this blog post:
Context
Here's the actual Brain Row 4 (called "bank 0x10" in the code), from the device tree:
Both modifiers -- Shift AND Symbol -- physically live on Row 4, together with N, M, and Minus.
Root cause
The original code drove columns like this (simplified):
And the rows were read as: pressed = HIGH. The key idea the original relied on: when you drive column c HIGH, a pressed key on column c pulls its row HIGH, so you see it.
The problem: the other columns were driven LOW the whole time. They are actively forced to ground, not disconnected.
The fix
Two coordinated changes.
Change A: idle columns go hi-Z instead of LOW
New scan:
Change B: rows get pull-ups, and we flip the polarity
If idle columns are now disconnected, nothing holds a row wire at a defined value when none of its keys is pressed. It would float. On the device, it would appear as if all keys are dead.
We need to give those wires a "default value". We do this by adding pull-up resistors to the row wires. Now:
1.0.So the logic flips to active-low:
0now means pressed. (Before, with the drive-HIGH scheme,1meant pressed.)That's why the active column is now driven LOW instead of HIGH: the pressed key needs to pull its pulled-up row down to be detected.
We had to flip the polarity because the i.MX28 has no pull-down resistors on these pins. Eviences:
The binding doc (
fsl,mxs-pinctrl.txt) says, "The configuration on the pins includes drive strength, voltage and pull-up." No "pull-downs".The constants in
mxs-pinfunc.honly has two values, and notice they describe an on/off switch, not a direction:So we can only weakly pull up, not weekly pull down. So the default value can only be "1", not "0". Thus we need to make "0" represent the "pressed" state.