-
-
Notifications
You must be signed in to change notification settings - Fork 2.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
feat(split): Transfer arbitrary tagged data from central to peripheral #2036
base: main
Are you sure you want to change the base?
Conversation
Rebased and changed the HID Indicators code to use this system too |
This should resolve #1494 for RGB and backlighting |
This has been rebased to solve the merge conflict as well as adding the ability to send keymap layer state to the peripherals for peripheral display widgets/rgb indications |
This could be expanded to include a peripheral side listener for the remaining global locality behaviours (reset, bootloader and ext power) with the intention of superceding the locality system, keen to hear other people's opinions on this idea |
1376642
to
b873b7b
Compare
Rebased after Zephyr 3.5 update, need to do some testing to confirm nothing broke |
2262731
to
0f09feb
Compare
Tested all 4 data channels and confirmed, RGB state, backlight state, HID indicators and keymap state all get successfully transmitted to the peripheral , a display widget or custom RGB underglow implementation can subscribe to the |
commit c0a3d49 Author: ReFil <[email protected]> Date: Mon Feb 12 13:44:56 2024 +0000 fix(split): Update events and init function commit f417665 Author: ReFil <[email protected]> Date: Wed Jan 10 13:39:18 2024 +0000 feat(split): Add keymap state sending commit 574ee4e Author: ReFil <[email protected]> Date: Tue Dec 19 12:23:06 2023 +0000 feat(split): Use split data transfer for hid indicators commit a7fb050 Author: ReFil <[email protected]> Date: Fri Nov 24 18:32:47 2023 +0000 feat(backlight): Use data transfer framework commit 8d953ab Author: ReFil <[email protected]> Date: Thu Nov 23 23:17:26 2023 +0000 feat(rgb): Use data transfer framework commit 5fc212f Author: ReFil <[email protected]> Date: Thu Nov 23 23:13:35 2023 +0000 fix(split): change peripheral to use work commit ef8ab95 Author: ReFil <[email protected]> Date: Tue Nov 21 11:55:45 2023 +0000 feat(split): Add data transfer event commit ff7e0b7 Author: ReFil <[email protected]> Date: Tue Nov 21 09:40:56 2023 +0000 feat(split): central to peripheral communication commit 6ed14e9 Author: ReFil <[email protected]> Date: Mon Nov 20 13:03:56 2023 +0000 feat(split): raise status changed events on central commit 2ee76be Author: German Gutierrez <[email protected]> Date: Mon May 13 23:43:35 2024 +0200 fix(soft_off): central waits 100ms in split if hold_time enabled commit f0b20c1 Author: Joel Spadin <[email protected]> Date: Fri Oct 13 13:07:55 2023 -0500 feat(boards): Add nRF52 high voltage DC/DC config Added a Kconfig option to enable SOC_DCDC_NRF52X_HV for nice_nano_v2 and mikoto. According to Nordic's documentation, the DC/DC regulator is more efficient than the LDO regulator, so this is enabled by default. The following boards do not support this mode and were not changed: - nice_nano - nice60 - nrfmicro_11, nrfmicro_13 - nrf52840_m2 - bluemicro840 I could not find schematics to confirm whether the following boards support this mode: - bt60_v1, bt60_v2 - bt65_v1 - bt75_v1 - corneish_zen_v1, corneish_zen_v2 - pillbug - puchi_ble_v1 - s40nc commit 8f5c7bb Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon Feb 26 05:52:14 2024 +0000 chore(deps): bump pre-commit/action from 3.0.0 to 3.0.1 Bumps [pre-commit/action](https://github.com/pre-commit/action) from 3.0.0 to 3.0.1. - [Release notes](https://github.com/pre-commit/action/releases) - [Commits](pre-commit/action@v3.0.0...v3.0.1) --- updated-dependencies: - dependency-name: pre-commit/action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <[email protected]> commit 7d1f84e Author: Horu <[email protected]> Date: Tue May 14 03:47:33 2024 +0700 chore: fix typos in various places commit 4dfc45d Author: ReFil <[email protected]> Date: Fri May 3 19:17:09 2024 +0100 feat(docs): Document example toggle-mode implementation --------- Co-authored-by: Cem Aksoylar <[email protected]> commit 2423136 Author: ReFil <[email protected]> Date: Fri May 3 08:22:05 2024 +0100 fix(boards): Fix pulls on ZMK uno toggle switch The devicetree pulls always add on to the extra pulls configured by toggle mode, so these should not have pulls defined in the devicetree. Saved ~200uA avg on another board with a 3t toggle switch commit af90882 Author: Peter Johanson <[email protected]> Date: Wed May 1 11:01:32 2024 -0700 fix: Initialize sideband kscan in APPLICATION. * In order to be sure the rest of the system is fully ready before intializing, because init may result in immediate events being triggered when used with toggle direct kscan inner devices. commit d1ad347 Author: German Gutierrez <[email protected]> Date: Mon Apr 29 18:22:40 2024 +0200 fix: shortening keymap_soft_off behavior node * Shorten the soft off node in order for it to work across splits. commit 0d3a4b7 Author: Jarryd Tilbrook <[email protected]> Date: Thu Apr 25 22:26:26 2024 +0800 fix(underglow): Correctly set underglow state This fixes a bug introduced in zmkfirmware#2244 commit 4d56685 Author: Pablo Martínez <[email protected]> Date: Thu Apr 25 10:55:42 2024 +0200 fix(rgb): auto-off logic commit f4a070a Author: Sadek Baroudi <[email protected]> Date: Sun Apr 21 12:37:47 2024 -0700 fix(boards): nrf boards missing SPI in pinctrl and dtsi, requiring users to manually define in their shield definitions if they wanted to use SPI commit 16e92cf Author: Peter Johanson <[email protected]> Date: Thu Apr 18 06:38:46 2024 +0000 fix(behaviors): Add multiple soft-off instances properly. * Properly pass the node id for the unique soft-off behavior instance when defining it. commit e22bc76 Author: Keeley Hoek <[email protected]> Date: Sun Apr 7 07:05:51 2024 -0400 fix(hid): Correct off-by-one buffer overflow with NKRO commit a9021de Author: Cem Aksoylar <[email protected]> Date: Tue Apr 9 10:25:33 2024 -0700 fix(docs): Add wakeup-source to split new shield example commit dfc6dc8 Author: Cem Aksoylar <[email protected]> Date: Tue Feb 27 11:50:54 2024 -0800 fix(docs): Make clear the matrix transform example is incomplete commit 7a51a46 Author: Cem Aksoylar <[email protected]> Date: Tue Feb 27 11:41:46 2024 -0800 feat(docs): Add pointer to shields folder in new shield docs commit 849eca7 Author: Xudong Zheng <[email protected]> Date: Fri Feb 23 16:59:48 2024 -0500 refactor(underglow): fix uninitialized variable warning
It has been over 3 months and it seems no review has taken place (don't see any review comments). Is something still pending? |
From my perspective it's ready for a preliminary review |
@petejohanson you were assigned. Will you be the person doing the review? |
@skewty I am not one of the maintainers, but have been involved in the project for a while and have submitted a few PRs, so here are my 2 cents... (Which are my opinions alone and do not represent the views of the project or maintainers. I could also be completely wrong about everything here adn they might disagree with it all.) The zmk maintainer team is very small, the userbase is quite big and the amount of PRs submitted is a lot. There is no way they could review everything and schedule each PR based on the time the PR has been open. I imagine they have an internal roadmap of the improvements they want to get in and not all the PRs match that roadmap. On top of that, each feature has a cost, because most of the time the original person submitting it, won't be maintaining it. Updating zephyr, the underlying RTOS, frequently requires a lot of modifications to the code base. Once a feature is merged, all of that work is dumped on the maintainers. Additionally, a lot of features are submitted by developers who are not familiar with zephyr and zmk. So many features work, but are not implemented in the correct and maintainable way. I'm not saying it's the case with this PR, but it's just one of the things that must be considered. So, considering all of this, I would recommend you learn how to maintain your own fork with all of the PRs you want to use. It's really not very difficult. Urob's guide is a great intro: That's the beauty of open source. You can be independent and include all teh features you want without relying on the maintainers prioritizing the features you want. |
LOG_DBG("Size correct, raising event"); | ||
struct zmk_split_data_xfer_event event; | ||
memcpy(&event.data_xfer, &data_xfer_payload, sizeof(struct zmk_split_data_xfer_data)); | ||
raise_zmk_split_data_xfer_event(event); |
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.
So... I think my main concern with this approach is that this introduces an extra level of indirection for consuming code on the peripheral sides. They no longer can subscribe to the specific event they want, they need to subscribe to this "grab bag" event and do two levels of checks/filtering.
I would much rather a system that uses some generic GATT bits as an internal implementation detail that allows domain specific events/data to be set and the rest of the code doesn't need to be aware of it.
Does that make sense?
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.
So the peripheral GATT handler raises the layer changed event or indicators changed event etc? I avoided that for a couple reasons:
- If someone wants to send their own data across this transport in a module they can't without modifying upstream files, unless we have the data transfer event as a backstop if the known tags don't match maybe
- We'd need to create a lot more events to handle RGB indicator state, backlight state etc
- Any alternative transports (e.g. wired) would probably need to reimplement the same sorting and individual event raising functionality, rather than just raising the same event and letting the downstream files handle it
The alternative would be having a split communication layer in between the transport's and the rest of the system on each side e.g.
System - split_central.c - (wired, Bluetooth etc etc)_central.c <-> transport <-> (wired, Bluetooth etc etc)_peripherals.c - split_peripheral.c - System
Which could pave the way for wired splits, or even having multiple different split transports available for use simultaneously, plug the trrs cable in if you're in a coffee shop or unplug it for wireless operation but that's a far more major rework than what I originally had in mind 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.
So the peripheral GATT handler raises the layer changed event or indicators changed event etc? I avoided that for a couple reasons:
That was the thinking, but you raise some interesting points, so replying below.
1. If someone wants to send their own data across this transport in a module they can't without modifying upstream files, unless we have the data transfer event as a backstop if the known tags don't match maybe
Yeah, that brings up another area of this that I have some hesitation around, but am not necessarily opposed to; I see that you added the "custom start" tag for the enum to allow third-party code to add their own data type tags. On the one hand, having such a mechanism makes sense, and yet simultaneously if this "takes off" then we'll quickly hit conflicts with features re-useing the same tag ID and then wanting to be used together.
If we want to keep going on that, I think having a layered system where we still fire the "raw" xfer event for custom tags, and for known types, fire the "native" semantic event.
2. We'd need to create a lot more events to handle RGB indicator state, backlight state etc
Is this a bad thing?
3. Any alternative transports (e.g. wired) would probably need to reimplement the same sorting and individual event raising functionality, rather than just raising the same event and letting the downstream files handle it
The alternative would be having a split communication layer in between the transport's and the rest of the system on each side e.g.
System - split_central.c - (wired, Bluetooth etc etc)_central.c <-> transport <-> (wired, Bluetooth etc etc)_peripherals.c - split_peripheral.c - System
I think if the "transport" can handle the low level bits, we can have code layered on top that does the "take a complete xfer event, and do the right thing with it". I believe that matches what you've described above.
Which could pave the way for wired splits, or even having multiple different split transports available for use simultaneously, plug the trrs cable in if you're in a coffee shop or unplug it for wireless operation but that's a far more major rework than what I originally had in mind here
I think that would be a start.
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.
Would a good path forward to be add an extra source file for a peripheral handler that captures all data transfer events and raises the appropriate events for recognised tags? Do we also want a central handler that captures events and turns that into data transfer requests.
1: I'm very keen on maintaining support for custom tags. I'll have a think on how best to avoid ID collisions, ideally some sort of compile time check but no obvious solution for this comes immediately to mind. The results of an ID collision would also be unpredictable which would lead to a challenging problem to diagnose. Good logging might help on this one.
2: no, I suppose it's not. Off the top of my head we'll need new events for backlight and underglow. For the keymap it gets a little trickier, because there's the current event for layer but not the display name, which a peripheral widget may well want to display. Should we treat the keymap information as a special case and add some extra code on the peripheral side to handle storing the keymap name or add a new event on both sides for highest layer keymap's name?
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.
[...] having multiple different split transports available for use simultaneously, plug the trrs cable in if you're in a coffee shop or unplug it for wireless operation [...]
Just wanted to add that this is probably the feature I'd want the most from wired split in ZMK (aside from it functioning).
Currently the only mechanism for data transfer for secondary features (underglow and backlighting primarily) is through the behaviour invocation process, this can only hander user initiated changes, so automatic state changes are missed and the halves state can go out of sync if the central is changed with the peripheral disconnected. Some new features currently in PR initalise a new characteristic for central-> peripheral data transfer however for infrequently updated things abstracting it away means there's not a variety of implementations in the split source files.
This introduces a new mechanism by which a data tag, size value and up to 16 bytes of data can be transferred from central to peripheral(s). I tried 32 bytes but ran into some MTU limitation. The data tags are handled in an enum and, in a similar manner to the zephyr sensor channels, additional tags can be defined separately from the current ones and passed to this system without issue. There are currently 5 tags defined, one each for underglow and backlighting, one for the upcoming HID indicators work and one for keymap state (which could be used for passing layer information to a peripheral display widget). the fifth is a marker to show the start of the unallocated ranges for custom usages. That way any future custom uses automatically get "bumped down" as new upstream uses get added seamlessly without any conflicts.
This also implements this feature for both RGB underglow and single colour backlighting for a more seamless lighting experience.