-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
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 wired split support using UART communication #1117
base: main
Are you sure you want to change the base?
Conversation
9072f10
to
a92c968
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.
First pass w/ some initial questions. Thanks for the work on this!
# ZMK_BLE | ||
endif | ||
|
||
if ZMK_USB |
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 not sure this really needs to be behind this condition, TBH.
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.
Do you mean we can remove this check ?
I added this check for cases where we have controllers with chips without having USB peripheral like nrf52832 chip.
If we are making an assumption that we support only USB controllers, we can remove this.
Let me know if i mis-understood the question
@@ -1,19 +1,41 @@ | |||
# Copyright (c) 2021 The ZMK Contributors | |||
# SPDX-License-Identifier: MIT | |||
|
|||
if SHIELD_A_DUX_LEFT || SHIELD_A_DUX_RIGHT | |||
|
|||
if ZMK_BLE || ZMK_USB |
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 isn't this just defaulted on? Why behind this check?
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.
Yes, does not makes much sense. No idea why i added this.
Will remove this check.
status = "okay"; | ||
}; | ||
|
||
&kscan0 { |
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 would the pins for a kscan device need overriding for just one board?
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.
Existing split keyboards use any one of four ports D0, D1, D2 and D3 for split communication
Ex: Lily58 uses D2 (promicro RX pin), A_Dux uses D1 (I2C SDA pin) etc
STM32 chips support half duplex UART comm only on TX pins.
So STeMCell has jumpers on back side to swap the TX/RX pins.
This depends completely on the shield which uses the pin for communication.
Other way is to use some KConfig variable to detect and swap pins.
But i have not figured out how to do it exactly using Kconfig and device tree yet,
So in the meantime, i have just juggling the pins inside the shields directly.
@@ -141,12 +142,12 @@ int send_position_state() { | |||
return 0; | |||
} | |||
|
|||
int zmk_split_bt_position_pressed(uint8_t position) { | |||
int zmk_split_position_pressed(uint8_t position) { |
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.
It this is common, it shouldn't, IMHO, be duplicated for both, but should really be a reusable common core that then delegates to the transport to send the state.
app/src/split/serial/central.c
Outdated
#include <zmk/events/position_state_changed.h> | ||
#include <zmk/matrix.h> | ||
|
||
#if DT_HAS_CHOSEN(zmk_split_serial) |
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.
If we don't have a chosen, we should just #error
instead of wrapping this all in a conditional.
app/src/split/serial/central.c
Outdated
#define CONFIG_ZMK_SPLIT_SERIAL_CENTRAL_POSITION_QUEUE_SIZE 5 | ||
|
||
#define CONFIG_SERIAL_THREAD_STACK_SIZE 128 | ||
#define CONFIG_SERIAL_THREAD_PRIORITY 5 |
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 not actual Kconfig settings?
app/src/split/serial/central.c
Outdated
uart_ready = 1; | ||
LOG_DBG("UART device:%s ready", serial_dev->name); | ||
|
||
while(true) { |
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.
Do we really need to hard loop here? Can't we just enable the RX here, and then in the notify callback, do more? Not familiar w/ the UART API in detail, but this seems off.
app/src/split/serial/service.c
Outdated
|
||
#include <zmk/matrix.h> | ||
|
||
#if DT_HAS_CHOSEN(zmk_split_serial) |
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.
Ditto, should #error
if no chosen node, not wrap all this in the #if
.
app/src/split/serial/service.c
Outdated
} | ||
|
||
for (int i=0; i < len; i++) { | ||
uart_poll_out(serial_dev, data[i]); |
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 not uart_tx
for the whole buffer?
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 have done the TX and RX part first using sync mode and then updated RX to async using DMA.
Will update TX also to use same apis
remote: megamind4089 | ||
revision: v2.5.0+zmk-fixes-stm32f4 |
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.
Anything here actually relevant to this work that this is needed?
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.
No, please ignore this file. Will remove this before final cleanup.
Just added here to show that i had to cherry-pick this PR to make it work in half duplex mode.
zephyrproject-rtos/zephyr#40525
71bbdc9
to
8c8be22
Compare
1b27605
to
5a8744f
Compare
@@ -45,7 +45,7 @@ target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/events/battery_state_changed | |||
target_sources_ifdef(CONFIG_USB app PRIVATE src/events/usb_conn_state_changed.c) | |||
target_sources(app PRIVATE src/behaviors/behavior_reset.c) | |||
target_sources_ifdef(CONFIG_ZMK_EXT_POWER app PRIVATE src/behaviors/behavior_ext_power.c) | |||
if ((NOT CONFIG_ZMK_SPLIT) OR CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL) | |||
if ((NOT CONFIG_ZMK_SPLIT) OR CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL OR CONFIG_ZMK_SPLIT_SERIAL_ROLE_CENTRAL) |
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.
See the refactor in #1314 which will massively simplify things drastically and avoid this change being needed.
@@ -155,10 +155,14 @@ config ZMK_SPLIT | |||
|
|||
if ZMK_SPLIT | |||
|
|||
choice ZMK_SPLIT_TYPE |
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.
Ditto on #1314
if ZMK_BLE | ||
config ZMK_SPLIT_BLE_ROLE_CENTRAL | ||
default y | ||
endif |
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 should be easier w/ the agnostic role config in #1314
Should really the Async-API of zephyr's uart be used here? At least for now I'm not able to 'simply' use this on a Pi Pico... maybe I'll looker deeper on how the async api has to be implemented or find a workaround for this. Maybe at least a Kconfig error should be generated if SERIAL_SUPPORT_ASYNC of a board is set to n? |
I do think using the async API is probably preferred, which means we should work on the RP2040 UART driver for Zephyr to add support for it. |
Yeah, thought so... maybe I'll find some time soon. So for now I'll have to stick with KMK for my KB2040 / Sofle combo ;-) |
@marcoster Can this be used for two Nice!Nanos in its current state? @petejohanson What would have to be done to move this forward? |
I would also be interested in the answers to @mbrgm 's questions. Also, I wonder what the main benefits are of wiring the two halves. Does it reduce power consumption or improve latency? And would it be possible to connect with Bluetooth to the host, and use uart between halves, or would this only be supported when connected over USB? |
@mbrgm Sorry, never wrote an answer - as I don't have any nice!nanos around I don't really know, but since the nRF52840 in Zephyr supports async uart it normally should work. |
Am I right to assume that UART support in Zephyr would allow for wired split communication between peripheral and central over TRRS? 🙏 |
This PR definitely needs a rebase into latest ZMK
|
I have a corne cherry with sparkfun_pro_micro_rp2040 and will make this work with the latest main branch within the next few days. Shall I open a new PR once done? |
Sure! See my previous note about the current state needing a working UART device (in terms of Zephyr device w/ associated UART driver) so any single wire work will need to either:
|
Hey there, I was looking at implementing "just this" (wired connection between halves, likely using TRRS and UART TTL) on the Glove80 (dual nRF52840, harware UART). Any way I can help? |
Am also interested in seeing this happen. If there's a contributor who wants to pick this up but needs hardware to do so, please post a comment and I'll sponsor the needful :) |
Update Apr 12 2024, my Dilemma is wired and I've learned that ZMK does not currently support wired splits. Without wanting to get new microcontrollers, I've decided to either wait this out or pivot to a Sugar Glider or Reviung 41. Currently following [lesshonor's Mechhwild ZMK work](https://github.com/lesshonor/mechwild-zmk-keyboards/tree/cirque) and [PR 1117 of ZMK](zmkfirmware/zmk#1117)
Initial wired split support. Raised this PR to get feedback on initial changes and design
Changes:
Note:
SteMCell board config:
https://github.com/megamind4089/zmk-config/tree/main/config/boards/arm/stemcell
Cherrypicked zephyr PR:
zephyrproject-rtos/zephyr#40525