-
-
Notifications
You must be signed in to change notification settings - Fork 40.8k
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
Add multilayer VIA support to Hasu usb_usb #16458
Conversation
@@ -39,6 +39,66 @@ extern "C" { | |||
#include "quantum.h" | |||
} | |||
|
|||
/* see keymaps/via/keymap.c for VIA implementation details */ | |||
#ifdef VIA_ENABLE |
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.
why is there via specific implementation here?
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.
To avoid code repetition - the keyboard report parsing and matrix scan logic for the converter remains unchanged. Only the scan matrix access macros (CODE, ROW, COL) had to be altered to support multiple dynamic keymaps.
In theory it would be possible to change all of the existing layouts to use the smaller-sized scan matrix and its associated HID-to-row,col translation, but that seemed to be a larger change with no benefit to existing QMK usb_usb users.
I could easily be missing a preferable way of handling the code separation - suggestions welcomed.
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.
That doesn't really answer the question, though. Why does there need to be via specific handling of this?
VIA should be unaware of the hardware, here. The dynamic keymap feature, which via leverages changes the keymap, and that reads from the matrix config.
Eg, there is not really a good reason to have via specific code if the matrix is properly implemented, as far as I can see.
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.
I'm still not 100% sure I understand the issue, but is it that you'd prefer a different ifdef to wrap that code?
There are two scan matrices (the original, which supports translation of all 256 USB keycodes but only one layer, and the new one I've added, which supports fewer keycodes in order to allow for three layers). Both matrices are implemented correctly, and the USB-to-USB converter can support both - but you have to choose one. Since only one of the two matrices supports multiple layers, it made sense to me to put it under an ifdef so that you can make that compile-time choice. If the issue you're getting at is that using VIA_ENABLE is too specific a toggle in this hardware-specific code to make that choice (since any dynamic keymap user might want to enable it) then I could put the smaller one under some other ifdef and then enable that new ifdef only in the via keymap, which would take the VIA ifdef out of custom_matrix.cpp.
I'd like to convert this board to Custom Matrix Lite first - this change should still be doable after that, but hopefully with a little less boilerplate. |
This PR is very helpful to me for Reduce program size . |
Thank you for your contribution! |
Still active (at least as far as I'm concerned). |
Thank you for your contribution! |
Still active. |
Updated PR to reflect changes to master, and replaced VIA_ENABLE with COMPRESS_MATRIX, to better reflect that the changes to the keymap are not VIA-specific. |
… and has been retested.
The remaining CI failures are outside the scope of this PR - they're in userspace code, and are failing to compile in master. |
@jshuf In an attempt to free up as much EEPROM as possible, In my local code base, I added a keymaps/via_ansi folder which removed 34 keys in total ( F13-F24, International keys, legacy key codes ). So that makes 108 HID keycodes for a US ANSI layout, which could fit into 16x7 with 4 spare. |
Merge conflicts fixed in attached custom_matrix.cpp file. |
@bbecker-inlogik thanks for the code changes - I'll try to integrate and resubmit when I have time. There have been other QMK changes since the last review that I need to factor back into this code. In the meantime... If foo is the HID code emitted by the keyboard and received by the converter, then hidindex[matrixindex[foo]] is the HID code that the converter will send to the host. That extra level of indirection is what allows us to reduce the size of each VIA layer in EEPROM.
|
uint8_t matrix_key_count(void) { | ||
uint8_t count = 0; | ||
|
||
count += bitpop(local_keyboard_report.mods); | ||
for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) { | ||
if (IS_ANY(local_keyboard_report.keys[i])) { | ||
count++; | ||
} | ||
} | ||
return count; | ||
} | ||
|
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.
uint8_t matrix_key_count(void) { | |
uint8_t count = 0; | |
count += bitpop(local_keyboard_report.mods); | |
for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) { | |
if (IS_ANY(local_keyboard_report.keys[i])) { | |
count++; | |
} | |
} | |
return count; | |
} |
matrix_key_count()
was removed back in #16603; no need to implement it.
(The implementation is also not correct in case the same key is pressed on multiple keyboards, or if the pressed key is filtered out by the matrix compression.)
|
||
// Integrated key state of all keyboards | ||
static report_keyboard_t local_keyboard_report; | ||
|
||
static bool matrix_is_mod = false; |
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.
This variable is modified in several places, but never read — that looks wrong.
0x39, 0x04, 0x16, 0x07, 0x09, 0x0A, 0x0B, 0x0D, 0x0E, 0x0F, 0x33, 0x34, 0x32, 0x28, 0x5C, 0x5D, /* 5 */ | ||
0x5E, 0x85, 0x77, 0x7C, 0x64, 0x1D, 0x1B, 0x06, 0x19, 0x05, 0x11, 0x10, 0x36, 0x37, 0x38, 0x87, /* 6 */ | ||
0x52, 0x59, 0x5A, 0x5B, 0x67, 0x74, 0x7D, 0x8B, 0x91, 0x2C, 0x90, 0x8A, 0x88, 0x65, 0x50, 0x51, /* 7 */ | ||
0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0x4F, 0x62, 0x63, 0x58, 0x7E, 0x7B, 0x00, 0x00 /* 8 */ |
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.
Using 0x00
for unused matrix locations would break the current matrix_is_on()
implementation — it would report these locations as pressed, because the unused entries in local_keyboard_report.keys
contain 0. (For the uncompressed matrix the same problem would happen for the [0,0] location.)
One way to fix this without changing matrix_is_on()
is to use something like 0x01
here, which is not accepted by IS_ANY()
(so can't get into local_keyboard_report.keys
), but also is not 0; this won't fix the uncompressed matrix case though. Another way is to add the IS_ANY(code)
check to matrix_is_on()
; this is probably safer.
The matrix compression feature could be useful even without VIA (the current implementation uses 400 bytes for the data tables, but reduces each layer by 224 bytes, so it may be a win even starting from 2 layers, depending on the code size increase). So the implementation probably should not be coupled with One major issue is that adding an option which changes the matrix layout makes all layouts which are currently defined in
|
In any case, changes like this are rather major, and need to go to the |
Also you should think about converting the matrix to the “lite” custom matrix — even though it would have some overhead due to the debounce logic (the debounce itself could be disabled, but the |
As of August 26, 2024, As you've submitted a PR containing |
Description
Adds VIA support to the Hasu usb_usb converter. 'multilayer' comes from some additional complexity above and beyond most VIA ports - in order to fit more than one dynamic keymap layer into the atmega32u4 EEPROM, the converter's default scheme of using USB HID codes to directly index a 16x16 scan matrix is replaced with an intermediate mapping. This mapping translates from the smaller (142-code) set of USB HID codes actually used by the existing usb_usb layout macros, to cells in a smaller 9x16 scan matrix. This reduced matrix size allows three dynamic keymap layers to be stored in the atmega32u4 EEPROM. A more detailed explanation can be found in the comments in keymaps/via/keymap.c.
All code changes to support this are ifdef'd under VIA_ENABLE, and hence should have no impact on existing usage of the QMK usb_usb converter code. Because the LAYOUT macro for this VIA implementation has scan matrix dimensions that differ from the others, it lives in keymaps/via/keymap.c to avoid confusion with existing LAYOUT macros and info.json.
Types of Changes
Issues Fixed or Closed by This PR
Checklist