-
Notifications
You must be signed in to change notification settings - Fork 1.3k
keypad: support for vector and matrix key scanning #4891
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Updated by "Update PO files to match POT (msgmerge)" hook in Weblate. Translation: CircuitPython/main Translate-URL: https://hosted.weblate.org/projects/circuitpython/main/
Currently translated at 100.0% (993 of 993 strings) Translation: CircuitPython/main Translate-URL: https://hosted.weblate.org/projects/circuitpython/main/es/
Currently translated at 100.0% (993 of 993 strings) Translation: CircuitPython/main Translate-URL: https://hosted.weblate.org/projects/circuitpython/main/sv/
Currently translated at 100.0% (993 of 993 strings) Translation: CircuitPython/main Translate-URL: https://hosted.weblate.org/projects/circuitpython/main/pt_BR/
Currently translated at 100.0% (993 of 993 strings) Translation: CircuitPython/main Translate-URL: https://hosted.weblate.org/projects/circuitpython/main/zh_Latn/
keypad.Buttons and keypad.State Buttons -> Keys; further work wip wip wip: compiles about to try keypad.Keys working
keypad.Buttons and keypad.State Buttons -> Keys; further work wip wip wip: compiles about to try keypad.Keys working
…python into keypad-scanning
[EDIT: Revised API in a new comment below:]
|
154412f
to
f97e0ec
Compare
I wonder if it would make sense to make those classes follow the iterator protocol, instead of having a custom named while True:
event = matrix.next_event()
... with for event in matrix:
... and while True:
event = next(matrix)
... the latter two using the iterator protocol. |
Maybe it would also make sense to have a |
I thought about that, and would be willing to entertain it. But there might be use cases for not using an iterator. I was also thinking about future additions, including things such as:
These could be intermixed with fetching events with I have also thought about factoring out the event queue, because the function names are duplicated in each keypad implementation. So for instance: k = keypad.Keys(...)
event = k.event_queue.next()
# or even
events = k.event_queue
event = events.next()
events.clear()
next_press = events.next_pressed_key_num() This is more complicated initially, but the factoring out reduces internal code size. |
Or like |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here's my take on the APIs. I really like the new arg validation and imagine we'll want to upstream it. Thanks!
I pushed f052dc4 because the SNES controller uses a shift register (CD4021 or equivalent) with a latch pin whose sense is opposite from 74HC165, so this needs to be parameterized. |
f47ebbc
to
f052dc4
Compare
Looks like you have more to push (for more resolved items) so let me know when that is pushed. |
18dc095
to
acf90fb
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please remove pressed
and get_states_into
. They provide more than one way to use the API and that may lead to confusion. They are also timing sensitive because they do not latch. If someone wants this API, they can be derived from the event queue.
One question about overflow as well.
Thanks! It's getting close.
@tannewt Ready for re-review.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One minor thing. Looks good otherwise.
Reading through the docs in #4891 (comment) and the example a comment or two below it, this looks nice to work with and it'd probably be pretty straightforward to port KMK over to this API and (1) rip out a bunch of messy DIY code I haven't really touched in years, and (2) get the C speed boost. The only thing our matrix implementation handles that this implementation doesn't appear to have an obvious-to-me direct equivalent for is what KMK calls tl;dr 👍 |
Co-authored-by: Scott Shawcroft <[email protected]>
(Oh - is it safe to assume this would make whatever the next stable CircuitPython is after merge? We'd have to communicate a new minimum CPy version and rebase KMKPython off of that version, and we try not to rebase off of |
Definitely yes, this will go in the next 7.0.0 alpha (or maybe it will be beta) release, and will be in 7.0.0 final. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the update and your patience with my feedback!
I am looking at this as a replacement for neokey1 = NeoKey1x4(board.I2C())
key0 = Debouncer(lambda: neokey1[0]) # subscripts 0..3 access the four keys' boolean states
while True:
key0.update()
if key0.rose:
print('key 0 pressed') Polling four keys in Python in this way works but is slow and misses some key presses since it happens in the main flow of execution. Does (or will) your lib support this use case? Please feel free to correct any misunderstandings I may have. |
This is not a library per se but is native C code. So the low-level background scanning would need to do I2C transactions to read the keys. We will consider adding more native C scanners. Feel free to open an enhancement request issue. |
@dhalbert #4891 (comment) Just today I came across a use case with the NeoKey Trinkey where it would be nice to have a single lib handle events & debounce, etc. for both the switch and the cap touch, so created the issue #5014 (comment). I hope the issue meets guidelines - I'm happy to rework it if not. |
keypad
module withKeys
,KeyMatrix
, andEvent
classes. The scanning is done in the background. Key transition events (pressed or released) are put on an event queue. Direct query of a key state, bypassing the queue, is also possible. Debouncing is done by scanning once every 20 msecs.Also added a simple atomic locking mechanism that I needed, in
supervisor/shared/lock.{h,c}
.[EDIT: Revised example in a new comment below]
Sample code scanning key-per-pin using a NeoKey FeatherWing and RP2040 Feather (D5 and D6 are the default pins for the FeatherWIng):
Sample code scanning a https://www.adafruit.com/product/1824 (telephone-style matrix) on a Metro M4:
Improved version of #4877