Skip to content
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

feat(core): Support for 64 layers #2846

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

bitmasked-bifurcator
Copy link

@bitmasked-bifurcator bitmasked-bifurcator commented Feb 27, 2025

Ability to use more than 32 layers by switching variable type from uint32_t to uint64_t.

  • Add macro: WRITE_BIT64
  • Update layer code to use BIT64 and WRITE_BIT64
  • Tested and working on a Corne Mini with 55 layers

I am a first time contributor and I am unsure if this has any deeper implications than I realize, so I'm submitting it as a draft PR. Perhaps it will be useful if anyone else makes a layout with an absurd number of layers and wonders why it is not working.

PR check-list

  • Branch has a clean commit history
  • Additional tests are included, if changing behaviors/core code that is testable.
  • Proper Copyright + License headers added to applicable files (Generally, we stick to "The ZMK Contributors" for copyrights to help avoid churn when files get edited)
  • Pre-commit used to check formatting of files, commit messages, etc.
  • Includes any necessary documentation changes.

Ability to use for more than 32 layers by switching layer variable type from uint32_t to uint64_t.

- Add macro: WRITE_BIT64
- Update layer code to use BIT64 and WRITE_BIT64
- Tested and working on Corne Mini
@Nick-Munnich
Copy link
Contributor

I think that rather than uint64_t, the preferred approach would be to switch it to an array of uint8_t, with the array length automatically inferred from the keymap.

@joelspadin
Copy link
Collaborator

If you use sizes smaller than uint32_t, then it's probably going to get padded out to 4 byte alignment anyways, so an array of uint32_t is probably better than an array of uint8_t.

Zephyr provides a bit array structure that does this, though it also adds a spinlock, which isn't really necessary here since this all runs on the same thread. https://docs.zephyrproject.org/apidoc/latest/group__bitarray__apis.html

@joelspadin
Copy link
Collaborator

I probably wouldn't use the bitarray functions directly, since they have a bunch of extra stuff we don't need and would take up much more space than 4 extra bytes you're using here, but you could use its implementation for reference. For example, to define an array of the correct size, you might do something like

#define ZMK_LAYER_CNT (...)

#define ZMK_LAYER_BUNDLE_CNT \
    DIV_ROUND_UP(DIV_ROUND_UP(ZMK_LAYER_CNT, 8), sizeof(uint32_t))

typedef uint32_t zmk_keymap_layers_state_t[ZMK_LAYER_BUNDLE_CNT];

and then to read/write layer bits, you could write functions that divide the index by sizeof(uint32_t) * 8 to get the index of the item in the array, and the remainder of the division is the bit within that item to use with BIT() and WRITE_BIT().

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants