From a2af74f5ab4d2d7142791ae55cab11d59b29bc4d Mon Sep 17 00:00:00 2001 From: Cem Aksoylar Date: Mon, 29 May 2023 21:25:12 -0700 Subject: [PATCH 01/76] feat(docs): Add note on modifier functions to macros --- docs/docs/behaviors/macros.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/docs/behaviors/macros.md b/docs/docs/behaviors/macros.md index 1648892e9f7..1628e0cb554 100644 --- a/docs/docs/behaviors/macros.md +++ b/docs/docs/behaviors/macros.md @@ -33,7 +33,7 @@ A macro definition looks like: :::note The text before the colon (`:`) in the declaration of the macro node is the "node label", and is the text -used to reference the macro in your keymap +used to reference the macro in your keymap. ::: The macro can then be bound in your keymap by referencing it by the label `&zed_em_kay`, e.g.: @@ -44,6 +44,11 @@ The macro can then be bound in your keymap by referencing it by the label `&zed_ }; ``` +:::note +For use cases involving sending a single keycode with modifiers, for instance ctrl+tab, the [key press behavior](key-press.md) +with [modifier functions](../codes/modifiers.mdx#modifier-functions) can be used instead of a macro. +::: + ### Bindings Like [hold-taps](/docs/behaviors/hold-tap), macros are created by composing other behaviors, and any of those behaviors can From 0508718d6ce8b40adbe932b0bd9bb30ee5e0bbf5 Mon Sep 17 00:00:00 2001 From: Cem Aksoylar Date: Mon, 29 May 2023 21:52:16 -0700 Subject: [PATCH 02/76] feat(docs): Add behavior types section for hold-tap --- docs/docs/behaviors/hold-tap.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/docs/docs/behaviors/hold-tap.md b/docs/docs/behaviors/hold-tap.md index f0096606938..2a8489a15ab 100644 --- a/docs/docs/behaviors/hold-tap.md +++ b/docs/docs/behaviors/hold-tap.md @@ -133,6 +133,23 @@ See the following example, which uses a hold-tap behavior definition, configured By default, `hold-trigger-key-positions` are evaluated upon the first _key press_ after the hold-tap. For homerow mods, this is not always ideal, because it prevents combining multiple modifiers unless they are included in `hold-trigger-key-positions`. To overwrite this behavior, one can set `hold-trigger-on-release`. If set to true, the evaluation of `hold-trigger-key-positions` gets delayed until _key release_. This allows combining multiple modifiers when the next key is _held_, while still deciding the hold-tap in favor of a tap when the next key is _tapped_. +#### Using different behavior types with hold-taps + +You can create instances of hold-taps invoking most [behavior types](../features/keymaps.md#behaviors) for hold or tap actions, by referencing their node labels in the `bindings` value. +The two parameters that are passed to the hold-tap in your keymap will be forwarded to the referred behaviors, first one to the hold behavior and second one to the tap. + +If you use behaviors that accept no parameters such as [mod-morphs](mod-morph.md) or [macros](macros.md), you can pass a dummy parameter value such as `0` to the hold-tap when you use it in your keymap. +For instance, a hold-tap with node label `caps` and `bindings = <&kp>, <&caps_word>;` can be used in the keymap as below to send the caps lock keycode on hold and invoke the [caps word behavior](caps-word.md) on tap: + +``` +&caps CAPS 0 +``` + +:::info +You cannot use behaviors that expect more than one parameter such as [`&bt`](bluetooth.md) and [`&rgb_ug`](underglow.md) with hold-taps, due to the limitations of the [devicetree keymap format](../config/index.md#devicetree-files). +One workaround is to create a [macro](macros.md) that invokes those behaviors and use the macro as the hold or tap action. +::: + ### Example Use-Cases Date: Mon, 29 May 2023 22:03:24 -0700 Subject: [PATCH 03/76] feat(docs): Add troubleshooting for Windows issue --- docs/docs/features/bluetooth.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/docs/docs/features/bluetooth.md b/docs/docs/features/bluetooth.md index f1a3e2416fe..ff1823984b4 100644 --- a/docs/docs/features/bluetooth.md +++ b/docs/docs/features/bluetooth.md @@ -57,3 +57,18 @@ If you attempt to pair a ZMK keyboard from macOS in a way that causes a bonding 1. Remove the keyboard from macOS using the Bluetooth control panel. 1. Invoke `&bt BT_CLR` on the keyboard while the profile associated with the macOS device is active, by pressing the correct keys for your particular keymap. 1. Try connecting again from macOS. + +### Windows Connected But Not Working + +Occasionally pairing the keyboard to a Windows device might result in a state where the keyboard is connected but does not send any key strokes. +If this occurs: + +1. Remove the keyboard from Windows using the Bluetooth settings. +1. Invoke `&bt BT_CLR` on the keyboard while the profile associated with the Windows device is active, by pressing the correct keys for your particular keymap. +1. Turn off Bluetooth from Windows settings, then turn it back on. +1. Pair the keyboard to the Windows device. + +If this doesn't help, try following the procedure above but replace step 3 with one of the following: + +- Restart the Windows device +- Open "Device Manager," turn on "Show hidden devices" from the "View" menu, then find and delete the keyboard under the "Bluetooth" item From 30ba4b08aed896d77fb7ade96ef0334d8f30af5d Mon Sep 17 00:00:00 2001 From: Cem Aksoylar Date: Mon, 29 May 2023 22:06:09 -0700 Subject: [PATCH 04/76] feat(docs): Add pointer to Bluetooth page in troubleshooting --- docs/docs/troubleshooting.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/docs/troubleshooting.md b/docs/docs/troubleshooting.md index 96f729b9631..e8a05b6bb46 100644 --- a/docs/docs/troubleshooting.md +++ b/docs/docs/troubleshooting.md @@ -5,6 +5,8 @@ sidebar_title: Troubleshooting The following page provides suggestions for common errors that may occur during firmware compilation or other issues with keyboard usage. If the information provided is insufficient to resolve the issue, feel free to seek out help from the [ZMK Discord](https://zmk.dev/community/discord/invite). +Please also see [the troubleshooting section](features/bluetooth.md#troubleshooting) under the Bluetooth feature page. + ### File Transfer Error Variations of the warnings shown below occur when flashing the `.uf2` onto the microcontroller. This is because the microcontroller resets itself before the OS receives confirmation that the file transfer is complete. Errors like this are normal and can generally be ignored. Verification of a functional board can be done by attempting to pair your newly flashed keyboard to your computer via Bluetooth or plugging in a USB cable if `ZMK_USB` is enabled in your Kconfig.defconfig. From a9ad11f91e82e214d91cf9bf1586431060759f06 Mon Sep 17 00:00:00 2001 From: Cem Aksoylar Date: Fri, 2 Jun 2023 18:42:50 -0700 Subject: [PATCH 05/76] refactor(docs): Move BT troubleshooting items to BT page --- docs/docs/features/bluetooth.md | 14 ++++++++++++++ docs/docs/troubleshooting.md | 16 +--------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/docs/docs/features/bluetooth.md b/docs/docs/features/bluetooth.md index ff1823984b4..386ad70e7f0 100644 --- a/docs/docs/features/bluetooth.md +++ b/docs/docs/features/bluetooth.md @@ -38,6 +38,20 @@ Management of the bluetooth in ZMK is accomplished using the [`&bt` behavior](.. ## Troubleshooting +### Connectivity Issues + +Some users may experience a poor connection between the keyboard and the host. This might be due to poor quality BLE hardware, a metal enclosure on the keyboard or host, or the distance between them. Increasing the transmit power of the keyboard's BLE radio may reduce the severity of this problem. To do this, set the `CONFIG_BT_CTLR_TX_PWR_PLUS_8` configuration value in the `.conf` file of your user config directory as such: + +``` +CONFIG_BT_CTLR_TX_PWR_PLUS_8=y +``` + +For the `nRF52840`, the value `PLUS_8` can be set to any multiple of four between `MINUS_20` and `PLUS_8`. The default value for this config is `0`, but if you are having connection issues it is recommended to set it to `PLUS_8` because the power consumption difference is negligible. For more information on changing the transmit power of your BLE device, please refer to [the Zephyr docs.](https://docs.zephyrproject.org/latest/kconfig.html#CONFIG_BT_CTLR_TX_PWR) + +### Using bluetooth output with USB power + +If you want to test bluetooth output on your keyboard and are powering it through the USB connection rather than a battery, you will be able to pair with a host device but may not see keystrokes sent. In this case you need to use the [output selection behavior](../docs/behaviors/outputs.md) to prefer sending keystrokes over bluetooth rather than USB. This might be necessary even if you are not powering from a device capable of receiving USB inputs, such as a USB charger. + ## Known Issues There are a few known issues related to BLE and ZMK: diff --git a/docs/docs/troubleshooting.md b/docs/docs/troubleshooting.md index e8a05b6bb46..d47671bce36 100644 --- a/docs/docs/troubleshooting.md +++ b/docs/docs/troubleshooting.md @@ -5,7 +5,7 @@ sidebar_title: Troubleshooting The following page provides suggestions for common errors that may occur during firmware compilation or other issues with keyboard usage. If the information provided is insufficient to resolve the issue, feel free to seek out help from the [ZMK Discord](https://zmk.dev/community/discord/invite). -Please also see [the troubleshooting section](features/bluetooth.md#troubleshooting) under the Bluetooth feature page. +Please also see [the troubleshooting section](features/bluetooth.md#troubleshooting) under the Bluetooth feature page for issues related to bluetooth. ### File Transfer Error @@ -102,17 +102,3 @@ Perform the following steps to reset both halves of your split keyboard: 1. Flash the actual image for each half of the split keyboard (e.g `my_board_left.uf2` to the left half, `my_board_right.uf2` to the right half). After completing these steps, pair the halves of the split keyboard together by resetting them at the same time. Most commonly, this is done by grounding the reset pins for each of your keyboard's microcontrollers or pressing the reset buttons at the same time. - -### Connectivity Issues - -Some users may experience a poor connection between the keyboard and the host. This might be due to poor quality BLE hardware, a metal enclosure on the keyboard or host, or the distance between them. Increasing the transmit power of the keyboard's BLE radio may reduce the severity of this problem. To do this, set the `CONFIG_BT_CTLR_TX_PWR_PLUS_8` configuration value in the `.conf` file of your user config directory as such: - -``` -CONFIG_BT_CTLR_TX_PWR_PLUS_8=y -``` - -For the `nRF52840`, the value `PLUS_8` can be set to any multiple of four between `MINUS_20` and `PLUS_8`. The default value for this config is `0`, but if you are having connection issues it is recommended to set it to `PLUS_8` because the power consumption difference is negligible. For more information on changing the transmit power of your BLE device, please refer to [the Zephyr docs.](https://docs.zephyrproject.org/latest/kconfig.html#CONFIG_BT_CTLR_TX_PWR) - -### Other notes and warnings - -- If you want to test bluetooth output on your keyboard and are powering it through the USB connection rather than a battery, you will be able to pair with a host device but may not see keystrokes sent. In this case you need to use the [output selection behavior](../docs/behaviors/outputs.md) to prefer sending keystrokes over bluetooth rather than USB. This might be necessary even if you are not powering from a device capable of receiving USB inputs, such as a USB charger. From 0682bc3aa6d9b9deac48b5aa6c781241075819b3 Mon Sep 17 00:00:00 2001 From: Cem Aksoylar Date: Fri, 2 Jun 2023 18:45:15 -0700 Subject: [PATCH 06/76] feat(docs): Note split connectivity improvement with TX power --- docs/docs/features/bluetooth.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/docs/features/bluetooth.md b/docs/docs/features/bluetooth.md index 386ad70e7f0..9637c4d00c9 100644 --- a/docs/docs/features/bluetooth.md +++ b/docs/docs/features/bluetooth.md @@ -48,6 +48,10 @@ CONFIG_BT_CTLR_TX_PWR_PLUS_8=y For the `nRF52840`, the value `PLUS_8` can be set to any multiple of four between `MINUS_20` and `PLUS_8`. The default value for this config is `0`, but if you are having connection issues it is recommended to set it to `PLUS_8` because the power consumption difference is negligible. For more information on changing the transmit power of your BLE device, please refer to [the Zephyr docs.](https://docs.zephyrproject.org/latest/kconfig.html#CONFIG_BT_CTLR_TX_PWR) +:::info +This setting can also improve the connection strength between the keyboard halves for split keyboards. +::: + ### Using bluetooth output with USB power If you want to test bluetooth output on your keyboard and are powering it through the USB connection rather than a battery, you will be able to pair with a host device but may not see keystrokes sent. In this case you need to use the [output selection behavior](../docs/behaviors/outputs.md) to prefer sending keystrokes over bluetooth rather than USB. This might be necessary even if you are not powering from a device capable of receiving USB inputs, such as a USB charger. From ace11e327fbfb4c4c894bb66328156d4d0b7eda0 Mon Sep 17 00:00:00 2001 From: Cem Aksoylar Date: Fri, 2 Jun 2023 20:46:13 -0700 Subject: [PATCH 07/76] fix(docs): Fix broken link in BT troubleshooting --- docs/docs/features/bluetooth.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/features/bluetooth.md b/docs/docs/features/bluetooth.md index 9637c4d00c9..b75b89537d4 100644 --- a/docs/docs/features/bluetooth.md +++ b/docs/docs/features/bluetooth.md @@ -54,7 +54,7 @@ This setting can also improve the connection strength between the keyboard halve ### Using bluetooth output with USB power -If you want to test bluetooth output on your keyboard and are powering it through the USB connection rather than a battery, you will be able to pair with a host device but may not see keystrokes sent. In this case you need to use the [output selection behavior](../docs/behaviors/outputs.md) to prefer sending keystrokes over bluetooth rather than USB. This might be necessary even if you are not powering from a device capable of receiving USB inputs, such as a USB charger. +If you want to test bluetooth output on your keyboard and are powering it through the USB connection rather than a battery, you will be able to pair with a host device but may not see keystrokes sent. In this case you need to use the [output selection behavior](../behaviors/outputs.md) to prefer sending keystrokes over bluetooth rather than USB. This might be necessary even if you are not powering from a device capable of receiving USB inputs, such as a USB charger. ## Known Issues From 19d883cdfe679977023116dcf689ce67a6ce548d Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Sat, 3 Jun 2023 02:53:20 +0000 Subject: [PATCH 08/76] fix(bluetooth): Passkey pairing improvements. * Capture the last 6 entered digits, and then require pressing Enter/Return to submit the entered digits. This matches the messaging shown on hosts regarding how to complete pairing. * Fix the wording on the Kconfig menu item to accurately describe the feature. --- app/Kconfig | 3 ++- app/src/ble.c | 47 +++++++++++++++++++++-------------- docs/docs/config/bluetooth.md | 7 +++--- 3 files changed, 34 insertions(+), 23 deletions(-) diff --git a/app/Kconfig b/app/Kconfig index d1b6682f507..1537bd61512 100644 --- a/app/Kconfig +++ b/app/Kconfig @@ -160,8 +160,9 @@ config BT_DEVICE_APPEARANCE default 961 config ZMK_BLE_PASSKEY_ENTRY - bool "Experimental: Requiring typing passkey from host to pair BLE connection" + bool "Require passkey entry on the keyboard to complete pairing" default n + select RING_BUFFER config BT_PERIPHERAL_PREF_MIN_INT default 6 diff --git a/app/src/ble.c b/app/src/ble.c index c7bdc401b66..383a727d268 100644 --- a/app/src/ble.c +++ b/app/src/ble.c @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -42,8 +43,7 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #define PASSKEY_DIGITS 6 static struct bt_conn *auth_passkey_entry_conn; -static uint8_t passkey_entries[PASSKEY_DIGITS] = {}; -static uint8_t passkey_digit = 0; +RING_BUF_DECLARE(passkey_entries, PASSKEY_DIGITS); #endif /* IS_ENABLED(CONFIG_ZMK_BLE_PASSKEY_ENTRY) */ @@ -469,7 +469,7 @@ static void auth_passkey_entry(struct bt_conn *conn) { bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); LOG_DBG("Passkey entry requested for %s", addr); - passkey_digit = 0; + ring_buf_reset(&passkey_entries); auth_passkey_entry_conn = bt_conn_ref(conn); } @@ -486,7 +486,7 @@ static void auth_cancel(struct bt_conn *conn) { auth_passkey_entry_conn = NULL; } - passkey_digit = 0; + ring_buf_reset(&passkey_entries); #endif LOG_DBG("Pairing cancelled: %s", addr); @@ -605,7 +605,7 @@ static int zmk_ble_init(const struct device *_arg) { #if IS_ENABLED(CONFIG_ZMK_BLE_PASSKEY_ENTRY) static bool zmk_ble_numeric_usage_to_value(const zmk_key_t key, const zmk_key_t one, - const zmk_key_t zero, uint32_t *value) { + const zmk_key_t zero, uint8_t *value) { if (key < one || key > zero) { return false; } @@ -634,29 +634,38 @@ static int zmk_ble_handle_key_user(struct zmk_keycode_state_changed *event) { return ZMK_EV_EVENT_HANDLED; } - uint32_t val; - if (!(zmk_ble_numeric_usage_to_value(key, HID_USAGE_KEY_KEYBOARD_1_AND_EXCLAMATION, - HID_USAGE_KEY_KEYBOARD_0_AND_RIGHT_PARENTHESIS, &val) || - zmk_ble_numeric_usage_to_value(key, HID_USAGE_KEY_KEYPAD_1_AND_END, - HID_USAGE_KEY_KEYPAD_0_AND_INSERT, &val))) { - LOG_DBG("Key not a number, ignoring"); - return ZMK_EV_EVENT_BUBBLE; - } - - passkey_entries[passkey_digit++] = val; - LOG_DBG("value entered: %d, digits collected so far: %d", val, passkey_digit); + if (key == HID_USAGE_KEY_KEYBOARD_RETURN || key == HID_USAGE_KEY_KEYBOARD_RETURN_ENTER) { + uint8_t digits[PASSKEY_DIGITS]; + uint32_t count = ring_buf_get(&passkey_entries, digits, PASSKEY_DIGITS); - if (passkey_digit == PASSKEY_DIGITS) { uint32_t passkey = 0; - for (int i = 0; i < PASSKEY_DIGITS; i++) { - passkey = (passkey * 10) + passkey_entries[i]; + for (int i = 0; i < count; i++) { + passkey = (passkey * 10) + digits[i]; } LOG_DBG("Final passkey: %d", passkey); bt_conn_auth_passkey_entry(auth_passkey_entry_conn, passkey); bt_conn_unref(auth_passkey_entry_conn); auth_passkey_entry_conn = NULL; + return ZMK_EV_EVENT_HANDLED; + } + + uint8_t val; + if (!(zmk_ble_numeric_usage_to_value(key, HID_USAGE_KEY_KEYBOARD_1_AND_EXCLAMATION, + HID_USAGE_KEY_KEYBOARD_0_AND_RIGHT_PARENTHESIS, &val) || + zmk_ble_numeric_usage_to_value(key, HID_USAGE_KEY_KEYPAD_1_AND_END, + HID_USAGE_KEY_KEYPAD_0_AND_INSERT, &val))) { + LOG_DBG("Key not a number, ignoring"); + return ZMK_EV_EVENT_BUBBLE; + } + + if (ring_buf_space_get(&passkey_entries) <= 0) { + uint8_t discard_val; + ring_buf_get(&passkey_entries, &discard_val, 1); } + ring_buf_put(&passkey_entries, &val, 1); + LOG_DBG("value entered: %d, digits collected so far: %d", val, + ring_buf_size_get(&passkey_entries)); return ZMK_EV_EVENT_HANDLED; } diff --git a/docs/docs/config/bluetooth.md b/docs/docs/config/bluetooth.md index 420dd5c3627..d2ddefddbd1 100644 --- a/docs/docs/config/bluetooth.md +++ b/docs/docs/config/bluetooth.md @@ -9,6 +9,7 @@ See [Configuration Overview](index.md) for instructions on how to change these s ## Kconfig -| Option | Type | Description | Default | -| ------------------------------------- | ---- | ----------------------------------------------------------------------------------------------------------------------- | ------- | -| `CONFIG_BT_GATT_ENFORCE_SUBSCRIPTION` | bool | Low level setting for GATT subscriptions. Set to `n` to work around an annoying Windows bug with battery notifications. | y | +| Option | Type | Description | Default | +| ------------------------------------- | ---- | -------------------------------------------------------------------------------------------------------------------------------------------- | ------- | +| `CONFIG_ZMK_BLE_PASSKEY_ENTRY` | bool | Enable passkey entry during pairing for enhanced security. (Note: After enabling this, you will need to re-pair all previously paired hosts) | n | +| `CONFIG_BT_GATT_ENFORCE_SUBSCRIPTION` | bool | Low level setting for GATT subscriptions. Set to `n` to work around an annoying Windows bug with battery notifications. | y | From f08802eaa735b87fa089b81512a941a1bcc8ca4b Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Mon, 5 Jun 2023 05:04:13 +0000 Subject: [PATCH 09/76] fix(boards): Proper i2c pinctrl for BlueMicro840 * Use the proper pin assignmets after the move to pinctrl for the Zephyr 3.2 migration. --- .../arm/bluemicro840/bluemicro840_v1-pinctrl.dtsi | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/boards/arm/bluemicro840/bluemicro840_v1-pinctrl.dtsi b/app/boards/arm/bluemicro840/bluemicro840_v1-pinctrl.dtsi index 15c48509202..868d3c27ad7 100644 --- a/app/boards/arm/bluemicro840/bluemicro840_v1-pinctrl.dtsi +++ b/app/boards/arm/bluemicro840/bluemicro840_v1-pinctrl.dtsi @@ -17,22 +17,22 @@ uart0_sleep: uart0_sleep { group1 { psels = , - ; + ; low-power-enable; }; }; i2c0_default: i2c0_default { group1 { - psels = , - ; + psels = , + ; }; }; i2c0_sleep: i2c0_sleep { group1 { - psels = , - ; + psels = , + ; low-power-enable; }; }; From 5d9ae8fffa869f36e3e0911bed92d41ed8640826 Mon Sep 17 00:00:00 2001 From: Xudong Zheng <7pkvm5aw@slicealias.com> Date: Fri, 17 Jun 2022 17:44:31 -0400 Subject: [PATCH 10/76] feat(split): allow central to connect to multiple peripherals --- app/include/zmk/ble.h | 6 +- app/src/ble.c | 54 ++++++++---- app/src/split/bluetooth/Kconfig | 4 + app/src/split/bluetooth/central.c | 138 ++++++++++++++++++------------ 4 files changed, 130 insertions(+), 72 deletions(-) diff --git a/app/include/zmk/ble.h b/app/include/zmk/ble.h index 1c84777d757..435fde49654 100644 --- a/app/include/zmk/ble.h +++ b/app/include/zmk/ble.h @@ -14,8 +14,8 @@ IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL)) #if ZMK_BLE_IS_CENTRAL -#define ZMK_BLE_PROFILE_COUNT (CONFIG_BT_MAX_PAIRED - 1) -#define ZMK_SPLIT_BLE_PERIPHERAL_COUNT 1 +#define ZMK_BLE_PROFILE_COUNT (CONFIG_BT_MAX_PAIRED - CONFIG_ZMK_SPLIT_BLE_CENTRAL_PERIPHERALS) +#define ZMK_SPLIT_BLE_PERIPHERAL_COUNT CONFIG_ZMK_SPLIT_BLE_CENTRAL_PERIPHERALS #else #define ZMK_BLE_PROFILE_COUNT CONFIG_BT_MAX_PAIRED #endif @@ -34,5 +34,5 @@ char *zmk_ble_active_profile_name(); int zmk_ble_unpair_all(); #if IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) -void zmk_ble_set_peripheral_addr(bt_addr_le_t *addr); +int zmk_ble_put_peripheral_addr(const bt_addr_le_t *addr); #endif /* IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) */ diff --git a/app/src/ble.c b/app/src/ble.c index 383a727d268..ff82f3cf40a 100644 --- a/app/src/ble.c +++ b/app/src/ble.c @@ -47,12 +47,6 @@ RING_BUF_DECLARE(passkey_entries, PASSKEY_DIGITS); #endif /* IS_ENABLED(CONFIG_ZMK_BLE_PASSKEY_ENTRY) */ -#if IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) -#define PROFILE_COUNT (CONFIG_BT_MAX_PAIRED - 1) -#else -#define PROFILE_COUNT CONFIG_BT_MAX_PAIRED -#endif - enum advertising_type { ZMK_ADV_NONE, ZMK_ADV_DIR, @@ -84,7 +78,7 @@ static const struct bt_data zmk_ble_ad[] = { #if IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) -static bt_addr_le_t peripheral_addr; +static bt_addr_le_t peripheral_addrs[ZMK_SPLIT_BLE_PERIPHERAL_COUNT]; #endif /* IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) */ @@ -283,9 +277,34 @@ char *zmk_ble_active_profile_name() { return profiles[active_profile].name; } #if IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) -void zmk_ble_set_peripheral_addr(bt_addr_le_t *addr) { - memcpy(&peripheral_addr, addr, sizeof(bt_addr_le_t)); - settings_save_one("ble/peripheral_address", addr, sizeof(bt_addr_le_t)); +int zmk_ble_put_peripheral_addr(const bt_addr_le_t *addr) { + for (int i = 0; i < ZMK_SPLIT_BLE_PERIPHERAL_COUNT; i++) { + // If the address is recognized and already stored in settings, return + // index and no additional action is necessary. + if (!bt_addr_le_cmp(&peripheral_addrs[i], addr)) { + return i; + } + + // If the peripheral address slot is open, store new peripheral in the + // slot and return index. This compares against BT_ADDR_LE_ANY as that + // is the zero value. + if (!bt_addr_le_cmp(&peripheral_addrs[i], BT_ADDR_LE_ANY)) { + char addr_str[BT_ADDR_LE_STR_LEN]; + bt_addr_le_to_str(addr, addr_str, sizeof(addr_str)); + LOG_DBG("Storing peripheral %s in slot %d", addr_str, i); + bt_addr_le_copy(&peripheral_addrs[i], addr); + + char setting_name[32]; + sprintf(setting_name, "ble/peripheral_addresses/%d", i); + settings_save_one(setting_name, addr, sizeof(bt_addr_le_t)); + + return i; + } + } + + // The peripheral does not match a known peripheral and there is no + // available slot. + return -ENOMEM; } #endif /* IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) */ @@ -340,15 +359,20 @@ static int ble_profiles_handle_set(const char *name, size_t len, settings_read_c } } #if IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) - else if (settings_name_steq(name, "peripheral_address", &next) && !next) { + else if (settings_name_steq(name, "peripheral_addresses", &next) && next) { if (len != sizeof(bt_addr_le_t)) { return -EINVAL; } - int err = read_cb(cb_arg, &peripheral_addr, sizeof(bt_addr_le_t)); - if (err <= 0) { - LOG_ERR("Failed to handle peripheral address from settings (err %d)", err); - return err; + int i = atoi(next); + if (i < 0 || i >= ZMK_SPLIT_BLE_PERIPHERAL_COUNT) { + LOG_ERR("Failed to store peripheral address in memory"); + } else { + int err = read_cb(cb_arg, &peripheral_addrs[i], sizeof(bt_addr_le_t)); + if (err <= 0) { + LOG_ERR("Failed to handle peripheral address from settings (err %d)", err); + return err; + } } } #endif diff --git a/app/src/split/bluetooth/Kconfig b/app/src/split/bluetooth/Kconfig index 005d75fd43b..e2c8d5c3395 100644 --- a/app/src/split/bluetooth/Kconfig +++ b/app/src/split/bluetooth/Kconfig @@ -17,6 +17,10 @@ config ZMK_SPLIT_ROLE_CENTRAL if ZMK_SPLIT_ROLE_CENTRAL +config ZMK_SPLIT_BLE_CENTRAL_PERIPHERALS + int "Number of peripherals that will connect to the central." + default 1 + config ZMK_SPLIT_BLE_CENTRAL_POSITION_QUEUE_SIZE int "Max number of key position state events to queue when received from peripherals" default 5 diff --git a/app/src/split/bluetooth/central.c b/app/src/split/bluetooth/central.c index a7c0d8a9964..53e61be621a 100644 --- a/app/src/split/bluetooth/central.c +++ b/app/src/split/bluetooth/central.c @@ -26,7 +26,7 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #include #include -static int start_scan(void); +static int start_scanning(void); #define POSITION_STATE_DATA_LEN 16 @@ -49,6 +49,8 @@ struct peripheral_slot { static struct peripheral_slot peripherals[ZMK_SPLIT_BLE_PERIPHERAL_COUNT]; +static bool is_scanning = false; + static const struct bt_uuid_128 split_service_uuid = BT_UUID_INIT_128(ZMK_SPLIT_BT_SERVICE_UUID); K_MSGQ_DEFINE(peripheral_event_msgq, sizeof(struct zmk_position_state_changed), @@ -130,8 +132,9 @@ int release_peripheral_slot(int index) { return 0; } -int reserve_peripheral_slot() { - for (int i = 0; i < ZMK_SPLIT_BLE_PERIPHERAL_COUNT; i++) { +int reserve_peripheral_slot(const bt_addr_le_t *addr) { + int i = zmk_ble_put_peripheral_addr(addr); + if (i >= 0) { if (peripherals[i].state == PERIPHERAL_SLOT_STATE_OPEN) { // Be sure the slot is fully reinitialized. release_peripheral_slot(i); @@ -344,9 +347,54 @@ static void split_central_process_connection(struct bt_conn *conn) { LOG_DBG("New connection params: Interval: %d, Latency: %d, PHY: %d", info.le.interval, info.le.latency, info.le.phy->rx_phy); + + // Restart scanning if necessary. + start_scanning(); +} + +static int stop_scanning() { + LOG_DBG("Stopping peripheral scanning"); + is_scanning = false; + + int err = bt_le_scan_stop(); + if (err < 0) { + LOG_ERR("Stop LE scan failed (err %d)", err); + return err; + } + + return 0; } -static bool split_central_eir_found(struct bt_data *data, void *user_data) { +static bool split_central_eir_found(const bt_addr_le_t *addr) { + LOG_DBG("Found the split service"); + + // Stop scanning so we can connect to the peripheral device. + int err = stop_scanning(); + if (err < 0) { + return false; + } + + int slot_idx = reserve_peripheral_slot(addr); + if (slot_idx < 0) { + LOG_ERR("Failed to reserve peripheral slot (err %d)", slot_idx); + return false; + } + + struct peripheral_slot *slot = &peripherals[slot_idx]; + + LOG_DBG("Initiating new connnection"); + struct bt_le_conn_param *param = BT_LE_CONN_PARAM(0x0006, 0x0006, 30, 400); + err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN, param, &slot->conn); + if (err < 0) { + LOG_ERR("Create conn failed (err %d) (create conn? 0x%04x)", err, BT_HCI_OP_LE_CREATE_CONN); + release_peripheral_slot(slot_idx); + start_scanning(); + } + + return false; +} + +static bool split_central_eir_parse(struct bt_data *data, void *user_data) { bt_addr_le_t *addr = user_data; int i; @@ -361,9 +409,7 @@ static bool split_central_eir_found(struct bt_data *data, void *user_data) { } for (i = 0; i < data->data_len; i += 16) { - struct bt_le_conn_param *param; struct bt_uuid_128 uuid; - int err; if (!bt_uuid_create(&uuid.uuid, &data->data[i], 16)) { LOG_ERR("Unable to load UUID"); @@ -381,46 +427,7 @@ static bool split_central_eir_found(struct bt_data *data, void *user_data) { continue; } - LOG_DBG("Found the split service"); - - zmk_ble_set_peripheral_addr(addr); - - err = bt_le_scan_stop(); - if (err) { - LOG_ERR("Stop LE scan failed (err %d)", err); - continue; - } - - uint8_t slot_idx = reserve_peripheral_slot(); - if (slot_idx < 0) { - LOG_ERR("Faild to reserve peripheral slot (err %d)", slot_idx); - continue; - } - - struct peripheral_slot *slot = &peripherals[slot_idx]; - - slot->conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, addr); - if (slot->conn) { - LOG_DBG("Found existing connection"); - split_central_process_connection(slot->conn); - err = bt_conn_le_phy_update(slot->conn, BT_CONN_LE_PHY_PARAM_2M); - if (err) { - LOG_ERR("Update phy conn failed (err %d)", err); - } - } else { - param = BT_LE_CONN_PARAM(0x0006, 0x0006, 30, 400); - - LOG_DBG("Initiating new connnection"); - - err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN, param, &slot->conn); - if (err) { - LOG_ERR("Create conn failed (err %d) (create conn? 0x%04x)", err, - BT_HCI_OP_LE_CREATE_CONN); - start_scan(); - } - } - - return false; + return split_central_eir_found(addr); } } @@ -436,15 +443,34 @@ static void split_central_device_found(const bt_addr_le_t *addr, int8_t rssi, ui /* We're only interested in connectable events */ if (type == BT_GAP_ADV_TYPE_ADV_IND || type == BT_GAP_ADV_TYPE_ADV_DIRECT_IND) { - bt_data_parse(ad, split_central_eir_found, (void *)addr); + bt_data_parse(ad, split_central_eir_parse, (void *)addr); } } -static int start_scan(void) { - int err; +static int start_scanning(void) { + // No action is necessary if central is already scanning. + if (is_scanning) { + LOG_DBG("Scanning already running"); + return 0; + } - err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, split_central_device_found); - if (err) { + // If all the devices are connected, there is no need to scan. + bool has_unconnected = false; + for (int i = 0; i < CONFIG_ZMK_SPLIT_BLE_CENTRAL_PERIPHERALS; i++) { + if (peripherals[i].conn == NULL) { + has_unconnected = true; + break; + } + } + if (!has_unconnected) { + LOG_DBG("All devices are connected, scanning is unnecessary"); + return 0; + } + + // Start scanning otherwise. + is_scanning = true; + int err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, split_central_device_found); + if (err < 0) { LOG_ERR("Scanning failed to start (err %d)", err); return err; } @@ -471,7 +497,7 @@ static void split_central_connected(struct bt_conn *conn, uint8_t conn_err) { release_peripheral_slot_for_conn(conn); - start_scan(); + start_scanning(); return; } @@ -495,7 +521,7 @@ static void split_central_disconnected(struct bt_conn *conn, uint8_t reason) { return; } - start_scan(); + start_scanning(); } static struct bt_conn_cb conn_callbacks = { @@ -527,6 +553,10 @@ void split_central_split_run_callback(struct k_work *work) { LOG_ERR("Source not connected"); continue; } + if (!peripherals[payload_wrapper.source].run_behavior_handle) { + LOG_ERR("Run behavior handle not found"); + continue; + } int err = bt_gatt_write_without_response( peripherals[payload_wrapper.source].conn, @@ -590,7 +620,7 @@ int zmk_split_bt_central_init(const struct device *_arg) { CONFIG_ZMK_BLE_THREAD_PRIORITY, NULL); bt_conn_cb_register(&conn_callbacks); - return start_scan(); + return start_scanning(); } SYS_INIT(zmk_split_bt_central_init, APPLICATION, CONFIG_ZMK_BLE_INIT_PRIORITY); From a5c57fa224ba410100dde4e64222505bfb2b89ea Mon Sep 17 00:00:00 2001 From: Albert Y <76888457+filterpaper@users.noreply.github.com> Date: Tue, 6 Jun 2023 13:22:39 +0800 Subject: [PATCH 11/76] feat(docs): Add an example for combining just modifiers (#1826) Co-authored-by: Cem Aksoylar --- docs/docs/codes/modifiers.mdx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/docs/codes/modifiers.mdx b/docs/docs/codes/modifiers.mdx index 483e34af026..db88ee926d2 100644 --- a/docs/docs/codes/modifiers.mdx +++ b/docs/docs/codes/modifiers.mdx @@ -38,6 +38,8 @@ These functions take the form: `XX(code)` - `&kp LS(A)` = `LEFT_SHIFT`+`A` (a capitalized **A**). - They can be combined: - `&kp LC(RA(B))` = `LEFT_CONTROL`+`RIGHT_ALT`+`B` +- They can be applied to a modifier keycode to create combined modifier keys: + - `&kp LS(LALT)` = `LEFT_SHIFT` + `LEFT_ALT` - Some basic codes already include a modifier function in their definition: - `DOLLAR` = `LS(NUMBER_4)` - There are left- and right-handed versions of each modifier (also see table above): From 98524a95671fe9d819a65d1515f9bc37895efc3d Mon Sep 17 00:00:00 2001 From: kadoyau <11990327+kadoyau@users.noreply.github.com> Date: Sun, 11 Jun 2023 04:32:50 +0900 Subject: [PATCH 12/76] fix(docs): Fix INT6 keycode description --- docs/src/data/hid.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/data/hid.js b/docs/src/data/hid.js index 00d48f3fe67..457671728f8 100644 --- a/docs/src/data/hid.js +++ b/docs/src/data/hid.js @@ -3477,7 +3477,7 @@ export default [ }, { names: ["INTERNATIONAL_6", "INT6", "INT_KPJPCOMMA"], - description: ", [カソマ] (International 6)", + description: ", [カンマ] (International 6)", context: "Keyboard", clarify: false, usages: [ From 9d39a87f67668b4c083e09b04adf006d6fd1385d Mon Sep 17 00:00:00 2001 From: pixls Date: Sat, 10 Jun 2023 20:49:30 -0400 Subject: [PATCH 13/76] fix(docs): Change user-setup.md order to agree with order in setup script Fixes #1281 Co-authored-by: Cem Aksoylar --- docs/docs/user-setup.md | 43 +++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/docs/docs/user-setup.md b/docs/docs/user-setup.md index a2e491b8957..8faa72df85f 100644 --- a/docs/docs/user-setup.md +++ b/docs/docs/user-setup.md @@ -88,34 +88,39 @@ powershell -Command "iex ((New-Object System.Net.WebClient).DownloadString('http -### MCU Board Selection +### Keyboard Selection -When prompted, enter the number for the corresponding MCU board you would like to target: +When prompted, enter the number for the corresponding keyboard you would like to target: ``` -MCU Board Selection: -1) nice!nano -2) QMK Proton-C -3) Quit -Pick an MCU board: +Keyboard Selection: + 1) 2% Milk 19) Ferris 0.2 37) Nibble + 2) A. Dux 20) Fourier Rev. 1 38) nice!60 + 3) BAT43 21) Helix 39) Osprette + 4) BDN9 Rev2 22) Hummingbird 40) Pancake + 5) BFO-9000 23) Iris 41) Planck Rev6 + 6) Boardsource 3x4 Macropad 24) etc... +Pick an keyboard: ``` -### Keyboard Shield Selection - -:::note -If you are building firmware for a new keyboard shield that is not included in the built-in -list of shields, you can choose any shield from the list that is similar to yours to generate the repository, -and edit / add necessary files according to the [guide for adding new keyboard shield](development/new-shield.md). +:::note For a keyboard not in the included list: +If you are building firmware for a new keyboard that is not included in the built-in +list of keyboards, you can choose any keyboard from the list that is similar to yours (e.g. in terms of unibody/split and [onboard controller](hardware.mdx#onboard)/[composite](hardware.mdx#composite)) to generate the repository, +and edit / add necessary files. You can follow the [new shield guide](development/new-shield.md) if you are adding support for a composite keyboard. ::: -When prompted, enter the number for the corresponding keyboard shield you would like to target: +### MCU Board Selection + +If the keyboard selected uses an onboard controller you will skip this step. +When prompted, enter the number for the corresponding MCU board you would like to target: ``` -Keyboard Shield Selection: -1) Kyria -2) Lily58 -3) Quit -Pick an keyboard: +MCU Board Selection: +1) BlueMicro840 v1 5) nRF52840 M.2 Module 9) QMK Proton-C +2) Mikoto 5.20 6) nRFMicro 1.1 (flipped) 10) Seeeduino XIAO +3) nice!nano v1 7) nRFMicro 1.1/1.2 11) Seeeduino XIAO BLE +4) nice!nano v2 8) nRFMicro 1.3/1.4 12) Quit +Pick an MCU board: ``` ### Keymap Customization From 0be0d0763081de0c163dd26c29752d1085381dbb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 11 Jun 2023 04:35:54 +0000 Subject: [PATCH 14/76] chore(deps): bump minimatch and serve-handler in /docs Bumps [minimatch](https://github.com/isaacs/minimatch) and [serve-handler](https://github.com/zeit/serve-handler). These dependencies needed to be updated together. Updates `minimatch` from 3.0.4 to 3.1.2 - [Release notes](https://github.com/isaacs/minimatch/releases) - [Commits](https://github.com/isaacs/minimatch/compare/v3.0.4...v3.1.2) Updates `serve-handler` from 6.1.3 to 6.1.5 - [Release notes](https://github.com/zeit/serve-handler/releases) - [Commits](https://github.com/zeit/serve-handler/compare/6.1.3...6.1.5) --- updated-dependencies: - dependency-name: minimatch dependency-type: indirect - dependency-name: serve-handler dependency-type: indirect ... Signed-off-by: dependabot[bot] --- docs/package-lock.json | 35 ++++++++--------------------------- 1 file changed, 8 insertions(+), 27 deletions(-) diff --git a/docs/package-lock.json b/docs/package-lock.json index 3183a51c144..f0cd1fc88ae 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -13612,31 +13612,20 @@ } }, "node_modules/serve-handler": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.3.tgz", - "integrity": "sha512-FosMqFBNrLyeiIDvP1zgO6YoTzFYHxLDEIavhlmQ+knB2Z7l1t+kGLHkZIDN7UVWqQAmKI3D20A6F6jo3nDd4w==", + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.5.tgz", + "integrity": "sha512-ijPFle6Hwe8zfmBxJdE+5fta53fdIY0lHISJvuikXB3VYFafRjMRpOffSPvCYsbKyBA7pvy9oYr/BT1O3EArlg==", "dependencies": { "bytes": "3.0.0", "content-disposition": "0.5.2", "fast-url-parser": "1.1.3", "mime-types": "2.1.18", - "minimatch": "3.0.4", + "minimatch": "3.1.2", "path-is-inside": "1.0.2", "path-to-regexp": "2.2.1", "range-parser": "1.2.0" } }, - "node_modules/serve-handler/node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/serve-handler/node_modules/path-to-regexp": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.2.1.tgz", @@ -25765,28 +25754,20 @@ } }, "serve-handler": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.3.tgz", - "integrity": "sha512-FosMqFBNrLyeiIDvP1zgO6YoTzFYHxLDEIavhlmQ+knB2Z7l1t+kGLHkZIDN7UVWqQAmKI3D20A6F6jo3nDd4w==", + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.5.tgz", + "integrity": "sha512-ijPFle6Hwe8zfmBxJdE+5fta53fdIY0lHISJvuikXB3VYFafRjMRpOffSPvCYsbKyBA7pvy9oYr/BT1O3EArlg==", "requires": { "bytes": "3.0.0", "content-disposition": "0.5.2", "fast-url-parser": "1.1.3", "mime-types": "2.1.18", - "minimatch": "3.0.4", + "minimatch": "3.1.2", "path-is-inside": "1.0.2", "path-to-regexp": "2.2.1", "range-parser": "1.2.0" }, "dependencies": { - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "requires": { - "brace-expansion": "^1.1.7" - } - }, "path-to-regexp": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.2.1.tgz", From 9d714c0b69fee2098a010d29e534051aeca26386 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 11 Jun 2023 06:47:34 +0000 Subject: [PATCH 15/76] chore(deps-dev): bump webpack from 5.80.0 to 5.86.0 in /docs Bumps [webpack](https://github.com/webpack/webpack) from 5.80.0 to 5.86.0. - [Release notes](https://github.com/webpack/webpack/releases) - [Commits](https://github.com/webpack/webpack/compare/v5.80.0...v5.86.0) --- updated-dependencies: - dependency-name: webpack dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- docs/package-lock.json | 46 +++++++++++++++++++++--------------------- docs/package.json | 2 +- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/docs/package-lock.json b/docs/package-lock.json index f0cd1fc88ae..5badb07e389 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -42,7 +42,7 @@ "prettier": "^2.8.7", "string-replace-loader": "^3.1.0", "typescript": "^5.0.4", - "webpack": "^5.80.0" + "webpack": "^5.86.0" } }, "node_modules/@algolia/autocomplete-core": { @@ -3950,9 +3950,9 @@ } }, "node_modules/acorn-import-assertions": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", + "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", "peerDependencies": { "acorn": "^8" } @@ -6069,9 +6069,9 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.13.0.tgz", - "integrity": "sha512-eyV8f0y1+bzyfh8xAwW/WTSZpLbjhqc4ne9eGSH4Zo2ejdyiNG9pU6mf9DG8a7+Auk6MFTlNOT4Y2y/9k8GKVg==", + "version": "5.14.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.14.1.tgz", + "integrity": "sha512-Vklwq2vDKtl0y/vtwjSesgJ5MYS7Etuk5txS8VdKL4AOS1aUlD96zqIfsOSLQsdv3xgMRbtkWM8eG9XDfKUPow==", "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -15390,9 +15390,9 @@ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" }, "node_modules/webpack": { - "version": "5.80.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.80.0.tgz", - "integrity": "sha512-OIMiq37XK1rWO8mH9ssfFKZsXg4n6klTEDL7S8/HqbAOBBaiy8ABvXvz0dDCXeEF9gqwxSvVk611zFPjS8hJxA==", + "version": "5.86.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.86.0.tgz", + "integrity": "sha512-3BOvworZ8SO/D4GVP+GoRC3fVeg5MO4vzmq8TJJEkdmopxyazGDxN8ClqN12uzrZW9Tv8EED8v5VSb6Sqyi0pg==", "dependencies": { "@types/eslint-scope": "^3.7.3", "@types/estree": "^1.0.0", @@ -15400,10 +15400,10 @@ "@webassemblyjs/wasm-edit": "^1.11.5", "@webassemblyjs/wasm-parser": "^1.11.5", "acorn": "^8.7.1", - "acorn-import-assertions": "^1.7.6", + "acorn-import-assertions": "^1.9.0", "browserslist": "^4.14.5", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.13.0", + "enhanced-resolve": "^5.14.1", "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", @@ -18899,9 +18899,9 @@ "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==" }, "acorn-import-assertions": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", + "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", "requires": {} }, "acorn-jsx": { @@ -20426,9 +20426,9 @@ } }, "enhanced-resolve": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.13.0.tgz", - "integrity": "sha512-eyV8f0y1+bzyfh8xAwW/WTSZpLbjhqc4ne9eGSH4Zo2ejdyiNG9pU6mf9DG8a7+Auk6MFTlNOT4Y2y/9k8GKVg==", + "version": "5.14.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.14.1.tgz", + "integrity": "sha512-Vklwq2vDKtl0y/vtwjSesgJ5MYS7Etuk5txS8VdKL4AOS1aUlD96zqIfsOSLQsdv3xgMRbtkWM8eG9XDfKUPow==", "requires": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -27031,9 +27031,9 @@ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" }, "webpack": { - "version": "5.80.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.80.0.tgz", - "integrity": "sha512-OIMiq37XK1rWO8mH9ssfFKZsXg4n6klTEDL7S8/HqbAOBBaiy8ABvXvz0dDCXeEF9gqwxSvVk611zFPjS8hJxA==", + "version": "5.86.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.86.0.tgz", + "integrity": "sha512-3BOvworZ8SO/D4GVP+GoRC3fVeg5MO4vzmq8TJJEkdmopxyazGDxN8ClqN12uzrZW9Tv8EED8v5VSb6Sqyi0pg==", "requires": { "@types/eslint-scope": "^3.7.3", "@types/estree": "^1.0.0", @@ -27041,10 +27041,10 @@ "@webassemblyjs/wasm-edit": "^1.11.5", "@webassemblyjs/wasm-parser": "^1.11.5", "acorn": "^8.7.1", - "acorn-import-assertions": "^1.7.6", + "acorn-import-assertions": "^1.9.0", "browserslist": "^4.14.5", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.13.0", + "enhanced-resolve": "^5.14.1", "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", diff --git a/docs/package.json b/docs/package.json index 15d5aa38eea..d82e54ec8c9 100644 --- a/docs/package.json +++ b/docs/package.json @@ -61,6 +61,6 @@ "prettier": "^2.8.7", "string-replace-loader": "^3.1.0", "typescript": "^5.0.4", - "webpack": "^5.80.0" + "webpack": "^5.86.0" } } From 9ff1eaeb5a5f892d17ca87c38697466fd48fc301 Mon Sep 17 00:00:00 2001 From: Joel Spadin Date: Sun, 14 May 2023 11:44:49 -0500 Subject: [PATCH 16/76] fix: Enable BT_TINYCRYPT_ECC when using HCI BT_TINYCRYPT_ECC is required for BT_SMP_SC_PAIR_ONLY to work on setups that use BT HCI like the nRF5340. --- app/Kconfig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/Kconfig b/app/Kconfig index 1537bd61512..18ee473d5db 100644 --- a/app/Kconfig +++ b/app/Kconfig @@ -120,6 +120,10 @@ menuconfig ZMK_BLE if ZMK_BLE +# BT_TINYCRYPT_ECC is required for BT_SMP_SC_PAIR_ONLY when using HCI +config BT_TINYCRYPT_ECC + default y if BT_HCI && !BT_CTLR + choice BT_LL_SW_LLCP_IMPL default BT_LL_SW_LLCP_LEGACY From dcf5e75fa674184d9615793882db1c3f4c4194b9 Mon Sep 17 00:00:00 2001 From: Joel Spadin Date: Sun, 14 May 2023 13:08:33 -0500 Subject: [PATCH 17/76] fix(boards): Bump nRF5340 DK I2C buffer size Increased the I2C buffer size again, since it needs to be at least 641 to support 128x64 displays. --- app/boards/nrf5340dk_nrf5340_cpuapp.overlay | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/boards/nrf5340dk_nrf5340_cpuapp.overlay b/app/boards/nrf5340dk_nrf5340_cpuapp.overlay index 66d2332f1a2..9427d9ca150 100644 --- a/app/boards/nrf5340dk_nrf5340_cpuapp.overlay +++ b/app/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -6,5 +6,5 @@ &arduino_i2c { // Default buffer size is too small for use with displays. - zephyr,concat-buf-size = <512>; + zephyr,concat-buf-size = <1024>; }; From 2244bd3d81931753dfd170e804a90a487a205aa1 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Wed, 1 Sep 2021 03:49:18 +0000 Subject: [PATCH 18/76] refactor(sensors): Sensor event channel data, resolution tweaks. * Refactor sensor events to include channel data, necessary for prop split encoders, and avoiding duplicate calls, to fetch channel data twice, etc. * More consistent behavior driver API. * Allow setting triggers per resolution at the behavior level optionally. --- app/Kconfig | 20 +++ app/dts/bindings/zmk,keymap-sensors.yaml | 12 +- app/include/drivers/behavior.h | 28 ++-- app/include/zmk/events/sensor_event.h | 17 ++- app/include/zmk/sensors.h | 14 ++ app/include/zmk/virtual_key_position.h | 5 + app/src/behaviors/behavior_sensor_rotate.c | 8 +- .../behaviors/behavior_sensor_rotate_common.c | 59 ++++++--- .../behaviors/behavior_sensor_rotate_common.h | 16 ++- .../behaviors/behavior_sensor_rotate_var.c | 6 +- app/src/keymap.c | 25 ++-- app/src/sensors.c | 123 +++++++++++++----- 12 files changed, 254 insertions(+), 79 deletions(-) diff --git a/app/Kconfig b/app/Kconfig index 18ee473d5db..1766bf07abe 100644 --- a/app/Kconfig +++ b/app/Kconfig @@ -194,6 +194,18 @@ rsource "src/split/Kconfig" #Basic Keyboard Setup endmenu +menu "Encoders" + +config ZMK_ENCODERS_DEFAULT_TRIGGERS_PER_ROTATION + int "Default behavior triggers per rotation" + help + Unless overridden for a specific behavior in the keymap/devicetree, this value + determines how many times to trigger the bound behavior per full rotation. + For tactile encoders with detents, this usually should match the number of + detents per rotation of the encoder. + default 30 + +endmenu menu "Display/LED Options" rsource "src/display/Kconfig" @@ -523,6 +535,14 @@ config ZMK_WPM config SENSOR default y +if ZMK_KEYMAP_SENSORS + +config ZMK_KEYMAP_SENSORS_DEFAULT_TRIGGERS_PER_ROTATION + int "Default triggers per rotation" + default 20 + +endif # ZMK_KEYMAP_SENSORS + choice CBPRINTF_IMPLEMENTATION default CBPRINTF_NANO diff --git a/app/dts/bindings/zmk,keymap-sensors.yaml b/app/dts/bindings/zmk,keymap-sensors.yaml index a879684f4f9..5282f25b04e 100644 --- a/app/dts/bindings/zmk,keymap-sensors.yaml +++ b/app/dts/bindings/zmk,keymap-sensors.yaml @@ -9,4 +9,14 @@ compatible: "zmk,keymap-sensors" properties: sensors: type: phandles - required: true + required: false + triggers-per-rotation: + type: int + required: false + +child-binding: + description: Per-sensor configuration settings + properties: + triggers-per-rotation: + type: int + required: false diff --git a/app/include/drivers/behavior.h b/app/include/drivers/behavior.h index 380fc76f9ba..0aa5d85e79a 100644 --- a/app/include/drivers/behavior.h +++ b/app/include/drivers/behavior.h @@ -12,6 +12,7 @@ #include #include #include +#include #include /** @@ -24,9 +25,10 @@ typedef int (*behavior_keymap_binding_callback_t)(struct zmk_behavior_binding *binding, struct zmk_behavior_binding_event event); -typedef int (*behavior_sensor_keymap_binding_callback_t)(struct zmk_behavior_binding *binding, - const struct device *sensor, - struct zmk_behavior_binding_event event); +typedef int (*behavior_sensor_keymap_binding_callback_t)( + struct zmk_behavior_binding *binding, struct zmk_behavior_binding_event event, + const struct zmk_sensor_config *sensor_config, size_t channel_data_size, + const struct zmk_sensor_channel_data channel_data[channel_data_size]); enum behavior_locality { BEHAVIOR_LOCALITY_CENTRAL, @@ -158,14 +160,15 @@ static inline int z_impl_behavior_keymap_binding_released(struct zmk_behavior_bi * @retval 0 If successful. * @retval Negative errno code if failure. */ -__syscall int behavior_sensor_keymap_binding_triggered(struct zmk_behavior_binding *binding, - const struct device *sensor, - struct zmk_behavior_binding_event event); - -static inline int -z_impl_behavior_sensor_keymap_binding_triggered(struct zmk_behavior_binding *binding, - const struct device *sensor, - struct zmk_behavior_binding_event event) { +__syscall int behavior_sensor_keymap_binding_triggered( + struct zmk_behavior_binding *binding, struct zmk_behavior_binding_event event, + const struct zmk_sensor_config *sensor_config, size_t channel_data_size, + const struct zmk_sensor_channel_data *channel_data); + +static inline int z_impl_behavior_sensor_keymap_binding_triggered( + struct zmk_behavior_binding *binding, struct zmk_behavior_binding_event event, + const struct zmk_sensor_config *sensor_config, size_t channel_data_size, + const struct zmk_sensor_channel_data *channel_data) { const struct device *dev = device_get_binding(binding->behavior_dev); if (dev == NULL) { @@ -178,7 +181,8 @@ z_impl_behavior_sensor_keymap_binding_triggered(struct zmk_behavior_binding *bin return -ENOTSUP; } - return api->sensor_binding_triggered(binding, sensor, event); + return api->sensor_binding_triggered(binding, event, sensor_config, channel_data_size, + channel_data); } /** diff --git a/app/include/zmk/events/sensor_event.h b/app/include/zmk/events/sensor_event.h index 9398bcbb713..5a5aa3ac711 100644 --- a/app/include/zmk/events/sensor_event.h +++ b/app/include/zmk/events/sensor_event.h @@ -6,12 +6,21 @@ #pragma once -#include + +#include #include -#include +#include +#include + +// TODO: Move to Kconfig when we need more than one channel +#define ZMK_SENSOR_EVENT_MAX_CHANNELS 1 + struct zmk_sensor_event { - uint8_t sensor_number; - const struct device *sensor; + uint8_t sensor_position; + + size_t channel_data_size; + struct zmk_sensor_channel_data channel_data[ZMK_SENSOR_EVENT_MAX_CHANNELS]; + int64_t timestamp; }; diff --git a/app/include/zmk/sensors.h b/app/include/zmk/sensors.h index 9e54695fc19..41061127981 100644 --- a/app/include/zmk/sensors.h +++ b/app/include/zmk/sensors.h @@ -6,6 +6,9 @@ #pragma once +#include + +#define _SENSOR_CHILD_LEN(node) 1 + #define ZMK_KEYMAP_SENSORS_NODE DT_INST(0, zmk_keymap_sensors) #define ZMK_KEYMAP_HAS_SENSORS DT_NODE_HAS_STATUS(ZMK_KEYMAP_SENSORS_NODE, okay) #define ZMK_KEYMAP_SENSORS_BY_IDX(idx) DT_PHANDLE_BY_IDX(ZMK_KEYMAP_SENSORS_NODE, sensors, idx) @@ -15,3 +18,14 @@ #else #define ZMK_KEYMAP_SENSORS_LEN 0 #endif + +const struct zmk_sensor_config *zmk_sensors_get_config_at_position(uint8_t sensor_position); + +struct zmk_sensor_config { + uint16_t triggers_per_rotation; +}; + +struct zmk_sensor_channel_data { + enum sensor_channel channel; + struct sensor_value value; +}; diff --git a/app/include/zmk/virtual_key_position.h b/app/include/zmk/virtual_key_position.h index 48deee5c6c8..b8f20683d7b 100644 --- a/app/include/zmk/virtual_key_position.h +++ b/app/include/zmk/virtual_key_position.h @@ -14,6 +14,11 @@ */ #define ZMK_VIRTUAL_KEY_POSITION_SENSOR(index) (ZMK_KEYMAP_LEN + (index)) +/** + * Gets the sensor number from the virtual key position. + */ +#define ZMK_SENSOR_POSITION_FROM_VIRTUAL_KEY_POSITION(vkp) ((vkp)-ZMK_KEYMAP_LEN) + /** * Gets the virtual key position to use for the combo with the given index. */ diff --git a/app/src/behaviors/behavior_sensor_rotate.c b/app/src/behaviors/behavior_sensor_rotate.c index e12278bba1a..86846d5be0b 100644 --- a/app/src/behaviors/behavior_sensor_rotate.c +++ b/app/src/behaviors/behavior_sensor_rotate.c @@ -33,8 +33,10 @@ static int behavior_sensor_rotate_init(const struct device *dev) { return 0; }; .tap_ms = DT_INST_PROP_OR(n, tap_ms, 5), \ .override_params = false, \ }; \ - DEVICE_DT_INST_DEFINE( \ - n, behavior_sensor_rotate_init, NULL, NULL, &behavior_sensor_rotate_config_##n, \ - APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_sensor_rotate_driver_api); + static struct behavior_sensor_rotate_data behavior_sensor_rotate_data_##n = {}; \ + DEVICE_DT_INST_DEFINE(n, behavior_sensor_rotate_init, NULL, &behavior_sensor_rotate_data_##n, \ + &behavior_sensor_rotate_config_##n, APPLICATION, \ + CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \ + &behavior_sensor_rotate_driver_api); DT_INST_FOREACH_STATUS_OKAY(SENSOR_ROTATE_INST) diff --git a/app/src/behaviors/behavior_sensor_rotate_common.c b/app/src/behaviors/behavior_sensor_rotate_common.c index bd31170eda0..99e4e019ba1 100644 --- a/app/src/behaviors/behavior_sensor_rotate_common.c +++ b/app/src/behaviors/behavior_sensor_rotate_common.c @@ -5,48 +5,75 @@ #include #include +#include #include "behavior_sensor_rotate_common.h" LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); int zmk_behavior_sensor_rotate_common_trigger(struct zmk_behavior_binding *binding, - const struct device *sensor, - struct zmk_behavior_binding_event event) { + struct zmk_behavior_binding_event event, + const struct zmk_sensor_config *sensor_config, + size_t channel_data_size, + const struct zmk_sensor_channel_data *channel_data) { const struct device *dev = device_get_binding(binding->behavior_dev); const struct behavior_sensor_rotate_config *cfg = dev->config; + struct behavior_sensor_rotate_data *data = dev->data; - struct sensor_value value; + const struct sensor_value value = channel_data[0].value; + int triggers; + int sensor_position = ZMK_SENSOR_POSITION_FROM_VIRTUAL_KEY_POSITION(event.position); - const int err = sensor_channel_get(sensor, SENSOR_CHAN_ROTATION, &value); + // Some funky special casing for "old encoder behavior" where ticks where reported in val2 only, + // instead of rotational degrees in val1. + // REMOVE ME: Remove after a grace period of old ec11 sensor behavior + if (value.val1 == 0) { + triggers = value.val2; + } else { + struct sensor_value remainder = data->remainder[sensor_position]; - if (err < 0) { - LOG_WRN("Failed to get sensor rotation value: %d", err); - return err; + remainder.val1 += value.val1; + remainder.val2 += value.val2; + + if (remainder.val2 >= 1000000 || remainder.val2 <= 1000000) { + remainder.val1 += remainder.val2 / 1000000; + remainder.val2 %= 1000000; + } + + int trigger_degrees = 360 / sensor_config->triggers_per_rotation; + triggers = remainder.val1 / trigger_degrees; + remainder.val1 %= trigger_degrees; + + data->remainder[sensor_position] = remainder; } + LOG_DBG( + "val1: %d, val2: %d, remainder: %d/%d triggers: %d inc keycode 0x%02X dec keycode 0x%02X", + value.val1, value.val2, data->remainder[sensor_position].val1, + data->remainder[sensor_position].val2, triggers, binding->param1, binding->param2); + struct zmk_behavior_binding triggered_binding; - switch (value.val1) { - case 1: + if (triggers > 0) { triggered_binding = cfg->cw_binding; if (cfg->override_params) { triggered_binding.param1 = binding->param1; } - break; - case -1: + } else if (triggers < 0) { + triggers = -triggers; triggered_binding = cfg->ccw_binding; if (cfg->override_params) { triggered_binding.param1 = binding->param2; } - break; - default: - return -ENOTSUP; + } else { + return 0; } LOG_DBG("Sensor binding: %s", binding->behavior_dev); - zmk_behavior_queue_add(event.position, triggered_binding, true, cfg->tap_ms); - zmk_behavior_queue_add(event.position, triggered_binding, false, 0); + for (int i = 0; i < triggers; i++) { + zmk_behavior_queue_add(event.position, triggered_binding, true, cfg->tap_ms); + zmk_behavior_queue_add(event.position, triggered_binding, false, 0); + } return ZMK_BEHAVIOR_OPAQUE; } diff --git a/app/src/behaviors/behavior_sensor_rotate_common.h b/app/src/behaviors/behavior_sensor_rotate_common.h index 2d58218d8ad..eab443a3987 100644 --- a/app/src/behaviors/behavior_sensor_rotate_common.h +++ b/app/src/behaviors/behavior_sensor_rotate_common.h @@ -1,5 +1,11 @@ +/* + * Copyright (c) 2023 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ #include +#include struct behavior_sensor_rotate_config { struct zmk_behavior_binding cw_binding; @@ -8,6 +14,12 @@ struct behavior_sensor_rotate_config { bool override_params; }; +struct behavior_sensor_rotate_data { + struct sensor_value remainder[ZMK_KEYMAP_SENSORS_LEN]; +}; + int zmk_behavior_sensor_rotate_common_trigger(struct zmk_behavior_binding *binding, - const struct device *sensor, - struct zmk_behavior_binding_event event); \ No newline at end of file + struct zmk_behavior_binding_event event, + const struct zmk_sensor_config *sensor_config, + size_t channel_data_size, + const struct zmk_sensor_channel_data *channel_data); \ No newline at end of file diff --git a/app/src/behaviors/behavior_sensor_rotate_var.c b/app/src/behaviors/behavior_sensor_rotate_var.c index a82267a55e9..95bb99610ba 100644 --- a/app/src/behaviors/behavior_sensor_rotate_var.c +++ b/app/src/behaviors/behavior_sensor_rotate_var.c @@ -24,8 +24,10 @@ static int behavior_sensor_rotate_var_init(const struct device *dev) { return 0; .tap_ms = DT_INST_PROP(n, tap_ms), \ .override_params = true, \ }; \ + static struct behavior_sensor_rotate_data behavior_sensor_rotate_var_data_##n = {}; \ DEVICE_DT_INST_DEFINE( \ - n, behavior_sensor_rotate_var_init, NULL, NULL, &behavior_sensor_rotate_var_config_##n, \ - APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_sensor_rotate_var_driver_api); + n, behavior_sensor_rotate_var_init, NULL, &behavior_sensor_rotate_var_data_##n, \ + &behavior_sensor_rotate_var_config_##n, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \ + &behavior_sensor_rotate_var_driver_api); DT_INST_FOREACH_STATUS_OKAY(SENSOR_ROTATE_VAR_INST) diff --git a/app/src/keymap.c b/app/src/keymap.c index da25fc096ca..16543d37840 100644 --- a/app/src/keymap.c +++ b/app/src/keymap.c @@ -252,27 +252,34 @@ int zmk_keymap_position_state_changed(uint8_t source, uint32_t position, bool pr } #if ZMK_KEYMAP_HAS_SENSORS -int zmk_keymap_sensor_triggered(uint8_t sensor_number, const struct device *sensor, - int64_t timestamp) { +int zmk_keymap_sensor_triggered( + uint8_t sensor_position, size_t channel_data_size, + const struct zmk_sensor_channel_data channel_data[channel_data_size], int64_t timestamp) { for (int layer = ZMK_KEYMAP_LAYERS_LEN - 1; layer >= _zmk_keymap_layer_default; layer--) { if (zmk_keymap_layer_active(layer)) { - struct zmk_behavior_binding *binding = &zmk_sensor_keymap[layer][sensor_number]; + struct zmk_behavior_binding *binding = &zmk_sensor_keymap[layer][sensor_position]; const struct device *behavior; int ret; - LOG_DBG("layer: %d sensor_number: %d, binding name: %s", layer, sensor_number, + LOG_DBG("layer: %d sensor_position: %d, binding name: %s", layer, sensor_position, binding->behavior_dev); behavior = device_get_binding(binding->behavior_dev); if (!behavior) { - LOG_DBG("No behavior assigned to %d on layer %d", sensor_number, layer); + LOG_DBG("No behavior assigned to %d on layer %d", sensor_position, layer); continue; } struct zmk_behavior_binding_event event = { - .position = ZMK_VIRTUAL_KEY_POSITION_SENSOR(sensor_number), .timestamp = timestamp}; - ret = behavior_sensor_keymap_binding_triggered(binding, sensor, event); + .layer = layer, + .position = ZMK_VIRTUAL_KEY_POSITION_SENSOR(sensor_position), + .timestamp = timestamp, + }; + + ret = behavior_sensor_keymap_binding_triggered( + binding, event, zmk_sensors_get_config_at_position(sensor_position), + channel_data_size, channel_data); if (ret > 0) { LOG_DBG("behavior processing to continue to next layer"); @@ -301,8 +308,8 @@ int keymap_listener(const zmk_event_t *eh) { #if ZMK_KEYMAP_HAS_SENSORS const struct zmk_sensor_event *sensor_ev; if ((sensor_ev = as_zmk_sensor_event(eh)) != NULL) { - return zmk_keymap_sensor_triggered(sensor_ev->sensor_number, sensor_ev->sensor, - sensor_ev->timestamp); + return zmk_keymap_sensor_triggered(sensor_ev->sensor_position, sensor_ev->channel_data_size, + sensor_ev->channel_data, sensor_ev->timestamp); } #endif /* ZMK_KEYMAP_HAS_SENSORS */ diff --git a/app/src/sensors.c b/app/src/sensors.c index 1b92147f8ca..5f41c4f2f20 100644 --- a/app/src/sensors.c +++ b/app/src/sensors.c @@ -18,65 +18,128 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #if ZMK_KEYMAP_HAS_SENSORS -struct sensors_data_item { - uint8_t sensor_number; +struct sensors_item_cfg { + uint8_t sensor_position; + const struct zmk_sensor_config *config; const struct device *dev; struct sensor_trigger trigger; }; -#define _SENSOR_ITEM(node) \ +#define _SENSOR_ITEM(idx, node) \ { \ - .dev = NULL, .trigger = {.type = SENSOR_TRIG_DELTA, .chan = SENSOR_CHAN_ROTATION } \ + .dev = DEVICE_DT_GET_OR_NULL(node), \ + .trigger = {.type = SENSOR_TRIG_DATA_READY, .chan = SENSOR_CHAN_ROTATION}, \ + .config = &configs[idx] \ } +#define SENSOR_ITEM(idx, _i) _SENSOR_ITEM(idx, ZMK_KEYMAP_SENSORS_BY_IDX(idx)) -#define SENSOR_ITEM(idx, _node) \ - COND_CODE_1(DT_NODE_HAS_STATUS(ZMK_KEYMAP_SENSORS_BY_IDX(idx), okay), \ - (_SENSOR_ITEM(ZMK_KEYMAP_SENSORS_BY_IDX(idx))), ({})) +#define PLUS_ONE(n) +1 +#define ZMK_KEYMAP_SENSORS_CHILD_COUNT (0 DT_FOREACH_CHILD(ZMK_KEYMAP_SENSORS_NODE, PLUS_ONE)) +#define SENSOR_CHILD_ITEM(node) \ + { \ + .triggers_per_rotation = \ + DT_PROP_OR(node, triggers_per_rotation, \ + DT_PROP_OR(ZMK_KEYMAP_SENSORS_NODE, triggers_per_rotation, \ + CONFIG_ZMK_KEYMAP_SENSORS_DEFAULT_TRIGGERS_PER_ROTATION)) \ + } +#define SENSOR_CHILD_DEFAULTS(idx, arg) \ + { .triggers_per_rotation = DT_PROP_OR(ZMK_KEYMAP_SENSORS_NODE, triggers_per_rotation, 20) } + +static struct zmk_sensor_config configs[] = { +#if ZMK_KEYMAP_SENSORS_CHILD_COUNT > 0 + DT_FOREACH_CHILD_SEP(ZMK_KEYMAP_SENSORS_NODE, SENSOR_CHILD_ITEM, (, )) +#else + LISTIFY(ZMK_KEYMAP_SENSORS_LEN, SENSOR_CHILD_DEFAULTS, (, ), 0) +#endif +}; -static struct sensors_data_item sensors[] = {LISTIFY(ZMK_KEYMAP_SENSORS_LEN, SENSOR_ITEM, (, ), 0)}; +static struct sensors_item_cfg sensors[] = {LISTIFY(ZMK_KEYMAP_SENSORS_LEN, SENSOR_ITEM, (, ), 0)}; -static void zmk_sensors_trigger_handler(const struct device *dev, - const struct sensor_trigger *trigger) { - int err; - const struct sensors_data_item *item = CONTAINER_OF(trigger, struct sensors_data_item, trigger); +static ATOMIC_DEFINE(pending_sensors, ZMK_KEYMAP_SENSORS_LEN); + +const struct zmk_sensor_config *zmk_sensors_get_config_at_position(uint8_t sensor_position) { + if (sensor_position > ARRAY_SIZE(configs)) { + return NULL; + } - LOG_DBG("sensor %d", item->sensor_number); + return &configs[sensor_position]; +} - err = sensor_sample_fetch(dev); +static void trigger_sensor_data_for_position(uint32_t sensor_position) { + int err; + const struct sensors_item_cfg *item = &sensors[sensor_position]; + + err = sensor_sample_fetch(item->dev); if (err) { LOG_WRN("Failed to fetch sample from device %d", err); return; } - ZMK_EVENT_RAISE(new_zmk_sensor_event((struct zmk_sensor_event){ - .sensor_number = item->sensor_number, .sensor = dev, .timestamp = k_uptime_get()})); + struct sensor_value value; + err = sensor_channel_get(item->dev, item->trigger.chan, &value); + + if (err) { + LOG_WRN("Failed to get channel data from device %d", err); + return; + } + + ZMK_EVENT_RAISE(new_zmk_sensor_event( + (struct zmk_sensor_event){.sensor_position = item->sensor_position, + .channel_data = {(struct zmk_sensor_channel_data){ + .value = value, .channel = item->trigger.chan}}, + .timestamp = k_uptime_get()})); } -static void zmk_sensors_init_item(const char *node, uint8_t i, uint8_t abs_i) { - LOG_DBG("Init %s at index %d with sensor_number %d", node, i, abs_i); +static void run_sensors_data_trigger(struct k_work *work) { + for (int i = 0; i < ARRAY_SIZE(sensors); i++) { + if (atomic_test_and_clear_bit(pending_sensors, i)) { + trigger_sensor_data_for_position(i); + } + } +} + +K_WORK_DEFINE(sensor_data_work, run_sensors_data_trigger); + +static void zmk_sensors_trigger_handler(const struct device *dev, + const struct sensor_trigger *trigger) { + const struct sensors_item_cfg *test_item = + CONTAINER_OF(trigger, struct sensors_item_cfg, trigger); + int sensor_index = test_item - sensors; + + if (sensor_index < 0 || sensor_index >= ARRAY_SIZE(sensors)) { + LOG_ERR("Invalid sensor item triggered our callback"); + return; + } - sensors[i].dev = device_get_binding(node); - sensors[i].sensor_number = abs_i; + if (k_is_in_isr()) { + atomic_set_bit(pending_sensors, sensor_index); + k_work_submit(&sensor_data_work); + } else { + trigger_sensor_data_for_position(sensor_index); + } +} + +static void zmk_sensors_init_item(uint8_t i) { + LOG_DBG("Init sensor at index %d", i); + + sensors[i].sensor_position = i; if (!sensors[i].dev) { - LOG_WRN("Failed to find device for %s", node); + LOG_DBG("No local device for %d", i); return; } - sensor_trigger_set(sensors[i].dev, &sensors[i].trigger, zmk_sensors_trigger_handler); + int err = sensor_trigger_set(sensors[i].dev, &sensors[i].trigger, zmk_sensors_trigger_handler); + if (err) { + LOG_WRN("Failed to set sensor trigger (%d)", err); + } } -#define _SENSOR_INIT(node) \ - zmk_sensors_init_item(DT_PROP(node, label), local_index++, absolute_index++); -#define SENSOR_INIT(idx, _i) \ - COND_CODE_1(DT_NODE_HAS_STATUS(ZMK_KEYMAP_SENSORS_BY_IDX(idx), okay), \ - (_SENSOR_INIT(ZMK_KEYMAP_SENSORS_BY_IDX(idx))), (absolute_index++;)) +#define SENSOR_INIT(idx, _t) zmk_sensors_init_item(idx); static int zmk_sensors_init(const struct device *_arg) { - int local_index = 0; - int absolute_index = 0; - LISTIFY(ZMK_KEYMAP_SENSORS_LEN, SENSOR_INIT, (), 0) + return 0; } From 295ed83409ab0bede761eb2e51f4e4670e4dbf08 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Thu, 2 Dec 2021 15:07:29 +0000 Subject: [PATCH 19/76] refactor(sensors): ec11 rotation sensor value in degrees. * Add new `steps` property to the `aips,ec11` binding, to make the driver properly report degrees in the rotation delta channel. * Handle old sensor values in sensor rotate behavior. --- app/drivers/sensor/ec11/Kconfig | 2 ++ app/drivers/sensor/ec11/ec11.c | 33 +++++++++++++++---- app/drivers/sensor/ec11/ec11.h | 1 + .../zephyr/dts/bindings/sensor/alps,ec11.yaml | 5 +++ app/include/zmk/events/sensor_event.h | 4 +-- app/include/zmk/sensors.h | 2 +- 6 files changed, 38 insertions(+), 9 deletions(-) diff --git a/app/drivers/sensor/ec11/Kconfig b/app/drivers/sensor/ec11/Kconfig index e86d092a127..5da327280a8 100644 --- a/app/drivers/sensor/ec11/Kconfig +++ b/app/drivers/sensor/ec11/Kconfig @@ -3,6 +3,8 @@ menuconfig EC11 bool "EC11 Incremental Encoder Sensor" + default y + depends on DT_HAS_ALPS_EC11_ENABLED depends on GPIO help Enable driver for EC11 incremental encoder sensors. diff --git a/app/drivers/sensor/ec11/ec11.c b/app/drivers/sensor/ec11/ec11.c index 7091f73e739..ee8b41e74c8 100644 --- a/app/drivers/sensor/ec11/ec11.c +++ b/app/drivers/sensor/ec11/ec11.c @@ -16,6 +16,8 @@ #include "ec11.h" +#define FULL_ROTATION 360 + LOG_MODULE_REGISTER(EC11, CONFIG_SENSOR_LOG_LEVEL); static int ec11_get_ab_state(const struct device *dev) { @@ -59,9 +61,14 @@ static int ec11_sample_fetch(const struct device *dev, enum sensor_channel chan) drv_data->pulses += delta; drv_data->ab_state = val; - drv_data->ticks = drv_data->pulses / drv_cfg->resolution; - drv_data->delta = delta; - drv_data->pulses %= drv_cfg->resolution; + // TODO: Temporary code for backwards compatibility to support + // the sensor channel rotation reporting *ticks* instead of delta of degrees. + // REMOVE ME + if (drv_cfg->steps == 0) { + drv_data->ticks = drv_data->pulses / drv_cfg->resolution; + drv_data->delta = delta; + drv_data->pulses %= drv_cfg->resolution; + } return 0; } @@ -69,13 +76,26 @@ static int ec11_sample_fetch(const struct device *dev, enum sensor_channel chan) static int ec11_channel_get(const struct device *dev, enum sensor_channel chan, struct sensor_value *val) { struct ec11_data *drv_data = dev->data; + const struct ec11_config *drv_cfg = dev->config; + int32_t pulses = drv_data->pulses; if (chan != SENSOR_CHAN_ROTATION) { return -ENOTSUP; } - val->val1 = drv_data->ticks; - val->val2 = drv_data->delta; + drv_data->pulses = 0; + + if (drv_cfg->steps > 0) { + val->val1 = (pulses * FULL_ROTATION) / drv_cfg->steps; + val->val2 = (pulses * FULL_ROTATION) % drv_cfg->steps; + if (val->val2 != 0) { + val->val2 *= 1000000; + val->val2 /= drv_cfg->steps; + } + } else { + val->val1 = drv_data->ticks; + val->val2 = drv_data->delta; + } return 0; } @@ -132,7 +152,8 @@ int ec11_init(const struct device *dev) { const struct ec11_config ec11_cfg_##n = { \ .a = GPIO_DT_SPEC_INST_GET(n, a_gpios), \ .b = GPIO_DT_SPEC_INST_GET(n, b_gpios), \ - COND_CODE_0(DT_INST_NODE_HAS_PROP(n, resolution), (1), (DT_INST_PROP(n, resolution))), \ + .resolution = DT_INST_PROP_OR(n, resolution, 1), \ + .steps = DT_INST_PROP_OR(n, steps, 0), \ }; \ DEVICE_DT_INST_DEFINE(n, ec11_init, NULL, &ec11_data_##n, &ec11_cfg_##n, POST_KERNEL, \ CONFIG_SENSOR_INIT_PRIORITY, &ec11_driver_api); diff --git a/app/drivers/sensor/ec11/ec11.h b/app/drivers/sensor/ec11/ec11.h index 82c21572329..4e2e5d2641c 100644 --- a/app/drivers/sensor/ec11/ec11.h +++ b/app/drivers/sensor/ec11/ec11.h @@ -14,6 +14,7 @@ struct ec11_config { const struct gpio_dt_spec a; const struct gpio_dt_spec b; + const uint16_t steps; const uint8_t resolution; }; diff --git a/app/drivers/zephyr/dts/bindings/sensor/alps,ec11.yaml b/app/drivers/zephyr/dts/bindings/sensor/alps,ec11.yaml index 5cbe77a2ad0..3672ea30579 100644 --- a/app/drivers/zephyr/dts/bindings/sensor/alps,ec11.yaml +++ b/app/drivers/zephyr/dts/bindings/sensor/alps,ec11.yaml @@ -18,4 +18,9 @@ properties: resolution: type: int description: Number of pulses per tick + deprecated: true + required: false + steps: + type: int + description: Number of pulses in one full rotation required: false diff --git a/app/include/zmk/events/sensor_event.h b/app/include/zmk/events/sensor_event.h index 5a5aa3ac711..c5157447dd4 100644 --- a/app/include/zmk/events/sensor_event.h +++ b/app/include/zmk/events/sensor_event.h @@ -6,11 +6,11 @@ #pragma once - +#include #include + #include #include -#include // TODO: Move to Kconfig when we need more than one channel #define ZMK_SENSOR_EVENT_MAX_CHANNELS 1 diff --git a/app/include/zmk/sensors.h b/app/include/zmk/sensors.h index 41061127981..06fbc63e564 100644 --- a/app/include/zmk/sensors.h +++ b/app/include/zmk/sensors.h @@ -6,7 +6,7 @@ #pragma once -#include +#include #define _SENSOR_CHILD_LEN(node) 1 + #define ZMK_KEYMAP_SENSORS_NODE DT_INST(0, zmk_keymap_sensors) From f0f7e2081b5a4aa5bc35d7d8855b0e73e962319b Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Thu, 26 May 2022 16:53:41 +0000 Subject: [PATCH 20/76] refactor(config): Select SENSOR as needed. * Don't force on SENSOR Kconfig setting unless needed based on the detected DT. --- app/Kconfig | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/Kconfig b/app/Kconfig index 1766bf07abe..5b313effcdc 100644 --- a/app/Kconfig +++ b/app/Kconfig @@ -532,8 +532,11 @@ config ZMK_WPM bool "Calculate WPM" default n -config SENSOR +config ZMK_KEYMAP_SENSORS + bool "Enable Keymap Sensors support" default y + depends on DT_HAS_ZMK_KEYMAP_SENSORS_ENABLED + select SENSOR if ZMK_KEYMAP_SENSORS From 621d946d2926f28aa866947f110182726fa9ca10 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Sun, 21 May 2023 21:27:41 -0700 Subject: [PATCH 21/76] refactor(bluetooth): Bump HoG stack size. * Bump the default stack size for the HoG processing thread to avoid issues w/ some pathways. --- app/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Kconfig b/app/Kconfig index 5b313effcdc..a54ad38967d 100644 --- a/app/Kconfig +++ b/app/Kconfig @@ -135,7 +135,7 @@ config SYSTEM_WORKQUEUE_STACK_SIZE config ZMK_BLE_THREAD_STACK_SIZE int "BLE notify thread stack size" - default 512 + default 768 config ZMK_BLE_THREAD_PRIORITY int "BLE notify thread priority" From f8aaaff556e1c43c6646ea1c1ee7faa2907cdf51 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Sun, 16 Apr 2023 08:18:57 +0000 Subject: [PATCH 22/76] refactor(shields): Updated ZMK Uno encoder config. * Move to new steps/triggers-per-rotation config. * Leverage QDEC Nordic driver when used on Nordic DK. --- .../boards/nrf52840dk_nrf52840.overlay | 24 +++++++++ app/boards/shields/zmk_uno/zmk_uno.overlay | 49 ++++++++++--------- 2 files changed, 50 insertions(+), 23 deletions(-) create mode 100644 app/boards/shields/zmk_uno/boards/nrf52840dk_nrf52840.overlay diff --git a/app/boards/shields/zmk_uno/boards/nrf52840dk_nrf52840.overlay b/app/boards/shields/zmk_uno/boards/nrf52840dk_nrf52840.overlay new file mode 100644 index 00000000000..5ac7af7c532 --- /dev/null +++ b/app/boards/shields/zmk_uno/boards/nrf52840dk_nrf52840.overlay @@ -0,0 +1,24 @@ + +/ { + // First, delete the existing basic GPIO based instance. + /delete-node/ encoder; +}; + +&pinctrl { + qdec_default: qdec_default { + group1 { + psels = , + ; + bias-pull-up; + }; + }; +}; + +// Set up the QDEC hardware based driver and give it the same label as the deleted node. +encoder: &qdec0 { + status = "okay"; + led-pre = <0>; + steps = <80>; + pinctrl-0 = <&qdec_default>; + pinctrl-names = "default"; +}; diff --git a/app/boards/shields/zmk_uno/zmk_uno.overlay b/app/boards/shields/zmk_uno/zmk_uno.overlay index 04332911e9b..78f3b4a7146 100644 --- a/app/boards/shields/zmk_uno/zmk_uno.overlay +++ b/app/boards/shields/zmk_uno/zmk_uno.overlay @@ -40,10 +40,10 @@ // Commented out until we add more powerful power domain support // external_power { - // compatible = "zmk,ext-power-generic"; - // label = "EXT_POWER"; - // init-delay-ms = <200>; - // control-gpios = <&arduino_header 1 GPIO_ACTIVE_LOW>; + // compatible = "zmk,ext-power-generic"; + // label = "EXT_POWER"; + // init-delay-ms = <200>; + // control-gpios = <&arduino_header 1 GPIO_ACTIVE_LOW>; // }; rgb_power { @@ -128,14 +128,14 @@ diode-direction = "col2row"; col-gpios - = <&arduino_header 10 GPIO_ACTIVE_HIGH> - , <&arduino_header 9 GPIO_ACTIVE_HIGH> - ; + = <&arduino_header 10 GPIO_ACTIVE_HIGH> + , <&arduino_header 9 GPIO_ACTIVE_HIGH> + ; row-gpios - = <&arduino_header 13 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> - , <&arduino_header 11 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> - ; + = <&arduino_header 13 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> + , <&arduino_header 11 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> + ; }; @@ -144,11 +144,11 @@ status = "disabled"; input-gpios - = <&arduino_header 10 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)> - , <&arduino_header 9 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)> - , <&arduino_header 13 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)> - , <&arduino_header 11 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)> - ; + = <&arduino_header 10 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)> + , <&arduino_header 9 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)> + , <&arduino_header 13 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)> + , <&arduino_header 11 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)> + ; }; @@ -157,23 +157,26 @@ toggle-mode; input-gpios - = <&arduino_header 4 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)> - , <&arduino_header 3 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)> - , <&arduino_header 2 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)> - ; + = <&arduino_header 4 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)> + , <&arduino_header 3 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)> + , <&arduino_header 2 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)> + ; }; encoder: encoder { label = "ENCODER"; - resolution = <4>; + steps = <80>; compatible = "alps,ec11"; - a-gpios = <&arduino_header 14 GPIO_PULL_UP>; - b-gpios = <&arduino_header 15 GPIO_PULL_UP>; + a-gpios = <&arduino_header 15 GPIO_PULL_UP>; + b-gpios = <&arduino_header 14 GPIO_PULL_UP>; }; - sensors { compatible = "zmk,keymap-sensors"; sensors = <&encoder>; + triggers-per-rotation = <20>; + left { + triggers-per-rotation = <20>; + }; }; }; From d781ec795b9d9e053ce71c30450ba2b979eab43b Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Tue, 18 Apr 2023 07:14:18 +0000 Subject: [PATCH 23/76] refactor(bluetooth): Add battery reporting config. * Add dedicated battery reporting Kconfig that is `imply`d by enabling ZMK_BLE. --- app/CMakeLists.txt | 4 ++-- app/Kconfig | 8 +++++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index a647e88363f..ea3b8f73364 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -77,8 +77,8 @@ endif() target_sources_ifdef(CONFIG_ZMK_RGB_UNDERGLOW app PRIVATE src/behaviors/behavior_rgb_underglow.c) target_sources_ifdef(CONFIG_ZMK_BACKLIGHT app PRIVATE src/behaviors/behavior_backlight.c) -target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/events/battery_state_changed.c) -target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/battery.c) +target_sources_ifdef(CONFIG_ZMK_BATTERY_REPORTING app PRIVATE src/events/battery_state_changed.c) +target_sources_ifdef(CONFIG_ZMK_BATTERY_REPORTING app PRIVATE src/battery.c) target_sources_ifdef(CONFIG_ZMK_SPLIT app PRIVATE src/events/split_peripheral_status_changed.c) add_subdirectory(src/split) diff --git a/app/Kconfig b/app/Kconfig index a54ad38967d..9c0606b02fc 100644 --- a/app/Kconfig +++ b/app/Kconfig @@ -114,9 +114,9 @@ menuconfig ZMK_BLE select BT_SMP_APP_PAIRING_ACCEPT select BT_PERIPHERAL select BT_DIS - select BT_BAS select BT_SETTINGS select SETTINGS + imply ZMK_BATTERY_REPORTING if ZMK_BLE @@ -322,6 +322,12 @@ endmenu menu "Power Management" +config ZMK_BATTERY_REPORTING + bool "Battery level detection/reporting" + default n + select SENSOR + select BT_BAS if ZMK_BLE + config ZMK_IDLE_TIMEOUT int "Milliseconds of inactivity before entering idle state (OLED shutoff, etc)" default 30000 From 8b29f6d34556d98df60f529e84ee66e49e6bf0c0 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Thu, 4 May 2023 00:04:20 +0000 Subject: [PATCH 24/76] refactor(sensors): Split data handling from triggers. * All sensor behaviors should see sensor data, then selectively only have some trigger their behaviors. --- app/include/drivers/behavior.h | 59 ++++++++++++-- app/src/behaviors/behavior_sensor_rotate.c | 3 +- .../behaviors/behavior_sensor_rotate_common.c | 31 +++++-- .../behaviors/behavior_sensor_rotate_common.h | 13 ++- .../behaviors/behavior_sensor_rotate_var.c | 3 +- app/src/keymap.c | 81 +++++++++++-------- 6 files changed, 135 insertions(+), 55 deletions(-) diff --git a/app/include/drivers/behavior.h b/app/include/drivers/behavior.h index 0aa5d85e79a..d7e57d02433 100644 --- a/app/include/drivers/behavior.h +++ b/app/include/drivers/behavior.h @@ -23,9 +23,17 @@ * (Internal use only.) */ +enum behavior_sensor_binding_process_mode { + BEHAVIOR_SENSOR_BINDING_PROCESS_MODE_TRIGGER, + BEHAVIOR_SENSOR_BINDING_PROCESS_MODE_DISCARD, +}; + typedef int (*behavior_keymap_binding_callback_t)(struct zmk_behavior_binding *binding, struct zmk_behavior_binding_event event); -typedef int (*behavior_sensor_keymap_binding_callback_t)( +typedef int (*behavior_sensor_keymap_binding_process_callback_t)( + struct zmk_behavior_binding *binding, struct zmk_behavior_binding_event event, + enum behavior_sensor_binding_process_mode mode); +typedef int (*behavior_sensor_keymap_binding_data_callback_t)( struct zmk_behavior_binding *binding, struct zmk_behavior_binding_event event, const struct zmk_sensor_config *sensor_config, size_t channel_data_size, const struct zmk_sensor_channel_data channel_data[channel_data_size]); @@ -41,7 +49,8 @@ __subsystem struct behavior_driver_api { behavior_keymap_binding_callback_t binding_convert_central_state_dependent_params; behavior_keymap_binding_callback_t binding_pressed; behavior_keymap_binding_callback_t binding_released; - behavior_sensor_keymap_binding_callback_t sensor_binding_triggered; + behavior_sensor_keymap_binding_data_callback_t sensor_binding_data; + behavior_sensor_keymap_binding_process_callback_t sensor_binding_process; }; /** * @endcond @@ -151,7 +160,7 @@ static inline int z_impl_behavior_keymap_binding_released(struct zmk_behavior_bi } /** - * @brief Handle the a sensor keymap binding being triggered + * @brief Handle the a sensor keymap binding processing any incoming data from the sensor * @param binding Sensor keymap binding which was triggered. * @param sensor Pointer to the sensor device structure for the sensor driver instance. * @param virtual_key_position ZMK_KEYMAP_LEN + sensor number @@ -160,12 +169,12 @@ static inline int z_impl_behavior_keymap_binding_released(struct zmk_behavior_bi * @retval 0 If successful. * @retval Negative errno code if failure. */ -__syscall int behavior_sensor_keymap_binding_triggered( +__syscall int behavior_sensor_keymap_binding_data( struct zmk_behavior_binding *binding, struct zmk_behavior_binding_event event, const struct zmk_sensor_config *sensor_config, size_t channel_data_size, const struct zmk_sensor_channel_data *channel_data); -static inline int z_impl_behavior_sensor_keymap_binding_triggered( +static inline int z_impl_behavior_sensor_keymap_binding_data( struct zmk_behavior_binding *binding, struct zmk_behavior_binding_event event, const struct zmk_sensor_config *sensor_config, size_t channel_data_size, const struct zmk_sensor_channel_data *channel_data) { @@ -177,12 +186,46 @@ static inline int z_impl_behavior_sensor_keymap_binding_triggered( const struct behavior_driver_api *api = (const struct behavior_driver_api *)dev->api; - if (api->sensor_binding_triggered == NULL) { + if (api->sensor_binding_data == NULL) { + return -ENOTSUP; + } + + return api->sensor_binding_data(binding, event, sensor_config, channel_data_size, channel_data); +} + +/** + * @brief Handle the keymap sensor binding being triggered after updating any local data + * @param dev Pointer to the device structure for the driver instance. + * @param param1 User parameter specified at time of behavior binding. + * @param param2 User parameter specified at time of behavior binding. + * + * @retval 0 If successful. + * @retval Negative errno code if failure. + */ +// clang-format off +__syscall int behavior_sensor_keymap_binding_process( + struct zmk_behavior_binding *binding, + struct zmk_behavior_binding_event event, + enum behavior_sensor_binding_process_mode mode); +// clang-format on + +static inline int +z_impl_behavior_sensor_keymap_binding_process(struct zmk_behavior_binding *binding, + struct zmk_behavior_binding_event event, + enum behavior_sensor_binding_process_mode mode) { + const struct device *dev = device_get_binding(binding->behavior_dev); + + if (dev == NULL) { + return -EINVAL; + } + + const struct behavior_driver_api *api = (const struct behavior_driver_api *)dev->api; + + if (api->sensor_binding_process == NULL) { return -ENOTSUP; } - return api->sensor_binding_triggered(binding, event, sensor_config, channel_data_size, - channel_data); + return api->sensor_binding_process(binding, event, mode); } /** diff --git a/app/src/behaviors/behavior_sensor_rotate.c b/app/src/behaviors/behavior_sensor_rotate.c index 86846d5be0b..3b5bef62183 100644 --- a/app/src/behaviors/behavior_sensor_rotate.c +++ b/app/src/behaviors/behavior_sensor_rotate.c @@ -13,7 +13,8 @@ #include "behavior_sensor_rotate_common.h" static const struct behavior_driver_api behavior_sensor_rotate_driver_api = { - .sensor_binding_triggered = zmk_behavior_sensor_rotate_common_trigger}; + .sensor_binding_data = zmk_behavior_sensor_rotate_common_data, + .sensor_binding_process = zmk_behavior_sensor_rotate_common_process}; static int behavior_sensor_rotate_init(const struct device *dev) { return 0; }; diff --git a/app/src/behaviors/behavior_sensor_rotate_common.c b/app/src/behaviors/behavior_sensor_rotate_common.c index 99e4e019ba1..0a2b619df81 100644 --- a/app/src/behaviors/behavior_sensor_rotate_common.c +++ b/app/src/behaviors/behavior_sensor_rotate_common.c @@ -11,13 +11,12 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); -int zmk_behavior_sensor_rotate_common_trigger(struct zmk_behavior_binding *binding, - struct zmk_behavior_binding_event event, - const struct zmk_sensor_config *sensor_config, - size_t channel_data_size, - const struct zmk_sensor_channel_data *channel_data) { +int zmk_behavior_sensor_rotate_common_data(struct zmk_behavior_binding *binding, + struct zmk_behavior_binding_event event, + const struct zmk_sensor_config *sensor_config, + size_t channel_data_size, + const struct zmk_sensor_channel_data *channel_data) { const struct device *dev = device_get_binding(binding->behavior_dev); - const struct behavior_sensor_rotate_config *cfg = dev->config; struct behavior_sensor_rotate_data *data = dev->data; const struct sensor_value value = channel_data[0].value; @@ -52,6 +51,26 @@ int zmk_behavior_sensor_rotate_common_trigger(struct zmk_behavior_binding *bindi value.val1, value.val2, data->remainder[sensor_position].val1, data->remainder[sensor_position].val2, triggers, binding->param1, binding->param2); + data->triggers[sensor_position] = triggers; + return 0; +} + +int zmk_behavior_sensor_rotate_common_process(struct zmk_behavior_binding *binding, + struct zmk_behavior_binding_event event, + enum behavior_sensor_binding_process_mode mode) { + const struct device *dev = device_get_binding(binding->behavior_dev); + const struct behavior_sensor_rotate_config *cfg = dev->config; + struct behavior_sensor_rotate_data *data = dev->data; + + const int sensor_position = ZMK_SENSOR_POSITION_FROM_VIRTUAL_KEY_POSITION(event.position); + + if (mode != BEHAVIOR_SENSOR_BINDING_PROCESS_MODE_TRIGGER) { + data->triggers[sensor_position] = 0; + return 0; + } + + int triggers = data->triggers[sensor_position]; + struct zmk_behavior_binding triggered_binding; if (triggers > 0) { triggered_binding = cfg->cw_binding; diff --git a/app/src/behaviors/behavior_sensor_rotate_common.h b/app/src/behaviors/behavior_sensor_rotate_common.h index eab443a3987..d9d4d855dfa 100644 --- a/app/src/behaviors/behavior_sensor_rotate_common.h +++ b/app/src/behaviors/behavior_sensor_rotate_common.h @@ -4,6 +4,7 @@ * SPDX-License-Identifier: MIT */ +#include #include #include @@ -16,10 +17,14 @@ struct behavior_sensor_rotate_config { struct behavior_sensor_rotate_data { struct sensor_value remainder[ZMK_KEYMAP_SENSORS_LEN]; + int triggers[ZMK_KEYMAP_SENSORS_LEN]; }; -int zmk_behavior_sensor_rotate_common_trigger(struct zmk_behavior_binding *binding, +int zmk_behavior_sensor_rotate_common_data(struct zmk_behavior_binding *binding, + struct zmk_behavior_binding_event event, + const struct zmk_sensor_config *sensor_config, + size_t channel_data_size, + const struct zmk_sensor_channel_data *channel_data); +int zmk_behavior_sensor_rotate_common_process(struct zmk_behavior_binding *binding, struct zmk_behavior_binding_event event, - const struct zmk_sensor_config *sensor_config, - size_t channel_data_size, - const struct zmk_sensor_channel_data *channel_data); \ No newline at end of file + enum behavior_sensor_binding_process_mode mode); \ No newline at end of file diff --git a/app/src/behaviors/behavior_sensor_rotate_var.c b/app/src/behaviors/behavior_sensor_rotate_var.c index 95bb99610ba..3c2373b0048 100644 --- a/app/src/behaviors/behavior_sensor_rotate_var.c +++ b/app/src/behaviors/behavior_sensor_rotate_var.c @@ -13,7 +13,8 @@ #include "behavior_sensor_rotate_common.h" static const struct behavior_driver_api behavior_sensor_rotate_var_driver_api = { - .sensor_binding_triggered = zmk_behavior_sensor_rotate_common_trigger}; + .sensor_binding_data = zmk_behavior_sensor_rotate_common_data, + .sensor_binding_process = zmk_behavior_sensor_rotate_common_process}; static int behavior_sensor_rotate_var_init(const struct device *dev) { return 0; }; diff --git a/app/src/keymap.c b/app/src/keymap.c index 16543d37840..c8121176f62 100644 --- a/app/src/keymap.c +++ b/app/src/keymap.c @@ -252,48 +252,59 @@ int zmk_keymap_position_state_changed(uint8_t source, uint32_t position, bool pr } #if ZMK_KEYMAP_HAS_SENSORS -int zmk_keymap_sensor_triggered( - uint8_t sensor_position, size_t channel_data_size, - const struct zmk_sensor_channel_data channel_data[channel_data_size], int64_t timestamp) { - for (int layer = ZMK_KEYMAP_LAYERS_LEN - 1; layer >= _zmk_keymap_layer_default; layer--) { - if (zmk_keymap_layer_active(layer)) { - struct zmk_behavior_binding *binding = &zmk_sensor_keymap[layer][sensor_position]; - const struct device *behavior; - int ret; +int zmk_keymap_sensor_event(uint8_t sensor_position, size_t channel_data_size, + const struct zmk_sensor_channel_data channel_data[channel_data_size], + int64_t timestamp) { + bool opaque_response = false; - LOG_DBG("layer: %d sensor_position: %d, binding name: %s", layer, sensor_position, - binding->behavior_dev); + for (int layer = ZMK_KEYMAP_LAYERS_LEN - 1; layer >= 0; layer--) { + struct zmk_behavior_binding *binding = &zmk_sensor_keymap[layer][sensor_position]; + const struct device *behavior; + int ret; - behavior = device_get_binding(binding->behavior_dev); + LOG_DBG("layer: %d sensor_position: %d, binding name: %s", layer, sensor_position, + binding->behavior_dev); - if (!behavior) { - LOG_DBG("No behavior assigned to %d on layer %d", sensor_position, layer); - continue; - } + behavior = device_get_binding(binding->behavior_dev); - struct zmk_behavior_binding_event event = { - .layer = layer, - .position = ZMK_VIRTUAL_KEY_POSITION_SENSOR(sensor_position), - .timestamp = timestamp, - }; + if (!behavior) { + LOG_DBG("No behavior assigned to %d on layer %d", sensor_position, layer); + continue; + } - ret = behavior_sensor_keymap_binding_triggered( - binding, event, zmk_sensors_get_config_at_position(sensor_position), - channel_data_size, channel_data); + struct zmk_behavior_binding_event event = { + .layer = layer, + .position = ZMK_VIRTUAL_KEY_POSITION_SENSOR(sensor_position), + .timestamp = timestamp, + }; - if (ret > 0) { - LOG_DBG("behavior processing to continue to next layer"); - continue; - } else if (ret < 0) { - LOG_DBG("Behavior returned error: %d", ret); - return ret; - } else { - return ret; - } + ret = behavior_sensor_keymap_binding_data( + binding, event, zmk_sensors_get_config_at_position(sensor_position), channel_data_size, + channel_data); + + if (ret > 0) { + LOG_DBG("behavior processing to continue to next layer"); + continue; + } + + enum behavior_sensor_binding_process_mode mode = + (!opaque_response && layer >= _zmk_keymap_layer_default && + zmk_keymap_layer_active(layer)) + ? BEHAVIOR_SENSOR_BINDING_PROCESS_MODE_TRIGGER + : BEHAVIOR_SENSOR_BINDING_PROCESS_MODE_DISCARD; + + ret = behavior_sensor_keymap_binding_process(binding, event, mode); + + if (ret == ZMK_BEHAVIOR_OPAQUE) { + LOG_DBG("sensor event processing complete, behavior response was opaque"); + opaque_response = true; + } else if (ret < 0) { + LOG_DBG("Behavior returned error: %d", ret); + return ret; } } - return -ENOTSUP; + return 0; } #endif /* ZMK_KEYMAP_HAS_SENSORS */ @@ -308,8 +319,8 @@ int keymap_listener(const zmk_event_t *eh) { #if ZMK_KEYMAP_HAS_SENSORS const struct zmk_sensor_event *sensor_ev; if ((sensor_ev = as_zmk_sensor_event(eh)) != NULL) { - return zmk_keymap_sensor_triggered(sensor_ev->sensor_position, sensor_ev->channel_data_size, - sensor_ev->channel_data, sensor_ev->timestamp); + return zmk_keymap_sensor_event(sensor_ev->sensor_position, sensor_ev->channel_data_size, + sensor_ev->channel_data, sensor_ev->timestamp); } #endif /* ZMK_KEYMAP_HAS_SENSORS */ From 3a91b325138dfba8ede743aec28e2cdbc85d17d2 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Tue, 16 May 2023 22:27:01 -0700 Subject: [PATCH 25/76] refactor(sensors): Use "sensor index" consistently --- app/include/drivers/behavior.h | 8 ++--- app/include/zmk/events/sensor_event.h | 4 +-- app/include/zmk/sensors.h | 3 +- .../behaviors/behavior_sensor_rotate_common.c | 18 +++++----- app/src/keymap.c | 33 +++++++++---------- app/src/sensors.c | 16 ++++----- 6 files changed, 40 insertions(+), 42 deletions(-) diff --git a/app/include/drivers/behavior.h b/app/include/drivers/behavior.h index d7e57d02433..bf2843bbe3e 100644 --- a/app/include/drivers/behavior.h +++ b/app/include/drivers/behavior.h @@ -33,7 +33,7 @@ typedef int (*behavior_keymap_binding_callback_t)(struct zmk_behavior_binding *b typedef int (*behavior_sensor_keymap_binding_process_callback_t)( struct zmk_behavior_binding *binding, struct zmk_behavior_binding_event event, enum behavior_sensor_binding_process_mode mode); -typedef int (*behavior_sensor_keymap_binding_data_callback_t)( +typedef int (*behavior_sensor_keymap_binding_accept_data_callback_t)( struct zmk_behavior_binding *binding, struct zmk_behavior_binding_event event, const struct zmk_sensor_config *sensor_config, size_t channel_data_size, const struct zmk_sensor_channel_data channel_data[channel_data_size]); @@ -49,7 +49,7 @@ __subsystem struct behavior_driver_api { behavior_keymap_binding_callback_t binding_convert_central_state_dependent_params; behavior_keymap_binding_callback_t binding_pressed; behavior_keymap_binding_callback_t binding_released; - behavior_sensor_keymap_binding_data_callback_t sensor_binding_data; + behavior_sensor_keymap_binding_accept_data_callback_t sensor_binding_data; behavior_sensor_keymap_binding_process_callback_t sensor_binding_process; }; /** @@ -169,12 +169,12 @@ static inline int z_impl_behavior_keymap_binding_released(struct zmk_behavior_bi * @retval 0 If successful. * @retval Negative errno code if failure. */ -__syscall int behavior_sensor_keymap_binding_data( +__syscall int behavior_sensor_keymap_binding_accept_data( struct zmk_behavior_binding *binding, struct zmk_behavior_binding_event event, const struct zmk_sensor_config *sensor_config, size_t channel_data_size, const struct zmk_sensor_channel_data *channel_data); -static inline int z_impl_behavior_sensor_keymap_binding_data( +static inline int z_impl_behavior_sensor_keymap_binding_accept_data( struct zmk_behavior_binding *binding, struct zmk_behavior_binding_event event, const struct zmk_sensor_config *sensor_config, size_t channel_data_size, const struct zmk_sensor_channel_data *channel_data) { diff --git a/app/include/zmk/events/sensor_event.h b/app/include/zmk/events/sensor_event.h index c5157447dd4..f6d23ac71d9 100644 --- a/app/include/zmk/events/sensor_event.h +++ b/app/include/zmk/events/sensor_event.h @@ -16,12 +16,12 @@ #define ZMK_SENSOR_EVENT_MAX_CHANNELS 1 struct zmk_sensor_event { - uint8_t sensor_position; - size_t channel_data_size; struct zmk_sensor_channel_data channel_data[ZMK_SENSOR_EVENT_MAX_CHANNELS]; int64_t timestamp; + + uint8_t sensor_index; }; ZMK_EVENT_DECLARE(zmk_sensor_event); \ No newline at end of file diff --git a/app/include/zmk/sensors.h b/app/include/zmk/sensors.h index 06fbc63e564..8ac1c283cb6 100644 --- a/app/include/zmk/sensors.h +++ b/app/include/zmk/sensors.h @@ -8,7 +8,6 @@ #include -#define _SENSOR_CHILD_LEN(node) 1 + #define ZMK_KEYMAP_SENSORS_NODE DT_INST(0, zmk_keymap_sensors) #define ZMK_KEYMAP_HAS_SENSORS DT_NODE_HAS_STATUS(ZMK_KEYMAP_SENSORS_NODE, okay) #define ZMK_KEYMAP_SENSORS_BY_IDX(idx) DT_PHANDLE_BY_IDX(ZMK_KEYMAP_SENSORS_NODE, sensors, idx) @@ -19,7 +18,7 @@ #define ZMK_KEYMAP_SENSORS_LEN 0 #endif -const struct zmk_sensor_config *zmk_sensors_get_config_at_position(uint8_t sensor_position); +const struct zmk_sensor_config *zmk_sensors_get_config_at_index(uint8_t sensor_index); struct zmk_sensor_config { uint16_t triggers_per_rotation; diff --git a/app/src/behaviors/behavior_sensor_rotate_common.c b/app/src/behaviors/behavior_sensor_rotate_common.c index 0a2b619df81..4ccfea0e4b3 100644 --- a/app/src/behaviors/behavior_sensor_rotate_common.c +++ b/app/src/behaviors/behavior_sensor_rotate_common.c @@ -21,7 +21,7 @@ int zmk_behavior_sensor_rotate_common_data(struct zmk_behavior_binding *binding, const struct sensor_value value = channel_data[0].value; int triggers; - int sensor_position = ZMK_SENSOR_POSITION_FROM_VIRTUAL_KEY_POSITION(event.position); + int sensor_index = ZMK_SENSOR_POSITION_FROM_VIRTUAL_KEY_POSITION(event.position); // Some funky special casing for "old encoder behavior" where ticks where reported in val2 only, // instead of rotational degrees in val1. @@ -29,7 +29,7 @@ int zmk_behavior_sensor_rotate_common_data(struct zmk_behavior_binding *binding, if (value.val1 == 0) { triggers = value.val2; } else { - struct sensor_value remainder = data->remainder[sensor_position]; + struct sensor_value remainder = data->remainder[sensor_index]; remainder.val1 += value.val1; remainder.val2 += value.val2; @@ -43,15 +43,15 @@ int zmk_behavior_sensor_rotate_common_data(struct zmk_behavior_binding *binding, triggers = remainder.val1 / trigger_degrees; remainder.val1 %= trigger_degrees; - data->remainder[sensor_position] = remainder; + data->remainder[sensor_index] = remainder; } LOG_DBG( "val1: %d, val2: %d, remainder: %d/%d triggers: %d inc keycode 0x%02X dec keycode 0x%02X", - value.val1, value.val2, data->remainder[sensor_position].val1, - data->remainder[sensor_position].val2, triggers, binding->param1, binding->param2); + value.val1, value.val2, data->remainder[sensor_index].val1, + data->remainder[sensor_index].val2, triggers, binding->param1, binding->param2); - data->triggers[sensor_position] = triggers; + data->triggers[sensor_index] = triggers; return 0; } @@ -62,14 +62,14 @@ int zmk_behavior_sensor_rotate_common_process(struct zmk_behavior_binding *bindi const struct behavior_sensor_rotate_config *cfg = dev->config; struct behavior_sensor_rotate_data *data = dev->data; - const int sensor_position = ZMK_SENSOR_POSITION_FROM_VIRTUAL_KEY_POSITION(event.position); + const int sensor_index = ZMK_SENSOR_POSITION_FROM_VIRTUAL_KEY_POSITION(event.position); if (mode != BEHAVIOR_SENSOR_BINDING_PROCESS_MODE_TRIGGER) { - data->triggers[sensor_position] = 0; + data->triggers[sensor_index] = 0; return 0; } - int triggers = data->triggers[sensor_position]; + int triggers = data->triggers[sensor_index]; struct zmk_behavior_binding triggered_binding; if (triggers > 0) { diff --git a/app/src/keymap.c b/app/src/keymap.c index c8121176f62..020faf3f2be 100644 --- a/app/src/keymap.c +++ b/app/src/keymap.c @@ -252,38 +252,37 @@ int zmk_keymap_position_state_changed(uint8_t source, uint32_t position, bool pr } #if ZMK_KEYMAP_HAS_SENSORS -int zmk_keymap_sensor_event(uint8_t sensor_position, size_t channel_data_size, - const struct zmk_sensor_channel_data channel_data[channel_data_size], - int64_t timestamp) { +int zmk_keymap_sensor_event(uint8_t sensor_index, + const struct zmk_sensor_channel_data *channel_data, + size_t channel_data_size, int64_t timestamp) { bool opaque_response = false; for (int layer = ZMK_KEYMAP_LAYERS_LEN - 1; layer >= 0; layer--) { - struct zmk_behavior_binding *binding = &zmk_sensor_keymap[layer][sensor_position]; - const struct device *behavior; - int ret; + struct zmk_behavior_binding *binding = &zmk_sensor_keymap[layer][sensor_index]; - LOG_DBG("layer: %d sensor_position: %d, binding name: %s", layer, sensor_position, + LOG_DBG("layer: %d sensor_index: %d, binding name: %s", layer, sensor_index, binding->behavior_dev); - behavior = device_get_binding(binding->behavior_dev); - + const struct device *behavior = device_get_binding(binding->behavior_dev); if (!behavior) { - LOG_DBG("No behavior assigned to %d on layer %d", sensor_position, layer); + LOG_DBG("No behavior assigned to %d on layer %d", sensor_index, layer); continue; } struct zmk_behavior_binding_event event = { .layer = layer, - .position = ZMK_VIRTUAL_KEY_POSITION_SENSOR(sensor_position), + .position = ZMK_VIRTUAL_KEY_POSITION_SENSOR(sensor_index), .timestamp = timestamp, }; - ret = behavior_sensor_keymap_binding_data( - binding, event, zmk_sensors_get_config_at_position(sensor_position), channel_data_size, + int ret = behavior_sensor_keymap_binding_accept_data( + binding, event, zmk_sensors_get_config_at_index(sensor_index), channel_data_size, channel_data); - if (ret > 0) { - LOG_DBG("behavior processing to continue to next layer"); + if (ret < 0) { + LOG_WRN("behavior data accept for behavior %s returned an error (%d). Processing to " + "continue to next layer", + binding->behavior_dev, ret); continue; } @@ -319,8 +318,8 @@ int keymap_listener(const zmk_event_t *eh) { #if ZMK_KEYMAP_HAS_SENSORS const struct zmk_sensor_event *sensor_ev; if ((sensor_ev = as_zmk_sensor_event(eh)) != NULL) { - return zmk_keymap_sensor_event(sensor_ev->sensor_position, sensor_ev->channel_data_size, - sensor_ev->channel_data, sensor_ev->timestamp); + return zmk_keymap_sensor_event(sensor_ev->sensor_index, sensor_ev->channel_data, + sensor_ev->channel_data_size, sensor_ev->timestamp); } #endif /* ZMK_KEYMAP_HAS_SENSORS */ diff --git a/app/src/sensors.c b/app/src/sensors.c index 5f41c4f2f20..3a34ca230f6 100644 --- a/app/src/sensors.c +++ b/app/src/sensors.c @@ -19,7 +19,7 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #if ZMK_KEYMAP_HAS_SENSORS struct sensors_item_cfg { - uint8_t sensor_position; + uint8_t sensor_index; const struct zmk_sensor_config *config; const struct device *dev; struct sensor_trigger trigger; @@ -57,17 +57,17 @@ static struct sensors_item_cfg sensors[] = {LISTIFY(ZMK_KEYMAP_SENSORS_LEN, SENS static ATOMIC_DEFINE(pending_sensors, ZMK_KEYMAP_SENSORS_LEN); -const struct zmk_sensor_config *zmk_sensors_get_config_at_position(uint8_t sensor_position) { - if (sensor_position > ARRAY_SIZE(configs)) { +const struct zmk_sensor_config *zmk_sensors_get_config_at_index(uint8_t sensor_index) { + if (sensor_index > ARRAY_SIZE(configs)) { return NULL; } - return &configs[sensor_position]; + return &configs[sensor_index]; } -static void trigger_sensor_data_for_position(uint32_t sensor_position) { +static void trigger_sensor_data_for_position(uint32_t sensor_index) { int err; - const struct sensors_item_cfg *item = &sensors[sensor_position]; + const struct sensors_item_cfg *item = &sensors[sensor_index]; err = sensor_sample_fetch(item->dev); if (err) { @@ -84,7 +84,7 @@ static void trigger_sensor_data_for_position(uint32_t sensor_position) { } ZMK_EVENT_RAISE(new_zmk_sensor_event( - (struct zmk_sensor_event){.sensor_position = item->sensor_position, + (struct zmk_sensor_event){.sensor_index = item->sensor_index, .channel_data = {(struct zmk_sensor_channel_data){ .value = value, .channel = item->trigger.chan}}, .timestamp = k_uptime_get()})); @@ -122,7 +122,7 @@ static void zmk_sensors_trigger_handler(const struct device *dev, static void zmk_sensors_init_item(uint8_t i) { LOG_DBG("Init sensor at index %d", i); - sensors[i].sensor_position = i; + sensors[i].sensor_index = i; if (!sensors[i].dev) { LOG_DBG("No local device for %d", i); From 753802cd79ce12d2e5d86c72ced3a4cc76fe4564 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Sun, 18 Jun 2023 05:59:31 +0000 Subject: [PATCH 26/76] fix(sensors): Clean ups based on code review. --- app/Kconfig | 17 +++++------------ app/include/drivers/behavior.h | 7 ++++--- app/src/behaviors/behavior_sensor_rotate.c | 2 +- .../behaviors/behavior_sensor_rotate_common.c | 9 ++++----- .../behaviors/behavior_sensor_rotate_common.h | 9 ++++----- app/src/behaviors/behavior_sensor_rotate_var.c | 2 +- app/src/sensors.c | 9 +++++++-- 7 files changed, 26 insertions(+), 29 deletions(-) diff --git a/app/Kconfig b/app/Kconfig index 9c0606b02fc..92641c14ed0 100644 --- a/app/Kconfig +++ b/app/Kconfig @@ -194,18 +194,6 @@ rsource "src/split/Kconfig" #Basic Keyboard Setup endmenu -menu "Encoders" - -config ZMK_ENCODERS_DEFAULT_TRIGGERS_PER_ROTATION - int "Default behavior triggers per rotation" - help - Unless overridden for a specific behavior in the keymap/devicetree, this value - determines how many times to trigger the bound behavior per full rotation. - For tactile encoders with detents, this usually should match the number of - detents per rotation of the encoder. - default 30 - -endmenu menu "Display/LED Options" rsource "src/display/Kconfig" @@ -548,6 +536,11 @@ if ZMK_KEYMAP_SENSORS config ZMK_KEYMAP_SENSORS_DEFAULT_TRIGGERS_PER_ROTATION int "Default triggers per rotation" + help + Unless overridden for a sensor in the board/shield/devicetree, this value + determines how many times to trigger the bound behavior per full rotation. + For tactile encoders with detents, this usually should match the number of + detents per rotation of the encoder. default 20 endif # ZMK_KEYMAP_SENSORS diff --git a/app/include/drivers/behavior.h b/app/include/drivers/behavior.h index bf2843bbe3e..066cc723ece 100644 --- a/app/include/drivers/behavior.h +++ b/app/include/drivers/behavior.h @@ -49,7 +49,7 @@ __subsystem struct behavior_driver_api { behavior_keymap_binding_callback_t binding_convert_central_state_dependent_params; behavior_keymap_binding_callback_t binding_pressed; behavior_keymap_binding_callback_t binding_released; - behavior_sensor_keymap_binding_accept_data_callback_t sensor_binding_data; + behavior_sensor_keymap_binding_accept_data_callback_t sensor_binding_accept_data; behavior_sensor_keymap_binding_process_callback_t sensor_binding_process; }; /** @@ -186,11 +186,12 @@ static inline int z_impl_behavior_sensor_keymap_binding_accept_data( const struct behavior_driver_api *api = (const struct behavior_driver_api *)dev->api; - if (api->sensor_binding_data == NULL) { + if (api->sensor_binding_accept_data == NULL) { return -ENOTSUP; } - return api->sensor_binding_data(binding, event, sensor_config, channel_data_size, channel_data); + return api->sensor_binding_accept_data(binding, event, sensor_config, channel_data_size, + channel_data); } /** diff --git a/app/src/behaviors/behavior_sensor_rotate.c b/app/src/behaviors/behavior_sensor_rotate.c index 3b5bef62183..822bc206b02 100644 --- a/app/src/behaviors/behavior_sensor_rotate.c +++ b/app/src/behaviors/behavior_sensor_rotate.c @@ -13,7 +13,7 @@ #include "behavior_sensor_rotate_common.h" static const struct behavior_driver_api behavior_sensor_rotate_driver_api = { - .sensor_binding_data = zmk_behavior_sensor_rotate_common_data, + .sensor_binding_accept_data = zmk_behavior_sensor_rotate_common_accept_data, .sensor_binding_process = zmk_behavior_sensor_rotate_common_process}; static int behavior_sensor_rotate_init(const struct device *dev) { return 0; }; diff --git a/app/src/behaviors/behavior_sensor_rotate_common.c b/app/src/behaviors/behavior_sensor_rotate_common.c index 4ccfea0e4b3..eea7bf48476 100644 --- a/app/src/behaviors/behavior_sensor_rotate_common.c +++ b/app/src/behaviors/behavior_sensor_rotate_common.c @@ -11,11 +11,10 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); -int zmk_behavior_sensor_rotate_common_data(struct zmk_behavior_binding *binding, - struct zmk_behavior_binding_event event, - const struct zmk_sensor_config *sensor_config, - size_t channel_data_size, - const struct zmk_sensor_channel_data *channel_data) { +int zmk_behavior_sensor_rotate_common_accept_data( + struct zmk_behavior_binding *binding, struct zmk_behavior_binding_event event, + const struct zmk_sensor_config *sensor_config, size_t channel_data_size, + const struct zmk_sensor_channel_data *channel_data) { const struct device *dev = device_get_binding(binding->behavior_dev); struct behavior_sensor_rotate_data *data = dev->data; diff --git a/app/src/behaviors/behavior_sensor_rotate_common.h b/app/src/behaviors/behavior_sensor_rotate_common.h index d9d4d855dfa..d354b67937c 100644 --- a/app/src/behaviors/behavior_sensor_rotate_common.h +++ b/app/src/behaviors/behavior_sensor_rotate_common.h @@ -20,11 +20,10 @@ struct behavior_sensor_rotate_data { int triggers[ZMK_KEYMAP_SENSORS_LEN]; }; -int zmk_behavior_sensor_rotate_common_data(struct zmk_behavior_binding *binding, - struct zmk_behavior_binding_event event, - const struct zmk_sensor_config *sensor_config, - size_t channel_data_size, - const struct zmk_sensor_channel_data *channel_data); +int zmk_behavior_sensor_rotate_common_accept_data( + struct zmk_behavior_binding *binding, struct zmk_behavior_binding_event event, + const struct zmk_sensor_config *sensor_config, size_t channel_data_size, + const struct zmk_sensor_channel_data *channel_data); int zmk_behavior_sensor_rotate_common_process(struct zmk_behavior_binding *binding, struct zmk_behavior_binding_event event, enum behavior_sensor_binding_process_mode mode); \ No newline at end of file diff --git a/app/src/behaviors/behavior_sensor_rotate_var.c b/app/src/behaviors/behavior_sensor_rotate_var.c index 3c2373b0048..e6d20cab9d1 100644 --- a/app/src/behaviors/behavior_sensor_rotate_var.c +++ b/app/src/behaviors/behavior_sensor_rotate_var.c @@ -13,7 +13,7 @@ #include "behavior_sensor_rotate_common.h" static const struct behavior_driver_api behavior_sensor_rotate_var_driver_api = { - .sensor_binding_data = zmk_behavior_sensor_rotate_common_data, + .sensor_binding_accept_data = zmk_behavior_sensor_rotate_common_accept_data, .sensor_binding_process = zmk_behavior_sensor_rotate_common_process}; static int behavior_sensor_rotate_var_init(const struct device *dev) { return 0; }; diff --git a/app/src/sensors.c b/app/src/sensors.c index 3a34ca230f6..e339afe0437 100644 --- a/app/src/sensors.c +++ b/app/src/sensors.c @@ -19,10 +19,10 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #if ZMK_KEYMAP_HAS_SENSORS struct sensors_item_cfg { - uint8_t sensor_index; const struct zmk_sensor_config *config; const struct device *dev; struct sensor_trigger trigger; + uint8_t sensor_index; }; #define _SENSOR_ITEM(idx, node) \ @@ -43,7 +43,11 @@ struct sensors_item_cfg { CONFIG_ZMK_KEYMAP_SENSORS_DEFAULT_TRIGGERS_PER_ROTATION)) \ } #define SENSOR_CHILD_DEFAULTS(idx, arg) \ - { .triggers_per_rotation = DT_PROP_OR(ZMK_KEYMAP_SENSORS_NODE, triggers_per_rotation, 20) } + { \ + .triggers_per_rotation = \ + DT_PROP_OR(ZMK_KEYMAP_SENSORS_NODE, triggers_per_rotation, \ + CONFIG_ZMK_KEYMAP_SENSORS_DEFAULT_TRIGGERS_PER_ROTATION) \ + } static struct zmk_sensor_config configs[] = { #if ZMK_KEYMAP_SENSORS_CHILD_COUNT > 0 @@ -85,6 +89,7 @@ static void trigger_sensor_data_for_position(uint32_t sensor_index) { ZMK_EVENT_RAISE(new_zmk_sensor_event( (struct zmk_sensor_event){.sensor_index = item->sensor_index, + .channel_data_size = 1, .channel_data = {(struct zmk_sensor_channel_data){ .value = value, .channel = item->trigger.chan}}, .timestamp = k_uptime_get()})); From 5763558a02154ab599775c770fcf954931816e52 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Tue, 30 May 2023 02:38:28 +0000 Subject: [PATCH 27/76] feat(blog): Add post about sensor refactor. * Document changed configuration, support for other Zephyr drivers, next steps. Co-authored-by: Cem Aksoylar --- docs/blog/2023-06-18-encoder-refactors.md | 119 ++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 docs/blog/2023-06-18-encoder-refactors.md diff --git a/docs/blog/2023-06-18-encoder-refactors.md b/docs/blog/2023-06-18-encoder-refactors.md new file mode 100644 index 00000000000..26f9cee8176 --- /dev/null +++ b/docs/blog/2023-06-18-encoder-refactors.md @@ -0,0 +1,119 @@ +--- +title: "Major Encoder Refactor" +author: Pete Johanson +author_title: Project Creator +author_url: https://gitlab.com/petejohanson +author_image_url: https://www.gravatar.com/avatar/2001ceff7e9dc753cf96fcb2e6f41110 +tags: [firmware, zephyr, sensors, encoders] +--- + +Today, we merged a significant change to the low level sensor code that is used to support encoders. In particular, +this paves the way for completing the work on supporting split peripheral sensors/encoders, and other future sensors +like pointing devices. + +As part of the work, backwards compatibility for existing shields has been retained, but only for a grace period to allow out-of-tree shields to move to the new approach for encoders. + +Special thanks to [joelspadin] for the _thorough_ code review and testing throughout the development of the refactor. + +## Summary of Changes + +The following items have been merged: + +1. Split configuration of hardware details, and behavior configuration to allow more flexible functionality of sensors/encoders, in particular linear encoders that lack detents/"clicks" as they rotate. +2. Support for upstream Zephyr sensor drivers, including the NRFX QDEC driver that can be used on nRF52 based keyboards. +3. Sensor data handling changes that pave the way for split sensor handling easily. + +## Configuration Changes + +The major changes to configuration in the devicetree files relates to how the number of steps/triggers for a given encoder are set. In particular, the number of pulses/steps for a given encoder is configured first, allowing ZMK to determine the exact angular degrees of change that is represented by a single pulse on the data lines to that encoder. + +Once that angular degrees mapping is completed, now independently there is a configuration setting to control how many triggers of the behavior in the keymap should occur for each full rotation of the sensor. Another way to think of this is "how many degrees of rotation results in a triggering of the sensor behavior in your keymap layer". + +Splitting these two parts of the encoder configuration allows greater flexibility, and fine grained control of encoder behavior for linear encoders that don't have fixed detents. + +### Old Configuration + +Previously, an encoder configuration looked like: + +``` + left_encoder: encoder_left { + compatible = "alps,ec11"; + label = "LEFT_ENCODER"; + a-gpios = <&pro_micro 21 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; + b-gpios = <&pro_micro 20 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; + resolution = <4>; + }; +``` + +Here, the `resolution` property was used to indicate how many encoder pulses should trigger the sensor behavior one time. Next, the encoder is selected in the sensors node: + +``` + sensors { + compatible = "zmk,keymap-sensors"; + sensors = <&left_encoder &right_encoder>; + }; +``` + +That was the entirety of the configuration for encoders. + +### New Configuration + +``` + left_encoder: encoder_left { + compatible = "alps,ec11"; + label = "LEFT_ENCODER"; + a-gpios = <&pro_micro 21 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; + b-gpios = <&pro_micro 20 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; + steps = <80>; + }; +``` + +Here, the `steps` property is now used to indicate how many encoder pulses there are in a single complete rotation of the encoder. Next, the encoder is selected in the sensors node as before, but an additional configuration is used to indicate how many times the encoder should trigger the behavior in your keymap per rotation: + +``` + sensors { + compatible = "zmk,keymap-sensors"; + sensors = <&left_encoder &right_encoder>; + triggers-per-rotation = <20>; + }; +``` + +For tactile encoders that have detents, the `triggers-per-rotation` would match the number of detents on the encoder. For linear encoders, the value can be chosen to suit your needs. + +## Zephyr Sensor Drivers + +The configuration changes bring ZMK's code in line with how upstream Zephyr sensor drivers handle rotations. This has the added advantage of allowing us to leverage other sensor drivers. On Nordic MCUs, like nRF52840, the NRFX QDEC driver can be used, for example: + +``` +&pinctrl { + qdec_default: qdec_default { + group1 { + psels = , + ; + bias-pull-up; + }; + }; +}; + +// Set up the QDEC hardware based driver and give it the same label as the deleted node. +encoder: &qdec0 { + status = "okay"; + led-pre = <0>; + steps = <80>; + pinctrl-0 = <&qdec_default>; + pinctrl-names = "default"; +}; +``` + +The NRFX QDEC driver has the advantage of supporting optical encoders as well, and although it polls, it does so in hardware without waking the MCU core; initial basic power profiling is promising. + +## Split Sensor/Encoder Support + +In addition to the refactors for splitting the configuration, the changes merged included refactors designed to simplify and move forward with the long outstanding feature of supporting encoders on the peripheral side of split keyboards. That work is planned as a follow up. + +## Deprecation + +The old configuration will be supported for a period of one month, and then removed, giving users a grace period to complete the migration to the new separated configuration. + +[petejohanson]: https://github.com/petejohanson +[joelspadin]: https://github.com/joelspadin From e686fce4d917b708da7f2baba4115043d3f0deab Mon Sep 17 00:00:00 2001 From: Xudong Zheng <7pkvm5aw@slicealias.com> Date: Fri, 19 May 2023 18:41:08 -0400 Subject: [PATCH 28/76] refactor(split): allow central to define connection parameters Fixes #1614 --- app/src/split/bluetooth/Kconfig | 17 +++++++++++++++-- app/src/split/bluetooth/central.c | 4 +++- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/app/src/split/bluetooth/Kconfig b/app/src/split/bluetooth/Kconfig index e2c8d5c3395..0610b667a26 100644 --- a/app/src/split/bluetooth/Kconfig +++ b/app/src/split/bluetooth/Kconfig @@ -33,6 +33,18 @@ config ZMK_SPLIT_BLE_CENTRAL_SPLIT_RUN_QUEUE_SIZE int "Max number of behavior run events to queue to send to the peripheral(s)" default 5 +config ZMK_SPLIT_BLE_PREF_INT + int "Connection interval to use for split central/peripheral connection" + default 6 + +config ZMK_SPLIT_BLE_PREF_LATENCY + int "Latency to use for split central/peripheral connection" + default 30 + +config ZMK_SPLIT_BLE_PREF_TIMEOUT + int "Supervision timeout to use for split central/peripheral connection" + default 400 + endif # ZMK_SPLIT_ROLE_CENTRAL if !ZMK_SPLIT_ROLE_CENTRAL @@ -58,8 +70,9 @@ config BT_MAX_PAIRED config BT_MAX_CONN default 1 -config BT_PERIPHERAL_PREF_MAX_INT - default 6 +# Allow central to specify connection parameters. +config BT_GAP_AUTO_UPDATE_CONN_PARAMS + default n #!ZMK_SPLIT_ROLE_CENTRAL endif diff --git a/app/src/split/bluetooth/central.c b/app/src/split/bluetooth/central.c index 53e61be621a..147760ffae7 100644 --- a/app/src/split/bluetooth/central.c +++ b/app/src/split/bluetooth/central.c @@ -383,7 +383,9 @@ static bool split_central_eir_found(const bt_addr_le_t *addr) { struct peripheral_slot *slot = &peripherals[slot_idx]; LOG_DBG("Initiating new connnection"); - struct bt_le_conn_param *param = BT_LE_CONN_PARAM(0x0006, 0x0006, 30, 400); + struct bt_le_conn_param *param = + BT_LE_CONN_PARAM(CONFIG_ZMK_SPLIT_BLE_PREF_INT, CONFIG_ZMK_SPLIT_BLE_PREF_INT, + CONFIG_ZMK_SPLIT_BLE_PREF_LATENCY, CONFIG_ZMK_SPLIT_BLE_PREF_TIMEOUT); err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN, param, &slot->conn); if (err < 0) { LOG_ERR("Create conn failed (err %d) (create conn? 0x%04x)", err, BT_HCI_OP_LE_CREATE_CONN); From 805dd4a53bc9ff7fe1f7eb5c9ea332a9affbc5f9 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Fri, 8 Apr 2022 15:38:46 +0000 Subject: [PATCH 29/76] feat(behaviors): Support parameterized macros. * Add two new compatibles for macros that take one or two parameters when bound in a keymap. * Use `¯o_param_1to1`, `¯o_param_1to2`, `¯o_param_2to1`, and `¯o_param_2to2` control entries in the bindings for the macro to have the next binding entry have it's values substituted. Co-authored-by: Cem Aksoylar --- app/CMakeLists.txt | 2 +- app/Kconfig.behaviors | 7 +- app/dts/behaviors/macros.dtsi | 55 +++++++-- app/dts/bindings/behaviors/macro_base.yaml | 13 +++ .../zmk,behavior-macro-one-param.yaml | 8 ++ .../zmk,behavior-macro-two-param.yaml | 8 ++ .../behaviors/zmk,behavior-macro.yaml | 13 +-- .../bindings/macros/zmk,macro-param-1to1.yaml | 8 ++ .../bindings/macros/zmk,macro-param-1to2.yaml | 8 ++ .../bindings/macros/zmk,macro-param-2to1.yaml | 8 ++ .../bindings/macros/zmk,macro-param-2to2.yaml | 8 ++ app/src/behaviors/behavior_macro.c | 104 +++++++++++++----- .../place-holder-parameters/events.patterns | 1 + .../keycode_events.snapshot | 16 +++ .../native_posix_64.keymap | 63 +++++++++++ docs/docs/behaviors/macros.md | 40 +++++++ 16 files changed, 312 insertions(+), 50 deletions(-) create mode 100644 app/dts/bindings/behaviors/macro_base.yaml create mode 100644 app/dts/bindings/behaviors/zmk,behavior-macro-one-param.yaml create mode 100644 app/dts/bindings/behaviors/zmk,behavior-macro-two-param.yaml create mode 100644 app/dts/bindings/macros/zmk,macro-param-1to1.yaml create mode 100644 app/dts/bindings/macros/zmk,macro-param-1to2.yaml create mode 100644 app/dts/bindings/macros/zmk,macro-param-2to1.yaml create mode 100644 app/dts/bindings/macros/zmk,macro-param-2to2.yaml create mode 100644 app/tests/macros/place-holder-parameters/events.patterns create mode 100644 app/tests/macros/place-holder-parameters/keycode_events.snapshot create mode 100644 app/tests/macros/place-holder-parameters/native_posix_64.keymap diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index ea3b8f73364..4c1c63c2cfa 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -43,7 +43,7 @@ if ((NOT CONFIG_ZMK_SPLIT) OR CONFIG_ZMK_SPLIT_ROLE_CENTRAL) target_sources(app PRIVATE src/behaviors/behavior_sticky_key.c) target_sources(app PRIVATE src/behaviors/behavior_caps_word.c) target_sources(app PRIVATE src/behaviors/behavior_key_repeat.c) - target_sources(app PRIVATE src/behaviors/behavior_macro.c) + target_sources_ifdef(CONFIG_ZMK_BEHAVIOR_MACRO app PRIVATE src/behaviors/behavior_macro.c) target_sources(app PRIVATE src/behaviors/behavior_momentary_layer.c) target_sources(app PRIVATE src/behaviors/behavior_mod_morph.c) target_sources(app PRIVATE src/behaviors/behavior_outputs.c) diff --git a/app/Kconfig.behaviors b/app/Kconfig.behaviors index 17850eae2ff..9e4a82b06e7 100644 --- a/app/Kconfig.behaviors +++ b/app/Kconfig.behaviors @@ -21,4 +21,9 @@ config ZMK_BEHAVIOR_SENSOR_ROTATE_VAR bool default y depends on DT_HAS_ZMK_BEHAVIOR_SENSOR_ROTATE_VAR_ENABLED - select ZMK_BEHAVIOR_SENSOR_ROTATE_COMMON \ No newline at end of file + select ZMK_BEHAVIOR_SENSOR_ROTATE_COMMON + +config ZMK_BEHAVIOR_MACRO + bool + default y + depends on DT_HAS_ZMK_BEHAVIOR_MACRO_ENABLED || DT_HAS_ZMK_BEHAVIOR_MACRO_ONE_PARAM_ENABLED || DT_HAS_ZMK_BEHAVIOR_MACRO_TWO_PARAM_ENABLED \ No newline at end of file diff --git a/app/dts/behaviors/macros.dtsi b/app/dts/behaviors/macros.dtsi index 757c046edd7..36b4a8d33f3 100644 --- a/app/dts/behaviors/macros.dtsi +++ b/app/dts/behaviors/macros.dtsi @@ -4,16 +4,33 @@ * SPDX-License-Identifier: MIT */ +#define MACRO_PLACEHOLDER 0 #define ZMK_MACRO_STRINGIFY(x) #x #define ZMK_MACRO(name,...) \ - name: name { \ - label = ZMK_MACRO_STRINGIFY(ZM_ ## name); \ - compatible = "zmk,behavior-macro"; \ - #binding-cells = <0>; \ - __VA_ARGS__ \ - }; +name: name { \ + label = ZMK_MACRO_STRINGIFY(ZM_ ## name); \ + compatible = "zmk,behavior-macro"; \ + #binding-cells = <0>; \ + __VA_ARGS__ \ +}; - / { +#define ZMK_MACRO1(name,...) \ +name: name { \ + label = ZMK_MACRO_STRINGIFY(ZM_ ## name); \ + compatible = "zmk,behavior-macro-one-param"; \ + #binding-cells = <1>; \ + __VA_ARGS__ \ +}; + +#define ZMK_MACRO2(name,...) \ +name: name { \ + label = ZMK_MACRO_STRINGIFY(ZM_ ## name); \ + compatible = "zmk,behavior-macro-two-param"; \ + #binding-cells = <2>; \ + __VA_ARGS__ \ +}; + +/ { behaviors { macro_tap: macro_control_mode_tap { compatible = "zmk,macro-control-mode-tap"; @@ -50,5 +67,29 @@ label = "MAC_WAIT_REL"; #binding-cells = <0>; }; + + macro_param_1to1: macro_param_1to1 { + compatible = "zmk,macro-param-1to1"; + label = "MAC_PARAM_1TO1"; + #binding-cells = <0>; + }; + + macro_param_1to2: macro_param_1to2 { + compatible = "zmk,macro-param-1to2"; + label = "MAC_PARAM_1TO2"; + #binding-cells = <0>; + }; + + macro_param_2to1: macro_param_2to1 { + compatible = "zmk,macro-param-2to1"; + label = "MAC_PARAM_2TO1"; + #binding-cells = <0>; + }; + + macro_param_2to2: macro_param_2to2 { + compatible = "zmk,macro-param-2to2"; + label = "MAC_PARAM_2TO2"; + #binding-cells = <0>; + }; }; }; diff --git a/app/dts/bindings/behaviors/macro_base.yaml b/app/dts/bindings/behaviors/macro_base.yaml new file mode 100644 index 00000000000..236ee33d3b2 --- /dev/null +++ b/app/dts/bindings/behaviors/macro_base.yaml @@ -0,0 +1,13 @@ +# Copyright (c) 2022 The ZMK Contributors +# SPDX-License-Identifier: MIT + +properties: + bindings: + type: phandle-array + required: true + wait-ms: + type: int + description: The default time to wait (in milliseconds) before triggering the next behavior in the macro bindings list. + tap-ms: + type: int + description: The default time to wait (in milliseconds) between the press and release events on a tapped macro behavior binding diff --git a/app/dts/bindings/behaviors/zmk,behavior-macro-one-param.yaml b/app/dts/bindings/behaviors/zmk,behavior-macro-one-param.yaml new file mode 100644 index 00000000000..4fe5a2fba1e --- /dev/null +++ b/app/dts/bindings/behaviors/zmk,behavior-macro-one-param.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2022 The ZMK Contributors +# SPDX-License-Identifier: MIT + +description: Macro Behavior + +compatible: "zmk,behavior-macro-one-param" + +include: [one_param.yaml, macro_base.yaml] diff --git a/app/dts/bindings/behaviors/zmk,behavior-macro-two-param.yaml b/app/dts/bindings/behaviors/zmk,behavior-macro-two-param.yaml new file mode 100644 index 00000000000..ab6e32b48ec --- /dev/null +++ b/app/dts/bindings/behaviors/zmk,behavior-macro-two-param.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2022 The ZMK Contributors +# SPDX-License-Identifier: MIT + +description: Macro Behavior + +compatible: "zmk,behavior-macro-two-param" + +include: [two_param.yaml, macro_base.yaml] diff --git a/app/dts/bindings/behaviors/zmk,behavior-macro.yaml b/app/dts/bindings/behaviors/zmk,behavior-macro.yaml index e6f6757d49a..035dd943542 100644 --- a/app/dts/bindings/behaviors/zmk,behavior-macro.yaml +++ b/app/dts/bindings/behaviors/zmk,behavior-macro.yaml @@ -5,15 +5,4 @@ description: Macro Behavior compatible: "zmk,behavior-macro" -include: zero_param.yaml - -properties: - bindings: - type: phandle-array - required: true - wait-ms: - type: int - description: The default time to wait (in milliseconds) before triggering the next behavior in the macro bindings list. - tap-ms: - type: int - description: The default time to wait (in milliseconds) between the press and release events on a tapped macro behavior binding +include: [zero_param.yaml, macro_base.yaml] diff --git a/app/dts/bindings/macros/zmk,macro-param-1to1.yaml b/app/dts/bindings/macros/zmk,macro-param-1to1.yaml new file mode 100644 index 00000000000..ae0d54dfbeb --- /dev/null +++ b/app/dts/bindings/macros/zmk,macro-param-1to1.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2023 The ZMK Contributors +# SPDX-License-Identifier: MIT + +description: Macro Parameter One Substituted Into Next Binding's First Parameter + +compatible: "zmk,macro-param-1to1" + +include: zero_param.yaml diff --git a/app/dts/bindings/macros/zmk,macro-param-1to2.yaml b/app/dts/bindings/macros/zmk,macro-param-1to2.yaml new file mode 100644 index 00000000000..1018526cbea --- /dev/null +++ b/app/dts/bindings/macros/zmk,macro-param-1to2.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2023 The ZMK Contributors +# SPDX-License-Identifier: MIT + +description: Macro Parameter One Substituted Into Next Binding's Second Parameter + +compatible: "zmk,macro-param-1to2" + +include: zero_param.yaml diff --git a/app/dts/bindings/macros/zmk,macro-param-2to1.yaml b/app/dts/bindings/macros/zmk,macro-param-2to1.yaml new file mode 100644 index 00000000000..3ebf8fc905d --- /dev/null +++ b/app/dts/bindings/macros/zmk,macro-param-2to1.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2023 The ZMK Contributors +# SPDX-License-Identifier: MIT + +description: Macro Parameter Two Substituted Into Next Binding's First Parameter + +compatible: "zmk,macro-param-2to1" + +include: zero_param.yaml diff --git a/app/dts/bindings/macros/zmk,macro-param-2to2.yaml b/app/dts/bindings/macros/zmk,macro-param-2to2.yaml new file mode 100644 index 00000000000..e3ebe40fb3a --- /dev/null +++ b/app/dts/bindings/macros/zmk,macro-param-2to2.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2023 The ZMK Contributors +# SPDX-License-Identifier: MIT + +description: Macro Parameter Two Substituted Into Next Binding's Second Parameter + +compatible: "zmk,macro-param-2to2" + +include: zero_param.yaml diff --git a/app/src/behaviors/behavior_macro.c b/app/src/behaviors/behavior_macro.c index e84f1fc89bb..c47284531a7 100644 --- a/app/src/behaviors/behavior_macro.c +++ b/app/src/behaviors/behavior_macro.c @@ -4,8 +4,6 @@ * SPDX-License-Identifier: MIT */ -#define DT_DRV_COMPAT zmk_behavior_macro - #include #include #include @@ -15,20 +13,22 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); -#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) - enum behavior_macro_mode { MACRO_MODE_TAP, MACRO_MODE_PRESS, MACRO_MODE_RELEASE, }; +enum param_source { PARAM_SOURCE_BINDING, PARAM_SOURCE_MACRO_1ST, PARAM_SOURCE_MACRO_2ND }; + struct behavior_macro_trigger_state { uint32_t wait_ms; uint32_t tap_ms; enum behavior_macro_mode mode; uint16_t start_index; uint16_t count; + enum param_source param1_source; + enum param_source param2_source; }; struct behavior_macro_state { @@ -52,6 +52,11 @@ struct behavior_macro_config { #define WAIT_TIME DT_PROP(DT_INST(0, zmk_macro_control_wait_time), label) #define WAIT_REL DT_PROP(DT_INST(0, zmk_macro_pause_for_release), label) +#define P1TO1 DT_PROP(DT_INST(0, zmk_macro_param_1to1), label) +#define P1TO2 DT_PROP(DT_INST(0, zmk_macro_param_1to2), label) +#define P2TO1 DT_PROP(DT_INST(0, zmk_macro_param_2to1), label) +#define P2TO2 DT_PROP(DT_INST(0, zmk_macro_param_2to2), label) + #define ZM_IS_NODE_MATCH(a, b) (strcmp(a, b) == 0) #define IS_TAP_MODE(dev) ZM_IS_NODE_MATCH(dev, TAP_MODE) #define IS_PRESS_MODE(dev) ZM_IS_NODE_MATCH(dev, PRESS_MODE) @@ -61,6 +66,11 @@ struct behavior_macro_config { #define IS_WAIT_TIME(dev) ZM_IS_NODE_MATCH(dev, WAIT_TIME) #define IS_PAUSE(dev) ZM_IS_NODE_MATCH(dev, WAIT_REL) +#define IS_P1TO1(dev) ZM_IS_NODE_MATCH(dev, P1TO1) +#define IS_P1TO2(dev) ZM_IS_NODE_MATCH(dev, P1TO2) +#define IS_P2TO1(dev) ZM_IS_NODE_MATCH(dev, P2TO1) +#define IS_P2TO2(dev) ZM_IS_NODE_MATCH(dev, P2TO2) + static bool handle_control_binding(struct behavior_macro_trigger_state *state, const struct zmk_behavior_binding *binding) { if (IS_TAP_MODE(binding->behavior_dev)) { @@ -78,6 +88,18 @@ static bool handle_control_binding(struct behavior_macro_trigger_state *state, } else if (IS_WAIT_TIME(binding->behavior_dev)) { state->wait_ms = binding->param1; LOG_DBG("macro wait time set: %d", state->wait_ms); + } else if (IS_P1TO1(binding->behavior_dev)) { + state->param1_source = PARAM_SOURCE_MACRO_1ST; + LOG_DBG("macro param: 1to1"); + } else if (IS_P1TO2(binding->behavior_dev)) { + state->param2_source = PARAM_SOURCE_MACRO_1ST; + LOG_DBG("macro param: 1to2"); + } else if (IS_P2TO1(binding->behavior_dev)) { + state->param1_source = PARAM_SOURCE_MACRO_2ND; + LOG_DBG("macro param: 2to1"); + } else if (IS_P2TO2(binding->behavior_dev)) { + state->param2_source = PARAM_SOURCE_MACRO_2ND; + LOG_DBG("macro param: 2to2"); } else { return false; } @@ -110,21 +132,47 @@ static int behavior_macro_init(const struct device *dev) { return 0; }; +static uint32_t select_param(enum param_source param_source, uint32_t source_binding, + const struct zmk_behavior_binding *macro_binding) { + switch (param_source) { + case PARAM_SOURCE_MACRO_1ST: + return macro_binding->param1; + case PARAM_SOURCE_MACRO_2ND: + return macro_binding->param2; + default: + return source_binding; + } +}; + +static void replace_params(struct behavior_macro_trigger_state *state, + struct zmk_behavior_binding *binding, + const struct zmk_behavior_binding *macro_binding) { + binding->param1 = select_param(state->param1_source, binding->param1, macro_binding); + binding->param2 = select_param(state->param2_source, binding->param2, macro_binding); + + state->param1_source = PARAM_SOURCE_BINDING; + state->param2_source = PARAM_SOURCE_BINDING; +} + static void queue_macro(uint32_t position, const struct zmk_behavior_binding bindings[], - struct behavior_macro_trigger_state state) { + struct behavior_macro_trigger_state state, + const struct zmk_behavior_binding *macro_binding) { LOG_DBG("Iterating macro bindings - starting: %d, count: %d", state.start_index, state.count); for (int i = state.start_index; i < state.start_index + state.count; i++) { if (!handle_control_binding(&state, &bindings[i])) { + struct zmk_behavior_binding binding = bindings[i]; + replace_params(&state, &binding, macro_binding); + switch (state.mode) { case MACRO_MODE_TAP: - zmk_behavior_queue_add(position, bindings[i], true, state.tap_ms); - zmk_behavior_queue_add(position, bindings[i], false, state.wait_ms); + zmk_behavior_queue_add(position, binding, true, state.tap_ms); + zmk_behavior_queue_add(position, binding, false, state.wait_ms); break; case MACRO_MODE_PRESS: - zmk_behavior_queue_add(position, bindings[i], true, state.wait_ms); + zmk_behavior_queue_add(position, binding, true, state.wait_ms); break; case MACRO_MODE_RELEASE: - zmk_behavior_queue_add(position, bindings[i], false, state.wait_ms); + zmk_behavior_queue_add(position, binding, false, state.wait_ms); break; default: LOG_ERR("Unknown macro mode: %d", state.mode); @@ -145,7 +193,7 @@ static int on_macro_binding_pressed(struct zmk_behavior_binding *binding, .start_index = 0, .count = state->press_bindings_count}; - queue_macro(event.position, cfg->bindings, trigger_state); + queue_macro(event.position, cfg->bindings, trigger_state, binding); return ZMK_BEHAVIOR_OPAQUE; } @@ -156,7 +204,7 @@ static int on_macro_binding_released(struct zmk_behavior_binding *binding, const struct behavior_macro_config *cfg = dev->config; struct behavior_macro_state *state = dev->data; - queue_macro(event.position, cfg->bindings, state->release_state); + queue_macro(event.position, cfg->bindings, state->release_state, binding); return ZMK_BEHAVIOR_OPAQUE; } @@ -166,22 +214,20 @@ static const struct behavior_driver_api behavior_macro_driver_api = { .binding_released = on_macro_binding_released, }; -#define BINDING_WITH_COMMA(idx, drv_inst) ZMK_KEYMAP_EXTRACT_BINDING(idx, DT_DRV_INST(drv_inst)) - #define TRANSFORMED_BEHAVIORS(n) \ - {LISTIFY(DT_PROP_LEN(DT_DRV_INST(n), bindings), BINDING_WITH_COMMA, (, ), n)}, - -#define MACRO_INST(n) \ - static struct behavior_macro_state behavior_macro_state_##n = {}; \ - static struct behavior_macro_config behavior_macro_config_##n = { \ - .default_wait_ms = DT_INST_PROP_OR(n, wait_ms, CONFIG_ZMK_MACRO_DEFAULT_WAIT_MS), \ - .default_tap_ms = DT_INST_PROP_OR(n, tap_ms, CONFIG_ZMK_MACRO_DEFAULT_TAP_MS), \ - .count = DT_INST_PROP_LEN(n, bindings), \ - .bindings = TRANSFORMED_BEHAVIORS(n)}; \ - DEVICE_DT_INST_DEFINE(n, behavior_macro_init, NULL, &behavior_macro_state_##n, \ - &behavior_macro_config_##n, APPLICATION, \ - CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_macro_driver_api); - -DT_INST_FOREACH_STATUS_OKAY(MACRO_INST) - -#endif /* DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) */ + {LISTIFY(DT_PROP_LEN(n, bindings), ZMK_KEYMAP_EXTRACT_BINDING, (, ), n)}, + +#define MACRO_INST(inst) \ + static struct behavior_macro_state behavior_macro_state_##inst = {}; \ + static struct behavior_macro_config behavior_macro_config_##inst = { \ + .default_wait_ms = DT_PROP_OR(inst, wait_ms, CONFIG_ZMK_MACRO_DEFAULT_WAIT_MS), \ + .default_tap_ms = DT_PROP_OR(inst, tap_ms, CONFIG_ZMK_MACRO_DEFAULT_TAP_MS), \ + .count = DT_PROP_LEN(inst, bindings), \ + .bindings = TRANSFORMED_BEHAVIORS(inst)}; \ + DEVICE_DT_DEFINE(inst, behavior_macro_init, NULL, &behavior_macro_state_##inst, \ + &behavior_macro_config_##inst, APPLICATION, \ + CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_macro_driver_api); + +DT_FOREACH_STATUS_OKAY(zmk_behavior_macro, MACRO_INST) +DT_FOREACH_STATUS_OKAY(zmk_behavior_macro_one_param, MACRO_INST) +DT_FOREACH_STATUS_OKAY(zmk_behavior_macro_two_param, MACRO_INST) diff --git a/app/tests/macros/place-holder-parameters/events.patterns b/app/tests/macros/place-holder-parameters/events.patterns new file mode 100644 index 00000000000..3c9d3f838c6 --- /dev/null +++ b/app/tests/macros/place-holder-parameters/events.patterns @@ -0,0 +1 @@ +s/.*hid_listener_keycode/kp/p \ No newline at end of file diff --git a/app/tests/macros/place-holder-parameters/keycode_events.snapshot b/app/tests/macros/place-holder-parameters/keycode_events.snapshot new file mode 100644 index 00000000000..f198a49b81e --- /dev/null +++ b/app/tests/macros/place-holder-parameters/keycode_events.snapshot @@ -0,0 +1,16 @@ +kp_pressed: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00 +kp_pressed: usage_page 0x07 keycode 0x38 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0x38 implicit_mods 0x00 explicit_mods 0x00 +kp_pressed: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00 +kp_pressed: usage_page 0x07 keycode 0x34 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0x34 implicit_mods 0x00 explicit_mods 0x00 +kp_pressed: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00 +kp_pressed: usage_page 0x07 keycode 0x34 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0x34 implicit_mods 0x00 explicit_mods 0x00 +kp_pressed: usage_page 0x07 keycode 0x08 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0x08 implicit_mods 0x00 explicit_mods 0x00 +kp_pressed: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00 diff --git a/app/tests/macros/place-holder-parameters/native_posix_64.keymap b/app/tests/macros/place-holder-parameters/native_posix_64.keymap new file mode 100644 index 00000000000..59d78b5e8fb --- /dev/null +++ b/app/tests/macros/place-holder-parameters/native_posix_64.keymap @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2022 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include +#include +#include + +/ { + macros { + slash_macro: slash_macro { + #binding-cells = <2>; + label = "ZM_SLASH"; + compatible = "zmk,behavior-macro-two-param"; + wait-ms = <40>; + tap-ms = <40>; + bindings = < + ¯o_param_1to1 &kp MACRO_PLACEHOLDER + &kp SLASH + ¯o_param_2to1 &kp MACRO_PLACEHOLDER>; + }; + + to_second_macro: to_second_macro { + #binding-cells = <2>; + label = "ZMK_TO_SECOND"; + compatible = "zmk,behavior-macro-two-param"; + wait-ms = <40>; + tap-ms = <40>; + bindings = < + ¯o_param_1to2 &mt LSHIFT MACRO_PLACEHOLDER + ¯o_param_2to2 &mt RSHIFT MACRO_PLACEHOLDER>; + }; + + quote_letter_macro: quote_letter_macro { + #binding-cells = <1>; + label = "ZMK_QLET"; + compatible = "zmk,behavior-macro-one-param"; + wait-ms = <40>; + tap-ms = <40>; + bindings = < + &kp QUOT + ¯o_param_1to1 &kp MACRO_PLACEHOLDER + &kp QUOT>; + }; + }; + + keymap { + compatible = "zmk,keymap"; + label = "Default keymap"; + + default_layer { + bindings = < + &slash_macro A B "e_letter_macro B + &to_second_macro E F &kp C>; + }; + }; +}; + +&kscan { + events = ; +}; \ No newline at end of file diff --git a/docs/docs/behaviors/macros.md b/docs/docs/behaviors/macros.md index 1628e0cb554..40c333a9066 100644 --- a/docs/docs/behaviors/macros.md +++ b/docs/docs/behaviors/macros.md @@ -49,6 +49,22 @@ For use cases involving sending a single keycode with modifiers, for instance ct with [modifier functions](../codes/modifiers.mdx#modifier-functions) can be used instead of a macro. ::: +### Parameterized Macros + +Macros can also be "parameterized", allowing them to be bound in your keymap with unique values passed into them, e.g.: + +``` + raise_layer { + bindings = <&my_cool_macro A> + }; +``` + +When defining a parameterized macro, a different `compatible` value will be used depending on how many parameters are passed into it: + +- `zmk,behavior-macro` - a parameter that takes no parameters. +- `zmk,behavior-macro-one-param` - a parameter that takes one parameter when used. +- `zmk,behavior-macro-two-param` - a parameter that takes two parameters when used. + ### Bindings Like [hold-taps](/docs/behaviors/hold-tap), macros are created by composing other behaviors, and any of those behaviors can @@ -67,6 +83,30 @@ bindings There are a set of special macro controls that can be included in the `bindings` list to modify the way the macro is processed. +### Parameters + +When creating a macro that takes parameter(s), there are macro controls that change when the parameters passed to the macro are used +within the macro itself. All of the controls are "one shot" and will change how the passed in parameters are used for the very next non-macro control behavior in the `bindings` list of the macro. + +For example, to pass the first parameter from the macro into a `&kp` used in the macro, you would use: + +``` +bindings + = <¯o_param_1to1> + , <&kp MACRO_PLACEHOLDER> + ; +``` + +Because `kp` takes one parameter, you can't simply make the second entry `<&kp>` in the `bindings` list. Whatever value you do pass in will be replaced when the macro is triggered, so you can put _any_ value there, e.g. `0`, `A` keycode, etc. To make it very obvious that the parameter there is not actually going to be used, you can use `MACRO_PLACEHOLDER` which is simply an alias for `0`. + +The available parameter controls are: + +- `¯o_param_1to1` - pass the first parameter of the macro into the first parameter of the next behavior in the `bindings` list. +- `¯o_param_1to2` - pass the first parameter of the macro into the second parameter of the next behavior in the `bindings` list. + +* `¯o_param_2to1` - pass the second parameter of the macro into the first parameter of the next behavior in the `bindings` list. +* `¯o_param_2to2` - pass the second parameter of the macro into the second parameter of the next behavior in the `bindings` list. + ### Binding Activation Mode Bindings in a macro are activated differently, depending on the current "activation mode" of the macro. From b259d5a22e423458b94bd1aba70fd62f327528c0 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Tue, 20 Jun 2023 22:23:06 +0000 Subject: [PATCH 30/76] fix(sensors): Sensor rotate behavior fix for layers. * Properly return transparent value when processing mode for higher disabled layers means the processing is ignored. --- app/src/behaviors/behavior_sensor_rotate_common.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/behaviors/behavior_sensor_rotate_common.c b/app/src/behaviors/behavior_sensor_rotate_common.c index eea7bf48476..586cac3fdf2 100644 --- a/app/src/behaviors/behavior_sensor_rotate_common.c +++ b/app/src/behaviors/behavior_sensor_rotate_common.c @@ -65,7 +65,7 @@ int zmk_behavior_sensor_rotate_common_process(struct zmk_behavior_binding *bindi if (mode != BEHAVIOR_SENSOR_BINDING_PROCESS_MODE_TRIGGER) { data->triggers[sensor_index] = 0; - return 0; + return ZMK_BEHAVIOR_TRANSPARENT; } int triggers = data->triggers[sensor_index]; @@ -83,7 +83,7 @@ int zmk_behavior_sensor_rotate_common_process(struct zmk_behavior_binding *bindi triggered_binding.param1 = binding->param2; } } else { - return 0; + return ZMK_BEHAVIOR_TRANSPARENT; } LOG_DBG("Sensor binding: %s", binding->behavior_dev); From 3772ecb04e777ec4d592711427211cfac26a712d Mon Sep 17 00:00:00 2001 From: Kyle McCreery Date: Wed, 5 Jul 2023 12:50:19 -0400 Subject: [PATCH 31/76] fix(boards): Update pillbug_defconfig to enable pinctrl --- app/boards/arm/pillbug/pillbug_defconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/boards/arm/pillbug/pillbug_defconfig b/app/boards/arm/pillbug/pillbug_defconfig index d71d9f62626..9781cf995cc 100644 --- a/app/boards/arm/pillbug/pillbug_defconfig +++ b/app/boards/arm/pillbug/pillbug_defconfig @@ -8,6 +8,9 @@ CONFIG_BOARD_PILLBUG=y # Enable MPU CONFIG_ARM_MPU=y +# Use pinctrl +CONFIG_PINCTRL=y + # enable GPIO CONFIG_GPIO=y From bbb27ac02769c7bf5f20b76605f2b4e0f811e6e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=83=95=E3=82=A3=E3=83=AB=E3=82=BF=E3=83=BC=E3=83=9A?= =?UTF-8?q?=E3=83=BC=E3=83=91=E3=83=BC?= <76888457+filterpaper@users.noreply.github.com> Date: Fri, 7 Jul 2023 01:39:08 +0800 Subject: [PATCH 32/76] feat(docs): Note that UF2 drive unmounts after flashing (#1859) Add a note about the UF2 drive that automatically unmounts itself to restart, which may surprise some new users. --- docs/docs/development/build-flash.md | 4 ++-- docs/docs/user-setup.md | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/docs/development/build-flash.md b/docs/docs/development/build-flash.md index 6f4ba84d23e..f57c4b5caf9 100644 --- a/docs/docs/development/build-flash.md +++ b/docs/docs/development/build-flash.md @@ -130,8 +130,8 @@ The above build commands generate a UF2 file in `build/zephyr` (or `build/left|right/zephyr` if you followed the instructions for splits) and is by default named `zmk.uf2`. If your board supports USB Flashing Format (UF2), copy that file onto the root of the USB mass storage device for your board. The -controller should flash your built firmware and automatically restart once -flashing is complete. +controller should flash your built firmware, unmount the USB storage device and +automatically restart once flashing is complete. Alternatively, if your board supports flashing and you're not developing from within a Dockerized environment, enable Device Firmware Upgrade (DFU) mode on diff --git a/docs/docs/user-setup.md b/docs/docs/user-setup.md index 8faa72df85f..9d04c347d58 100644 --- a/docs/docs/user-setup.md +++ b/docs/docs/user-setup.md @@ -198,8 +198,9 @@ To flash the firmware, first put your board into bootloader mode by double click or the one that is part of your keyboard). The controller should appear in your OS as a new USB storage device. Once this happens, copy the correct UF2 file (e.g. left or right if working on a split), and paste it onto the root of that USB mass -storage device. Once the flash is complete, the controller should automatically restart, and load your newly flashed firmware. It is -recommended that you test your keyboard works over USB first to rule out hardware issues, before trying to connect to it wirelessly. +storage device. Once the flash is complete, the controller should unmount the USB storage, automatically restart and load your newly +flashed firmware. It is recommended that you test your keyboard works over USB first to rule out hardware issues, before trying to +connect to it wirelessly. :::caution Split keyboards From aaf9958d865ac28659d16e1ea1ba356f7e742ea8 Mon Sep 17 00:00:00 2001 From: ClicketySplit <101202583+ClicketySplit@users.noreply.github.com> Date: Mon, 17 Jul 2023 15:26:27 -0600 Subject: [PATCH 33/76] feat(boards): Leeloo v2 and V2 Zephyr 3.2 fixes * Add Leeloo v2 * Leeloo-Micro v1 updates to support Zephyr 3.2 * Refactored for new Encoder Configuration Co-authored-by: Cem Aksoylar --- app/boards/shields/leeloo/Kconfig.defconfig | 15 +- app/boards/shields/leeloo/Kconfig.shield | 15 +- app/boards/shields/leeloo/README.md | 120 +++++++++++--- .../leeloo/boards/nice_nano_v2.overlay | 47 ++++++ app/boards/shields/leeloo/leeloo.conf | 11 +- app/boards/shields/leeloo/leeloo.dtsi | 85 +--------- app/boards/shields/leeloo/leeloo.keymap | 37 +++-- app/boards/shields/leeloo/leeloo_common.dtsi | 90 +++++++++++ app/boards/shields/leeloo/leeloo_left.overlay | 6 +- app/boards/shields/leeloo/leeloo_rev2.conf | 43 +++++ app/boards/shields/leeloo/leeloo_rev2.dtsi | 6 + app/boards/shields/leeloo/leeloo_rev2.keymap | 79 +++++++++ app/boards/shields/leeloo/leeloo_rev2.zmk.yml | 15 ++ .../shields/leeloo/leeloo_rev2_left.overlay | 21 +++ .../shields/leeloo/leeloo_rev2_right.overlay | 25 +++ .../shields/leeloo/leeloo_right.overlay | 6 +- .../shields/leeloo_micro/Kconfig.defconfig | 49 ++++++ .../shields/leeloo_micro/Kconfig.shield | 13 ++ app/boards/shields/leeloo_micro/README.md | 89 +++++++++++ .../leeloo_micro/boards/nice_nano_v2.overlay | 47 ++++++ .../shields/leeloo_micro/leeloo_micro.conf | 38 +++++ .../shields/leeloo_micro/leeloo_micro.dtsi | 88 ++++++++++ .../shields/leeloo_micro/leeloo_micro.keymap | 151 ++++++++++++++++++ .../shields/leeloo_micro/leeloo_micro.zmk.yml | 15 ++ .../leeloo_micro/leeloo_micro_left.overlay | 20 +++ .../leeloo_micro/leeloo_micro_right.overlay | 24 +++ 26 files changed, 1027 insertions(+), 128 deletions(-) create mode 100644 app/boards/shields/leeloo/boards/nice_nano_v2.overlay create mode 100644 app/boards/shields/leeloo/leeloo_common.dtsi create mode 100644 app/boards/shields/leeloo/leeloo_rev2.conf create mode 100644 app/boards/shields/leeloo/leeloo_rev2.dtsi create mode 100644 app/boards/shields/leeloo/leeloo_rev2.keymap create mode 100644 app/boards/shields/leeloo/leeloo_rev2.zmk.yml create mode 100644 app/boards/shields/leeloo/leeloo_rev2_left.overlay create mode 100644 app/boards/shields/leeloo/leeloo_rev2_right.overlay create mode 100644 app/boards/shields/leeloo_micro/Kconfig.defconfig create mode 100644 app/boards/shields/leeloo_micro/Kconfig.shield create mode 100644 app/boards/shields/leeloo_micro/README.md create mode 100644 app/boards/shields/leeloo_micro/boards/nice_nano_v2.overlay create mode 100644 app/boards/shields/leeloo_micro/leeloo_micro.conf create mode 100644 app/boards/shields/leeloo_micro/leeloo_micro.dtsi create mode 100644 app/boards/shields/leeloo_micro/leeloo_micro.keymap create mode 100644 app/boards/shields/leeloo_micro/leeloo_micro.zmk.yml create mode 100644 app/boards/shields/leeloo_micro/leeloo_micro_left.overlay create mode 100644 app/boards/shields/leeloo_micro/leeloo_micro_right.overlay diff --git a/app/boards/shields/leeloo/Kconfig.defconfig b/app/boards/shields/leeloo/Kconfig.defconfig index 7388a4b9af0..046bd49a3dd 100644 --- a/app/boards/shields/leeloo/Kconfig.defconfig +++ b/app/boards/shields/leeloo/Kconfig.defconfig @@ -1,6 +1,16 @@ -# Copyright (c) 2022 The ZMK Contributors +# Copyright (c) 2023 The ZMK Contributors # SPDX-License-Identifier: MIT +if SHIELD_LEELOO_REV2_LEFT + +config ZMK_KEYBOARD_NAME + default "Leeloo v2" + +config ZMK_SPLIT_ROLE_CENTRAL + default y + +endif + if SHIELD_LEELOO_LEFT config ZMK_KEYBOARD_NAME @@ -11,7 +21,7 @@ config ZMK_SPLIT_ROLE_CENTRAL endif -if SHIELD_LEELOO_LEFT || SHIELD_LEELOO_RIGHT +if SHIELD_LEELOO config ZMK_SPLIT default y @@ -31,7 +41,6 @@ endif # ZMK_DISPLAY if LVGL - config LV_Z_VDB_SIZE default 64 diff --git a/app/boards/shields/leeloo/Kconfig.shield b/app/boards/shields/leeloo/Kconfig.shield index 46ea96400fb..1d7843957e5 100644 --- a/app/boards/shields/leeloo/Kconfig.shield +++ b/app/boards/shields/leeloo/Kconfig.shield @@ -1,8 +1,21 @@ -# Copyright (c) 2022 The ZMK Contributors +# Copyright (c) 2023 The ZMK Contributors # SPDX-License-Identifier: MIT +config SHIELD_LEELOO + bool + config SHIELD_LEELOO_LEFT def_bool $(shields_list_contains,leeloo_left) + select SHIELD_LEELOO config SHIELD_LEELOO_RIGHT def_bool $(shields_list_contains,leeloo_right) + select SHIELD_LEELOO + +config SHIELD_LEELOO_REV2_LEFT + def_bool $(shields_list_contains,leeloo_rev2_left) + select SHIELD_LEELOO + +config SHIELD_LEELOO_REV2_RIGHT + def_bool $(shields_list_contains,leeloo_rev2_right) + select SHIELD_LEELOO \ No newline at end of file diff --git a/app/boards/shields/leeloo/README.md b/app/boards/shields/leeloo/README.md index a807843f08f..27d5e872b5a 100644 --- a/app/boards/shields/leeloo/README.md +++ b/app/boards/shields/leeloo/README.md @@ -1,41 +1,123 @@ -# Clickety Split | Leeloo +# Clickety Split | Leeloo v2 -![Leeloo](https://cdn.shopify.com/s/files/1/0599/3460/5491/files/Leeloo-rev1.0-w.jpg?v=1646798726) +![Leeloo v2](https://github.com/ClicketySplit/build-guides/blob/main/leeloo/images/gallery/Leeloo-v2-ZMK.jpg) Keyboard Designer: [clicketysplit.ca](https://clicketysplit.ca) GitHub: [ClicketySplit](https://github.com/ClicketySplit) -Hardware Supported: Pro Micro, Elite-C, nice!nano v2 +Hardware Supported: Pro Micro, Elite-C, and nice!nano v2 -Albeit, there is no doubt where Leeloo's heritage is derived from—Lily58, and Corne. It is not a copy-paste-modify implementation. +Leeloo v2 has been designed from scratch—again. Everything from the wiring schematic to its case. Leeloo v2 still keeps the column stagger that it's known for, along with its low profile design. -Leeloo has been designed from scratch; everything from the schematic to its PCB footprints, and column stagger. There are some subtle differences that may not be apparent; however, its subtle changes enable an interesting future. +## Features/Differences from Leeloo v1 -Features: +- Support for Kailh Low Profile Choc switches with 18mm x 18mm spacing. + - A version for Kailh Box/MX switches with 19.05mm x 19.05mm spacing will be available in the future. +- All switch locations are socketed. +- Rotary encoder locations are socketed. + - One of two locations on each side can be used for a rotary encoder. +- OLED Displays and nice!view Displays are natively supported, socketed, and no extra wiring is required. +- Support for per-switch RGB underglow. +- Better location for 110mAh or 700mAh batteries. + - Different location for soldering battery leads. +- Support for Alps Alpine Micro On/off switches. + +# Leeloo v1 + +![Leeloo](https://github.com/ClicketySplit/build-guides/blob/main/leeloo/images/gallery/Leeloo-v1.jpg) + +## Features - 4x6x5m Split Keyboard -- Support for MX/Box or Low Profile Choc switches. -- 90% of the switches are socketed; with the exception to the rotary encoder positions—6 positions require soldering. -- Support for 128x32 OLED Displays. -- The option to select one of three positions for an EC11 rotary encoder on each half. -- Support for Alps Alpine Micro Switch -- Support for 3.7v 301230 LiPo Battery +- Support for both Low Profile Choc switches, and Box/MX switches; 19.05mm x 19.05mm spacing. +- 90% of the switches are socketed; with the exception to the rotary encoder positions. +- Support for Alps Alpine EC11 Rotary Encoders—one on each side, in one of three locations. +- Support for OLED Displays or nice!view Displays. + - nice!view displays require a wire to be soldered from the CS Pin on nice!view display to P0.22 or D4 on the nice!nano. +- Support for both 110mAh or 700mAh batteries. +- Solder pads for battery leads. +- Support for Alps Alpine Micro On/off switches. -# Building Your Firmware +# Building Leeloo's ZMK Firmware ZMK Firmware: [Introduction to ZMK](https://zmk.dev/docs/) Installation: [Installing ZMK](https://zmk.dev/docs/user-setup) Customization: [Customizing ZMK](https://zmk.dev/docs/customization) Development Environment: [Basic Setup](https://zmk.dev/docs/development/setup) -Build command for the default keymap of Leeloo: +Build commands for the default keymap of Leeloo v1: + +``` +west build -d build/left -p -b nice_nano_v2 -- -DSHIELD=leeloo_left +west build -d build/right -p -b nice_nano_v2 -- -DSHIELD=leeloo_right +``` + +Build commands for the default keymap of Leeloo v2: + +``` +west build -d build/left_v2 -p -b nice_nano_v2 -- -DSHIELD=leeloo_rev2_left +west build -d build/right_v2 -p -b nice_nano_v2 -- -DSHIELD=leeloo_rev2_right +``` + +Build commands for your custom keymap of Leeloo v1: + +``` +west build -d build/right -p -b nice_nano_v2 -- -DSHIELD=leeloo_right -DZMK_CONFIG="C:/dev/zmk/[yourName]/leeloo/config" +west build -d build/left -p -b nice_nano_v2 -- -DSHIELD=leeloo_left -DZMK_CONFIG="C:/dev/zmk/[yourName]/leeloo/config" +``` + +Build commands for your custom keymap of Leeloo v2: + +``` +west build -d build/right_v2 -p -b nice_nano_v2 -- -DSHIELD=leeloo_rev2_right -DZMK_CONFIG="C:/dev/zmk/[yourName]/leeloo_v2/config" +west build -d build/left_v2 -p -b nice_nano_v2 -- -DSHIELD=leeloo_rev2_left -DZMK_CONFIG="C:/dev/zmk/[yourName]/leeloo_v2/config" +``` + +## Building Leeloo's ZMK Firmware with nice!view Displays + +There are a couple of files that need to be adjusted before the build commands can be run. + +### Edit the leeloo[_rev2].keymap File + +Near the top 3rd of the leeloo[_rev2].keymap file, locate the following code block: + +``` +//nice_view_spi: &spi0 { +// cs-gpios = <&pro_micro 4 GPIO_ACTIVE_HIGH>; +//}; +``` + +Remove the forward slashes to resemble the following: + +``` +nice_view_spi: &spi0 { + cs-gpios = <&pro_micro 4 GPIO_ACTIVE_HIGH>; +}; +``` + +Save your changes and close the file. + +### Sample Build Commands for nice!view Displays + +Build commands for the default keymap of Leeloo v1: + +``` +west build -d build/left -p -b nice_nano_v2 -- -DSHIELD="leeloo_left nice_view_adapter nice_view" +west build -d build/right -p -b nice_nano_v2 -- -DSHIELD="leeloo_right nice_view_adapter nice_view" +``` + +Build commands for the default keymap of Leeloo v2: - west build -d build/left -p -b nice_nano_v2 -- -DSHIELD=leeloo_left - west build -d build/right -p -b nice_nano_v2 -- -DSHIELD=leeloo_right +``` +west build -d build/left_v2 -p -b nice_nano_v2 -- -DSHIELD="leeloo_rev2_left nice_view_adapter nice_view" +west build -d build/right_v2 -p -b nice_nano_v2 -- -DSHIELD="leeloo_rev2_right nice_view_adapter nice_view" +``` -Build command for your custom keymap of Leeloo: +Build commands for your custom keymap of Leeloo v2: - west build -d build/right -p -b nice_nano_v2 -- -DSHIELD=leeloo_right -DZMK_CONFIG="C:/dev/zmk/[yourNmae]/leeloo/config" - west build -d build/left -p -b nice_nano_v2 -- -DSHIELD=leeloo_left -DZMK_CONFIG="C:/dev/zmk/[yourName]/leeloo/config" +``` +west build -d build/left -p -b nice_nano_v2 -- -DSHIELD="leeloo_rev2_left nice_view_adapter nice_view" -DZMK_CONFIG="/workspaces/zmk-config/[yourName]/leeloo_v2/config" +west build -d build/right -p -b nice_nano_v2 -- -DSHIELD="leeloo_rev2_right nice_view_adapter nice_view" -DZMK_CONFIG="/workspaces/zmk-config/[yourName]/leeloo_v2/config" +``` # Support diff --git a/app/boards/shields/leeloo/boards/nice_nano_v2.overlay b/app/boards/shields/leeloo/boards/nice_nano_v2.overlay new file mode 100644 index 00000000000..5c451b73eaf --- /dev/null +++ b/app/boards/shields/leeloo/boards/nice_nano_v2.overlay @@ -0,0 +1,47 @@ +#include + +&pinctrl { + spi3_default: spi3_default { + group1 { + psels = ; + }; + }; + + spi3_sleep: spi3_sleep { + group1 { + psels = ; + low-power-enable; + }; + }; +}; + +&spi3 { + compatible = "nordic,nrf-spim"; + status = "okay"; + + pinctrl-0 = <&spi3_default>; + pinctrl-1 = <&spi3_sleep>; + pinctrl-names = "default", "sleep"; + + led_strip: ws2812@0 { + compatible = "worldsemi,ws2812-spi"; + label = "WS2812"; + + /* SPI */ + reg = <0>; /* ignored, but necessary for SPI bindings */ + spi-max-frequency = <4000000>; + + /* WS2812 */ + chain-length = <37>; /* arbitrary; change at will */ + spi-one-frame = <0x70>; + spi-zero-frame = <0x40>; + + color-mapping = ; + }; +}; + +/ { + chosen { + zmk,underglow = &led_strip; + }; +}; \ No newline at end of file diff --git a/app/boards/shields/leeloo/leeloo.conf b/app/boards/shields/leeloo/leeloo.conf index a652bb65144..466279a33e3 100644 --- a/app/boards/shields/leeloo/leeloo.conf +++ b/app/boards/shields/leeloo/leeloo.conf @@ -1,9 +1,16 @@ -# Copyright (c) 2022 The ZMK Contributors +# Copyright (c) 2023 The ZMK Contributors # SPDX-License-Identifier: MIT # Uncomment the following line to enable the OLED Display # CONFIG_ZMK_DISPLAY=y +# Uncomment to turn off WPM Status. +# CONFIG_ZMK_WIDGET_WPM_STATUS=n + +# Uncomment to invert colour when using nice!view Displays +# CONFIG_ZMK_DISPLAY_INVERT=y + + # Uncomment these two lines to add support for encoders # CONFIG_EC11=y -# CONFIG_EC11_TRIGGER_GLOBAL_THREAD=y +# CONFIG_EC11_TRIGGER_GLOBAL_THREAD=y \ No newline at end of file diff --git a/app/boards/shields/leeloo/leeloo.dtsi b/app/boards/shields/leeloo/leeloo.dtsi index 438f9a9d924..dad05c55c6e 100644 --- a/app/boards/shields/leeloo/leeloo.dtsi +++ b/app/boards/shields/leeloo/leeloo.dtsi @@ -1,87 +1,6 @@ /* - * Copyright (c) 2022 The ZMK Contributors - * + * Copyright (c) 2023 The ZMK Contributors * SPDX-License-Identifier: MIT */ -#include -/ { - chosen { - zephyr,display = &oled; - zmk,kscan = &kscan0; - zmk,matrix_transform = &default_transform; - }; - - default_transform: keymap_transform_0 { - compatible = "zmk,matrix-transform"; - columns = <12>; - rows = <5>; -// | SW1 | SW2 | SW3 | SW4 | SW5 | SW6 | | SW6 | SW5 | SW4 | SW3 | SW2 | SW1 | -// | SW7 | SW8 | SW9 | SW10 | SW11 | SW12 | | SW12 | SW11 | SW10 | SW9 | SW8 | SW7 | -// | SW13 | SW14 | SW15 | SW16 | SW17 | SW18 | | SW18 | SW17 | SW16 | SW15 | SW14 | SW13 | -// | SW19 | SW20 | SW21 | SW22 | SW23 | SW24 | SW29 | | SW29 | SW24 | SW23 | SW22 | SW21 | SW20 | SW19 | -// | SW25 | SW26 | SW27 | SW28 | | SW28 | SW27 | SW26 | SW25 | - map = < -RC(0,0) RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(0,5) RC(0,6) RC(0,7) RC(0,8) RC(0,9) RC(0,10) RC(0,11) -RC(1,0) RC(1,1) RC(1,2) RC(1,3) RC(1,4) RC(1,5) RC(1,6) RC(1,7) RC(1,8) RC(1,9) RC(1,10) RC(1,11) -RC(2,0) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(2,5) RC(2,6) RC(2,7) RC(2,8) RC(2,9) RC(2,10) RC(2,11) -RC(3,0) RC(3,1) RC(3,2) RC(3,3) RC(3,4) RC(3,5) RC(3,6) RC(3,7) RC(3,8) RC(3,9) RC(3,10) RC(3,11) - RC(4,1) RC(4,2) RC(4,3) RC(4,4) RC(4,5) RC(4,6) RC(4,7) RC(4,8) RC(4,9) RC(4,10) - >; - }; - - kscan0: kscan { - compatible = "zmk,kscan-gpio-matrix"; - label = "KSCAN"; - - diode-direction = "col2row"; - row-gpios - = <&pro_micro 5 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> - , <&pro_micro 6 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> - , <&pro_micro 7 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> - , <&pro_micro 8 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> - , <&pro_micro 9 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> - ; - }; - - left_encoder: encoder_left { - compatible = "alps,ec11"; - label = "LEFT_ENCODER"; - a-gpios = <&pro_micro 21 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; - b-gpios = <&pro_micro 20 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; - resolution = <4>; - }; - - right_encoder: encoder_right { - compatible = "alps,ec11"; - label = "RIGHT_ENCODER"; - a-gpios = <&pro_micro 20 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; - b-gpios = <&pro_micro 21 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; - resolution = <4>; - }; - - sensors { - compatible = "zmk,keymap-sensors"; - sensors = <&left_encoder &right_encoder>; - }; -}; - -&pro_micro_i2c { - status = "okay"; - - oled: ssd1306@3c { - compatible = "solomon,ssd1306fb"; - reg = <0x3c>; - label = "DISPLAY"; - width = <128>; - height = <32>; - segment-offset = <0>; - page-offset = <0>; - display-offset = <0>; - multiplex-ratio = <31>; - segment-remap; - com-invdir; - com-sequential; - prechargep = <0x22>; - }; -}; +#include "leeloo_common.dtsi" \ No newline at end of file diff --git a/app/boards/shields/leeloo/leeloo.keymap b/app/boards/shields/leeloo/leeloo.keymap index fc3b25e03e2..bdbf8988cc8 100644 --- a/app/boards/shields/leeloo/leeloo.keymap +++ b/app/boards/shields/leeloo/leeloo.keymap @@ -1,17 +1,23 @@ /* - * Copyright (c) 2022 The ZMK Contributors - * + * Copyright (c) 2023 The ZMK Contributors * SPDX-License-Identifier: MIT */ + #include #include #include #include -// Layers -#define DEFAULT 0 // default_layer -#define LOWER 1 // lower_layer -#define RAISE 2 // raise_layer +/* + * Assign the cs-gpios pin to 4. + * Uncomment these next few lines if implementing nice!view Displays + * A wire from the nice!view CS display needs to be connected to the + * High Frequency P0.22, also known as D4 if you choose to refer to + * the pins with Arduino Labels. + */ +//nice_view_spi: &spi0 { +// cs-gpios = <&pro_micro 4 GPIO_ACTIVE_HIGH>; +//}; / { @@ -19,40 +25,43 @@ compatible = "zmk,keymap"; default_layer { + label = " QWERTY"; bindings = < &kp ESC &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 &kp BSLH &kp TAB &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &kp GRAV &kp CAPS &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SEMI &kp SQT -&kp LSHFT &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp RSHFT - &kp LALT &kp LCTRL < 1 RET < 2 MINUS &kp LGUI &kp LGUI < 2 EQUAL < 1 SPACE &kp BSPC &kp DEL +&kp LSHFT &kp Z &kp X &kp C &kp V &kp B &kp LGUI &kp LGUI &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp RSHFT + &kp LALT &kp LCTRL < 1 RET < 2 MINUS < 2 EQUAL < 1 SPACE &kp BSPC &kp DEL >; sensor-bindings = <&inc_dec_kp C_VOL_UP C_VOL_DN>; }; lower_layer { + label = " Lower"; bindings = < &trans &kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &trans &trans &trans &trans &trans &trans &kp PG_UP &kp HOME &kp UP &kp END &trans &kp F12 &trans &trans &trans &trans &trans &trans &kp PG_DN &kp LEFT &kp DOWN &kp RIGHT &trans &trans -&trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans - &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans +&trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans >; sensor-bindings = <&inc_dec_kp C_VOL_UP C_VOL_DN>; }; raise_layer { + label = " Raise"; bindings = < &trans &trans &trans &trans &trans &trans &bt BT_SEL 0 &bt BT_SEL 1 &bt BT_SEL 2 &bt BT_SEL 3 &bt BT_SEL 4 &trans -&trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &sys_reset &bootloader -&trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans +&trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &sys_reset &bootloader &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans - &trans &trans &trans &trans &trans &trans &trans &trans &bt BT_CLR &trans +&trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &bt BT_CLR &trans >; sensor-bindings = <&inc_dec_kp C_VOL_UP C_VOL_DN>; }; }; -}; +}; \ No newline at end of file diff --git a/app/boards/shields/leeloo/leeloo_common.dtsi b/app/boards/shields/leeloo/leeloo_common.dtsi new file mode 100644 index 00000000000..6ce93504b2d --- /dev/null +++ b/app/boards/shields/leeloo/leeloo_common.dtsi @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2023 The ZMK Contributors + * SPDX-License-Identifier: MIT + */ + +#include + +/ { + chosen { + zephyr,display = &oled; + zmk,kscan = &kscan0; + zmk,matrix_transform = &default_transform; + }; + + default_transform: keymap_transform_0 { + compatible = "zmk,matrix-transform"; + columns = <12>; + rows = <5>; +// | SW1 | SW2 | SW3 | SW4 | SW5 | SW6 | | SW6 | SW5 | SW4 | SW3 | SW2 | SW1 | +// | SW7 | SW8 | SW9 | SW10 | SW11 | SW12 | | SW12 | SW11 | SW10 | SW9 | SW8 | SW7 | +// | SW13 | SW14 | SW15 | SW16 | SW17 | SW18 | | SW18 | SW17 | SW16 | SW15 | SW14 | SW13 | +// | SW19 | SW20 | SW21 | SW22 | SW23 | SW24 | SW29 | | SW29 | SW24 | SW23 | SW22 | SW21 | SW20 | SW19 | +// | SW25 | SW26 | SW27 | SW28 | | SW28 | SW27 | SW26 | SW25 | + map = < +RC(0,0) RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(0,5) RC(0,6) RC(0,7) RC(0,8) RC(0,9) RC(0,10) RC(0,11) +RC(1,0) RC(1,1) RC(1,2) RC(1,3) RC(1,4) RC(1,5) RC(1,6) RC(1,7) RC(1,8) RC(1,9) RC(1,10) RC(1,11) +RC(2,0) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(2,5) RC(2,6) RC(2,7) RC(2,8) RC(2,9) RC(2,10) RC(2,11) +RC(3,0) RC(3,1) RC(3,2) RC(3,3) RC(3,4) RC(3,5) RC(4,5) RC(4,6) RC(3,6) RC(3,7) RC(3,8) RC(3,9) RC(3,10) RC(3,11) + RC(4,1) RC(4,2) RC(4,3) RC(4,4) RC(4,7) RC(4,8) RC(4,9) RC(4,10) + >; + }; + + kscan0: kscan { + compatible = "zmk,kscan-gpio-matrix"; + label = "KSCAN"; + + diode-direction = "col2row"; + + row-gpios + = <&pro_micro 5 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> + , <&pro_micro 6 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> + , <&pro_micro 7 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> + , <&pro_micro 8 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> + , <&pro_micro 9 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> + ; + }; + + left_encoder: left_encoder { + compatible = "alps,ec11"; + label = "LEFT_ENCODER"; + a-gpios = <&pro_micro 21 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; + b-gpios = <&pro_micro 20 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; + steps = <120>; + }; + + right_encoder: right_encoder { + compatible = "alps,ec11"; + label = "RIGHT_ENCODER"; + a-gpios = <&pro_micro 20 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; + b-gpios = <&pro_micro 21 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; + steps = <120>; + }; + + sensors { + compatible = "zmk,keymap-sensors"; + sensors = <&left_encoder &right_encoder>; + triggers-per-rotation = <30>; + }; + +}; + +&pro_micro_i2c { + status = "okay"; + + oled: ssd1306@3c { + compatible = "solomon,ssd1306fb"; + reg = <0x3c>; + label = "DISPLAY"; + width = <128>; + height = <32>; + segment-offset = <0>; + page-offset = <0>; + display-offset = <0>; + multiplex-ratio = <31>; + segment-remap; + com-invdir; + com-sequential; + prechargep = <0x22>; + }; +}; \ No newline at end of file diff --git a/app/boards/shields/leeloo/leeloo_left.overlay b/app/boards/shields/leeloo/leeloo_left.overlay index 59fce1b0e5b..4421e1124ef 100644 --- a/app/boards/shields/leeloo/leeloo_left.overlay +++ b/app/boards/shields/leeloo/leeloo_left.overlay @@ -1,8 +1,8 @@ /* - * Copyright (c) 2022 The ZMK Contributors - * + * Copyright (c) 2023 The ZMK Contributors * SPDX-License-Identifier: MIT */ + #include "leeloo.dtsi" &kscan0 { @@ -18,4 +18,4 @@ &left_encoder { status = "okay"; -}; +}; \ No newline at end of file diff --git a/app/boards/shields/leeloo/leeloo_rev2.conf b/app/boards/shields/leeloo/leeloo_rev2.conf new file mode 100644 index 00000000000..8c1cf3eed7b --- /dev/null +++ b/app/boards/shields/leeloo/leeloo_rev2.conf @@ -0,0 +1,43 @@ +# Copyright (c) 2023 The ZMK Contributors +# SPDX-License-Identifier: MIT + +# Uncomment the following line to enable the OLED Display +# CONFIG_ZMK_DISPLAY=y + +# Uncomment to turn off WPM Status. +# CONFIG_ZMK_WIDGET_WPM_STATUS=n + +# Uncomment to invert colour when using nice!view Displays +# CONFIG_ZMK_DISPLAY_INVERT=y + + +# Uncomment the following line to enable per-key lighting +# CONFIG_ZMK_RGB_UNDERGLOW=y + +# Use the STRIP config specific to the LEDs you're using +# CONFIG_WS2812_STRIP=y + +# Keep OLED or nice!view Displays on even when toggling off LEDs +# Change to y if you wish to toggle Displays on and off with LEDs +# CONFIG_ZMK_RGB_UNDERGLOW_EXT_POWER=n + +# Turn off LEDs when idle. +# Change to n if you wish to keep LEDs on even when idle. +# CONFIG_ZMK_RGB_UNDERGLOW_AUTO_OFF_IDLE=y + +# When USB is disconnected, turn off LEDs +# Change to n if you wish to keep LEDs on even when USB is unpluged. +# CONFIG_ZMK_RGB_UNDERGLOW_AUTO_OFF_USB=y + +# Start LEDs off at 75% +# CONFIG_ZMK_RGB_UNDERGLOW_BRT_START=75 + + +# Uncomment these two lines to add support for encoders +# CONFIG_EC11=y +# CONFIG_EC11_TRIGGER_GLOBAL_THREAD=y + + +# Uncomment if you are experiencing connectivity issues; this +# configuration item boosts the BLE transmit power. +# CONFIG_BT_CTLR_TX_PWR_PLUS_8=y \ No newline at end of file diff --git a/app/boards/shields/leeloo/leeloo_rev2.dtsi b/app/boards/shields/leeloo/leeloo_rev2.dtsi new file mode 100644 index 00000000000..dad05c55c6e --- /dev/null +++ b/app/boards/shields/leeloo/leeloo_rev2.dtsi @@ -0,0 +1,6 @@ +/* + * Copyright (c) 2023 The ZMK Contributors + * SPDX-License-Identifier: MIT + */ + +#include "leeloo_common.dtsi" \ No newline at end of file diff --git a/app/boards/shields/leeloo/leeloo_rev2.keymap b/app/boards/shields/leeloo/leeloo_rev2.keymap new file mode 100644 index 00000000000..a66205b64cc --- /dev/null +++ b/app/boards/shields/leeloo/leeloo_rev2.keymap @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2023 The ZMK Contributors + * SPDX-License-Identifier: MIT + */ + +#include +#include +#include +#include +#include + +// Short versions +#define RGBON &rgb_ug RGB_ON +#define RGBOFF &rgb_ug RGB_OFF +#define RGBTOG &rgb_ug RGB_TOG +#define RGBHUI &rgb_ug RGB_HUI +#define RGBHUD &rgb_ug RGB_HUD +#define RGBSAI &rgb_ug RGB_SAI +#define RGBSAD &rgb_ug RGB_SAD +#define RGBBRI &rgb_ug RGB_BRI +#define RGBBRD &rgb_ug RGB_BRD +#define RGBEFF &rgb_ug RGB_EFF + + +/* + * Assign the cs-gpios pin to 4. + * Uncomment these next few lines if implementing nice!view Displays + */ +//nice_view_spi: &spi0 { +// cs-gpios = <&pro_micro 4 GPIO_ACTIVE_HIGH>; +//}; + + +/ { + + keymap { + compatible = "zmk,keymap"; + + default_layer { + label = " QWERTY"; + bindings = < +&kp ESC &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 &kp BSLH +&kp TAB &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &kp GRAV +&kp CAPS &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SEMI &kp SQT +&kp LSHFT &kp Z &kp X &kp C &kp V &kp B &kp LGUI &kp RGUI &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp RSHFT + &kp LALT &kp LCTRL < 1 RET < 2 MINUS < 2 EQUAL < 1 SPACE &kp BSPC &kp DEL + >; + + sensor-bindings = <&inc_dec_kp C_VOL_UP C_VOL_DN>; + }; + + lower_layer { + label = " Lower"; + bindings = < +&trans &kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 +&trans &trans &trans &trans &trans &trans &kp PG_UP &kp HOME &kp UP &kp END &trans &kp F12 +&trans &trans &trans &trans &trans &trans &kp PG_DN &kp LEFT &kp DOWN &kp RIGHT &trans &trans +&trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans + >; + + sensor-bindings = <&inc_dec_kp C_VOL_UP C_VOL_DN>; + }; + + raise_layer { + label = " Raise"; + bindings = < +&trans &trans &trans &trans &trans &trans &bt BT_SEL 0 &bt BT_SEL 1 &bt BT_SEL 2 &bt BT_SEL 3 &bt BT_SEL 4 &trans +&trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &sys_reset &bootloader +RGBON RGBTOG RGBHUI RGBSAI RGBBRI &trans &trans &trans &trans &trans &trans &trans +RGBOFF RGBEFF RGBHUD RGBSAD RGBBRD &trans &trans &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &bt BT_CLR &trans + >; + + sensor-bindings = <&inc_dec_kp C_VOL_UP C_VOL_DN>; + }; + + }; +}; \ No newline at end of file diff --git a/app/boards/shields/leeloo/leeloo_rev2.zmk.yml b/app/boards/shields/leeloo/leeloo_rev2.zmk.yml new file mode 100644 index 00000000000..5e0a4db3dc5 --- /dev/null +++ b/app/boards/shields/leeloo/leeloo_rev2.zmk.yml @@ -0,0 +1,15 @@ +file_format: "1" +id: leeloo_rev2 +name: Leeloo v2 +type: shield +url: https://clicketysplit.ca/pages/leeloo +requires: [pro_micro] +exposes: [i2c_oled] +features: + - keys + - display + - encoder + - underglow +siblings: + - leeloo_rev2_left + - leeloo_rev2_right diff --git a/app/boards/shields/leeloo/leeloo_rev2_left.overlay b/app/boards/shields/leeloo/leeloo_rev2_left.overlay new file mode 100644 index 00000000000..14ddc0eceb1 --- /dev/null +++ b/app/boards/shields/leeloo/leeloo_rev2_left.overlay @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2023 The ZMK Contributors + * SPDX-License-Identifier: MIT + */ + +#include "leeloo_rev2.dtsi" + +&kscan0 { + col-gpios + = <&pro_micro 19 GPIO_ACTIVE_HIGH> + , <&pro_micro 18 GPIO_ACTIVE_HIGH> + , <&pro_micro 15 GPIO_ACTIVE_HIGH> + , <&pro_micro 14 GPIO_ACTIVE_HIGH> + , <&pro_micro 16 GPIO_ACTIVE_HIGH> + , <&pro_micro 10 GPIO_ACTIVE_HIGH> + ; +}; + +&left_encoder { + status = "okay"; +}; \ No newline at end of file diff --git a/app/boards/shields/leeloo/leeloo_rev2_right.overlay b/app/boards/shields/leeloo/leeloo_rev2_right.overlay new file mode 100644 index 00000000000..afca41b474b --- /dev/null +++ b/app/boards/shields/leeloo/leeloo_rev2_right.overlay @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2023 The ZMK Contributors + * SPDX-License-Identifier: MIT + */ + +#include "leeloo_rev2.dtsi" + +&default_transform { + col-offset = <6>; +}; + +&kscan0 { + col-gpios + = <&pro_micro 10 GPIO_ACTIVE_HIGH> + , <&pro_micro 16 GPIO_ACTIVE_HIGH> + , <&pro_micro 14 GPIO_ACTIVE_HIGH> + , <&pro_micro 15 GPIO_ACTIVE_HIGH> + , <&pro_micro 18 GPIO_ACTIVE_HIGH> + , <&pro_micro 19 GPIO_ACTIVE_HIGH> + ; +}; + +&right_encoder { + status = "okay"; +}; \ No newline at end of file diff --git a/app/boards/shields/leeloo/leeloo_right.overlay b/app/boards/shields/leeloo/leeloo_right.overlay index 80e89529566..b860c2ca651 100644 --- a/app/boards/shields/leeloo/leeloo_right.overlay +++ b/app/boards/shields/leeloo/leeloo_right.overlay @@ -1,8 +1,8 @@ /* - * Copyright (c) 2022 The ZMK Contributors - * + * Copyright (c) 2023 The ZMK Contributors * SPDX-License-Identifier: MIT */ + #include "leeloo.dtsi" &default_transform { @@ -22,4 +22,4 @@ &right_encoder { status = "okay"; -}; +}; \ No newline at end of file diff --git a/app/boards/shields/leeloo_micro/Kconfig.defconfig b/app/boards/shields/leeloo_micro/Kconfig.defconfig new file mode 100644 index 00000000000..26256120a76 --- /dev/null +++ b/app/boards/shields/leeloo_micro/Kconfig.defconfig @@ -0,0 +1,49 @@ +# Copyright (c) 2023 The ZMK Contributors +# SPDX-License-Identifier: MIT + +if SHIELD_LEELOO_MICRO_LEFT + +config ZMK_KEYBOARD_NAME + default "Leeloo-Micro" + +config ZMK_SPLIT_ROLE_CENTRAL + default y + +endif + +if SHIELD_LEELOO_MICRO + +config ZMK_SPLIT + default y + +if ZMK_DISPLAY + +config I2C + default y + +config SSD1306 + default y + +config SSD1306_REVERSE_MODE + default y + +endif # ZMK_DISPLAY + +if LVGL + +config LV_Z_VDB_SIZE + default 64 + +config LV_Z_DPI + default 148 + +config LV_Z_BITS_PER_PIXEL + default 1 + +choice LV_COLOR_DEPTH + default LV_COLOR_DEPTH_1 +endchoice + +endif # LVGL + +endif diff --git a/app/boards/shields/leeloo_micro/Kconfig.shield b/app/boards/shields/leeloo_micro/Kconfig.shield new file mode 100644 index 00000000000..c622f16dfcd --- /dev/null +++ b/app/boards/shields/leeloo_micro/Kconfig.shield @@ -0,0 +1,13 @@ +# Copyright (c) 2023 The ZMK Contributors +# SPDX-License-Identifier: MIT + +config SHIELD_LEELOO_MICRO + bool + +config SHIELD_LEELOO_MICRO_LEFT + def_bool $(shields_list_contains,leeloo_micro_left) + select SHIELD_LEELOO_MICRO + +config SHIELD_LEELOO_MICRO_RIGHT + def_bool $(shields_list_contains,leeloo_micro_right) + select SHIELD_LEELOO_MICRO \ No newline at end of file diff --git a/app/boards/shields/leeloo_micro/README.md b/app/boards/shields/leeloo_micro/README.md new file mode 100644 index 00000000000..c1827f82b72 --- /dev/null +++ b/app/boards/shields/leeloo_micro/README.md @@ -0,0 +1,89 @@ +# Clickety Split | Leeloo-Micro + +![Leeloo-Micro v1 Wireless](https://github.com/ClicketySplit/build-guides/blob/main/leeloo/images/gallery/Leeloo-Micro-v1-ZMK.jpg) + +Keyboard Designer: [clicketysplit.ca](https://clicketysplit.ca) +GitHub: [ClicketySplit](https://github.com/ClicketySplit) +Hardware Supported: nice!nano v2, nice!view v1 + +Leeloo-Micro is a 3x5x5m derivative of Leeloo v2; inheriting the column stagger and modifiers row, yet, reducing the number of switches by removing the top row and outside columns. With Leeloo-Micro's inaugural release being wireless, it leverages nice!nanos and nice!views for its microcontrollers and displays. + +## Features + +- 3x5x5m Split Keyboard +- Support for Kailh Low Profile Choc switches with 18mm x 18mm spacing. +- All switch locations are socketed. +- Support for Alps Alpine EC11 Rotary Encoders—one on each side, in one of two locations. + - Rotary encoder locations are socketed. +- nice!view Displays are inherently supported, socketed, and no extra wiring is required. +- Support for per-switch RGB underglow. +- Support for both 110mAh or 700mAh batteries. +- Support for Alps Alpine Micro On/off switches. + +# Building Leeloo-Micro ZMK Firmware + +ZMK Firmware: [Introduction to ZMK](https://zmk.dev/docs/) +Installation: [Installing ZMK](https://zmk.dev/docs/user-setup) +Customization: [Customizing ZMK](https://zmk.dev/docs/customization) +Development Environment: [Basic Setup](https://zmk.dev/docs/development/setup) + +Build commands for the default keymap of Leeloo-Micro: + +``` +west build -d build/left -p -b nice_nano_v2 -- -DSHIELD=leeloo_micro_left +west build -d build/right -p -b nice_nano_v2 -- -DSHIELD=leeloo_micro_right +``` + +Build commands for your custom keymap of Leeloo-Micro: + +``` +west build -d build/right -p -b nice_nano_v2 -- -DSHIELD=leeloo_micro_right -DZMK_CONFIG="C:/dev/zmk/[yourName]/leeloo_micro/config" +west build -d build/left -p -b nice_nano_v2 -- -DSHIELD=leeloo_micro_left -DZMK_CONFIG="C:/dev/zmk/[yourName]/leeloo_micro/config" +``` + +## Building Leeloo-Micro's ZMK Firmware with nice!view Displays + +There are a couple of files that need to be adjusted before the build commands can be run. + +### Edit the leeloo_micro.keymap File + +Near the top 3rd of the leeloo_micro.keymap file, locate the following code block: + +``` +//nice_view_spi: &spi0 { +// cs-gpios = <&pro_micro 4 GPIO_ACTIVE_HIGH>; +//}; +``` + +Remove the forward slashes to resemble the following: + +``` +nice_view_spi: &spi0 { + cs-gpios = <&pro_micro 4 GPIO_ACTIVE_HIGH>; +}; +``` + +Save your changes and close the file. + +### Sample Build Commands for nice!view Displays + +Build commands for the default keymap of Leeloo-Micro: + +``` +west build -d build/left -p -b nice_nano_v2 -- -DSHIELD="leeloo_micro_left nice_view_adapter nice_view" +west build -d build/right -p -b nice_nano_v2 -- -DSHIELD="leeloo_micro_right nice_view_adapter nice_view" +``` + +Build commands for your custom keymap of Leeloo-Micro: + +``` +west build -d build/left -p -b nice_nano_v2 -- -DSHIELD="leeloo_micro_left nice_view_adapter nice_view" -DZMK_CONFIG="/workspaces/zmk-config/[yourName]/leeloo_micro/config" +west build -d build/right -p -b nice_nano_v2 -- -DSHIELD="leeloo_micro_right nice_view_adapter nice_view" -DZMK_CONFIG="/workspaces/zmk-config/[yourName]/leeloo_micro/config" +``` + +# Support + +If you have any questions with regards to Leeloo-Micro, please [Contact Us](https://clicketysplit.ca/pages/contact-us). + +Clickety Split +For the love of split keyboards. diff --git a/app/boards/shields/leeloo_micro/boards/nice_nano_v2.overlay b/app/boards/shields/leeloo_micro/boards/nice_nano_v2.overlay new file mode 100644 index 00000000000..be5dc54ec29 --- /dev/null +++ b/app/boards/shields/leeloo_micro/boards/nice_nano_v2.overlay @@ -0,0 +1,47 @@ +#include + +&pinctrl { + spi3_default: spi3_default { + group1 { + psels = ; + }; + }; + + spi3_sleep: spi3_sleep { + group1 { + psels = ; + low-power-enable; + }; + }; +}; + +&spi3 { + compatible = "nordic,nrf-spim"; + status = "okay"; + + pinctrl-0 = <&spi3_default>; + pinctrl-1 = <&spi3_sleep>; + pinctrl-names = "default", "sleep"; + + led_strip: ws2812@0 { + compatible = "worldsemi,ws2812-spi"; + label = "WS2812"; + + /* SPI */ + reg = <0>; /* ignored, but necessary for SPI bindings */ + spi-max-frequency = <4000000>; + + /* WS2812 */ + chain-length = <20>; /* arbitrary; change at will */ + spi-one-frame = <0x70>; + spi-zero-frame = <0x40>; + + color-mapping = ; + }; +}; + +/ { + chosen { + zmk,underglow = &led_strip; + }; +}; \ No newline at end of file diff --git a/app/boards/shields/leeloo_micro/leeloo_micro.conf b/app/boards/shields/leeloo_micro/leeloo_micro.conf new file mode 100644 index 00000000000..02c1d60587b --- /dev/null +++ b/app/boards/shields/leeloo_micro/leeloo_micro.conf @@ -0,0 +1,38 @@ +# Copyright (c) 2023 The ZMK Contributors +# SPDX-License-Identifier: MIT + +# Uncomment the following line to enable the OLED Display +# CONFIG_ZMK_DISPLAY=y + +# Uncomment to turn off WPM Status. +# CONFIG_ZMK_WIDGET_WPM_STATUS=n + +# Uncomment to invert colour, if using nice!view Displays +# CONFIG_ZMK_DISPLAY_INVERT=y + + +# Uncomment the following line to enable per-key lighting +# CONFIG_ZMK_RGB_UNDERGLOW=y + +# Use the STRIP config specific to the LEDs you're using +# CONFIG_WS2812_STRIP=y + +# Keep OLED or nice!view Displays on even when toggling off LEDs +# Change to y if you wish to toggle Displays on and off with LEDs +# CONFIG_ZMK_RGB_UNDERGLOW_EXT_POWER=n + +# Turn off LEDs when idle. +# Change to n if you wish to keep LEDs on even when idle. +# CONFIG_ZMK_RGB_UNDERGLOW_AUTO_OFF_IDLE=y + +# When USB is disconnected, turn off LEDs +# Change to n if you wish to keep LEDs on even when USB is unpluged. +# CONFIG_ZMK_RGB_UNDERGLOW_AUTO_OFF_USB=y + +# Start LEDs off at 75% +# CONFIG_ZMK_RGB_UNDERGLOW_BRT_START=75 + + +# Uncomment these two lines to add support for encoders +# CONFIG_EC11=y +# CONFIG_EC11_TRIGGER_GLOBAL_THREAD=y \ No newline at end of file diff --git a/app/boards/shields/leeloo_micro/leeloo_micro.dtsi b/app/boards/shields/leeloo_micro/leeloo_micro.dtsi new file mode 100644 index 00000000000..afe16dfa605 --- /dev/null +++ b/app/boards/shields/leeloo_micro/leeloo_micro.dtsi @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2023 The ZMK Contributors + * SPDX-License-Identifier: MIT + */ + +#include + +/ { + chosen { + zephyr,display = &oled; + zmk,kscan = &kscan0; + zmk,matrix_transform = &default_transform; + }; + + default_transform: keymap_transform_0 { + compatible = "zmk,matrix-transform"; + columns = <10>; + rows = <4>; +// +// | SW1 | SW2 | SW3 | SW4 | SW5 | | SW15 | SW4 | SW3 | SW2 | SW1 | +// | SW6 | SW7 | SW8 | SW9 | SW10 | | SW10 | SW9 | SW8 | SW7 | SW6 | +// | SW11 | SW12 | SW13 | SW14 | SW15 | SW20 | | SW20 | SW15 | SW14 | SW13 | SW12 | SW11 | +// | SW16 | SW17 | SW18 | SW19 | | SW19 | SW18 | SW17 | SW16 | + map = < +RC(0,0) RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(0,5) RC(0,6) RC(0,7) RC(0,8) RC(0,9) +RC(1,0) RC(1,1) RC(1,2) RC(1,3) RC(1,4) RC(1,5) RC(1,6) RC(1,7) RC(1,8) RC(1,9) +RC(2,0) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(3,4) RC(3,5) RC(2,5) RC(2,6) RC(2,7) RC(2,8) RC(2,9) + RC(3,0) RC(3,1) RC(3,2) RC(3,3) RC(3,6) RC(3,7) RC(3,8) RC(3,9) + >; + }; + + kscan0: kscan { + compatible = "zmk,kscan-gpio-matrix"; + label = "KSCAN"; + + diode-direction = "col2row"; + + row-gpios + = <&pro_micro 5 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> + , <&pro_micro 6 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> + , <&pro_micro 7 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> + , <&pro_micro 8 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> + ; + }; + + left_encoder: left_encoder { + compatible = "alps,ec11"; + label = "LEFT_ENCODER"; + a-gpios = <&pro_micro 21 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; + b-gpios = <&pro_micro 20 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; + steps = <120>; + }; + + right_encoder: right_encoder { + compatible = "alps,ec11"; + label = "RIGHT_ENCODER"; + a-gpios = <&pro_micro 20 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; + b-gpios = <&pro_micro 21 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; + steps = <120>; + }; + + sensors { + compatible = "zmk,keymap-sensors"; + sensors = <&left_encoder &right_encoder>; + triggers-per-rotation = <30>; + }; + +}; + +&pro_micro_i2c { + status = "okay"; + + oled: ssd1306@3c { + compatible = "solomon,ssd1306fb"; + reg = <0x3c>; + label = "DISPLAY"; + width = <128>; + height = <32>; + segment-offset = <0>; + page-offset = <0>; + display-offset = <0>; + multiplex-ratio = <31>; + segment-remap; + com-invdir; + com-sequential; + prechargep = <0x22>; + }; +}; \ No newline at end of file diff --git a/app/boards/shields/leeloo_micro/leeloo_micro.keymap b/app/boards/shields/leeloo_micro/leeloo_micro.keymap new file mode 100644 index 00000000000..8526f5ac2a8 --- /dev/null +++ b/app/boards/shields/leeloo_micro/leeloo_micro.keymap @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2023 The ZMK Contributors + * SPDX-License-Identifier: MIT + */ + +#include +#include +#include +#include +#include + +// Layers +#define QW_M 0 // Main +#define QW_L 1 // Lower +#define QW_R 2 // Raise +#define QW_A 3 // Adjust + +#define QC_N 4 // Number Pad +#define QC_B 5 // Firmware + + +// Short versions +#define BT0 BT_SEL 0 +#define BT1 BT_SEL 1 +#define BT2 BT_SEL 2 +#define BT3 BT_SEL 3 +#define BT4 BT_SEL 4 + +#define BOOTLDR &bootloader + +#define RGBON &rgb_ug RGB_ON +#define RGBOFF &rgb_ug RGB_OFF +#define RGBTOG &rgb_ug RGB_TOG +#define RGBHUI &rgb_ug RGB_HUI +#define RGBHUD &rgb_ug RGB_HUD +#define RGBSAI &rgb_ug RGB_SAI +#define RGBSAD &rgb_ug RGB_SAD +#define RGBBRI &rgb_ug RGB_BRI +#define RGBBRD &rgb_ug RGB_BRD +#define RGBEFF &rgb_ug RGB_EFF + + +/* + * Assign the cs-gpios pin to 4. + * Uncomment these next few lines if implementing nice!view Displays. + */ +//nice_view_spi: &spi0 { +// cs-gpios = <&pro_micro 4 GPIO_ACTIVE_HIGH>; +//}; + + +/ { + conditional_layers { + compatible = "zmk,conditional-layers"; + adjust_layer { + if-layers = ; + then-layer = ; + }; + }; + + combos { + compatible = "zmk,combos"; + + combo_esc { + timeout-ms = <50>; + key-positions = <0 1>; + layers = ; + bindings = <&kp ESC>; + }; + }; + + keymap { + compatible = "zmk,keymap"; + + default_layer { + label = " QWERTY"; + bindings = < +&kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P +&kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SEMI +&mt LSFT Z &kp X &kp C &kp V &kp B &mo QC_N &kp RGUI &kp N &kp M &kp COMMA &kp DOT &mt RSFT FSLH + &kp LALT &kp LCTRL < 1 RET < 2 MINUS < 2 EQUAL < 1 SPACE &kp BSPC &mo QC_B + >; + + sensor-bindings = <&inc_dec_kp C_VOL_DN C_VOL_UP>; + }; + + lower_layer { + label = " Lower"; + bindings = < +&kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 +&trans &trans &trans &trans &trans &trans &trans &trans &trans &kp QUOT +&kp LSHFT &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &kp RSHFT + &trans &trans &trans &trans &trans &trans &trans &trans + >; + + sensor-bindings = <&inc_dec_kp C_VOL_DN C_VOL_UP>; + }; + + raise_layer { + label = " Raise"; + bindings = < +&kp TAB &trans &trans &trans &trans &kp PG_UP &kp HOME &kp UP &kp END &kp BSLH +&kp CAPS &trans &trans &trans &trans &kp PG_DN &kp LEFT &kp DOWN &kp RIGHT &kp GRAVE +&trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &mt RSFT TILDE + &trans &trans &trans &trans &trans &trans &kp DEL &trans + >; + + sensor-bindings = <&inc_dec_kp C_VOL_DN C_VOL_UP>; + }; + + adjust_layer { + label = " Adjust"; + bindings = < + +&kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &trans &trans &trans &trans &trans +&kp F6 &kp F7 &kp F8 &kp F9 &kp F10 &trans &trans &trans &trans &trans +&kp F11 &kp F12 &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans + >; + + sensor-bindings = <&inc_dec_kp C_VOL_DN C_VOL_UP>; + }; + + numpad_layer { + label = " NumPad"; + bindings = < + +&trans &none &none &none &none &kp SLASH &kp N7 &kp N8 &kp N9 &kp MINUS +RGBON RGBTOG RGBHUI RGBSAI RGBBRI &kp ASTRK &kp N4 &kp N5 &kp N6 &kp PLUS +RGBOFF RGBEFF RGBHUD RGBSAD RGBBRD &trans &trans &none &kp N1 &kp N2 &kp N3 &kp EQUAL + &trans &trans &trans &trans &trans &kp N0 &kp DOT &none + >; + + sensor-bindings = <&inc_dec_kp C_VOL_DN C_VOL_UP>; + }; + + ble_layer { + label = " BLE"; + bindings = < + +&bt BT0 &bt BT1 &bt BT2 &bt BT3 &bt BT4 &bt BT0 &bt BT1 &bt BT2 &bt BT3 &bt BT4 +BOOTLDR &sys_reset &trans &trans &trans &trans &trans &trans &sys_reset BOOTLDR +&trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans + &trans &bt BT_CLR &trans &trans &trans &trans &bt BT_CLR &trans + >; + + sensor-bindings = <&inc_dec_kp C_VOL_DN C_VOL_UP>; + }; + + }; +}; \ No newline at end of file diff --git a/app/boards/shields/leeloo_micro/leeloo_micro.zmk.yml b/app/boards/shields/leeloo_micro/leeloo_micro.zmk.yml new file mode 100644 index 00000000000..e78ce0a3530 --- /dev/null +++ b/app/boards/shields/leeloo_micro/leeloo_micro.zmk.yml @@ -0,0 +1,15 @@ +file_format: "1" +id: leeloo_micro +name: Leeloo-Micro +type: shield +url: https://clicketysplit.ca/pages/leeloo-micro +requires: [pro_micro] +exposes: [i2c_oled] +features: + - keys + - display + - encoder + - underglow +siblings: + - leeloo_micro_left + - leeloo_micro_right diff --git a/app/boards/shields/leeloo_micro/leeloo_micro_left.overlay b/app/boards/shields/leeloo_micro/leeloo_micro_left.overlay new file mode 100644 index 00000000000..d31fcf2c0fd --- /dev/null +++ b/app/boards/shields/leeloo_micro/leeloo_micro_left.overlay @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2023 The ZMK Contributors + * SPDX-License-Identifier: MIT + */ + +#include "leeloo_micro.dtsi" + +&kscan0 { + col-gpios + = <&pro_micro 19 GPIO_ACTIVE_HIGH> + , <&pro_micro 18 GPIO_ACTIVE_HIGH> + , <&pro_micro 15 GPIO_ACTIVE_HIGH> + , <&pro_micro 14 GPIO_ACTIVE_HIGH> + , <&pro_micro 16 GPIO_ACTIVE_HIGH> + ; +}; + +&left_encoder { + status = "okay"; +}; \ No newline at end of file diff --git a/app/boards/shields/leeloo_micro/leeloo_micro_right.overlay b/app/boards/shields/leeloo_micro/leeloo_micro_right.overlay new file mode 100644 index 00000000000..a3f347fb9c3 --- /dev/null +++ b/app/boards/shields/leeloo_micro/leeloo_micro_right.overlay @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2023 The ZMK Contributors + * SPDX-License-Identifier: MIT + */ + +#include "leeloo_micro.dtsi" + +&default_transform { + col-offset = <5>; +}; + +&kscan0 { + col-gpios + = <&pro_micro 16 GPIO_ACTIVE_HIGH> + , <&pro_micro 14 GPIO_ACTIVE_HIGH> + , <&pro_micro 15 GPIO_ACTIVE_HIGH> + , <&pro_micro 18 GPIO_ACTIVE_HIGH> + , <&pro_micro 19 GPIO_ACTIVE_HIGH> + ; +}; + +&right_encoder { + status = "okay"; +}; \ No newline at end of file From f3110d1d1ea195725551b4c997c542a4003e1452 Mon Sep 17 00:00:00 2001 From: NAHO <90870942+trueNAHO@users.noreply.github.com> Date: Tue, 18 Jul 2023 00:23:22 +0200 Subject: [PATCH 34/76] fix(docs): Fix README punctuation and add license link --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 50cb2817b8f..f112b0f9705 100644 --- a/README.md +++ b/README.md @@ -4,10 +4,10 @@ [![Build](https://github.com/zmkfirmware/zmk/workflows/Build/badge.svg)](https://github.com/zmkfirmware/zmk/actions) [![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-v2.0%20adopted-ff69b4.svg)](CODE_OF_CONDUCT.md) -[ZMK Firmware](https://zmk.dev/) is an open source (MIT) keyboard firmware built on the [Zephyr™ Project](https://www.zephyrproject.org/) Real Time Operating System (RTOS). ZMK's goal is to provide a modern, wireless, and powerful firmware free of licensing issues. +[ZMK Firmware](https://zmk.dev/) is an open source ([MIT](LICENSE)) keyboard firmware built on the [Zephyr™ Project](https://www.zephyrproject.org/) Real Time Operating System (RTOS). ZMK's goal is to provide a modern, wireless, and powerful firmware free of licensing issues. -Check out the website to learn more: https://zmk.dev/ +Check out the website to learn more: https://zmk.dev/. -You can also come join our [ZMK Discord Server](https://zmk.dev/community/discord/invite) +You can also come join our [ZMK Discord Server](https://zmk.dev/community/discord/invite). To review features, check out the [feature overview](https://zmk.dev/docs/). ZMK is under active development, and new features are listed with the [enhancement label](https://github.com/zmkfirmware/zmk/issues?q=is%3Aissue+is%3Aopen+label%3Aenhancement) in GitHub. Please feel free to add 👍 to the issue description of any requests to upvote the feature. From 18a2b76bf085249e9d650d6664d32931c56dc7b7 Mon Sep 17 00:00:00 2001 From: Nick Winans Date: Tue, 18 Jul 2023 16:43:30 -0500 Subject: [PATCH 35/76] feat(nice!view): Custom widgets --- app/boards/shields/nice_view/CMakeLists.txt | 13 + .../shields/nice_view/Kconfig.defconfig | 53 ++- app/boards/shields/nice_view/README.md | 14 +- .../shields/nice_view/custom_status_screen.c | 28 ++ app/boards/shields/nice_view/nice_view.conf | 3 +- app/boards/shields/nice_view/widgets/art.c | 229 ++++++++++++ app/boards/shields/nice_view/widgets/bolt.c | 45 +++ .../nice_view/widgets/peripheral_status.c | 128 +++++++ .../nice_view/widgets/peripheral_status.h | 22 ++ app/boards/shields/nice_view/widgets/status.c | 330 ++++++++++++++++++ app/boards/shields/nice_view/widgets/status.h | 24 ++ app/boards/shields/nice_view/widgets/util.c | 69 ++++ app/boards/shields/nice_view/widgets/util.h | 47 +++ 13 files changed, 986 insertions(+), 19 deletions(-) create mode 100644 app/boards/shields/nice_view/CMakeLists.txt create mode 100644 app/boards/shields/nice_view/custom_status_screen.c create mode 100644 app/boards/shields/nice_view/widgets/art.c create mode 100644 app/boards/shields/nice_view/widgets/bolt.c create mode 100644 app/boards/shields/nice_view/widgets/peripheral_status.c create mode 100644 app/boards/shields/nice_view/widgets/peripheral_status.h create mode 100644 app/boards/shields/nice_view/widgets/status.c create mode 100644 app/boards/shields/nice_view/widgets/status.h create mode 100644 app/boards/shields/nice_view/widgets/util.c create mode 100644 app/boards/shields/nice_view/widgets/util.h diff --git a/app/boards/shields/nice_view/CMakeLists.txt b/app/boards/shields/nice_view/CMakeLists.txt new file mode 100644 index 00000000000..694242b2ec1 --- /dev/null +++ b/app/boards/shields/nice_view/CMakeLists.txt @@ -0,0 +1,13 @@ +if(CONFIG_ZMK_DISPLAY AND CONFIG_NICE_VIEW_WIDGET_STATUS) + zephyr_library_include_directories(${CMAKE_SOURCE_DIR}/include) + zephyr_library_sources(custom_status_screen.c) + zephyr_library_sources(widgets/bolt.c) + zephyr_library_sources(widgets/util.c) + + if(NOT CONFIG_ZMK_SPLIT OR CONFIG_ZMK_SPLIT_ROLE_CENTRAL) + zephyr_library_sources(widgets/status.c) + else() + zephyr_library_sources(widgets/art.c) + zephyr_library_sources(widgets/peripheral_status.c) + endif() +endif() diff --git a/app/boards/shields/nice_view/Kconfig.defconfig b/app/boards/shields/nice_view/Kconfig.defconfig index d2378409612..53edc1ccc7f 100644 --- a/app/boards/shields/nice_view/Kconfig.defconfig +++ b/app/boards/shields/nice_view/Kconfig.defconfig @@ -1,21 +1,13 @@ -# Copyright (c) 2022 The ZMK Contributors +# Copyright (c) 2023 The ZMK Contributors # SPDX-License-Identifier: MIT if SHIELD_NICE_VIEW -config ZMK_DISPLAY - select LV_FONT_MONTSERRAT_26 - -if ZMK_DISPLAY - -config SPI - default y - -config LS0XX - default y +config LV_Z_VDB_SIZE + default 100 -config ZMK_WIDGET_WPM_STATUS - default y if !ZMK_SPLIT || ZMK_SPLIT_ROLE_CENTRAL +config LV_Z_DPI + default 161 config LV_Z_BITS_PER_PIXEL default 1 @@ -24,6 +16,37 @@ choice LV_COLOR_DEPTH default LV_COLOR_DEPTH_1 endchoice -endif # ZMK_DISPLAY +choice ZMK_DISPLAY_WORK_QUEUE + default ZMK_DISPLAY_WORK_QUEUE_DEDICATED +endchoice + +choice ZMK_DISPLAY_STATUS_SCREEN + default ZMK_DISPLAY_STATUS_SCREEN_CUSTOM +endchoice + +config ZMK_DISPLAY_STATUS_SCREEN_CUSTOM + imply NICE_VIEW_WIDGET_STATUS + +config NICE_VIEW_WIDGET_STATUS + bool "Custom nice!view status widget" + select LV_FONT_MONTSERRAT_16 + select LV_USE_IMG + select LV_USE_CANVAS + +config NICE_VIEW_WIDGET_INVERTED + bool "Invert custom status widget colors" + +if !ZMK_SPLIT || ZMK_SPLIT_ROLE_CENTRAL + +config NICE_VIEW_WIDGET_STATUS + select LV_FONT_MONTSERRAT_18 + select LV_FONT_MONTSERRAT_14 + select LV_FONT_UNSCII_8 + select ZMK_WPM + +endif # !ZMK_SPLIT || ZMK_SPLIT_ROLE_CENTRAL + +config ZMK_DISPLAY_STATUS_SCREEN_BUILT_IN + select LV_FONT_MONTSERRAT_26 -endif +endif # SHIELD_NICE_VIEW diff --git a/app/boards/shields/nice_view/README.md b/app/boards/shields/nice_view/README.md index e3dffa3446e..00abfbfab1e 100644 --- a/app/boards/shields/nice_view/README.md +++ b/app/boards/shields/nice_view/README.md @@ -1,5 +1,15 @@ # nice!view -The nice!view is a low power, high refresh rate display meant to replace I2C OLEDs traditionally used. +The nice!view is a low-power, high refresh rate display meant to replace I2C OLEDs traditionally used. -This shield requires that an `&nice_view_spi` labelled SPI bus is provided with _at least_ MOSI, SCK, and CS pins defined. +This shield requires that an `&nice_view_spi` labeled SPI bus is provided with _at least_ MOSI, SCK, and CS pins defined. + +## Disable custom widget + +The nice!view shield includes a custom vertical widget. To use the built-in ZMK one, add the following item to your `.conf` file: + +``` +CONFIG_ZMK_DISPLAY_STATUS_SCREEN_BUILT_IN=y +CONFIG_ZMK_LV_FONT_DEFAULT_SMALL_MONTSERRAT_26=y +CONFIG_LV_FONT_DEFAULT_MONTSERRAT_26=y +``` diff --git a/app/boards/shields/nice_view/custom_status_screen.c b/app/boards/shields/nice_view/custom_status_screen.c new file mode 100644 index 00000000000..c08da0eb511 --- /dev/null +++ b/app/boards/shields/nice_view/custom_status_screen.c @@ -0,0 +1,28 @@ +/* + * + * Copyright (c) 2023 The ZMK Contributors + * SPDX-License-Identifier: MIT + * + */ + +#include "widgets/status.h" + +#include +LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); + +#if IS_ENABLED(CONFIG_NICE_VIEW_WIDGET_STATUS) +static struct zmk_widget_status status_widget; +#endif + +lv_obj_t *zmk_display_status_screen() { + + lv_obj_t *screen; + screen = lv_obj_create(NULL); + +#if IS_ENABLED(CONFIG_NICE_VIEW_WIDGET_STATUS) + zmk_widget_status_init(&status_widget, screen); + lv_obj_align(zmk_widget_status_obj(&status_widget), LV_ALIGN_TOP_LEFT, 0, 0); +#endif + + return screen; +} diff --git a/app/boards/shields/nice_view/nice_view.conf b/app/boards/shields/nice_view/nice_view.conf index ff57c07c9aa..e6f9158f137 100644 --- a/app/boards/shields/nice_view/nice_view.conf +++ b/app/boards/shields/nice_view/nice_view.conf @@ -1,5 +1,4 @@ # Enable nice!view CONFIG_ZMK_DISPLAY=y -CONFIG_ZMK_LV_FONT_DEFAULT_SMALL_MONTSERRAT_26=y -CONFIG_LV_FONT_DEFAULT_MONTSERRAT_26=y +# Disable idle blanking CONFIG_ZMK_DISPLAY_BLANK_ON_IDLE=n diff --git a/app/boards/shields/nice_view/widgets/art.c b/app/boards/shields/nice_view/widgets/art.c new file mode 100644 index 00000000000..56c8914629f --- /dev/null +++ b/app/boards/shields/nice_view/widgets/art.c @@ -0,0 +1,229 @@ +/* + * + * Copyright (c) 2023 Collin Hodge + * Copyright (c) 2023 The ZMK Contributors + * SPDX-License-Identifier: MIT + * + */ + +#include + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_BALLOON +#define LV_ATTRIBUTE_IMG_BALLOON +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_BALLOON uint8_t + balloon_map[] = { +#if CONFIG_NICE_VIEW_WIDGET_INVERTED + 0xff, 0xff, 0xff, 0xff, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ +#else + 0x00, 0x00, 0x00, 0xff, /*Color of index 0*/ + 0xff, 0xff, 0xff, 0xff, /*Color of index 1*/ +#endif + + 0xfe, 0xaa, 0x0a, 0x2a, 0x9f, 0xff, 0xff, 0xff, 0xfa, 0xea, 0xaa, 0xae, 0xba, 0xff, 0xff, + 0xfb, 0xff, 0xf0, 0xf1, 0x55, 0x05, 0x15, 0x47, 0xff, 0xff, 0xff, 0xf5, 0xd5, 0x55, 0x5f, + 0x7f, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xa4, 0xaa, 0x8a, 0x8a, 0xa1, 0xff, 0xff, 0xfb, 0xea, + 0xaa, 0xaa, 0xbe, 0xbf, 0xef, 0xfb, 0xfb, 0xff, 0xf0, 0x54, 0x55, 0x05, 0x45, 0x54, 0xff, + 0xff, 0x7d, 0x55, 0xd5, 0x75, 0x7f, 0x7f, 0xdf, 0xff, 0xff, 0xff, 0xf0, 0xae, 0x2a, 0x82, + 0xa0, 0xaa, 0x3f, 0xff, 0xfe, 0xaa, 0xea, 0xbb, 0xfe, 0xbf, 0xff, 0xfb, 0xfb, 0xfe, 0xf0, + 0x5f, 0x55, 0x01, 0x50, 0x54, 0x1f, 0xff, 0x7f, 0x55, 0xd5, 0x7f, 0xff, 0x7f, 0xd7, 0xff, + 0xfd, 0xfd, 0xf0, 0x2f, 0xff, 0x20, 0x28, 0x00, 0x0f, 0xff, 0xae, 0xaa, 0xaa, 0xbf, 0xff, + 0xff, 0xeb, 0xfb, 0xff, 0xff, 0xf0, 0x0e, 0x01, 0x50, 0x14, 0x00, 0x3f, 0xff, 0x57, 0x55, + 0xd5, 0x7f, 0xff, 0x7f, 0xd7, 0xfd, 0xff, 0xfd, 0xf0, 0x1e, 0x01, 0xa8, 0x0a, 0x00, 0xff, + 0xff, 0xaf, 0xaa, 0xaa, 0xff, 0xff, 0xff, 0xaf, 0xfb, 0xff, 0xff, 0xf0, 0x1f, 0xf9, 0x50, + 0x01, 0x03, 0xff, 0xff, 0x57, 0x55, 0xd5, 0x7d, 0xff, 0x7f, 0xdf, 0xfd, 0xff, 0xfd, 0xf0, + 0x9f, 0xf9, 0xa8, 0x00, 0x8f, 0xff, 0xfe, 0xaf, 0xaa, 0xaa, 0xff, 0xff, 0xfd, 0xbf, 0xfb, + 0xff, 0xfb, 0xf0, 0x5a, 0x01, 0x54, 0x00, 0x3f, 0xff, 0xff, 0x7f, 0x5d, 0xd5, 0xfd, 0xff, + 0xfd, 0xdf, 0xfd, 0xff, 0xfd, 0xf0, 0x8e, 0x01, 0xaa, 0x00, 0x7f, 0xff, 0xfe, 0xbf, 0xae, + 0xef, 0xff, 0xff, 0xfb, 0xef, 0xfb, 0xff, 0xfa, 0xf0, 0xcf, 0xff, 0xf4, 0x00, 0xf7, 0xff, + 0xff, 0x7f, 0x5d, 0xff, 0xff, 0xff, 0xfd, 0xdf, 0xff, 0xff, 0xfd, 0xf0, 0xae, 0x01, 0x2a, + 0x00, 0xfb, 0xff, 0xff, 0xbf, 0xae, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xfb, 0xff, 0xfa, 0xf0, + 0xde, 0x01, 0x35, 0x01, 0xfb, 0xff, 0xff, 0x7f, 0x5d, 0xfd, 0xbf, 0xff, 0xff, 0xdf, 0xfd, + 0xff, 0xdd, 0xf0, 0xa7, 0xff, 0xea, 0x81, 0xfc, 0xff, 0x7f, 0xbe, 0xbe, 0xff, 0xe3, 0xff, + 0xff, 0xef, 0xff, 0xf9, 0x3e, 0xf0, 0x56, 0x01, 0x55, 0x41, 0xff, 0x7f, 0xff, 0xff, 0xfd, + 0xfd, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0xfc, 0x7d, 0xf0, 0xa6, 0x01, 0x2a, 0x88, 0xfe, 0xff, + 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xe0, 0x03, 0xff, 0xff, 0xfc, 0xfe, 0xf0, 0x52, 0x79, 0x15, + 0x44, 0x7d, 0xff, 0xff, 0xfd, 0x7f, 0xbd, 0xff, 0xff, 0xfc, 0x00, 0x07, 0xf8, 0xfd, 0xf0, + 0x22, 0x69, 0x2a, 0xa0, 0x3d, 0xff, 0xff, 0xfa, 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xe2, 0x48, + 0xfa, 0xff, 0xf0, 0x42, 0x59, 0x15, 0x54, 0x1b, 0xff, 0xff, 0xf7, 0xff, 0xbd, 0xf7, 0xff, + 0xff, 0x95, 0x55, 0x37, 0x7d, 0xf0, 0x02, 0x69, 0x0a, 0xa2, 0x1f, 0xfe, 0xff, 0xee, 0xff, + 0xff, 0xfc, 0xff, 0xff, 0x2a, 0x4a, 0x9f, 0xff, 0xf0, 0x03, 0xff, 0x55, 0x11, 0x4f, 0xff, + 0xff, 0x55, 0x7f, 0xfd, 0xff, 0x00, 0xfc, 0x55, 0x55, 0x4f, 0xff, 0xf0, 0x02, 0x01, 0xaa, + 0x88, 0x8f, 0xde, 0xff, 0xaa, 0xbf, 0xfe, 0xff, 0xff, 0x00, 0xa8, 0x02, 0xa7, 0xff, 0xf0, + 0x02, 0x01, 0x55, 0x55, 0x47, 0xff, 0x7f, 0xd5, 0x5f, 0xff, 0xff, 0xff, 0xc8, 0x47, 0x5c, + 0x53, 0xff, 0xf0, 0x82, 0x49, 0xaa, 0x8a, 0xa7, 0xfe, 0xff, 0xea, 0xbf, 0xff, 0xff, 0xff, + 0xb0, 0x3f, 0x5f, 0x89, 0xff, 0xf0, 0xc2, 0x49, 0x55, 0x45, 0x53, 0xff, 0xff, 0xf5, 0x5f, + 0xff, 0xff, 0xfe, 0x70, 0x7f, 0x5f, 0xe5, 0xff, 0xf0, 0xe2, 0x41, 0xa2, 0xa2, 0xab, 0xfe, + 0xfb, 0xfa, 0xaf, 0xef, 0xff, 0xf9, 0xe2, 0xbf, 0x5f, 0xfa, 0xff, 0xf0, 0xe2, 0x41, 0x51, + 0x51, 0x51, 0xff, 0x77, 0xfd, 0x57, 0xf9, 0xff, 0xe7, 0x85, 0x7f, 0x5f, 0xfc, 0xff, 0xf0, + 0xe3, 0xff, 0xf2, 0xa0, 0xa8, 0xff, 0xfb, 0xbe, 0xaf, 0xfe, 0x1e, 0x80, 0x6a, 0x80, 0x00, + 0x7e, 0xff, 0xb0, 0xe2, 0x60, 0x11, 0x50, 0x54, 0x7f, 0xff, 0xfd, 0x57, 0xff, 0xe0, 0x1f, + 0xc4, 0x15, 0x55, 0x06, 0x7f, 0x70, 0xee, 0x60, 0x18, 0xa8, 0x2a, 0x1f, 0xff, 0xfe, 0xaf, + 0xff, 0xe8, 0xf0, 0x00, 0x0a, 0x4a, 0xa8, 0x7f, 0xf0, 0xdf, 0xff, 0xf1, 0x54, 0x15, 0x43, + 0xff, 0xff, 0x5f, 0xff, 0xe8, 0x7b, 0xc0, 0x05, 0x55, 0x55, 0x7f, 0x70, 0xff, 0x81, 0x28, + 0xaa, 0x0a, 0xa1, 0xff, 0xfe, 0xbf, 0xf7, 0xea, 0x09, 0xe0, 0x0a, 0x4a, 0xaa, 0x7f, 0xf0, + 0xff, 0x81, 0x50, 0x54, 0x05, 0x54, 0x7f, 0xff, 0x7f, 0xfc, 0xe8, 0x4b, 0xc0, 0x05, 0x55, + 0x55, 0x7f, 0x70, 0xfe, 0x7f, 0x28, 0xaa, 0x00, 0xa8, 0xff, 0xfe, 0xbf, 0xff, 0x0a, 0xf0, + 0x00, 0x02, 0x4a, 0xa8, 0x7e, 0xb0, 0xfe, 0x7f, 0x14, 0x55, 0x00, 0x03, 0xff, 0xf7, 0x5f, + 0x7f, 0xe0, 0x1f, 0xc4, 0x01, 0x55, 0x06, 0x7f, 0x70, 0xff, 0x81, 0x08, 0x2a, 0x80, 0x07, + 0xff, 0xf6, 0xaf, 0xff, 0xfe, 0x80, 0x6a, 0x80, 0x00, 0x7e, 0xff, 0xb0, 0x7f, 0x81, 0x14, + 0x55, 0x40, 0x0f, 0xff, 0xed, 0x57, 0x7f, 0xff, 0xe7, 0x85, 0x55, 0x5f, 0xfc, 0xff, 0x70, + 0xbf, 0xff, 0xe8, 0x2a, 0xa8, 0x1f, 0xff, 0xf6, 0xae, 0xff, 0xff, 0xf9, 0xea, 0xaa, 0x5f, + 0xfa, 0xff, 0xf0, 0x5e, 0x01, 0x24, 0x15, 0x54, 0x3f, 0xff, 0xf5, 0x57, 0x7f, 0xfb, 0xfe, + 0xf0, 0x55, 0x5f, 0xe5, 0xff, 0x70, 0xbe, 0x01, 0x22, 0x2a, 0xa0, 0xff, 0xff, 0xba, 0xae, + 0xff, 0xfe, 0x1f, 0x30, 0x2a, 0x0f, 0x89, 0xbf, 0xf0, 0x5f, 0xff, 0xe5, 0x15, 0x41, 0xff, + 0xff, 0xd5, 0x57, 0x7f, 0xff, 0xe0, 0x48, 0x05, 0x54, 0x53, 0xff, 0xf0, 0xbe, 0x01, 0xa2, + 0x02, 0x03, 0xff, 0xff, 0xea, 0xaa, 0xbf, 0xff, 0xff, 0x80, 0x00, 0x02, 0xa7, 0xbf, 0xf0, + 0x5e, 0x01, 0x41, 0x00, 0x06, 0xfd, 0xff, 0xd5, 0x55, 0x5f, 0xff, 0xff, 0xfc, 0x00, 0x40, + 0x4f, 0xff, 0xf0, 0xbe, 0x49, 0x20, 0x80, 0x0f, 0x7f, 0xfe, 0xea, 0xaa, 0xbe, 0xff, 0xff, + 0xff, 0x00, 0x00, 0x1f, 0xbf, 0xf0, 0x7e, 0x49, 0x50, 0x00, 0x0f, 0x7f, 0xff, 0xd5, 0x55, + 0x5f, 0x83, 0xff, 0xff, 0x80, 0x40, 0x3f, 0xff, 0xf0, 0xfe, 0x41, 0x28, 0x00, 0x0f, 0xbf, + 0xff, 0xeb, 0xaa, 0xbf, 0xfc, 0x00, 0x03, 0xe0, 0x00, 0xff, 0xbf, 0xf0, 0xfe, 0x41, 0x14, + 0x00, 0x1f, 0xdf, 0xff, 0xd5, 0xd5, 0x57, 0xff, 0xff, 0xfc, 0x00, 0x07, 0xff, 0xdf, 0xf0, + 0xff, 0xff, 0x08, 0x00, 0x1f, 0x3f, 0xdf, 0xeb, 0xaa, 0xab, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xbf, 0xf0, 0xfe, 0x01, 0x14, 0x40, 0x3e, 0xff, 0xbf, 0xf5, 0x55, 0x57, 0xdf, 0xff, + 0xf9, 0xff, 0xff, 0xff, 0xdf, 0xf0, 0xfe, 0x01, 0x0a, 0x20, 0x3f, 0xff, 0xdf, 0xfa, 0xaa, + 0xab, 0xbf, 0xff, 0xf3, 0xff, 0xff, 0xdf, 0xbf, 0xf0, 0xde, 0x7f, 0x05, 0x10, 0x7f, 0xff, + 0xff, 0xfd, 0x55, 0x55, 0xdf, 0xff, 0xe4, 0xff, 0xff, 0xbf, 0x7f, 0xf0, 0xee, 0x7e, 0x02, + 0x88, 0x7f, 0xff, 0xff, 0xfa, 0xaa, 0xab, 0xbf, 0xff, 0xe3, 0xff, 0xbf, 0xbf, 0xbf, 0xf0, + 0xde, 0x05, 0x41, 0x54, 0x3f, 0xff, 0xff, 0xdd, 0x55, 0x55, 0xff, 0xff, 0xd7, 0xff, 0xdf, + 0x7f, 0x7f, 0xf0, 0xee, 0x06, 0xa2, 0xaa, 0x3f, 0xff, 0xff, 0xbe, 0xaa, 0xab, 0xbf, 0xff, + 0xf7, 0xff, 0xbf, 0x3f, 0xbf, 0xf0, 0xde, 0x7d, 0x55, 0x55, 0x1f, 0xfb, 0xff, 0xff, 0x55, + 0x55, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xbf, 0xff, 0xf0, 0xfe, 0x7f, 0xaa, 0xaa, 0x8f, 0xff, + 0xff, 0xba, 0xaa, 0xab, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xdf, 0xbf, 0xf0, 0xfe, 0x01, 0x55, + 0x55, 0x47, 0xff, 0xff, 0xf7, 0xd5, 0x57, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, + 0xfe, 0x01, 0xaa, 0xaa, 0xa1, 0xff, 0xff, 0xbf, 0xea, 0xab, 0xff, 0xff, 0xff, 0xff, 0xbf, + 0xff, 0xff, 0xf0, 0xff, 0xff, 0x55, 0x55, 0x54, 0xff, 0xff, 0x5f, 0xf5, 0x57, 0xff, 0xfd, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xff, 0xda, 0xaa, 0xaa, 0xaa, 0x7f, 0xff, 0xbf, 0xfa, + 0xab, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xff, 0x9d, 0x55, 0x55, 0x00, 0xff, + 0xff, 0x7f, 0xfd, 0x57, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xf0, 0xff, 0xbf, 0xa2, + 0xa8, 0x03, 0xff, 0xfb, 0xbf, 0xfa, 0xaa, 0xbf, 0xfb, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xf0, + 0xff, 0x3f, 0xc0, 0x00, 0x07, 0xff, 0xff, 0x5f, 0xfd, 0x57, 0x57, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xf0, 0xff, 0x3f, 0x80, 0x00, 0x0f, 0xff, 0xfb, 0xaf, 0xfe, 0xae, 0xaa, 0xfb, + 0xff, 0xbf, 0xff, 0xff, 0xff, 0xf0, 0xf6, 0x7f, 0xc0, 0x00, 0x0f, 0xff, 0xff, 0x57, 0xfd, + 0x55, 0x55, 0x77, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xf0, +}; + +const lv_img_dsc_t balloon = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 140, + .header.h = 68, + .data_size = 1232, + .data = balloon_map, +}; + +#ifndef LV_ATTRIBUTE_IMG_MOUNTAIN +#define LV_ATTRIBUTE_IMG_MOUNTAIN +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_MOUNTAIN uint8_t + mountain_map[] = { +#if CONFIG_NICE_VIEW_WIDGET_INVERTED + 0xff, 0xff, 0xff, 0xff, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ +#else + 0x00, 0x00, 0x00, 0xff, /*Color of index 0*/ + 0xff, 0xff, 0xff, 0xff, /*Color of index 1*/ +#endif + + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xf0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, + 0x00, 0x00, 0x00, 0x90, 0x00, 0x30, 0x80, 0x00, 0x00, 0x00, 0x00, 0x5f, 0xa0, 0x00, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0x10, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xf4, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0x10, 0x80, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x40, 0x00, 0x00, 0x01, 0xfe, 0x03, 0xe0, 0x0f, 0x9e, 0x01, 0x90, + 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe8, 0x00, 0x00, 0x00, 0xff, 0x07, 0xe0, 0x1f, + 0x9e, 0x00, 0x90, 0x80, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x80, 0x00, 0x00, 0x7f, + 0x8f, 0xe0, 0x1f, 0xbe, 0x00, 0x90, 0x80, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd0, + 0x00, 0x00, 0x3f, 0xcf, 0xf0, 0x1f, 0xbc, 0x00, 0x90, 0x80, 0x7f, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xfe, 0x00, 0x00, 0x3f, 0xcf, 0xf0, 0x3f, 0xbc, 0x00, 0x90, 0x80, 0x7f, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xe8, 0x00, 0x00, 0x1f, 0xe7, 0xf0, 0x7f, 0x3c, 0x00, 0x90, + 0x80, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x80, 0x00, 0x00, 0x0f, 0xe7, 0xf8, 0x7f, + 0x78, 0x01, 0xb0, 0x80, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xec, 0x00, 0x00, 0x00, 0x07, + 0xf3, 0xf8, 0x3f, 0x78, 0x03, 0xd0, 0x80, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xc0, 0x00, + 0x00, 0x00, 0x07, 0xfb, 0xf8, 0x3f, 0xf8, 0x0f, 0x90, 0xc0, 0x1f, 0xff, 0xff, 0xff, 0xff, + 0xec, 0x00, 0x00, 0x00, 0x00, 0x03, 0xfd, 0xfc, 0x3f, 0xf8, 0x0f, 0x10, 0xc0, 0x1e, 0xff, + 0xff, 0xff, 0xff, 0x40, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xfc, 0x3f, 0xf0, 0x0e, 0x10, + 0xc0, 0x0c, 0x27, 0xff, 0xff, 0xfa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe, 0x7f, + 0xf0, 0x1e, 0x30, 0xc0, 0x00, 0x1f, 0xff, 0xff, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7f, 0xfe, 0x7f, 0xf3, 0xfc, 0x50, 0xe0, 0x00, 0x3f, 0xff, 0xfa, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7f, 0xfe, 0x7f, 0xf7, 0xf8, 0x90, 0xe0, 0x00, 0x7f, 0xfe, 0xb0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0x7f, 0xe7, 0xf1, 0x90, 0xe0, 0x00, 0x7f, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0x7f, 0xef, 0xe3, 0x90, + 0xf0, 0x00, 0x7f, 0xff, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x7f, + 0xff, 0xe7, 0x90, 0xb0, 0x10, 0xff, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0xff, 0xbf, 0xff, 0xcf, 0x90, 0xf0, 0x30, 0xff, 0xff, 0xff, 0x60, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0xff, 0xf9, 0xff, 0x9f, 0x90, 0xb0, 0x30, 0xff, 0xff, 0xff, 0xf2, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0xff, 0x3e, 0x90, 0xf8, 0x70, 0xff, + 0xff, 0xff, 0xff, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xf6, 0xfe, 0x7c, 0x90, + 0xf8, 0x78, 0xff, 0xff, 0xff, 0xff, 0xf4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xf9, + 0xfe, 0xf8, 0x90, 0xa8, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x03, 0xff, 0xfd, 0xf3, 0x90, 0xdc, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xe8, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xfb, 0xef, 0x90, 0xf5, 0xac, 0xff, 0xff, 0xff, 0xfe, + 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x90, 0xff, 0xd6, 0x7f, + 0xff, 0xff, 0xe4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0x90, + 0xff, 0xfa, 0x7f, 0xff, 0xff, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, + 0xff, 0xff, 0x90, 0xdd, 0xff, 0x7f, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0f, 0xff, 0xff, 0xf0, 0xea, 0xbf, 0x3f, 0xff, 0xa0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xf0, 0x10, 0xff, 0x4f, 0xbf, 0xf5, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0x00, 0x10, 0xff, 0xff, 0x9f, + 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf0, + 0xff, 0xb0, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0xff, 0xff, 0x90, 0xcd, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x1f, 0xff, 0xff, 0x90, 0xb2, 0xe0, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0c, 0x7f, 0xff, 0xff, 0x90, 0xff, 0xc0, 0x3f, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xff, 0xff, 0xff, 0x90, 0xfe, 0xc0, 0x7f, + 0xe8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf1, 0xff, 0xff, 0x7c, 0x90, + 0xfd, 0x80, 0xff, 0xfd, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xc3, 0xff, + 0xff, 0xb8, 0x90, 0xff, 0x80, 0xff, 0xff, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3f, 0x87, 0xff, 0xff, 0xc8, 0x90, 0x9f, 0x01, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7f, 0x1f, 0xff, 0xff, 0xe0, 0x90, 0x86, 0x01, 0xff, 0xff, 0xd0, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xfe, 0x3f, 0xff, 0xff, 0xe0, 0x90, 0x80, 0x01, 0xff, + 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x06, 0x19, 0x83, 0xfe, 0x7f, 0xff, 0xff, 0xf0, 0x90, + 0x80, 0x01, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x7f, 0xc7, 0xee, 0x7f, 0xff, + 0xff, 0xf8, 0x90, 0x80, 0x1a, 0xbf, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x01, 0x98, 0xff, 0xff, + 0xc6, 0x7f, 0xff, 0xff, 0xfc, 0x90, 0x80, 0x3f, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0xf1, 0xff, 0xff, 0xc0, 0x7f, 0xff, 0xff, 0xfe, 0x90, 0x80, 0x3f, 0xf8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x07, 0xe3, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x90, 0x80, 0x7f, 0xfe, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xc7, 0xff, 0xfe, 0x18, 0xff, 0xef, 0xff, 0xff, 0x90, + 0x80, 0x7f, 0xff, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x8f, 0xff, 0xfc, 0x7f, 0xff, 0xef, + 0xfd, 0xff, 0x90, 0x80, 0xff, 0xff, 0xfa, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x9f, 0xff, 0xf8, + 0xff, 0xff, 0xef, 0xfc, 0xf7, 0x90, 0x80, 0xff, 0xff, 0xff, 0x60, 0x00, 0x00, 0x00, 0x3f, + 0x1f, 0xff, 0xf1, 0xff, 0xff, 0xcf, 0xfc, 0xe1, 0x90, 0x80, 0xff, 0xff, 0xff, 0xf4, 0x00, + 0x00, 0x00, 0x7f, 0x3f, 0xff, 0xe3, 0xff, 0xff, 0xcf, 0xfe, 0x60, 0x90, 0x81, 0xff, 0xff, + 0xff, 0xfe, 0x80, 0x00, 0x00, 0x7f, 0x3f, 0xff, 0xc7, 0xff, 0xff, 0xdf, 0xfe, 0x40, 0x90, + 0x81, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x01, 0xfe, 0x3f, 0xff, 0xcf, 0xbf, 0xff, 0xdf, + 0xfe, 0x00, 0x90, 0x81, 0xff, 0xff, 0xff, 0xff, 0x40, 0x00, 0x07, 0xfe, 0x7f, 0xff, 0x8f, + 0x7f, 0xff, 0x9f, 0xfe, 0x00, 0x90, 0x80, 0xff, 0xff, 0xff, 0xe6, 0x00, 0x00, 0x1f, 0xfe, + 0x7f, 0xff, 0x1e, 0xff, 0xff, 0x91, 0xfe, 0x00, 0x90, 0x80, 0xff, 0xff, 0xfe, 0xc0, 0x00, + 0x00, 0x3f, 0xfc, 0x7f, 0xfe, 0x3c, 0xff, 0xff, 0x81, 0xff, 0x00, 0x90, 0x80, 0x7f, 0xff, + 0xec, 0x00, 0x00, 0x3c, 0xff, 0xf8, 0xff, 0xfc, 0x79, 0xfd, 0xff, 0x80, 0xff, 0x00, 0x90, + 0x80, 0x27, 0xff, 0x80, 0x00, 0x00, 0x7f, 0xff, 0xf9, 0xff, 0xfc, 0xf3, 0xfb, 0xff, 0x00, + 0xff, 0x00, 0x90, 0x80, 0x5f, 0xff, 0xd8, 0x00, 0x00, 0xff, 0xff, 0xf1, 0xff, 0xc8, 0xe7, + 0xf3, 0xff, 0x00, 0x7f, 0x00, 0x90, 0x80, 0xff, 0xff, 0xfd, 0x80, 0x01, 0xff, 0xff, 0xe3, + 0xff, 0x81, 0xcf, 0xf7, 0xff, 0x00, 0x7f, 0x00, 0x90, 0x80, 0xff, 0xff, 0xff, 0xd8, 0x03, + 0xff, 0xff, 0x87, 0xff, 0x03, 0x8f, 0xe7, 0xff, 0x00, 0x3f, 0x81, 0x90, 0x81, 0xff, 0xff, + 0xff, 0xfe, 0x83, 0xff, 0xfe, 0x0f, 0xfe, 0x3f, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0x10, + 0x80, 0x00, 0x00, 0x00, 0x2f, 0xc6, 0x00, 0x00, 0x38, 0x00, 0x60, 0x00, 0x48, 0x00, 0x00, + 0x00, 0x00, 0x10, 0xc0, 0x00, 0x00, 0x00, 0x17, 0xf4, 0x00, 0x00, 0xe0, 0x00, 0xc0, 0x00, + 0x88, 0x00, 0x00, 0x00, 0x00, 0x30, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, +}; + +const lv_img_dsc_t mountain = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 140, + .header.h = 68, + .data_size = 1232, + .data = mountain_map, +}; diff --git a/app/boards/shields/nice_view/widgets/bolt.c b/app/boards/shields/nice_view/widgets/bolt.c new file mode 100644 index 00000000000..74dcc2b00c6 --- /dev/null +++ b/app/boards/shields/nice_view/widgets/bolt.c @@ -0,0 +1,45 @@ +/* + * + * Copyright (c) 2023 The ZMK Contributors + * SPDX-License-Identifier: MIT + * + */ + +#include + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_BOLT +#define LV_ATTRIBUTE_IMG_BOLT +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_BOLT uint8_t bolt_map[] = { +#if CONFIG_NICE_VIEW_WIDGET_INVERTED + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + 0xff, 0xff, 0xff, 0xff, /*Color of index 2*/ + 0x00, 0x00, 0x00, 0x00, /*Color of index 3*/ +#else + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0xff, 0xff, 0xff, 0xff, /*Color of index 1*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 2*/ + 0x00, 0x00, 0x00, 0x00, /*Color of index 3*/ +#endif + + 0x00, 0x14, 0x00, 0x00, 0x64, 0x00, 0x00, 0x64, 0x00, 0x01, 0xa4, 0x00, 0x01, 0xa4, + 0x00, 0x06, 0xa4, 0x00, 0x06, 0xa4, 0x00, 0x1a, 0xa5, 0x54, 0x1a, 0xaa, 0xa4, 0x6a, + 0xaa, 0x90, 0x55, 0x6a, 0x90, 0x00, 0x6a, 0x40, 0x00, 0x6a, 0x40, 0x00, 0x69, 0x00, + 0x00, 0x69, 0x00, 0x00, 0x64, 0x00, 0x00, 0x64, 0x00, 0x00, 0x50, 0x00, +}; + +const lv_img_dsc_t bolt = { + .header.cf = LV_IMG_CF_INDEXED_2BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 11, + .header.h = 18, + .data_size = 70, + .data = bolt_map, +}; diff --git a/app/boards/shields/nice_view/widgets/peripheral_status.c b/app/boards/shields/nice_view/widgets/peripheral_status.c new file mode 100644 index 00000000000..85c2a1d8793 --- /dev/null +++ b/app/boards/shields/nice_view/widgets/peripheral_status.c @@ -0,0 +1,128 @@ +/* + * + * Copyright (c) 2023 The ZMK Contributors + * SPDX-License-Identifier: MIT + * + */ + +#include +#include +#include + +#include +LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); + +#include +#include "peripheral_status.h" +#include +#include +#include +#include +#include +#include +#include + +LV_IMG_DECLARE(balloon); +LV_IMG_DECLARE(mountain); + +static sys_slist_t widgets = SYS_SLIST_STATIC_INIT(&widgets); + +struct peripheral_status_state { + bool connected; +}; + +static void draw_top(lv_obj_t *widget, lv_color_t cbuf[], struct status_state state) { + lv_obj_t *canvas = lv_obj_get_child(widget, 0); + + lv_draw_label_dsc_t label_dsc; + init_label_dsc(&label_dsc, LVGL_FOREGROUND, &lv_font_montserrat_16, LV_TEXT_ALIGN_RIGHT); + lv_draw_rect_dsc_t rect_black_dsc; + init_rect_dsc(&rect_black_dsc, LVGL_BACKGROUND); + + // Fill background + lv_canvas_draw_rect(canvas, 0, 0, CANVAS_SIZE, CANVAS_SIZE, &rect_black_dsc); + + // Draw battery + draw_battery(canvas, state); + + // Draw output status + lv_canvas_draw_text(canvas, 0, 0, CANVAS_SIZE, &label_dsc, + state.connected ? LV_SYMBOL_WIFI : LV_SYMBOL_CLOSE); + + // Rotate canvas + rotate_canvas(canvas, cbuf); +} + +static void set_battery_status(struct zmk_widget_status *widget, + struct battery_status_state state) { +#if IS_ENABLED(CONFIG_USB_DEVICE_STACK) + widget->state.charging = state.usb_present; +#endif /* IS_ENABLED(CONFIG_USB_DEVICE_STACK) */ + + widget->state.battery = state.level; + + draw_top(widget->obj, widget->cbuf, widget->state); +} + +static void battery_status_update_cb(struct battery_status_state state) { + struct zmk_widget_status *widget; + SYS_SLIST_FOR_EACH_CONTAINER(&widgets, widget, node) { set_battery_status(widget, state); } +} + +static struct battery_status_state battery_status_get_state(const zmk_event_t *eh) { + return (struct battery_status_state) { + .level = bt_bas_get_battery_level(), +#if IS_ENABLED(CONFIG_USB_DEVICE_STACK) + .usb_present = zmk_usb_is_powered(), +#endif /* IS_ENABLED(CONFIG_USB_DEVICE_STACK) */ + }; +} + +ZMK_DISPLAY_WIDGET_LISTENER(widget_battery_status, struct battery_status_state, + battery_status_update_cb, battery_status_get_state) + +ZMK_SUBSCRIPTION(widget_battery_status, zmk_battery_state_changed); +#if IS_ENABLED(CONFIG_USB_DEVICE_STACK) +ZMK_SUBSCRIPTION(widget_battery_status, zmk_usb_conn_state_changed); +#endif /* IS_ENABLED(CONFIG_USB_DEVICE_STACK) */ + +static struct peripheral_status_state get_state(const zmk_event_t *_eh) { + return (struct peripheral_status_state){.connected = zmk_split_bt_peripheral_is_connected()}; +} + +static void set_connection_status(struct zmk_widget_status *widget, + struct peripheral_status_state state) { + widget->state.connected = state.connected; + + draw_top(widget->obj, widget->cbuf, widget->state); +} + +static void output_status_update_cb(struct peripheral_status_state state) { + struct zmk_widget_status *widget; + SYS_SLIST_FOR_EACH_CONTAINER(&widgets, widget, node) { set_connection_status(widget, state); } +} + +ZMK_DISPLAY_WIDGET_LISTENER(widget_peripheral_status, struct peripheral_status_state, + output_status_update_cb, get_state) +ZMK_SUBSCRIPTION(widget_peripheral_status, zmk_split_peripheral_status_changed); + +int zmk_widget_status_init(struct zmk_widget_status *widget, lv_obj_t *parent) { + widget->obj = lv_obj_create(parent); + lv_obj_set_size(widget->obj, 160, 68); + lv_obj_t *top = lv_canvas_create(widget->obj); + lv_obj_align(top, LV_ALIGN_TOP_RIGHT, 0, 0); + lv_canvas_set_buffer(top, widget->cbuf, CANVAS_SIZE, CANVAS_SIZE, LV_IMG_CF_TRUE_COLOR); + + lv_obj_t *art = lv_img_create(widget->obj); + bool random = sys_rand32_get() & 1; + lv_img_set_src(art, random ? &balloon : &mountain); + lv_obj_align(art, LV_ALIGN_TOP_LEFT, 0, 0); + + sys_slist_append(&widgets, &widget->node); + widget_battery_status_init(); + widget_peripheral_status_init(); + + return 0; +} + +lv_obj_t *zmk_widget_status_obj(struct zmk_widget_status *widget) { return widget->obj; } diff --git a/app/boards/shields/nice_view/widgets/peripheral_status.h b/app/boards/shields/nice_view/widgets/peripheral_status.h new file mode 100644 index 00000000000..815963572b4 --- /dev/null +++ b/app/boards/shields/nice_view/widgets/peripheral_status.h @@ -0,0 +1,22 @@ +/* + * + * Copyright (c) 2023 The ZMK Contributors + * SPDX-License-Identifier: MIT + * + */ + +#pragma once + +#include +#include +#include "util.h" + +struct zmk_widget_status { + sys_snode_t node; + lv_obj_t *obj; + lv_color_t cbuf[CANVAS_SIZE * CANVAS_SIZE]; + struct status_state state; +}; + +int zmk_widget_status_init(struct zmk_widget_status *widget, lv_obj_t *parent); +lv_obj_t *zmk_widget_status_obj(struct zmk_widget_status *widget); diff --git a/app/boards/shields/nice_view/widgets/status.c b/app/boards/shields/nice_view/widgets/status.c new file mode 100644 index 00000000000..1ad9e9207d7 --- /dev/null +++ b/app/boards/shields/nice_view/widgets/status.c @@ -0,0 +1,330 @@ +/* + * + * Copyright (c) 2023 The ZMK Contributors + * SPDX-License-Identifier: MIT + * + */ + +#include +#include + +#include +LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); + +#include +#include "status.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static sys_slist_t widgets = SYS_SLIST_STATIC_INIT(&widgets); + +struct output_status_state { + enum zmk_endpoint selected_endpoint; + bool active_profile_connected; + bool active_profile_bonded; + uint8_t active_profile_index; +}; + +struct layer_status_state { + uint8_t index; + const char *label; +}; + +struct wpm_status_state { + uint8_t wpm; +}; + +static void draw_top(lv_obj_t *widget, lv_color_t cbuf[], struct status_state state) { + lv_obj_t *canvas = lv_obj_get_child(widget, 0); + + lv_draw_label_dsc_t label_dsc; + init_label_dsc(&label_dsc, LVGL_FOREGROUND, &lv_font_montserrat_16, LV_TEXT_ALIGN_RIGHT); + lv_draw_label_dsc_t label_dsc_wpm; + init_label_dsc(&label_dsc_wpm, LVGL_FOREGROUND, &lv_font_unscii_8, LV_TEXT_ALIGN_RIGHT); + lv_draw_rect_dsc_t rect_black_dsc; + init_rect_dsc(&rect_black_dsc, LVGL_BACKGROUND); + lv_draw_rect_dsc_t rect_white_dsc; + init_rect_dsc(&rect_white_dsc, LVGL_FOREGROUND); + lv_draw_line_dsc_t line_dsc; + init_line_dsc(&line_dsc, LVGL_FOREGROUND, 1); + + // Fill background + lv_canvas_draw_rect(canvas, 0, 0, CANVAS_SIZE, CANVAS_SIZE, &rect_black_dsc); + + // Draw battery + draw_battery(canvas, state); + + // Draw output status + char output_text[10] = {}; + + switch (state.selected_endpoint) { + case ZMK_ENDPOINT_USB: + strcat(output_text, LV_SYMBOL_USB); + break; + case ZMK_ENDPOINT_BLE: + if (state.active_profile_bonded) { + if (state.active_profile_connected) { + strcat(output_text, LV_SYMBOL_WIFI); + } else { + strcat(output_text, LV_SYMBOL_CLOSE); + } + } else { + strcat(output_text, LV_SYMBOL_SETTINGS); + } + break; + } + + lv_canvas_draw_text(canvas, 0, 0, CANVAS_SIZE, &label_dsc, output_text); + + // Draw WPM + lv_canvas_draw_rect(canvas, 0, 21, 68, 42, &rect_white_dsc); + lv_canvas_draw_rect(canvas, 1, 22, 66, 40, &rect_black_dsc); + + char wpm_text[6] = {}; + snprintf(wpm_text, sizeof(wpm_text), "%d", state.wpm[9]); + lv_canvas_draw_text(canvas, 42, 52, 24, &label_dsc_wpm, wpm_text); + + int max = 0; + int min = 256; + + for (int i = 0; i < 10; i++) { + if (state.wpm[i] > max) { + max = state.wpm[i]; + } + if (state.wpm[i] < min) { + min = state.wpm[i]; + } + } + + int range = max - min; + if (range == 0) { + range = 1; + } + + lv_point_t points[10]; + for (int i = 0; i < 10; i++) { + points[i].x = 2 + i * 7; + points[i].y = 60 - (state.wpm[i] - min) * 36 / range; + } + lv_canvas_draw_line(canvas, points, 10, &line_dsc); + + // Rotate canvas + rotate_canvas(canvas, cbuf); +} + +static void draw_middle(lv_obj_t *widget, lv_color_t cbuf[], struct status_state state) { + lv_obj_t *canvas = lv_obj_get_child(widget, 1); + + lv_draw_rect_dsc_t rect_black_dsc; + init_rect_dsc(&rect_black_dsc, LVGL_BACKGROUND); + lv_draw_rect_dsc_t rect_white_dsc; + init_rect_dsc(&rect_white_dsc, LVGL_FOREGROUND); + lv_draw_arc_dsc_t arc_dsc; + init_arc_dsc(&arc_dsc, LVGL_FOREGROUND, 2); + lv_draw_arc_dsc_t arc_dsc_filled; + init_arc_dsc(&arc_dsc_filled, LVGL_FOREGROUND, 9); + lv_draw_label_dsc_t label_dsc; + init_label_dsc(&label_dsc, LVGL_FOREGROUND, &lv_font_montserrat_18, LV_TEXT_ALIGN_CENTER); + lv_draw_label_dsc_t label_dsc_black; + init_label_dsc(&label_dsc_black, LVGL_BACKGROUND, &lv_font_montserrat_18, LV_TEXT_ALIGN_CENTER); + + // Fill background + lv_canvas_draw_rect(canvas, 0, 0, CANVAS_SIZE, CANVAS_SIZE, &rect_black_dsc); + + // Draw circles + int circle_offsets[5][2] = { + {13, 13}, {55, 13}, {34, 34}, {13, 55}, {55, 55}, + }; + + for (int i = 0; i < 5; i++) { + bool selected = state.active_profile_index == i; + + lv_canvas_draw_arc(canvas, circle_offsets[i][0], circle_offsets[i][1], 13, 0, 359, + &arc_dsc); + + if (selected) { + lv_canvas_draw_arc(canvas, circle_offsets[i][0], circle_offsets[i][1], 9, 0, 359, + &arc_dsc_filled); + } + + char label[2]; + snprintf(label, sizeof(label), "%d", i + 1); + lv_canvas_draw_text(canvas, circle_offsets[i][0] - 8, circle_offsets[i][1] - 10, 16, + (selected ? &label_dsc_black : &label_dsc), label); + } + + // Rotate canvas + rotate_canvas(canvas, cbuf); +} + +static void draw_bottom(lv_obj_t *widget, lv_color_t cbuf[], struct status_state state) { + lv_obj_t *canvas = lv_obj_get_child(widget, 2); + + lv_draw_rect_dsc_t rect_black_dsc; + init_rect_dsc(&rect_black_dsc, LVGL_BACKGROUND); + lv_draw_label_dsc_t label_dsc; + init_label_dsc(&label_dsc, LVGL_FOREGROUND, &lv_font_montserrat_14, LV_TEXT_ALIGN_CENTER); + + // Fill background + lv_canvas_draw_rect(canvas, 0, 0, CANVAS_SIZE, CANVAS_SIZE, &rect_black_dsc); + + // Draw layer + if (state.layer_label == NULL) { + char text[9] = {}; + + sprintf(text, "LAYER %i", state.layer_index); + + lv_canvas_draw_text(canvas, 0, 5, 68, &label_dsc, text); + } else { + lv_canvas_draw_text(canvas, 0, 5, 68, &label_dsc, state.layer_label); + } + + // Rotate canvas + rotate_canvas(canvas, cbuf); +} + +static void set_battery_status(struct zmk_widget_status *widget, + struct battery_status_state state) { +#if IS_ENABLED(CONFIG_USB_DEVICE_STACK) + widget->state.charging = state.usb_present; +#endif /* IS_ENABLED(CONFIG_USB_DEVICE_STACK) */ + + widget->state.battery = state.level; + + draw_top(widget->obj, widget->cbuf, widget->state); +} + +static void battery_status_update_cb(struct battery_status_state state) { + struct zmk_widget_status *widget; + SYS_SLIST_FOR_EACH_CONTAINER(&widgets, widget, node) { set_battery_status(widget, state); } +} + +static struct battery_status_state battery_status_get_state(const zmk_event_t *eh) { + return (struct battery_status_state) { + .level = bt_bas_get_battery_level(), +#if IS_ENABLED(CONFIG_USB_DEVICE_STACK) + .usb_present = zmk_usb_is_powered(), +#endif /* IS_ENABLED(CONFIG_USB_DEVICE_STACK) */ + }; +} + +ZMK_DISPLAY_WIDGET_LISTENER(widget_battery_status, struct battery_status_state, + battery_status_update_cb, battery_status_get_state) + +ZMK_SUBSCRIPTION(widget_battery_status, zmk_battery_state_changed); +#if IS_ENABLED(CONFIG_USB_DEVICE_STACK) +ZMK_SUBSCRIPTION(widget_battery_status, zmk_usb_conn_state_changed); +#endif /* IS_ENABLED(CONFIG_USB_DEVICE_STACK) */ + +static void set_output_status(struct zmk_widget_status *widget, struct output_status_state state) { + widget->state.selected_endpoint = state.selected_endpoint; + widget->state.active_profile_connected = state.active_profile_connected; + widget->state.active_profile_bonded = state.active_profile_bonded; + widget->state.active_profile_index = state.active_profile_index; + + draw_top(widget->obj, widget->cbuf, widget->state); + draw_middle(widget->obj, widget->cbuf2, widget->state); +} + +static void output_status_update_cb(struct output_status_state state) { + struct zmk_widget_status *widget; + SYS_SLIST_FOR_EACH_CONTAINER(&widgets, widget, node) { set_output_status(widget, state); } +} + +static struct output_status_state output_status_get_state(const zmk_event_t *_eh) { + return (struct output_status_state){.selected_endpoint = zmk_endpoints_selected(), + .active_profile_connected = + zmk_ble_active_profile_is_connected(), + .active_profile_bonded = !zmk_ble_active_profile_is_open(), + .active_profile_index = zmk_ble_active_profile_index()}; + ; +} + +ZMK_DISPLAY_WIDGET_LISTENER(widget_output_status, struct output_status_state, + output_status_update_cb, output_status_get_state) +ZMK_SUBSCRIPTION(widget_output_status, zmk_endpoint_selection_changed); + +#if IS_ENABLED(CONFIG_USB_DEVICE_STACK) +ZMK_SUBSCRIPTION(widget_output_status, zmk_usb_conn_state_changed); +#endif +#if defined(CONFIG_ZMK_BLE) +ZMK_SUBSCRIPTION(widget_output_status, zmk_ble_active_profile_changed); +#endif + +static void set_layer_status(struct zmk_widget_status *widget, struct layer_status_state state) { + widget->state.layer_index = state.index; + widget->state.layer_label = state.label; + + draw_bottom(widget->obj, widget->cbuf3, widget->state); +} + +static void layer_status_update_cb(struct layer_status_state state) { + struct zmk_widget_status *widget; + SYS_SLIST_FOR_EACH_CONTAINER(&widgets, widget, node) { set_layer_status(widget, state); } +} + +static struct layer_status_state layer_status_get_state(const zmk_event_t *eh) { + uint8_t index = zmk_keymap_highest_layer_active(); + return (struct layer_status_state){.index = index, .label = zmk_keymap_layer_label(index)}; +} + +ZMK_DISPLAY_WIDGET_LISTENER(widget_layer_status, struct layer_status_state, layer_status_update_cb, + layer_status_get_state) + +ZMK_SUBSCRIPTION(widget_layer_status, zmk_layer_state_changed); + +static void set_wpm_status(struct zmk_widget_status *widget, struct wpm_status_state state) { + for (int i = 0; i < 9; i++) { + widget->state.wpm[i] = widget->state.wpm[i + 1]; + } + widget->state.wpm[9] = state.wpm; + + draw_top(widget->obj, widget->cbuf, widget->state); +} + +static void wpm_status_update_cb(struct wpm_status_state state) { + struct zmk_widget_status *widget; + SYS_SLIST_FOR_EACH_CONTAINER(&widgets, widget, node) { set_wpm_status(widget, state); } +} + +struct wpm_status_state wpm_status_get_state(const zmk_event_t *eh) { + return (struct wpm_status_state){.wpm = zmk_wpm_get_state()}; +}; + +ZMK_DISPLAY_WIDGET_LISTENER(widget_wpm_status, struct wpm_status_state, wpm_status_update_cb, + wpm_status_get_state) +ZMK_SUBSCRIPTION(widget_wpm_status, zmk_wpm_state_changed); + +int zmk_widget_status_init(struct zmk_widget_status *widget, lv_obj_t *parent) { + widget->obj = lv_obj_create(parent); + lv_obj_set_size(widget->obj, 160, 68); + lv_obj_t *top = lv_canvas_create(widget->obj); + lv_obj_align(top, LV_ALIGN_TOP_RIGHT, 0, 0); + lv_canvas_set_buffer(top, widget->cbuf, CANVAS_SIZE, CANVAS_SIZE, LV_IMG_CF_TRUE_COLOR); + lv_obj_t *middle = lv_canvas_create(widget->obj); + lv_obj_align(middle, LV_ALIGN_TOP_LEFT, 24, 0); + lv_canvas_set_buffer(middle, widget->cbuf2, CANVAS_SIZE, CANVAS_SIZE, LV_IMG_CF_TRUE_COLOR); + lv_obj_t *bottom = lv_canvas_create(widget->obj); + lv_obj_align(bottom, LV_ALIGN_TOP_LEFT, -44, 0); + lv_canvas_set_buffer(bottom, widget->cbuf3, CANVAS_SIZE, CANVAS_SIZE, LV_IMG_CF_TRUE_COLOR); + + sys_slist_append(&widgets, &widget->node); + widget_battery_status_init(); + widget_output_status_init(); + widget_layer_status_init(); + widget_wpm_status_init(); + + return 0; +} + +lv_obj_t *zmk_widget_status_obj(struct zmk_widget_status *widget) { return widget->obj; } diff --git a/app/boards/shields/nice_view/widgets/status.h b/app/boards/shields/nice_view/widgets/status.h new file mode 100644 index 00000000000..53a22518d73 --- /dev/null +++ b/app/boards/shields/nice_view/widgets/status.h @@ -0,0 +1,24 @@ +/* + * + * Copyright (c) 2023 The ZMK Contributors + * SPDX-License-Identifier: MIT + * + */ + +#pragma once + +#include +#include +#include "util.h" + +struct zmk_widget_status { + sys_snode_t node; + lv_obj_t *obj; + lv_color_t cbuf[CANVAS_SIZE * CANVAS_SIZE]; + lv_color_t cbuf2[CANVAS_SIZE * CANVAS_SIZE]; + lv_color_t cbuf3[CANVAS_SIZE * CANVAS_SIZE]; + struct status_state state; +}; + +int zmk_widget_status_init(struct zmk_widget_status *widget, lv_obj_t *parent); +lv_obj_t *zmk_widget_status_obj(struct zmk_widget_status *widget); diff --git a/app/boards/shields/nice_view/widgets/util.c b/app/boards/shields/nice_view/widgets/util.c new file mode 100644 index 00000000000..9655f837f6e --- /dev/null +++ b/app/boards/shields/nice_view/widgets/util.c @@ -0,0 +1,69 @@ +/* + * + * Copyright (c) 2023 The ZMK Contributors + * SPDX-License-Identifier: MIT + * + */ + +#include +#include "util.h" + +LV_IMG_DECLARE(bolt); + +void rotate_canvas(lv_obj_t *canvas, lv_color_t cbuf[]) { + static lv_color_t cbuf_tmp[CANVAS_SIZE * CANVAS_SIZE]; + memcpy(cbuf_tmp, cbuf, sizeof(cbuf_tmp)); + lv_img_dsc_t img; + img.data = (void *)cbuf_tmp; + img.header.cf = LV_IMG_CF_TRUE_COLOR; + img.header.w = CANVAS_SIZE; + img.header.h = CANVAS_SIZE; + + lv_canvas_fill_bg(canvas, LVGL_BACKGROUND, LV_OPA_COVER); + lv_canvas_transform(canvas, &img, 900, LV_IMG_ZOOM_NONE, -1, 0, CANVAS_SIZE / 2, + CANVAS_SIZE / 2, true); +} + +void draw_battery(lv_obj_t *canvas, struct status_state state) { + lv_draw_rect_dsc_t rect_black_dsc; + init_rect_dsc(&rect_black_dsc, LVGL_BACKGROUND); + lv_draw_rect_dsc_t rect_white_dsc; + init_rect_dsc(&rect_white_dsc, LVGL_FOREGROUND); + + lv_canvas_draw_rect(canvas, 0, 2, 29, 12, &rect_white_dsc); + lv_canvas_draw_rect(canvas, 1, 3, 27, 10, &rect_black_dsc); + lv_canvas_draw_rect(canvas, 2, 4, (state.battery + 2) / 4, 8, &rect_white_dsc); + lv_canvas_draw_rect(canvas, 30, 5, 3, 6, &rect_white_dsc); + lv_canvas_draw_rect(canvas, 31, 6, 1, 4, &rect_black_dsc); + + if (state.charging) { + lv_draw_img_dsc_t img_dsc; + lv_draw_img_dsc_init(&img_dsc); + lv_canvas_draw_img(canvas, 9, -1, &bolt, &img_dsc); + } +} + +void init_label_dsc(lv_draw_label_dsc_t *label_dsc, lv_color_t color, const lv_font_t *font, + lv_text_align_t align) { + lv_draw_label_dsc_init(label_dsc); + label_dsc->color = color; + label_dsc->font = font; + label_dsc->align = align; +} + +void init_rect_dsc(lv_draw_rect_dsc_t *rect_dsc, lv_color_t bg_color) { + lv_draw_rect_dsc_init(rect_dsc); + rect_dsc->bg_color = bg_color; +} + +void init_line_dsc(lv_draw_line_dsc_t *line_dsc, lv_color_t color, uint8_t width) { + lv_draw_line_dsc_init(line_dsc); + line_dsc->color = color; + line_dsc->width = width; +} + +void init_arc_dsc(lv_draw_arc_dsc_t *arc_dsc, lv_color_t color, uint8_t width) { + lv_draw_arc_dsc_init(arc_dsc); + arc_dsc->color = color; + arc_dsc->width = width; +} diff --git a/app/boards/shields/nice_view/widgets/util.h b/app/boards/shields/nice_view/widgets/util.h new file mode 100644 index 00000000000..e48c1082ce9 --- /dev/null +++ b/app/boards/shields/nice_view/widgets/util.h @@ -0,0 +1,47 @@ +/* + * + * Copyright (c) 2023 The ZMK Contributors + * SPDX-License-Identifier: MIT + * + */ + +#include +#include + +#define CANVAS_SIZE 68 + +#define LVGL_BACKGROUND \ + IS_ENABLED(CONFIG_NICE_VIEW_WIDGET_INVERTED) ? lv_color_black() : lv_color_white() +#define LVGL_FOREGROUND \ + IS_ENABLED(CONFIG_NICE_VIEW_WIDGET_INVERTED) ? lv_color_white() : lv_color_black() + +struct status_state { + uint8_t battery; + bool charging; +#if !IS_ENABLED(CONFIG_ZMK_SPLIT) || IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) + enum zmk_endpoint selected_endpoint; + bool active_profile_connected; + bool active_profile_bonded; + uint8_t active_profile_index; + uint8_t layer_index; + const char *layer_label; + uint8_t wpm[10]; +#else + bool connected; +#endif +}; + +struct battery_status_state { + uint8_t level; +#if IS_ENABLED(CONFIG_USB_DEVICE_STACK) + bool usb_present; +#endif +}; + +void rotate_canvas(lv_obj_t *canvas, lv_color_t cbuf[]); +void draw_battery(lv_obj_t *canvas, struct status_state state); +void init_label_dsc(lv_draw_label_dsc_t *label_dsc, lv_color_t color, const lv_font_t *font, + lv_text_align_t align); +void init_rect_dsc(lv_draw_rect_dsc_t *rect_dsc, lv_color_t bg_color); +void init_line_dsc(lv_draw_line_dsc_t *line_dsc, lv_color_t color, uint8_t width); +void init_arc_dsc(lv_draw_arc_dsc_t *arc_dsc, lv_color_t color, uint8_t width); From 51a4be89355550ccdc00833c18ceaba5ddabcb51 Mon Sep 17 00:00:00 2001 From: Nick Winans Date: Tue, 18 Jul 2023 16:55:32 -0500 Subject: [PATCH 36/76] fix(displays): Don't enable built-in widget configs by default --- app/src/display/Kconfig | 6 +++++- app/src/display/widgets/Kconfig | 4 ---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/src/display/Kconfig b/app/src/display/Kconfig index 63ba968b445..a2029481080 100644 --- a/app/src/display/Kconfig +++ b/app/src/display/Kconfig @@ -7,7 +7,6 @@ menuconfig ZMK_DISPLAY select DISPLAY select LVGL select LV_CONF_MINIMAL - imply LV_USE_THEME_MONO if ZMK_DISPLAY @@ -42,6 +41,11 @@ choice ZMK_DISPLAY_STATUS_SCREEN config ZMK_DISPLAY_STATUS_SCREEN_BUILT_IN bool "Built in status screen" select LV_OBJ_LABEL + imply LV_USE_THEME_MONO + imply ZMK_WIDGET_LAYER_STATUS + imply ZMK_WIDGET_BATTERY_STATUS + imply ZMK_WIDGET_OUTPUT_STATUS + imply ZMK_WIDGET_PERIPHERAL_STATUS config ZMK_DISPLAY_STATUS_SCREEN_CUSTOM bool "Custom status screen" diff --git a/app/src/display/widgets/Kconfig b/app/src/display/widgets/Kconfig index 4c056cf5e00..7ec20c1fe4d 100644 --- a/app/src/display/widgets/Kconfig +++ b/app/src/display/widgets/Kconfig @@ -5,14 +5,12 @@ menu "ZMK Display Widgets" config ZMK_WIDGET_LAYER_STATUS bool "Widget for highest, active layer using small icons" - default y depends on !ZMK_SPLIT || ZMK_SPLIT_ROLE_CENTRAL select LV_USE_LABEL config ZMK_WIDGET_BATTERY_STATUS bool "Widget for battery charge information, using small icons" depends on BT - default y if BT select LV_USE_LABEL if ZMK_WIDGET_BATTERY_STATUS @@ -25,13 +23,11 @@ endif config ZMK_WIDGET_OUTPUT_STATUS bool "Widget for keyboard output status icons" depends on BT && (!ZMK_SPLIT_BLE || ZMK_SPLIT_ROLE_CENTRAL) - default y if BT && (!ZMK_SPLIT_BLE || ZMK_SPLIT_ROLE_CENTRAL) select LV_USE_LABEL config ZMK_WIDGET_PERIPHERAL_STATUS bool "Widget for split peripheral status icons" depends on BT && ZMK_SPLIT_BLE && !ZMK_SPLIT_ROLE_CENTRAL - default y if BT && ZMK_SPLIT_BLE && !ZMK_SPLIT_ROLE_CENTRAL select LV_USE_LABEL config ZMK_WIDGET_WPM_STATUS From ee1e13510410e9b482fd20acf112bc3f1466c362 Mon Sep 17 00:00:00 2001 From: Cem Aksoylar Date: Tue, 18 Jul 2023 23:21:09 -0700 Subject: [PATCH 37/76] fix: Proper battery sensor Kconfig dependencies. Properly make the battery sensor Kconfig symbols depend on `SENSOR` config, and minor battery reporting Kconfig symbol dependency fix. --- app/Kconfig | 2 +- app/drivers/sensor/battery/Kconfig | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/app/Kconfig b/app/Kconfig index 92641c14ed0..fe019918cbb 100644 --- a/app/Kconfig +++ b/app/Kconfig @@ -500,7 +500,7 @@ config ZMK_SETTINGS_SAVE_DEBOUNCE endif config ZMK_BATTERY_REPORT_INTERVAL - depends on ZMK_BLE + depends on ZMK_BATTERY_REPORTING int "Battery level report interval in seconds" default 60 diff --git a/app/drivers/sensor/battery/Kconfig b/app/drivers/sensor/battery/Kconfig index a9d7189e58a..703adebd44e 100644 --- a/app/drivers/sensor/battery/Kconfig +++ b/app/drivers/sensor/battery/Kconfig @@ -14,6 +14,7 @@ config ZMK_BATTERY_NRF_VDDH default $(dt_compat_enabled,$(DT_COMPAT_ZMK_BATTERY_NRF_VDDH)) select ADC select ZMK_BATTERY + depends on SENSOR help Enable ZMK nRF VDDH voltage driver for battery monitoring. @@ -22,5 +23,6 @@ config ZMK_BATTERY_VOLTAGE_DIVIDER default $(dt_compat_enabled,$(DT_COMPAT_ZMK_BATTERY_VOLTAGE_DIVIDER)) select ADC select ZMK_BATTERY + depends on SENSOR help Enable ZMK battery voltage divider driver for battery monitoring. From cec2061dada6b18580ce20f0c1c70df38aa2a379 Mon Sep 17 00:00:00 2001 From: Maciej Konieczny aka narf Date: Wed, 19 Jul 2023 21:59:29 +0200 Subject: [PATCH 38/76] fix(docs): Fix typos in parameterized macros docs. --- docs/docs/behaviors/macros.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/docs/behaviors/macros.md b/docs/docs/behaviors/macros.md index 40c333a9066..279d135697c 100644 --- a/docs/docs/behaviors/macros.md +++ b/docs/docs/behaviors/macros.md @@ -61,9 +61,9 @@ Macros can also be "parameterized", allowing them to be bound in your keymap wit When defining a parameterized macro, a different `compatible` value will be used depending on how many parameters are passed into it: -- `zmk,behavior-macro` - a parameter that takes no parameters. -- `zmk,behavior-macro-one-param` - a parameter that takes one parameter when used. -- `zmk,behavior-macro-two-param` - a parameter that takes two parameters when used. +- `zmk,behavior-macro` - a macro that takes no parameters. +- `zmk,behavior-macro-one-param` - a macro that takes one parameter when used. +- `zmk,behavior-macro-two-param` - a macro that takes two parameters when used. ### Bindings From b945ffe943f1639bfe992ddb4bc12f968d3858f9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 12 Jul 2023 15:07:59 +0000 Subject: [PATCH 39/76] chore(deps): bump semver from 5.7.1 to 5.7.2 in /docs Bumps [semver](https://github.com/npm/node-semver) from 5.7.1 to 5.7.2. - [Release notes](https://github.com/npm/node-semver/releases) - [Changelog](https://github.com/npm/node-semver/blob/v5.7.2/CHANGELOG.md) - [Commits](https://github.com/npm/node-semver/compare/v5.7.1...v5.7.2) --- updated-dependencies: - dependency-name: semver dependency-type: indirect ... Signed-off-by: dependabot[bot] --- docs/package-lock.json | 156 ++++++++++++++++++++--------------------- 1 file changed, 78 insertions(+), 78 deletions(-) diff --git a/docs/package-lock.json b/docs/package-lock.json index 5badb07e389..b990f53c3dc 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -251,9 +251,9 @@ } }, "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "bin": { "semver": "bin/semver.js" } @@ -325,9 +325,9 @@ } }, "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "bin": { "semver": "bin/semver.js" } @@ -384,9 +384,9 @@ } }, "node_modules/@babel/helper-define-polyfill-provider/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "bin": { "semver": "bin/semver.js" } @@ -1634,9 +1634,9 @@ } }, "node_modules/@babel/plugin-transform-runtime/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "bin": { "semver": "bin/semver.js" } @@ -1846,9 +1846,9 @@ } }, "node_modules/@babel/preset-env/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "bin": { "semver": "bin/semver.js" } @@ -2959,9 +2959,9 @@ } }, "node_modules/@mdx-js/mdx/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "bin": { "semver": "bin/semver" } @@ -4366,9 +4366,9 @@ } }, "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "bin": { "semver": "bin/semver.js" } @@ -6812,9 +6812,9 @@ } }, "node_modules/eslint-plugin-react/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "bin": { "semver": "bin/semver.js" @@ -9456,9 +9456,9 @@ } }, "node_modules/make-dir/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "bin": { "semver": "bin/semver.js" } @@ -11353,9 +11353,9 @@ } }, "node_modules/package-json/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "bin": { "semver": "bin/semver.js" } @@ -13008,9 +13008,9 @@ } }, "node_modules/remark-mdx/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "bin": { "semver": "bin/semver" } @@ -13522,9 +13522,9 @@ } }, "node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dependencies": { "lru-cache": "^6.0.0" }, @@ -13547,9 +13547,9 @@ } }, "node_modules/semver-diff/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "bin": { "semver": "bin/semver.js" } @@ -16203,9 +16203,9 @@ }, "dependencies": { "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" } } }, @@ -16260,9 +16260,9 @@ }, "dependencies": { "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" } } }, @@ -16303,9 +16303,9 @@ }, "dependencies": { "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" } } }, @@ -17113,9 +17113,9 @@ }, "dependencies": { "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" } } }, @@ -17270,9 +17270,9 @@ }, "dependencies": { "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" } } }, @@ -18097,9 +18097,9 @@ } }, "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==" }, "source-map": { "version": "0.5.7", @@ -19210,9 +19210,9 @@ }, "dependencies": { "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" } } }, @@ -20999,9 +20999,9 @@ } }, "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true } } @@ -22887,9 +22887,9 @@ }, "dependencies": { "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" } } }, @@ -24147,9 +24147,9 @@ }, "dependencies": { "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" } } }, @@ -25310,9 +25310,9 @@ } }, "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==" }, "source-map": { "version": "0.5.7", @@ -25676,9 +25676,9 @@ } }, "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "requires": { "lru-cache": "^6.0.0" } @@ -25692,9 +25692,9 @@ }, "dependencies": { "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" } } }, From 73e1b526d56376be09908a3726fbe9553052e447 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Wed, 19 Jul 2023 14:59:40 +0000 Subject: [PATCH 40/76] fix(bluetooth): Properly clear peripheral slots * When the clear bonds Kconfig is set, also clear peripheral address slots addresses from settings as well. --- app/src/ble.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/app/src/ble.c b/app/src/ble.c index ff82f3cf40a..6607574cc44 100644 --- a/app/src/ble.c +++ b/app/src/ble.c @@ -606,7 +606,7 @@ static int zmk_ble_init(const struct device *_arg) { bt_unpair(BT_ID_DEFAULT, NULL); - for (int i = 0; i < ZMK_BLE_PROFILE_COUNT; i++) { + for (int i = 0; i < 8; i++) { char setting_name[15]; sprintf(setting_name, "ble/profiles/%d", i); @@ -615,7 +615,20 @@ static int zmk_ble_init(const struct device *_arg) { LOG_ERR("Failed to delete setting: %d", err); } } -#endif + + // Hardcoding a reasonable hardcoded value of peripheral addresses + // to clear so we properly clear a split central as well. + for (int i = 0; i < 8; i++) { + char setting_name[32]; + sprintf(setting_name, "ble/peripheral_addresses/%d", i); + + err = settings_delete(setting_name); + if (err) { + LOG_ERR("Failed to delete setting: %d", err); + } + } + +#endif // IS_ENABLED(CONFIG_ZMK_BLE_CLEAR_BONDS_ON_START) bt_conn_cb_register(&conn_callbacks); bt_conn_auth_cb_register(&zmk_ble_auth_cb_display); From ed400c4feb7955bdc839fbf33b463a73c898a033 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Wed, 19 Jul 2023 16:21:06 +0000 Subject: [PATCH 41/76] fix(bluetooth): Corrected use of `bt_addr_le_cmp` * Properly compare to zero when comparing LE addresses. --- app/src/ble.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/ble.c b/app/src/ble.c index 6607574cc44..38a9833c991 100644 --- a/app/src/ble.c +++ b/app/src/ble.c @@ -281,14 +281,14 @@ int zmk_ble_put_peripheral_addr(const bt_addr_le_t *addr) { for (int i = 0; i < ZMK_SPLIT_BLE_PERIPHERAL_COUNT; i++) { // If the address is recognized and already stored in settings, return // index and no additional action is necessary. - if (!bt_addr_le_cmp(&peripheral_addrs[i], addr)) { + if (bt_addr_le_cmp(&peripheral_addrs[i], addr) == 0) { return i; } // If the peripheral address slot is open, store new peripheral in the // slot and return index. This compares against BT_ADDR_LE_ANY as that // is the zero value. - if (!bt_addr_le_cmp(&peripheral_addrs[i], BT_ADDR_LE_ANY)) { + if (bt_addr_le_cmp(&peripheral_addrs[i], BT_ADDR_LE_ANY) == 0) { char addr_str[BT_ADDR_LE_STR_LEN]; bt_addr_le_to_str(addr, addr_str, sizeof(addr_str)); LOG_DBG("Storing peripheral %s in slot %d", addr_str, i); From 54c2e8e155e9be71026251946c98e8e45c989388 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Thu, 20 Jul 2023 06:35:41 +0000 Subject: [PATCH 42/76] feat: Add more logging to peripheral settings. --- app/src/ble.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/src/ble.c b/app/src/ble.c index 38a9833c991..483bc9d79c1 100644 --- a/app/src/ble.c +++ b/app/src/ble.c @@ -282,7 +282,12 @@ int zmk_ble_put_peripheral_addr(const bt_addr_le_t *addr) { // If the address is recognized and already stored in settings, return // index and no additional action is necessary. if (bt_addr_le_cmp(&peripheral_addrs[i], addr) == 0) { + LOG_DBG("Found existing peripheral address in slot %d", i); return i; + } else { + char addr_str[BT_ADDR_LE_STR_LEN]; + bt_addr_le_to_str(&peripheral_addrs[i], addr_str, sizeof(addr_str)); + LOG_DBG("peripheral slot %d occupied by %s", i, addr_str); } // If the peripheral address slot is open, store new peripheral in the From 5f6a13413bba84eeb1eb89c4ff2a5710ca552e6b Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Thu, 20 Jul 2023 23:34:09 -0700 Subject: [PATCH 43/76] fix(bluetooth): Split improvements * Proper usage of bt_uuid_cmp. * Central's don't start scanning for peripherals if `ZMK_BLE_CLEAR_BONDS_ON_START` is enabled. * Split peripherals don't advertize if `ZMK_BLE_CLEAR_BONDS_ON_START` is enabled. --- app/src/split/bluetooth/central.c | 15 ++++++++------- app/src/split/bluetooth/peripheral.c | 4 ++-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/app/src/split/bluetooth/central.c b/app/src/split/bluetooth/central.c index 147760ffae7..8a5e9d35c5a 100644 --- a/app/src/split/bluetooth/central.c +++ b/app/src/split/bluetooth/central.c @@ -251,8 +251,8 @@ static uint8_t split_central_chrc_discovery_func(struct bt_conn *conn, LOG_DBG("[ATTRIBUTE] handle %u", attr->handle); - if (!bt_uuid_cmp(((struct bt_gatt_chrc *)attr->user_data)->uuid, - BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_POSITION_STATE_UUID))) { + if (bt_uuid_cmp(((struct bt_gatt_chrc *)attr->user_data)->uuid, + BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_POSITION_STATE_UUID)) == 0) { LOG_DBG("Found position state characteristic"); slot->discover_params.uuid = NULL; slot->discover_params.start_handle = attr->handle + 2; @@ -264,8 +264,8 @@ static uint8_t split_central_chrc_discovery_func(struct bt_conn *conn, slot->subscribe_params.notify = split_central_notify_func; slot->subscribe_params.value = BT_GATT_CCC_NOTIFY; split_central_subscribe(conn); - } else if (!bt_uuid_cmp(((struct bt_gatt_chrc *)attr->user_data)->uuid, - BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_RUN_BEHAVIOR_UUID))) { + } else if (bt_uuid_cmp(((struct bt_gatt_chrc *)attr->user_data)->uuid, + BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_RUN_BEHAVIOR_UUID)) == 0) { LOG_DBG("Found run behavior handle"); slot->run_behavior_handle = bt_gatt_attr_value_handle(attr); } @@ -292,7 +292,8 @@ static uint8_t split_central_service_discovery_func(struct bt_conn *conn, return BT_GATT_ITER_STOP; } - if (bt_uuid_cmp(slot->discover_params.uuid, BT_UUID_DECLARE_128(ZMK_SPLIT_BT_SERVICE_UUID))) { + if (bt_uuid_cmp(slot->discover_params.uuid, BT_UUID_DECLARE_128(ZMK_SPLIT_BT_SERVICE_UUID)) != + 0) { LOG_DBG("Found other service"); return BT_GATT_ITER_CONTINUE; } @@ -418,7 +419,7 @@ static bool split_central_eir_parse(struct bt_data *data, void *user_data) { continue; } - if (bt_uuid_cmp(&uuid.uuid, BT_UUID_DECLARE_128(ZMK_SPLIT_BT_SERVICE_UUID))) { + if (bt_uuid_cmp(&uuid.uuid, BT_UUID_DECLARE_128(ZMK_SPLIT_BT_SERVICE_UUID)) != 0) { char uuid_str[BT_UUID_STR_LEN]; char service_uuid_str[BT_UUID_STR_LEN]; @@ -622,7 +623,7 @@ int zmk_split_bt_central_init(const struct device *_arg) { CONFIG_ZMK_BLE_THREAD_PRIORITY, NULL); bt_conn_cb_register(&conn_callbacks); - return start_scanning(); + return IS_ENABLED(CONFIG_ZMK_BLE_CLEAR_BONDS_ON_START) ? 0 : start_scanning(); } SYS_INIT(zmk_split_bt_central_init, APPLICATION, CONFIG_ZMK_BLE_INIT_PRIORITY); diff --git a/app/src/split/bluetooth/peripheral.c b/app/src/split/bluetooth/peripheral.c index 6b767baa7c1..e053db8a61a 100644 --- a/app/src/split/bluetooth/peripheral.c +++ b/app/src/split/bluetooth/peripheral.c @@ -116,11 +116,11 @@ static int zmk_peripheral_ble_init(const struct device *_arg) { LOG_WRN("Clearing all existing BLE bond information from the keyboard"); bt_unpair(BT_ID_DEFAULT, NULL); -#endif - +#else bt_conn_cb_register(&conn_callbacks); start_advertising(); +#endif return 0; } From 147f7f23dca7a2eb5d7433d399948cfd51e068a9 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Thu, 20 Jul 2023 23:53:38 -0700 Subject: [PATCH 44/76] fix(shields): Make settings_reset more flexible. * Don't reference `pro_micro` nexus node in settings_reset so it can be used with other controllers. * Use mock kscan node instead. --- app/boards/shields/settings_reset/settings_reset.keymap | 4 +--- app/boards/shields/settings_reset/settings_reset.overlay | 8 ++++---- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/app/boards/shields/settings_reset/settings_reset.keymap b/app/boards/shields/settings_reset/settings_reset.keymap index 0afdcc2bf35..1206ef1e363 100644 --- a/app/boards/shields/settings_reset/settings_reset.keymap +++ b/app/boards/shields/settings_reset/settings_reset.keymap @@ -12,9 +12,7 @@ compatible = "zmk,keymap"; default_layer { - bindings = < - &sys_reset - >; + bindings = <&sys_reset>; }; }; }; diff --git a/app/boards/shields/settings_reset/settings_reset.overlay b/app/boards/shields/settings_reset/settings_reset.overlay index 77a9d85871d..48a5f223b65 100644 --- a/app/boards/shields/settings_reset/settings_reset.overlay +++ b/app/boards/shields/settings_reset/settings_reset.overlay @@ -12,12 +12,12 @@ }; kscan0: kscan { - compatible = "zmk,kscan-gpio-direct"; + compatible = "zmk,kscan-mock"; label = "KSCAN"; + columns = <1>; + rows = <0>; - input-gpios - = <&pro_micro 4 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)> - ; + events = <>; }; }; From f743d57ff1d4d68f51fb11b99fc0217eeca42919 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Mon, 10 Jul 2023 22:44:44 -0700 Subject: [PATCH 45/76] feat(shields): Add splitkb.com Aurora Sofle * Add new shield for splitkb.com Aurora Sofle, supporting keys, encoder(s), displays, and RGB. Co-authored-by: Cem Aksoylar --- .../splitkb_aurora_sofle/Kconfig.defconfig | 53 +++++++++++++ .../splitkb_aurora_sofle/Kconfig.shield | 8 ++ .../boards/nice_nano.overlay | 46 +++++++++++ .../boards/nice_nano_v2.overlay | 46 +++++++++++ .../splitkb_aurora_sofle.conf | 9 +++ .../splitkb_aurora_sofle.dtsi | 79 +++++++++++++++++++ .../splitkb_aurora_sofle.keymap | 78 ++++++++++++++++++ .../splitkb_aurora_sofle.zmk.yml | 15 ++++ .../splitkb_aurora_sofle_left.overlay | 43 ++++++++++ .../splitkb_aurora_sofle_right.overlay | 45 +++++++++++ 10 files changed, 422 insertions(+) create mode 100644 app/boards/shields/splitkb_aurora_sofle/Kconfig.defconfig create mode 100644 app/boards/shields/splitkb_aurora_sofle/Kconfig.shield create mode 100644 app/boards/shields/splitkb_aurora_sofle/boards/nice_nano.overlay create mode 100644 app/boards/shields/splitkb_aurora_sofle/boards/nice_nano_v2.overlay create mode 100644 app/boards/shields/splitkb_aurora_sofle/splitkb_aurora_sofle.conf create mode 100644 app/boards/shields/splitkb_aurora_sofle/splitkb_aurora_sofle.dtsi create mode 100644 app/boards/shields/splitkb_aurora_sofle/splitkb_aurora_sofle.keymap create mode 100644 app/boards/shields/splitkb_aurora_sofle/splitkb_aurora_sofle.zmk.yml create mode 100644 app/boards/shields/splitkb_aurora_sofle/splitkb_aurora_sofle_left.overlay create mode 100644 app/boards/shields/splitkb_aurora_sofle/splitkb_aurora_sofle_right.overlay diff --git a/app/boards/shields/splitkb_aurora_sofle/Kconfig.defconfig b/app/boards/shields/splitkb_aurora_sofle/Kconfig.defconfig new file mode 100644 index 00000000000..b53c4c8dc16 --- /dev/null +++ b/app/boards/shields/splitkb_aurora_sofle/Kconfig.defconfig @@ -0,0 +1,53 @@ +# Copyright (c) 2023 The ZMK Contributors +# SPDX-License-Identifier: MIT + +if SHIELD_SPLITKB_AURORA_SOFLE_LEFT + +config ZMK_KEYBOARD_NAME + default "Aurora Sofle" + +config ZMK_SPLIT_ROLE_CENTRAL + default y + +endif # SHIELD_SPLITKB_AURORA_SOFLE_LEFT + +if SHIELD_SPLITKB_AURORA_SOFLE_LEFT || SHIELD_SPLITKB_AURORA_SOFLE_RIGHT + +config ZMK_SPLIT + default y + +config ZMK_RGB_UNDERGLOW + select WS2812_STRIP + select SPI + +if ZMK_DISPLAY + +config SSD1306 + default y + +config I2C + default y + +config SSD1306_REVERSE_MODE + default y + +endif # ZMK_DISPLAY + +if LVGL + +config LV_Z_VDB_SIZE + default 64 + +config LV_DPI_DEF + default 148 + +config LV_Z_BITS_PER_PIXEL + default 1 + +choice LV_COLOR_DEPTH + default LV_COLOR_DEPTH_1 +endchoice + +endif # LVGL + +endif # SHIELD_SPLITKB_AURORA_SOFLE_LEFT || SHIELD_SPLITKB_AURORA_SOFLE_RIGHT diff --git a/app/boards/shields/splitkb_aurora_sofle/Kconfig.shield b/app/boards/shields/splitkb_aurora_sofle/Kconfig.shield new file mode 100644 index 00000000000..c72e95d9d0f --- /dev/null +++ b/app/boards/shields/splitkb_aurora_sofle/Kconfig.shield @@ -0,0 +1,8 @@ +# Copyright (c) 2023 The ZMK Contributors +# SPDX-License-Identifier: MIT + +config SHIELD_SPLITKB_AURORA_SOFLE_LEFT + def_bool $(shields_list_contains,splitkb_aurora_sofle_left) + +config SHIELD_SPLITKB_AURORA_SOFLE_RIGHT + def_bool $(shields_list_contains,splitkb_aurora_sofle_right) diff --git a/app/boards/shields/splitkb_aurora_sofle/boards/nice_nano.overlay b/app/boards/shields/splitkb_aurora_sofle/boards/nice_nano.overlay new file mode 100644 index 00000000000..8f1629ced14 --- /dev/null +++ b/app/boards/shields/splitkb_aurora_sofle/boards/nice_nano.overlay @@ -0,0 +1,46 @@ +#include + +&pinctrl { + spi3_default: spi3_default { + group1 { + psels = ; + }; + }; + + spi3_sleep: spi3_sleep { + group1 { + psels = ; + low-power-enable; + }; + }; +}; + +&spi3 { + compatible = "nordic,nrf-spim"; + status = "okay"; + + pinctrl-0 = <&spi3_default>; + pinctrl-1 = <&spi3_sleep>; + pinctrl-names = "default", "sleep"; + + led_strip: ws2812@0 { + compatible = "worldsemi,ws2812-spi"; + label = "WS2812"; + + /* SPI */ + reg = <0>; /* ignored, but necessary for SPI bindings */ + spi-max-frequency = <4000000>; + + /* WS2812 */ + chain-length = <6>; /* arbitrary; change at will */ + spi-one-frame = <0x70>; + spi-zero-frame = <0x40>; + color-mapping = ; + }; +}; + +/ { + chosen { + zmk,underglow = &led_strip; + }; +}; diff --git a/app/boards/shields/splitkb_aurora_sofle/boards/nice_nano_v2.overlay b/app/boards/shields/splitkb_aurora_sofle/boards/nice_nano_v2.overlay new file mode 100644 index 00000000000..8f1629ced14 --- /dev/null +++ b/app/boards/shields/splitkb_aurora_sofle/boards/nice_nano_v2.overlay @@ -0,0 +1,46 @@ +#include + +&pinctrl { + spi3_default: spi3_default { + group1 { + psels = ; + }; + }; + + spi3_sleep: spi3_sleep { + group1 { + psels = ; + low-power-enable; + }; + }; +}; + +&spi3 { + compatible = "nordic,nrf-spim"; + status = "okay"; + + pinctrl-0 = <&spi3_default>; + pinctrl-1 = <&spi3_sleep>; + pinctrl-names = "default", "sleep"; + + led_strip: ws2812@0 { + compatible = "worldsemi,ws2812-spi"; + label = "WS2812"; + + /* SPI */ + reg = <0>; /* ignored, but necessary for SPI bindings */ + spi-max-frequency = <4000000>; + + /* WS2812 */ + chain-length = <6>; /* arbitrary; change at will */ + spi-one-frame = <0x70>; + spi-zero-frame = <0x40>; + color-mapping = ; + }; +}; + +/ { + chosen { + zmk,underglow = &led_strip; + }; +}; diff --git a/app/boards/shields/splitkb_aurora_sofle/splitkb_aurora_sofle.conf b/app/boards/shields/splitkb_aurora_sofle/splitkb_aurora_sofle.conf new file mode 100644 index 00000000000..d456100ab74 --- /dev/null +++ b/app/boards/shields/splitkb_aurora_sofle/splitkb_aurora_sofle.conf @@ -0,0 +1,9 @@ +# Uncomment these two line to add support for encoders to your firmware +# CONFIG_EC11=y +# CONFIG_EC11_TRIGGER_GLOBAL_THREAD=y + +# Uncomment the following line to enable the OLED Display +# CONFIG_ZMK_DISPLAY=y + +# Uncomment the following lines to enable RGB underglow +# CONFIG_ZMK_RGB_UNDERGLOW=y diff --git a/app/boards/shields/splitkb_aurora_sofle/splitkb_aurora_sofle.dtsi b/app/boards/shields/splitkb_aurora_sofle/splitkb_aurora_sofle.dtsi new file mode 100644 index 00000000000..798cd84e5f3 --- /dev/null +++ b/app/boards/shields/splitkb_aurora_sofle/splitkb_aurora_sofle.dtsi @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2023 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include + +/ { + + chosen { + zephyr,display = &oled; + zmk,matrix_transform = &default_transform; + }; + + default_transform: keymap_transform_0 { + compatible = "zmk,matrix-transform"; + columns = <14>; + rows = <5>; +// | SW6 | SW5 | SW4 | SW3 | SW2 | SW1 | | SW1 | SW2 | SW3 | SW4 | SW5 | SW6 | +// | SW12 | SW11 | SW10 | SW9 | SW8 | SW7 | | SW7 | SW8 | SW9 | SW10 | SW11 | SW12 | +// | SW18 | SW17 | SW16 | SW15 | SW14 | SW13 | | SW13 | SW14 | SW15 | SW16 | SW17 | SW18 | +// | SW24 | SW23 | SW22 | SW21 | SW20 | SW19 | SW25 | | SW25 | SW19 | SW20 | SW21 | SW22 | SW23 | SW24 | +// | SW30 | SW29 | SW28 | SW27 | SW26 | | SW26 | SW27 | SW28 | SW29 | SW30 | + map = < +RC(0,0) RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(0,5) RC(0,6) RC(0,7) RC(0,8) RC(0,9) RC(0,10) RC(0,11) +RC(1,0) RC(1,1) RC(1,2) RC(1,3) RC(1,4) RC(1,5) RC(1,6) RC(1,7) RC(1,8) RC(1,9) RC(1,10) RC(1,11) +RC(2,0) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(2,5) RC(2,6) RC(2,7) RC(2,8) RC(2,9) RC(2,10) RC(2,11) +RC(3,0) RC(3,1) RC(3,2) RC(3,3) RC(3,4) RC(3,5) RC(4,5) RC(4,6) RC(3,6) RC(3,7) RC(3,8) RC(3,9) RC(3,10) RC(3,11) + RC(4,0) RC(4,1) RC(4,2) RC(4,3) RC(4,4) RC(4,7) RC(4,8) RC(4,9) RC(4,10) RC(4,11) + >; + }; + + left_encoder: left_encoder { + compatible = "alps,ec11"; + label = "L_ENCODER"; + steps = <144>; + status = "disabled"; + + a-gpios = <&pro_micro 16 GPIO_PULL_UP>; + b-gpios = <&pro_micro 10 GPIO_PULL_UP>; + }; + + right_encoder: right_encoder { + compatible = "alps,ec11"; + label = "R_ENCODER"; + steps = <144>; + status = "disabled"; + + a-gpios = <&pro_micro 16 GPIO_PULL_UP>; + b-gpios = <&pro_micro 10 GPIO_PULL_UP>; + }; + + sensors { + compatible = "zmk,keymap-sensors"; + sensors = <&left_encoder &right_encoder>; + triggers-per-rotation = <36>; + }; +}; + +&pro_micro_i2c { + status = "okay"; + + oled: ssd1306@3c { + compatible = "solomon,ssd1306fb"; + reg = <0x3c>; + label = "DISPLAY"; + width = <128>; + height = <32>; + segment-offset = <0>; + page-offset = <0>; + display-offset = <0>; + multiplex-ratio = <31>; + segment-remap; + com-invdir; + com-sequential; + prechargep = <0x22>; + }; +}; diff --git a/app/boards/shields/splitkb_aurora_sofle/splitkb_aurora_sofle.keymap b/app/boards/shields/splitkb_aurora_sofle/splitkb_aurora_sofle.keymap new file mode 100644 index 00000000000..23127416762 --- /dev/null +++ b/app/boards/shields/splitkb_aurora_sofle/splitkb_aurora_sofle.keymap @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2023 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include +#include +#include +#include + +/* Uncomment this block if using RGB +&led_strip { + chain-length = <6>; + // chain-length = <35>; // Uncomment if using both per-key and underglow LEDs + // chain-length = <29>; // Uncomment if using only per-key LEDs. +}; + */ + +/ { + keymap { + compatible = "zmk,keymap"; + + default_layer { +// ------------------------------------------------------------------------------------------------------------ +// | ESC | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | ` | +// | TAB | Q | W | E | R | T | | Y | U | I | O | P | - | +// | CTRL | A | S | D | F | G | | H | J | K | L | ; | ' | +// | SHIFT | Z | X | C | V | B | "[" | | "]" | N | M | , | . | / | SHIFT | +// |CTRL | ALT | GUI | LOWER| SPACE | | ENTER | RAISE| BSPC | GUI | RALT | + bindings = < +&kp ESC &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 &kp GRAVE +&kp TAB &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &kp MINUS +&kp LCTRL &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SEMI &kp SQT +&kp LSHFT &kp Z &kp X &kp C &kp V &kp B &kp LBKT &kp RBKT &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp RSHFT + &kp LCTRL &kp LALT &kp LGUI &mo 1 &kp SPACE &kp RET &mo 2 &kp BSPC &kp RGUI &kp RALT + >; + + sensor-bindings = <&inc_dec_kp C_VOL_UP C_VOL_DN>; + }; + + lower_layer { +// ------------------------------------------------------------------------------------------------------------ +// | BTCLR | BT1 | BT2 | BT3 | BT4 | BT5 | | | | | | | | +// | F1 | F2 | F3 | F4 | F5 | F6 | | F7 | F8 | F9 | F10 | F11 | F12 | +// | ` | ! | @ | # | $ | % | | ^ | & | * | ( | ) | ~ | +// | | | | | | | | | | | _ | + | { | } | "|" | +// | | | | | | | | | | | | + bindings = < +&bt BT_CLR &bt BT_SEL 0 &bt BT_SEL 1 &bt BT_SEL 2 &bt BT_SEL 3 &bt BT_SEL 4 &trans &trans &trans &trans &trans &trans +&kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12 +&kp GRAVE &kp EXCL &kp AT &kp HASH &kp DOLLAR &kp PRCNT &kp CARET &kp AMPS &kp STAR &kp LPAR &kp RPAR &kp TILDE +&trans &ext_power EP_ON &ext_power EP_OFF &ext_power EP_TOG &trans &trans &trans &trans &trans &kp MINUS &kp PLUS &kp LBRC &kp RBRC &kp PIPE + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans + >; + + sensor-bindings = <&inc_dec_kp C_VOL_UP C_VOL_DN>; + }; + + raise_layer { +// ------------------------------------------------------------------------------------------------------------ +// | | | | | | | | | | | | | | +// | ` | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | | +// | F1 | F2 | F3 | F4 | F5 | F6 | | | <- | v | ^ | -> | | +// | F7 | F8 | F9 | F10 | F11 | F12 | | | | + | - | = | [ | ] | \ | +// | | | | | | | | | | | | + bindings = < +&trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans +&kp GRAVE &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 &trans +&kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &trans &kp LEFT &kp DOWN &kp UP &kp RIGHT &trans +&kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12 &trans &trans &kp KP_PLUS &kp MINUS &kp EQUAL &kp LBKT &kp RBKT &kp BSLH + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans + >; + + sensor-bindings = <&inc_dec_kp C_VOL_UP C_VOL_DN>; + }; + }; +}; diff --git a/app/boards/shields/splitkb_aurora_sofle/splitkb_aurora_sofle.zmk.yml b/app/boards/shields/splitkb_aurora_sofle/splitkb_aurora_sofle.zmk.yml new file mode 100644 index 00000000000..d832d3e1053 --- /dev/null +++ b/app/boards/shields/splitkb_aurora_sofle/splitkb_aurora_sofle.zmk.yml @@ -0,0 +1,15 @@ +file_format: "1" +id: splitkb_aurora_sofle +name: splitkb.com Aurora Sofle +type: shield +url: https://splitkb.com/products/aurora-sofle-pcb-kit +requires: [pro_micro] +exposes: [i2c_oled] +features: + - keys + - display + - encoder + - underglow +siblings: + - splitkb_aurora_sofle_left + - splitkb_aurora_sofle_right diff --git a/app/boards/shields/splitkb_aurora_sofle/splitkb_aurora_sofle_left.overlay b/app/boards/shields/splitkb_aurora_sofle/splitkb_aurora_sofle_left.overlay new file mode 100644 index 00000000000..1adaf401563 --- /dev/null +++ b/app/boards/shields/splitkb_aurora_sofle/splitkb_aurora_sofle_left.overlay @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2023 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include "splitkb_aurora_sofle.dtsi" + +/ { + chosen { + zmk,kscan = &kscan; + }; + + kscan: kscan { + compatible = "zmk,kscan-gpio-matrix"; + + label = "KSCAN"; + diode-direction = "col2row"; + + row-gpios + = <&pro_micro 20 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)> + , <&pro_micro 15 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)> + , <&pro_micro 18 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)> + , <&pro_micro 19 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)> + , <&pro_micro 14 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)> + ; + + col-gpios + = <&pro_micro 9 GPIO_ACTIVE_HIGH> + , <&pro_micro 8 GPIO_ACTIVE_HIGH> + , <&pro_micro 7 GPIO_ACTIVE_HIGH> + , <&pro_micro 6 GPIO_ACTIVE_HIGH> + , <&pro_micro 5 GPIO_ACTIVE_HIGH> + , <&pro_micro 4 GPIO_ACTIVE_HIGH> + ; + }; +}; + +&left_encoder { + status = "okay"; +}; + + diff --git a/app/boards/shields/splitkb_aurora_sofle/splitkb_aurora_sofle_right.overlay b/app/boards/shields/splitkb_aurora_sofle/splitkb_aurora_sofle_right.overlay new file mode 100644 index 00000000000..3249b94193c --- /dev/null +++ b/app/boards/shields/splitkb_aurora_sofle/splitkb_aurora_sofle_right.overlay @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2023 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include "splitkb_aurora_sofle.dtsi" + +/ { + chosen { + zmk,kscan = &kscan; + }; + + kscan: kscan { + compatible = "zmk,kscan-gpio-matrix"; + + label = "KSCAN"; + diode-direction = "col2row"; + + row-gpios + = <&pro_micro 14 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)> + , <&pro_micro 15 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)> + , <&pro_micro 18 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)> + , <&pro_micro 19 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)> + , <&pro_micro 20 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)> + ; + + col-gpios + = <&pro_micro 6 GPIO_ACTIVE_HIGH> + , <&pro_micro 7 GPIO_ACTIVE_HIGH> + , <&pro_micro 8 GPIO_ACTIVE_HIGH> + , <&pro_micro 9 GPIO_ACTIVE_HIGH> + , <&pro_micro 4 GPIO_ACTIVE_HIGH> + , <&pro_micro 5 GPIO_ACTIVE_HIGH> + ; + }; +}; + +&right_encoder { + status = "okay"; +}; + +&default_transform { + col-offset = <6>; +}; From 9a963abfc8b27c6fdfb5b6b4b38e5905d6a360a7 Mon Sep 17 00:00:00 2001 From: Xudong Zheng <7pkvm5aw@slicealias.com> Date: Mon, 17 Jul 2023 17:16:04 -0400 Subject: [PATCH 46/76] refactor: use low priority workqueue for underglow and battery reporting Blocking operations on the high priority system workqueue may result in deadlocks, particularly when Bluetooth is in use. --- app/CMakeLists.txt | 1 + app/Kconfig | 8 ++++++++ app/include/zmk/workqueue.h | 1 + app/src/battery.c | 14 +++++--------- app/src/rgb_underglow.c | 3 ++- app/src/workqueue.c | 27 +++++++++++++++++++++++++++ 6 files changed, 44 insertions(+), 10 deletions(-) create mode 100644 app/include/zmk/workqueue.h create mode 100644 app/src/workqueue.c diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 4c1c63c2cfa..efa349052cf 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -87,6 +87,7 @@ target_sources_ifdef(CONFIG_USB_DEVICE_STACK app PRIVATE src/usb.c) target_sources_ifdef(CONFIG_ZMK_USB app PRIVATE src/usb_hid.c) target_sources_ifdef(CONFIG_ZMK_RGB_UNDERGLOW app PRIVATE src/rgb_underglow.c) target_sources_ifdef(CONFIG_ZMK_BACKLIGHT app PRIVATE src/backlight.c) +target_sources(app PRIVATE src/workqueue.c) target_sources(app PRIVATE src/main.c) add_subdirectory(src/display/) diff --git a/app/Kconfig b/app/Kconfig index fe019918cbb..89a128b5a27 100644 --- a/app/Kconfig +++ b/app/Kconfig @@ -504,6 +504,14 @@ config ZMK_BATTERY_REPORT_INTERVAL int "Battery level report interval in seconds" default 60 +config ZMK_LOW_PRIORITY_THREAD_STACK_SIZE + int "Low priority thread stack size" + default 768 + +config ZMK_LOW_PRIORITY_THREAD_PRIORITY + int "Low priority thread priority" + default 10 + #Advanced endmenu diff --git a/app/include/zmk/workqueue.h b/app/include/zmk/workqueue.h new file mode 100644 index 00000000000..41e94580846 --- /dev/null +++ b/app/include/zmk/workqueue.h @@ -0,0 +1 @@ +struct k_work_q *zmk_workqueue_lowprio_work_q(); diff --git a/app/src/battery.c b/app/src/battery.c index 540f7c3eab0..87a25e08a2d 100644 --- a/app/src/battery.c +++ b/app/src/battery.c @@ -18,6 +18,7 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #include #include #include +#include static uint8_t last_state_of_charge = 0; @@ -77,7 +78,9 @@ static void zmk_battery_work(struct k_work *work) { K_WORK_DEFINE(battery_work, zmk_battery_work); -static void zmk_battery_timer(struct k_timer *timer) { k_work_submit(&battery_work); } +static void zmk_battery_timer(struct k_timer *timer) { + k_work_submit_to_queue(zmk_workqueue_lowprio_work_q(), &battery_work); +} K_TIMER_DEFINE(battery_timer, zmk_battery_timer, NULL); @@ -97,14 +100,7 @@ static int zmk_battery_init(const struct device *_arg) { return -ENODEV; } - int rc = zmk_battery_update(battery); - - if (rc != 0) { - LOG_DBG("Failed to update battery value: %d.", rc); - return rc; - } - - k_timer_start(&battery_timer, K_MINUTES(1), K_SECONDS(CONFIG_ZMK_BATTERY_REPORT_INTERVAL)); + k_timer_start(&battery_timer, K_NO_WAIT, K_SECONDS(CONFIG_ZMK_BATTERY_REPORT_INTERVAL)); return 0; } diff --git a/app/src/rgb_underglow.c b/app/src/rgb_underglow.c index 7b6491749e2..08ba2fb233e 100644 --- a/app/src/rgb_underglow.c +++ b/app/src/rgb_underglow.c @@ -24,6 +24,7 @@ #include #include #include +#include LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); @@ -203,7 +204,7 @@ static void zmk_rgb_underglow_tick_handler(struct k_timer *timer) { return; } - k_work_submit(&underglow_work); + k_work_submit_to_queue(zmk_workqueue_lowprio_work_q(), &underglow_work); } K_TIMER_DEFINE(underglow_tick, zmk_rgb_underglow_tick_handler, NULL); diff --git a/app/src/workqueue.c b/app/src/workqueue.c new file mode 100644 index 00000000000..a9a8bce5202 --- /dev/null +++ b/app/src/workqueue.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2023 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include +#include + +#include + +K_THREAD_STACK_DEFINE(lowprio_q_stack, CONFIG_ZMK_LOW_PRIORITY_THREAD_STACK_SIZE); + +static struct k_work_q lowprio_work_q; + +struct k_work_q *zmk_workqueue_lowprio_work_q() { + return &lowprio_work_q; +} + +static int workqueue_init() { + static const struct k_work_queue_config queue_config = {.name = "Low Priority Work Queue"}; + k_work_queue_start(&lowprio_work_q, lowprio_q_stack, K_THREAD_STACK_SIZEOF(lowprio_q_stack), + CONFIG_ZMK_LOW_PRIORITY_THREAD_PRIORITY, &queue_config); + return 0; +} + +SYS_INIT(workqueue_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); From cb9c573b534dcb52ee8cf6b2cec6cb880e841301 Mon Sep 17 00:00:00 2001 From: Xudong Zheng <7pkvm5aw@slicealias.com> Date: Mon, 17 Jul 2023 17:32:14 -0400 Subject: [PATCH 47/76] refactor(underglow): turn underglow off in low priority work queue --- app/src/rgb_underglow.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/app/src/rgb_underglow.c b/app/src/rgb_underglow.c index 08ba2fb233e..b80d403953f 100644 --- a/app/src/rgb_underglow.c +++ b/app/src/rgb_underglow.c @@ -197,14 +197,14 @@ static void zmk_rgb_underglow_tick(struct k_work *work) { } } -K_WORK_DEFINE(underglow_work, zmk_rgb_underglow_tick); +K_WORK_DEFINE(underglow_tick_work, zmk_rgb_underglow_tick); static void zmk_rgb_underglow_tick_handler(struct k_timer *timer) { if (!state.on) { return; } - k_work_submit_to_queue(zmk_workqueue_lowprio_work_q(), &underglow_work); + k_work_submit_to_queue(zmk_workqueue_lowprio_work_q(), &underglow_tick_work); } K_TIMER_DEFINE(underglow_tick, zmk_rgb_underglow_tick_handler, NULL); @@ -323,6 +323,16 @@ int zmk_rgb_underglow_on() { return zmk_rgb_underglow_save_state(); } +static void zmk_rgb_underglow_off_handler(struct k_work *work) { + for (int i = 0; i < STRIP_NUM_PIXELS; i++) { + pixels[i] = (struct led_rgb){r : 0, g : 0, b : 0}; + } + + led_strip_update_rgb(led_strip, pixels, STRIP_NUM_PIXELS); +} + +K_WORK_DEFINE(underglow_off_work, zmk_rgb_underglow_off_handler); + int zmk_rgb_underglow_off() { if (!led_strip) return -ENODEV; @@ -336,11 +346,7 @@ int zmk_rgb_underglow_off() { } #endif - for (int i = 0; i < STRIP_NUM_PIXELS; i++) { - pixels[i] = (struct led_rgb){r : 0, g : 0, b : 0}; - } - - led_strip_update_rgb(led_strip, pixels, STRIP_NUM_PIXELS); + k_work_submit_to_queue(zmk_workqueue_lowprio_work_q(), &underglow_off_work); k_timer_stop(&underglow_tick); state.on = false; From e65a7e3075a7a153ea478d4fd293ae65b31e33ed Mon Sep 17 00:00:00 2001 From: Xudong Zheng <7pkvm5aw@slicealias.com> Date: Thu, 20 Jul 2023 16:48:02 -0400 Subject: [PATCH 48/76] fix(battery): change nRF52 ADC gain With ADC pin, maximum 3.6V input needs gain 1/6 to be less than the 0.6V reference. With VDDHDIV5, maximum 6V input corresponds to 1.2V so gain 1/2 will be less than the 0.6V reference and be slightly more precise. --- app/drivers/sensor/battery/battery_nrf_vddh.c | 2 +- app/drivers/sensor/battery/battery_voltage_divider.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/drivers/sensor/battery/battery_nrf_vddh.c b/app/drivers/sensor/battery/battery_nrf_vddh.c index 3f230812f4b..32c7c61eb82 100644 --- a/app/drivers/sensor/battery/battery_nrf_vddh.c +++ b/app/drivers/sensor/battery/battery_nrf_vddh.c @@ -93,7 +93,7 @@ static int vddh_init(const struct device *dev) { #ifdef CONFIG_ADC_NRFX_SAADC drv_data->acc = (struct adc_channel_cfg){ - .gain = ADC_GAIN_1_5, + .gain = ADC_GAIN_1_2, .reference = ADC_REF_INTERNAL, .acquisition_time = ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 40), .input_positive = SAADC_CH_PSELN_PSELN_VDDHDIV5, diff --git a/app/drivers/sensor/battery/battery_voltage_divider.c b/app/drivers/sensor/battery/battery_voltage_divider.c index 655af3dbd74..62a02e9c3df 100644 --- a/app/drivers/sensor/battery/battery_voltage_divider.c +++ b/app/drivers/sensor/battery/battery_voltage_divider.c @@ -140,7 +140,7 @@ static int bvd_init(const struct device *dev) { #ifdef CONFIG_ADC_NRFX_SAADC drv_data->acc = (struct adc_channel_cfg){ - .gain = ADC_GAIN_1_5, + .gain = ADC_GAIN_1_6, .reference = ADC_REF_INTERNAL, .acquisition_time = ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 40), .input_positive = SAADC_CH_PSELP_PSELP_AnalogInput0 + drv_cfg->io_channel.channel, From d17c473d45b3bd01d80b8a5eab417986be0281da Mon Sep 17 00:00:00 2001 From: Jorge Villalobos Date: Wed, 2 Aug 2023 12:57:00 -0400 Subject: [PATCH 49/76] feat(docs): Improve parameterized macros docs --- docs/docs/behaviors/macros.md | 150 +++++++++++++++++++++++----------- docs/docs/config/behaviors.md | 37 +++++---- 2 files changed, 122 insertions(+), 65 deletions(-) diff --git a/docs/docs/behaviors/macros.md b/docs/docs/behaviors/macros.md index 279d135697c..0757e735285 100644 --- a/docs/docs/behaviors/macros.md +++ b/docs/docs/behaviors/macros.md @@ -49,22 +49,6 @@ For use cases involving sending a single keycode with modifiers, for instance ct with [modifier functions](../codes/modifiers.mdx#modifier-functions) can be used instead of a macro. ::: -### Parameterized Macros - -Macros can also be "parameterized", allowing them to be bound in your keymap with unique values passed into them, e.g.: - -``` - raise_layer { - bindings = <&my_cool_macro A> - }; -``` - -When defining a parameterized macro, a different `compatible` value will be used depending on how many parameters are passed into it: - -- `zmk,behavior-macro` - a macro that takes no parameters. -- `zmk,behavior-macro-one-param` - a macro that takes one parameter when used. -- `zmk,behavior-macro-two-param` - a macro that takes two parameters when used. - ### Bindings Like [hold-taps](/docs/behaviors/hold-tap), macros are created by composing other behaviors, and any of those behaviors can @@ -83,30 +67,6 @@ bindings There are a set of special macro controls that can be included in the `bindings` list to modify the way the macro is processed. -### Parameters - -When creating a macro that takes parameter(s), there are macro controls that change when the parameters passed to the macro are used -within the macro itself. All of the controls are "one shot" and will change how the passed in parameters are used for the very next non-macro control behavior in the `bindings` list of the macro. - -For example, to pass the first parameter from the macro into a `&kp` used in the macro, you would use: - -``` -bindings - = <¯o_param_1to1> - , <&kp MACRO_PLACEHOLDER> - ; -``` - -Because `kp` takes one parameter, you can't simply make the second entry `<&kp>` in the `bindings` list. Whatever value you do pass in will be replaced when the macro is triggered, so you can put _any_ value there, e.g. `0`, `A` keycode, etc. To make it very obvious that the parameter there is not actually going to be used, you can use `MACRO_PLACEHOLDER` which is simply an alias for `0`. - -The available parameter controls are: - -- `¯o_param_1to1` - pass the first parameter of the macro into the first parameter of the next behavior in the `bindings` list. -- `¯o_param_1to2` - pass the first parameter of the macro into the second parameter of the next behavior in the `bindings` list. - -* `¯o_param_2to1` - pass the second parameter of the macro into the first parameter of the next behavior in the `bindings` list. -* `¯o_param_2to2` - pass the second parameter of the macro into the second parameter of the next behavior in the `bindings` list. - ### Binding Activation Mode Bindings in a macro are activated differently, depending on the current "activation mode" of the macro. @@ -185,6 +145,70 @@ Macros use an internal queue to invoke each behavior in the bindings list when t To prevent issues with longer macros, you can change the size of this queue via the `CONFIG_ZMK_BEHAVIORS_QUEUE_SIZE` setting in your configuration, [typically through your `.conf` file](../config/index.md). For example, `CONFIG_ZMK_BEHAVIORS_QUEUE_SIZE=512` would allow your macro to type about 256 characters. +## Parameterized Macros + +Macros can also be "parameterized", allowing them to be bound in your keymap with unique values passed into them, e.g.: + +``` + raise_layer { + bindings = <&my_one_param_macro A> + }; +``` + +### Defining Parameterized Macros + +Parameterized macros must be defined using specific values for the `compatible` and `#binding-cells` properties, depending on how many parameters they require (up to a maximum of two): + +```dts +/ { + macros { + // 0 params macro + my_macro: my_macro { + // ... + compatible = "zmk,behavior-macro"; + #binding-cells = <0>; // Must be 0 + bindings = /* ... */; + }; + + // 1 param macro + my_one_param_macro: my_one_param_macro { + // ... + compatible = "zmk,behavior-macro-one-param"; + #binding-cells = <1>; // Must be 1 + bindings = /* ... */; + }; + + // 2 params macro + my_two_param_macro: my_two_param_macro { + // ... + compatible = "zmk,behavior-macro-two-param"; + #binding-cells = <2>; // Must be 2 + bindings = /* ... */; + }; + }; +}; +``` + +### Parameters, Bindings and Controls + +There are special macro controls which must be used in order to forward received parameters to the macro's `bindings`. These controls are "one shot" and will determine how received parameters are used on the very next (non-macro control) behavior in the macro's `bindings` list. + +For example, to pass the first parameter received into a `&kp` binding, you would use: + +```dts +bindings = <¯o_param_1to1>, <&kp MACRO_PLACEHOLDER>; +``` + +Because `kp` takes one parameter, you can't simply make the second entry `<&kp>` in the `bindings` list. Whatever value you do pass in will be replaced when the macro is triggered, so you can put _any_ value there, e.g. `0`, `A` keycode, etc. To make it very obvious that the parameter there is not actually going to be used, you can use `MACRO_PLACEHOLDER` which is simply an alias for `0`. + +The available parameter controls are: + +- `¯o_param_1to1` - pass the first parameter of the macro into the first parameter of the next behavior in the `bindings` list. +- `¯o_param_1to2` - pass the first parameter of the macro into the second parameter of the next behavior in the `bindings` list. + +* `¯o_param_2to1` - pass the second parameter of the macro into the first parameter of the next behavior in the `bindings` list. +* `¯o_param_2to2` - pass the second parameter of the macro into the second parameter of the next behavior in the `bindings` list. + ## Common Patterns Below are some examples of how the macro behavior can be used for various useful functionality. @@ -198,12 +222,36 @@ To achieve this, a combination of a 0ms wait time and splitting the press and re #### Layer + Modifier -``` -wait-ms = <0>; -bindings - = <¯o_press &mo 1 &kp LSHFT> - , <¯o_pause_for_release> - , <¯o_release &mo 1 &kp LSHFT>; +```dts +/** + * Temporarily switches to a layer (`&mo`) while a modifier is held. + * Analogous to QMK's `LM()`, using a parameterized macro. + * + * Params: + * 1. Layer to switch to + * 2. Modifier to press while layer is active + * + * Example: + * `&lm NUM_LAYER LSHIFT` + */ +lm: lm { + label = "LAYER_MOD"; + compatible = "zmk,behavior-macro-two-param"; + wait-ms = <0>; + tap-ms = <0>; + #binding-cells = <2>; + bindings + = <¯o_param_1to1> + , <¯o_press &mo MACRO_PLACEHOLDER> + , <¯o_param_2to1> + , <¯o_press &kp MACRO_PLACEHOLDER> + , <¯o_pause_for_release> + , <¯o_param_2to1> + , <¯o_release &kp MACRO_PLACEHOLDER> + , <¯o_param_1to1> + , <¯o_release &mo MACRO_PLACEHOLDER> + ; +}; ``` #### Layer + Underglow Color @@ -252,20 +300,24 @@ bindings ## Convenience C Macro -To avoid repetition or possible typos when declaring a macro, a convenience _C_ macro, named `ZMK_MACRO(name, props)` can be used to simplify things: +To avoid repetition or possible typos when declaring a **zero parameter macro**, a convenience _C_ macro, named `ZMK_MACRO(name, props)` can be used to simplify things: ``` - ZMK_MACRO(my_macro, + ZMK_MACRO(my_zero_param_macro, wait-ms = <30>; tap-ms = <40>; bindings = <&kp Z &kp M &kp K>; ) ``` +:::note +`ZMK_MACRO()` **only supports declaring non-parameterized (zero parameter) macros**; parameterized declarations are not currently supported. +::: + This can be used instead of a complete macro definition. During the firmware build process, the example above would produce the complete macro definition below: ``` - my_macro: my_macro { + my_zero_param_macro: my_zero_param_macro { compatible = "zmk,behavior-macro"; label = "ZM_my_macro"; #binding-cells = <0>; diff --git a/docs/docs/config/behaviors.md b/docs/docs/config/behaviors.md index 2ff99d58cbb..60e8b72abca 100644 --- a/docs/docs/config/behaviors.md +++ b/docs/docs/config/behaviors.md @@ -131,26 +131,31 @@ See the [macro behavior](../behaviors/macros.md) documentation for more details Definition file: [zmk/app/dts/bindings/behaviors/zmk,behavior-macro.yaml](https://github.com/zmkfirmware/zmk/blob/main/app/dts/bindings/behaviors/zmk%2Cbehavior-macro.yaml) -Applies to: `compatible = "zmk,behavior-macro"` +| Property | Type | Description | Default | +| ---------------- | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------- | +| `label` | string | Unique label for the node | | +| `compatible` | string | Macro type, **must be _one_ of**:
• `"zmk,behavior-macro"`
• `"zmk,behavior-macro-one-param"`
• `"zmk,behavior-macro-two-param"` | | +| `#binding-cells` | int | Number of params accepted (depends on `compatible` property), **must be _one_ of**:
• `<0>`
• `<1>`
• `<2>` | | +| `bindings` | phandle array | List of behaviors to trigger | | +| `wait-ms` | int | The default time to wait (in milliseconds) before triggering the next behavior. | `CONFIG_ZMK_MACRO_DEFAULT_WAIT_MS` | +| `tap-ms` | int | The default time to wait (in milliseconds) between the press and release events of a tapped behavior. | `CONFIG_ZMK_MACRO_DEFAULT_TAP_MS` | -| Property | Type | Description | Default | -| ---------------- | ------------- | ----------------------------------------------------------------------------------------------------- | ---------------------------------- | -| `label` | string | Unique label for the node | | -| `#binding-cells` | int | Must be `<0>` | | -| `bindings` | phandle array | List of behaviors to trigger | | -| `wait-ms` | int | The default time to wait (in milliseconds) before triggering the next behavior. | `CONFIG_ZMK_MACRO_DEFAULT_WAIT_MS` | -| `tap-ms` | int | The default time to wait (in milliseconds) between the press and release events of a tapped behavior. | `CONFIG_ZMK_MACRO_DEFAULT_TAP_MS` | +### Macro Control Behaviors The following macro-specific behaviors can be added at any point in the `bindings` list to change how the macro triggers subsequent behaviors. -| Behavior | Description | -| -------------------------- | ----------------------------------------------------------------------------------------------------- | -| `¯o_tap` | Switches to tap mode | -| `¯o_press` | Switches to press mode | -| `¯o_release` | Switches to release mode | -| `¯o_pause_for_release` | Pauses the macro until the macro key itself is released | -| `¯o_wait_time TIME` | Changes the time to wait (in milliseconds) before triggering the next behavior. | -| `¯o_tap_time TIME` | Changes the time to wait (in milliseconds) between the press and release events of a tapped behavior. | +| Behavior | Description | +| -------------------------- | -------------------------------------------------------------------------------------------------------------------- | +| `¯o_tap` | Switches to tap mode | +| `¯o_press` | Switches to press mode | +| `¯o_release` | Switches to release mode | +| `¯o_pause_for_release` | Pauses the macro until the macro key itself is released | +| `¯o_wait_time TIME` | Changes the time to wait (in milliseconds) before triggering the next behavior. | +| `¯o_tap_time TIME` | Changes the time to wait (in milliseconds) between the press and release events of a tapped behavior. | +| `¯o_param_1to1` | Forward the first parameter received by the macro to the first parameter of the next (non-macro control) behavior. | +| `¯o_param_1to2` | Forward the first parameter received by the macro to the second parameter of the next (non-macro control) behavior. | +| `¯o_param_2to1` | Forward the second parameter received by the macro to the first parameter of the next (non-macro control) behavior. | +| `¯o_param_2to2` | Forward the second parameter received by the macro to the second parameter of the next (non-macro control) behavior. | ## Mod-Morph From c957348e6187ffde3c073e8c367a60a7ee16b12c Mon Sep 17 00:00:00 2001 From: Seth Milliken Date: Tue, 8 Aug 2023 15:12:46 -0700 Subject: [PATCH 50/76] fix(docs): detail overriding the `led_strip` `chain-length` property Quite a few people have struggled with setting the correct `chain-length` for their `led_strip`. For some, this is their first time needing to change a pre-defined devicetree property, and so they aren't familiar with the technique. I commonly see folks adding a duplicate of the entire `*.overlay` file with only the `chain-length` value changed. Having clear documentation for this specific application of the property override technique could help forestall these problems, and give those of us helping out in Discord something to easily reference. --- docs/docs/features/underglow.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/docs/docs/features/underglow.md b/docs/docs/features/underglow.md index 00d3aa0ab8a..2b1400fc7e8 100644 --- a/docs/docs/features/underglow.md +++ b/docs/docs/features/underglow.md @@ -39,6 +39,20 @@ use Kconfig. If your board or shield does not have RGB underglow configured, refer to [Adding RGB Underglow to a Board](#adding-rgb-underglow-to-a-board). +### Modifying the number of LEDs + +A common issue when enabling underglow is that some of the installed LEDs do not illuminate. This can happen when a board's default underglow configuration accounts only for either the downward facing LEDs or the upward facing LEDs under each key. On a split keyboard, a good sign that this may be the problem is that the unilluminated LEDs on each half are symmetrical. + +The number of underglow LEDs is controlled by the `chain-length` property in the `led_strip` node. You can [change the value of this property](../config/index.md#changing-devicetree-properties) in the `.keymap` file by adding a stanza like this one outside of any other node (i.e. above or below the `/` node): + +``` +&led_strip { + chain-length = <21>; +}; +``` + +where the value is the total count of LEDs (per half, for split keyboards). + ## Configuring RGB Underglow See [RGB underglow configuration](/docs/config/underglow). From 9d4422980088fb6d2130ac9a3119809984762267 Mon Sep 17 00:00:00 2001 From: Stephen Wan Date: Mon, 15 Mar 2021 12:26:18 -0700 Subject: [PATCH 51/76] feature(split): add support for sensors from peripheral This commit adds a new GATT characteristics on the peripheral side and wires it up to read sensor values. The central side subscribes to this new characteristics and replays sensor values on its side. Co-authored-by: Peter Johanson --- app/include/zmk/sensors.h | 6 +- app/include/zmk/split/bluetooth/service.h | 15 +++- app/include/zmk/split/bluetooth/uuid.h | 1 + app/src/sensors.c | 6 +- app/src/split/bluetooth/central.c | 92 +++++++++++++++++++---- app/src/split/bluetooth/service.c | 78 ++++++++++++++++++- app/src/split/bluetooth/split_listener.c | 26 +++++-- 7 files changed, 196 insertions(+), 28 deletions(-) diff --git a/app/include/zmk/sensors.h b/app/include/zmk/sensors.h index 8ac1c283cb6..1919d4ce647 100644 --- a/app/include/zmk/sensors.h +++ b/app/include/zmk/sensors.h @@ -24,7 +24,9 @@ struct zmk_sensor_config { uint16_t triggers_per_rotation; }; +// This struct is also used for data transfer for splits, so any changes to the size, layout, etc +// is a breaking change for the split GATT service protocol. struct zmk_sensor_channel_data { - enum sensor_channel channel; struct sensor_value value; -}; + enum sensor_channel channel; +} __packed; diff --git a/app/include/zmk/split/bluetooth/service.h b/app/include/zmk/split/bluetooth/service.h index f0c1d79ff7d..112cd552942 100644 --- a/app/include/zmk/split/bluetooth/service.h +++ b/app/include/zmk/split/bluetooth/service.h @@ -6,8 +6,18 @@ #pragma once +#include +#include + #define ZMK_SPLIT_RUN_BEHAVIOR_DEV_LEN 9 +struct sensor_event { + uint8_t sensor_index; + + uint8_t channel_data_size; + struct zmk_sensor_channel_data channel_data[ZMK_SENSOR_EVENT_MAX_CHANNELS]; +} __packed; + struct zmk_split_run_behavior_data { uint8_t position; uint8_t state; @@ -21,4 +31,7 @@ struct zmk_split_run_behavior_payload { } __packed; int zmk_split_bt_position_pressed(uint8_t position); -int zmk_split_bt_position_released(uint8_t position); \ No newline at end of file +int zmk_split_bt_position_released(uint8_t position); +int zmk_split_bt_sensor_triggered(uint8_t sensor_index, + const struct zmk_sensor_channel_data channel_data[], + size_t channel_data_size); diff --git a/app/include/zmk/split/bluetooth/uuid.h b/app/include/zmk/split/bluetooth/uuid.h index cbdb17723cd..c38131dd83e 100644 --- a/app/include/zmk/split/bluetooth/uuid.h +++ b/app/include/zmk/split/bluetooth/uuid.h @@ -16,3 +16,4 @@ #define ZMK_SPLIT_BT_SERVICE_UUID ZMK_BT_SPLIT_UUID(0x00000000) #define ZMK_SPLIT_BT_CHAR_POSITION_STATE_UUID ZMK_BT_SPLIT_UUID(0x00000001) #define ZMK_SPLIT_BT_CHAR_RUN_BEHAVIOR_UUID ZMK_BT_SPLIT_UUID(0x00000002) +#define ZMK_SPLIT_BT_CHAR_SENSOR_STATE_UUID ZMK_BT_SPLIT_UUID(0x00000003) diff --git a/app/src/sensors.c b/app/src/sensors.c index e339afe0437..60f2bd2a33f 100644 --- a/app/src/sensors.c +++ b/app/src/sensors.c @@ -29,7 +29,7 @@ struct sensors_item_cfg { { \ .dev = DEVICE_DT_GET_OR_NULL(node), \ .trigger = {.type = SENSOR_TRIG_DATA_READY, .chan = SENSOR_CHAN_ROTATION}, \ - .config = &configs[idx] \ + .config = &configs[idx], .sensor_index = idx \ } #define SENSOR_ITEM(idx, _i) _SENSOR_ITEM(idx, ZMK_KEYMAP_SENSORS_BY_IDX(idx)) @@ -112,7 +112,7 @@ static void zmk_sensors_trigger_handler(const struct device *dev, int sensor_index = test_item - sensors; if (sensor_index < 0 || sensor_index >= ARRAY_SIZE(sensors)) { - LOG_ERR("Invalid sensor item triggered our callback"); + LOG_ERR("Invalid sensor item triggered our callback (%d)", sensor_index); return; } @@ -127,8 +127,6 @@ static void zmk_sensors_trigger_handler(const struct device *dev, static void zmk_sensors_init_item(uint8_t i) { LOG_DBG("Init sensor at index %d", i); - sensors[i].sensor_index = i; - if (!sensors[i].dev) { LOG_DBG("No local device for %d", i); return; diff --git a/app/src/split/bluetooth/central.c b/app/src/split/bluetooth/central.c index 8a5e9d35c5a..b70d79e3a3a 100644 --- a/app/src/split/bluetooth/central.c +++ b/app/src/split/bluetooth/central.c @@ -21,10 +21,12 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #include #include #include +#include #include #include #include #include +#include static int start_scanning(void); @@ -41,6 +43,7 @@ struct peripheral_slot { struct bt_conn *conn; struct bt_gatt_discover_params discover_params; struct bt_gatt_subscribe_params subscribe_params; + struct bt_gatt_subscribe_params sensor_subscribe_params; struct bt_gatt_discover_params sub_discover_params; uint16_t run_behavior_handle; uint8_t position_state[POSITION_STATE_DATA_LEN]; @@ -165,6 +168,52 @@ int confirm_peripheral_slot_conn(struct bt_conn *conn) { return 0; } +#if ZMK_KEYMAP_HAS_SENSORS +K_MSGQ_DEFINE(peripheral_sensor_event_msgq, sizeof(struct zmk_sensor_event), + CONFIG_ZMK_SPLIT_BLE_CENTRAL_POSITION_QUEUE_SIZE, 4); + +void peripheral_sensor_event_work_callback(struct k_work *work) { + struct zmk_sensor_event ev; + while (k_msgq_get(&peripheral_sensor_event_msgq, &ev, K_NO_WAIT) == 0) { + LOG_DBG("Trigger sensor change for %d", ev.sensor_index); + ZMK_EVENT_RAISE(new_zmk_sensor_event(ev)); + } +} + +K_WORK_DEFINE(peripheral_sensor_event_work, peripheral_sensor_event_work_callback); + +static uint8_t split_central_sensor_notify_func(struct bt_conn *conn, + struct bt_gatt_subscribe_params *params, + const void *data, uint16_t length) { + if (!data) { + LOG_DBG("[UNSUBSCRIBED]"); + params->value_handle = 0U; + return BT_GATT_ITER_STOP; + } + + LOG_DBG("[SENSOR NOTIFICATION] data %p length %u", data, length); + + if (length < offsetof(struct sensor_event, channel_data)) { + LOG_WRN("Ignoring sensor notify with insufficient data length (%d)", length); + return BT_GATT_ITER_STOP; + } + + struct sensor_event sensor_event; + memcpy(&sensor_event, data, MIN(length, sizeof(sensor_event))); + struct zmk_sensor_event ev = { + .sensor_index = sensor_event.sensor_index, + .channel_data_size = MIN(sensor_event.channel_data_size, ZMK_SENSOR_EVENT_MAX_CHANNELS), + .timestamp = k_uptime_get()}; + + memcpy(ev.channel_data, sensor_event.channel_data, + sizeof(struct zmk_sensor_channel_data) * sensor_event.channel_data_size); + k_msgq_put(&peripheral_sensor_event_msgq, &ev, K_NO_WAIT); + k_work_submit(&peripheral_sensor_event_work); + + return BT_GATT_ITER_CONTINUE; +} +#endif /* ZMK_KEYMAP_HAS_SENSORS */ + static uint8_t split_central_notify_func(struct bt_conn *conn, struct bt_gatt_subscribe_params *params, const void *data, uint16_t length) { @@ -209,14 +258,8 @@ static uint8_t split_central_notify_func(struct bt_conn *conn, return BT_GATT_ITER_CONTINUE; } -static void split_central_subscribe(struct bt_conn *conn) { - struct peripheral_slot *slot = peripheral_slot_for_conn(conn); - if (slot == NULL) { - LOG_ERR("No peripheral state found for connection"); - return; - } - - int err = bt_gatt_subscribe(conn, &slot->subscribe_params); +static int split_central_subscribe(struct bt_conn *conn, struct bt_gatt_subscribe_params *params) { + int err = bt_gatt_subscribe(conn, params); switch (err) { case -EALREADY: LOG_DBG("[ALREADY SUBSCRIBED]"); @@ -228,6 +271,8 @@ static void split_central_subscribe(struct bt_conn *conn) { LOG_ERR("Subscribe failed (err %d)", err); break; } + + return err; } static uint8_t split_central_chrc_discovery_func(struct bt_conn *conn, @@ -250,9 +295,9 @@ static uint8_t split_central_chrc_discovery_func(struct bt_conn *conn, } LOG_DBG("[ATTRIBUTE] handle %u", attr->handle); + const struct bt_uuid *chrc_uuid = ((struct bt_gatt_chrc *)attr->user_data)->uuid; - if (bt_uuid_cmp(((struct bt_gatt_chrc *)attr->user_data)->uuid, - BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_POSITION_STATE_UUID)) == 0) { + if (bt_uuid_cmp(chrc_uuid, BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_POSITION_STATE_UUID)) == 0) { LOG_DBG("Found position state characteristic"); slot->discover_params.uuid = NULL; slot->discover_params.start_handle = attr->handle + 2; @@ -263,14 +308,33 @@ static uint8_t split_central_chrc_discovery_func(struct bt_conn *conn, slot->subscribe_params.value_handle = bt_gatt_attr_value_handle(attr); slot->subscribe_params.notify = split_central_notify_func; slot->subscribe_params.value = BT_GATT_CCC_NOTIFY; - split_central_subscribe(conn); - } else if (bt_uuid_cmp(((struct bt_gatt_chrc *)attr->user_data)->uuid, - BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_RUN_BEHAVIOR_UUID)) == 0) { + split_central_subscribe(conn, &slot->subscribe_params); +#if ZMK_KEYMAP_HAS_SENSORS + } else if (bt_uuid_cmp(chrc_uuid, BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_SENSOR_STATE_UUID)) == + 0) { + slot->discover_params.uuid = NULL; + slot->discover_params.start_handle = attr->handle + 2; + slot->discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC; + + slot->sensor_subscribe_params.disc_params = &slot->sub_discover_params; + slot->sensor_subscribe_params.end_handle = slot->discover_params.end_handle; + slot->sensor_subscribe_params.value_handle = bt_gatt_attr_value_handle(attr); + slot->sensor_subscribe_params.notify = split_central_sensor_notify_func; + slot->sensor_subscribe_params.value = BT_GATT_CCC_NOTIFY; + split_central_subscribe(conn, &slot->sensor_subscribe_params); +#endif /* ZMK_KEYMAP_HAS_SENSORS */ + } else if (bt_uuid_cmp(chrc_uuid, BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_RUN_BEHAVIOR_UUID)) == + 0) { LOG_DBG("Found run behavior handle"); + slot->discover_params.uuid = NULL; + slot->discover_params.start_handle = attr->handle + 2; slot->run_behavior_handle = bt_gatt_attr_value_handle(attr); } - bool subscribed = (slot->run_behavior_handle && slot->subscribe_params.value_handle); + bool subscribed = slot->run_behavior_handle && slot->subscribe_params.value_handle; +#if ZMK_KEYMAP_HAS_SENSORS + subscribed = subscribed && slot->sensor_subscribe_params.value_handle; +#endif /* ZMK_KEYMAP_HAS_SENSORS */ return subscribed ? BT_GATT_ITER_STOP : BT_GATT_ITER_CONTINUE; } diff --git a/app/src/split/bluetooth/service.c b/app/src/split/bluetooth/service.c index f7b0d587b26..620df53e11c 100644 --- a/app/src/split/bluetooth/service.c +++ b/app/src/split/bluetooth/service.c @@ -4,6 +4,7 @@ * SPDX-License-Identifier: MIT */ +#include #include #include #include @@ -20,6 +21,22 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #include #include #include +#include +#include + +#if ZMK_KEYMAP_HAS_SENSORS +static struct sensor_event last_sensor_event; + +static ssize_t split_svc_sensor_state(struct bt_conn *conn, const struct bt_gatt_attr *attrs, + void *buf, uint16_t len, uint16_t offset) { + return bt_gatt_attr_read(conn, attrs, buf, len, offset, &last_sensor_event, + sizeof(last_sensor_event)); +} + +static void split_svc_sensor_state_ccc(const struct bt_gatt_attr *attr, uint16_t value) { + LOG_DBG("value %d", value); +} +#endif /* ZMK_KEYMAP_HAS_SENSORS */ #define POS_STATE_LEN 16 @@ -98,7 +115,14 @@ BT_GATT_SERVICE_DEFINE( BT_GATT_CHRC_WRITE_WITHOUT_RESP, BT_GATT_PERM_WRITE_ENCRYPT, NULL, split_svc_run_behavior, &behavior_run_payload), BT_GATT_DESCRIPTOR(BT_UUID_NUM_OF_DIGITALS, BT_GATT_PERM_READ, split_svc_num_of_positions, NULL, - &num_of_positions), ); + &num_of_positions), +#if ZMK_KEYMAP_HAS_SENSORS + BT_GATT_CHARACTERISTIC(BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_SENSOR_STATE_UUID), + BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, BT_GATT_PERM_READ_ENCRYPT, + split_svc_sensor_state, NULL, &last_sensor_event), + BT_GATT_CCC(split_svc_sensor_state_ccc, BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT), +#endif /* ZMK_KEYMAP_HAS_SENSORS */ +); K_THREAD_STACK_DEFINE(service_q_stack, CONFIG_ZMK_SPLIT_BLE_PERIPHERAL_STACK_SIZE); @@ -151,6 +175,58 @@ int zmk_split_bt_position_released(uint8_t position) { return send_position_state(); } +#if ZMK_KEYMAP_HAS_SENSORS +K_MSGQ_DEFINE(sensor_state_msgq, sizeof(struct sensor_event), + CONFIG_ZMK_SPLIT_BLE_PERIPHERAL_POSITION_QUEUE_SIZE, 4); + +void send_sensor_state_callback(struct k_work *work) { + while (k_msgq_get(&sensor_state_msgq, &last_sensor_event, K_NO_WAIT) == 0) { + int err = bt_gatt_notify(NULL, &split_svc.attrs[8], &last_sensor_event, + sizeof(last_sensor_event)); + if (err) { + LOG_DBG("Error notifying %d", err); + } + } +}; + +K_WORK_DEFINE(service_sensor_notify_work, send_sensor_state_callback); + +int send_sensor_state(struct sensor_event ev) { + int err = k_msgq_put(&sensor_state_msgq, &ev, K_MSEC(100)); + if (err) { + // retry... + switch (err) { + case -EAGAIN: { + LOG_WRN("Sensor state message queue full, popping first message and queueing again"); + struct sensor_event discarded_state; + k_msgq_get(&sensor_state_msgq, &discarded_state, K_NO_WAIT); + return send_sensor_state(ev); + } + default: + LOG_WRN("Failed to queue sensor state to send (%d)", err); + return err; + } + } + + k_work_submit_to_queue(&service_work_q, &service_sensor_notify_work); + return 0; +} + +int zmk_split_bt_sensor_triggered(uint8_t sensor_index, + const struct zmk_sensor_channel_data channel_data[], + size_t channel_data_size) { + if (channel_data_size > ZMK_SENSOR_EVENT_MAX_CHANNELS) { + return -EINVAL; + } + + struct sensor_event ev = + (struct sensor_event){.sensor_index = sensor_index, .channel_data_size = channel_data_size}; + memcpy(ev.channel_data, channel_data, + channel_data_size * sizeof(struct zmk_sensor_channel_data)); + return send_sensor_state(ev); +} +#endif /* ZMK_KEYMAP_HAS_SENSORS */ + int service_init(const struct device *_arg) { static const struct k_work_queue_config queue_config = { .name = "Split Peripheral Notification Queue"}; diff --git a/app/src/split/bluetooth/split_listener.c b/app/src/split/bluetooth/split_listener.c index eb5398c42d6..9b680d2c89c 100644 --- a/app/src/split/bluetooth/split_listener.c +++ b/app/src/split/bluetooth/split_listener.c @@ -13,21 +13,35 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #include #include +#include #include +#include #include int split_listener(const zmk_event_t *eh) { LOG_DBG(""); - const struct zmk_position_state_changed *ev = as_zmk_position_state_changed(eh); - if (ev != NULL) { - if (ev->state) { - return zmk_split_bt_position_pressed(ev->position); + const struct zmk_position_state_changed *pos_ev; + if ((pos_ev = as_zmk_position_state_changed(eh)) != NULL) { + if (pos_ev->state) { + return zmk_split_bt_position_pressed(pos_ev->position); } else { - return zmk_split_bt_position_released(ev->position); + return zmk_split_bt_position_released(pos_ev->position); } } + +#if ZMK_KEYMAP_HAS_SENSORS + const struct zmk_sensor_event *sensor_ev; + if ((sensor_ev = as_zmk_sensor_event(eh)) != NULL) { + return zmk_split_bt_sensor_triggered(sensor_ev->sensor_index, sensor_ev->channel_data, + sensor_ev->channel_data_size); + } +#endif /* ZMK_KEYMAP_HAS_SENSORS */ return ZMK_EV_EVENT_BUBBLE; } ZMK_LISTENER(split_listener, split_listener); -ZMK_SUBSCRIPTION(split_listener, zmk_position_state_changed); \ No newline at end of file +ZMK_SUBSCRIPTION(split_listener, zmk_position_state_changed); + +#if ZMK_KEYMAP_HAS_SENSORS +ZMK_SUBSCRIPTION(split_listener, zmk_sensor_event); +#endif /* ZMK_KEYMAP_HAS_SENSORS */ From dcb1f8f13528effc3e2ee3dadf9b385bf2394037 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Fri, 23 Jun 2023 07:28:27 +0000 Subject: [PATCH 52/76] fix(docs): Update docs about split encoder support --- docs/docs/features/encoders.md | 4 ---- docs/docs/intro.md | 9 ++++----- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/docs/docs/features/encoders.md b/docs/docs/features/encoders.md index 29906c909de..0c493330cc6 100644 --- a/docs/docs/features/encoders.md +++ b/docs/docs/features/encoders.md @@ -5,10 +5,6 @@ sidebar_label: Encoders Existing support for encoders in ZMK is focused around the five pin EC11 rotary encoder with push button design used in the majority of current keyboard and macropad designs. -:::note -Encoders are currently only support on the left/central sides of splits. For progress on this, see [#728](https://github.com/zmkfirmware/zmk/pull/728). -::: - ## Enabling EC11 Encoders To enable encoders for boards that have existing encoder support, uncomment the `CONFIG_EC11=y` and `CONFIG_EC11_TRIGGER_GLOBAL_THREAD=y` lines in your board's .conf file in your `zmk-config/config` folder. Save and push your changes, then download and flash the new firmware. diff --git a/docs/docs/intro.md b/docs/docs/intro.md index 142dcafc97e..d65ac46e405 100644 --- a/docs/docs/intro.md +++ b/docs/docs/intro.md @@ -23,11 +23,11 @@ ZMK is currently missing some features found in other popular firmware. This tab | Split Keyboard Support | ✅ | ✅ | ✅ | | [Keymaps and Layers](behaviors/layers.md) | ✅ | ✅ | ✅ | | [Hold-Tap](behaviors/hold-tap.md) (which includes [Mod-Tap](behaviors/mod-tap.md) and [Layer-Tap](behaviors/layers.md/#layer-tap)) | ✅ | ✅ | ✅ | -| [Tap-Dance](behaviors/tap-dance.md) | ✅ | ✅[^3] | ✅ | +| [Tap-Dance](behaviors/tap-dance.md) | ✅ | ✅[^2] | ✅ | | [Keyboard Codes](codes/index.mdx#keyboard) | ✅ | ✅ | ✅ | | [Media](codes/index.mdx#media-controls) & [Consumer](codes/index.mdx#consumer-controls) Codes | ✅ | ✅ | ✅ | -| [Encoders](features/encoders.md)[^1] | ✅ | ✅ | ✅ | -| [Display Support](features/displays.md)[^2] | 🚧 | 🚧 | ✅ | +| [Encoders](features/encoders.md) | ✅ | ✅ | ✅ | +| [Display Support](features/displays.md)[^1] | 🚧 | 🚧 | ✅ | | [RGB Underglow](features/underglow.md) | ✅ | ✅ | ✅ | | [Backlight](features/backlight.md) | ✅ | ✅ | ✅ | | One Shot Keys | ✅ | ✅ | ✅ | @@ -43,8 +43,7 @@ ZMK is currently missing some features found in other popular firmware. This tab | AVR/8 Bit | | | ✅ | | [Wide Range of ARM Chips Supported](https://docs.zephyrproject.org/latest/boards/index.html) | ✅ | | | -[^3]: Tap-Dances are limited to single and double-tap on BlueMicro -[^2]: Encoders are not currently supported on peripheral side splits. +[^2]: Tap-Dances are limited to single and double-tap on BlueMicro [^1]: OLEDs are currently proof of concept in ZMK. ## Code Of Conduct From a92a4967aa85f4ab19d36bcb81afc0420f2775d2 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Wed, 28 Jun 2023 19:26:33 +0000 Subject: [PATCH 53/76] fix(sensors): Only accept data once per behavior. * Don't accept data for the same behavior on multiple layers more than once, to avoid duplicate/extraneous triggers. --- app/include/zmk/keymap.h | 4 ++++ app/src/behaviors/behavior_sensor_rotate_common.c | 15 ++++++++------- app/src/behaviors/behavior_sensor_rotate_common.h | 5 +++-- app/src/keymap.c | 4 ---- 4 files changed, 15 insertions(+), 13 deletions(-) diff --git a/app/include/zmk/keymap.h b/app/include/zmk/keymap.h index a47cd505643..9ce140bfa27 100644 --- a/app/include/zmk/keymap.h +++ b/app/include/zmk/keymap.h @@ -8,6 +8,10 @@ #include +#define ZMK_LAYER_CHILD_LEN_PLUS_ONE(node) 1 + +#define ZMK_KEYMAP_LAYERS_LEN \ + (DT_FOREACH_CHILD(DT_INST(0, zmk_keymap), ZMK_LAYER_CHILD_LEN_PLUS_ONE) 0) + typedef uint32_t zmk_keymap_layers_state_t; uint8_t zmk_keymap_layer_default(); diff --git a/app/src/behaviors/behavior_sensor_rotate_common.c b/app/src/behaviors/behavior_sensor_rotate_common.c index 586cac3fdf2..98b4aec1267 100644 --- a/app/src/behaviors/behavior_sensor_rotate_common.c +++ b/app/src/behaviors/behavior_sensor_rotate_common.c @@ -28,7 +28,7 @@ int zmk_behavior_sensor_rotate_common_accept_data( if (value.val1 == 0) { triggers = value.val2; } else { - struct sensor_value remainder = data->remainder[sensor_index]; + struct sensor_value remainder = data->remainder[sensor_index][event.layer]; remainder.val1 += value.val1; remainder.val2 += value.val2; @@ -42,15 +42,16 @@ int zmk_behavior_sensor_rotate_common_accept_data( triggers = remainder.val1 / trigger_degrees; remainder.val1 %= trigger_degrees; - data->remainder[sensor_index] = remainder; + data->remainder[sensor_index][event.layer] = remainder; } LOG_DBG( "val1: %d, val2: %d, remainder: %d/%d triggers: %d inc keycode 0x%02X dec keycode 0x%02X", - value.val1, value.val2, data->remainder[sensor_index].val1, - data->remainder[sensor_index].val2, triggers, binding->param1, binding->param2); + value.val1, value.val2, data->remainder[sensor_index][event.layer].val1, + data->remainder[sensor_index][event.layer].val2, triggers, binding->param1, + binding->param2); - data->triggers[sensor_index] = triggers; + data->triggers[sensor_index][event.layer] = triggers; return 0; } @@ -64,11 +65,11 @@ int zmk_behavior_sensor_rotate_common_process(struct zmk_behavior_binding *bindi const int sensor_index = ZMK_SENSOR_POSITION_FROM_VIRTUAL_KEY_POSITION(event.position); if (mode != BEHAVIOR_SENSOR_BINDING_PROCESS_MODE_TRIGGER) { - data->triggers[sensor_index] = 0; + data->triggers[sensor_index][event.layer] = 0; return ZMK_BEHAVIOR_TRANSPARENT; } - int triggers = data->triggers[sensor_index]; + int triggers = data->triggers[sensor_index][event.layer]; struct zmk_behavior_binding triggered_binding; if (triggers > 0) { diff --git a/app/src/behaviors/behavior_sensor_rotate_common.h b/app/src/behaviors/behavior_sensor_rotate_common.h index d354b67937c..c92ac3d5e5f 100644 --- a/app/src/behaviors/behavior_sensor_rotate_common.h +++ b/app/src/behaviors/behavior_sensor_rotate_common.h @@ -6,6 +6,7 @@ #include #include +#include #include struct behavior_sensor_rotate_config { @@ -16,8 +17,8 @@ struct behavior_sensor_rotate_config { }; struct behavior_sensor_rotate_data { - struct sensor_value remainder[ZMK_KEYMAP_SENSORS_LEN]; - int triggers[ZMK_KEYMAP_SENSORS_LEN]; + struct sensor_value remainder[ZMK_KEYMAP_SENSORS_LEN][ZMK_KEYMAP_LAYERS_LEN]; + int triggers[ZMK_KEYMAP_SENSORS_LEN][ZMK_KEYMAP_LAYERS_LEN]; }; int zmk_behavior_sensor_rotate_common_accept_data( diff --git a/app/src/keymap.c b/app/src/keymap.c index 020faf3f2be..bda694276c8 100644 --- a/app/src/keymap.c +++ b/app/src/keymap.c @@ -31,10 +31,6 @@ static uint8_t _zmk_keymap_layer_default = 0; #define DT_DRV_COMPAT zmk_keymap -#define LAYER_CHILD_LEN(node) 1 + -#define ZMK_KEYMAP_NODE DT_DRV_INST(0) -#define ZMK_KEYMAP_LAYERS_LEN (DT_INST_FOREACH_CHILD(0, LAYER_CHILD_LEN) 0) - #define BINDING_WITH_COMMA(idx, drv_inst) ZMK_KEYMAP_EXTRACT_BINDING(idx, drv_inst) #define TRANSFORMED_LAYER(node) \ From 185457bc1169176037aa281edb0a9bf485a70dbd Mon Sep 17 00:00:00 2001 From: Mikhail Stralenia Date: Tue, 29 Aug 2023 18:53:30 +0300 Subject: [PATCH 54/76] fix(shields): leeloo - proper encoder status for split encoders. --- app/boards/shields/leeloo/leeloo_common.dtsi | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/boards/shields/leeloo/leeloo_common.dtsi b/app/boards/shields/leeloo/leeloo_common.dtsi index 6ce93504b2d..ef775cfbe61 100644 --- a/app/boards/shields/leeloo/leeloo_common.dtsi +++ b/app/boards/shields/leeloo/leeloo_common.dtsi @@ -51,6 +51,7 @@ RC(3,0) RC(3,1) RC(3,2) RC(3,3) RC(3,4) RC(3,5) RC(4,5) RC(4,6) RC(3,6) RC(3,7) a-gpios = <&pro_micro 21 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; b-gpios = <&pro_micro 20 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; steps = <120>; + status = "disabled"; }; right_encoder: right_encoder { @@ -59,6 +60,7 @@ RC(3,0) RC(3,1) RC(3,2) RC(3,3) RC(3,4) RC(3,5) RC(4,5) RC(4,6) RC(3,6) RC(3,7) a-gpios = <&pro_micro 20 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; b-gpios = <&pro_micro 21 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; steps = <120>; + status = "disabled"; }; sensors { @@ -87,4 +89,4 @@ RC(3,0) RC(3,1) RC(3,2) RC(3,3) RC(3,4) RC(3,5) RC(4,5) RC(4,6) RC(3,6) RC(3,7) com-sequential; prechargep = <0x22>; }; -}; \ No newline at end of file +}; From fd4796583810b6fa42edcee7aa33fa9db4ba4a44 Mon Sep 17 00:00:00 2001 From: Cem Aksoylar Date: Sat, 2 Sep 2023 13:49:18 -0700 Subject: [PATCH 55/76] fix(docs): Remove diode-direction from direct GPIO driver --- docs/docs/config/kscan.md | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/docs/docs/config/kscan.md b/docs/docs/config/kscan.md index 787d513661f..d240d79fe67 100644 --- a/docs/docs/config/kscan.md +++ b/docs/docs/config/kscan.md @@ -72,16 +72,15 @@ Applies to: `compatible = "zmk,kscan-gpio-direct"` Definition file: [zmk/app/drivers/zephyr/dts/bindings/kscan/zmk,kscan-gpio-direct.yaml](https://github.com/zmkfirmware/zmk/blob/main/app/drivers/zephyr/dts/bindings/kscan/zmk%2Ckscan-gpio-direct.yaml) -| Property | Type | Description | Default | -| ------------------------- | ---------- | ----------------------------------------------------------------------------------------------------------- | ----------- | -| `label` | string | Unique label for the node | | -| `input-gpios` | GPIO array | Input GPIOs (one per key) | | -| `debounce-press-ms` | int | Debounce time for key press in milliseconds. Use 0 for eager debouncing. | 5 | -| `debounce-release-ms` | int | Debounce time for key release in milliseconds. | 5 | -| `debounce-scan-period-ms` | int | Time between reads in milliseconds when any key is pressed. | 1 | -| `diode-direction` | string | The direction of the matrix diodes | `"row2col"` | -| `poll-period-ms` | int | Time between reads in milliseconds when no key is pressed and `CONFIG_ZMK_KSCAN_DIRECT_POLLING` is enabled. | 10 | -| `toggle-mode` | bool | Use toggle switch mode. | n | +| Property | Type | Description | Default | +| ------------------------- | ---------- | ----------------------------------------------------------------------------------------------------------- | ------- | +| `label` | string | Unique label for the node | | +| `input-gpios` | GPIO array | Input GPIOs (one per key) | | +| `debounce-press-ms` | int | Debounce time for key press in milliseconds. Use 0 for eager debouncing. | 5 | +| `debounce-release-ms` | int | Debounce time for key release in milliseconds. | 5 | +| `debounce-scan-period-ms` | int | Time between reads in milliseconds when any key is pressed. | 1 | +| `poll-period-ms` | int | Time between reads in milliseconds when no key is pressed and `CONFIG_ZMK_KSCAN_DIRECT_POLLING` is enabled. | 10 | +| `toggle-mode` | bool | Use toggle switch mode. | n | By default, a switch will drain current through the internal pull up/down resistor whenever it is pressed. This is not ideal for a toggle switch, where the switch may be left in the "pressed" state for a long time. Enabling `toggle-mode` will make the driver flip between pull up and down as the switch is toggled to optimize for power. From 1e11e84d0d367a90d155df1d13824077f61bf158 Mon Sep 17 00:00:00 2001 From: Cem Aksoylar Date: Sat, 2 Sep 2023 14:44:37 -0700 Subject: [PATCH 56/76] fix(docs): Fix row/col comments in matrix examples --- docs/docs/config/kscan.md | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/docs/docs/config/kscan.md b/docs/docs/config/kscan.md index d240d79fe67..5c70f4ba1b1 100644 --- a/docs/docs/config/kscan.md +++ b/docs/docs/config/kscan.md @@ -296,9 +296,7 @@ Any keyboard which is not a grid of 1 unit keys will likely have some unused pos kscan0: kscan { compatible = "zmk,kscan-gpio-matrix"; - rows = <5>; - columns = <4>; - // define the matrix... + // define row-gpios with 5 elements and col-gpios with 4... }; default_transform: matrix_transform { @@ -358,9 +356,7 @@ Consider a keyboard with a [duplex matrix](https://wiki.ai03.com/books/pcb-desig kscan0: kscan { compatible = "zmk,kscan-gpio-matrix"; - rows = <12>; - columns = <8>; - // define the matrix... + // define row-gpios with 12 elements and col-gpios with 8... }; default_transform: matrix_transform { From 3d938033b002c78ce24245e3cf37b7ba55876145 Mon Sep 17 00:00:00 2001 From: Cem Aksoylar Date: Sat, 2 Sep 2023 14:45:25 -0700 Subject: [PATCH 57/76] feat(docs): Note GPIO flags and add examples --- docs/docs/config/kscan.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/docs/docs/config/kscan.md b/docs/docs/config/kscan.md index 5c70f4ba1b1..296cb4a179c 100644 --- a/docs/docs/config/kscan.md +++ b/docs/docs/config/kscan.md @@ -86,6 +86,18 @@ By default, a switch will drain current through the internal pull up/down resist `toggle-mode` applies to all switches handled by the instance of the driver. To use a toggle switch with other, non-toggle, direct GPIO switches, create two instances of the direct GPIO driver, one with `toggle-mode` and the other without. Then, use a [composite driver](#composite-driver) to combine them. +Assuming the switches connect each GPIO pin to the ground, the [GPIO flags](https://docs.zephyrproject.org/3.2.0/hardware/peripherals/gpio.html#api-reference) for the elements in `input-gpios` should be `(GPIO_ACTIVE_LOW | GPIO_PULL_UP)`: + +```devicetree + kscan0: kscan { + compatible = "zmk,kscan-gpio-direct"; + input-gpios + = <&pro_micro 4 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)> + , <&pro_micro 5 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)> + ; + }; +``` + ## Matrix Driver Keyboard scan driver where keys are arranged on a matrix with one GPIO per row and column. @@ -122,6 +134,24 @@ The `diode-direction` property must be one of: | `"row2col"` | Diodes point from rows to columns (cathodes are connected to columns) | | `"col2row"` | Diodes point from columns to rows (cathodes are connected to rows) | +Given the `diode-direction`, the [GPIO flags](https://docs.zephyrproject.org/3.2.0/hardware/peripherals/gpio.html#api-reference) for the elements in `row-` and `col-gpios` should be set appropriately. +The output pins (e.g. columns for `col2row`) should have the flag `GPIO_ACTIVE_HIGH`, and input pins (e.g. rows for `col2row`) should have the flags `(GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)`: + +```devicetree + kscan0: kscan { + compatible = "zmk,kscan-gpio-matrix"; + diode-direction = "col2row"; + col-gpios + = <&pro_micro 4 GPIO_ACTIVE_HIGH> + , <&pro_micro 5 GPIO_ACTIVE_HIGH> + ; + row-gpios + = <&pro_micro 6 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> + , <&pro_micro 7 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> + ; + }; +``` + ## Composite Driver Keyboard scan driver which combines multiple other keyboard scan drivers. From 369c7c1721861c9a0e5e47c6b1090abe8cfb0566 Mon Sep 17 00:00:00 2001 From: Cem Aksoylar Date: Sat, 2 Sep 2023 14:10:59 -0700 Subject: [PATCH 58/76] fix(docs): Correct default macro wait/tap ms --- docs/docs/behaviors/macros.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/docs/behaviors/macros.md b/docs/docs/behaviors/macros.md index 0757e735285..4836c205e41 100644 --- a/docs/docs/behaviors/macros.md +++ b/docs/docs/behaviors/macros.md @@ -111,7 +111,8 @@ bindings ### Wait Time -The wait time setting controls how long of a delay is introduced between behaviors in the `bindings` list. The initial wait time for a macro, 100ms by default, can +The wait time setting controls how long of a delay is introduced between behaviors in the `bindings` list. The initial wait time for a macro, +which is equal to the value of [`CONFIG_ZMK_MACRO_DEFAULT_WAIT_MS`](../config/behaviors.md#macro) by default, can be set by assigning a value to the `wait-ms` property of the macro, e.g. `wait-ms = <20>;`. If you want to update the wait time at any point in the macro bindings list, use `¯o_wait_time`, e.g. `¯o_wait_time 30`. A full example: @@ -126,7 +127,8 @@ bindings ### Tap Time -The tap time setting controls how long a tapped behavior is held in the `bindings` list. The initial tap time for a macro, 100ms by default, can +The tap time setting controls how long a tapped behavior is held in the `bindings` list. The initial tap time for a macro, +which is equal to the value of [`CONFIG_ZMK_MACRO_DEFAULT_TAP_MS`](../config/behaviors.md#macro) by default, can be set by assigning a value to the `tap-ms` property of the macro, e.g. `tap-ms = <20>;`. If you want to update the tap time at any point in a macro bindings list, use `¯o_tap_time`, e.g. `¯o_tap_time 30`. A full example: From b20d3178b9d681f2b959cc7980d7252cda415189 Mon Sep 17 00:00:00 2001 From: Cem Aksoylar Date: Sat, 2 Sep 2023 14:11:30 -0700 Subject: [PATCH 59/76] feat(docs): Note devicetree limits re: macro bindings --- docs/docs/behaviors/macros.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/docs/behaviors/macros.md b/docs/docs/behaviors/macros.md index 4836c205e41..377ce7fecdb 100644 --- a/docs/docs/behaviors/macros.md +++ b/docs/docs/behaviors/macros.md @@ -147,6 +147,8 @@ Macros use an internal queue to invoke each behavior in the bindings list when t To prevent issues with longer macros, you can change the size of this queue via the `CONFIG_ZMK_BEHAVIORS_QUEUE_SIZE` setting in your configuration, [typically through your `.conf` file](../config/index.md). For example, `CONFIG_ZMK_BEHAVIORS_QUEUE_SIZE=512` would allow your macro to type about 256 characters. +Another limit worth noting is that the maximum number of bindings you can pass to a `bindings` field in the [Devicetree](../config/index.md#devicetree-files) is 256, which also constrains how many behaviors can be invoked by a macro. + ## Parameterized Macros Macros can also be "parameterized", allowing them to be bound in your keymap with unique values passed into them, e.g.: From 4e18b879bdeab047e901856cf6a0cbf3a4855adc Mon Sep 17 00:00:00 2001 From: Cem Aksoylar Date: Sat, 2 Sep 2023 15:26:00 -0700 Subject: [PATCH 60/76] feat(docs): Document persisted settings and debouncing --- docs/docs/behaviors/backlight.md | 6 ++++++ docs/docs/behaviors/bluetooth.md | 5 +++++ docs/docs/behaviors/outputs.md | 5 +++++ docs/docs/behaviors/power.md | 5 +++++ docs/docs/behaviors/underglow.md | 6 ++++++ 5 files changed, 27 insertions(+) diff --git a/docs/docs/behaviors/backlight.md b/docs/docs/behaviors/backlight.md index cb9a85a830e..8c613fe6bd1 100644 --- a/docs/docs/behaviors/backlight.md +++ b/docs/docs/behaviors/backlight.md @@ -36,6 +36,12 @@ Here is a table describing the action for each define: - Parameter #1: The backlight action define, e.g. `BL_TOG` or `BL_INC` - Parameter #2: Only applies to `BL_SET`and is the brightness value +:::note Backlight settings persistence +The backlight settings that are changed via the `&bl` behavior will be saved to flash storage and hence persist across restarts and firmware flashes. +They will also override the start values set by [`CONFIG_ZMK_BACKLIGHT_*_START` settings](../config/backlight.md#kconfig). +However the settings will only be saved after [`CONFIG_ZMK_SETTINGS_SAVE_DEBOUNCE`](../config/system.md#general) milliseconds in order to reduce potential wear on the flash memory. +::: + ### Examples 1. Toggle backlight on/off diff --git a/docs/docs/behaviors/bluetooth.md b/docs/docs/behaviors/bluetooth.md index 7c77c4ad2b7..89496948d50 100644 --- a/docs/docs/behaviors/bluetooth.md +++ b/docs/docs/behaviors/bluetooth.md @@ -35,6 +35,11 @@ Here is a table describing the command for each define: | `BT_PRV` | Switch to the previous profile, cycling through to the last one when the beginning is reached. | | `BT_SEL` | Select the 0-indexed profile by number. Please note: this definition must include a number as an argument in the keymap to work correctly. eg. `BT_SEL 0` | +:::note Selected profile persistence +The profile that is selected by the `BT_SEL`/`BT_PRV`/`BT_NXT` actions will be saved to flash storage and hence persist across restarts and firmware flashes. +However it will only be saved after [`CONFIG_ZMK_SETTINGS_SAVE_DEBOUNCE`](../config/system.md#general) milliseconds in order to reduce potential wear on the flash memory. +::: + ## Bluetooth Behavior The bluetooth behavior completes an bluetooth action given on press. diff --git a/docs/docs/behaviors/outputs.md b/docs/docs/behaviors/outputs.md index 198d9acc617..dad52be2ccb 100644 --- a/docs/docs/behaviors/outputs.md +++ b/docs/docs/behaviors/outputs.md @@ -44,6 +44,11 @@ The output selection behavior changes the preferred output on press. - Reference: `&out` - Parameter #1: Command, e.g. `OUT_BLE` +:::note External power state persistence +The endpoint that is selected by the `&out` behavior will be saved to flash storage and hence persist across restarts and firmware flashes. +However it will only be saved after [`CONFIG_ZMK_SETTINGS_SAVE_DEBOUNCE`](../config/system.md#general) milliseconds in order to reduce potential wear on the flash memory. +::: + ### Examples 1. Behavior binding to prefer sending keyboard output to USB diff --git a/docs/docs/behaviors/power.md b/docs/docs/behaviors/power.md index 805806095ac..11f920845a3 100644 --- a/docs/docs/behaviors/power.md +++ b/docs/docs/behaviors/power.md @@ -43,6 +43,11 @@ Here is a table describing the command for each define: - Reference: `&ext_power` - Parameter#1: Command, e.g `EP_ON` +:::note External power state persistence +The on/off state that is set by the `&ext_power` behavior will be saved to flash storage and hence persist across restarts and firmware flashes. +However it will only be saved after [`CONFIG_ZMK_SETTINGS_SAVE_DEBOUNCE`](../config/system.md#general) milliseconds in order to reduce potential wear on the flash memory. +::: + ### Example: 1. Behavior binding to enable the external power diff --git a/docs/docs/behaviors/underglow.md b/docs/docs/behaviors/underglow.md index 52429e69987..29f34c2ab0b 100644 --- a/docs/docs/behaviors/underglow.md +++ b/docs/docs/behaviors/underglow.md @@ -55,6 +55,12 @@ Value Limits: ::: +:::note RGB settings persistence +The RGB settings that are changed via the `&rgb_ug` behavior will be saved to flash storage and hence persist across restarts and firmware flashes. +They will also override the start values set by [`CONFIG_ZMK_RGB_*_START` settings](../config/underglow.md#kconfig). +However the settings will only be saved after [`CONFIG_ZMK_SETTINGS_SAVE_DEBOUNCE`](../config/system.md#general) milliseconds in order to reduce potential wear on the flash memory. +::: + ## Examples 1. Toggle underglow on/off From 544612c8c0929ff3089bcdb86f9ea8a2f77081eb Mon Sep 17 00:00:00 2001 From: Xudong Zheng <7pkvm5aw@slicealias.com> Date: Fri, 1 Sep 2023 23:32:17 -0400 Subject: [PATCH 61/76] fix(split): reserve peripheral slot before stopping scanning In the event that the peripheral MAC address does not match, this allows scanning to continue. --- app/src/split/bluetooth/central.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/app/src/split/bluetooth/central.c b/app/src/split/bluetooth/central.c index b70d79e3a3a..ccf1cc28ced 100644 --- a/app/src/split/bluetooth/central.c +++ b/app/src/split/bluetooth/central.c @@ -433,20 +433,22 @@ static int stop_scanning() { static bool split_central_eir_found(const bt_addr_le_t *addr) { LOG_DBG("Found the split service"); - // Stop scanning so we can connect to the peripheral device. - int err = stop_scanning(); - if (err < 0) { - return false; - } - + // Reserve peripheral slot. Once the central has bonded to its peripherals, + // the peripheral MAC addresses will be validated internally and the slot + // reservation will fail if there is a mismatch. int slot_idx = reserve_peripheral_slot(addr); if (slot_idx < 0) { - LOG_ERR("Failed to reserve peripheral slot (err %d)", slot_idx); + LOG_INF("Unable to reserve peripheral slot (err %d)", slot_idx); return false; } - struct peripheral_slot *slot = &peripherals[slot_idx]; + // Stop scanning so we can connect to the peripheral device. + int err = stop_scanning(); + if (err < 0) { + return false; + } + LOG_DBG("Initiating new connnection"); struct bt_le_conn_param *param = BT_LE_CONN_PARAM(CONFIG_ZMK_SPLIT_BLE_PREF_INT, CONFIG_ZMK_SPLIT_BLE_PREF_INT, From ac0691471f1adb8336fb7eb5d01f18c988c5bad8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=83=95=E3=82=A3=E3=83=AB=E3=82=BF=E3=83=BC=E3=83=9A?= =?UTF-8?q?=E3=83=BC=E3=83=91=E3=83=BC?= <76888457+filterpaper@users.noreply.github.com> Date: Thu, 3 Aug 2023 10:26:34 +0800 Subject: [PATCH 62/76] feat(shields): Add Bluetooth bindings to kyria keymaps Bluetooth bindings are useful for handling pairings with hosts. This change adds the header and a few default commands as template for new users to work with. --- app/boards/shields/kyria/kyria.keymap | 20 +++++++++++++++-- app/boards/shields/kyria/kyria_rev2.keymap | 20 +++++++++++++++-- app/boards/shields/kyria/kyria_rev3.keymap | 26 +++++++++++++++++----- 3 files changed, 57 insertions(+), 9 deletions(-) diff --git a/app/boards/shields/kyria/kyria.keymap b/app/boards/shields/kyria/kyria.keymap index 9a2163db549..a11c13259e1 100644 --- a/app/boards/shields/kyria/kyria.keymap +++ b/app/boards/shields/kyria/kyria.keymap @@ -5,6 +5,7 @@ */ #include +#include #include / { @@ -15,15 +16,30 @@ // --------------------------------------------------------------------------------------------------------------------------------- // | ESC | Q | W | E | R | T | | Y | U | I | O | P | \ | // | TAB | A | S | D | F | G | | H | J | K | L | ; | ' | -// | SHIFT | Z | X | C | V | B | L SHIFT | L SHIFT | | L SHIFT | L SHIFT | N | M | , | . | / | CTRL | +// | SHIFT | Z | X | C | V | B | L SHIFT | L SHIFT | | LAYER 1 | L SHIFT | N | M | , | . | / | CTRL | // | GUI | DEL | RET | SPACE | ESC | | RET | SPACE | TAB | BSPC | R-ALT | bindings = < &kp ESC &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &kp BSLH &kp TAB &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SEMI &kp SQT - &kp LSHFT &kp Z &kp X &kp C &kp V &kp B &kp LSHFT &kp LSHFT &kp LSHFT &kp LSHFT &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp RCTRL + &kp LSHFT &kp Z &kp X &kp C &kp V &kp B &kp LSHFT &kp LSHFT &mo 1 &kp LSHFT &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp RCTRL &kp LGUI &kp DEL &kp RET &kp SPACE &kp ESC &kp RET &kp SPACE &kp TAB &kp BSPC &kp RALT >; + sensor-bindings = <&inc_dec_kp C_VOL_UP C_VOL_DN &inc_dec_kp PG_UP PG_DN>; + }; + function_layer { +// --------------------------------------------------------------------------------------------------------------------------------- +// | | |BT_CLR|BTSEL0|BTSEL1|BTSEL2| | | | | | | | +// | | | |BTSEL3|BTSEL4| | | | | | | | | +// | | | | | | | | | | | | | | | | | | | +// | | | | | | | | | | | | | + bindings = < + &trans &trans &bt BT_CLR &bt BT_SEL 0 &bt BT_SEL 1 &bt BT_SEL 2 &trans &trans &trans &trans &trans &trans + &trans &trans &trans &bt BT_SEL 3 &bt BT_SEL 4 &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans + >; + sensor-bindings = <&inc_dec_kp C_VOL_UP C_VOL_DN &inc_dec_kp PG_UP PG_DN>; }; }; diff --git a/app/boards/shields/kyria/kyria_rev2.keymap b/app/boards/shields/kyria/kyria_rev2.keymap index 9a2163db549..a11c13259e1 100644 --- a/app/boards/shields/kyria/kyria_rev2.keymap +++ b/app/boards/shields/kyria/kyria_rev2.keymap @@ -5,6 +5,7 @@ */ #include +#include #include / { @@ -15,15 +16,30 @@ // --------------------------------------------------------------------------------------------------------------------------------- // | ESC | Q | W | E | R | T | | Y | U | I | O | P | \ | // | TAB | A | S | D | F | G | | H | J | K | L | ; | ' | -// | SHIFT | Z | X | C | V | B | L SHIFT | L SHIFT | | L SHIFT | L SHIFT | N | M | , | . | / | CTRL | +// | SHIFT | Z | X | C | V | B | L SHIFT | L SHIFT | | LAYER 1 | L SHIFT | N | M | , | . | / | CTRL | // | GUI | DEL | RET | SPACE | ESC | | RET | SPACE | TAB | BSPC | R-ALT | bindings = < &kp ESC &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &kp BSLH &kp TAB &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SEMI &kp SQT - &kp LSHFT &kp Z &kp X &kp C &kp V &kp B &kp LSHFT &kp LSHFT &kp LSHFT &kp LSHFT &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp RCTRL + &kp LSHFT &kp Z &kp X &kp C &kp V &kp B &kp LSHFT &kp LSHFT &mo 1 &kp LSHFT &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp RCTRL &kp LGUI &kp DEL &kp RET &kp SPACE &kp ESC &kp RET &kp SPACE &kp TAB &kp BSPC &kp RALT >; + sensor-bindings = <&inc_dec_kp C_VOL_UP C_VOL_DN &inc_dec_kp PG_UP PG_DN>; + }; + function_layer { +// --------------------------------------------------------------------------------------------------------------------------------- +// | | |BT_CLR|BTSEL0|BTSEL1|BTSEL2| | | | | | | | +// | | | |BTSEL3|BTSEL4| | | | | | | | | +// | | | | | | | | | | | | | | | | | | | +// | | | | | | | | | | | | | + bindings = < + &trans &trans &bt BT_CLR &bt BT_SEL 0 &bt BT_SEL 1 &bt BT_SEL 2 &trans &trans &trans &trans &trans &trans + &trans &trans &trans &bt BT_SEL 3 &bt BT_SEL 4 &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans + >; + sensor-bindings = <&inc_dec_kp C_VOL_UP C_VOL_DN &inc_dec_kp PG_UP PG_DN>; }; }; diff --git a/app/boards/shields/kyria/kyria_rev3.keymap b/app/boards/shields/kyria/kyria_rev3.keymap index d74757cad7d..ac2fc044e73 100644 --- a/app/boards/shields/kyria/kyria_rev3.keymap +++ b/app/boards/shields/kyria/kyria_rev3.keymap @@ -5,6 +5,7 @@ */ #include +#include #include /* Uncomment this block if using RGB @@ -23,13 +24,28 @@ // --------------------------------------------------------------------------------------------------------------------------------- // | ESC | Q | W | E | R | T | | Y | U | I | O | P | \ | // | TAB | A | S | D | F | G | | H | J | K | L | ; | ' | - // | SHIFT | Z | X | C | V | B | L SHIFT | L SHIFT | | L SHIFT | L SHIFT | N | M | , | . | / | CTRL | + // | SHIFT | Z | X | C | V | B | L SHIFT | L SHIFT | | LAYER 1 | L SHIFT | N | M | , | . | / | CTRL | // | GUI | DEL | RET | SPACE | ESC | | RET | SPACE | TAB | BSPC | R-ALT | bindings = < - &kp ESC &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &kp BSLH - &kp TAB &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SEMI &kp SQT - &kp LSHFT &kp Z &kp X &kp C &kp V &kp B &kp LSHFT &kp LSHFT &kp LSHFT &kp LSHFT &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp RCTRL - &kp LGUI &kp DEL &kp RET &kp SPACE &kp ESC &kp RET &kp SPACE &kp TAB &kp BSPC &kp RALT + &kp ESC &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &kp BSLH + &kp TAB &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SEMI &kp SQT + &kp LSHFT &kp Z &kp X &kp C &kp V &kp B &kp LSHFT &kp LSHFT &mo 1 &kp LSHFT &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp RCTRL + &kp LGUI &kp DEL &kp RET &kp SPACE &kp ESC &kp RET &kp SPACE &kp TAB &kp BSPC &kp RALT + >; + + sensor-bindings = <&inc_dec_kp C_VOL_UP C_VOL_DN &inc_dec_kp PG_UP PG_DN>; + }; + function_layer { + // --------------------------------------------------------------------------------------------------------------------------------- + // | | |BT_CLR|BTSEL0|BTSEL1|BTSEL2| | | | | | | | + // | | | |BTSEL3|BTSEL4| | | | | | | | | + // | | | | | | | | | | | | | | | | | | | + // | | | | | | | | | | | | | + bindings = < + &trans &trans &bt BT_CLR &bt BT_SEL 0 &bt BT_SEL 1 &bt BT_SEL 2 &trans &trans &trans &trans &trans &trans + &trans &trans &trans &bt BT_SEL 3 &bt BT_SEL 4 &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans >; sensor-bindings = <&inc_dec_kp C_VOL_UP C_VOL_DN &inc_dec_kp PG_UP PG_DN>; From 3de23938d687badb346cd97f2e4003bc4357508c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 19 Jul 2023 08:51:44 +0000 Subject: [PATCH 63/76] chore(deps): bump word-wrap from 1.2.3 to 1.2.4 in /docs Bumps [word-wrap](https://github.com/jonschlinkert/word-wrap) from 1.2.3 to 1.2.4. - [Release notes](https://github.com/jonschlinkert/word-wrap/releases) - [Commits](https://github.com/jonschlinkert/word-wrap/compare/1.2.3...1.2.4) --- updated-dependencies: - dependency-name: word-wrap dependency-type: indirect ... Signed-off-by: dependabot[bot] --- docs/package-lock.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/package-lock.json b/docs/package-lock.json index b990f53c3dc..3aec8dd5014 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -15859,9 +15859,9 @@ "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==" }, "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz", + "integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==", "devOptional": true, "engines": { "node": ">=0.10.0" @@ -27353,9 +27353,9 @@ "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==" }, "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz", + "integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==", "devOptional": true }, "wrap-ansi": { From 8984e12f0d0442b15e6fd18dfd48666bc4cbceb2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 30 Aug 2023 05:10:14 +0000 Subject: [PATCH 64/76] chore(deps-dev): bump json-schema-to-typescript in /docs Bumps [json-schema-to-typescript](https://github.com/bcherny/json-schema-to-typescript) from 12.0.0 to 13.1.1. - [Changelog](https://github.com/bcherny/json-schema-to-typescript/blob/master/CHANGELOG.md) - [Commits](https://github.com/bcherny/json-schema-to-typescript/commits) --- updated-dependencies: - dependency-name: json-schema-to-typescript dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- docs/package-lock.json | 14 +++++++------- docs/package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/package-lock.json b/docs/package-lock.json index 3aec8dd5014..38eae2b7dc8 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -35,7 +35,7 @@ "eslint-config-prettier": "^8.8.0", "eslint-plugin-mdx": "^2.0.5", "eslint-plugin-react": "^7.32.2", - "json-schema-to-typescript": "^12.0.0", + "json-schema-to-typescript": "^13.1.1", "mustache": "^4.2.0", "null-loader": "^4.0.0", "prebuild-webpack-plugin": "^1.1.1", @@ -9163,9 +9163,9 @@ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, "node_modules/json-schema-to-typescript": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/json-schema-to-typescript/-/json-schema-to-typescript-12.0.0.tgz", - "integrity": "sha512-Uk/BDIAo8vqepPBhM86UhNMHgCv7JulicNj/BgnQPHE1fGCoej0UTtcEYzXU/uk6lSvbZCf7pccW+dnNMrr5rg==", + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/json-schema-to-typescript/-/json-schema-to-typescript-13.1.1.tgz", + "integrity": "sha512-F3CYhtA7F3yPbb8vF7sFchk/2dnr1/yTKf8RcvoNpjnh67ZS/ZMH1ElLt5KHAtf2/bymiejLQQszszPWEeTdSw==", "dev": true, "dependencies": { "@bcherny/json-schema-ref-parser": "10.0.5-fork", @@ -22663,9 +22663,9 @@ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, "json-schema-to-typescript": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/json-schema-to-typescript/-/json-schema-to-typescript-12.0.0.tgz", - "integrity": "sha512-Uk/BDIAo8vqepPBhM86UhNMHgCv7JulicNj/BgnQPHE1fGCoej0UTtcEYzXU/uk6lSvbZCf7pccW+dnNMrr5rg==", + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/json-schema-to-typescript/-/json-schema-to-typescript-13.1.1.tgz", + "integrity": "sha512-F3CYhtA7F3yPbb8vF7sFchk/2dnr1/yTKf8RcvoNpjnh67ZS/ZMH1ElLt5KHAtf2/bymiejLQQszszPWEeTdSw==", "dev": true, "requires": { "@bcherny/json-schema-ref-parser": "10.0.5-fork", diff --git a/docs/package.json b/docs/package.json index d82e54ec8c9..9b38bef8b67 100644 --- a/docs/package.json +++ b/docs/package.json @@ -54,7 +54,7 @@ "eslint-config-prettier": "^8.8.0", "eslint-plugin-mdx": "^2.0.5", "eslint-plugin-react": "^7.32.2", - "json-schema-to-typescript": "^12.0.0", + "json-schema-to-typescript": "^13.1.1", "mustache": "^4.2.0", "null-loader": "^4.0.0", "prebuild-webpack-plugin": "^1.1.1", From 647945d9f8c80b7de8df8f9dc54bdcf865d531ad Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Mon, 17 Jul 2023 07:20:45 -0700 Subject: [PATCH 65/76] feat(shields): Add splitkb.com Aurora Helix * Add new shield for splitkb.com Aurora Helix, supporting keys, encoder(s), displays, and RGB. --- .../splitkb_aurora_helix/Kconfig.defconfig | 53 ++++++++++ .../splitkb_aurora_helix/Kconfig.shield | 8 ++ .../boards/nice_nano.overlay | 46 +++++++++ .../boards/nice_nano_v2.overlay | 46 +++++++++ .../splitkb_aurora_helix.conf | 9 ++ .../splitkb_aurora_helix.dtsi | 79 +++++++++++++++ .../splitkb_aurora_helix.keymap | 96 +++++++++++++++++++ .../splitkb_aurora_helix.zmk.yml | 15 +++ .../splitkb_aurora_helix_left.overlay | 42 ++++++++ .../splitkb_aurora_helix_right.overlay | 46 +++++++++ 10 files changed, 440 insertions(+) create mode 100644 app/boards/shields/splitkb_aurora_helix/Kconfig.defconfig create mode 100644 app/boards/shields/splitkb_aurora_helix/Kconfig.shield create mode 100644 app/boards/shields/splitkb_aurora_helix/boards/nice_nano.overlay create mode 100644 app/boards/shields/splitkb_aurora_helix/boards/nice_nano_v2.overlay create mode 100644 app/boards/shields/splitkb_aurora_helix/splitkb_aurora_helix.conf create mode 100644 app/boards/shields/splitkb_aurora_helix/splitkb_aurora_helix.dtsi create mode 100644 app/boards/shields/splitkb_aurora_helix/splitkb_aurora_helix.keymap create mode 100644 app/boards/shields/splitkb_aurora_helix/splitkb_aurora_helix.zmk.yml create mode 100644 app/boards/shields/splitkb_aurora_helix/splitkb_aurora_helix_left.overlay create mode 100644 app/boards/shields/splitkb_aurora_helix/splitkb_aurora_helix_right.overlay diff --git a/app/boards/shields/splitkb_aurora_helix/Kconfig.defconfig b/app/boards/shields/splitkb_aurora_helix/Kconfig.defconfig new file mode 100644 index 00000000000..6d7a55691e2 --- /dev/null +++ b/app/boards/shields/splitkb_aurora_helix/Kconfig.defconfig @@ -0,0 +1,53 @@ +# Copyright (c) 2023 The ZMK Contributors +# SPDX-License-Identifier: MIT + +if SHIELD_SPLITKB_AURORA_HELIX_LEFT + +config ZMK_KEYBOARD_NAME + default "Aurora Helix" + +config ZMK_SPLIT_ROLE_CENTRAL + default y + +endif # SHIELD_SPLITKB_AURORA_HELIX_LEFT + +if SHIELD_SPLITKB_AURORA_HELIX_LEFT || SHIELD_SPLITKB_AURORA_HELIX_RIGHT + +config ZMK_SPLIT + default y + +config ZMK_RGB_UNDERGLOW + select WS2812_STRIP + select SPI + +if ZMK_DISPLAY + +config SSD1306 + default y + +config I2C + default y + +config SSD1306_REVERSE_MODE + default y + +endif # ZMK_DISPLAY + +if LVGL + +config LV_Z_VDB_SIZE + default 64 + +config LV_DPI_DEF + default 148 + +config LV_Z_BITS_PER_PIXEL + default 1 + +choice LV_COLOR_DEPTH + default LV_COLOR_DEPTH_1 +endchoice + +endif # LVGL + +endif # SHIELD_SPLITKB_AURORA_HELIX_LEFT || SHIELD_SPLITKB_AURORA_HELIX_RIGHT diff --git a/app/boards/shields/splitkb_aurora_helix/Kconfig.shield b/app/boards/shields/splitkb_aurora_helix/Kconfig.shield new file mode 100644 index 00000000000..c64ef8798e1 --- /dev/null +++ b/app/boards/shields/splitkb_aurora_helix/Kconfig.shield @@ -0,0 +1,8 @@ +# Copyright (c) 2023 The ZMK Contributors +# SPDX-License-Identifier: MIT + +config SHIELD_SPLITKB_AURORA_HELIX_LEFT + def_bool $(shields_list_contains,splitkb_aurora_helix_left) + +config SHIELD_SPLITKB_AURORA_HELIX_RIGHT + def_bool $(shields_list_contains,splitkb_aurora_helix_right) diff --git a/app/boards/shields/splitkb_aurora_helix/boards/nice_nano.overlay b/app/boards/shields/splitkb_aurora_helix/boards/nice_nano.overlay new file mode 100644 index 00000000000..8f1629ced14 --- /dev/null +++ b/app/boards/shields/splitkb_aurora_helix/boards/nice_nano.overlay @@ -0,0 +1,46 @@ +#include + +&pinctrl { + spi3_default: spi3_default { + group1 { + psels = ; + }; + }; + + spi3_sleep: spi3_sleep { + group1 { + psels = ; + low-power-enable; + }; + }; +}; + +&spi3 { + compatible = "nordic,nrf-spim"; + status = "okay"; + + pinctrl-0 = <&spi3_default>; + pinctrl-1 = <&spi3_sleep>; + pinctrl-names = "default", "sleep"; + + led_strip: ws2812@0 { + compatible = "worldsemi,ws2812-spi"; + label = "WS2812"; + + /* SPI */ + reg = <0>; /* ignored, but necessary for SPI bindings */ + spi-max-frequency = <4000000>; + + /* WS2812 */ + chain-length = <6>; /* arbitrary; change at will */ + spi-one-frame = <0x70>; + spi-zero-frame = <0x40>; + color-mapping = ; + }; +}; + +/ { + chosen { + zmk,underglow = &led_strip; + }; +}; diff --git a/app/boards/shields/splitkb_aurora_helix/boards/nice_nano_v2.overlay b/app/boards/shields/splitkb_aurora_helix/boards/nice_nano_v2.overlay new file mode 100644 index 00000000000..8f1629ced14 --- /dev/null +++ b/app/boards/shields/splitkb_aurora_helix/boards/nice_nano_v2.overlay @@ -0,0 +1,46 @@ +#include + +&pinctrl { + spi3_default: spi3_default { + group1 { + psels = ; + }; + }; + + spi3_sleep: spi3_sleep { + group1 { + psels = ; + low-power-enable; + }; + }; +}; + +&spi3 { + compatible = "nordic,nrf-spim"; + status = "okay"; + + pinctrl-0 = <&spi3_default>; + pinctrl-1 = <&spi3_sleep>; + pinctrl-names = "default", "sleep"; + + led_strip: ws2812@0 { + compatible = "worldsemi,ws2812-spi"; + label = "WS2812"; + + /* SPI */ + reg = <0>; /* ignored, but necessary for SPI bindings */ + spi-max-frequency = <4000000>; + + /* WS2812 */ + chain-length = <6>; /* arbitrary; change at will */ + spi-one-frame = <0x70>; + spi-zero-frame = <0x40>; + color-mapping = ; + }; +}; + +/ { + chosen { + zmk,underglow = &led_strip; + }; +}; diff --git a/app/boards/shields/splitkb_aurora_helix/splitkb_aurora_helix.conf b/app/boards/shields/splitkb_aurora_helix/splitkb_aurora_helix.conf new file mode 100644 index 00000000000..af482abcc4b --- /dev/null +++ b/app/boards/shields/splitkb_aurora_helix/splitkb_aurora_helix.conf @@ -0,0 +1,9 @@ +# Uncomment these two line to add support for encoders to your firmware +# CONFIG_EC11=y +# CONFIG_EC11_TRIGGER_GLOBAL_THREAD=y + +# Uncomment the following line to enable the OLED Display +# CONFIG_ZMK_DISPLAY=y + +# Uncomment the following line to enable RGB underglow +# CONFIG_ZMK_RGB_UNDERGLOW=y diff --git a/app/boards/shields/splitkb_aurora_helix/splitkb_aurora_helix.dtsi b/app/boards/shields/splitkb_aurora_helix/splitkb_aurora_helix.dtsi new file mode 100644 index 00000000000..e580e87daba --- /dev/null +++ b/app/boards/shields/splitkb_aurora_helix/splitkb_aurora_helix.dtsi @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2023 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include + +/ { + + chosen { + zephyr,display = &oled; + zmk,matrix_transform = &default_transform; + }; + + default_transform: keymap_transform_0 { + compatible = "zmk,matrix-transform"; + columns = <14>; + rows = <5>; + // | SW1 | SW2 | SW3 | SW4 | SW5 | SW6 | | SW6 | SW5 | SW4 | SW3 | SW2 | SW1 | + // | SW7 | SW8 | SW9 | SW10 | SW11 | SW12 | | SW12 | SW11 | SW10 | SW9 | SW8 | SW7 | + // | SW13 | SW14 | SW15 | SW16 | SW17 | SW18 | | SW18 | SW17 | SW16 | SW15 | SW14 | SW13 | + // | SW19 | SW20 | SW21 | SW22 | SW23 | SW24 | SW25 | | SW25 | SW24 | SW23 | SW22 | SW21 | SW20 | SW19 | + // | SW26 | SW27 | SW28 | SW29 | SW30 | SW31 | SW32 | | SW32 | SW31 | SW30 | SW29 | SW28 | SW27 | SW26 | + map = < + RC(0,0) RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(0,5) RC(0,8) RC(0,9) RC(0,10) RC(0,11) RC(0,12) RC(0,13) + RC(1,0) RC(1,1) RC(1,2) RC(1,3) RC(1,4) RC(1,5) RC(1,8) RC(1,9) RC(1,10) RC(1,11) RC(1,12) RC(1,13) + RC(2,0) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(2,5) RC(2,8) RC(2,9) RC(2,10) RC(2,11) RC(2,12) RC(2,13) + RC(3,0) RC(3,1) RC(3,2) RC(3,3) RC(3,4) RC(3,5) RC(3,6) RC(3,7) RC(3,8) RC(3,9) RC(3,10) RC(3,11) RC(3,12) RC(3,13) + RC(4,0) RC(4,1) RC(4,2) RC(4,3) RC(4,4) RC(4,5) RC(4,6) RC(4,7) RC(4,8) RC(4,9) RC(4,10) RC(4,11) RC(4,12) RC(4,13) + >; + }; + + left_encoder: left_encoder { + compatible = "alps,ec11"; + label = "L_ENCODER"; + steps = <144>; + status = "disabled"; + + a-gpios = <&pro_micro 7 GPIO_PULL_UP>; + b-gpios = <&pro_micro 8 GPIO_PULL_UP>; + }; + + right_encoder: right_encoder { + compatible = "alps,ec11"; + label = "R_ENCODER"; + steps = <144>; + status = "disabled"; + + a-gpios = <&pro_micro 16 GPIO_PULL_UP>; + b-gpios = <&pro_micro 14 GPIO_PULL_UP>; + }; + + sensors { + compatible = "zmk,keymap-sensors"; + sensors = <&left_encoder &right_encoder>; + triggers-per-rotation = <36>; + }; +}; + +&pro_micro_i2c { + status = "okay"; + + oled: ssd1306@3c { + compatible = "solomon,ssd1306fb"; + reg = <0x3c>; + label = "DISPLAY"; + width = <128>; + height = <32>; + segment-offset = <0>; + page-offset = <0>; + display-offset = <0>; + multiplex-ratio = <31>; + segment-remap; + com-invdir; + com-sequential; + prechargep = <0x22>; + }; +}; diff --git a/app/boards/shields/splitkb_aurora_helix/splitkb_aurora_helix.keymap b/app/boards/shields/splitkb_aurora_helix/splitkb_aurora_helix.keymap new file mode 100644 index 00000000000..edec8fec306 --- /dev/null +++ b/app/boards/shields/splitkb_aurora_helix/splitkb_aurora_helix.keymap @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2023 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include +#include +#include +#include +#include +#include + +#define DEFAULT 0 +#define LOWER 1 +#define RAISE 2 +#define ADJUST 3 + +/* Uncomment this block if using RGB +&led_strip { + chain-length = <6>; + // chain-length = <38>; // Uncomment if using both per-key and underglow LEDs + // chain-length = <32>; // Uncomment if using only per-key LEDs. +}; + */ + +/* NOTE: At the time of the creation of this keymap, there are no specified codes for 'eisuu' and 'kana' input in ZMK. +However, 'LANG1' and 'LANG2' are fully-functioning candidates for 'kana' and 'eisuu' input respectively. +As such, those are in use within the default layer at this time.*/ + +/ { + keymap { + compatible = "zmk,keymap"; + + default_layer { + // --------------------------------------------------------------------------------------------------------------------------------- + // | GRAVE | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | DEL | + // | TAB | Q | W | E | R | T | | Y | U | I | O | P | BSPC | + // | CTRL | A | S | D | F | G | | H | J | K | L | ; | ' | + // | SHIFT | Z | X | C | V | B | LBKT | | RBKT | N | M | , | . | / | RET | + // | ADJUST | ESC | ALT | LGUI | EISUU | LOWER | SPACE | | SPACE | RAISE | KANA | LEFT | DOWN | UP | RIGHT | + bindings = < + &kp GRAVE &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 &kp DEL + &kp TAB &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &kp BSPC + &kp LCTRL &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SEMI &kp SQT + &kp LSHFT &kp Z &kp X &kp C &kp V &kp B &kp LBKT &kp RBKT &kp N &kp M &kp COMMA &kp PERIOD &kp SLASH &kp RET + &mo ADJUST &kp ESC &kp LALT &kp LGUI &kp LANG2 &mo LOWER &kp SPACE &kp SPACE &mo RAISE &kp LANG1 &kp LEFT &kp DOWN &kp UP &kp RIGHT + >; + }; + lower_layer { + // --------------------------------------------------------------------------------------------------------------------------------- + // | | | | | | | | | | | | | | + // | ~ | ! | @ | # | $ | % | | ^ | & | * | ( | ) | | + // | | | | | | | | | _ | + | { | } | PIPE | + // | | | | | | | ( | | ) | | | | HOME | END | | + // | | | | | | | | | | | | | | | | + bindings = < + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans + &kp TILDE &kp EXCL &kp AT &kp HASH &kp DLLR &kp PRCNT &kp CARET &kp AMPS &kp ASTRK &kp LPAR &kp RPAR &trans + &trans &trans &trans &trans &trans &trans &trans &kp UNDER &kp PLUS &kp LBRC &kp RBRC &kp PIPE + &trans &trans &trans &trans &trans &trans &kp LPAR &kp RPAR &trans &trans &trans &kp HOME &kp END &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans + >; + }; + raise_layer { + // --------------------------------------------------------------------------------------------------------------------------------- + // | | | | | | | | | | | | | | + // | ` | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | DEL | + // | | F1 | F2 | F3 | F4 | F5 | | F6 | - | = | [ | ] | \ | + // | | F7 | F8 | F9 | F10 | F11 | | | | F12 | | PSCRN | PG_DN | PG_UP | | + // | | | | | | | | | | | | NEXT | VOL- | VOL+ | PLAY | + bindings = < + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans + &kp GRAVE &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 &kp DEL + &trans &kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp MINUS &kp EQUAL &kp LBKT &kp RBKT &kp BSLH + &trans &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &trans &trans &kp F12 &trans &kp PSCRN &kp PG_DN &kp PG_UP &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &kp C_NEXT &kp C_VOL_DN &kp C_VOL_UP &kp C_PP + >; + }; + adjust_layer { + // --------------------------------------------------------------------------------------------------------------------------------- + // | ` | ! | @ | # | $ | % | | ^ | & | * | ( | ) | EP TOG | + // | BT CLR | BT SEL0 | BT SEL1 | BT SEL2 | BGT SEL3 | BT SEL4 | | RGB EFF+ | RGB HUE+ | RGB SAT+ | RGB SPD+ | RGB BRI+ | RGB TOG | + // | BT NXT | OUT TOG | OUT USB | OUT BLE | | | | RGB EFF- | RGB HUE- | RGB SAT- | RGB SPD- | RGB BRI- | | + // | BT PRV | | | | | | { | | } | | | | | | | + // | | | | | | | | | | | | | | | | + bindings = < + &kp GRAVE &kp EXCL &kp AT &kp HASH &kp DLLR &kp PRCNT &kp CARET &kp AMPS &kp ASTRK &kp LPAR &kp RPAR &ext_power EP_TOG + &bt BT_CLR &bt BT_SEL 0 &bt BT_SEL 1 &bt BT_SEL 2 &bt BT_SEL 3 &bt BT_SEL 4 &rgb_ug RGB_EFF &rgb_ug RGB_HUI &rgb_ug RGB_SAI &rgb_ug RGB_SPI &rgb_ug RGB_BRI &rgb_ug RGB_TOG + &bt BT_NXT &out OUT_TOG &out OUT_USB &out OUT_BLE &trans &trans &rgb_ug RGB_EFR &rgb_ug RGB_HUD &rgb_ug RGB_SAD &rgb_ug RGB_SPD &rgb_ug RGB_BRD &trans + &bt BT_PRV &trans &trans &trans &trans &trans &kp LBRC &kp RBRC &trans &trans &trans &trans &trans &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans + >; + }; + }; +}; diff --git a/app/boards/shields/splitkb_aurora_helix/splitkb_aurora_helix.zmk.yml b/app/boards/shields/splitkb_aurora_helix/splitkb_aurora_helix.zmk.yml new file mode 100644 index 00000000000..d83c74ecca8 --- /dev/null +++ b/app/boards/shields/splitkb_aurora_helix/splitkb_aurora_helix.zmk.yml @@ -0,0 +1,15 @@ +file_format: "1" +id: splitkb_aurora_helix +name: splitkb.com Aurora Helix +type: shield +url: https://splitkb.com/products/aurora-helix-pcb-kit +requires: [pro_micro] +exposes: [i2c_oled] +features: + - keys + - display + - encoder + - underglow +siblings: + - splitkb_aurora_helix_left + - splitkb_aurora_helix_right diff --git a/app/boards/shields/splitkb_aurora_helix/splitkb_aurora_helix_left.overlay b/app/boards/shields/splitkb_aurora_helix/splitkb_aurora_helix_left.overlay new file mode 100644 index 00000000000..c9830658b00 --- /dev/null +++ b/app/boards/shields/splitkb_aurora_helix/splitkb_aurora_helix_left.overlay @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2023 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include "splitkb_aurora_helix.dtsi" + +/ { + chosen { + zmk,kscan = &kscan; + }; + + kscan: kscan { + compatible = "zmk,kscan-gpio-matrix"; + + label = "KSCAN"; + diode-direction = "col2row"; + + row-gpios + = <&pro_micro 21 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)> + , <&pro_micro 20 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)> + , <&pro_micro 4 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)> + , <&pro_micro 5 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)> + , <&pro_micro 6 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)> + ; + + col-gpios + = <&pro_micro 19 GPIO_ACTIVE_HIGH> + , <&pro_micro 18 GPIO_ACTIVE_HIGH> + , <&pro_micro 15 GPIO_ACTIVE_HIGH> + , <&pro_micro 14 GPIO_ACTIVE_HIGH> + , <&pro_micro 16 GPIO_ACTIVE_HIGH> + , <&pro_micro 10 GPIO_ACTIVE_HIGH> + , <&pro_micro 9 GPIO_ACTIVE_HIGH> + ; + }; +}; + +&left_encoder { + status = "okay"; +}; diff --git a/app/boards/shields/splitkb_aurora_helix/splitkb_aurora_helix_right.overlay b/app/boards/shields/splitkb_aurora_helix/splitkb_aurora_helix_right.overlay new file mode 100644 index 00000000000..48572de902d --- /dev/null +++ b/app/boards/shields/splitkb_aurora_helix/splitkb_aurora_helix_right.overlay @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2023 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include "splitkb_aurora_helix.dtsi" + +/ { + chosen { + zmk,kscan = &kscan; + }; + + kscan: kscan { + compatible = "zmk,kscan-gpio-matrix"; + + label = "KSCAN"; + diode-direction = "col2row"; + + row-gpios + = <&pro_micro 21 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)> + , <&pro_micro 20 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)> + , <&pro_micro 19 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)> + , <&pro_micro 18 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)> + , <&pro_micro 15 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)> + ; + + col-gpios + = <&pro_micro 10 GPIO_ACTIVE_HIGH> + , <&pro_micro 9 GPIO_ACTIVE_HIGH> + , <&pro_micro 8 GPIO_ACTIVE_HIGH> + , <&pro_micro 7 GPIO_ACTIVE_HIGH> + , <&pro_micro 6 GPIO_ACTIVE_HIGH> + , <&pro_micro 5 GPIO_ACTIVE_HIGH> + , <&pro_micro 4 GPIO_ACTIVE_HIGH> + ; + }; +}; + +&right_encoder { + status = "okay"; +}; + +&default_transform { + col-offset = <7>; +}; From 3936298260699d88f8fb8c839991128ed0edfafa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Sep 2023 05:18:02 +0000 Subject: [PATCH 66/76] chore(deps-dev): bump eslint-plugin-react from 7.32.2 to 7.33.2 in /docs Bumps [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) from 7.32.2 to 7.33.2. - [Release notes](https://github.com/jsx-eslint/eslint-plugin-react/releases) - [Changelog](https://github.com/jsx-eslint/eslint-plugin-react/blob/master/CHANGELOG.md) - [Commits](https://github.com/jsx-eslint/eslint-plugin-react/compare/v7.32.2...v7.33.2) --- updated-dependencies: - dependency-name: eslint-plugin-react dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- docs/package-lock.json | 1004 ++++++++++++++++++++++++++++++++++++---- docs/package.json | 2 +- 2 files changed, 914 insertions(+), 92 deletions(-) diff --git a/docs/package-lock.json b/docs/package-lock.json index 38eae2b7dc8..ded7bf838cb 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -34,7 +34,7 @@ "eslint": "^8.39.0", "eslint-config-prettier": "^8.8.0", "eslint-plugin-mdx": "^2.0.5", - "eslint-plugin-react": "^7.32.2", + "eslint-plugin-react": "^7.33.2", "json-schema-to-typescript": "^13.1.1", "mustache": "^4.2.0", "null-loader": "^4.0.0", @@ -4172,6 +4172,19 @@ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/array-flatten": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", @@ -4235,11 +4248,40 @@ "get-intrinsic": "^1.1.3" } }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.1.tgz", + "integrity": "sha512-09x0ZWFEjj4WD8PDbykUwo3t9arLn8NIzmmYEJFpYekOAQjpkGSyrQhNoRTcwwcFRu+ycWF78QZ63oWTqSjBcw==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "get-intrinsic": "^1.2.1", + "is-array-buffer": "^3.0.2", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/asap": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" }, + "node_modules/asynciterator.prototype": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz", + "integrity": "sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.3" + } + }, "node_modules/at-least-node": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", @@ -4280,6 +4322,18 @@ "postcss": "^8.1.0" } }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/axios": { "version": "0.25.0", "resolved": "https://registry.npmjs.org/axios/-/axios-0.25.0.tgz", @@ -5750,9 +5804,9 @@ } }, "node_modules/define-properties": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", - "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", + "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", "dependencies": { "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" @@ -6100,35 +6154,50 @@ } }, "node_modules/es-abstract": { - "version": "1.20.4", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.4.tgz", - "integrity": "sha512-0UtvRN79eMe2L+UNEF1BwRe364sj/DXhQ/k5FmivgoSdpM90b8Jc0mDzKMGo7QS0BVbOP/bTwBKNnDc9rNzaPA==", + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.1.tgz", + "integrity": "sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw==", "dev": true, "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "arraybuffer.prototype.slice": "^1.0.1", + "available-typed-arrays": "^1.0.5", "call-bind": "^1.0.2", + "es-set-tostringtag": "^2.0.1", "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.1.3", + "get-intrinsic": "^1.2.1", "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", "has": "^1.0.3", "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", "is-callable": "^1.2.7", "is-negative-zero": "^2.0.2", "is-regex": "^1.1.4", "is-shared-array-buffer": "^1.0.2", "is-string": "^1.0.7", + "is-typed-array": "^1.1.10", "is-weakref": "^1.0.2", - "object-inspect": "^1.12.2", + "object-inspect": "^1.12.3", "object-keys": "^1.1.1", "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", + "regexp.prototype.flags": "^1.5.0", + "safe-array-concat": "^1.0.0", "safe-regex-test": "^1.0.0", - "string.prototype.trimend": "^1.0.5", - "string.prototype.trimstart": "^1.0.5", - "unbox-primitive": "^1.0.2" + "string.prototype.trim": "^1.2.7", + "string.prototype.trimend": "^1.0.6", + "string.prototype.trimstart": "^1.0.6", + "typed-array-buffer": "^1.0.0", + "typed-array-byte-length": "^1.0.0", + "typed-array-byte-offset": "^1.0.0", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.10" }, "engines": { "node": ">= 0.4" @@ -6137,11 +6206,47 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es-iterator-helpers": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.14.tgz", + "integrity": "sha512-JgtVnwiuoRuzLvqelrvN3Xu7H9bu2ap/kQ2CrM62iidP8SKuD99rWU3CJy++s7IVL2qb/AjXPGR/E7i9ngd/Cw==", + "dev": true, + "dependencies": { + "asynciterator.prototype": "^1.0.0", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-set-tostringtag": "^2.0.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.2.1", + "globalthis": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.5", + "iterator.prototype": "^1.1.0", + "safe-array-concat": "^1.0.0" + } + }, "node_modules/es-module-lexer": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.2.1.tgz", "integrity": "sha512-9978wrXM50Y4rTMmW5kXIC09ZdXQZqkE4mxhwkd8VbzsGkXGPgV4zWuqQJgCEzYngdo2dYDa0l8xhX4fkSwJSg==" }, + "node_modules/es-set-tostringtag": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", + "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3", + "has": "^1.0.3", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-shim-unscopables": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", @@ -6754,15 +6859,16 @@ } }, "node_modules/eslint-plugin-react": { - "version": "7.32.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.32.2.tgz", - "integrity": "sha512-t2fBMa+XzonrrNkyVirzKlvn5RXzzPwRHtMvLAtVZrt8oxgnTQaYbU6SXTOO1mwQgp1y5+toMSKInnzGr0Knqg==", + "version": "7.33.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz", + "integrity": "sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==", "dev": true, "dependencies": { "array-includes": "^3.1.6", "array.prototype.flatmap": "^1.3.1", "array.prototype.tosorted": "^1.1.1", "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.0.12", "estraverse": "^5.3.0", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", @@ -6772,7 +6878,7 @@ "object.values": "^1.1.6", "prop-types": "^15.8.1", "resolve": "^2.0.0-next.4", - "semver": "^6.3.0", + "semver": "^6.3.1", "string.prototype.matchall": "^4.0.8" }, "engines": { @@ -7454,6 +7560,15 @@ } } }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, "node_modules/fork-ts-checker-webpack-plugin": { "version": "6.5.2", "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.2.tgz", @@ -7651,12 +7766,13 @@ } }, "node_modules/get-intrinsic": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", - "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", + "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", "dependencies": { "function-bind": "^1.1.1", "has": "^1.0.3", + "has-proto": "^1.0.1", "has-symbols": "^1.0.3" }, "funding": { @@ -7831,6 +7947,21 @@ "node": ">=4" } }, + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/globalyzer": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/globalyzer/-/globalyzer-0.1.0.tgz", @@ -7862,6 +7993,18 @@ "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==", "dev": true }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/got": { "version": "9.6.0", "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", @@ -7986,6 +8129,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-symbols": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", @@ -8553,12 +8707,12 @@ "integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==" }, "node_modules/internal-slot": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", - "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", + "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", "dev": true, "dependencies": { - "get-intrinsic": "^1.1.0", + "get-intrinsic": "^1.2.0", "has": "^1.0.3", "side-channel": "^1.0.4" }, @@ -8612,11 +8766,40 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/is-array-buffer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" }, + "node_modules/is-async-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", + "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-bigint": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", @@ -8771,6 +8954,18 @@ "node": ">=0.10.0" } }, + "node_modules/is-finalizationregistry": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", + "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -8779,6 +8974,21 @@ "node": ">=8" } }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -8814,6 +9024,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", + "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-negative-zero": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", @@ -8941,6 +9160,15 @@ "node": ">=6" } }, + "node_modules/is-set": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", + "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-shared-array-buffer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", @@ -8994,11 +9222,35 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-typed-array": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", + "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", + "dev": true, + "dependencies": { + "which-typed-array": "^1.1.11" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" }, + "node_modules/is-weakmap": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", + "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-weakref": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", @@ -9011,6 +9263,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-weakset": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", + "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-whitespace-character": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz", @@ -9063,6 +9328,18 @@ "node": ">=0.10.0" } }, + "node_modules/iterator.prototype": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.1.tgz", + "integrity": "sha512-9E+nePc8C9cnQldmNl6bgpTY6zI4OPRZd97fhJ/iVZ1GifIUDVV5F6x1nEDqpe8KaMEZGT4xgrwKQDxXnjOIZQ==", + "dev": true, + "dependencies": { + "define-properties": "^1.2.0", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "reflect.getprototypeof": "^1.0.3" + } + }, "node_modules/jest-util": { "version": "29.2.1", "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.2.1.tgz", @@ -11088,9 +11365,9 @@ } }, "node_modules/object-inspect": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", - "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -12794,6 +13071,26 @@ "node": ">=6.0.0" } }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz", + "integrity": "sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "globalthis": "^1.0.3", + "which-builtin-type": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", @@ -12824,14 +13121,14 @@ } }, "node_modules/regexp.prototype.flags": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", - "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", + "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "functions-have-names": "^1.2.2" + "define-properties": "^1.2.0", + "functions-have-names": "^1.2.3" }, "engines": { "node": ">= 0.4" @@ -13424,6 +13721,30 @@ "node": ">=6" } }, + "node_modules/safe-array-concat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.0.tgz", + "integrity": "sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-array-concat/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -14063,29 +14384,46 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/string.prototype.trim": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", + "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/string.prototype.trimend": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz", - "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", + "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", - "es-abstract": "^1.19.5" + "es-abstract": "^1.20.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/string.prototype.trimstart": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz", - "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", + "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", - "es-abstract": "^1.19.5" + "es-abstract": "^1.20.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -14619,18 +14957,83 @@ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "engines": { - "node": ">= 0.6" + "node": ">= 0.6" + } + }, + "node_modules/type-is/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", + "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", + "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", + "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/type-is/node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "node_modules/typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "dev": true, "dependencies": { - "mime-db": "1.52.0" + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" }, - "engines": { - "node": ">= 0.6" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/typedarray-to-buffer": { @@ -15839,6 +16242,72 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/which-builtin-type": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", + "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", + "dev": true, + "dependencies": { + "function.prototype.name": "^1.1.5", + "has-tostringtag": "^1.0.0", + "is-async-function": "^2.0.0", + "is-date-object": "^1.0.5", + "is-finalizationregistry": "^1.0.2", + "is-generator-function": "^1.0.10", + "is-regex": "^1.1.4", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/which-collection": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", + "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", + "dev": true, + "dependencies": { + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-weakmap": "^2.0.1", + "is-weakset": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", + "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/widest-line": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", @@ -19070,6 +19539,16 @@ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, + "array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + } + }, "array-flatten": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", @@ -19118,11 +19597,34 @@ "get-intrinsic": "^1.1.3" } }, + "arraybuffer.prototype.slice": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.1.tgz", + "integrity": "sha512-09x0ZWFEjj4WD8PDbykUwo3t9arLn8NIzmmYEJFpYekOAQjpkGSyrQhNoRTcwwcFRu+ycWF78QZ63oWTqSjBcw==", + "dev": true, + "requires": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "get-intrinsic": "^1.2.1", + "is-array-buffer": "^3.0.2", + "is-shared-array-buffer": "^1.0.2" + } + }, "asap": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" }, + "asynciterator.prototype": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz", + "integrity": "sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==", + "dev": true, + "requires": { + "has-symbols": "^1.0.3" + } + }, "at-least-node": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", @@ -19141,6 +19643,12 @@ "postcss-value-parser": "^4.2.0" } }, + "available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "dev": true + }, "axios": { "version": "0.25.0", "resolved": "https://registry.npmjs.org/axios/-/axios-0.25.0.tgz", @@ -20186,9 +20694,9 @@ "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==" }, "define-properties": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", - "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", + "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", "requires": { "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" @@ -20448,35 +20956,72 @@ } }, "es-abstract": { - "version": "1.20.4", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.4.tgz", - "integrity": "sha512-0UtvRN79eMe2L+UNEF1BwRe364sj/DXhQ/k5FmivgoSdpM90b8Jc0mDzKMGo7QS0BVbOP/bTwBKNnDc9rNzaPA==", + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.1.tgz", + "integrity": "sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw==", "dev": true, "requires": { + "array-buffer-byte-length": "^1.0.0", + "arraybuffer.prototype.slice": "^1.0.1", + "available-typed-arrays": "^1.0.5", "call-bind": "^1.0.2", + "es-set-tostringtag": "^2.0.1", "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.1.3", + "get-intrinsic": "^1.2.1", "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", "has": "^1.0.3", "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", "is-callable": "^1.2.7", "is-negative-zero": "^2.0.2", "is-regex": "^1.1.4", "is-shared-array-buffer": "^1.0.2", "is-string": "^1.0.7", + "is-typed-array": "^1.1.10", "is-weakref": "^1.0.2", - "object-inspect": "^1.12.2", + "object-inspect": "^1.12.3", "object-keys": "^1.1.1", "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", + "regexp.prototype.flags": "^1.5.0", + "safe-array-concat": "^1.0.0", "safe-regex-test": "^1.0.0", - "string.prototype.trimend": "^1.0.5", - "string.prototype.trimstart": "^1.0.5", - "unbox-primitive": "^1.0.2" + "string.prototype.trim": "^1.2.7", + "string.prototype.trimend": "^1.0.6", + "string.prototype.trimstart": "^1.0.6", + "typed-array-buffer": "^1.0.0", + "typed-array-byte-length": "^1.0.0", + "typed-array-byte-offset": "^1.0.0", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.10" + } + }, + "es-iterator-helpers": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.14.tgz", + "integrity": "sha512-JgtVnwiuoRuzLvqelrvN3Xu7H9bu2ap/kQ2CrM62iidP8SKuD99rWU3CJy++s7IVL2qb/AjXPGR/E7i9ngd/Cw==", + "dev": true, + "requires": { + "asynciterator.prototype": "^1.0.0", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-set-tostringtag": "^2.0.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.2.1", + "globalthis": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.5", + "iterator.prototype": "^1.1.0", + "safe-array-concat": "^1.0.0" } }, "es-module-lexer": { @@ -20484,6 +21029,17 @@ "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.2.1.tgz", "integrity": "sha512-9978wrXM50Y4rTMmW5kXIC09ZdXQZqkE4mxhwkd8VbzsGkXGPgV4zWuqQJgCEzYngdo2dYDa0l8xhX4fkSwJSg==" }, + "es-set-tostringtag": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", + "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "dev": true, + "requires": { + "get-intrinsic": "^1.1.3", + "has": "^1.0.3", + "has-tostringtag": "^1.0.0" + } + }, "es-shim-unscopables": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", @@ -20956,15 +21512,16 @@ } }, "eslint-plugin-react": { - "version": "7.32.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.32.2.tgz", - "integrity": "sha512-t2fBMa+XzonrrNkyVirzKlvn5RXzzPwRHtMvLAtVZrt8oxgnTQaYbU6SXTOO1mwQgp1y5+toMSKInnzGr0Knqg==", + "version": "7.33.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz", + "integrity": "sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==", "dev": true, "requires": { "array-includes": "^3.1.6", "array.prototype.flatmap": "^1.3.1", "array.prototype.tosorted": "^1.1.1", "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.0.12", "estraverse": "^5.3.0", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", @@ -20974,7 +21531,7 @@ "object.values": "^1.1.6", "prop-types": "^15.8.1", "resolve": "^2.0.0-next.4", - "semver": "^6.3.0", + "semver": "^6.3.1", "string.prototype.matchall": "^4.0.8" }, "dependencies": { @@ -21457,6 +22014,15 @@ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==" }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "requires": { + "is-callable": "^1.1.3" + } + }, "fork-ts-checker-webpack-plugin": { "version": "6.5.2", "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.2.tgz", @@ -21587,12 +22153,13 @@ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==" }, "get-intrinsic": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", - "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", + "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", "requires": { "function-bind": "^1.1.1", "has": "^1.0.3", + "has-proto": "^1.0.1", "has-symbols": "^1.0.3" } }, @@ -21713,6 +22280,15 @@ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" }, + "globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3" + } + }, "globalyzer": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/globalyzer/-/globalyzer-0.1.0.tgz", @@ -21738,6 +22314,15 @@ "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==", "dev": true }, + "gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "requires": { + "get-intrinsic": "^1.1.3" + } + }, "got": { "version": "9.6.0", "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", @@ -21837,6 +22422,11 @@ "get-intrinsic": "^1.1.1" } }, + "has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==" + }, "has-symbols": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", @@ -22255,12 +22845,12 @@ "integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==" }, "internal-slot": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", - "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", + "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", "dev": true, "requires": { - "get-intrinsic": "^1.1.0", + "get-intrinsic": "^1.2.0", "has": "^1.0.3", "side-channel": "^1.0.4" } @@ -22297,11 +22887,31 @@ "is-decimal": "^1.0.0" } }, + "is-array-buffer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" + } + }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" }, + "is-async-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", + "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, "is-bigint": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", @@ -22392,11 +23002,29 @@ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==" }, + "is-finalizationregistry": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", + "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2" + } + }, "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" }, + "is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, "is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -22419,6 +23047,12 @@ "is-path-inside": "^3.0.2" } }, + "is-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", + "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", + "dev": true + }, "is-negative-zero": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", @@ -22498,6 +23132,12 @@ "resolved": "https://registry.npmjs.org/is-root/-/is-root-2.1.0.tgz", "integrity": "sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg==" }, + "is-set": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", + "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", + "dev": true + }, "is-shared-array-buffer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", @@ -22530,11 +23170,26 @@ "has-symbols": "^1.0.2" } }, + "is-typed-array": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", + "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", + "dev": true, + "requires": { + "which-typed-array": "^1.1.11" + } + }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" }, + "is-weakmap": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", + "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", + "dev": true + }, "is-weakref": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", @@ -22544,6 +23199,16 @@ "call-bind": "^1.0.2" } }, + "is-weakset": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", + "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + } + }, "is-whitespace-character": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz", @@ -22582,6 +23247,18 @@ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==" }, + "iterator.prototype": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.1.tgz", + "integrity": "sha512-9E+nePc8C9cnQldmNl6bgpTY6zI4OPRZd97fhJ/iVZ1GifIUDVV5F6x1nEDqpe8KaMEZGT4xgrwKQDxXnjOIZQ==", + "dev": true, + "requires": { + "define-properties": "^1.2.0", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "reflect.getprototypeof": "^1.0.3" + } + }, "jest-util": { "version": "29.2.1", "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.2.1.tgz", @@ -23966,9 +24643,9 @@ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" }, "object-inspect": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", - "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==" + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==" }, "object-keys": { "version": "1.1.1", @@ -25142,6 +25819,20 @@ "minimatch": "^3.0.5" } }, + "reflect.getprototypeof": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz", + "integrity": "sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "globalthis": "^1.0.3", + "which-builtin-type": "^1.1.3" + } + }, "regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", @@ -25169,14 +25860,14 @@ } }, "regexp.prototype.flags": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", - "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", + "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", "dev": true, "requires": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "functions-have-names": "^1.2.2" + "define-properties": "^1.2.0", + "functions-have-names": "^1.2.3" } }, "regexpu-core": { @@ -25608,6 +26299,26 @@ "mri": "^1.1.0" } }, + "safe-array-concat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.0.tgz", + "integrity": "sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "dependencies": { + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + } + } + }, "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -26111,26 +26822,37 @@ "side-channel": "^1.0.4" } }, + "string.prototype.trim": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", + "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + } + }, "string.prototype.trimend": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz", - "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", + "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", "dev": true, "requires": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", - "es-abstract": "^1.19.5" + "es-abstract": "^1.20.4" } }, "string.prototype.trimstart": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz", - "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", + "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", "dev": true, "requires": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", - "es-abstract": "^1.19.5" + "es-abstract": "^1.20.4" } }, "stringify-entities": { @@ -26520,6 +27242,53 @@ } } }, + "typed-array-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", + "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "is-typed-array": "^1.1.10" + } + }, + "typed-array-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", + "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + } + }, + "typed-array-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", + "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "dev": true, + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + } + }, + "typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + } + }, "typedarray-to-buffer": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", @@ -27339,6 +28108,59 @@ "is-symbol": "^1.0.3" } }, + "which-builtin-type": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", + "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", + "dev": true, + "requires": { + "function.prototype.name": "^1.1.5", + "has-tostringtag": "^1.0.0", + "is-async-function": "^2.0.0", + "is-date-object": "^1.0.5", + "is-finalizationregistry": "^1.0.2", + "is-generator-function": "^1.0.10", + "is-regex": "^1.1.4", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.9" + }, + "dependencies": { + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + } + } + }, + "which-collection": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", + "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", + "dev": true, + "requires": { + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-weakmap": "^2.0.1", + "is-weakset": "^2.0.1" + } + }, + "which-typed-array": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", + "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", + "dev": true, + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + } + }, "widest-line": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", diff --git a/docs/package.json b/docs/package.json index 9b38bef8b67..a3c3481d672 100644 --- a/docs/package.json +++ b/docs/package.json @@ -53,7 +53,7 @@ "eslint": "^8.39.0", "eslint-config-prettier": "^8.8.0", "eslint-plugin-mdx": "^2.0.5", - "eslint-plugin-react": "^7.32.2", + "eslint-plugin-react": "^7.33.2", "json-schema-to-typescript": "^13.1.1", "mustache": "^4.2.0", "null-loader": "^4.0.0", From 718500543b6d087ce8aac00caac173030b75be16 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Sat, 2 Sep 2023 01:45:12 -0700 Subject: [PATCH 67/76] feat(split): Use directed advertising. * Split centrals to scan with their identity so they receive direct advertising packets. * Split peripherals to use direct advertising if they have an existing bond to a split central. --- app/src/split/bluetooth/Kconfig | 1 + app/src/split/bluetooth/central.c | 4 ++- app/src/split/bluetooth/peripheral.c | 44 ++++++++++++++++++++++++++-- 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/app/src/split/bluetooth/Kconfig b/app/src/split/bluetooth/Kconfig index 0610b667a26..5919010ba31 100644 --- a/app/src/split/bluetooth/Kconfig +++ b/app/src/split/bluetooth/Kconfig @@ -14,6 +14,7 @@ config ZMK_SPLIT_ROLE_CENTRAL select BT_CENTRAL select BT_GATT_CLIENT select BT_GATT_AUTO_DISCOVER_CCC + select BT_SCAN_WITH_IDENTITY if ZMK_SPLIT_ROLE_CENTRAL diff --git a/app/src/split/bluetooth/central.c b/app/src/split/bluetooth/central.c index ccf1cc28ced..860e89a5f3e 100644 --- a/app/src/split/bluetooth/central.c +++ b/app/src/split/bluetooth/central.c @@ -511,8 +511,10 @@ static void split_central_device_found(const bt_addr_le_t *addr, int8_t rssi, ui LOG_DBG("[DEVICE]: %s, AD evt type %u, AD data len %u, RSSI %i", dev, type, ad->len, rssi); /* We're only interested in connectable events */ - if (type == BT_GAP_ADV_TYPE_ADV_IND || type == BT_GAP_ADV_TYPE_ADV_DIRECT_IND) { + if (type == BT_GAP_ADV_TYPE_ADV_IND) { bt_data_parse(ad, split_central_eir_parse, (void *)addr); + } else if (type == BT_GAP_ADV_TYPE_ADV_DIRECT_IND) { + split_central_eir_found(addr); } } diff --git a/app/src/split/bluetooth/peripheral.c b/app/src/split/bluetooth/peripheral.c index e053db8a61a..1d649f71221 100644 --- a/app/src/split/bluetooth/peripheral.c +++ b/app/src/split/bluetooth/peripheral.c @@ -43,15 +43,49 @@ static const struct bt_data zmk_ble_ad[] = { static bool is_connected = false; -static int start_advertising() { - return bt_le_adv_start(BT_LE_ADV_CONN, zmk_ble_ad, ARRAY_SIZE(zmk_ble_ad), NULL, 0); +static void each_bond(const struct bt_bond_info *info, void *user_data) { + bt_addr_le_t *addr = (bt_addr_le_t *)user_data; + + if (bt_addr_le_cmp(&info->addr, BT_ADDR_LE_NONE) != 0) { + bt_addr_le_copy(addr, &info->addr); + } +} + +static int start_advertising(bool low_duty) { + bt_addr_le_t central_addr = bt_addr_le_none; + + bt_foreach_bond(BT_ID_DEFAULT, each_bond, ¢ral_addr); + + if (bt_addr_le_cmp(¢ral_addr, BT_ADDR_LE_NONE) != 0) { + struct bt_le_adv_param adv_param = low_duty ? *BT_LE_ADV_CONN_DIR_LOW_DUTY(¢ral_addr) + : *BT_LE_ADV_CONN_DIR(¢ral_addr); + return bt_le_adv_start(&adv_param, NULL, 0, NULL, 0); + } else { + return bt_le_adv_start(BT_LE_ADV_CONN, zmk_ble_ad, ARRAY_SIZE(zmk_ble_ad), NULL, 0); + } }; +static bool low_duty_advertising = false; + +static void advertising_cb(struct k_work *work) { + const int err = start_advertising(low_duty_advertising); + if (err < 0) { + LOG_ERR("Failed to start advertising (%d)", err); + } +} + +K_WORK_DEFINE(advertising_work, advertising_cb); + static void connected(struct bt_conn *conn, uint8_t err) { is_connected = (err == 0); ZMK_EVENT_RAISE(new_zmk_split_peripheral_status_changed( (struct zmk_split_peripheral_status_changed){.connected = is_connected})); + + if (err == BT_HCI_ERR_ADV_TIMEOUT) { + low_duty_advertising = true; + k_work_submit(&advertising_work); + } } static void disconnected(struct bt_conn *conn, uint8_t reason) { @@ -65,6 +99,9 @@ static void disconnected(struct bt_conn *conn, uint8_t reason) { ZMK_EVENT_RAISE(new_zmk_split_peripheral_status_changed( (struct zmk_split_peripheral_status_changed){.connected = is_connected})); + + low_duty_advertising = false; + k_work_submit(&advertising_work); } static void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_security_err err) { @@ -119,7 +156,8 @@ static int zmk_peripheral_ble_init(const struct device *_arg) { #else bt_conn_cb_register(&conn_callbacks); - start_advertising(); + low_duty_advertising = false; + k_work_submit(&advertising_work); #endif return 0; From 693875675fec96b46c687540ef46a17fa4132779 Mon Sep 17 00:00:00 2001 From: Nate Eagleson Date: Mon, 4 Sep 2023 19:59:59 -0400 Subject: [PATCH 68/76] fix(docs): Fix typo in caps-word.md (#1924) --- docs/docs/behaviors/caps-word.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/behaviors/caps-word.md b/docs/docs/behaviors/caps-word.md index e85d7ecae98..e5d862d785b 100644 --- a/docs/docs/behaviors/caps-word.md +++ b/docs/docs/behaviors/caps-word.md @@ -7,7 +7,7 @@ sidebar_label: Caps Word The caps word behavior behaves similar to a caps lock, but will automatically deactivate when any key not in a continue list is pressed, or if the caps word key is pressed again. For smaller keyboards using [mod-taps](/docs/behaviors/mod-tap), this can help avoid repeated alternating holds when typing words in all caps. -The modifiers are applied only to to the alphabetic (`A` to `Z`) keycodes, to avoid automatically appliying them to numeric values, etc. +The modifiers are applied only to to the alphabetic (`A` to `Z`) keycodes, to avoid automatically applying them to numeric values, etc. ### Behavior Binding From 8087fa3b2b8bb0590e7cf5de6d22b03acd9411a4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Sep 2023 05:12:55 +0000 Subject: [PATCH 69/76] chore(deps): bump @fortawesome/fontawesome-svg-core in /docs Bumps [@fortawesome/fontawesome-svg-core](https://github.com/FortAwesome/Font-Awesome) from 6.4.0 to 6.4.2. - [Release notes](https://github.com/FortAwesome/Font-Awesome/releases) - [Changelog](https://github.com/FortAwesome/Font-Awesome/blob/6.x/CHANGELOG.md) - [Commits](https://github.com/FortAwesome/Font-Awesome/compare/6.4.0...6.4.2) --- updated-dependencies: - dependency-name: "@fortawesome/fontawesome-svg-core" dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- docs/package-lock.json | 34 +++++++++++++++++++++++++--------- docs/package.json | 2 +- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/docs/package-lock.json b/docs/package-lock.json index ded7bf838cb..f17adc4bde9 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -10,7 +10,7 @@ "dependencies": { "@docusaurus/core": "^2.4.0", "@docusaurus/preset-classic": "^2.4.0", - "@fortawesome/fontawesome-svg-core": "^6.4.0", + "@fortawesome/fontawesome-svg-core": "^6.4.2", "@fortawesome/free-solid-svg-icons": "^6.4.0", "@fortawesome/react-fontawesome": "^0.2.0", "@mdx-js/react": "^1.6.22", @@ -2704,17 +2704,26 @@ } }, "node_modules/@fortawesome/fontawesome-svg-core": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.4.0.tgz", - "integrity": "sha512-Bertv8xOiVELz5raB2FlXDPKt+m94MQ3JgDfsVbrqNpLU9+UE2E18GKjLKw+d3XbeYPqg1pzyQKGsrzbw+pPaw==", + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.4.2.tgz", + "integrity": "sha512-gjYDSKv3TrM2sLTOKBc5rH9ckje8Wrwgx1CxAPbN5N3Fm4prfi7NsJVWd1jklp7i5uSCVwhZS5qlhMXqLrpAIg==", "hasInstallScript": true, "dependencies": { - "@fortawesome/fontawesome-common-types": "6.4.0" + "@fortawesome/fontawesome-common-types": "6.4.2" }, "engines": { "node": ">=6" } }, + "node_modules/@fortawesome/fontawesome-svg-core/node_modules/@fortawesome/fontawesome-common-types": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.4.2.tgz", + "integrity": "sha512-1DgP7f+XQIJbLFCTX1V2QnxVmpLdKdzzo2k8EmvDOePfchaIGQ9eCHj2up3/jNEbZuBqel5OxiaOJf37TWauRA==", + "hasInstallScript": true, + "engines": { + "node": ">=6" + } + }, "node_modules/@fortawesome/free-solid-svg-icons": { "version": "6.4.0", "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.4.0.tgz", @@ -18363,11 +18372,18 @@ "integrity": "sha512-HNii132xfomg5QVZw0HwXXpN22s7VBHQBv9CeOu9tfJnhsWQNd2lmTNi8CSrnw5B+5YOmzu1UoPAyxaXsJ6RgQ==" }, "@fortawesome/fontawesome-svg-core": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.4.0.tgz", - "integrity": "sha512-Bertv8xOiVELz5raB2FlXDPKt+m94MQ3JgDfsVbrqNpLU9+UE2E18GKjLKw+d3XbeYPqg1pzyQKGsrzbw+pPaw==", + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.4.2.tgz", + "integrity": "sha512-gjYDSKv3TrM2sLTOKBc5rH9ckje8Wrwgx1CxAPbN5N3Fm4prfi7NsJVWd1jklp7i5uSCVwhZS5qlhMXqLrpAIg==", "requires": { - "@fortawesome/fontawesome-common-types": "6.4.0" + "@fortawesome/fontawesome-common-types": "6.4.2" + }, + "dependencies": { + "@fortawesome/fontawesome-common-types": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.4.2.tgz", + "integrity": "sha512-1DgP7f+XQIJbLFCTX1V2QnxVmpLdKdzzo2k8EmvDOePfchaIGQ9eCHj2up3/jNEbZuBqel5OxiaOJf37TWauRA==" + } } }, "@fortawesome/free-solid-svg-icons": { diff --git a/docs/package.json b/docs/package.json index a3c3481d672..aa48af24d3c 100644 --- a/docs/package.json +++ b/docs/package.json @@ -17,7 +17,7 @@ "dependencies": { "@docusaurus/core": "^2.4.0", "@docusaurus/preset-classic": "^2.4.0", - "@fortawesome/fontawesome-svg-core": "^6.4.0", + "@fortawesome/fontawesome-svg-core": "^6.4.2", "@fortawesome/free-solid-svg-icons": "^6.4.0", "@fortawesome/react-fontawesome": "^0.2.0", "@mdx-js/react": "^1.6.22", From f442776fe2bea2a3644d0767a2cf1e975c6d9b38 Mon Sep 17 00:00:00 2001 From: Cem Aksoylar Date: Sat, 10 Jun 2023 17:41:22 -0700 Subject: [PATCH 70/76] feat(docs): Detail logging and note extra useful options --- docs/docs/development/usb-logging.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/docs/docs/development/usb-logging.md b/docs/docs/development/usb-logging.md index 9a2980ae6c8..87cd0e7d853 100644 --- a/docs/docs/development/usb-logging.md +++ b/docs/docs/development/usb-logging.md @@ -20,13 +20,16 @@ It is recommended to only enable logging when needed, and not leaving it on by d ## Kconfig -The `CONFIG_ZMK_USB_LOGGING` KConfig value needs to be set, either by copy and pasting into the `app/prj.conf` file, or by running -`west build -t menuconfig` and manually enabling the setting in that UI at `ZMK -> Advanced -> USB Logging`. +The `CONFIG_ZMK_USB_LOGGING` Kconfig enables USB logging. This can be set at the keyboard level, typically in the `config/.conf` +file if you are using a [user config repository](user-setup.md). It can also be enabled at the ZMK level using the `app/prj.conf` file, or other +search locations described in the [configuration overview](config/index.md#config-file-locations). + +Logging can be further configured using Kconfig described in [the Zephyr documentation](https://docs.zephyrproject.org/3.2.0/services/logging/index.html). +For instance, setting `CONFIG_LOG_PROCESS_THREAD_STARTUP_DELAY_MS` to a large value such as `8000` might help catch issues that happen near keyboard +boot, before you can connect to view the logs. :::note -If you are debugging your own keyboard in your [user config repository](user-setup.md), use -`config/boards/shields//.conf` instead of `app/prj.conf`. In Github -Actions, you can search the `Kconfig file` build log to verify the options above have been enabled +In Github Actions, you can check the ` Kconfig file` step output to verify the options above have been enabled for you successfully. ::: From 7f9e9f8c64f3128c2c3e7af3f22ced665fe1b873 Mon Sep 17 00:00:00 2001 From: Cem Aksoylar Date: Tue, 5 Sep 2023 22:23:44 -0700 Subject: [PATCH 71/76] fix(boards): Disable QSPI for Xiao BLE The GD25Q16 flash connected via QSPI seems to be causing issues with excessive battery use and inability to sleep. Since ZMK doesn't use it, disable it. Resolves #1901 --- app/boards/seeeduino_xiao_ble.overlay | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/boards/seeeduino_xiao_ble.overlay b/app/boards/seeeduino_xiao_ble.overlay index 51671a803b4..e6a5b62c738 100644 --- a/app/boards/seeeduino_xiao_ble.overlay +++ b/app/boards/seeeduino_xiao_ble.overlay @@ -32,3 +32,6 @@ }; }; +&qspi { + status = "disabled"; +}; From eaeea4bdfa2d67c7faea8e5f77b638723ebfe5e9 Mon Sep 17 00:00:00 2001 From: Jeppe Klitgaard Date: Tue, 12 Sep 2023 08:32:09 +0200 Subject: [PATCH 72/76] feat(docs): Add missing `&kp` tip for `devicetree_unfixed.h` error --- docs/docs/troubleshooting.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/docs/troubleshooting.md b/docs/docs/troubleshooting.md index d47671bce36..1418f327feb 100644 --- a/docs/docs/troubleshooting.md +++ b/docs/docs/troubleshooting.md @@ -58,10 +58,14 @@ A `devicetree_unfixed.h` error that follows with an "undeclared here" string ind In this example, the error string `DT_N_S_keymap_S_symbol_layer_P_bindings_IDX_12_PH_P_label` indicates a problem with the key binding in position `12` in the `symbol_layer` of the keymap. -:::note +:::info Key positions are numbered starting from `0` at the top left key on the keymap, incrementing horizontally, row by row. ::: +:::tip +A common mistake that leads to this error is to use [key press keycodes](behaviors/key-press.md) without the leading `&kp` binding. That is, having entries such as `SPACE` that should have been `&kp SPACE`. +::: + ### Split Keyboard Halves Unable to Pair Split keyboard halves pairing issue can be resolved by flashing a settings reset firmware to both controllers. You will first need to acquire the reset UF2 image file with one of the following options: From 690bc1bb44b1b62228900906cb308dc6f1a05eb8 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Sat, 2 Sep 2023 20:07:31 -0700 Subject: [PATCH 73/76] refactor: Move drivers into properly module. * Align our driver module layout to properly match Zephyr conventions, allowing proper CMake setup to amend the library for each type of driver. --- app/CMakeLists.txt | 2 +- app/Kconfig | 10 +++++++--- app/drivers/CMakeLists.txt | 7 ------- app/drivers/display/CMakeLists.txt | 4 ---- app/include/dt-bindings/zmk/kscan-mock.h | 9 --------- app/module/CMakeLists.txt | 3 +++ app/module/Kconfig | 2 ++ app/module/drivers/CMakeLists.txt | 7 +++++++ app/{ => module}/drivers/Kconfig | 0 app/module/drivers/display/CMakeLists.txt | 6 ++++++ app/{ => module}/drivers/display/Kconfig | 6 +++++- app/{ => module}/drivers/display/Kconfig.il0323 | 0 app/{ => module}/drivers/display/il0323.c | 0 app/{ => module}/drivers/display/il0323_regs.h | 0 app/{ => module}/drivers/gpio/CMakeLists.txt | 3 +-- app/{ => module}/drivers/gpio/Kconfig | 6 ++++-- app/{ => module}/drivers/gpio/Kconfig.595 | 1 - app/{ => module}/drivers/gpio/Kconfig.max7318 | 1 - app/{ => module}/drivers/gpio/gpio_595.c | 0 app/{ => module}/drivers/gpio/gpio_max7318.c | 0 app/{ => module}/drivers/kscan/CMakeLists.txt | 3 +-- app/{ => module}/drivers/kscan/Kconfig | 14 +++++++++----- app/{ => module}/drivers/kscan/debounce.c | 0 app/{ => module}/drivers/kscan/debounce.h | 0 app/{ => module}/drivers/kscan/kscan_composite.c | 0 app/{ => module}/drivers/kscan/kscan_gpio.c | 0 app/{ => module}/drivers/kscan/kscan_gpio.h | 0 app/{ => module}/drivers/kscan/kscan_gpio_demux.c | 0 app/{ => module}/drivers/kscan/kscan_gpio_direct.c | 0 app/{ => module}/drivers/kscan/kscan_gpio_matrix.c | 0 app/{ => module}/drivers/kscan/kscan_mock.c | 0 app/{ => module}/drivers/sensor/CMakeLists.txt | 0 app/{ => module}/drivers/sensor/Kconfig | 6 +++++- .../drivers/sensor/battery/CMakeLists.txt | 0 app/{ => module}/drivers/sensor/battery/Kconfig | 0 .../drivers/sensor/battery/battery_common.c | 0 .../drivers/sensor/battery/battery_common.h | 0 .../drivers/sensor/battery/battery_nrf_vddh.c | 0 .../sensor/battery/battery_voltage_divider.c | 0 .../drivers/sensor/ec11/CMakeLists.txt | 0 app/{ => module}/drivers/sensor/ec11/Kconfig | 0 app/{ => module}/drivers/sensor/ec11/ec11.c | 0 app/{ => module}/drivers/sensor/ec11/ec11.h | 0 .../drivers/sensor/ec11/ec11_trigger.c | 0 .../dts/bindings/display/gooddisplay,il0323.yaml | 0 .../dts/bindings/gpio/maxim,max7318.yaml | 0 .../dts/bindings/gpio/zmk,gpio-595.yaml | 0 .../dts/bindings/kscan/zmk,kscan-gpio-demux.yaml | 0 .../dts/bindings/kscan/zmk,kscan-gpio-direct.yaml | 0 .../dts/bindings/kscan/zmk,kscan-gpio-matrix.yaml | 0 .../dts/bindings/sensor/alps,ec11.yaml | 0 .../dts/bindings/sensor/zmk,battery-nrf-vddh.yaml | 0 .../sensor/zmk,battery-voltage-divider.yaml | 0 .../include/dt-bindings/zmk/kscan_mock.h | 0 app/{drivers => module}/zephyr/module.yml | 2 ++ 55 files changed, 53 insertions(+), 39 deletions(-) delete mode 100644 app/drivers/CMakeLists.txt delete mode 100644 app/drivers/display/CMakeLists.txt delete mode 100644 app/include/dt-bindings/zmk/kscan-mock.h create mode 100644 app/module/CMakeLists.txt create mode 100644 app/module/Kconfig create mode 100644 app/module/drivers/CMakeLists.txt rename app/{ => module}/drivers/Kconfig (100%) create mode 100644 app/module/drivers/display/CMakeLists.txt rename app/{ => module}/drivers/display/Kconfig (58%) rename app/{ => module}/drivers/display/Kconfig.il0323 (100%) rename app/{ => module}/drivers/display/il0323.c (100%) rename app/{ => module}/drivers/display/il0323_regs.h (100%) rename app/{ => module}/drivers/gpio/CMakeLists.txt (65%) rename app/{ => module}/drivers/gpio/Kconfig (52%) rename app/{ => module}/drivers/gpio/Kconfig.595 (95%) rename app/{ => module}/drivers/gpio/Kconfig.max7318 (95%) rename app/{ => module}/drivers/gpio/gpio_595.c (100%) rename app/{ => module}/drivers/gpio/gpio_max7318.c (100%) rename app/{ => module}/drivers/kscan/CMakeLists.txt (85%) rename app/{ => module}/drivers/kscan/Kconfig (94%) rename app/{ => module}/drivers/kscan/debounce.c (100%) rename app/{ => module}/drivers/kscan/debounce.h (100%) rename app/{ => module}/drivers/kscan/kscan_composite.c (100%) rename app/{ => module}/drivers/kscan/kscan_gpio.c (100%) rename app/{ => module}/drivers/kscan/kscan_gpio.h (100%) rename app/{ => module}/drivers/kscan/kscan_gpio_demux.c (100%) rename app/{ => module}/drivers/kscan/kscan_gpio_direct.c (100%) rename app/{ => module}/drivers/kscan/kscan_gpio_matrix.c (100%) rename app/{ => module}/drivers/kscan/kscan_mock.c (100%) rename app/{ => module}/drivers/sensor/CMakeLists.txt (100%) rename app/{ => module}/drivers/sensor/Kconfig (67%) rename app/{ => module}/drivers/sensor/battery/CMakeLists.txt (100%) rename app/{ => module}/drivers/sensor/battery/Kconfig (100%) rename app/{ => module}/drivers/sensor/battery/battery_common.c (100%) rename app/{ => module}/drivers/sensor/battery/battery_common.h (100%) rename app/{ => module}/drivers/sensor/battery/battery_nrf_vddh.c (100%) rename app/{ => module}/drivers/sensor/battery/battery_voltage_divider.c (100%) rename app/{ => module}/drivers/sensor/ec11/CMakeLists.txt (100%) rename app/{ => module}/drivers/sensor/ec11/Kconfig (100%) rename app/{ => module}/drivers/sensor/ec11/ec11.c (100%) rename app/{ => module}/drivers/sensor/ec11/ec11.h (100%) rename app/{ => module}/drivers/sensor/ec11/ec11_trigger.c (100%) rename app/{ => module}/dts/bindings/display/gooddisplay,il0323.yaml (100%) rename app/{drivers/zephyr => module}/dts/bindings/gpio/maxim,max7318.yaml (100%) rename app/{drivers/zephyr => module}/dts/bindings/gpio/zmk,gpio-595.yaml (100%) rename app/{drivers/zephyr => module}/dts/bindings/kscan/zmk,kscan-gpio-demux.yaml (100%) rename app/{drivers/zephyr => module}/dts/bindings/kscan/zmk,kscan-gpio-direct.yaml (100%) rename app/{drivers/zephyr => module}/dts/bindings/kscan/zmk,kscan-gpio-matrix.yaml (100%) rename app/{drivers/zephyr => module}/dts/bindings/sensor/alps,ec11.yaml (100%) rename app/{drivers/zephyr => module}/dts/bindings/sensor/zmk,battery-nrf-vddh.yaml (100%) rename app/{drivers/zephyr => module}/dts/bindings/sensor/zmk,battery-voltage-divider.yaml (100%) rename app/{ => module}/include/dt-bindings/zmk/kscan_mock.h (100%) rename app/{drivers => module}/zephyr/module.yml (56%) diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index efa349052cf..29944753f80 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -8,7 +8,7 @@ list(APPEND DTS_ROOT ${CMAKE_SOURCE_DIR}/drivers/zephyr) set(ZephyrBuildConfiguration_ROOT ${CMAKE_SOURCE_DIR}/cmake) list(APPEND ZEPHYR_EXTRA_MODULES - ${CMAKE_CURRENT_SOURCE_DIR}/drivers + ${CMAKE_CURRENT_SOURCE_DIR}/module ) # Find Zephyr. This also loads Zephyr's build system. diff --git a/app/Kconfig b/app/Kconfig index 89a128b5a27..0dd9316a2a7 100644 --- a/app/Kconfig +++ b/app/Kconfig @@ -403,14 +403,18 @@ endif #Initialization Priorities endmenu -menu "KSCAN Settings" +menuconfig ZMK_KSCAN + bool "ZMK KScan Integration" + default y + select KSCAN + +if ZMK_KSCAN config ZMK_KSCAN_EVENT_QUEUE_SIZE int "Size of the event queue for KSCAN events to buffer events" default 4 -#KSCAN Settings -endmenu +endif # ZMK_KSCAN menu "Logging" diff --git a/app/drivers/CMakeLists.txt b/app/drivers/CMakeLists.txt deleted file mode 100644 index 44d69ac37a2..00000000000 --- a/app/drivers/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -# Copyright (c) 2020 The ZMK Contributors -# SPDX-License-Identifier: MIT - -add_subdirectory_ifdef(CONFIG_ZMK_DRIVERS_GPIO gpio) -add_subdirectory(kscan) -add_subdirectory(sensor) -add_subdirectory(display) diff --git a/app/drivers/display/CMakeLists.txt b/app/drivers/display/CMakeLists.txt deleted file mode 100644 index d5e83c1dc4e..00000000000 --- a/app/drivers/display/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -# Copyright (c) 2021 The ZMK Contributors -# SPDX-License-Identifier: MIT - -zephyr_sources_ifdef(CONFIG_IL0323 il0323.c) \ No newline at end of file diff --git a/app/include/dt-bindings/zmk/kscan-mock.h b/app/include/dt-bindings/zmk/kscan-mock.h deleted file mode 100644 index 4ed666c61ca..00000000000 --- a/app/include/dt-bindings/zmk/kscan-mock.h +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Copyright (c) 2020 The ZMK Contributors - * - * SPDX-License-Identifier: MIT - */ - -#warning "kscan-mock.h has been deprecated and superseded by kscan_mock.h" - -#include "kscan_mock.h" \ No newline at end of file diff --git a/app/module/CMakeLists.txt b/app/module/CMakeLists.txt new file mode 100644 index 00000000000..1c140d33d4a --- /dev/null +++ b/app/module/CMakeLists.txt @@ -0,0 +1,3 @@ +zephyr_include_directories(include) + +add_subdirectory(drivers) \ No newline at end of file diff --git a/app/module/Kconfig b/app/module/Kconfig new file mode 100644 index 00000000000..cb2ae20cd7c --- /dev/null +++ b/app/module/Kconfig @@ -0,0 +1,2 @@ + +rsource "drivers/Kconfig" \ No newline at end of file diff --git a/app/module/drivers/CMakeLists.txt b/app/module/drivers/CMakeLists.txt new file mode 100644 index 00000000000..5281c3dcb21 --- /dev/null +++ b/app/module/drivers/CMakeLists.txt @@ -0,0 +1,7 @@ +# Copyright (c) 2020 The ZMK Contributors +# SPDX-License-Identifier: MIT + +add_subdirectory_ifdef(CONFIG_GPIO gpio) +add_subdirectory_ifdef(CONFIG_KSCAN kscan) +add_subdirectory_ifdef(CONFIG_SENSOR sensor) +add_subdirectory_ifdef(CONFIG_DISPLAY display) diff --git a/app/drivers/Kconfig b/app/module/drivers/Kconfig similarity index 100% rename from app/drivers/Kconfig rename to app/module/drivers/Kconfig diff --git a/app/module/drivers/display/CMakeLists.txt b/app/module/drivers/display/CMakeLists.txt new file mode 100644 index 00000000000..6fc98c95a9d --- /dev/null +++ b/app/module/drivers/display/CMakeLists.txt @@ -0,0 +1,6 @@ +# Copyright (c) 2021 The ZMK Contributors +# SPDX-License-Identifier: MIT + +zephyr_library_amend() + +zephyr_library_sources_ifdef(CONFIG_IL0323 il0323.c) \ No newline at end of file diff --git a/app/drivers/display/Kconfig b/app/module/drivers/display/Kconfig similarity index 58% rename from app/drivers/display/Kconfig rename to app/module/drivers/display/Kconfig index efa064d4f6b..d70aff7c40a 100644 --- a/app/drivers/display/Kconfig +++ b/app/module/drivers/display/Kconfig @@ -1,4 +1,8 @@ # Copyright (c) 2021 The ZMK Contributors # SPDX-License-Identifier: MIT -rsource "Kconfig.il0323" \ No newline at end of file +if DISPLAY + +rsource "Kconfig.il0323" + +endif # DISPLAY \ No newline at end of file diff --git a/app/drivers/display/Kconfig.il0323 b/app/module/drivers/display/Kconfig.il0323 similarity index 100% rename from app/drivers/display/Kconfig.il0323 rename to app/module/drivers/display/Kconfig.il0323 diff --git a/app/drivers/display/il0323.c b/app/module/drivers/display/il0323.c similarity index 100% rename from app/drivers/display/il0323.c rename to app/module/drivers/display/il0323.c diff --git a/app/drivers/display/il0323_regs.h b/app/module/drivers/display/il0323_regs.h similarity index 100% rename from app/drivers/display/il0323_regs.h rename to app/module/drivers/display/il0323_regs.h diff --git a/app/drivers/gpio/CMakeLists.txt b/app/module/drivers/gpio/CMakeLists.txt similarity index 65% rename from app/drivers/gpio/CMakeLists.txt rename to app/module/drivers/gpio/CMakeLists.txt index 0756ed386b4..b5647e87bd7 100644 --- a/app/drivers/gpio/CMakeLists.txt +++ b/app/module/drivers/gpio/CMakeLists.txt @@ -1,8 +1,7 @@ # Copyright (c) 2022 The ZMK Contributors # SPDX-License-Identifier: MIT -zephyr_library_named(zmk__drivers__gpio) -zephyr_library_include_directories(${CMAKE_SOURCE_DIR}/include) +zephyr_library_amend() zephyr_library_sources_ifdef(CONFIG_GPIO_595 gpio_595.c) zephyr_library_sources_ifdef(CONFIG_GPIO_MAX7318 gpio_max7318.c) diff --git a/app/drivers/gpio/Kconfig b/app/module/drivers/gpio/Kconfig similarity index 52% rename from app/drivers/gpio/Kconfig rename to app/module/drivers/gpio/Kconfig index 54b30590e1c..a6c7b4a19ef 100644 --- a/app/drivers/gpio/Kconfig +++ b/app/module/drivers/gpio/Kconfig @@ -1,5 +1,7 @@ -menuconfig ZMK_DRIVERS_GPIO - bool "GPIO" + +if GPIO rsource "Kconfig.max7318" rsource "Kconfig.595" + +endif # GPIO \ No newline at end of file diff --git a/app/drivers/gpio/Kconfig.595 b/app/module/drivers/gpio/Kconfig.595 similarity index 95% rename from app/drivers/gpio/Kconfig.595 rename to app/module/drivers/gpio/Kconfig.595 index b4b6bdcc2d8..7ebdc0cc54c 100644 --- a/app/drivers/gpio/Kconfig.595 +++ b/app/module/drivers/gpio/Kconfig.595 @@ -10,7 +10,6 @@ menuconfig GPIO_595 default $(dt_compat_enabled,$(DT_COMPAT_ZMK_GPIO_595)) depends on SPI select HAS_DTS_GPIO - select ZMK_DRIVERS_GPIO help Enable driver for 595 shift register chip using SPI. diff --git a/app/drivers/gpio/Kconfig.max7318 b/app/module/drivers/gpio/Kconfig.max7318 similarity index 95% rename from app/drivers/gpio/Kconfig.max7318 rename to app/module/drivers/gpio/Kconfig.max7318 index d572b97090f..b54e1dba465 100644 --- a/app/drivers/gpio/Kconfig.max7318 +++ b/app/module/drivers/gpio/Kconfig.max7318 @@ -10,7 +10,6 @@ menuconfig GPIO_MAX7318 default $(dt_compat_enabled,$(DT_COMPAT_MAXIM_MAX7318)) depends on I2C select HAS_DTS_GPIO - select ZMK_DRIVERS_GPIO help Enable driver for MAX7318 I2C-based GPIO chip. diff --git a/app/drivers/gpio/gpio_595.c b/app/module/drivers/gpio/gpio_595.c similarity index 100% rename from app/drivers/gpio/gpio_595.c rename to app/module/drivers/gpio/gpio_595.c diff --git a/app/drivers/gpio/gpio_max7318.c b/app/module/drivers/gpio/gpio_max7318.c similarity index 100% rename from app/drivers/gpio/gpio_max7318.c rename to app/module/drivers/gpio/gpio_max7318.c diff --git a/app/drivers/kscan/CMakeLists.txt b/app/module/drivers/kscan/CMakeLists.txt similarity index 85% rename from app/drivers/kscan/CMakeLists.txt rename to app/module/drivers/kscan/CMakeLists.txt index 8fc7ed58d50..0bdcd90ea72 100644 --- a/app/drivers/kscan/CMakeLists.txt +++ b/app/module/drivers/kscan/CMakeLists.txt @@ -1,8 +1,7 @@ # Copyright (c) 2020 The ZMK Contributors # SPDX-License-Identifier: MIT -zephyr_library_named(zmk__drivers__kscan) -zephyr_library_include_directories(${CMAKE_SOURCE_DIR}/include) +zephyr_library_amend() zephyr_library_sources_ifdef(CONFIG_ZMK_KSCAN_GPIO_DRIVER debounce.c) zephyr_library_sources_ifdef(CONFIG_ZMK_KSCAN_GPIO_DRIVER kscan_gpio.c) diff --git a/app/drivers/kscan/Kconfig b/app/module/drivers/kscan/Kconfig similarity index 94% rename from app/drivers/kscan/Kconfig rename to app/module/drivers/kscan/Kconfig index 1d1656694dc..e67c9aa8894 100644 --- a/app/drivers/kscan/Kconfig +++ b/app/module/drivers/kscan/Kconfig @@ -7,6 +7,8 @@ DT_COMPAT_ZMK_KSCAN_GPIO_DIRECT := zmk,kscan-gpio-direct DT_COMPAT_ZMK_KSCAN_GPIO_MATRIX := zmk,kscan-gpio-matrix DT_COMPAT_ZMK_KSCAN_MOCK := zmk,kscan-mock +if KSCAN + config ZMK_KSCAN_COMPOSITE_DRIVER bool default $(dt_compat_enabled,$(DT_COMPAT_ZMK_KSCAN_COMPOSITE)) @@ -87,8 +89,10 @@ config ZMK_KSCAN_DEBOUNCE_RELEASE_MS endif -config ZMK_KSCAN_INIT_PRIORITY - int "Keyboard scan driver init priority" - default 40 - help - Keyboard scan device driver initialization priority. +# config ZMK_KSCAN_INIT_PRIORITY +# int "Keyboard scan driver init priority" +# default 40 +# help +# Keyboard scan device driver initialization priority. + +endif # KSCAN diff --git a/app/drivers/kscan/debounce.c b/app/module/drivers/kscan/debounce.c similarity index 100% rename from app/drivers/kscan/debounce.c rename to app/module/drivers/kscan/debounce.c diff --git a/app/drivers/kscan/debounce.h b/app/module/drivers/kscan/debounce.h similarity index 100% rename from app/drivers/kscan/debounce.h rename to app/module/drivers/kscan/debounce.h diff --git a/app/drivers/kscan/kscan_composite.c b/app/module/drivers/kscan/kscan_composite.c similarity index 100% rename from app/drivers/kscan/kscan_composite.c rename to app/module/drivers/kscan/kscan_composite.c diff --git a/app/drivers/kscan/kscan_gpio.c b/app/module/drivers/kscan/kscan_gpio.c similarity index 100% rename from app/drivers/kscan/kscan_gpio.c rename to app/module/drivers/kscan/kscan_gpio.c diff --git a/app/drivers/kscan/kscan_gpio.h b/app/module/drivers/kscan/kscan_gpio.h similarity index 100% rename from app/drivers/kscan/kscan_gpio.h rename to app/module/drivers/kscan/kscan_gpio.h diff --git a/app/drivers/kscan/kscan_gpio_demux.c b/app/module/drivers/kscan/kscan_gpio_demux.c similarity index 100% rename from app/drivers/kscan/kscan_gpio_demux.c rename to app/module/drivers/kscan/kscan_gpio_demux.c diff --git a/app/drivers/kscan/kscan_gpio_direct.c b/app/module/drivers/kscan/kscan_gpio_direct.c similarity index 100% rename from app/drivers/kscan/kscan_gpio_direct.c rename to app/module/drivers/kscan/kscan_gpio_direct.c diff --git a/app/drivers/kscan/kscan_gpio_matrix.c b/app/module/drivers/kscan/kscan_gpio_matrix.c similarity index 100% rename from app/drivers/kscan/kscan_gpio_matrix.c rename to app/module/drivers/kscan/kscan_gpio_matrix.c diff --git a/app/drivers/kscan/kscan_mock.c b/app/module/drivers/kscan/kscan_mock.c similarity index 100% rename from app/drivers/kscan/kscan_mock.c rename to app/module/drivers/kscan/kscan_mock.c diff --git a/app/drivers/sensor/CMakeLists.txt b/app/module/drivers/sensor/CMakeLists.txt similarity index 100% rename from app/drivers/sensor/CMakeLists.txt rename to app/module/drivers/sensor/CMakeLists.txt diff --git a/app/drivers/sensor/Kconfig b/app/module/drivers/sensor/Kconfig similarity index 67% rename from app/drivers/sensor/Kconfig rename to app/module/drivers/sensor/Kconfig index a828f6c63ab..6a8ac07ea3e 100644 --- a/app/drivers/sensor/Kconfig +++ b/app/module/drivers/sensor/Kconfig @@ -1,5 +1,9 @@ # Copyright (c) 2020 The ZMK Contributors # SPDX-License-Identifier: MIT +if SENSOR + rsource "battery/Kconfig" -rsource "ec11/Kconfig" \ No newline at end of file +rsource "ec11/Kconfig" + +endif # SENSOR \ No newline at end of file diff --git a/app/drivers/sensor/battery/CMakeLists.txt b/app/module/drivers/sensor/battery/CMakeLists.txt similarity index 100% rename from app/drivers/sensor/battery/CMakeLists.txt rename to app/module/drivers/sensor/battery/CMakeLists.txt diff --git a/app/drivers/sensor/battery/Kconfig b/app/module/drivers/sensor/battery/Kconfig similarity index 100% rename from app/drivers/sensor/battery/Kconfig rename to app/module/drivers/sensor/battery/Kconfig diff --git a/app/drivers/sensor/battery/battery_common.c b/app/module/drivers/sensor/battery/battery_common.c similarity index 100% rename from app/drivers/sensor/battery/battery_common.c rename to app/module/drivers/sensor/battery/battery_common.c diff --git a/app/drivers/sensor/battery/battery_common.h b/app/module/drivers/sensor/battery/battery_common.h similarity index 100% rename from app/drivers/sensor/battery/battery_common.h rename to app/module/drivers/sensor/battery/battery_common.h diff --git a/app/drivers/sensor/battery/battery_nrf_vddh.c b/app/module/drivers/sensor/battery/battery_nrf_vddh.c similarity index 100% rename from app/drivers/sensor/battery/battery_nrf_vddh.c rename to app/module/drivers/sensor/battery/battery_nrf_vddh.c diff --git a/app/drivers/sensor/battery/battery_voltage_divider.c b/app/module/drivers/sensor/battery/battery_voltage_divider.c similarity index 100% rename from app/drivers/sensor/battery/battery_voltage_divider.c rename to app/module/drivers/sensor/battery/battery_voltage_divider.c diff --git a/app/drivers/sensor/ec11/CMakeLists.txt b/app/module/drivers/sensor/ec11/CMakeLists.txt similarity index 100% rename from app/drivers/sensor/ec11/CMakeLists.txt rename to app/module/drivers/sensor/ec11/CMakeLists.txt diff --git a/app/drivers/sensor/ec11/Kconfig b/app/module/drivers/sensor/ec11/Kconfig similarity index 100% rename from app/drivers/sensor/ec11/Kconfig rename to app/module/drivers/sensor/ec11/Kconfig diff --git a/app/drivers/sensor/ec11/ec11.c b/app/module/drivers/sensor/ec11/ec11.c similarity index 100% rename from app/drivers/sensor/ec11/ec11.c rename to app/module/drivers/sensor/ec11/ec11.c diff --git a/app/drivers/sensor/ec11/ec11.h b/app/module/drivers/sensor/ec11/ec11.h similarity index 100% rename from app/drivers/sensor/ec11/ec11.h rename to app/module/drivers/sensor/ec11/ec11.h diff --git a/app/drivers/sensor/ec11/ec11_trigger.c b/app/module/drivers/sensor/ec11/ec11_trigger.c similarity index 100% rename from app/drivers/sensor/ec11/ec11_trigger.c rename to app/module/drivers/sensor/ec11/ec11_trigger.c diff --git a/app/dts/bindings/display/gooddisplay,il0323.yaml b/app/module/dts/bindings/display/gooddisplay,il0323.yaml similarity index 100% rename from app/dts/bindings/display/gooddisplay,il0323.yaml rename to app/module/dts/bindings/display/gooddisplay,il0323.yaml diff --git a/app/drivers/zephyr/dts/bindings/gpio/maxim,max7318.yaml b/app/module/dts/bindings/gpio/maxim,max7318.yaml similarity index 100% rename from app/drivers/zephyr/dts/bindings/gpio/maxim,max7318.yaml rename to app/module/dts/bindings/gpio/maxim,max7318.yaml diff --git a/app/drivers/zephyr/dts/bindings/gpio/zmk,gpio-595.yaml b/app/module/dts/bindings/gpio/zmk,gpio-595.yaml similarity index 100% rename from app/drivers/zephyr/dts/bindings/gpio/zmk,gpio-595.yaml rename to app/module/dts/bindings/gpio/zmk,gpio-595.yaml diff --git a/app/drivers/zephyr/dts/bindings/kscan/zmk,kscan-gpio-demux.yaml b/app/module/dts/bindings/kscan/zmk,kscan-gpio-demux.yaml similarity index 100% rename from app/drivers/zephyr/dts/bindings/kscan/zmk,kscan-gpio-demux.yaml rename to app/module/dts/bindings/kscan/zmk,kscan-gpio-demux.yaml diff --git a/app/drivers/zephyr/dts/bindings/kscan/zmk,kscan-gpio-direct.yaml b/app/module/dts/bindings/kscan/zmk,kscan-gpio-direct.yaml similarity index 100% rename from app/drivers/zephyr/dts/bindings/kscan/zmk,kscan-gpio-direct.yaml rename to app/module/dts/bindings/kscan/zmk,kscan-gpio-direct.yaml diff --git a/app/drivers/zephyr/dts/bindings/kscan/zmk,kscan-gpio-matrix.yaml b/app/module/dts/bindings/kscan/zmk,kscan-gpio-matrix.yaml similarity index 100% rename from app/drivers/zephyr/dts/bindings/kscan/zmk,kscan-gpio-matrix.yaml rename to app/module/dts/bindings/kscan/zmk,kscan-gpio-matrix.yaml diff --git a/app/drivers/zephyr/dts/bindings/sensor/alps,ec11.yaml b/app/module/dts/bindings/sensor/alps,ec11.yaml similarity index 100% rename from app/drivers/zephyr/dts/bindings/sensor/alps,ec11.yaml rename to app/module/dts/bindings/sensor/alps,ec11.yaml diff --git a/app/drivers/zephyr/dts/bindings/sensor/zmk,battery-nrf-vddh.yaml b/app/module/dts/bindings/sensor/zmk,battery-nrf-vddh.yaml similarity index 100% rename from app/drivers/zephyr/dts/bindings/sensor/zmk,battery-nrf-vddh.yaml rename to app/module/dts/bindings/sensor/zmk,battery-nrf-vddh.yaml diff --git a/app/drivers/zephyr/dts/bindings/sensor/zmk,battery-voltage-divider.yaml b/app/module/dts/bindings/sensor/zmk,battery-voltage-divider.yaml similarity index 100% rename from app/drivers/zephyr/dts/bindings/sensor/zmk,battery-voltage-divider.yaml rename to app/module/dts/bindings/sensor/zmk,battery-voltage-divider.yaml diff --git a/app/include/dt-bindings/zmk/kscan_mock.h b/app/module/include/dt-bindings/zmk/kscan_mock.h similarity index 100% rename from app/include/dt-bindings/zmk/kscan_mock.h rename to app/module/include/dt-bindings/zmk/kscan_mock.h diff --git a/app/drivers/zephyr/module.yml b/app/module/zephyr/module.yml similarity index 56% rename from app/drivers/zephyr/module.yml rename to app/module/zephyr/module.yml index 0b6605945e5..219b2cfd201 100644 --- a/app/drivers/zephyr/module.yml +++ b/app/module/zephyr/module.yml @@ -1,3 +1,5 @@ build: cmake: . kconfig: Kconfig + settings: + dts_root: . From c28ef1b61e9feb748ff0823f7f226d67e14fd3aa Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Sat, 2 Sep 2023 20:28:47 -0700 Subject: [PATCH 74/76] refactor(drivers): Use proper init stage/priority. * Avoid APPLICATION stage and use the proper earlier stage for kscan drivers. --- app/module/drivers/kscan/Kconfig | 6 ------ app/module/drivers/kscan/kscan_composite.c | 2 +- app/module/drivers/kscan/kscan_gpio_demux.c | 2 +- app/module/drivers/kscan/kscan_gpio_direct.c | 2 +- app/module/drivers/kscan/kscan_gpio_matrix.c | 2 +- app/module/drivers/kscan/kscan_mock.c | 4 ++-- 6 files changed, 6 insertions(+), 12 deletions(-) diff --git a/app/module/drivers/kscan/Kconfig b/app/module/drivers/kscan/Kconfig index e67c9aa8894..60b5df3b6ad 100644 --- a/app/module/drivers/kscan/Kconfig +++ b/app/module/drivers/kscan/Kconfig @@ -89,10 +89,4 @@ config ZMK_KSCAN_DEBOUNCE_RELEASE_MS endif -# config ZMK_KSCAN_INIT_PRIORITY -# int "Keyboard scan driver init priority" -# default 40 -# help -# Keyboard scan device driver initialization priority. - endif # KSCAN diff --git a/app/module/drivers/kscan/kscan_composite.c b/app/module/drivers/kscan/kscan_composite.c index 9909a4cfcfa..97311ef8e52 100644 --- a/app/module/drivers/kscan/kscan_composite.c +++ b/app/module/drivers/kscan/kscan_composite.c @@ -109,4 +109,4 @@ static const struct kscan_composite_config kscan_composite_config = {}; static struct kscan_composite_data kscan_composite_data; DEVICE_DT_INST_DEFINE(0, kscan_composite_init, NULL, &kscan_composite_data, &kscan_composite_config, - APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &mock_driver_api); + POST_KERNEL, CONFIG_KSCAN_INIT_PRIORITY, &mock_driver_api); diff --git a/app/module/drivers/kscan/kscan_gpio_demux.c b/app/module/drivers/kscan/kscan_gpio_demux.c index 812a899d89c..2cbe116d9f2 100644 --- a/app/module/drivers/kscan/kscan_gpio_demux.c +++ b/app/module/drivers/kscan/kscan_gpio_demux.c @@ -201,7 +201,7 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); }; \ \ DEVICE_DT_INST_DEFINE(n, kscan_gpio_init_##n, NULL, &kscan_gpio_data_##n, \ - &kscan_gpio_config_##n, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY, \ + &kscan_gpio_config_##n, POST_KERNEL, CONFIG_KSCAN_INIT_PRIORITY, \ &gpio_driver_api_##n); DT_INST_FOREACH_STATUS_OKAY(GPIO_INST_INIT) diff --git a/app/module/drivers/kscan/kscan_gpio_direct.c b/app/module/drivers/kscan/kscan_gpio_direct.c index d43d716bf64..c0990887083 100644 --- a/app/module/drivers/kscan/kscan_gpio_direct.c +++ b/app/module/drivers/kscan/kscan_gpio_direct.c @@ -354,7 +354,7 @@ static const struct kscan_driver_api kscan_direct_api = { }; \ \ DEVICE_DT_INST_DEFINE(n, &kscan_direct_init, NULL, &kscan_direct_data_##n, \ - &kscan_direct_config_##n, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY, \ + &kscan_direct_config_##n, POST_KERNEL, CONFIG_KSCAN_INIT_PRIORITY, \ &kscan_direct_api); DT_INST_FOREACH_STATUS_OKAY(KSCAN_DIRECT_INIT); diff --git a/app/module/drivers/kscan/kscan_gpio_matrix.c b/app/module/drivers/kscan/kscan_gpio_matrix.c index b8e72044928..309da204b13 100644 --- a/app/module/drivers/kscan/kscan_gpio_matrix.c +++ b/app/module/drivers/kscan/kscan_gpio_matrix.c @@ -465,7 +465,7 @@ static const struct kscan_driver_api kscan_matrix_api = { }; \ \ DEVICE_DT_INST_DEFINE(n, &kscan_matrix_init, NULL, &kscan_matrix_data_##n, \ - &kscan_matrix_config_##n, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY, \ + &kscan_matrix_config_##n, POST_KERNEL, CONFIG_KSCAN_INIT_PRIORITY, \ &kscan_matrix_api); DT_INST_FOREACH_STATUS_OKAY(KSCAN_MATRIX_INIT); diff --git a/app/module/drivers/kscan/kscan_mock.c b/app/module/drivers/kscan/kscan_mock.c index 57862b0d6f4..604e164cbc5 100644 --- a/app/module/drivers/kscan/kscan_mock.c +++ b/app/module/drivers/kscan/kscan_mock.c @@ -89,7 +89,7 @@ static int kscan_mock_configure(const struct device *dev, kscan_callback_t callb static const struct kscan_mock_config_##n kscan_mock_config_##n = { \ .events = DT_INST_PROP(n, events), .exit_after = DT_INST_PROP(n, exit_after)}; \ DEVICE_DT_INST_DEFINE(n, kscan_mock_init_##n, NULL, &kscan_mock_data_##n, \ - &kscan_mock_config_##n, APPLICATION, \ - CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &mock_driver_api_##n); + &kscan_mock_config_##n, POST_KERNEL, CONFIG_KSCAN_INIT_PRIORITY, \ + &mock_driver_api_##n); DT_INST_FOREACH_STATUS_OKAY(MOCK_INST_INIT) From 0ca7f69b6d21f0e24555d635a017459a8ed0fe43 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Mon, 11 Sep 2023 21:56:37 -0700 Subject: [PATCH 75/76] refactor: Promote debounce to exposed mod lib. * Promote previously local debounce code from kscan drivers to exposed module lib, for use with other drivers as needed. * Refactor existing kscan driver to new "public" API. --- app/module/CMakeLists.txt | 3 ++- app/module/Kconfig | 3 ++- app/module/drivers/kscan/CMakeLists.txt | 1 - app/module/drivers/kscan/Kconfig | 1 + app/module/drivers/kscan/kscan_gpio_direct.c | 21 ++++++++++--------- app/module/drivers/kscan/kscan_gpio_matrix.c | 21 ++++++++++--------- .../{drivers/kscan => include/zmk}/debounce.h | 14 ++++++------- app/module/lib/CMakeLists.txt | 2 ++ app/module/lib/Kconfig | 2 ++ app/module/lib/zmk_debounce/CMakeLists.txt | 3 +++ app/module/lib/zmk_debounce/Kconfig | 3 +++ .../kscan => lib/zmk_debounce}/debounce.c | 20 +++++++++--------- 12 files changed, 54 insertions(+), 40 deletions(-) rename app/module/{drivers/kscan => include/zmk}/debounce.h (73%) create mode 100644 app/module/lib/CMakeLists.txt create mode 100644 app/module/lib/Kconfig create mode 100644 app/module/lib/zmk_debounce/CMakeLists.txt create mode 100644 app/module/lib/zmk_debounce/Kconfig rename app/module/{drivers/kscan => lib/zmk_debounce}/debounce.c (62%) diff --git a/app/module/CMakeLists.txt b/app/module/CMakeLists.txt index 1c140d33d4a..db886ac6987 100644 --- a/app/module/CMakeLists.txt +++ b/app/module/CMakeLists.txt @@ -1,3 +1,4 @@ zephyr_include_directories(include) -add_subdirectory(drivers) \ No newline at end of file +add_subdirectory(drivers) +add_subdirectory(lib) \ No newline at end of file diff --git a/app/module/Kconfig b/app/module/Kconfig index cb2ae20cd7c..52c013151a9 100644 --- a/app/module/Kconfig +++ b/app/module/Kconfig @@ -1,2 +1,3 @@ -rsource "drivers/Kconfig" \ No newline at end of file +rsource "drivers/Kconfig" +rsource "lib/Kconfig" \ No newline at end of file diff --git a/app/module/drivers/kscan/CMakeLists.txt b/app/module/drivers/kscan/CMakeLists.txt index 0bdcd90ea72..7ae9524c75f 100644 --- a/app/module/drivers/kscan/CMakeLists.txt +++ b/app/module/drivers/kscan/CMakeLists.txt @@ -3,7 +3,6 @@ zephyr_library_amend() -zephyr_library_sources_ifdef(CONFIG_ZMK_KSCAN_GPIO_DRIVER debounce.c) zephyr_library_sources_ifdef(CONFIG_ZMK_KSCAN_GPIO_DRIVER kscan_gpio.c) zephyr_library_sources_ifdef(CONFIG_ZMK_KSCAN_GPIO_MATRIX kscan_gpio_matrix.c) zephyr_library_sources_ifdef(CONFIG_ZMK_KSCAN_GPIO_DIRECT kscan_gpio_direct.c) diff --git a/app/module/drivers/kscan/Kconfig b/app/module/drivers/kscan/Kconfig index 60b5df3b6ad..6f60b3f919f 100644 --- a/app/module/drivers/kscan/Kconfig +++ b/app/module/drivers/kscan/Kconfig @@ -16,6 +16,7 @@ config ZMK_KSCAN_COMPOSITE_DRIVER config ZMK_KSCAN_GPIO_DRIVER bool select GPIO + select ZMK_DEBOUNCE config ZMK_KSCAN_GPIO_DEMUX bool diff --git a/app/module/drivers/kscan/kscan_gpio_direct.c b/app/module/drivers/kscan/kscan_gpio_direct.c index c0990887083..5b227784dad 100644 --- a/app/module/drivers/kscan/kscan_gpio_direct.c +++ b/app/module/drivers/kscan/kscan_gpio_direct.c @@ -4,7 +4,6 @@ * SPDX-License-Identifier: MIT */ -#include "debounce.h" #include "kscan_gpio.h" #include @@ -15,6 +14,8 @@ #include #include +#include + LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #define DT_DRV_COMPAT zmk_kscan_gpio_direct @@ -61,11 +62,11 @@ struct kscan_direct_data { /** Timestamp of the current or scheduled scan. */ int64_t scan_time; /** Current state of the inputs as an array of length config->inputs.len */ - struct debounce_state *pin_state; + struct zmk_debounce_state *pin_state; }; struct kscan_direct_config { - struct debounce_config debounce_config; + struct zmk_debounce_config debounce_config; int32_t debounce_scan_period_ms; int32_t poll_period_ms; bool toggle_mode; @@ -182,8 +183,8 @@ static int kscan_direct_read(const struct device *dev) { return active; } - debounce_update(&data->pin_state[gpio->index], active, config->debounce_scan_period_ms, - &config->debounce_config); + zmk_debounce_update(&data->pin_state[gpio->index], active, config->debounce_scan_period_ms, + &config->debounce_config); } // Process the new state. @@ -191,10 +192,10 @@ static int kscan_direct_read(const struct device *dev) { for (int i = 0; i < data->inputs.len; i++) { const struct kscan_gpio *gpio = &data->inputs.gpios[i]; - struct debounce_state *state = &data->pin_state[gpio->index]; + struct zmk_debounce_state *state = &data->pin_state[gpio->index]; - if (debounce_get_changed(state)) { - const bool pressed = debounce_is_pressed(state); + if (zmk_debounce_get_changed(state)) { + const bool pressed = zmk_debounce_is_pressed(state); LOG_DBG("Sending event at 0,%i state %s", gpio->index, pressed ? "on" : "off"); data->callback(dev, 0, gpio->index, pressed); @@ -203,7 +204,7 @@ static int kscan_direct_read(const struct device *dev) { } } - continue_scan = continue_scan || debounce_is_active(state); + continue_scan = continue_scan || zmk_debounce_is_active(state); } if (continue_scan) { @@ -332,7 +333,7 @@ static const struct kscan_driver_api kscan_direct_api = { static struct kscan_gpio kscan_direct_inputs_##n[] = { \ LISTIFY(INST_INPUTS_LEN(n), KSCAN_DIRECT_INPUT_CFG_INIT, (, ), n)}; \ \ - static struct debounce_state kscan_direct_state_##n[INST_INPUTS_LEN(n)]; \ + static struct zmk_debounce_state kscan_direct_state_##n[INST_INPUTS_LEN(n)]; \ \ COND_INTERRUPTS( \ (static struct kscan_direct_irq_callback kscan_direct_irqs_##n[INST_INPUTS_LEN(n)];)) \ diff --git a/app/module/drivers/kscan/kscan_gpio_matrix.c b/app/module/drivers/kscan/kscan_gpio_matrix.c index 309da204b13..0d8a3190659 100644 --- a/app/module/drivers/kscan/kscan_gpio_matrix.c +++ b/app/module/drivers/kscan/kscan_gpio_matrix.c @@ -4,7 +4,6 @@ * SPDX-License-Identifier: MIT */ -#include "debounce.h" #include "kscan_gpio.h" #include @@ -16,6 +15,8 @@ #include #include +#include + LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #define DT_DRV_COMPAT zmk_kscan_gpio_matrix @@ -80,12 +81,12 @@ struct kscan_matrix_data { * Current state of the matrix as a flattened 2D array of length * (config->rows * config->cols) */ - struct debounce_state *matrix_state; + struct zmk_debounce_state *matrix_state; }; struct kscan_matrix_config { struct kscan_gpio_list outputs; - struct debounce_config debounce_config; + struct zmk_debounce_config debounce_config; size_t rows; size_t cols; int32_t debounce_scan_period_ms; @@ -242,8 +243,8 @@ static int kscan_matrix_read(const struct device *dev) { return active; } - debounce_update(&data->matrix_state[index], active, config->debounce_scan_period_ms, - &config->debounce_config); + zmk_debounce_update(&data->matrix_state[index], active, config->debounce_scan_period_ms, + &config->debounce_config); } err = gpio_pin_set_dt(&out_gpio->spec, 0); @@ -263,16 +264,16 @@ static int kscan_matrix_read(const struct device *dev) { for (int r = 0; r < config->rows; r++) { for (int c = 0; c < config->cols; c++) { const int index = state_index_rc(config, r, c); - struct debounce_state *state = &data->matrix_state[index]; + struct zmk_debounce_state *state = &data->matrix_state[index]; - if (debounce_get_changed(state)) { - const bool pressed = debounce_is_pressed(state); + if (zmk_debounce_get_changed(state)) { + const bool pressed = zmk_debounce_is_pressed(state); LOG_DBG("Sending event at %i,%i state %s", r, c, pressed ? "on" : "off"); data->callback(dev, r, c, pressed); } - continue_scan = continue_scan || debounce_is_active(state); + continue_scan = continue_scan || zmk_debounce_is_active(state); } } @@ -438,7 +439,7 @@ static const struct kscan_driver_api kscan_matrix_api = { static struct kscan_gpio kscan_matrix_cols_##n[] = { \ LISTIFY(INST_COLS_LEN(n), KSCAN_GPIO_COL_CFG_INIT, (, ), n)}; \ \ - static struct debounce_state kscan_matrix_state_##n[INST_MATRIX_LEN(n)]; \ + static struct zmk_debounce_state kscan_matrix_state_##n[INST_MATRIX_LEN(n)]; \ \ COND_INTERRUPTS( \ (static struct kscan_matrix_irq_callback kscan_matrix_irqs_##n[INST_INPUTS_LEN(n)];)) \ diff --git a/app/module/drivers/kscan/debounce.h b/app/module/include/zmk/debounce.h similarity index 73% rename from app/module/drivers/kscan/debounce.h rename to app/module/include/zmk/debounce.h index 6e9faa66818..afa775a023d 100644 --- a/app/module/drivers/kscan/debounce.h +++ b/app/module/include/zmk/debounce.h @@ -13,13 +13,13 @@ #define DEBOUNCE_COUNTER_BITS 14 #define DEBOUNCE_COUNTER_MAX BIT_MASK(DEBOUNCE_COUNTER_BITS) -struct debounce_state { +struct zmk_debounce_state { bool pressed : 1; bool changed : 1; uint16_t counter : DEBOUNCE_COUNTER_BITS; }; -struct debounce_config { +struct zmk_debounce_config { /** Duration a switch must be pressed to latch as pressed. */ uint32_t debounce_press_ms; /** Duration a switch must be released to latch as released. */ @@ -34,23 +34,23 @@ struct debounce_config { * @param elapsed_ms Time elapsed since the previous update in milliseconds. * @param config Debounce settings. */ -void debounce_update(struct debounce_state *state, const bool active, const int elapsed_ms, - const struct debounce_config *config); +void zmk_debounce_update(struct zmk_debounce_state *state, const bool active, const int elapsed_ms, + const struct zmk_debounce_config *config); /** * @returns whether the switch is either latched as pressed or it is potentially * pressed but the debouncer has not yet made a decision. If this returns true, * the kscan driver should continue to poll quickly. */ -bool debounce_is_active(const struct debounce_state *state); +bool zmk_debounce_is_active(const struct zmk_debounce_state *state); /** * @returns whether the switch is latched as pressed. */ -bool debounce_is_pressed(const struct debounce_state *state); +bool zmk_debounce_is_pressed(const struct zmk_debounce_state *state); /** * @returns whether the pressed state of the switch changed in the last call to * debounce_update. */ -bool debounce_get_changed(const struct debounce_state *state); +bool zmk_debounce_get_changed(const struct zmk_debounce_state *state); diff --git a/app/module/lib/CMakeLists.txt b/app/module/lib/CMakeLists.txt new file mode 100644 index 00000000000..146b3637b68 --- /dev/null +++ b/app/module/lib/CMakeLists.txt @@ -0,0 +1,2 @@ + +add_subdirectory_ifdef(CONFIG_ZMK_DEBOUNCE zmk_debounce) \ No newline at end of file diff --git a/app/module/lib/Kconfig b/app/module/lib/Kconfig new file mode 100644 index 00000000000..8f2f06017d3 --- /dev/null +++ b/app/module/lib/Kconfig @@ -0,0 +1,2 @@ + +rsource "zmk_debounce/Kconfig" \ No newline at end of file diff --git a/app/module/lib/zmk_debounce/CMakeLists.txt b/app/module/lib/zmk_debounce/CMakeLists.txt new file mode 100644 index 00000000000..0a65dde1109 --- /dev/null +++ b/app/module/lib/zmk_debounce/CMakeLists.txt @@ -0,0 +1,3 @@ + +zephyr_library() +zephyr_library_sources(debounce.c) \ No newline at end of file diff --git a/app/module/lib/zmk_debounce/Kconfig b/app/module/lib/zmk_debounce/Kconfig new file mode 100644 index 00000000000..cd0321e8569 --- /dev/null +++ b/app/module/lib/zmk_debounce/Kconfig @@ -0,0 +1,3 @@ + +config ZMK_DEBOUNCE + bool "Debounce Support" \ No newline at end of file diff --git a/app/module/drivers/kscan/debounce.c b/app/module/lib/zmk_debounce/debounce.c similarity index 62% rename from app/module/drivers/kscan/debounce.c rename to app/module/lib/zmk_debounce/debounce.c index b38782267e8..6f4885b745c 100644 --- a/app/module/drivers/kscan/debounce.c +++ b/app/module/lib/zmk_debounce/debounce.c @@ -4,14 +4,14 @@ * SPDX-License-Identifier: MIT */ -#include "debounce.h" +#include -static uint32_t get_threshold(const struct debounce_state *state, - const struct debounce_config *config) { +static uint32_t get_threshold(const struct zmk_debounce_state *state, + const struct zmk_debounce_config *config) { return state->pressed ? config->debounce_release_ms : config->debounce_press_ms; } -static void increment_counter(struct debounce_state *state, const int elapsed_ms) { +static void increment_counter(struct zmk_debounce_state *state, const int elapsed_ms) { if (state->counter + elapsed_ms > DEBOUNCE_COUNTER_MAX) { state->counter = DEBOUNCE_COUNTER_MAX; } else { @@ -19,7 +19,7 @@ static void increment_counter(struct debounce_state *state, const int elapsed_ms } } -static void decrement_counter(struct debounce_state *state, const int elapsed_ms) { +static void decrement_counter(struct zmk_debounce_state *state, const int elapsed_ms) { if (state->counter < elapsed_ms) { state->counter = 0; } else { @@ -27,8 +27,8 @@ static void decrement_counter(struct debounce_state *state, const int elapsed_ms } } -void debounce_update(struct debounce_state *state, const bool active, const int elapsed_ms, - const struct debounce_config *config) { +void zmk_debounce_update(struct zmk_debounce_state *state, const bool active, const int elapsed_ms, + const struct zmk_debounce_config *config) { // This uses a variation of the integrator debouncing described at // https://www.kennethkuhn.com/electronics/debounce.c // Every update where "active" does not match the current state, we increment @@ -53,10 +53,10 @@ void debounce_update(struct debounce_state *state, const bool active, const int state->changed = true; } -bool debounce_is_active(const struct debounce_state *state) { +bool zmk_debounce_is_active(const struct zmk_debounce_state *state) { return state->pressed || state->counter > 0; } -bool debounce_is_pressed(const struct debounce_state *state) { return state->pressed; } +bool zmk_debounce_is_pressed(const struct zmk_debounce_state *state) { return state->pressed; } -bool debounce_get_changed(const struct debounce_state *state) { return state->changed; } \ No newline at end of file +bool zmk_debounce_get_changed(const struct zmk_debounce_state *state) { return state->changed; } \ No newline at end of file From 28ce23d4891eee3a1ef0a0d8187afe233d05cf81 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Thu, 14 Sep 2023 23:43:47 -0700 Subject: [PATCH 76/76] chore(tests): Move to proper header name. --- app/tests/combo/combos-and-holdtaps-0/native_posix_64.keymap | 2 +- app/tests/combo/combos-and-holdtaps-1/native_posix_64.keymap | 2 +- app/tests/combo/combos-and-holdtaps-2/native_posix_64.keymap | 2 +- app/tests/combo/combos-and-holdtaps-3/native_posix_64.keymap | 2 +- app/tests/combo/combos-and-holdtaps-4/native_posix_64.keymap | 2 +- app/tests/combo/layer-filter-0/native_posix_64.keymap | 2 +- app/tests/combo/layer-filter-1/native_posix_64.keymap | 2 +- app/tests/combo/multiple-timeouts/native_posix_64.keymap | 2 +- app/tests/combo/overlapping-combos-0/native_posix_64.keymap | 2 +- app/tests/combo/overlapping-combos-1/native_posix_64.keymap | 2 +- app/tests/combo/overlapping-combos-2/native_posix_64.keymap | 2 +- app/tests/combo/overlapping-combos-3/native_posix_64.keymap | 2 +- .../combo/partially-overlapping-combos/native_posix_64.keymap | 2 +- .../press-release-long-combo-complete/native_posix_64.keymap | 2 +- .../press-release-long-combo-incomplete/native_posix_64.keymap | 2 +- .../native_posix_64.keymap | 2 +- app/tests/combo/press-release/native_posix_64.keymap | 2 +- app/tests/combo/press-timeout/native_posix_64.keymap | 2 +- .../press1-press2-release1-release2/native_posix_64.keymap | 2 +- .../press1-press2-release2-release1/native_posix_64.keymap | 2 +- .../press1-release1-press2-release2/native_posix_64.keymap | 2 +- app/tests/combo/slowrelease-disabled/native_posix_64.keymap | 2 +- app/tests/combo/slowrelease-enabled/native_posix_64.keymap | 2 +- app/tests/gresc/gresc-press-release/native_posix_64.keymap | 2 +- app/tests/gresc/gresc-two-instances/native_posix_64.keymap | 2 +- .../kp-hyper-dn-a-dn-a-up-hyper-up/native_posix_64.keymap | 2 +- app/tests/sticky-keys/10-sl-sl-kp/native_posix_64.keymap | 2 +- .../sticky-keys/2-sl-dn-up-kcdn-kcup/native_posix_64.keymap | 2 +- app/tests/to-layer/behavior_keymap.dtsi | 2 +- app/tests/to-layer/normal/native_posix_64.keymap | 2 +- 30 files changed, 30 insertions(+), 30 deletions(-) diff --git a/app/tests/combo/combos-and-holdtaps-0/native_posix_64.keymap b/app/tests/combo/combos-and-holdtaps-0/native_posix_64.keymap index e6754b71128..3438f9bc77d 100644 --- a/app/tests/combo/combos-and-holdtaps-0/native_posix_64.keymap +++ b/app/tests/combo/combos-and-holdtaps-0/native_posix_64.keymap @@ -1,6 +1,6 @@ #include #include -#include +#include &mt { flavor = "hold-preferred"; diff --git a/app/tests/combo/combos-and-holdtaps-1/native_posix_64.keymap b/app/tests/combo/combos-and-holdtaps-1/native_posix_64.keymap index 9538243291c..9120e8c3b4a 100644 --- a/app/tests/combo/combos-and-holdtaps-1/native_posix_64.keymap +++ b/app/tests/combo/combos-and-holdtaps-1/native_posix_64.keymap @@ -1,6 +1,6 @@ #include #include -#include +#include &mt { flavor = "hold-preferred"; diff --git a/app/tests/combo/combos-and-holdtaps-2/native_posix_64.keymap b/app/tests/combo/combos-and-holdtaps-2/native_posix_64.keymap index d6d187e2046..a227fe4c91f 100644 --- a/app/tests/combo/combos-and-holdtaps-2/native_posix_64.keymap +++ b/app/tests/combo/combos-and-holdtaps-2/native_posix_64.keymap @@ -1,6 +1,6 @@ #include #include -#include +#include &mt { flavor = "hold-preferred"; diff --git a/app/tests/combo/combos-and-holdtaps-3/native_posix_64.keymap b/app/tests/combo/combos-and-holdtaps-3/native_posix_64.keymap index f1c7eee7087..4fbf24071e6 100644 --- a/app/tests/combo/combos-and-holdtaps-3/native_posix_64.keymap +++ b/app/tests/combo/combos-and-holdtaps-3/native_posix_64.keymap @@ -1,6 +1,6 @@ #include #include -#include +#include &mt { flavor = "hold-preferred"; diff --git a/app/tests/combo/combos-and-holdtaps-4/native_posix_64.keymap b/app/tests/combo/combos-and-holdtaps-4/native_posix_64.keymap index 134b77dfa34..59f4391f288 100644 --- a/app/tests/combo/combos-and-holdtaps-4/native_posix_64.keymap +++ b/app/tests/combo/combos-and-holdtaps-4/native_posix_64.keymap @@ -1,6 +1,6 @@ #include #include -#include +#include #define ZMK_COMBO(name, combo_bindings, keypos, combo_term) \ diff --git a/app/tests/combo/layer-filter-0/native_posix_64.keymap b/app/tests/combo/layer-filter-0/native_posix_64.keymap index 8d94872b658..68077849a34 100644 --- a/app/tests/combo/layer-filter-0/native_posix_64.keymap +++ b/app/tests/combo/layer-filter-0/native_posix_64.keymap @@ -1,6 +1,6 @@ #include #include -#include +#include /* it is useful to set timeout to a large value when attaching a debugger. */ #define TIMEOUT (60*60*1000) diff --git a/app/tests/combo/layer-filter-1/native_posix_64.keymap b/app/tests/combo/layer-filter-1/native_posix_64.keymap index 96eccea4ea8..a11b86ad4d9 100644 --- a/app/tests/combo/layer-filter-1/native_posix_64.keymap +++ b/app/tests/combo/layer-filter-1/native_posix_64.keymap @@ -1,6 +1,6 @@ #include #include -#include +#include /* it is useful to set timeout to a large value when attaching a debugger. */ #define TIMEOUT (60*60*1000) diff --git a/app/tests/combo/multiple-timeouts/native_posix_64.keymap b/app/tests/combo/multiple-timeouts/native_posix_64.keymap index d2176390403..a2edc32fcc3 100644 --- a/app/tests/combo/multiple-timeouts/native_posix_64.keymap +++ b/app/tests/combo/multiple-timeouts/native_posix_64.keymap @@ -1,6 +1,6 @@ #include #include -#include +#include / { combos { diff --git a/app/tests/combo/overlapping-combos-0/native_posix_64.keymap b/app/tests/combo/overlapping-combos-0/native_posix_64.keymap index e82846652d3..e89a3f22d33 100644 --- a/app/tests/combo/overlapping-combos-0/native_posix_64.keymap +++ b/app/tests/combo/overlapping-combos-0/native_posix_64.keymap @@ -1,6 +1,6 @@ #include #include -#include +#include /* combo 0 timeout inf diff --git a/app/tests/combo/overlapping-combos-1/native_posix_64.keymap b/app/tests/combo/overlapping-combos-1/native_posix_64.keymap index a695a388c66..4b0166bee15 100644 --- a/app/tests/combo/overlapping-combos-1/native_posix_64.keymap +++ b/app/tests/combo/overlapping-combos-1/native_posix_64.keymap @@ -1,6 +1,6 @@ #include #include -#include +#include /* combo 01 timeout 50 diff --git a/app/tests/combo/overlapping-combos-2/native_posix_64.keymap b/app/tests/combo/overlapping-combos-2/native_posix_64.keymap index 6bf0e7100cd..5c38bcfc403 100644 --- a/app/tests/combo/overlapping-combos-2/native_posix_64.keymap +++ b/app/tests/combo/overlapping-combos-2/native_posix_64.keymap @@ -1,6 +1,6 @@ #include #include -#include +#include /* combo 01 timeout 100 diff --git a/app/tests/combo/overlapping-combos-3/native_posix_64.keymap b/app/tests/combo/overlapping-combos-3/native_posix_64.keymap index 0a2f5ee137f..48e3397f4a6 100644 --- a/app/tests/combo/overlapping-combos-3/native_posix_64.keymap +++ b/app/tests/combo/overlapping-combos-3/native_posix_64.keymap @@ -1,6 +1,6 @@ #include #include -#include +#include /* combo 12 timeout 100 diff --git a/app/tests/combo/partially-overlapping-combos/native_posix_64.keymap b/app/tests/combo/partially-overlapping-combos/native_posix_64.keymap index 900c4af3f1e..55e8f1e77b6 100644 --- a/app/tests/combo/partially-overlapping-combos/native_posix_64.keymap +++ b/app/tests/combo/partially-overlapping-combos/native_posix_64.keymap @@ -1,6 +1,6 @@ #include #include -#include +#include / { combos { diff --git a/app/tests/combo/press-release-long-combo-complete/native_posix_64.keymap b/app/tests/combo/press-release-long-combo-complete/native_posix_64.keymap index dac0bd5ca4c..da2e9483ff7 100644 --- a/app/tests/combo/press-release-long-combo-complete/native_posix_64.keymap +++ b/app/tests/combo/press-release-long-combo-complete/native_posix_64.keymap @@ -1,6 +1,6 @@ #include #include -#include +#include / { combos { diff --git a/app/tests/combo/press-release-long-combo-incomplete/native_posix_64.keymap b/app/tests/combo/press-release-long-combo-incomplete/native_posix_64.keymap index 19bad1d0d1d..b1494cecf20 100644 --- a/app/tests/combo/press-release-long-combo-incomplete/native_posix_64.keymap +++ b/app/tests/combo/press-release-long-combo-incomplete/native_posix_64.keymap @@ -1,6 +1,6 @@ #include #include -#include +#include / { combos { diff --git a/app/tests/combo/press-release-long-combo-wrong-last-key/native_posix_64.keymap b/app/tests/combo/press-release-long-combo-wrong-last-key/native_posix_64.keymap index 2eb6271e2f0..8769286413b 100644 --- a/app/tests/combo/press-release-long-combo-wrong-last-key/native_posix_64.keymap +++ b/app/tests/combo/press-release-long-combo-wrong-last-key/native_posix_64.keymap @@ -1,6 +1,6 @@ #include #include -#include +#include / { combos { diff --git a/app/tests/combo/press-release/native_posix_64.keymap b/app/tests/combo/press-release/native_posix_64.keymap index 6bd432f9c86..26cd241b0bb 100644 --- a/app/tests/combo/press-release/native_posix_64.keymap +++ b/app/tests/combo/press-release/native_posix_64.keymap @@ -1,6 +1,6 @@ #include #include -#include +#include / { combos { diff --git a/app/tests/combo/press-timeout/native_posix_64.keymap b/app/tests/combo/press-timeout/native_posix_64.keymap index 6ca6487ba93..a71de45a7d2 100644 --- a/app/tests/combo/press-timeout/native_posix_64.keymap +++ b/app/tests/combo/press-timeout/native_posix_64.keymap @@ -1,6 +1,6 @@ #include #include -#include +#include / { combos { diff --git a/app/tests/combo/press1-press2-release1-release2/native_posix_64.keymap b/app/tests/combo/press1-press2-release1-release2/native_posix_64.keymap index 9a395a41468..2e0a67a3e7f 100644 --- a/app/tests/combo/press1-press2-release1-release2/native_posix_64.keymap +++ b/app/tests/combo/press1-press2-release1-release2/native_posix_64.keymap @@ -1,6 +1,6 @@ #include #include -#include +#include / { combos { diff --git a/app/tests/combo/press1-press2-release2-release1/native_posix_64.keymap b/app/tests/combo/press1-press2-release2-release1/native_posix_64.keymap index 86ca3931dce..8d4838eb511 100644 --- a/app/tests/combo/press1-press2-release2-release1/native_posix_64.keymap +++ b/app/tests/combo/press1-press2-release2-release1/native_posix_64.keymap @@ -1,6 +1,6 @@ #include #include -#include +#include / { combos { diff --git a/app/tests/combo/press1-release1-press2-release2/native_posix_64.keymap b/app/tests/combo/press1-release1-press2-release2/native_posix_64.keymap index 650895784ae..9c75e5705b1 100644 --- a/app/tests/combo/press1-release1-press2-release2/native_posix_64.keymap +++ b/app/tests/combo/press1-release1-press2-release2/native_posix_64.keymap @@ -1,6 +1,6 @@ #include #include -#include +#include / { combos { diff --git a/app/tests/combo/slowrelease-disabled/native_posix_64.keymap b/app/tests/combo/slowrelease-disabled/native_posix_64.keymap index 832e9705897..46b35be02ee 100644 --- a/app/tests/combo/slowrelease-disabled/native_posix_64.keymap +++ b/app/tests/combo/slowrelease-disabled/native_posix_64.keymap @@ -1,6 +1,6 @@ #include #include -#include +#include / { combos { diff --git a/app/tests/combo/slowrelease-enabled/native_posix_64.keymap b/app/tests/combo/slowrelease-enabled/native_posix_64.keymap index 7fdb012ed15..d64876da557 100644 --- a/app/tests/combo/slowrelease-enabled/native_posix_64.keymap +++ b/app/tests/combo/slowrelease-enabled/native_posix_64.keymap @@ -1,6 +1,6 @@ #include #include -#include +#include / { combos { diff --git a/app/tests/gresc/gresc-press-release/native_posix_64.keymap b/app/tests/gresc/gresc-press-release/native_posix_64.keymap index 5e3fac42c72..c472dd6d4ad 100644 --- a/app/tests/gresc/gresc-press-release/native_posix_64.keymap +++ b/app/tests/gresc/gresc-press-release/native_posix_64.keymap @@ -1,6 +1,6 @@ #include #include -#include +#include / { keymap { diff --git a/app/tests/gresc/gresc-two-instances/native_posix_64.keymap b/app/tests/gresc/gresc-two-instances/native_posix_64.keymap index 18f94da5771..14adcf45c8e 100644 --- a/app/tests/gresc/gresc-two-instances/native_posix_64.keymap +++ b/app/tests/gresc/gresc-two-instances/native_posix_64.keymap @@ -1,6 +1,6 @@ #include #include -#include +#include /* This test checks nothing breaks if two grave-escapes are pressed at the same time. diff --git a/app/tests/modifiers/explicit/kp-hyper-dn-a-dn-a-up-hyper-up/native_posix_64.keymap b/app/tests/modifiers/explicit/kp-hyper-dn-a-dn-a-up-hyper-up/native_posix_64.keymap index 621945a8218..72b218f510f 100644 --- a/app/tests/modifiers/explicit/kp-hyper-dn-a-dn-a-up-hyper-up/native_posix_64.keymap +++ b/app/tests/modifiers/explicit/kp-hyper-dn-a-dn-a-up-hyper-up/native_posix_64.keymap @@ -1,6 +1,6 @@ #include #include -#include +#include &kscan { diff --git a/app/tests/sticky-keys/10-sl-sl-kp/native_posix_64.keymap b/app/tests/sticky-keys/10-sl-sl-kp/native_posix_64.keymap index 23ceeeb6161..bafdbe38d39 100644 --- a/app/tests/sticky-keys/10-sl-sl-kp/native_posix_64.keymap +++ b/app/tests/sticky-keys/10-sl-sl-kp/native_posix_64.keymap @@ -1,6 +1,6 @@ #include #include -#include +#include /* sticky layers should quick-release. diff --git a/app/tests/sticky-keys/2-sl-dn-up-kcdn-kcup/native_posix_64.keymap b/app/tests/sticky-keys/2-sl-dn-up-kcdn-kcup/native_posix_64.keymap index 390207515dd..38c8fb4c91c 100644 --- a/app/tests/sticky-keys/2-sl-dn-up-kcdn-kcup/native_posix_64.keymap +++ b/app/tests/sticky-keys/2-sl-dn-up-kcdn-kcup/native_posix_64.keymap @@ -1,6 +1,6 @@ #include #include -#include +#include /* sticky layers should quick-release. diff --git a/app/tests/to-layer/behavior_keymap.dtsi b/app/tests/to-layer/behavior_keymap.dtsi index 663e897d74b..7dc857fe143 100644 --- a/app/tests/to-layer/behavior_keymap.dtsi +++ b/app/tests/to-layer/behavior_keymap.dtsi @@ -1,6 +1,6 @@ #include #include -#include +#include / { keymap { diff --git a/app/tests/to-layer/normal/native_posix_64.keymap b/app/tests/to-layer/normal/native_posix_64.keymap index 4cb23809452..6ccc9088bb2 100644 --- a/app/tests/to-layer/normal/native_posix_64.keymap +++ b/app/tests/to-layer/normal/native_posix_64.keymap @@ -1,6 +1,6 @@ #include #include -#include +#include #include "../behavior_keymap.dtsi" // Press key A