From d52bb040904092c48286faf71ebe19d7e0cece03 Mon Sep 17 00:00:00 2001 From: Pete Johanson Date: Sat, 7 Sep 2024 00:12:45 -0600 Subject: [PATCH 001/415] Revert "feat: Split physical layout selection sync." This reverts commit 03b5b38bc4b81b68787bb052613e771279fa049c. --- app/include/zmk/physical_layouts.h | 7 ---- app/include/zmk/split/bluetooth/uuid.h | 1 - app/src/physical_layouts.c | 11 +---- app/src/split/bluetooth/central.c | 57 +------------------------- app/src/split/bluetooth/service.c | 43 +------------------ 5 files changed, 3 insertions(+), 116 deletions(-) diff --git a/app/include/zmk/physical_layouts.h b/app/include/zmk/physical_layouts.h index 33004af7..e78602e3 100644 --- a/app/include/zmk/physical_layouts.h +++ b/app/include/zmk/physical_layouts.h @@ -8,13 +8,6 @@ #include #include -#include - -struct zmk_physical_layout_selection_changed { - uint8_t selection; -}; - -ZMK_EVENT_DECLARE(zmk_physical_layout_selection_changed); struct zmk_key_physical_attrs { int16_t width; diff --git a/app/include/zmk/split/bluetooth/uuid.h b/app/include/zmk/split/bluetooth/uuid.h index 4a653c73..dccdfc80 100644 --- a/app/include/zmk/split/bluetooth/uuid.h +++ b/app/include/zmk/split/bluetooth/uuid.h @@ -18,4 +18,3 @@ #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) #define ZMK_SPLIT_BT_UPDATE_HID_INDICATORS_UUID ZMK_BT_SPLIT_UUID(0x00000004) -#define ZMK_SPLIT_BT_SELECT_PHYS_LAYOUT_UUID ZMK_BT_SPLIT_UUID(0x00000005) diff --git a/app/src/physical_layouts.c b/app/src/physical_layouts.c index 26bb3ef4..00cfa29e 100644 --- a/app/src/physical_layouts.c +++ b/app/src/physical_layouts.c @@ -22,8 +22,6 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #include #include -ZMK_EVENT_IMPL(zmk_physical_layout_selection_changed); - #define DT_DRV_COMPAT zmk_physical_layout #if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) @@ -229,14 +227,7 @@ int zmk_physical_layouts_select(uint8_t index) { return -EINVAL; } - int ret = zmk_physical_layouts_select_layout(layouts[index]); - - if (ret >= 0) { - raise_zmk_physical_layout_selection_changed( - (struct zmk_physical_layout_selection_changed){.selection = index}); - } - - return ret; + return zmk_physical_layouts_select_layout(layouts[index]); } int zmk_physical_layouts_get_selected(void) { diff --git a/app/src/split/bluetooth/central.c b/app/src/split/bluetooth/central.c index f5e7b818..0f4cd78b 100644 --- a/app/src/split/bluetooth/central.c +++ b/app/src/split/bluetooth/central.c @@ -30,7 +30,6 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #include #include #include -#include static int start_scanning(void); @@ -57,7 +56,6 @@ struct peripheral_slot { #if IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS) uint16_t update_hid_indicators; #endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS) - uint16_t selected_physical_layout_handle; uint8_t position_state[POSITION_STATE_DATA_LEN]; uint8_t changed_positions[POSITION_STATE_DATA_LEN]; }; @@ -143,7 +141,6 @@ int release_peripheral_slot(int index) { // Clean up previously discovered handles; slot->subscribe_params.value_handle = 0; slot->run_behavior_handle = 0; - slot->selected_physical_layout_handle = 0; #if IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS) slot->update_hid_indicators = 0; #endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS) @@ -395,28 +392,6 @@ static int split_central_subscribe(struct bt_conn *conn, struct bt_gatt_subscrib return err; } -static int update_peripheral_selected_layout(struct peripheral_slot *slot, uint8_t layout_idx) { - if (slot->state != PERIPHERAL_SLOT_STATE_CONNECTED) { - return -ENOTCONN; - } - - if (slot->selected_physical_layout_handle == 0) { - // It appears that sometimes the peripheral is considered connected - // before the GATT characteristics have been discovered. If this is - // the case, the selected_physical_layout_handle will not yet be set. - return -EAGAIN; - } - - int err = bt_gatt_write_without_response(slot->conn, slot->selected_physical_layout_handle, - &layout_idx, sizeof(layout_idx), true); - - if (err < 0) { - LOG_ERR("Failed to write physical layout index to peripheral (err %d)", err); - } - - return err; -} - static uint8_t split_central_chrc_discovery_func(struct bt_conn *conn, const struct bt_gatt_attr *attr, struct bt_gatt_discover_params *params) { @@ -467,11 +442,6 @@ static uint8_t split_central_chrc_discovery_func(struct bt_conn *conn, slot->discover_params.uuid = NULL; slot->discover_params.start_handle = attr->handle + 2; slot->run_behavior_handle = bt_gatt_attr_value_handle(attr); - } else if (!bt_uuid_cmp(((struct bt_gatt_chrc *)attr->user_data)->uuid, - BT_UUID_DECLARE_128(ZMK_SPLIT_BT_SELECT_PHYS_LAYOUT_UUID))) { - LOG_DBG("Found select physical layout handle"); - slot->selected_physical_layout_handle = bt_gatt_attr_value_handle(attr); - update_peripheral_selected_layout(slot, zmk_physical_layouts_get_selected()); #if IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS) } else if (!bt_uuid_cmp(((struct bt_gatt_chrc *)attr->user_data)->uuid, BT_UUID_DECLARE_128(ZMK_SPLIT_BT_UPDATE_HID_INDICATORS_UUID))) { @@ -497,8 +467,7 @@ static uint8_t split_central_chrc_discovery_func(struct bt_conn *conn, #endif /* IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_CENTRAL_BATTERY_LEVEL_FETCHING) */ } - bool subscribed = slot->run_behavior_handle && slot->subscribe_params.value_handle && - slot->selected_physical_layout_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; @@ -928,27 +897,3 @@ static int zmk_split_bt_central_init(void) { } SYS_INIT(zmk_split_bt_central_init, APPLICATION, CONFIG_ZMK_BLE_INIT_PRIORITY); - -static void update_peripherals_selected_physical_layout(struct k_work *_work) { - uint8_t layout_idx = zmk_physical_layouts_get_selected(); - for (int i = 0; i < ZMK_SPLIT_BLE_PERIPHERAL_COUNT; i++) { - if (peripherals[i].state != PERIPHERAL_SLOT_STATE_CONNECTED) { - continue; - } - - update_peripheral_selected_layout(&peripherals[i], layout_idx); - } -} - -K_WORK_DEFINE(update_peripherals_selected_layouts_work, - update_peripherals_selected_physical_layout); - -static int zmk_split_bt_central_listener_cb(const zmk_event_t *eh) { - if (as_zmk_physical_layout_selection_changed(eh)) { - k_work_submit(&update_peripherals_selected_layouts_work); - } - return ZMK_EV_EVENT_BUBBLE; -} - -ZMK_LISTENER(zmk_split_bt_central, zmk_split_bt_central_listener_cb); -ZMK_SUBSCRIPTION(zmk_split_bt_central, zmk_physical_layout_selection_changed); \ No newline at end of file diff --git a/app/src/split/bluetooth/service.c b/app/src/split/bluetooth/service.c index 9529d516..505eb363 100644 --- a/app/src/split/bluetooth/service.c +++ b/app/src/split/bluetooth/service.c @@ -19,7 +19,6 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #include #include #include -#include #include #include @@ -139,42 +138,6 @@ static ssize_t split_svc_update_indicators(struct bt_conn *conn, const struct bt #endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS) -static uint8_t selected_phys_layout = 0; - -static void split_svc_select_phys_layout_callback(struct k_work *work) { - LOG_DBG("Selecting physical layout after GATT write of %d", selected_phys_layout); - zmk_physical_layouts_select(selected_phys_layout); -} - -static K_WORK_DEFINE(split_svc_select_phys_layout_work, split_svc_select_phys_layout_callback); - -static ssize_t split_svc_select_phys_layout(struct bt_conn *conn, const struct bt_gatt_attr *attr, - const void *buf, uint16_t len, uint16_t offset, - uint8_t flags) { - if (offset + len > sizeof(uint8_t) || len == 0) { - return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET); - } - - selected_phys_layout = *(uint8_t *)buf; - - k_work_submit(&split_svc_select_phys_layout_work); - - return len; -} - -static ssize_t split_svc_get_selected_phys_layout(struct bt_conn *conn, - const struct bt_gatt_attr *attrs, void *buf, - uint16_t len, uint16_t offset) { - int selected_ret = zmk_physical_layouts_get_selected(); - if (selected_ret < 0) { - return BT_GATT_ERR(BT_ATT_ERR_VALUE_NOT_ALLOWED); - } - - uint8_t selected = (uint8_t)selected_ret; - - return bt_gatt_attr_read(conn, attrs, buf, len, offset, &selected, sizeof(selected)); -} - BT_GATT_SERVICE_DEFINE( split_svc, BT_GATT_PRIMARY_SERVICE(BT_UUID_DECLARE_128(ZMK_SPLIT_BT_SERVICE_UUID)), BT_GATT_CHARACTERISTIC(BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_POSITION_STATE_UUID), @@ -197,11 +160,7 @@ BT_GATT_SERVICE_DEFINE( BT_GATT_CHRC_WRITE_WITHOUT_RESP, BT_GATT_PERM_WRITE_ENCRYPT, NULL, split_svc_update_indicators, NULL), #endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS) - BT_GATT_CHARACTERISTIC(BT_UUID_DECLARE_128(ZMK_SPLIT_BT_SELECT_PHYS_LAYOUT_UUID), - BT_GATT_CHRC_WRITE | BT_GATT_CHRC_READ, - BT_GATT_PERM_WRITE_ENCRYPT | BT_GATT_PERM_READ_ENCRYPT, - split_svc_get_selected_phys_layout, split_svc_select_phys_layout, - NULL), ); +); K_THREAD_STACK_DEFINE(service_q_stack, CONFIG_ZMK_SPLIT_BLE_PERIPHERAL_STACK_SIZE); From f0319fde948d0bb3afd29b068370b25890fd272a Mon Sep 17 00:00:00 2001 From: Nicolas Munnich <98408764+Nick-Munnich@users.noreply.github.com> Date: Sat, 7 Sep 2024 13:19:01 +0200 Subject: [PATCH 002/415] docs(feat): Added a page on shift registers (#2452) Added a page on shift registers --------- Co-authored-by: Cem Aksoylar --- .../shift-register-daisy.png | Bin 0 -> 92887 bytes .../hardware-integration/shift-registers.md | 151 ++++++++++++++++++ docs/sidebars.js | 1 + 3 files changed, 152 insertions(+) create mode 100644 docs/docs/assets/hardware-integration/shift-register-daisy.png create mode 100644 docs/docs/development/hardware-integration/shift-registers.md diff --git a/docs/docs/assets/hardware-integration/shift-register-daisy.png b/docs/docs/assets/hardware-integration/shift-register-daisy.png new file mode 100644 index 0000000000000000000000000000000000000000..db4031a66e2cdff2e3b02c5d97ecc9be5908e307 GIT binary patch literal 92887 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 mZ|L#BsEk*0wno%{*lX3GAT8; + pinctrl-1 = <&spi2_sleep>; + pinctrl-names = "default", "sleep"; +}; +``` + +You will need to overwrite the pinctrl nodes to use your desired pins. Look through the devicetree files once again, this time looking for `spi2_default` and `spi2_sleep` (or the equivalently named nodes for your board). You should find nodes that look similar to below: + +```dts title="boards/arm/seeeduino_xiao_ble/seeeduino_xiao_ble-pinctrl.dtsi" +spi2_default: spi2_default { + group1 { + psels = , + , + ; + }; +}; + +spi2_sleep: spi2_sleep { + group1 { + psels = , + , + ; + low-power-enable; + }; +}; +``` + +Overwrite the pin definitions like so: + +```dts +&spi2_default { + group1 { + psels = , + ; + }; +}; + +&spi2_sleep { + group1 { + psels = , + ; + }; +}; +``` + +Note that for convenience, ZMK gives the `spi2` node of the Seeed Studio XIAO series the label `xiao_spi`. + +:::tip +If you are making a shield, add a `/boards/.overlay` file rather than editing the board's files directly. This will then be included in your board's definition when you build with your shield. +::: + +### Enable SPI + +Add the following line to `.defconfig`, inside of your device's `if` block: + +```kconfig title=".defconfig" +config SPI + default y +``` + +### Shift Register SPI Device + +To add your shift register as a SPI device, you'll need to overwrite your board's SPI configuration. For example, if your SPI bus has the node label `xiao_spi`, then you would add the following to your `.overlay`: + +```dts title=".overlay" +&xiao_spi { + status = "okay"; + cs-gpios = <&xiao_d 9 GPIO_ACTIVE_LOW>; + shifter: 595@0 { + compatible = "zmk,gpio-595"; + status = "okay"; + gpio-controller; + spi-max-frequency = <200000>; + reg = <0>; + #gpio-cells = <2>; + ngpios = <8>; + }; +}; +``` + +If there is more than one device on the SPI bus, you will need to add additional pins to the `cs-gpios` phandle array - one for each device. The `@0` number marks the index of the `cs-gpios` pin used to control a device. If you have daisy chained multiple shift registers, you'll also want to increase the number of GPIOs that the shift register provides by editing the `ngpios` node - set this to your number of output pins (should be one of 8, 16, 24, 32). You may also need to increase `spi-max-frequency` to a higher value if you have daisy chained shift registers, otherwise quick key presses may on occasion not trigger. + +### Using Shift Register Pins In Kscan + +Once all of this is set up, you can refer to pins from the shift register using `&shifter X` where X is the pin number. Use this to define your kscan, for example: + +```dts title=".overlay" +kscan0: kscan_0 { + compatible = "zmk,kscan-gpio-matrix"; + diode-direction = "col2row"; + col-gpios + = <&shifter 7 GPIO_ACTIVE_HIGH> + , <&shifter 6 GPIO_ACTIVE_HIGH> + , <&shifter 5 GPIO_ACTIVE_HIGH> + , <&shifter 4 GPIO_ACTIVE_HIGH> + , <&shifter 3 GPIO_ACTIVE_HIGH> + , <&shifter 2 GPIO_ACTIVE_HIGH> + ; +}; +``` diff --git a/docs/sidebars.js b/docs/sidebars.js index daff5c7f..8825746f 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -128,6 +128,7 @@ module.exports = { "development/hardware-integration/hardware-metadata-files", "development/hardware-integration/boards-shields-keymaps", "development/hardware-integration/studio-setup", + "development/hardware-integration/shift-registers", ], }, { From 1c48f64730a479115ae827c342c1063b2b8e93ca Mon Sep 17 00:00:00 2001 From: Nicolas Munnich <98408764+Nick-Munnich@users.noreply.github.com> Date: Sat, 7 Sep 2024 18:26:24 +0200 Subject: [PATCH 003/415] fix(docs): Fix broken anchor in Studio setup (#2465) --- docs/docs/development/hardware-integration/studio-setup.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/development/hardware-integration/studio-setup.md b/docs/docs/development/hardware-integration/studio-setup.md index d00f7de2..dfa80020 100644 --- a/docs/docs/development/hardware-integration/studio-setup.md +++ b/docs/docs/development/hardware-integration/studio-setup.md @@ -15,7 +15,7 @@ to properly to display the physical layouts available for the particular keyboar # Physical Layout Positions -Physical layouts are described as part of the [new shield guide](./new-shield.mdx#physical-layouts) with the exception of the `keys` property that is required for ZMK Studio support. This is used to describe the physical attributes of each key position present in that layout and its items are listed in the same order as keymap bindings, matrix transforms, etc. The properties available are: +Physical layouts are described as part of the [new shield guide](./new-shield.mdx#physical-layout) with the exception of the `keys` property that is required for ZMK Studio support. This is used to describe the physical attributes of each key position present in that layout and its items are listed in the same order as keymap bindings, matrix transforms, etc. The properties available are: | Property | Type | Description | Unit | | ---------- | -------- | ------------------------------------ | ------------------------------------------------------- | From 6b4d591c3792c89653e88772f18a3b063fb16d27 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Mon, 9 Sep 2024 11:07:15 -0600 Subject: [PATCH 004/415] fix(bt): Fix compilation failure for clearing bonds. * Refactor broke the build when clearing bonds on start. --- app/src/ble.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/ble.c b/app/src/ble.c index 776730fe..2308de52 100644 --- a/app/src/ble.c +++ b/app/src/ble.c @@ -659,7 +659,7 @@ static int zmk_ble_complete_startup(void) { char setting_name[15]; sprintf(setting_name, "ble/profiles/%d", i); - err = settings_delete(setting_name); + int err = settings_delete(setting_name); if (err) { LOG_ERR("Failed to delete setting: %d", err); } From 6e03a0bb67d0b2fc12004b109cbbd8c5c1448a21 Mon Sep 17 00:00:00 2001 From: Jim Aho Date: Thu, 12 Sep 2024 22:57:19 +0200 Subject: [PATCH 005/415] fix(docs): Fix wording in layers section in keymaps (#2474) --- docs/docs/keymaps/index.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/keymaps/index.mdx b/docs/docs/keymaps/index.mdx index 0409cecb..6a5c9698 100644 --- a/docs/docs/keymaps/index.mdx +++ b/docs/docs/keymaps/index.mdx @@ -143,7 +143,7 @@ Each layer of your keymap will be nested under the keymap node. Here is an examp Each layer should have: -1. A `bindings` property this will be a list of [behavior bindings](behaviors/index.mdx), one for each key position for the keyboard. +1. A `bindings` property that will be a list of [behavior bindings](behaviors/index.mdx), one for each key position for the keyboard. 1. (Optional) A `sensor-bindings` property that will be a list of behavior bindings for each sensor on the keyboard. (Currently, only encoders are supported as sensor hardware, but in the future devices like trackpoints would be supported the same way) 1. (Optional) A `display-name` property that is a string used by certain features, such as the layer status display widget. From 82a22d731bdd6719844437cddaffc9773b538fcc Mon Sep 17 00:00:00 2001 From: Maxime Vincent Date: Wed, 29 May 2024 14:03:40 +0200 Subject: [PATCH 006/415] pre-commit: use versioned clang-format hook (v18.1.8) --- .pre-commit-config.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e0666ea8..352ad723 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,10 +5,11 @@ repos: hooks: - id: remove-tabs exclude: "vendor-prefixes\\.txt$" - - repo: https://github.com/pocc/pre-commit-hooks - rev: v1.3.5 + - repo: https://github.com/pre-commit/mirrors-clang-format + rev: v18.1.8 hooks: - id: clang-format + types_or: [c++, c] args: - -i - repo: https://github.com/pre-commit/mirrors-prettier From 67d595f29f7495ca32fa8e413e74e22d23bb993a Mon Sep 17 00:00:00 2001 From: Maxime Vincent Date: Fri, 13 Sep 2024 21:39:26 +0200 Subject: [PATCH 007/415] pre-commit: re-format using clang-format hook (v18.1.8) --- .../arm/corneish_zen/widgets/battery_status.c | 2 +- .../nice_view/widgets/peripheral_status.c | 2 +- app/boards/shields/nice_view/widgets/status.c | 2 +- app/include/drivers/behavior.h | 13 +++++++--- app/include/zmk/virtual_key_position.h | 2 +- app/src/behaviors/behavior_caps_word.c | 5 +--- app/src/behaviors/behavior_tap_dance.c | 2 +- app/src/display/widgets/battery_status.c | 2 +- app/src/endpoints.c | 4 +-- app/src/hid.c | 12 +++------ app/src/keymap.c | 13 +++++----- app/src/kscan_sideband_behaviors.c | 3 ++- app/src/physical_layouts.c | 4 ++- app/src/sensors.c | 26 +++++++------------ app/src/studio/rpc.c | 8 ++---- app/src/workqueue.c | 4 +-- 16 files changed, 45 insertions(+), 59 deletions(-) diff --git a/app/boards/arm/corneish_zen/widgets/battery_status.c b/app/boards/arm/corneish_zen/widgets/battery_status.c index 39b811b5..622e39df 100644 --- a/app/boards/arm/corneish_zen/widgets/battery_status.c +++ b/app/boards/arm/corneish_zen/widgets/battery_status.c @@ -68,7 +68,7 @@ void battery_status_update_cb(struct battery_status_state state) { static struct battery_status_state battery_status_get_state(const zmk_event_t *eh) { const struct zmk_battery_state_changed *ev = as_zmk_battery_state_changed(eh); - return (struct battery_status_state) { + return (struct battery_status_state){ .level = (ev != NULL) ? ev->state_of_charge : zmk_battery_state_of_charge(), #if IS_ENABLED(CONFIG_USB_DEVICE_STACK) .usb_present = zmk_usb_is_powered(), diff --git a/app/boards/shields/nice_view/widgets/peripheral_status.c b/app/boards/shields/nice_view/widgets/peripheral_status.c index b9da1996..e9002b33 100644 --- a/app/boards/shields/nice_view/widgets/peripheral_status.c +++ b/app/boards/shields/nice_view/widgets/peripheral_status.c @@ -71,7 +71,7 @@ static void battery_status_update_cb(struct battery_status_state state) { } static struct battery_status_state battery_status_get_state(const zmk_event_t *eh) { - return (struct battery_status_state) { + return (struct battery_status_state){ .level = zmk_battery_state_of_charge(), #if IS_ENABLED(CONFIG_USB_DEVICE_STACK) .usb_present = zmk_usb_is_powered(), diff --git a/app/boards/shields/nice_view/widgets/status.c b/app/boards/shields/nice_view/widgets/status.c index 061b7127..f5095cbf 100644 --- a/app/boards/shields/nice_view/widgets/status.c +++ b/app/boards/shields/nice_view/widgets/status.c @@ -212,7 +212,7 @@ static void battery_status_update_cb(struct battery_status_state state) { static struct battery_status_state battery_status_get_state(const zmk_event_t *eh) { const struct zmk_battery_state_changed *ev = as_zmk_battery_state_changed(eh); - return (struct battery_status_state) { + return (struct battery_status_state){ .level = (ev != NULL) ? ev->state_of_charge : zmk_battery_state_of_charge(), #if IS_ENABLED(CONFIG_USB_DEVICE_STACK) .usb_present = zmk_usb_is_powered(), diff --git a/app/include/drivers/behavior.h b/app/include/drivers/behavior.h index 7c99f04e..56c26a01 100644 --- a/app/include/drivers/behavior.h +++ b/app/include/drivers/behavior.h @@ -122,7 +122,9 @@ struct zmk_behavior_local_id_map { #if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA) #define ZMK_BEHAVIOR_METADATA_INITIALIZER(node_id) \ - { .display_name = DT_PROP_OR(node_id, display_name, DEVICE_DT_NAME(node_id)), } + { \ + .display_name = DT_PROP_OR(node_id, display_name, DEVICE_DT_NAME(node_id)), \ + } #else @@ -132,10 +134,15 @@ struct zmk_behavior_local_id_map { #endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA) #define ZMK_BEHAVIOR_REF_INITIALIZER(node_id, _dev) \ - { .device = _dev, .metadata = ZMK_BEHAVIOR_METADATA_INITIALIZER(node_id), } + { \ + .device = _dev, \ + .metadata = ZMK_BEHAVIOR_METADATA_INITIALIZER(node_id), \ + } #define ZMK_BEHAVIOR_LOCAL_ID_MAP_INITIALIZER(node_id, _dev) \ - { .device = _dev, } + { \ + .device = _dev, \ + } #define ZMK_BEHAVIOR_REF_DEFINE(name, node_id, _dev) \ static const STRUCT_SECTION_ITERABLE(zmk_behavior_ref, name) = \ diff --git a/app/include/zmk/virtual_key_position.h b/app/include/zmk/virtual_key_position.h index b8f20683..563f951e 100644 --- a/app/include/zmk/virtual_key_position.h +++ b/app/include/zmk/virtual_key_position.h @@ -17,7 +17,7 @@ /** * Gets the sensor number from the virtual key position. */ -#define ZMK_SENSOR_POSITION_FROM_VIRTUAL_KEY_POSITION(vkp) ((vkp)-ZMK_KEYMAP_LEN) +#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_caps_word.c b/app/src/behaviors/behavior_caps_word.c index bf74a4b3..c3255f12 100644 --- a/app/src/behaviors/behavior_caps_word.c +++ b/app/src/behaviors/behavior_caps_word.c @@ -169,10 +169,7 @@ static int behavior_caps_word_init(const struct device *dev) { #define CAPS_WORD_LABEL(i, _n) DT_INST_LABEL(i) #define PARSE_BREAK(i) \ - { \ - .page = ZMK_HID_USAGE_PAGE(i), .id = ZMK_HID_USAGE_ID(i), \ - .implicit_modifiers = SELECT_MODS(i) \ - } + {.page = ZMK_HID_USAGE_PAGE(i), .id = ZMK_HID_USAGE_ID(i), .implicit_modifiers = SELECT_MODS(i)} #define BREAK_ITEM(i, n) PARSE_BREAK(DT_INST_PROP_BY_IDX(n, continue_list, i)) diff --git a/app/src/behaviors/behavior_tap_dance.c b/app/src/behaviors/behavior_tap_dance.c index ce57b70f..61e75585 100644 --- a/app/src/behaviors/behavior_tap_dance.c +++ b/app/src/behaviors/behavior_tap_dance.c @@ -245,7 +245,7 @@ static int behavior_tap_dance_init(const struct device *dev) { #define _TRANSFORM_ENTRY(idx, node) ZMK_KEYMAP_EXTRACT_BINDING(idx, node) #define TRANSFORMED_BINDINGS(node) \ - { LISTIFY(DT_INST_PROP_LEN(node, bindings), _TRANSFORM_ENTRY, (, ), DT_DRV_INST(node)) } + {LISTIFY(DT_INST_PROP_LEN(node, bindings), _TRANSFORM_ENTRY, (, ), DT_DRV_INST(node))} #define KP_INST(n) \ static struct zmk_behavior_binding \ diff --git a/app/src/display/widgets/battery_status.c b/app/src/display/widgets/battery_status.c index bec6964b..22e73faf 100644 --- a/app/src/display/widgets/battery_status.c +++ b/app/src/display/widgets/battery_status.c @@ -65,7 +65,7 @@ void battery_status_update_cb(struct battery_status_state state) { static struct battery_status_state battery_status_get_state(const zmk_event_t *eh) { const struct zmk_battery_state_changed *ev = as_zmk_battery_state_changed(eh); - return (struct battery_status_state) { + return (struct battery_status_state){ .level = (ev != NULL) ? ev->state_of_charge : zmk_battery_state_of_charge(), #if IS_ENABLED(CONFIG_USB_DEVICE_STACK) .usb_present = zmk_usb_is_powered(), diff --git a/app/src/endpoints.c b/app/src/endpoints.c index 65243853..b17a6646 100644 --- a/app/src/endpoints.c +++ b/app/src/endpoints.c @@ -116,9 +116,7 @@ int zmk_endpoints_toggle_transport(void) { return zmk_endpoints_select_transport(new_transport); } -struct zmk_endpoint_instance zmk_endpoints_selected(void) { - return current_instance; -} +struct zmk_endpoint_instance zmk_endpoints_selected(void) { return current_instance; } static int send_keyboard_report(void) { switch (current_instance.transport) { diff --git a/app/src/hid.c b/app/src/hid.c index 24572ad3..df0715ee 100644 --- a/app/src/hid.c +++ b/app/src/hid.c @@ -435,18 +435,12 @@ void zmk_hid_mouse_clear(void) { memset(&mouse_report.body, 0, sizeof(mouse_repo #endif // IS_ENABLED(CONFIG_ZMK_MOUSE) -struct zmk_hid_keyboard_report *zmk_hid_get_keyboard_report(void) { - return &keyboard_report; -} +struct zmk_hid_keyboard_report *zmk_hid_get_keyboard_report(void) { return &keyboard_report; } -struct zmk_hid_consumer_report *zmk_hid_get_consumer_report(void) { - return &consumer_report; -} +struct zmk_hid_consumer_report *zmk_hid_get_consumer_report(void) { return &consumer_report; } #if IS_ENABLED(CONFIG_ZMK_MOUSE) -struct zmk_hid_mouse_report *zmk_hid_get_mouse_report(void) { - return &mouse_report; -} +struct zmk_hid_mouse_report *zmk_hid_get_mouse_report(void) { return &mouse_report; } #endif // IS_ENABLED(CONFIG_ZMK_MOUSE) diff --git a/app/src/keymap.c b/app/src/keymap.c index dabe338d..c9845479 100644 --- a/app/src/keymap.c +++ b/app/src/keymap.c @@ -40,11 +40,9 @@ static zmk_keymap_layer_id_t _zmk_keymap_layer_default = 0; #endif #define TRANSFORMED_LAYER(node) \ - { \ - COND_CODE_1( \ - DT_NODE_HAS_PROP(node, bindings), \ - (LISTIFY(DT_PROP_LEN(node, bindings), ZMK_KEYMAP_EXTRACT_BINDING, (, ), node)), ()) \ - } + {COND_CODE_1(DT_NODE_HAS_PROP(node, bindings), \ + (LISTIFY(DT_PROP_LEN(node, bindings), ZMK_KEYMAP_EXTRACT_BINDING, (, ), node)), \ + ())} #if ZMK_KEYMAP_HAS_SENSORS #define _TRANSFORM_SENSOR_ENTRY(idx, layer) \ @@ -841,11 +839,12 @@ static int keymap_handle_set(const char *name, size_t len, settings_read_cb read binding_setting.behavior_local_id); } - zmk_keymap[layer][key_position] = (struct zmk_behavior_binding) { + zmk_keymap[layer][key_position] = (struct zmk_behavior_binding){ #if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_LOCAL_IDS_IN_BINDINGS) .local_id = binding_setting.behavior_local_id, #endif - .behavior_dev = name, .param1 = binding_setting.param1, + .behavior_dev = name, + .param1 = binding_setting.param1, .param2 = binding_setting.param2, }; } diff --git a/app/src/kscan_sideband_behaviors.c b/app/src/kscan_sideband_behaviors.c index 602cae12..4ef5b052 100644 --- a/app/src/kscan_sideband_behaviors.c +++ b/app/src/kscan_sideband_behaviors.c @@ -183,7 +183,8 @@ static const struct kscan_driver_api ksbb_api = { #define ENTRY(e) \ { \ - .row = DT_PROP(e, row), .column = DT_PROP(e, column), \ + .row = DT_PROP(e, row), \ + .column = DT_PROP(e, column), \ .binding = ZMK_KEYMAP_EXTRACT_BINDING(0, e), \ } diff --git a/app/src/physical_layouts.c b/app/src/physical_layouts.c index 00cfa29e..a7f65078 100644 --- a/app/src/physical_layouts.c +++ b/app/src/physical_layouts.c @@ -139,7 +139,9 @@ struct zmk_kscan_event { uint32_t state; }; -static struct zmk_kscan_msg_processor { struct k_work work; } msg_processor; +static struct zmk_kscan_msg_processor { + struct k_work work; +} msg_processor; K_MSGQ_DEFINE(physical_layouts_kscan_msgq, sizeof(struct zmk_kscan_event), CONFIG_ZMK_KSCAN_EVENT_QUEUE_SIZE, 4); diff --git a/app/src/sensors.c b/app/src/sensors.c index 4dcda44d..90ea1903 100644 --- a/app/src/sensors.c +++ b/app/src/sensors.c @@ -26,28 +26,22 @@ struct sensors_item_cfg { }; #define _SENSOR_ITEM(idx, node) \ - { \ - .dev = DEVICE_DT_GET_OR_NULL(node), \ - .trigger = {.type = SENSOR_TRIG_DATA_READY, .chan = SENSOR_CHAN_ROTATION}, \ - .config = &configs[idx], .sensor_index = idx \ - } + {.dev = DEVICE_DT_GET_OR_NULL(node), \ + .trigger = {.type = SENSOR_TRIG_DATA_READY, .chan = SENSOR_CHAN_ROTATION}, \ + .config = &configs[idx], \ + .sensor_index = idx} #define SENSOR_ITEM(idx, _i) _SENSOR_ITEM(idx, 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)) \ - } + {.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, \ - CONFIG_ZMK_KEYMAP_SENSORS_DEFAULT_TRIGGERS_PER_ROTATION) \ - } + {.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 diff --git a/app/src/studio/rpc.c b/app/src/studio/rpc.c index 8dfb025d..bd980eb4 100644 --- a/app/src/studio/rpc.c +++ b/app/src/studio/rpc.c @@ -77,9 +77,7 @@ static enum studio_framing_state rpc_framing_state; static K_MUTEX_DEFINE(rpc_transport_mutex); static struct zmk_rpc_transport *selected_transport; -struct ring_buf *zmk_rpc_get_rx_buf(void) { - return &rpc_rx_buf; -} +struct ring_buf *zmk_rpc_get_rx_buf(void) { return &rpc_rx_buf; } void zmk_rpc_rx_notify(void) { k_sem_give(&rpc_rx_sem); } @@ -118,9 +116,7 @@ static pb_istream_t pb_istream_for_rx_ring_buf() { RING_BUF_DECLARE(rpc_tx_buf, CONFIG_ZMK_STUDIO_RPC_TX_BUF_SIZE); -struct ring_buf *zmk_rpc_get_tx_buf(void) { - return &rpc_tx_buf; -} +struct ring_buf *zmk_rpc_get_tx_buf(void) { return &rpc_tx_buf; } static bool rpc_tx_buffer_write(pb_ostream_t *stream, const uint8_t *buf, size_t count) { void *user_data = stream->state; diff --git a/app/src/workqueue.c b/app/src/workqueue.c index e6e55c87..2decc5aa 100644 --- a/app/src/workqueue.c +++ b/app/src/workqueue.c @@ -13,9 +13,7 @@ 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(void) { - return &lowprio_work_q; -} +struct k_work_q *zmk_workqueue_lowprio_work_q(void) { return &lowprio_work_q; } static int workqueue_init(void) { static const struct k_work_queue_config queue_config = {.name = "Low Priority Work Queue"}; From 92745903c98876f78a8a6da5890b7a6ff93563ec Mon Sep 17 00:00:00 2001 From: Abe Nonym Date: Mon, 16 Sep 2024 18:06:34 +0200 Subject: [PATCH 008/415] fix(ble): Properly compile with clear bonds on start --- app/src/ble.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/ble.c b/app/src/ble.c index 2308de52..9ecfb7ec 100644 --- a/app/src/ble.c +++ b/app/src/ble.c @@ -671,7 +671,7 @@ static int zmk_ble_complete_startup(void) { char setting_name[32]; sprintf(setting_name, "ble/peripheral_addresses/%d", i); - err = settings_delete(setting_name); + int err = settings_delete(setting_name); if (err) { LOG_ERR("Failed to delete setting: %d", err); } From 32d0a4bf4102148d394dc5a7acc962e71c5ed000 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Mon, 16 Sep 2024 14:13:51 -0600 Subject: [PATCH 009/415] fix: Fix wakeup from kscan wrapped in sideband. * If using a sideband kscan device to wrap a native kscan device, ensure the inner kscan device is also wakeup enabled to it can be waken from a deep sleep state by key press. --- app/src/kscan_sideband_behaviors.c | 7 +++++++ app/src/physical_layouts.c | 7 +++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/app/src/kscan_sideband_behaviors.c b/app/src/kscan_sideband_behaviors.c index 4ef5b052..9f38e0fb 100644 --- a/app/src/kscan_sideband_behaviors.c +++ b/app/src/kscan_sideband_behaviors.c @@ -111,6 +111,9 @@ static int ksbb_enable(const struct device *dev) { pm_device_runtime_get(config->kscan); } #elif IS_ENABLED(CONFIG_PM_DEVICE) + if (pm_device_wakeup_is_capable(config->kscan)) { + pm_device_wakeup_enable(config->kscan, true); + } pm_device_action_run(config->kscan, PM_DEVICE_ACTION_RESUME); #endif // IS_ENABLED(CONFIG_PM_DEVICE) @@ -132,6 +135,10 @@ static int ksbb_disable(const struct device *dev) { pm_device_runtime_put(config->kscan); } #elif IS_ENABLED(CONFIG_PM_DEVICE) + if (pm_device_wakeup_is_capable(config->kscan) && !pm_device_wakeup_is_enabled(dev) && + pm_device_wakeup_is_enabled(config->kscan)) { + pm_device_wakeup_enable(config->kscan, false); + } pm_device_action_run(config->kscan, PM_DEVICE_ACTION_SUSPEND); #endif // IS_ENABLED(CONFIG_PM_DEVICE) diff --git a/app/src/physical_layouts.c b/app/src/physical_layouts.c index a7f65078..ac627f46 100644 --- a/app/src/physical_layouts.c +++ b/app/src/physical_layouts.c @@ -393,10 +393,9 @@ static int zmk_physical_layouts_init(void) { #if IS_ENABLED(CONFIG_PM_DEVICE) for (int l = 0; l < ARRAY_SIZE(layouts); l++) { const struct zmk_physical_layout *pl = layouts[l]; - if (pl->kscan) { - if (pm_device_wakeup_is_capable(pl->kscan)) { - pm_device_wakeup_enable(pl->kscan, true); - } + if (pl->kscan && pm_device_wakeup_is_capable(pl->kscan) && + !pm_device_wakeup_enable(pl->kscan, true)) { + LOG_WRN("Failed to wakeup enable %s", pl->kscan->name); } } #endif // IS_ENABLED(CONFIG_PM_DEVICE) From a9167b2275a17970169a84c5041441ef0b36d0f7 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Mon, 16 Sep 2024 22:59:47 -0600 Subject: [PATCH 010/415] fix: Reduce RAM usage in the keymap * When not building with runtime keymap support, make the keymap const. --- app/src/keymap.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/app/src/keymap.c b/app/src/keymap.c index c9845479..041ee113 100644 --- a/app/src/keymap.c +++ b/app/src/keymap.c @@ -83,7 +83,7 @@ static uint8_t keymap_layer_orders[ZMK_KEYMAP_LAYERS_LEN]; (DT_INST_FOREACH_CHILD_SEP(0, TRANSFORMED_LAYER, (, ))), \ (DT_INST_FOREACH_CHILD_STATUS_OKAY_SEP(0, TRANSFORMED_LAYER, (, ))))}; -KEYMAP_VAR(zmk_keymap, ) +KEYMAP_VAR(zmk_keymap, COND_CODE_1(IS_ENABLED(CONFIG_ZMK_KEYMAP_SETTINGS_STORAGE), (), (const))) #if IS_ENABLED(CONFIG_ZMK_KEYMAP_SETTINGS_STORAGE) @@ -238,8 +238,6 @@ zmk_keymap_get_layer_binding_at_idx(zmk_keymap_layer_id_t layer_id, uint8_t bind static uint8_t zmk_keymap_layer_pending_changes[ZMK_KEYMAP_LAYERS_LEN][PENDING_ARRAY_SIZE]; -#endif // IS_ENABLED(CONFIG_ZMK_KEYMAP_SETTINGS_STORAGE) - int zmk_keymap_set_layer_binding_at_idx(zmk_keymap_layer_id_t layer_id, uint8_t binding_idx, struct zmk_behavior_binding binding) { if (binding_idx >= ZMK_KEYMAP_LEN) { @@ -248,11 +246,9 @@ int zmk_keymap_set_layer_binding_at_idx(zmk_keymap_layer_id_t layer_id, uint8_t ASSERT_LAYER_VAL(layer_id, -EINVAL) -#if IS_ENABLED(CONFIG_ZMK_KEYMAP_SETTINGS_STORAGE) uint8_t *pending = zmk_keymap_layer_pending_changes[layer_id]; WRITE_BIT(pending[binding_idx / 8], binding_idx % 8, 1); -#endif // IS_ENABLED(CONFIG_ZMK_KEYMAP_SETTINGS_STORAGE) // TODO: Need a mutex to protect access to the keymap data? memcpy(&zmk_keymap[layer_id][binding_idx], &binding, sizeof(binding)); @@ -260,6 +256,14 @@ int zmk_keymap_set_layer_binding_at_idx(zmk_keymap_layer_id_t layer_id, uint8_t return 0; } +#else + +int zmk_keymap_set_layer_binding_at_idx(zmk_keymap_layer_id_t layer_id, uint8_t binding_idx, + struct zmk_behavior_binding binding) { + return -ENOTSUP; +} + +#endif // IS_ENABLED(CONFIG_ZMK_KEYMAP_SETTINGS_STORAGE) #if IS_ENABLED(CONFIG_ZMK_KEYMAP_LAYER_REORDERING) #if IS_ENABLED(CONFIG_ZMK_KEYMAP_SETTINGS_STORAGE) From c8c8835a19642d745785c62ae7ab5e74ab88ad24 Mon Sep 17 00:00:00 2001 From: Andrew Kannan Date: Tue, 17 Sep 2024 20:59:05 -0400 Subject: [PATCH 011/415] fix(studio): Update position map querying --- app/src/physical_layouts.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/physical_layouts.c b/app/src/physical_layouts.c index ac627f46..e77a290e 100644 --- a/app/src/physical_layouts.c +++ b/app/src/physical_layouts.c @@ -81,7 +81,8 @@ DT_FOREACH_CHILD_SEP(DT_INST(0, POS_MAP_COMPAT), ZMK_POS_MAP_LEN_CHECK, (;)); #define ZMK_POS_MAP_ENTRY(node_id) \ { \ .layout = COND_CODE_1( \ - DT_HAS_COMPAT_STATUS_OKAY(DT_PHANDLE(node_id, physical_layout)), \ + UTIL_AND(DT_NODE_HAS_COMPAT(DT_PHANDLE(node_id, physical_layout), DT_DRV_COMPAT), \ + DT_NODE_HAS_STATUS(DT_PHANDLE(node_id, physical_layout), okay)), \ (&_CONCAT(_zmk_physical_layout_, DT_PHANDLE(node_id, physical_layout))), (NULL)), \ .positions = DT_PROP(node_id, positions), \ } From 62900c62bed78c6583a91d9cd0185800b6be3bd9 Mon Sep 17 00:00:00 2001 From: XiNGRZ Date: Sun, 15 Sep 2024 01:51:32 +0800 Subject: [PATCH 012/415] fix(studio): Ensure null-termination of layer name read from settings This fixes the string leak when a layer name is changed to a longer one, but is discarded and reverted to the original shorter one from ZMK Studio. --- app/src/keymap.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/app/src/keymap.c b/app/src/keymap.c index 041ee113..41e57024 100644 --- a/app/src/keymap.c +++ b/app/src/keymap.c @@ -791,12 +791,14 @@ static int keymap_handle_set(const char *name, size_t len, settings_read_cb read LOG_WRN("Found layer name for invalid layer ID %d", layer); } - int err = read_cb(cb_arg, zmk_keymap_layer_names[layer], + int ret = read_cb(cb_arg, zmk_keymap_layer_names[layer], MIN(len, CONFIG_ZMK_KEYMAP_LAYER_NAME_MAX_LEN - 1)); - if (err <= 0) { - LOG_ERR("Failed to handle keymap layer name from settings (err %d)", err); - return err; + if (ret <= 0) { + LOG_ERR("Failed to handle keymap layer name from settings (err %d)", ret); + return ret; } + + zmk_keymap_layer_names[layer][ret] = 0; } else if (settings_name_steq(name, "l", &next) && next) { char *endptr; uint8_t layer = strtoul(next, &endptr, 10); From 6ae07d222a23f1b3887432d35a647bf15a4baf0d Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Wed, 18 Sep 2024 13:08:35 -0600 Subject: [PATCH 013/415] feat: Bit of extra studio keymap logging. --- app/src/studio/keymap_subsystem.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/studio/keymap_subsystem.c b/app/src/studio/keymap_subsystem.c index aa4b9799..95d89d3f 100644 --- a/app/src/studio/keymap_subsystem.c +++ b/app/src/studio/keymap_subsystem.c @@ -175,11 +175,13 @@ zmk_studio_Response save_changes(const zmk_studio_Request *req) { int ret = zmk_physical_layouts_save_selected(); if (ret < 0) { + LOG_WRN("Failed to save selected physical layout (0x%02x)", ret); return ZMK_RPC_SIMPLE_ERR(GENERIC); } ret = zmk_keymap_save_changes(); if (ret < 0) { + LOG_WRN("Failed to save keymap changes (0x%02x)", ret); return ZMK_RPC_SIMPLE_ERR(GENERIC); } From 1baf18d671b8e2e68aaecab8d16967014ad9d2bd Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Thu, 19 Sep 2024 01:15:13 -0600 Subject: [PATCH 014/415] chore: Better errno formatting in logs. --- app/src/studio/keymap_subsystem.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/studio/keymap_subsystem.c b/app/src/studio/keymap_subsystem.c index 95d89d3f..d734afb6 100644 --- a/app/src/studio/keymap_subsystem.c +++ b/app/src/studio/keymap_subsystem.c @@ -175,13 +175,13 @@ zmk_studio_Response save_changes(const zmk_studio_Request *req) { int ret = zmk_physical_layouts_save_selected(); if (ret < 0) { - LOG_WRN("Failed to save selected physical layout (0x%02x)", ret); + LOG_WRN("Failed to save selected physical layout (%d)", ret); return ZMK_RPC_SIMPLE_ERR(GENERIC); } ret = zmk_keymap_save_changes(); if (ret < 0) { - LOG_WRN("Failed to save keymap changes (0x%02x)", ret); + LOG_WRN("Failed to save keymap changes (%d)", ret); return ZMK_RPC_SIMPLE_ERR(GENERIC); } From de38676afda510305d9af057e536954d6626f0ee Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Wed, 18 Sep 2024 10:30:22 -0600 Subject: [PATCH 015/415] fix(core): Warn only with layouts + chosen transform * Instead of erroring out, simply ignore physical layouts if we detect a chosen matrix transform, and warn instead. --- app/include/zmk/matrix.h | 4 ---- app/src/physical_layouts.c | 21 +++++++++++++++++++-- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/app/include/zmk/matrix.h b/app/include/zmk/matrix.h index e38f5a49..436f86f5 100644 --- a/app/include/zmk/matrix.h +++ b/app/include/zmk/matrix.h @@ -13,10 +13,6 @@ #if DT_HAS_COMPAT_STATUS_OKAY(zmk_physical_layout) -#if ZMK_MATRIX_HAS_TRANSFORM -#error "To use physical layouts, remove the chosen `zmk,matrix-transform` value." -#endif - #define ZMK_PHYSICAL_LAYOUT_BYTE_ARRAY(node_id) \ uint8_t _CONCAT(prop_, node_id)[DT_PROP_LEN(DT_PHANDLE(node_id, transform), map)]; diff --git a/app/src/physical_layouts.c b/app/src/physical_layouts.c index e77a290e..c71b427a 100644 --- a/app/src/physical_layouts.c +++ b/app/src/physical_layouts.c @@ -24,7 +24,10 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #define DT_DRV_COMPAT zmk_physical_layout -#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) +#define USE_PHY_LAYOUTS \ + (DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) && !DT_HAS_CHOSEN(zmk_matrix_transform)) + +#if USE_PHY_LAYOUTS #define ZKPA_INIT(i, n) \ (const struct zmk_key_physical_attrs) { \ @@ -99,6 +102,13 @@ static const struct zmk_physical_layout *const layouts[] = { #elif DT_HAS_CHOSEN(zmk_matrix_transform) +#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) + +#warning \ + "Ignoring the physical layouts and using the chosen matrix transform. Consider setting a chosen physical layout instead." + +#endif + ZMK_MATRIX_TRANSFORM_EXTERN(DT_CHOSEN(zmk_matrix_transform)); static const struct zmk_physical_layout _CONCAT(_zmk_physical_layout_, chosen) = { @@ -111,6 +121,13 @@ static const struct zmk_physical_layout *const layouts[] = { #elif DT_HAS_CHOSEN(zmk_kscan) +#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) + +#warning \ + "Ignoring the physical layouts and using the chosen kscan with a synthetic transform. Consider setting a chosen physical layout instead." + +#endif + ZMK_MATRIX_TRANSFORM_DEFAULT_EXTERN(); static const struct zmk_physical_layout _CONCAT(_zmk_physical_layout_, chosen) = { .display_name = "Default", @@ -252,7 +269,7 @@ static int8_t saved_selected_index = -1; int zmk_physical_layouts_select_initial(void) { const struct zmk_physical_layout *initial; -#if DT_HAS_CHOSEN(zmk_physical_layout) +#if USE_PHY_LAYOUTS && DT_HAS_CHOSEN(zmk_physical_layout) initial = &_CONCAT(_zmk_physical_layout_, DT_CHOSEN(zmk_physical_layout)); #else initial = layouts[0]; From cca637d66e36a85706d1807d44a5fecbc66bc5f7 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Thu, 19 Sep 2024 01:34:20 -0600 Subject: [PATCH 016/415] fix: Properly calculate highest active layer for display. --- .../arm/corneish_zen/widgets/layer_status.c | 9 +++++---- app/boards/shields/nice_view/widgets/status.c | 7 ++++--- app/include/zmk/keymap.h | 2 +- app/src/display/widgets/layer_status.c | 7 ++++--- app/src/keymap.c | 17 ++++++++++++----- 5 files changed, 26 insertions(+), 16 deletions(-) diff --git a/app/boards/arm/corneish_zen/widgets/layer_status.c b/app/boards/arm/corneish_zen/widgets/layer_status.c index 86418318..82de72c9 100644 --- a/app/boards/arm/corneish_zen/widgets/layer_status.c +++ b/app/boards/arm/corneish_zen/widgets/layer_status.c @@ -19,13 +19,13 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); static sys_slist_t widgets = SYS_SLIST_STATIC_INIT(&widgets); struct layer_status_state { - uint8_t index; + zmk_keymap_layer_index_t index; const char *label; }; static void set_layer_symbol(lv_obj_t *label, struct layer_status_state state) { const char *layer_label = state.label; - uint8_t active_layer_index = state.index; + zmk_keymap_layer_index_t active_layer_index = state.index; if (layer_label == NULL) { char text[6] = {}; @@ -44,8 +44,9 @@ static void layer_status_update_cb(struct layer_status_state 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_name(index)}; + zmk_keymap_layer_index_t index = zmk_keymap_highest_layer_active(); + return (struct layer_status_state){ + .index = index, .label = zmk_keymap_layer_name(zmk_keymap_layer_index_to_id(index))}; } ZMK_DISPLAY_WIDGET_LISTENER(widget_layer_status, struct layer_status_state, layer_status_update_cb, diff --git a/app/boards/shields/nice_view/widgets/status.c b/app/boards/shields/nice_view/widgets/status.c index f5095cbf..fa022355 100644 --- a/app/boards/shields/nice_view/widgets/status.c +++ b/app/boards/shields/nice_view/widgets/status.c @@ -36,7 +36,7 @@ struct output_status_state { }; struct layer_status_state { - uint8_t index; + zmk_keymap_layer_index_t index; const char *label; }; @@ -277,8 +277,9 @@ static void layer_status_update_cb(struct layer_status_state 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_name(index)}; + zmk_keymap_layer_index_t index = zmk_keymap_highest_layer_active(); + return (struct layer_status_state){ + .index = index, .label = zmk_keymap_layer_name(zmk_keymap_layer_index_to_id(index))}; } ZMK_DISPLAY_WIDGET_LISTENER(widget_layer_status, struct layer_status_state, layer_status_update_cb, diff --git a/app/include/zmk/keymap.h b/app/include/zmk/keymap.h index 50b358ba..9b278a60 100644 --- a/app/include/zmk/keymap.h +++ b/app/include/zmk/keymap.h @@ -34,7 +34,7 @@ zmk_keymap_layer_id_t zmk_keymap_layer_index_to_id(zmk_keymap_layer_index_t laye zmk_keymap_layer_id_t zmk_keymap_layer_default(void); zmk_keymap_layers_state_t zmk_keymap_layer_state(void); bool zmk_keymap_layer_active(zmk_keymap_layer_id_t layer); -zmk_keymap_layer_id_t zmk_keymap_highest_layer_active(void); +zmk_keymap_layer_index_t zmk_keymap_highest_layer_active(void); int zmk_keymap_layer_activate(zmk_keymap_layer_id_t layer); int zmk_keymap_layer_deactivate(zmk_keymap_layer_id_t layer); int zmk_keymap_layer_toggle(zmk_keymap_layer_id_t layer); diff --git a/app/src/display/widgets/layer_status.c b/app/src/display/widgets/layer_status.c index 19e25d93..d341ccd3 100644 --- a/app/src/display/widgets/layer_status.c +++ b/app/src/display/widgets/layer_status.c @@ -18,7 +18,7 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); static sys_slist_t widgets = SYS_SLIST_STATIC_INIT(&widgets); struct layer_status_state { - uint8_t index; + zmk_keymap_layer_index_t index; const char *label; }; @@ -44,8 +44,9 @@ static void layer_status_update_cb(struct layer_status_state 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_name(index)}; + zmk_keymap_layer_index_t index = zmk_keymap_highest_layer_active(); + return (struct layer_status_state){ + .index = index, .label = zmk_keymap_layer_name(zmk_keymap_layer_index_to_id(index))}; } ZMK_DISPLAY_WIDGET_LISTENER(widget_layer_status, struct layer_status_state, layer_status_update_cb, diff --git a/app/src/keymap.c b/app/src/keymap.c index 41e57024..e49acb57 100644 --- a/app/src/keymap.c +++ b/app/src/keymap.c @@ -182,13 +182,20 @@ bool zmk_keymap_layer_active(zmk_keymap_layer_id_t layer) { return zmk_keymap_layer_active_with_state(layer, _zmk_keymap_layer_state); }; -zmk_keymap_layer_id_t zmk_keymap_highest_layer_active(void) { - for (uint8_t layer = ZMK_KEYMAP_LAYERS_LEN - 1; layer > 0; layer--) { - if (zmk_keymap_layer_active(layer)) { - return layer; +zmk_keymap_layer_index_t zmk_keymap_highest_layer_active(void) { + for (int layer_idx = ZMK_KEYMAP_LAYERS_LEN - 1; + layer_idx >= LAYER_ID_TO_INDEX(_zmk_keymap_layer_default); layer_idx--) { + zmk_keymap_layer_id_t layer_id = LAYER_INDEX_TO_ID(layer_idx); + + if (layer_id == ZMK_KEYMAP_LAYER_ID_INVAL) { + continue; + } + if (zmk_keymap_layer_active(layer_id)) { + return LAYER_ID_TO_INDEX(layer_id); } } - return zmk_keymap_layer_default(); + + return LAYER_ID_TO_INDEX(zmk_keymap_layer_default()); } int zmk_keymap_layer_activate(zmk_keymap_layer_id_t layer) { return set_layer_state(layer, true); }; From 11f600d9e52233a038b86069c99c5f7947b7b925 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Fri, 20 Sep 2024 16:37:10 -0600 Subject: [PATCH 017/415] fix(display): Check layer name length too. --- app/boards/arm/corneish_zen/widgets/layer_status.c | 2 +- app/src/display/widgets/layer_status.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/boards/arm/corneish_zen/widgets/layer_status.c b/app/boards/arm/corneish_zen/widgets/layer_status.c index 82de72c9..002ce46b 100644 --- a/app/boards/arm/corneish_zen/widgets/layer_status.c +++ b/app/boards/arm/corneish_zen/widgets/layer_status.c @@ -27,7 +27,7 @@ static void set_layer_symbol(lv_obj_t *label, struct layer_status_state state) { const char *layer_label = state.label; zmk_keymap_layer_index_t active_layer_index = state.index; - if (layer_label == NULL) { + if (layer_label == NULL || strlen(layer_label) == 0) { char text[6] = {}; sprintf(text, " %i", active_layer_index); diff --git a/app/src/display/widgets/layer_status.c b/app/src/display/widgets/layer_status.c index d341ccd3..64cb7c3d 100644 --- a/app/src/display/widgets/layer_status.c +++ b/app/src/display/widgets/layer_status.c @@ -23,7 +23,7 @@ struct layer_status_state { }; static void set_layer_symbol(lv_obj_t *label, struct layer_status_state state) { - if (state.label == NULL) { + if (state.label == NULL || strlen(state.label) == 0) { char text[8] = {}; snprintf(text, sizeof(text), LV_SYMBOL_KEYBOARD " %i", state.index); From 9e36ebd52587c0364562057466a458fdcfcdc685 Mon Sep 17 00:00:00 2001 From: Cem Aksoylar Date: Tue, 17 Jan 2023 19:05:04 +0100 Subject: [PATCH 018/415] feat(split): Make locality work nested behavior invocations Co-authored-by: Tokazio --- app/include/zmk/behavior.h | 14 ++++ app/include/zmk/behavior_queue.h | 4 +- app/include/zmk/split/bluetooth/service.h | 1 + app/src/behavior.c | 67 ++++++++++++++++++ app/src/behavior_queue.c | 17 +++-- app/src/behaviors/behavior_hold_tap.c | 24 ++++--- app/src/behaviors/behavior_macro.c | 15 ++-- app/src/behaviors/behavior_mod_morph.c | 4 +- .../behaviors/behavior_sensor_rotate_common.c | 4 +- app/src/behaviors/behavior_sticky_key.c | 15 ++-- app/src/behaviors/behavior_tap_dance.c | 15 ++-- app/src/keymap.c | 70 ++----------------- app/src/split/bluetooth/central.c | 1 + 13 files changed, 146 insertions(+), 105 deletions(-) diff --git a/app/include/zmk/behavior.h b/app/include/zmk/behavior.h index d45bbfff..0940fc6e 100644 --- a/app/include/zmk/behavior.h +++ b/app/include/zmk/behavior.h @@ -26,6 +26,7 @@ struct zmk_behavior_binding_event { int layer; uint32_t position; int64_t timestamp; + uint8_t source; }; /** @@ -42,6 +43,19 @@ struct zmk_behavior_binding_event { */ const struct device *zmk_behavior_get_binding(const char *name); +/** + * @brief Invoke a behavior given its binding and invoking event details. + * + * @param src_binding Behavior binding to invoke. + * @param event The binding event struct containing details of the event that invoked it. + * @param pressed Whether the binding is pressed or released. + * + * @retval 0 If successful. + * @retval Negative errno code if failure. + */ +int zmk_behavior_invoke_binding(const struct zmk_behavior_binding *src_binding, + struct zmk_behavior_binding_event event, bool pressed); + /** * @brief Get a local ID for a behavior from its @p name field. * diff --git a/app/include/zmk/behavior_queue.h b/app/include/zmk/behavior_queue.h index 307482e7..781f582e 100644 --- a/app/include/zmk/behavior_queue.h +++ b/app/include/zmk/behavior_queue.h @@ -10,5 +10,5 @@ #include #include -int zmk_behavior_queue_add(uint32_t position, const struct zmk_behavior_binding behavior, - bool press, uint32_t wait); +int zmk_behavior_queue_add(uint32_t position, uint8_t source, + const struct zmk_behavior_binding behavior, bool press, uint32_t wait); diff --git a/app/include/zmk/split/bluetooth/service.h b/app/include/zmk/split/bluetooth/service.h index 112cd552..1c9e7522 100644 --- a/app/include/zmk/split/bluetooth/service.h +++ b/app/include/zmk/split/bluetooth/service.h @@ -20,6 +20,7 @@ struct sensor_event { struct zmk_split_run_behavior_data { uint8_t position; + uint8_t source; uint8_t state; uint32_t param1; uint32_t param2; diff --git a/app/src/behavior.c b/app/src/behavior.c index e69cdf88..f24f0223 100644 --- a/app/src/behavior.c +++ b/app/src/behavior.c @@ -17,11 +17,18 @@ #endif +#include +#if ZMK_BLE_IS_CENTRAL +#include +#endif + #include #include #include #include +#include + #include LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); @@ -49,6 +56,66 @@ const struct device *z_impl_behavior_get_binding(const char *name) { return NULL; } +static int invoke_locally(struct zmk_behavior_binding *binding, + struct zmk_behavior_binding_event event, bool pressed) { + if (pressed) { + return behavior_keymap_binding_pressed(binding, event); + } else { + return behavior_keymap_binding_released(binding, event); + } +} + +int zmk_behavior_invoke_binding(const struct zmk_behavior_binding *src_binding, + struct zmk_behavior_binding_event event, bool pressed) { + // We want to make a copy of this, since it may be converted from + // relative to absolute before being invoked + struct zmk_behavior_binding binding = *src_binding; + + const struct device *behavior = zmk_behavior_get_binding(binding.behavior_dev); + + if (!behavior) { + LOG_WRN("No behavior assigned to %d on layer %d", event.position, event.layer); + return 1; + } + + int err = behavior_keymap_binding_convert_central_state_dependent_params(&binding, event); + if (err) { + LOG_ERR("Failed to convert relative to absolute behavior binding (err %d)", err); + return err; + } + + enum behavior_locality locality = BEHAVIOR_LOCALITY_CENTRAL; + err = behavior_get_locality(behavior, &locality); + if (err) { + LOG_ERR("Failed to get behavior locality %d", err); + return err; + } + + switch (locality) { + case BEHAVIOR_LOCALITY_CENTRAL: + return invoke_locally(&binding, event, pressed); + case BEHAVIOR_LOCALITY_EVENT_SOURCE: +#if ZMK_BLE_IS_CENTRAL + if (event.source == ZMK_POSITION_STATE_CHANGE_SOURCE_LOCAL) { + return invoke_locally(&binding, event, pressed); + } else { + return zmk_split_bt_invoke_behavior(event.source, &binding, event, pressed); + } +#else + return invoke_locally(&binding, event, pressed); +#endif + case BEHAVIOR_LOCALITY_GLOBAL: +#if ZMK_BLE_IS_CENTRAL + for (int i = 0; i < ZMK_SPLIT_BLE_PERIPHERAL_COUNT; i++) { + zmk_split_bt_invoke_behavior(i, &binding, event, pressed); + } +#endif + return invoke_locally(&binding, event, pressed); + } + + return -ENOTSUP; +} + #if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA) int zmk_behavior_get_empty_param_metadata(const struct device *dev, diff --git a/app/src/behavior_queue.c b/app/src/behavior_queue.c index 1511e755..19275fe1 100644 --- a/app/src/behavior_queue.c +++ b/app/src/behavior_queue.c @@ -5,6 +5,7 @@ */ #include +#include #include #include @@ -14,6 +15,7 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); struct q_item { uint32_t position; + uint8_t source; struct zmk_behavior_binding binding; bool press : 1; uint32_t wait : 31; @@ -31,13 +33,13 @@ static void behavior_queue_process_next(struct k_work *work) { LOG_DBG("Invoking %s: 0x%02x 0x%02x", item.binding.behavior_dev, item.binding.param1, item.binding.param2); - struct zmk_behavior_binding_event event = {.position = item.position, - .timestamp = k_uptime_get()}; + struct zmk_behavior_binding_event event = { + .position = item.position, .timestamp = k_uptime_get(), .source = item.source}; if (item.press) { - behavior_keymap_binding_pressed(&item.binding, event); + zmk_behavior_invoke_binding(&item.binding, event, true); } else { - behavior_keymap_binding_released(&item.binding, event); + zmk_behavior_invoke_binding(&item.binding, event, false); } LOG_DBG("Processing next queued behavior in %dms", item.wait); @@ -49,9 +51,10 @@ static void behavior_queue_process_next(struct k_work *work) { } } -int zmk_behavior_queue_add(uint32_t position, const struct zmk_behavior_binding binding, bool press, - uint32_t wait) { - struct q_item item = {.press = press, .binding = binding, .wait = wait}; +int zmk_behavior_queue_add(uint32_t position, uint8_t source, + const struct zmk_behavior_binding binding, bool press, uint32_t wait) { + struct q_item item = { + .press = press, .binding = binding, .wait = wait, .position = position, .source = source}; const int ret = k_msgq_put(&zmk_behavior_queue_msgq, &item, K_NO_WAIT); if (ret < 0) { diff --git a/app/src/behaviors/behavior_hold_tap.c b/app/src/behaviors/behavior_hold_tap.c index c45ee803..7280451a 100644 --- a/app/src/behaviors/behavior_hold_tap.c +++ b/app/src/behaviors/behavior_hold_tap.c @@ -18,7 +18,6 @@ #include #include #include -#include LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); @@ -77,6 +76,7 @@ struct behavior_hold_tap_data { // this data is specific for each hold-tap struct active_hold_tap { int32_t position; + uint8_t source; uint32_t param_hold; uint32_t param_tap; int64_t timestamp; @@ -250,14 +250,16 @@ static struct active_hold_tap *find_hold_tap(uint32_t position) { return NULL; } -static struct active_hold_tap *store_hold_tap(uint32_t position, uint32_t param_hold, - uint32_t param_tap, int64_t timestamp, +static struct active_hold_tap *store_hold_tap(uint32_t position, uint8_t source, + uint32_t param_hold, uint32_t param_tap, + int64_t timestamp, const struct behavior_hold_tap_config *config) { for (int i = 0; i < ZMK_BHV_HOLD_TAP_MAX_HELD; i++) { if (active_hold_taps[i].position != ZMK_BHV_HOLD_TAP_POSITION_NOT_USED) { continue; } active_hold_taps[i].position = position; + active_hold_taps[i].source = source; active_hold_taps[i].status = STATUS_UNDECIDED; active_hold_taps[i].config = config; active_hold_taps[i].param_hold = param_hold; @@ -400,45 +402,49 @@ static int press_hold_binding(struct active_hold_tap *hold_tap) { struct zmk_behavior_binding_event event = { .position = hold_tap->position, .timestamp = hold_tap->timestamp, + .source = hold_tap->source, }; struct zmk_behavior_binding binding = {.behavior_dev = hold_tap->config->hold_behavior_dev, .param1 = hold_tap->param_hold}; - return behavior_keymap_binding_pressed(&binding, event); + return zmk_behavior_invoke_binding(&binding, event, true); } static int press_tap_binding(struct active_hold_tap *hold_tap) { struct zmk_behavior_binding_event event = { .position = hold_tap->position, .timestamp = hold_tap->timestamp, + .source = hold_tap->source, }; struct zmk_behavior_binding binding = {.behavior_dev = hold_tap->config->tap_behavior_dev, .param1 = hold_tap->param_tap}; store_last_hold_tapped(hold_tap); - return behavior_keymap_binding_pressed(&binding, event); + return zmk_behavior_invoke_binding(&binding, event, true); } static int release_hold_binding(struct active_hold_tap *hold_tap) { struct zmk_behavior_binding_event event = { .position = hold_tap->position, .timestamp = hold_tap->timestamp, + .source = hold_tap->source, }; struct zmk_behavior_binding binding = {.behavior_dev = hold_tap->config->hold_behavior_dev, .param1 = hold_tap->param_hold}; - return behavior_keymap_binding_released(&binding, event); + return zmk_behavior_invoke_binding(&binding, event, false); } static int release_tap_binding(struct active_hold_tap *hold_tap) { struct zmk_behavior_binding_event event = { .position = hold_tap->position, .timestamp = hold_tap->timestamp, + .source = hold_tap->source, }; struct zmk_behavior_binding binding = {.behavior_dev = hold_tap->config->tap_behavior_dev, .param1 = hold_tap->param_tap}; - return behavior_keymap_binding_released(&binding, event); + return zmk_behavior_invoke_binding(&binding, event, false); } static int press_binding(struct active_hold_tap *hold_tap) { @@ -597,8 +603,8 @@ static int on_hold_tap_binding_pressed(struct zmk_behavior_binding *binding, return ZMK_BEHAVIOR_OPAQUE; } - struct active_hold_tap *hold_tap = - store_hold_tap(event.position, binding->param1, binding->param2, event.timestamp, cfg); + struct active_hold_tap *hold_tap = store_hold_tap(event.position, event.source, binding->param1, + binding->param2, event.timestamp, cfg); if (hold_tap == NULL) { LOG_ERR("unable to store hold-tap info, did you press more than %d hold-taps?", ZMK_BHV_HOLD_TAP_MAX_HELD); diff --git a/app/src/behaviors/behavior_macro.c b/app/src/behaviors/behavior_macro.c index b535ed8b..adf3fa65 100644 --- a/app/src/behaviors/behavior_macro.c +++ b/app/src/behaviors/behavior_macro.c @@ -158,7 +158,8 @@ static void replace_params(struct behavior_macro_trigger_state *state, state->param2_source = PARAM_SOURCE_BINDING; } -static void queue_macro(uint32_t position, const struct zmk_behavior_binding bindings[], +static void queue_macro(uint32_t position, uint8_t source, + const struct zmk_behavior_binding bindings[], 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); @@ -169,14 +170,14 @@ static void queue_macro(uint32_t position, const struct zmk_behavior_binding bin switch (state.mode) { case MACRO_MODE_TAP: - zmk_behavior_queue_add(position, binding, true, state.tap_ms); - zmk_behavior_queue_add(position, binding, false, state.wait_ms); + zmk_behavior_queue_add(position, source, binding, true, state.tap_ms); + zmk_behavior_queue_add(position, source, binding, false, state.wait_ms); break; case MACRO_MODE_PRESS: - zmk_behavior_queue_add(position, binding, true, state.wait_ms); + zmk_behavior_queue_add(position, source, binding, true, state.wait_ms); break; case MACRO_MODE_RELEASE: - zmk_behavior_queue_add(position, binding, false, state.wait_ms); + zmk_behavior_queue_add(position, source, binding, false, state.wait_ms); break; default: LOG_ERR("Unknown macro mode: %d", state.mode); @@ -197,7 +198,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, binding); + queue_macro(event.position, event.source, cfg->bindings, trigger_state, binding); return ZMK_BEHAVIOR_OPAQUE; } @@ -208,7 +209,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, binding); + queue_macro(event.position, event.source, cfg->bindings, state->release_state, binding); return ZMK_BEHAVIOR_OPAQUE; } diff --git a/app/src/behaviors/behavior_mod_morph.c b/app/src/behaviors/behavior_mod_morph.c index 303f96a7..6698f248 100644 --- a/app/src/behaviors/behavior_mod_morph.c +++ b/app/src/behaviors/behavior_mod_morph.c @@ -51,7 +51,7 @@ static int on_mod_morph_binding_pressed(struct zmk_behavior_binding *binding, } else { data->pressed_binding = (struct zmk_behavior_binding *)&cfg->normal_binding; } - return behavior_keymap_binding_pressed(data->pressed_binding, event); + return zmk_behavior_invoke_binding(data->pressed_binding, event, true); } static int on_mod_morph_binding_released(struct zmk_behavior_binding *binding, @@ -67,7 +67,7 @@ static int on_mod_morph_binding_released(struct zmk_behavior_binding *binding, struct zmk_behavior_binding *pressed_binding = data->pressed_binding; data->pressed_binding = NULL; int err; - err = behavior_keymap_binding_released(pressed_binding, event); + err = zmk_behavior_invoke_binding(pressed_binding, event, false); zmk_hid_masked_modifiers_clear(); return err; } diff --git a/app/src/behaviors/behavior_sensor_rotate_common.c b/app/src/behaviors/behavior_sensor_rotate_common.c index 94bf40c1..677443ee 100644 --- a/app/src/behaviors/behavior_sensor_rotate_common.c +++ b/app/src/behaviors/behavior_sensor_rotate_common.c @@ -90,8 +90,8 @@ int zmk_behavior_sensor_rotate_common_process(struct zmk_behavior_binding *bindi LOG_DBG("Sensor binding: %s", binding->behavior_dev); 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); + zmk_behavior_queue_add(event.position, event.source, triggered_binding, true, cfg->tap_ms); + zmk_behavior_queue_add(event.position, event.source, triggered_binding, false, 0); } return ZMK_BEHAVIOR_OPAQUE; diff --git a/app/src/behaviors/behavior_sticky_key.c b/app/src/behaviors/behavior_sticky_key.c index 61c86fb7..a77ba4d0 100644 --- a/app/src/behaviors/behavior_sticky_key.c +++ b/app/src/behaviors/behavior_sticky_key.c @@ -40,6 +40,7 @@ struct behavior_sticky_key_config { struct active_sticky_key { uint32_t position; + uint8_t source; uint32_t param1; uint32_t param2; const struct behavior_sticky_key_config *config; @@ -55,8 +56,8 @@ struct active_sticky_key { struct active_sticky_key active_sticky_keys[ZMK_BHV_STICKY_KEY_MAX_HELD] = {}; -static struct active_sticky_key *store_sticky_key(uint32_t position, uint32_t param1, - uint32_t param2, +static struct active_sticky_key *store_sticky_key(uint32_t position, uint8_t source, + uint32_t param1, uint32_t param2, const struct behavior_sticky_key_config *config) { for (int i = 0; i < ZMK_BHV_STICKY_KEY_MAX_HELD; i++) { struct active_sticky_key *const sticky_key = &active_sticky_keys[i]; @@ -65,6 +66,7 @@ static struct active_sticky_key *store_sticky_key(uint32_t position, uint32_t pa continue; } sticky_key->position = position; + sticky_key->source = source; sticky_key->param1 = param1; sticky_key->param2 = param2; sticky_key->config = config; @@ -101,8 +103,9 @@ static inline int press_sticky_key_behavior(struct active_sticky_key *sticky_key struct zmk_behavior_binding_event event = { .position = sticky_key->position, .timestamp = timestamp, + .source = sticky_key->source, }; - return behavior_keymap_binding_pressed(&binding, event); + return zmk_behavior_invoke_binding(&binding, event, true); } static inline int release_sticky_key_behavior(struct active_sticky_key *sticky_key, @@ -115,10 +118,11 @@ static inline int release_sticky_key_behavior(struct active_sticky_key *sticky_k struct zmk_behavior_binding_event event = { .position = sticky_key->position, .timestamp = timestamp, + .source = sticky_key->source, }; clear_sticky_key(sticky_key); - return behavior_keymap_binding_released(&binding, event); + return zmk_behavior_invoke_binding(&binding, event, false); } static inline void on_sticky_key_timeout(struct active_sticky_key *sticky_key) { @@ -149,7 +153,8 @@ static int on_sticky_key_binding_pressed(struct zmk_behavior_binding *binding, stop_timer(sticky_key); release_sticky_key_behavior(sticky_key, event.timestamp); } - sticky_key = store_sticky_key(event.position, binding->param1, binding->param2, cfg); + sticky_key = + store_sticky_key(event.position, event.source, binding->param1, binding->param2, cfg); if (sticky_key == NULL) { LOG_ERR("unable to store sticky key, did you press more than %d sticky_key?", ZMK_BHV_STICKY_KEY_MAX_HELD); diff --git a/app/src/behaviors/behavior_tap_dance.c b/app/src/behaviors/behavior_tap_dance.c index 61e75585..606a1639 100644 --- a/app/src/behaviors/behavior_tap_dance.c +++ b/app/src/behaviors/behavior_tap_dance.c @@ -35,6 +35,7 @@ struct active_tap_dance { // Tap Dance Data int counter; uint32_t position; + uint8_t source; uint32_t param1; uint32_t param2; bool is_pressed; @@ -59,13 +60,15 @@ static struct active_tap_dance *find_tap_dance(uint32_t position) { return NULL; } -static int new_tap_dance(uint32_t position, const struct behavior_tap_dance_config *config, +static int new_tap_dance(uint32_t position, uint8_t source, + const struct behavior_tap_dance_config *config, struct active_tap_dance **tap_dance) { for (int i = 0; i < ZMK_BHV_TAP_DANCE_MAX_HELD; i++) { struct active_tap_dance *const ref_dance = &active_tap_dances[i]; if (ref_dance->position == ZMK_BHV_TAP_DANCE_POSITION_FREE) { ref_dance->counter = 0; ref_dance->position = position; + ref_dance->source = source; ref_dance->config = config; ref_dance->release_at = 0; ref_dance->is_pressed = true; @@ -108,8 +111,9 @@ static inline int press_tap_dance_behavior(struct active_tap_dance *tap_dance, i struct zmk_behavior_binding_event event = { .position = tap_dance->position, .timestamp = timestamp, + .source = tap_dance->source, }; - return behavior_keymap_binding_pressed(&binding, event); + return zmk_behavior_invoke_binding(&binding, event, true); } static inline int release_tap_dance_behavior(struct active_tap_dance *tap_dance, @@ -118,9 +122,10 @@ static inline int release_tap_dance_behavior(struct active_tap_dance *tap_dance, struct zmk_behavior_binding_event event = { .position = tap_dance->position, .timestamp = timestamp, + .source = tap_dance->source, }; clear_tap_dance(tap_dance); - return behavior_keymap_binding_released(&binding, event); + return zmk_behavior_invoke_binding(&binding, event, false); } static int on_tap_dance_binding_pressed(struct zmk_behavior_binding *binding, @@ -130,7 +135,7 @@ static int on_tap_dance_binding_pressed(struct zmk_behavior_binding *binding, struct active_tap_dance *tap_dance; tap_dance = find_tap_dance(event.position); if (tap_dance == NULL) { - if (new_tap_dance(event.position, cfg, &tap_dance) == -ENOMEM) { + if (new_tap_dance(event.position, event.source, cfg, &tap_dance) == -ENOMEM) { LOG_ERR("Unable to create new tap dance. Insufficient space in active_tap_dances[]."); return ZMK_BEHAVIOR_OPAQUE; } @@ -261,4 +266,4 @@ static int behavior_tap_dance_init(const struct device *dev) { DT_INST_FOREACH_STATUS_OKAY(KP_INST) -#endif \ No newline at end of file +#endif diff --git a/app/src/keymap.c b/app/src/keymap.c index e49acb57..d4a4ab1f 100644 --- a/app/src/keymap.c +++ b/app/src/keymap.c @@ -7,7 +7,6 @@ #include #include #include -#include #include LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); @@ -18,11 +17,6 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #include #include -#include -#if ZMK_BLE_IS_CENTRAL -#include -#endif - #include #include #include @@ -585,76 +579,20 @@ int zmk_keymap_reset_settings(void) { return -ENOTSUP; } #endif // IS_ENABLED(CONFIG_ZMK_KEYMAP_SETTINGS_STORAGE) -int invoke_locally(struct zmk_behavior_binding *binding, struct zmk_behavior_binding_event event, - bool pressed) { - if (pressed) { - return behavior_keymap_binding_pressed(binding, event); - } else { - return behavior_keymap_binding_released(binding, event); - } -} - int zmk_keymap_apply_position_state(uint8_t source, zmk_keymap_layer_id_t layer_id, uint32_t position, bool pressed, int64_t timestamp) { - // We want to make a copy of this, since it may be converted from - // relative to absolute before being invoked - - ASSERT_LAYER_VAL(layer_id, -EINVAL); - - struct zmk_behavior_binding binding = zmk_keymap[layer_id][position]; - const struct device *behavior; + struct zmk_behavior_binding *binding = &zmk_keymap[layer_id][position]; struct zmk_behavior_binding_event event = { .layer = layer_id, .position = position, .timestamp = timestamp, + .source = source, }; LOG_DBG("layer_id: %d position: %d, binding name: %s", layer_id, position, - binding.behavior_dev); + binding->behavior_dev); - behavior = zmk_behavior_get_binding(binding.behavior_dev); - - if (!behavior) { - LOG_WRN("No behavior assigned to %d on layer %d", position, layer_id); - return 1; - } - - int err = behavior_keymap_binding_convert_central_state_dependent_params(&binding, event); - if (err) { - LOG_ERR("Failed to convert relative to absolute behavior binding (err %d)", err); - return err; - } - - enum behavior_locality locality = BEHAVIOR_LOCALITY_CENTRAL; - err = behavior_get_locality(behavior, &locality); - if (err) { - LOG_ERR("Failed to get behavior locality %d", err); - return err; - } - - switch (locality) { - case BEHAVIOR_LOCALITY_CENTRAL: - return invoke_locally(&binding, event, pressed); - case BEHAVIOR_LOCALITY_EVENT_SOURCE: -#if ZMK_BLE_IS_CENTRAL - if (source == ZMK_POSITION_STATE_CHANGE_SOURCE_LOCAL) { - return invoke_locally(&binding, event, pressed); - } else { - return zmk_split_bt_invoke_behavior(source, &binding, event, pressed); - } -#else - return invoke_locally(&binding, event, pressed); -#endif - case BEHAVIOR_LOCALITY_GLOBAL: -#if ZMK_BLE_IS_CENTRAL - for (int i = 0; i < ZMK_SPLIT_BLE_PERIPHERAL_COUNT; i++) { - zmk_split_bt_invoke_behavior(i, &binding, event, pressed); - } -#endif - return invoke_locally(&binding, event, pressed); - } - - return -ENOTSUP; + return zmk_behavior_invoke_binding(binding, event, pressed); } int zmk_keymap_position_state_changed(uint8_t source, uint32_t position, bool pressed, diff --git a/app/src/split/bluetooth/central.c b/app/src/split/bluetooth/central.c index 0f4cd78b..9c459bf1 100644 --- a/app/src/split/bluetooth/central.c +++ b/app/src/split/bluetooth/central.c @@ -816,6 +816,7 @@ int zmk_split_bt_invoke_behavior(uint8_t source, struct zmk_behavior_binding *bi .param1 = binding->param1, .param2 = binding->param2, .position = event.position, + .source = event.source, .state = state ? 1 : 0, }}; const size_t payload_dev_size = sizeof(payload.behavior_dev); From 4fdfb01b6aa3715ae9e28391991f8bb1b604db4d Mon Sep 17 00:00:00 2001 From: Cem Aksoylar Date: Fri, 9 Aug 2024 00:07:21 -0700 Subject: [PATCH 019/415] feat(split): Make combos invoke behaviors with locality TODO: Currently the source is hardcoded to central for source local behaviors --- app/src/combo.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/src/combo.c b/app/src/combo.c index 3f78878f..a990e2f2 100644 --- a/app/src/combo.c +++ b/app/src/combo.c @@ -291,21 +291,23 @@ static int release_pressed_keys() { static inline int press_combo_behavior(struct combo_cfg *combo, int32_t timestamp) { struct zmk_behavior_binding_event event = { .position = combo->virtual_key_position, + .source = ZMK_POSITION_STATE_CHANGE_SOURCE_LOCAL, .timestamp = timestamp, }; last_combo_timestamp = timestamp; - return behavior_keymap_binding_pressed(&combo->behavior, event); + return zmk_behavior_invoke_binding(&combo->behavior, event, true); } static inline int release_combo_behavior(struct combo_cfg *combo, int32_t timestamp) { struct zmk_behavior_binding_event event = { .position = combo->virtual_key_position, + .source = ZMK_POSITION_STATE_CHANGE_SOURCE_LOCAL, .timestamp = timestamp, }; - return behavior_keymap_binding_released(&combo->behavior, event); + return zmk_behavior_invoke_binding(&combo->behavior, event, false); } static void move_pressed_keys_to_active_combo(struct active_combo *active_combo) { From b249135742ebba10c07fa899b50cbb260c155a45 Mon Sep 17 00:00:00 2001 From: Cem Aksoylar Date: Fri, 9 Aug 2024 11:27:36 -0700 Subject: [PATCH 020/415] feat(sensors): Make sensors always trigger on central (for now) --- app/src/behaviors/behavior_sensor_rotate_common.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/src/behaviors/behavior_sensor_rotate_common.c b/app/src/behaviors/behavior_sensor_rotate_common.c index 677443ee..e8fd7c37 100644 --- a/app/src/behaviors/behavior_sensor_rotate_common.c +++ b/app/src/behaviors/behavior_sensor_rotate_common.c @@ -6,6 +6,7 @@ #include #include +#include #include "behavior_sensor_rotate_common.h" @@ -90,8 +91,10 @@ int zmk_behavior_sensor_rotate_common_process(struct zmk_behavior_binding *bindi LOG_DBG("Sensor binding: %s", binding->behavior_dev); for (int i = 0; i < triggers; i++) { - zmk_behavior_queue_add(event.position, event.source, triggered_binding, true, cfg->tap_ms); - zmk_behavior_queue_add(event.position, event.source, triggered_binding, false, 0); + zmk_behavior_queue_add(event.position, ZMK_POSITION_STATE_CHANGE_SOURCE_LOCAL, + triggered_binding, true, cfg->tap_ms); + zmk_behavior_queue_add(event.position, ZMK_POSITION_STATE_CHANGE_SOURCE_LOCAL, + triggered_binding, false, 0); } return ZMK_BEHAVIOR_OPAQUE; From fb18a4d871485b7e184f7a13d3095cf624b2b433 Mon Sep 17 00:00:00 2001 From: Cem Aksoylar Date: Sat, 17 Aug 2024 21:03:43 -0700 Subject: [PATCH 021/415] refactor: Condition source props on CONFIG_ZMK_SPLIT --- app/include/zmk/behavior.h | 2 ++ app/include/zmk/behavior_queue.h | 2 +- app/src/behavior.c | 2 +- app/src/behavior_queue.c | 20 +++++++++++--- app/src/behaviors/behavior_hold_tap.c | 26 ++++++++++++++----- app/src/behaviors/behavior_macro.c | 14 +++++----- .../behaviors/behavior_sensor_rotate_common.c | 11 +++++--- app/src/behaviors/behavior_sticky_key.c | 17 ++++++++---- app/src/behaviors/behavior_tap_dance.c | 16 +++++++++--- app/src/combo.c | 8 ++++-- app/src/keymap.c | 2 ++ 11 files changed, 86 insertions(+), 34 deletions(-) diff --git a/app/include/zmk/behavior.h b/app/include/zmk/behavior.h index 0940fc6e..5028d320 100644 --- a/app/include/zmk/behavior.h +++ b/app/include/zmk/behavior.h @@ -26,7 +26,9 @@ struct zmk_behavior_binding_event { int layer; uint32_t position; int64_t timestamp; +#if IS_ENABLED(CONFIG_ZMK_SPLIT) uint8_t source; +#endif }; /** diff --git a/app/include/zmk/behavior_queue.h b/app/include/zmk/behavior_queue.h index 781f582e..b942bd28 100644 --- a/app/include/zmk/behavior_queue.h +++ b/app/include/zmk/behavior_queue.h @@ -10,5 +10,5 @@ #include #include -int zmk_behavior_queue_add(uint32_t position, uint8_t source, +int zmk_behavior_queue_add(const struct zmk_behavior_binding_event *event, const struct zmk_behavior_binding behavior, bool press, uint32_t wait); diff --git a/app/src/behavior.c b/app/src/behavior.c index f24f0223..9b20c706 100644 --- a/app/src/behavior.c +++ b/app/src/behavior.c @@ -95,7 +95,7 @@ int zmk_behavior_invoke_binding(const struct zmk_behavior_binding *src_binding, case BEHAVIOR_LOCALITY_CENTRAL: return invoke_locally(&binding, event, pressed); case BEHAVIOR_LOCALITY_EVENT_SOURCE: -#if ZMK_BLE_IS_CENTRAL +#if ZMK_BLE_IS_CENTRAL // source is a member of event because CONFIG_ZMK_SPLIT is enabled if (event.source == ZMK_POSITION_STATE_CHANGE_SOURCE_LOCAL) { return invoke_locally(&binding, event, pressed); } else { diff --git a/app/src/behavior_queue.c b/app/src/behavior_queue.c index 19275fe1..86837f42 100644 --- a/app/src/behavior_queue.c +++ b/app/src/behavior_queue.c @@ -15,7 +15,9 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); struct q_item { uint32_t position; +#if IS_ENABLED(CONFIG_ZMK_SPLIT) uint8_t source; +#endif struct zmk_behavior_binding binding; bool press : 1; uint32_t wait : 31; @@ -34,7 +36,12 @@ static void behavior_queue_process_next(struct k_work *work) { item.binding.param2); struct zmk_behavior_binding_event event = { - .position = item.position, .timestamp = k_uptime_get(), .source = item.source}; + .position = item.position, + .timestamp = k_uptime_get(), +#if IS_ENABLED(CONFIG_ZMK_SPLIT) + .source = item.source +#endif + }; if (item.press) { zmk_behavior_invoke_binding(&item.binding, event, true); @@ -51,10 +58,17 @@ static void behavior_queue_process_next(struct k_work *work) { } } -int zmk_behavior_queue_add(uint32_t position, uint8_t source, +int zmk_behavior_queue_add(const struct zmk_behavior_binding_event *event, const struct zmk_behavior_binding binding, bool press, uint32_t wait) { struct q_item item = { - .press = press, .binding = binding, .wait = wait, .position = position, .source = source}; + .press = press, + .binding = binding, + .wait = wait, + .position = event->position, +#if IS_ENABLED(CONFIG_ZMK_SPLIT) + .source = event->source, +#endif + }; const int ret = k_msgq_put(&zmk_behavior_queue_msgq, &item, K_NO_WAIT); if (ret < 0) { diff --git a/app/src/behaviors/behavior_hold_tap.c b/app/src/behaviors/behavior_hold_tap.c index 7280451a..3df3bc86 100644 --- a/app/src/behaviors/behavior_hold_tap.c +++ b/app/src/behaviors/behavior_hold_tap.c @@ -76,7 +76,9 @@ struct behavior_hold_tap_data { // this data is specific for each hold-tap struct active_hold_tap { int32_t position; +#if IS_ENABLED(CONFIG_ZMK_SPLIT) uint8_t source; +#endif uint32_t param_hold; uint32_t param_tap; int64_t timestamp; @@ -250,21 +252,22 @@ static struct active_hold_tap *find_hold_tap(uint32_t position) { return NULL; } -static struct active_hold_tap *store_hold_tap(uint32_t position, uint8_t source, +static struct active_hold_tap *store_hold_tap(struct zmk_behavior_binding_event *event, uint32_t param_hold, uint32_t param_tap, - int64_t timestamp, const struct behavior_hold_tap_config *config) { for (int i = 0; i < ZMK_BHV_HOLD_TAP_MAX_HELD; i++) { if (active_hold_taps[i].position != ZMK_BHV_HOLD_TAP_POSITION_NOT_USED) { continue; } - active_hold_taps[i].position = position; - active_hold_taps[i].source = source; + active_hold_taps[i].position = event->position; +#if IS_ENABLED(CONFIG_ZMK_SPLIT) + active_hold_taps[i].source = event->source; +#endif active_hold_taps[i].status = STATUS_UNDECIDED; active_hold_taps[i].config = config; active_hold_taps[i].param_hold = param_hold; active_hold_taps[i].param_tap = param_tap; - active_hold_taps[i].timestamp = timestamp; + active_hold_taps[i].timestamp = event->timestamp; active_hold_taps[i].position_of_first_other_key_pressed = -1; return &active_hold_taps[i]; } @@ -402,7 +405,9 @@ static int press_hold_binding(struct active_hold_tap *hold_tap) { struct zmk_behavior_binding_event event = { .position = hold_tap->position, .timestamp = hold_tap->timestamp, +#if IS_ENABLED(CONFIG_ZMK_SPLIT) .source = hold_tap->source, +#endif }; struct zmk_behavior_binding binding = {.behavior_dev = hold_tap->config->hold_behavior_dev, @@ -414,7 +419,9 @@ static int press_tap_binding(struct active_hold_tap *hold_tap) { struct zmk_behavior_binding_event event = { .position = hold_tap->position, .timestamp = hold_tap->timestamp, +#if IS_ENABLED(CONFIG_ZMK_SPLIT) .source = hold_tap->source, +#endif }; struct zmk_behavior_binding binding = {.behavior_dev = hold_tap->config->tap_behavior_dev, @@ -427,7 +434,9 @@ static int release_hold_binding(struct active_hold_tap *hold_tap) { struct zmk_behavior_binding_event event = { .position = hold_tap->position, .timestamp = hold_tap->timestamp, +#if IS_ENABLED(CONFIG_ZMK_SPLIT) .source = hold_tap->source, +#endif }; struct zmk_behavior_binding binding = {.behavior_dev = hold_tap->config->hold_behavior_dev, @@ -439,7 +448,9 @@ static int release_tap_binding(struct active_hold_tap *hold_tap) { struct zmk_behavior_binding_event event = { .position = hold_tap->position, .timestamp = hold_tap->timestamp, +#if IS_ENABLED(CONFIG_ZMK_SPLIT) .source = hold_tap->source, +#endif }; struct zmk_behavior_binding binding = {.behavior_dev = hold_tap->config->tap_behavior_dev, @@ -603,8 +614,9 @@ static int on_hold_tap_binding_pressed(struct zmk_behavior_binding *binding, return ZMK_BEHAVIOR_OPAQUE; } - struct active_hold_tap *hold_tap = store_hold_tap(event.position, event.source, binding->param1, - binding->param2, event.timestamp, cfg); + struct active_hold_tap *hold_tap = + store_hold_tap(&event, binding->param1, binding->param2, cfg); + if (hold_tap == NULL) { LOG_ERR("unable to store hold-tap info, did you press more than %d hold-taps?", ZMK_BHV_HOLD_TAP_MAX_HELD); diff --git a/app/src/behaviors/behavior_macro.c b/app/src/behaviors/behavior_macro.c index adf3fa65..c16fb69a 100644 --- a/app/src/behaviors/behavior_macro.c +++ b/app/src/behaviors/behavior_macro.c @@ -158,7 +158,7 @@ static void replace_params(struct behavior_macro_trigger_state *state, state->param2_source = PARAM_SOURCE_BINDING; } -static void queue_macro(uint32_t position, uint8_t source, +static void queue_macro(struct zmk_behavior_binding_event *event, const struct zmk_behavior_binding bindings[], struct behavior_macro_trigger_state state, const struct zmk_behavior_binding *macro_binding) { @@ -170,14 +170,14 @@ static void queue_macro(uint32_t position, uint8_t source, switch (state.mode) { case MACRO_MODE_TAP: - zmk_behavior_queue_add(position, source, binding, true, state.tap_ms); - zmk_behavior_queue_add(position, source, binding, false, state.wait_ms); + zmk_behavior_queue_add(event, binding, true, state.tap_ms); + zmk_behavior_queue_add(event, binding, false, state.wait_ms); break; case MACRO_MODE_PRESS: - zmk_behavior_queue_add(position, source, binding, true, state.wait_ms); + zmk_behavior_queue_add(event, binding, true, state.wait_ms); break; case MACRO_MODE_RELEASE: - zmk_behavior_queue_add(position, source, binding, false, state.wait_ms); + zmk_behavior_queue_add(event, binding, false, state.wait_ms); break; default: LOG_ERR("Unknown macro mode: %d", state.mode); @@ -198,7 +198,7 @@ static int on_macro_binding_pressed(struct zmk_behavior_binding *binding, .start_index = 0, .count = state->press_bindings_count}; - queue_macro(event.position, event.source, cfg->bindings, trigger_state, binding); + queue_macro(&event, cfg->bindings, trigger_state, binding); return ZMK_BEHAVIOR_OPAQUE; } @@ -209,7 +209,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, event.source, cfg->bindings, state->release_state, binding); + queue_macro(&event, cfg->bindings, state->release_state, binding); return ZMK_BEHAVIOR_OPAQUE; } diff --git a/app/src/behaviors/behavior_sensor_rotate_common.c b/app/src/behaviors/behavior_sensor_rotate_common.c index e8fd7c37..278f1cb2 100644 --- a/app/src/behaviors/behavior_sensor_rotate_common.c +++ b/app/src/behaviors/behavior_sensor_rotate_common.c @@ -90,11 +90,14 @@ int zmk_behavior_sensor_rotate_common_process(struct zmk_behavior_binding *bindi LOG_DBG("Sensor binding: %s", binding->behavior_dev); +#if IS_ENABLED(CONFIG_ZMK_SPLIT) + // set this value so that it always triggers on central, can be handled more properly later + event.source = ZMK_POSITION_STATE_CHANGE_SOURCE_LOCAL; +#endif + for (int i = 0; i < triggers; i++) { - zmk_behavior_queue_add(event.position, ZMK_POSITION_STATE_CHANGE_SOURCE_LOCAL, - triggered_binding, true, cfg->tap_ms); - zmk_behavior_queue_add(event.position, ZMK_POSITION_STATE_CHANGE_SOURCE_LOCAL, - triggered_binding, false, 0); + zmk_behavior_queue_add(&event, triggered_binding, true, cfg->tap_ms); + zmk_behavior_queue_add(&event, triggered_binding, false, 0); } return ZMK_BEHAVIOR_OPAQUE; diff --git a/app/src/behaviors/behavior_sticky_key.c b/app/src/behaviors/behavior_sticky_key.c index a77ba4d0..3faeec53 100644 --- a/app/src/behaviors/behavior_sticky_key.c +++ b/app/src/behaviors/behavior_sticky_key.c @@ -40,7 +40,9 @@ struct behavior_sticky_key_config { struct active_sticky_key { uint32_t position; +#if IS_ENABLED(CONFIG_ZMK_SPLIT) uint8_t source; +#endif uint32_t param1; uint32_t param2; const struct behavior_sticky_key_config *config; @@ -56,7 +58,7 @@ struct active_sticky_key { struct active_sticky_key active_sticky_keys[ZMK_BHV_STICKY_KEY_MAX_HELD] = {}; -static struct active_sticky_key *store_sticky_key(uint32_t position, uint8_t source, +static struct active_sticky_key *store_sticky_key(struct zmk_behavior_binding_event *event, uint32_t param1, uint32_t param2, const struct behavior_sticky_key_config *config) { for (int i = 0; i < ZMK_BHV_STICKY_KEY_MAX_HELD; i++) { @@ -65,8 +67,10 @@ static struct active_sticky_key *store_sticky_key(uint32_t position, uint8_t sou sticky_key->timer_cancelled) { continue; } - sticky_key->position = position; - sticky_key->source = source; + sticky_key->position = event->position; +#if IS_ENABLED(CONFIG_ZMK_SPLIT) + sticky_key->source = event->source; +#endif sticky_key->param1 = param1; sticky_key->param2 = param2; sticky_key->config = config; @@ -103,7 +107,9 @@ static inline int press_sticky_key_behavior(struct active_sticky_key *sticky_key struct zmk_behavior_binding_event event = { .position = sticky_key->position, .timestamp = timestamp, +#if IS_ENABLED(CONFIG_ZMK_SPLIT) .source = sticky_key->source, +#endif }; return zmk_behavior_invoke_binding(&binding, event, true); } @@ -118,7 +124,9 @@ static inline int release_sticky_key_behavior(struct active_sticky_key *sticky_k struct zmk_behavior_binding_event event = { .position = sticky_key->position, .timestamp = timestamp, +#if IS_ENABLED(CONFIG_ZMK_SPLIT) .source = sticky_key->source, +#endif }; clear_sticky_key(sticky_key); @@ -153,8 +161,7 @@ static int on_sticky_key_binding_pressed(struct zmk_behavior_binding *binding, stop_timer(sticky_key); release_sticky_key_behavior(sticky_key, event.timestamp); } - sticky_key = - store_sticky_key(event.position, event.source, binding->param1, binding->param2, cfg); + sticky_key = store_sticky_key(&event, binding->param1, binding->param2, cfg); if (sticky_key == NULL) { LOG_ERR("unable to store sticky key, did you press more than %d sticky_key?", ZMK_BHV_STICKY_KEY_MAX_HELD); diff --git a/app/src/behaviors/behavior_tap_dance.c b/app/src/behaviors/behavior_tap_dance.c index 606a1639..5423f93f 100644 --- a/app/src/behaviors/behavior_tap_dance.c +++ b/app/src/behaviors/behavior_tap_dance.c @@ -35,7 +35,9 @@ struct active_tap_dance { // Tap Dance Data int counter; uint32_t position; +#if IS_ENABLED(CONFIG_ZMK_SPLIT) uint8_t source; +#endif uint32_t param1; uint32_t param2; bool is_pressed; @@ -60,15 +62,17 @@ static struct active_tap_dance *find_tap_dance(uint32_t position) { return NULL; } -static int new_tap_dance(uint32_t position, uint8_t source, +static int new_tap_dance(struct zmk_behavior_binding_event *event, const struct behavior_tap_dance_config *config, struct active_tap_dance **tap_dance) { for (int i = 0; i < ZMK_BHV_TAP_DANCE_MAX_HELD; i++) { struct active_tap_dance *const ref_dance = &active_tap_dances[i]; if (ref_dance->position == ZMK_BHV_TAP_DANCE_POSITION_FREE) { ref_dance->counter = 0; - ref_dance->position = position; - ref_dance->source = source; + ref_dance->position = event->position; +#if IS_ENABLED(CONFIG_ZMK_SPLIT) + ref_dance->source = event->source; +#endif ref_dance->config = config; ref_dance->release_at = 0; ref_dance->is_pressed = true; @@ -111,7 +115,9 @@ static inline int press_tap_dance_behavior(struct active_tap_dance *tap_dance, i struct zmk_behavior_binding_event event = { .position = tap_dance->position, .timestamp = timestamp, +#if IS_ENABLED(CONFIG_ZMK_SPLIT) .source = tap_dance->source, +#endif }; return zmk_behavior_invoke_binding(&binding, event, true); } @@ -122,7 +128,9 @@ static inline int release_tap_dance_behavior(struct active_tap_dance *tap_dance, struct zmk_behavior_binding_event event = { .position = tap_dance->position, .timestamp = timestamp, +#if IS_ENABLED(CONFIG_ZMK_SPLIT) .source = tap_dance->source, +#endif }; clear_tap_dance(tap_dance); return zmk_behavior_invoke_binding(&binding, event, false); @@ -135,7 +143,7 @@ static int on_tap_dance_binding_pressed(struct zmk_behavior_binding *binding, struct active_tap_dance *tap_dance; tap_dance = find_tap_dance(event.position); if (tap_dance == NULL) { - if (new_tap_dance(event.position, event.source, cfg, &tap_dance) == -ENOMEM) { + if (new_tap_dance(&event, cfg, &tap_dance) == -ENOMEM) { LOG_ERR("Unable to create new tap dance. Insufficient space in active_tap_dances[]."); return ZMK_BEHAVIOR_OPAQUE; } diff --git a/app/src/combo.c b/app/src/combo.c index a990e2f2..c3334bdb 100644 --- a/app/src/combo.c +++ b/app/src/combo.c @@ -291,8 +291,10 @@ static int release_pressed_keys() { static inline int press_combo_behavior(struct combo_cfg *combo, int32_t timestamp) { struct zmk_behavior_binding_event event = { .position = combo->virtual_key_position, - .source = ZMK_POSITION_STATE_CHANGE_SOURCE_LOCAL, .timestamp = timestamp, +#if IS_ENABLED(CONFIG_ZMK_SPLIT) + .source = ZMK_POSITION_STATE_CHANGE_SOURCE_LOCAL, +#endif }; last_combo_timestamp = timestamp; @@ -303,8 +305,10 @@ static inline int press_combo_behavior(struct combo_cfg *combo, int32_t timestam static inline int release_combo_behavior(struct combo_cfg *combo, int32_t timestamp) { struct zmk_behavior_binding_event event = { .position = combo->virtual_key_position, - .source = ZMK_POSITION_STATE_CHANGE_SOURCE_LOCAL, .timestamp = timestamp, +#if IS_ENABLED(CONFIG_ZMK_SPLIT) + .source = ZMK_POSITION_STATE_CHANGE_SOURCE_LOCAL, +#endif }; return zmk_behavior_invoke_binding(&combo->behavior, event, false); diff --git a/app/src/keymap.c b/app/src/keymap.c index d4a4ab1f..af94bbfd 100644 --- a/app/src/keymap.c +++ b/app/src/keymap.c @@ -586,7 +586,9 @@ int zmk_keymap_apply_position_state(uint8_t source, zmk_keymap_layer_id_t layer_ .layer = layer_id, .position = position, .timestamp = timestamp, +#if IS_ENABLED(CONFIG_ZMK_SPLIT) .source = source, +#endif }; LOG_DBG("layer_id: %d position: %d, binding name: %s", layer_id, position, From 8166527ea35923d8be6278b9d1727285dd504d3c Mon Sep 17 00:00:00 2001 From: Cem Aksoylar Date: Fri, 9 Aug 2024 11:31:09 -0700 Subject: [PATCH 022/415] fix(docs): Remove split locality issue note --- docs/docs/features/split-keyboards.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/docs/docs/features/split-keyboards.md b/docs/docs/features/split-keyboards.md index 8c69d51a..ff9397f7 100644 --- a/docs/docs/features/split-keyboards.md +++ b/docs/docs/features/split-keyboards.md @@ -86,11 +86,6 @@ These behaviors only affect the keyboard part that they are invoked from: - [Reset behaviors](../keymaps/behaviors/reset.md) -:::warning[Nesting behaviors with locality] -Currently there is [an issue](https://github.com/zmkfirmware/zmk/issues/1494) preventing both global and source locality behaviors from working as expected if they are invoked from another behavior, such as a hold-tap, tap dance or a mod-morph. -For this reason it is recommended that these behaviors are placed directly on a keymap layer. -::: - :::note[Peripheral invocation] Peripherals must be paired and connected to the central in order to be able to activate these behaviors, even if it is possible to trigger the behavior using only keys on a particular peripheral. This is because the key bindings are processed on the central side which would then instruct the peripheral side to run the behavior's effect. From f992352936f6556da8b343a34e75ac61514d0ecf Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Mon, 23 Sep 2024 10:28:56 -0600 Subject: [PATCH 023/415] chore: Formatting fix. --- app/src/behavior_queue.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/app/src/behavior_queue.c b/app/src/behavior_queue.c index 86837f42..82c58ca8 100644 --- a/app/src/behavior_queue.c +++ b/app/src/behavior_queue.c @@ -35,11 +35,10 @@ static void behavior_queue_process_next(struct k_work *work) { LOG_DBG("Invoking %s: 0x%02x 0x%02x", item.binding.behavior_dev, item.binding.param1, item.binding.param2); - struct zmk_behavior_binding_event event = { - .position = item.position, - .timestamp = k_uptime_get(), + struct zmk_behavior_binding_event event = {.position = item.position, + .timestamp = k_uptime_get(), #if IS_ENABLED(CONFIG_ZMK_SPLIT) - .source = item.source + .source = item.source #endif }; From 33e3b02ddb0509a38b39dc565f21fdc17553ff0c Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Wed, 31 Jul 2024 11:54:15 -0600 Subject: [PATCH 024/415] feat: Split physical layout selection sync. * Ensure the split peripherals have the same selected physical layout on connection and change. --- app/include/zmk/physical_layouts.h | 7 +++ app/include/zmk/split/bluetooth/uuid.h | 1 + app/src/physical_layouts.c | 11 +++- app/src/split/bluetooth/central.c | 82 +++++++++++++++++++++++++- app/src/split/bluetooth/service.c | 43 +++++++++++++- 5 files changed, 141 insertions(+), 3 deletions(-) diff --git a/app/include/zmk/physical_layouts.h b/app/include/zmk/physical_layouts.h index e78602e3..33004af7 100644 --- a/app/include/zmk/physical_layouts.h +++ b/app/include/zmk/physical_layouts.h @@ -8,6 +8,13 @@ #include #include +#include + +struct zmk_physical_layout_selection_changed { + uint8_t selection; +}; + +ZMK_EVENT_DECLARE(zmk_physical_layout_selection_changed); struct zmk_key_physical_attrs { int16_t width; diff --git a/app/include/zmk/split/bluetooth/uuid.h b/app/include/zmk/split/bluetooth/uuid.h index dccdfc80..4a653c73 100644 --- a/app/include/zmk/split/bluetooth/uuid.h +++ b/app/include/zmk/split/bluetooth/uuid.h @@ -18,3 +18,4 @@ #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) #define ZMK_SPLIT_BT_UPDATE_HID_INDICATORS_UUID ZMK_BT_SPLIT_UUID(0x00000004) +#define ZMK_SPLIT_BT_SELECT_PHYS_LAYOUT_UUID ZMK_BT_SPLIT_UUID(0x00000005) diff --git a/app/src/physical_layouts.c b/app/src/physical_layouts.c index c71b427a..59077ede 100644 --- a/app/src/physical_layouts.c +++ b/app/src/physical_layouts.c @@ -22,6 +22,8 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #include #include +ZMK_EVENT_IMPL(zmk_physical_layout_selection_changed); + #define DT_DRV_COMPAT zmk_physical_layout #define USE_PHY_LAYOUTS \ @@ -247,7 +249,14 @@ int zmk_physical_layouts_select(uint8_t index) { return -EINVAL; } - return zmk_physical_layouts_select_layout(layouts[index]); + int ret = zmk_physical_layouts_select_layout(layouts[index]); + + if (ret >= 0) { + raise_zmk_physical_layout_selection_changed( + (struct zmk_physical_layout_selection_changed){.selection = index}); + } + + return ret; } int zmk_physical_layouts_get_selected(void) { diff --git a/app/src/split/bluetooth/central.c b/app/src/split/bluetooth/central.c index 9c459bf1..21ff611f 100644 --- a/app/src/split/bluetooth/central.c +++ b/app/src/split/bluetooth/central.c @@ -30,6 +30,7 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #include #include #include +#include static int start_scanning(void); @@ -56,6 +57,7 @@ struct peripheral_slot { #if IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS) uint16_t update_hid_indicators; #endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS) + uint16_t selected_physical_layout_handle; uint8_t position_state[POSITION_STATE_DATA_LEN]; uint8_t changed_positions[POSITION_STATE_DATA_LEN]; }; @@ -141,6 +143,7 @@ int release_peripheral_slot(int index) { // Clean up previously discovered handles; slot->subscribe_params.value_handle = 0; slot->run_behavior_handle = 0; + slot->selected_physical_layout_handle = 0; #if IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS) slot->update_hid_indicators = 0; #endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS) @@ -392,6 +395,46 @@ static int split_central_subscribe(struct bt_conn *conn, struct bt_gatt_subscrib return err; } +static int update_peripheral_selected_layout(struct peripheral_slot *slot, uint8_t layout_idx) { + if (slot->state != PERIPHERAL_SLOT_STATE_CONNECTED) { + return -ENOTCONN; + } + + if (slot->selected_physical_layout_handle == 0) { + // It appears that sometimes the peripheral is considered connected + // before the GATT characteristics have been discovered. If this is + // the case, the selected_physical_layout_handle will not yet be set. + return -EAGAIN; + } + + if (bt_conn_get_security(slot->conn) < BT_SECURITY_L2) { + return -EAGAIN; + } + + int err = bt_gatt_write_without_response(slot->conn, slot->selected_physical_layout_handle, + &layout_idx, sizeof(layout_idx), true); + + if (err < 0) { + LOG_ERR("Failed to write physical layout index to peripheral (err %d)", err); + } + + return err; +} + +static void update_peripherals_selected_physical_layout(struct k_work *_work) { + uint8_t layout_idx = zmk_physical_layouts_get_selected(); + for (int i = 0; i < ZMK_SPLIT_BLE_PERIPHERAL_COUNT; i++) { + if (peripherals[i].state != PERIPHERAL_SLOT_STATE_CONNECTED) { + continue; + } + + update_peripheral_selected_layout(&peripherals[i], layout_idx); + } +} + +K_WORK_DEFINE(update_peripherals_selected_layouts_work, + update_peripherals_selected_physical_layout); + static uint8_t split_central_chrc_discovery_func(struct bt_conn *conn, const struct bt_gatt_attr *attr, struct bt_gatt_discover_params *params) { @@ -442,6 +485,11 @@ static uint8_t split_central_chrc_discovery_func(struct bt_conn *conn, slot->discover_params.uuid = NULL; slot->discover_params.start_handle = attr->handle + 2; slot->run_behavior_handle = bt_gatt_attr_value_handle(attr); + } else if (!bt_uuid_cmp(((struct bt_gatt_chrc *)attr->user_data)->uuid, + BT_UUID_DECLARE_128(ZMK_SPLIT_BT_SELECT_PHYS_LAYOUT_UUID))) { + LOG_DBG("Found select physical layout handle"); + slot->selected_physical_layout_handle = bt_gatt_attr_value_handle(attr); + k_work_submit(&update_peripherals_selected_layouts_work); #if IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS) } else if (!bt_uuid_cmp(((struct bt_gatt_chrc *)attr->user_data)->uuid, BT_UUID_DECLARE_128(ZMK_SPLIT_BT_UPDATE_HID_INDICATORS_UUID))) { @@ -467,7 +515,8 @@ static uint8_t split_central_chrc_discovery_func(struct bt_conn *conn, #endif /* IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_CENTRAL_BATTERY_LEVEL_FETCHING) */ } - bool subscribed = slot->run_behavior_handle && slot->subscribe_params.value_handle; + bool subscribed = slot->run_behavior_handle && slot->subscribe_params.value_handle && + slot->selected_physical_layout_handle; #if ZMK_KEYMAP_HAS_SENSORS subscribed = subscribed && slot->sensor_subscribe_params.value_handle; @@ -739,9 +788,30 @@ static void split_central_disconnected(struct bt_conn *conn, uint8_t reason) { start_scanning(); } +static void split_central_security_changed(struct bt_conn *conn, bt_security_t level, + enum bt_security_err err) { + struct peripheral_slot *slot = peripheral_slot_for_conn(conn); + if (!slot || !slot->selected_physical_layout_handle) { + return; + } + + if (err > 0) { + LOG_DBG("Skipping updating the physical layout for peripheral with security error"); + return; + } + + if (level < BT_SECURITY_L2) { + LOG_DBG("Skipping updating the physical layout for peripheral with insufficient security"); + return; + } + + k_work_submit(&update_peripherals_selected_layouts_work); +} + static struct bt_conn_cb conn_callbacks = { .connected = split_central_connected, .disconnected = split_central_disconnected, + .security_changed = split_central_security_changed, }; K_THREAD_STACK_DEFINE(split_central_split_run_q_stack, @@ -898,3 +968,13 @@ static int zmk_split_bt_central_init(void) { } SYS_INIT(zmk_split_bt_central_init, APPLICATION, CONFIG_ZMK_BLE_INIT_PRIORITY); + +static int zmk_split_bt_central_listener_cb(const zmk_event_t *eh) { + if (as_zmk_physical_layout_selection_changed(eh)) { + k_work_submit(&update_peripherals_selected_layouts_work); + } + return ZMK_EV_EVENT_BUBBLE; +} + +ZMK_LISTENER(zmk_split_bt_central, zmk_split_bt_central_listener_cb); +ZMK_SUBSCRIPTION(zmk_split_bt_central, zmk_physical_layout_selection_changed); \ No newline at end of file diff --git a/app/src/split/bluetooth/service.c b/app/src/split/bluetooth/service.c index 505eb363..9529d516 100644 --- a/app/src/split/bluetooth/service.c +++ b/app/src/split/bluetooth/service.c @@ -19,6 +19,7 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #include #include #include +#include #include #include @@ -138,6 +139,42 @@ static ssize_t split_svc_update_indicators(struct bt_conn *conn, const struct bt #endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS) +static uint8_t selected_phys_layout = 0; + +static void split_svc_select_phys_layout_callback(struct k_work *work) { + LOG_DBG("Selecting physical layout after GATT write of %d", selected_phys_layout); + zmk_physical_layouts_select(selected_phys_layout); +} + +static K_WORK_DEFINE(split_svc_select_phys_layout_work, split_svc_select_phys_layout_callback); + +static ssize_t split_svc_select_phys_layout(struct bt_conn *conn, const struct bt_gatt_attr *attr, + const void *buf, uint16_t len, uint16_t offset, + uint8_t flags) { + if (offset + len > sizeof(uint8_t) || len == 0) { + return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET); + } + + selected_phys_layout = *(uint8_t *)buf; + + k_work_submit(&split_svc_select_phys_layout_work); + + return len; +} + +static ssize_t split_svc_get_selected_phys_layout(struct bt_conn *conn, + const struct bt_gatt_attr *attrs, void *buf, + uint16_t len, uint16_t offset) { + int selected_ret = zmk_physical_layouts_get_selected(); + if (selected_ret < 0) { + return BT_GATT_ERR(BT_ATT_ERR_VALUE_NOT_ALLOWED); + } + + uint8_t selected = (uint8_t)selected_ret; + + return bt_gatt_attr_read(conn, attrs, buf, len, offset, &selected, sizeof(selected)); +} + BT_GATT_SERVICE_DEFINE( split_svc, BT_GATT_PRIMARY_SERVICE(BT_UUID_DECLARE_128(ZMK_SPLIT_BT_SERVICE_UUID)), BT_GATT_CHARACTERISTIC(BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_POSITION_STATE_UUID), @@ -160,7 +197,11 @@ BT_GATT_SERVICE_DEFINE( BT_GATT_CHRC_WRITE_WITHOUT_RESP, BT_GATT_PERM_WRITE_ENCRYPT, NULL, split_svc_update_indicators, NULL), #endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS) -); + BT_GATT_CHARACTERISTIC(BT_UUID_DECLARE_128(ZMK_SPLIT_BT_SELECT_PHYS_LAYOUT_UUID), + BT_GATT_CHRC_WRITE | BT_GATT_CHRC_READ, + BT_GATT_PERM_WRITE_ENCRYPT | BT_GATT_PERM_READ_ENCRYPT, + split_svc_get_selected_phys_layout, split_svc_select_phys_layout, + NULL), ); K_THREAD_STACK_DEFINE(service_q_stack, CONFIG_ZMK_SPLIT_BLE_PERIPHERAL_STACK_SIZE); From 58dcf5c28520def16d00fa615c412cddc0151760 Mon Sep 17 00:00:00 2001 From: ReFil <31960031+ReFil@users.noreply.github.com> Date: Wed, 25 Sep 2024 20:30:45 +0100 Subject: [PATCH 025/415] feat(power): Support multiple ext_power GPIOS --- app/src/ext_power_generic.c | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/app/src/ext_power_generic.c b/app/src/ext_power_generic.c index 17b3ba64..3975e038 100644 --- a/app/src/ext_power_generic.c +++ b/app/src/ext_power_generic.c @@ -22,7 +22,8 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); struct ext_power_generic_config { - const struct gpio_dt_spec control; + const struct gpio_dt_spec *control; + const size_t control_gpios_count; const uint16_t init_delay_ms; }; @@ -59,9 +60,12 @@ static int ext_power_generic_enable(const struct device *dev) { struct ext_power_generic_data *data = dev->data; const struct ext_power_generic_config *config = dev->config; - if (gpio_pin_set_dt(&config->control, 1)) { - LOG_WRN("Failed to set ext-power control pin"); - return -EIO; + for (int i = 0; i < config->control_gpios_count; i++) { + const struct gpio_dt_spec *gpio = &config->control[i]; + if (gpio_pin_set_dt(gpio, 1)) { + LOG_WRN("Failed to set ext-power control pin %d", i); + return -EIO; + } } data->status = true; return ext_power_save_state(); @@ -71,10 +75,12 @@ static int ext_power_generic_disable(const struct device *dev) { struct ext_power_generic_data *data = dev->data; const struct ext_power_generic_config *config = dev->config; - if (gpio_pin_set_dt(&config->control, 0)) { - LOG_WRN("Failed to set ext-power control pin"); - LOG_WRN("Failed to clear ext-power control pin"); - return -EIO; + for (int i = 0; i < config->control_gpios_count; i++) { + const struct gpio_dt_spec *gpio = &config->control[i]; + if (gpio_pin_set_dt(gpio, 0)) { + LOG_WRN("Failed to clear ext-power control pin %d", i); + return -EIO; + } } data->status = false; return ext_power_save_state(); @@ -144,9 +150,12 @@ SETTINGS_STATIC_HANDLER_DEFINE(ext_power, "ext_power/state", NULL, ext_power_set static int ext_power_generic_init(const struct device *dev) { const struct ext_power_generic_config *config = dev->config; - if (gpio_pin_configure_dt(&config->control, GPIO_OUTPUT_INACTIVE)) { - LOG_ERR("Failed to configure ext-power control pin"); - return -EIO; + for (int i = 0; i < config->control_gpios_count; i++) { + const struct gpio_dt_spec *gpio = &config->control[i]; + if (gpio_pin_configure_dt(gpio, GPIO_OUTPUT_INACTIVE)) { + LOG_ERR("Failed to configure ext-power control pin %d", i); + return -EIO; + } } #if IS_ENABLED(CONFIG_SETTINGS) @@ -178,8 +187,12 @@ static int ext_power_generic_pm_action(const struct device *dev, enum pm_device_ } #endif /* CONFIG_PM_DEVICE */ +static const struct gpio_dt_spec ext_power_control_gpios[DT_INST_PROP_LEN(0, control_gpios)] = { + DT_INST_FOREACH_PROP_ELEM_SEP(0, control_gpios, GPIO_DT_SPEC_GET_BY_IDX, (, ))}; + static const struct ext_power_generic_config config = { - .control = GPIO_DT_SPEC_INST_GET(0, control_gpios), + .control = ext_power_control_gpios, + .control_gpios_count = DT_INST_PROP_LEN(0, control_gpios), .init_delay_ms = DT_INST_PROP_OR(0, init_delay_ms, 0)}; static struct ext_power_generic_data data = { From 17f0a4d307700e278e53548cecb04bb49803b515 Mon Sep 17 00:00:00 2001 From: ReFil <31960031+ReFil@users.noreply.github.com> Date: Wed, 25 Sep 2024 20:35:42 +0100 Subject: [PATCH 026/415] feat(ble): Set device name at runtime This allows for the device name to be set at runtime, possible uses for this include a custom display screen that lets you type it in using the keycode state event, future configuration in zmk studio, or altering it per profile as per #1169 --- app/Kconfig | 1 + app/include/zmk/ble.h | 2 ++ app/src/ble.c | 28 ++++++++++++++++--- .../snapshot.log | 2 -- .../bond-to-cleared-profile/snapshot.log | 2 -- .../snapshot.log | 1 - .../dont-bond-to-taken-profile/snapshot.log | 2 -- .../snapshot.log | 2 -- .../snapshot.log | 2 -- .../snapshot.log | 2 -- .../snapshot.log | 1 - .../snapshot.log | 1 - 12 files changed, 27 insertions(+), 19 deletions(-) diff --git a/app/Kconfig b/app/Kconfig index 108fcbe7..b0ffc72a 100644 --- a/app/Kconfig +++ b/app/Kconfig @@ -153,6 +153,7 @@ menuconfig ZMK_BLE select BT_SMP_APP_PAIRING_ACCEPT select BT_PERIPHERAL select BT_DIS + imply BT_DEVICE_NAME_DYNAMIC imply BT_SETTINGS if !ARCH_POSIX imply SETTINGS if !ARCH_POSIX imply ZMK_BATTERY_REPORTING if !ARCH_POSIX diff --git a/app/include/zmk/ble.h b/app/include/zmk/ble.h index cc55a6ce..c44c5e16 100644 --- a/app/include/zmk/ble.h +++ b/app/include/zmk/ble.h @@ -39,6 +39,8 @@ char *zmk_ble_active_profile_name(void); int zmk_ble_unpair_all(void); +int zmk_ble_set_device_name(char *name); + #if IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) 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 9ecfb7ec..e63c63b0 100644 --- a/app/src/ble.c +++ b/app/src/ble.c @@ -56,8 +56,9 @@ enum advertising_type { #define CURR_ADV(adv) (adv << 4) #define ZMK_ADV_CONN_NAME \ - BT_LE_ADV_PARAM(BT_LE_ADV_OPT_CONNECTABLE | BT_LE_ADV_OPT_ONE_TIME, BT_GAP_ADV_FAST_INT_MIN_2, \ - BT_GAP_ADV_FAST_INT_MAX_2, NULL) + BT_LE_ADV_PARAM(BT_LE_ADV_OPT_CONNECTABLE | BT_LE_ADV_OPT_ONE_TIME | BT_LE_ADV_OPT_USE_NAME | \ + BT_LE_ADV_OPT_FORCE_NAME_IN_AD, \ + BT_GAP_ADV_FAST_INT_MIN_2, BT_GAP_ADV_FAST_INT_MAX_2, NULL) static struct zmk_ble_profile profiles[ZMK_BLE_PROFILE_COUNT]; static uint8_t active_profile; @@ -67,8 +68,7 @@ static uint8_t active_profile; BUILD_ASSERT(DEVICE_NAME_LEN <= 16, "ERROR: BLE device name is too long. Max length: 16"); -static const struct bt_data zmk_ble_ad[] = { - BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN), +static struct bt_data zmk_ble_ad[] = { BT_DATA_BYTES(BT_DATA_GAP_APPEARANCE, 0xC1, 0x03), BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)), BT_DATA_BYTES(BT_DATA_UUID16_SOME, 0x12, 0x18, /* HID Service */ @@ -335,6 +335,26 @@ struct bt_conn *zmk_ble_active_profile_conn(void) { char *zmk_ble_active_profile_name(void) { return profiles[active_profile].name; } +int zmk_ble_set_device_name(char *name) { + // Copy new name to advertising parameters + int err = bt_set_name(name); + LOG_DBG("New device name: %s", name); + if (err) { + LOG_ERR("Failed to set new device name (err %d)", err); + return err; + } + if (advertising_status == ZMK_ADV_CONN) { + // Stop current advertising so it can restart with new name + err = bt_le_adv_stop(); + advertising_status = ZMK_ADV_NONE; + if (err) { + LOG_ERR("Failed to stop advertising (err %d)", err); + return err; + } + } + return update_advertising(); +} + #if IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) int zmk_ble_put_peripheral_addr(const bt_addr_le_t *addr) { diff --git a/app/tests/ble/profiles/bond-clear-then-bond-second-client/snapshot.log b/app/tests/ble/profiles/bond-clear-then-bond-second-client/snapshot.log index 077634f2..c7a0884d 100644 --- a/app/tests/ble/profiles/bond-clear-then-bond-second-client/snapshot.log +++ b/app/tests/ble/profiles/bond-clear-then-bond-second-client/snapshot.log @@ -2,7 +2,6 @@ profile 0 bt_id: No static addresses stored in controller profile 0 ble_central: main: [Bluetooth initialized] profile 0 ble_central: start_scan: [Scanning successfully started] profile 0 ble_central: device_found: [DEVICE]: FD:9E:B2:48:47:39 (random), AD evt type 0, AD data len 15, RSSI -59 -profile 0 ble_central: eir_found: [AD]: 9 data_len 0 profile 0 ble_central: eir_found: [AD]: 25 data_len 2 profile 0 ble_central: eir_found: [AD]: 1 data_len 1 profile 0 ble_central: eir_found: [AD]: 2 data_len 4 @@ -13,7 +12,6 @@ profile 1 bt_id: No static addresses stored in controller profile 1 ble_central: main: [Bluetooth initialized] profile 1 ble_central: start_scan: [Scanning successfully started] profile 1 ble_central: device_found: [DEVICE]: FD:9E:B2:48:47:39 (random), AD evt type 0, AD data len 15, RSSI -59 -profile 1 ble_central: eir_found: [AD]: 9 data_len 0 profile 1 ble_central: eir_found: [AD]: 25 data_len 2 profile 1 ble_central: eir_found: [AD]: 1 data_len 1 profile 1 ble_central: eir_found: [AD]: 2 data_len 4 diff --git a/app/tests/ble/profiles/bond-to-cleared-profile/snapshot.log b/app/tests/ble/profiles/bond-to-cleared-profile/snapshot.log index 077634f2..c7a0884d 100644 --- a/app/tests/ble/profiles/bond-to-cleared-profile/snapshot.log +++ b/app/tests/ble/profiles/bond-to-cleared-profile/snapshot.log @@ -2,7 +2,6 @@ profile 0 bt_id: No static addresses stored in controller profile 0 ble_central: main: [Bluetooth initialized] profile 0 ble_central: start_scan: [Scanning successfully started] profile 0 ble_central: device_found: [DEVICE]: FD:9E:B2:48:47:39 (random), AD evt type 0, AD data len 15, RSSI -59 -profile 0 ble_central: eir_found: [AD]: 9 data_len 0 profile 0 ble_central: eir_found: [AD]: 25 data_len 2 profile 0 ble_central: eir_found: [AD]: 1 data_len 1 profile 0 ble_central: eir_found: [AD]: 2 data_len 4 @@ -13,7 +12,6 @@ profile 1 bt_id: No static addresses stored in controller profile 1 ble_central: main: [Bluetooth initialized] profile 1 ble_central: start_scan: [Scanning successfully started] profile 1 ble_central: device_found: [DEVICE]: FD:9E:B2:48:47:39 (random), AD evt type 0, AD data len 15, RSSI -59 -profile 1 ble_central: eir_found: [AD]: 9 data_len 0 profile 1 ble_central: eir_found: [AD]: 25 data_len 2 profile 1 ble_central: eir_found: [AD]: 1 data_len 1 profile 1 ble_central: eir_found: [AD]: 2 data_len 4 diff --git a/app/tests/ble/profiles/connnect-and-output-to-selection/snapshot.log b/app/tests/ble/profiles/connnect-and-output-to-selection/snapshot.log index 62cb2d6d..61f3e09e 100644 --- a/app/tests/ble/profiles/connnect-and-output-to-selection/snapshot.log +++ b/app/tests/ble/profiles/connnect-and-output-to-selection/snapshot.log @@ -2,7 +2,6 @@ ble_central: main: [Bluetooth initialized] ble_central: start_scan: [Scanning successfully started] ble_central: device_found: [DEVICE]: FD:9E:B2:48:47:39 (random), AD evt type 0, AD data len 15, RSSI -59 - ble_central: eir_found: [AD]: 9 data_len 0 ble_central: eir_found: [AD]: 25 data_len 2 ble_central: eir_found: [AD]: 1 data_len 1 ble_central: eir_found: [AD]: 2 data_len 4 diff --git a/app/tests/ble/profiles/dont-bond-to-taken-profile/snapshot.log b/app/tests/ble/profiles/dont-bond-to-taken-profile/snapshot.log index 6ea4fc72..d754b9c4 100644 --- a/app/tests/ble/profiles/dont-bond-to-taken-profile/snapshot.log +++ b/app/tests/ble/profiles/dont-bond-to-taken-profile/snapshot.log @@ -2,7 +2,6 @@ profile 0 bt_id: No static addresses stored in controller profile 0 ble_central: main: [Bluetooth initialized] profile 0 ble_central: start_scan: [Scanning successfully started] profile 0 ble_central: device_found: [DEVICE]: FD:9E:B2:48:47:39 (random), AD evt type 0, AD data len 15, RSSI -59 -profile 0 ble_central: eir_found: [AD]: 9 data_len 0 profile 0 ble_central: eir_found: [AD]: 25 data_len 2 profile 0 ble_central: eir_found: [AD]: 1 data_len 1 profile 0 ble_central: eir_found: [AD]: 2 data_len 4 @@ -13,7 +12,6 @@ profile 1 bt_id: No static addresses stored in controller profile 1 ble_central: main: [Bluetooth initialized] profile 1 ble_central: start_scan: [Scanning successfully started] profile 1 ble_central: device_found: [DEVICE]: FD:9E:B2:48:47:39 (random), AD evt type 0, AD data len 15, RSSI -59 -profile 1 ble_central: eir_found: [AD]: 9 data_len 0 profile 1 ble_central: eir_found: [AD]: 25 data_len 2 profile 1 ble_central: eir_found: [AD]: 1 data_len 1 profile 1 ble_central: eir_found: [AD]: 2 data_len 4 diff --git a/app/tests/ble/profiles/first-and-second-profile-paired-then-send-data/snapshot.log b/app/tests/ble/profiles/first-and-second-profile-paired-then-send-data/snapshot.log index 1a88748d..bc345b0b 100644 --- a/app/tests/ble/profiles/first-and-second-profile-paired-then-send-data/snapshot.log +++ b/app/tests/ble/profiles/first-and-second-profile-paired-then-send-data/snapshot.log @@ -2,7 +2,6 @@ profile 0 bt_id: No static addresses stored in controller profile 0 ble_central: main: [Bluetooth initialized] profile 0 ble_central: start_scan: [Scanning successfully started] profile 0 ble_central: device_found: [DEVICE]: FD:9E:B2:48:47:39 (random), AD evt type 0, AD data len 15, RSSI -59 -profile 0 ble_central: eir_found: [AD]: 9 data_len 0 profile 0 ble_central: eir_found: [AD]: 25 data_len 2 profile 0 ble_central: eir_found: [AD]: 1 data_len 1 profile 0 ble_central: eir_found: [AD]: 2 data_len 4 @@ -22,7 +21,6 @@ profile 0 00 00 04 00 00 00 00 00 |. profile 0 ble_central: notify_func: payload profile 0 00 00 00 00 00 00 00 00 |........ profile 1 ble_central: device_found: [DEVICE]: FD:9E:B2:48:47:39 (random), AD evt type 0, AD data len 15, RSSI -59 -profile 1 ble_central: eir_found: [AD]: 9 data_len 0 profile 1 ble_central: eir_found: [AD]: 25 data_len 2 profile 1 ble_central: eir_found: [AD]: 1 data_len 1 profile 1 ble_central: eir_found: [AD]: 2 data_len 4 diff --git a/app/tests/ble/profiles/overwrite-enabled-reconnect-without-bond-then-output-to-selection/snapshot.log b/app/tests/ble/profiles/overwrite-enabled-reconnect-without-bond-then-output-to-selection/snapshot.log index 6c0bac58..e54d7092 100644 --- a/app/tests/ble/profiles/overwrite-enabled-reconnect-without-bond-then-output-to-selection/snapshot.log +++ b/app/tests/ble/profiles/overwrite-enabled-reconnect-without-bond-then-output-to-selection/snapshot.log @@ -2,7 +2,6 @@ ble_central: main: [Bluetooth initialized] ble_central: start_scan: [Scanning successfully started] ble_central: device_found: [DEVICE]: FD:9E:B2:48:47:39 (random), AD evt type 0, AD data len 15, RSSI -59 - ble_central: eir_found: [AD]: 9 data_len 0 ble_central: eir_found: [AD]: 25 data_len 2 ble_central: eir_found: [AD]: 1 data_len 1 ble_central: eir_found: [AD]: 2 data_len 4 @@ -12,7 +11,6 @@ ble_central: disconnected: [Disconnected]: FD:9E:B2:48:47:39 (random) (reason 0x16) ble_central: start_scan: [Scanning successfully started] ble_central: device_found: [DEVICE]: FD:9E:B2:48:47:39 (random), AD evt type 0, AD data len 15, RSSI -59 - ble_central: eir_found: [AD]: 9 data_len 0 ble_central: eir_found: [AD]: 25 data_len 2 ble_central: eir_found: [AD]: 1 data_len 1 ble_central: eir_found: [AD]: 2 data_len 4 diff --git a/app/tests/ble/profiles/reconnect-then-output-to-selection/snapshot.log b/app/tests/ble/profiles/reconnect-then-output-to-selection/snapshot.log index 2323de6f..c6f2d914 100644 --- a/app/tests/ble/profiles/reconnect-then-output-to-selection/snapshot.log +++ b/app/tests/ble/profiles/reconnect-then-output-to-selection/snapshot.log @@ -2,7 +2,6 @@ ble_central: main: [Bluetooth initialized] ble_central: start_scan: [Scanning successfully started] ble_central: device_found: [DEVICE]: FD:9E:B2:48:47:39 (random), AD evt type 0, AD data len 15, RSSI -59 - ble_central: eir_found: [AD]: 9 data_len 0 ble_central: eir_found: [AD]: 25 data_len 2 ble_central: eir_found: [AD]: 1 data_len 1 ble_central: eir_found: [AD]: 2 data_len 4 @@ -12,7 +11,6 @@ ble_central: disconnected: [Disconnected]: FD:9E:B2:48:47:39 (random) (reason 0x16) ble_central: start_scan: [Scanning successfully started] ble_central: device_found: [DEVICE]: FD:9E:B2:48:47:39 (random), AD evt type 0, AD data len 15, RSSI -59 - ble_central: eir_found: [AD]: 9 data_len 0 ble_central: eir_found: [AD]: 25 data_len 2 ble_central: eir_found: [AD]: 1 data_len 1 ble_central: eir_found: [AD]: 2 data_len 4 diff --git a/app/tests/ble/security/read-hid-after-connect-with-auto-sec/snapshot.log b/app/tests/ble/security/read-hid-after-connect-with-auto-sec/snapshot.log index b8ee29eb..fa40c20a 100644 --- a/app/tests/ble/security/read-hid-after-connect-with-auto-sec/snapshot.log +++ b/app/tests/ble/security/read-hid-after-connect-with-auto-sec/snapshot.log @@ -2,7 +2,6 @@ ble_central: main: [Bluetooth initialized] ble_central: start_scan: [Scanning successfully started] ble_central: device_found: [DEVICE]: FD:9E:B2:48:47:39 (random), AD evt type 0, AD data len 15, RSSI -59 - ble_central: eir_found: [AD]: 9 data_len 0 ble_central: eir_found: [AD]: 25 data_len 2 ble_central: eir_found: [AD]: 1 data_len 1 ble_central: eir_found: [AD]: 2 data_len 4 diff --git a/app/tests/ble/security/read-hid-after-connect-without-auto-sec/snapshot.log b/app/tests/ble/security/read-hid-after-connect-without-auto-sec/snapshot.log index 2157fd03..e32f76af 100644 --- a/app/tests/ble/security/read-hid-after-connect-without-auto-sec/snapshot.log +++ b/app/tests/ble/security/read-hid-after-connect-without-auto-sec/snapshot.log @@ -2,7 +2,6 @@ ble_central: main: [Bluetooth initialized] ble_central: start_scan: [Scanning successfully started] ble_central: device_found: [DEVICE]: FD:9E:B2:48:47:39 (random), AD evt type 0, AD data len 15, RSSI -59 - ble_central: eir_found: [AD]: 9 data_len 0 ble_central: eir_found: [AD]: 25 data_len 2 ble_central: eir_found: [AD]: 1 data_len 1 ble_central: eir_found: [AD]: 2 data_len 4 From 21e1b2acad171536923777433f08fb8313eaab7f Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Wed, 25 Sep 2024 11:06:52 -0600 Subject: [PATCH 027/415] feat: Add RPC thread analysis support. --- app/src/studio/rpc.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/src/studio/rpc.c b/app/src/studio/rpc.c index bd980eb4..7b8dd605 100644 --- a/app/src/studio/rpc.c +++ b/app/src/studio/rpc.c @@ -11,6 +11,7 @@ #include #include +#include #include LOG_MODULE_REGISTER(zmk_studio, CONFIG_ZMK_STUDIO_LOG_LEVEL); @@ -215,6 +216,9 @@ static void rpc_main(void) { for (;;) { pb_istream_t stream = pb_istream_for_rx_ring_buf(); zmk_studio_Request req = zmk_studio_Request_init_zero; +#if IS_ENABLED(CONFIG_THREAD_ANALYZER) + thread_analyzer_print(); +#endif // IS_ENABLED(CONFIG_THREAD_ANALYZER) bool status = pb_decode(&stream, &zmk_studio_Request_msg, &req); rpc_framing_state = FRAMING_STATE_IDLE; @@ -223,6 +227,9 @@ static void rpc_main(void) { zmk_studio_Response resp = handle_request(&req); int err = send_response(&resp); +#if IS_ENABLED(CONFIG_THREAD_ANALYZER) + thread_analyzer_print(); +#endif // IS_ENABLED(CONFIG_THREAD_ANALYZER) if (err < 0) { LOG_ERR("Failed to send the RPC response %d", err); } From 5d4b6df6a7d5bc29675d016d63e0bef899f29a99 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Wed, 25 Sep 2024 16:31:23 -0600 Subject: [PATCH 028/415] feat(studio): Log entry into all RPC. --- app/src/studio/behavior_subsystem.c | 4 +++- app/src/studio/core_subsystem.c | 3 +++ app/src/studio/keymap_subsystem.c | 12 ++++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/app/src/studio/behavior_subsystem.c b/app/src/studio/behavior_subsystem.c index b8d1ef1d..96c1f236 100644 --- a/app/src/studio/behavior_subsystem.c +++ b/app/src/studio/behavior_subsystem.c @@ -33,6 +33,7 @@ static bool encode_behavior_summaries(pb_ostream_t *stream, const pb_field_t *fi } zmk_studio_Response list_all_behaviors(const zmk_studio_Request *req) { + LOG_DBG(""); zmk_behaviors_ListAllBehaviorsResponse beh_resp = zmk_behaviors_ListAllBehaviorsResponse_init_zero; beh_resp.behaviors.funcs.encode = encode_behavior_summaries; @@ -164,9 +165,10 @@ static struct encode_metadata_sets_state state = {}; zmk_studio_Response get_behavior_details(const zmk_studio_Request *req) { uint32_t behavior_id = req->subsystem.behaviors.request_type.get_behavior_details.behavior_id; - const char *behavior_name = zmk_behavior_find_behavior_name_from_local_id(behavior_id); + LOG_DBG("behavior_id %d, name %s", behavior_id, behavior_name); + if (!behavior_name) { LOG_WRN("No behavior found for ID %d", behavior_id); return ZMK_RPC_SIMPLE_ERR(GENERIC); diff --git a/app/src/studio/core_subsystem.c b/app/src/studio/core_subsystem.c index 2cdc9d7c..1739919a 100644 --- a/app/src/studio/core_subsystem.c +++ b/app/src/studio/core_subsystem.c @@ -45,6 +45,7 @@ static bool encode_device_info_serial_number(pb_ostream_t *stream, const pb_fiel #endif // IS_ENABLED(CONFIG_HWINFO) zmk_studio_Response get_device_info(const zmk_studio_Request *req) { + LOG_DBG(""); zmk_core_GetDeviceInfoResponse resp = zmk_core_GetDeviceInfoResponse_init_zero; resp.name.funcs.encode = encode_device_info_name; @@ -56,12 +57,14 @@ zmk_studio_Response get_device_info(const zmk_studio_Request *req) { } zmk_studio_Response get_lock_state(const zmk_studio_Request *req) { + LOG_DBG(""); zmk_core_LockState resp = zmk_studio_core_get_lock_state(); return CORE_RESPONSE(get_lock_state, resp); } zmk_studio_Response reset_settings(const zmk_studio_Request *req) { + LOG_DBG(""); ZMK_RPC_SUBSYSTEM_SETTINGS_RESET_FOREACH(sub) { int ret = sub->callback(); if (ret < 0) { diff --git a/app/src/studio/keymap_subsystem.c b/app/src/studio/keymap_subsystem.c index d734afb6..25297b63 100644 --- a/app/src/studio/keymap_subsystem.c +++ b/app/src/studio/keymap_subsystem.c @@ -98,6 +98,7 @@ static bool encode_keymap_layers(pb_ostream_t *stream, const pb_field_t *field, } zmk_studio_Response get_keymap(const zmk_studio_Request *req) { + LOG_DBG(""); zmk_keymap_Keymap resp = zmk_keymap_Keymap_init_zero; resp.layers.funcs.encode = encode_keymap_layers; @@ -117,6 +118,7 @@ zmk_studio_Response get_keymap(const zmk_studio_Request *req) { } zmk_studio_Response set_layer_binding(const zmk_studio_Request *req) { + LOG_DBG(""); const zmk_keymap_SetLayerBindingRequest *set_req = &req->subsystem.keymap.request_type.set_layer_binding; @@ -165,6 +167,7 @@ zmk_studio_Response set_layer_binding(const zmk_studio_Request *req) { } zmk_studio_Response check_unsaved_changes(const zmk_studio_Request *req) { + LOG_DBG(""); int layout_changes = zmk_physical_layouts_check_unsaved_selection(); int keymap_changes = zmk_keymap_check_unsaved_changes(); @@ -172,6 +175,7 @@ zmk_studio_Response check_unsaved_changes(const zmk_studio_Request *req) { } zmk_studio_Response save_changes(const zmk_studio_Request *req) { + LOG_DBG(""); int ret = zmk_physical_layouts_save_selected(); if (ret < 0) { @@ -192,6 +196,7 @@ zmk_studio_Response save_changes(const zmk_studio_Request *req) { } zmk_studio_Response discard_changes(const zmk_studio_Request *req) { + LOG_DBG(""); int ret = zmk_physical_layouts_revert_selected(); if (ret < 0) { return ZMK_RPC_SIMPLE_ERR(GENERIC); @@ -288,6 +293,7 @@ static bool encode_layouts(pb_ostream_t *stream, const pb_field_t *field, void * } zmk_studio_Response get_physical_layouts(const zmk_studio_Request *req) { + LOG_DBG(""); zmk_keymap_PhysicalLayouts resp = zmk_keymap_PhysicalLayouts_init_zero; resp.active_layout_index = zmk_physical_layouts_get_selected(); resp.layouts.funcs.encode = encode_layouts; @@ -336,6 +342,7 @@ static void migrate_keymap(const uint8_t old) { } zmk_studio_Response set_active_physical_layout(const zmk_studio_Request *req) { + LOG_DBG(""); uint8_t index = (uint8_t)req->subsystem.keymap.request_type.set_active_physical_layout; int old = zmk_physical_layouts_get_selected(); @@ -364,6 +371,7 @@ zmk_studio_Response set_active_physical_layout(const zmk_studio_Request *req) { } zmk_studio_Response move_layer(const zmk_studio_Request *req) { + LOG_DBG(""); const zmk_keymap_MoveLayerRequest *move_req = &req->subsystem.keymap.request_type.move_layer; zmk_keymap_MoveLayerResponse resp = zmk_keymap_MoveLayerResponse_init_zero; @@ -386,6 +394,7 @@ zmk_studio_Response move_layer(const zmk_studio_Request *req) { } zmk_studio_Response add_layer(const zmk_studio_Request *req) { + LOG_DBG(""); // Use a static here to keep the value valid during serialization static zmk_keymap_layer_id_t layer_id = 0; @@ -428,6 +437,7 @@ zmk_studio_Response add_layer(const zmk_studio_Request *req) { } zmk_studio_Response remove_layer(const zmk_studio_Request *req) { + LOG_DBG(""); const zmk_keymap_RemoveLayerRequest *rm_req = &req->subsystem.keymap.request_type.remove_layer; zmk_keymap_RemoveLayerResponse resp = zmk_keymap_RemoveLayerResponse_init_zero; @@ -456,6 +466,7 @@ zmk_studio_Response remove_layer(const zmk_studio_Request *req) { } zmk_studio_Response restore_layer(const zmk_studio_Request *req) { + LOG_DBG(""); const zmk_keymap_RestoreLayerRequest *restore_req = &req->subsystem.keymap.request_type.restore_layer; @@ -492,6 +503,7 @@ zmk_studio_Response restore_layer(const zmk_studio_Request *req) { } zmk_studio_Response set_layer_props(const zmk_studio_Request *req) { + LOG_DBG(""); const zmk_keymap_SetLayerPropsRequest *set_req = &req->subsystem.keymap.request_type.set_layer_props; From 4a8ceba0db8bcd9c1ffda85d14f4b40080cae7fe Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Wed, 25 Sep 2024 18:11:31 -0600 Subject: [PATCH 029/415] chore: Fix keymap const warning. --- app/src/keymap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/keymap.c b/app/src/keymap.c index af94bbfd..ad3c7278 100644 --- a/app/src/keymap.c +++ b/app/src/keymap.c @@ -581,7 +581,7 @@ int zmk_keymap_reset_settings(void) { return -ENOTSUP; } int zmk_keymap_apply_position_state(uint8_t source, zmk_keymap_layer_id_t layer_id, uint32_t position, bool pressed, int64_t timestamp) { - struct zmk_behavior_binding *binding = &zmk_keymap[layer_id][position]; + const struct zmk_behavior_binding *binding = &zmk_keymap[layer_id][position]; struct zmk_behavior_binding_event event = { .layer = layer_id, .position = position, From a17266847dcd5e3e202ed7eb559665f22a10b86e Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Thu, 26 Sep 2024 10:01:14 -0600 Subject: [PATCH 030/415] fix: Force Ubuntu 22.04, pending CI fixes. --- .github/workflows/build-user-config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-user-config.yml b/.github/workflows/build-user-config.yml index c3e4789d..7b4f10b0 100644 --- a/.github/workflows/build-user-config.yml +++ b/.github/workflows/build-user-config.yml @@ -26,7 +26,7 @@ on: jobs: matrix: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 name: Fetch Build Keyboards outputs: build_matrix: ${{ env.build_matrix }} From 1f900bfc9cd8d8946c8855d1ca869dffa45e2a1f Mon Sep 17 00:00:00 2001 From: Nicolas Munnich <98408764+Nick-Munnich@users.noreply.github.com> Date: Thu, 26 Sep 2024 19:49:13 +0200 Subject: [PATCH 031/415] docs: Added a note on bluetooth profiles under "unable to connect to device" (#2509) * docs: Added a note on bluetooth profiles under "unable to connect to device" Co-authored-by: Cem Aksoylar --------- Co-authored-by: Cem Aksoylar --- docs/docs/troubleshooting/connection-issues.mdx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/docs/troubleshooting/connection-issues.mdx b/docs/docs/troubleshooting/connection-issues.mdx index a57a3d20..7de953a9 100644 --- a/docs/docs/troubleshooting/connection-issues.mdx +++ b/docs/docs/troubleshooting/connection-issues.mdx @@ -97,6 +97,10 @@ The settings reset firmware has Bluetooth disabled to prevent the two sides from ## Unable to Connect to Device +### Bluetooth Profiles + +A very common issue is that the wrong Bluetooth profile has been selected, or the Bluetooth profile already has a saved connection. Learn more about Bluetooth profiles [here](../features/bluetooth.md), and learn how to adjust Bluetooth profiles via the `&bt` behavior [here](../keymaps/behaviors/bluetooth.md). + ### Additional Bluetooth Options Some devices and operating systems may have additional restrictions that they require be met before allowing a bluetooth peripheral to pair with them. If your keyboard is visible to your host but you are having issues trouble connecting or no input is registered, this might be the cause. Some of ZMK's [experimental bluetooth settings](../config/bluetooth.md) may suffice to resolve the issue. In particular: From 0a25fa2f95c0d7f5c93ad15ff12f634b11ec2537 Mon Sep 17 00:00:00 2001 From: ReFil <31960031+ReFil@users.noreply.github.com> Date: Mon, 9 Sep 2024 12:57:02 +0100 Subject: [PATCH 032/415] feat(boards): add common keyboard layouts --- .../layouts/common/60percent/60percent.dtsi | 72 ++++++++++++++ app/dts/layouts/common/60percent/all1u.dtsi | 77 +++++++++++++++ app/dts/layouts/common/60percent/ansi.dtsi | 72 ++++++++++++++ app/dts/layouts/common/60percent/hhkb.dtsi | 71 ++++++++++++++ app/dts/layouts/common/60percent/iso.dtsi | 73 ++++++++++++++ .../layouts/common/65percent/65percent.dtsi | 72 ++++++++++++++ app/dts/layouts/common/65percent/all1u.dtsi | 85 ++++++++++++++++ app/dts/layouts/common/65percent/ansi.dtsi | 79 +++++++++++++++ app/dts/layouts/common/65percent/hhkb.dtsi | 76 ++++++++++++++ app/dts/layouts/common/65percent/iso.dtsi | 80 +++++++++++++++ .../layouts/common/75percent/75percent.dtsi | 59 +++++++++++ app/dts/layouts/common/75percent/all1u.dtsi | 98 +++++++++++++++++++ app/dts/layouts/common/75percent/ansi.dtsi | 95 ++++++++++++++++++ app/dts/layouts/common/75percent/iso.dtsi | 96 ++++++++++++++++++ app/dts/layouts/common/ortho_4x12/1x2u.dtsi | 58 +++++++++++ app/dts/layouts/common/ortho_4x12/2x2u.dtsi | 57 +++++++++++ app/dts/layouts/common/ortho_4x12/all1u.dtsi | 59 +++++++++++ .../layouts/common/ortho_4x12/ortho_4x12.dtsi | 53 ++++++++++ app/dts/layouts/common/ortho_5x12/1x2u.dtsi | 70 +++++++++++++ app/dts/layouts/common/ortho_5x12/2x2u.dtsi | 69 +++++++++++++ app/dts/layouts/common/ortho_5x12/all1u.dtsi | 71 ++++++++++++++ .../layouts/common/ortho_5x12/ortho_5x12.dtsi | 56 +++++++++++ app/dts/layouts/common/tkl/ansi.dtsi | 98 +++++++++++++++++++ 23 files changed, 1696 insertions(+) create mode 100644 app/dts/layouts/common/60percent/60percent.dtsi create mode 100644 app/dts/layouts/common/60percent/all1u.dtsi create mode 100644 app/dts/layouts/common/60percent/ansi.dtsi create mode 100644 app/dts/layouts/common/60percent/hhkb.dtsi create mode 100644 app/dts/layouts/common/60percent/iso.dtsi create mode 100644 app/dts/layouts/common/65percent/65percent.dtsi create mode 100644 app/dts/layouts/common/65percent/all1u.dtsi create mode 100644 app/dts/layouts/common/65percent/ansi.dtsi create mode 100644 app/dts/layouts/common/65percent/hhkb.dtsi create mode 100644 app/dts/layouts/common/65percent/iso.dtsi create mode 100644 app/dts/layouts/common/75percent/75percent.dtsi create mode 100644 app/dts/layouts/common/75percent/all1u.dtsi create mode 100644 app/dts/layouts/common/75percent/ansi.dtsi create mode 100644 app/dts/layouts/common/75percent/iso.dtsi create mode 100644 app/dts/layouts/common/ortho_4x12/1x2u.dtsi create mode 100644 app/dts/layouts/common/ortho_4x12/2x2u.dtsi create mode 100644 app/dts/layouts/common/ortho_4x12/all1u.dtsi create mode 100644 app/dts/layouts/common/ortho_4x12/ortho_4x12.dtsi create mode 100644 app/dts/layouts/common/ortho_5x12/1x2u.dtsi create mode 100644 app/dts/layouts/common/ortho_5x12/2x2u.dtsi create mode 100644 app/dts/layouts/common/ortho_5x12/all1u.dtsi create mode 100644 app/dts/layouts/common/ortho_5x12/ortho_5x12.dtsi create mode 100644 app/dts/layouts/common/tkl/ansi.dtsi diff --git a/app/dts/layouts/common/60percent/60percent.dtsi b/app/dts/layouts/common/60percent/60percent.dtsi new file mode 100644 index 00000000..03f42e2a --- /dev/null +++ b/app/dts/layouts/common/60percent/60percent.dtsi @@ -0,0 +1,72 @@ +#include +#include +#include +#include + +&layout_60_ansi { + status = "disabled"; +}; + +&layout_60_iso { + status = "disabled"; +}; + +&layout_60_all1u { + status = "disabled"; +}; + +&layout_60_hhkb { + status = "disabled"; +}; + +/ { + layouts_common_60_percent_position_map: layouts_common_60_percent_position_map { + compatible = "zmk,physical-layout-position-map"; + + complete; + + layout_60_all1u { + physical-layout = <&layout_60_all1u>; + positions + = < 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14> + , <15 16 17 18 19 20 21 22 23 24 25 26 27 28> + , <29 30 31 32 33 34 35 36 37 38 39 40 41> + , <42 43 44 45 46 47 48 49 50 51 52 53 54 55 56> + , <57 58 59 60 61 62 64 63 65> + ; + }; + + layout_60_ansi { + physical-layout = <&layout_60_ansi>; + positions + = < 0 1 2 3 4 5 6 7 8 9 10 11 12 13 61> + , <14 15 16 17 18 19 20 21 22 23 24 25 26 27> + , <28 29 30 31 32 33 34 35 36 37 38 39 40> + , <41 62 42 43 44 45 46 47 48 49 50 51 52 63 64> + , <53 54 55 56 57 58 60 59 65> + ; + }; + + layout_60_hhkb { + physical-layout = <&layout_60_hhkb>; + positions + = < 0 1 2 3 4 5 6 7 8 9 10 11 12 13 60> + , <14 15 16 17 18 19 20 21 22 23 24 25 26 27> + , <28 29 30 31 32 33 34 35 36 37 38 39 40> + , <41 61 42 43 44 45 46 47 48 49 50 51 52 62 63> + , <53 54 55 56 57 58 59 64 65> + ; + }; + + layout_60_iso { + physical-layout = <&layout_60_iso>; + positions + = < 0 1 2 3 4 5 6 7 8 9 10 11 12 13 62> + , <14 15 16 17 18 19 20 21 22 23 24 25 26 63> + , <27 28 29 30 31 32 33 34 35 36 37 38 40> + , <41 42 43 44 45 46 47 48 49 50 51 52 53 64 65> + , <54 55 56 57 58 59 61 60 39> + ; + }; + }; +}; \ No newline at end of file diff --git a/app/dts/layouts/common/60percent/all1u.dtsi b/app/dts/layouts/common/60percent/all1u.dtsi new file mode 100644 index 00000000..47e3ad38 --- /dev/null +++ b/app/dts/layouts/common/60percent/all1u.dtsi @@ -0,0 +1,77 @@ +#include + +/ { + layout_60_all1u: layout_60_all1u { + compatible = "zmk,physical-layout"; + display-name = "60% All 1U"; + + keys // w h x y rot rx ry + = <&key_physical_attrs 100 100 0 0 0 0 0> + , <&key_physical_attrs 100 100 100 0 0 0 0> + , <&key_physical_attrs 100 100 200 0 0 0 0> + , <&key_physical_attrs 100 100 300 0 0 0 0> + , <&key_physical_attrs 100 100 400 0 0 0 0> + , <&key_physical_attrs 100 100 500 0 0 0 0> + , <&key_physical_attrs 100 100 600 0 0 0 0> + , <&key_physical_attrs 100 100 700 0 0 0 0> + , <&key_physical_attrs 100 100 800 0 0 0 0> + , <&key_physical_attrs 100 100 900 0 0 0 0> + , <&key_physical_attrs 100 100 1000 0 0 0 0> + , <&key_physical_attrs 100 100 1100 0 0 0 0> + , <&key_physical_attrs 100 100 1200 0 0 0 0> + , <&key_physical_attrs 100 100 1300 0 0 0 0> + , <&key_physical_attrs 100 100 1400 0 0 0 0> + , <&key_physical_attrs 150 100 0 100 0 0 0> + , <&key_physical_attrs 100 100 150 100 0 0 0> + , <&key_physical_attrs 100 100 250 100 0 0 0> + , <&key_physical_attrs 100 100 350 100 0 0 0> + , <&key_physical_attrs 100 100 450 100 0 0 0> + , <&key_physical_attrs 100 100 550 100 0 0 0> + , <&key_physical_attrs 100 100 650 100 0 0 0> + , <&key_physical_attrs 100 100 750 100 0 0 0> + , <&key_physical_attrs 100 100 850 100 0 0 0> + , <&key_physical_attrs 100 100 950 100 0 0 0> + , <&key_physical_attrs 100 100 1050 100 0 0 0> + , <&key_physical_attrs 100 100 1150 100 0 0 0> + , <&key_physical_attrs 100 100 1250 100 0 0 0> + , <&key_physical_attrs 150 100 1350 100 0 0 0> + , <&key_physical_attrs 175 100 0 200 0 0 0> + , <&key_physical_attrs 100 100 175 200 0 0 0> + , <&key_physical_attrs 100 100 275 200 0 0 0> + , <&key_physical_attrs 100 100 375 200 0 0 0> + , <&key_physical_attrs 100 100 475 200 0 0 0> + , <&key_physical_attrs 100 100 575 200 0 0 0> + , <&key_physical_attrs 100 100 675 200 0 0 0> + , <&key_physical_attrs 100 100 775 200 0 0 0> + , <&key_physical_attrs 100 100 875 200 0 0 0> + , <&key_physical_attrs 100 100 975 200 0 0 0> + , <&key_physical_attrs 100 100 1075 200 0 0 0> + , <&key_physical_attrs 100 100 1175 200 0 0 0> + , <&key_physical_attrs 225 100 1275 200 0 0 0> + , <&key_physical_attrs 100 100 0 300 0 0 0> + , <&key_physical_attrs 100 100 100 300 0 0 0> + , <&key_physical_attrs 100 100 200 300 0 0 0> + , <&key_physical_attrs 100 100 300 300 0 0 0> + , <&key_physical_attrs 100 100 400 300 0 0 0> + , <&key_physical_attrs 100 100 500 300 0 0 0> + , <&key_physical_attrs 100 100 600 300 0 0 0> + , <&key_physical_attrs 100 100 700 300 0 0 0> + , <&key_physical_attrs 100 100 800 300 0 0 0> + , <&key_physical_attrs 100 100 900 300 0 0 0> + , <&key_physical_attrs 100 100 1000 300 0 0 0> + , <&key_physical_attrs 100 100 1100 300 0 0 0> + , <&key_physical_attrs 100 100 1200 300 0 0 0> + , <&key_physical_attrs 100 100 1300 300 0 0 0> + , <&key_physical_attrs 100 100 1400 300 0 0 0> + , <&key_physical_attrs 125 100 0 400 0 0 0> + , <&key_physical_attrs 125 100 125 400 0 0 0> + , <&key_physical_attrs 125 100 250 400 0 0 0> + , <&key_physical_attrs 625 100 375 400 0 0 0> + , <&key_physical_attrs 100 100 1000 400 0 0 0> + , <&key_physical_attrs 100 100 1100 400 0 0 0> + , <&key_physical_attrs 100 100 1200 400 0 0 0> + , <&key_physical_attrs 100 100 1300 400 0 0 0> + , <&key_physical_attrs 100 100 1400 400 0 0 0> + ; + }; +}; \ No newline at end of file diff --git a/app/dts/layouts/common/60percent/ansi.dtsi b/app/dts/layouts/common/60percent/ansi.dtsi new file mode 100644 index 00000000..2c8074bc --- /dev/null +++ b/app/dts/layouts/common/60percent/ansi.dtsi @@ -0,0 +1,72 @@ +#include + +/ { + layout_60_ansi: layout_60_ansi { + compatible = "zmk,physical-layout"; + display-name = "60% ANSI"; + + keys // w h x y rot rx ry + = <&key_physical_attrs 100 100 0 0 0 0 0> + , <&key_physical_attrs 100 100 100 0 0 0 0> + , <&key_physical_attrs 100 100 200 0 0 0 0> + , <&key_physical_attrs 100 100 300 0 0 0 0> + , <&key_physical_attrs 100 100 400 0 0 0 0> + , <&key_physical_attrs 100 100 500 0 0 0 0> + , <&key_physical_attrs 100 100 600 0 0 0 0> + , <&key_physical_attrs 100 100 700 0 0 0 0> + , <&key_physical_attrs 100 100 800 0 0 0 0> + , <&key_physical_attrs 100 100 900 0 0 0 0> + , <&key_physical_attrs 100 100 1000 0 0 0 0> + , <&key_physical_attrs 100 100 1100 0 0 0 0> + , <&key_physical_attrs 100 100 1200 0 0 0 0> + , <&key_physical_attrs 200 100 1300 0 0 0 0> + , <&key_physical_attrs 150 100 0 100 0 0 0> + , <&key_physical_attrs 100 100 150 100 0 0 0> + , <&key_physical_attrs 100 100 250 100 0 0 0> + , <&key_physical_attrs 100 100 350 100 0 0 0> + , <&key_physical_attrs 100 100 450 100 0 0 0> + , <&key_physical_attrs 100 100 550 100 0 0 0> + , <&key_physical_attrs 100 100 650 100 0 0 0> + , <&key_physical_attrs 100 100 750 100 0 0 0> + , <&key_physical_attrs 100 100 850 100 0 0 0> + , <&key_physical_attrs 100 100 950 100 0 0 0> + , <&key_physical_attrs 100 100 1050 100 0 0 0> + , <&key_physical_attrs 100 100 1150 100 0 0 0> + , <&key_physical_attrs 100 100 1250 100 0 0 0> + , <&key_physical_attrs 150 100 1350 100 0 0 0> + , <&key_physical_attrs 175 100 0 200 0 0 0> + , <&key_physical_attrs 100 100 175 200 0 0 0> + , <&key_physical_attrs 100 100 275 200 0 0 0> + , <&key_physical_attrs 100 100 375 200 0 0 0> + , <&key_physical_attrs 100 100 475 200 0 0 0> + , <&key_physical_attrs 100 100 575 200 0 0 0> + , <&key_physical_attrs 100 100 675 200 0 0 0> + , <&key_physical_attrs 100 100 775 200 0 0 0> + , <&key_physical_attrs 100 100 875 200 0 0 0> + , <&key_physical_attrs 100 100 975 200 0 0 0> + , <&key_physical_attrs 100 100 1075 200 0 0 0> + , <&key_physical_attrs 100 100 1175 200 0 0 0> + , <&key_physical_attrs 225 100 1275 200 0 0 0> + , <&key_physical_attrs 225 100 0 300 0 0 0> + , <&key_physical_attrs 100 100 225 300 0 0 0> + , <&key_physical_attrs 100 100 325 300 0 0 0> + , <&key_physical_attrs 100 100 425 300 0 0 0> + , <&key_physical_attrs 100 100 525 300 0 0 0> + , <&key_physical_attrs 100 100 625 300 0 0 0> + , <&key_physical_attrs 100 100 725 300 0 0 0> + , <&key_physical_attrs 100 100 825 300 0 0 0> + , <&key_physical_attrs 100 100 925 300 0 0 0> + , <&key_physical_attrs 100 100 1025 300 0 0 0> + , <&key_physical_attrs 100 100 1125 300 0 0 0> + , <&key_physical_attrs 275 100 1225 300 0 0 0> + , <&key_physical_attrs 125 100 0 400 0 0 0> + , <&key_physical_attrs 125 100 125 400 0 0 0> + , <&key_physical_attrs 125 100 250 400 0 0 0> + , <&key_physical_attrs 625 100 375 400 0 0 0> + , <&key_physical_attrs 125 100 1000 400 0 0 0> + , <&key_physical_attrs 125 100 1125 400 0 0 0> + , <&key_physical_attrs 125 100 1250 400 0 0 0> + , <&key_physical_attrs 125 100 1375 400 0 0 0> + ; + }; +}; \ No newline at end of file diff --git a/app/dts/layouts/common/60percent/hhkb.dtsi b/app/dts/layouts/common/60percent/hhkb.dtsi new file mode 100644 index 00000000..f14e72be --- /dev/null +++ b/app/dts/layouts/common/60percent/hhkb.dtsi @@ -0,0 +1,71 @@ +#include + +/ { + layout_60_hhkb: layout_60_hhkb { + compatible = "zmk,physical-layout"; + display-name = "60% HHKB/Tsangan layout"; + + keys // w h x y rot rx ry + = <&key_physical_attrs 100 100 0 0 0 0 0> + , <&key_physical_attrs 100 100 100 0 0 0 0> + , <&key_physical_attrs 100 100 200 0 0 0 0> + , <&key_physical_attrs 100 100 300 0 0 0 0> + , <&key_physical_attrs 100 100 400 0 0 0 0> + , <&key_physical_attrs 100 100 500 0 0 0 0> + , <&key_physical_attrs 100 100 600 0 0 0 0> + , <&key_physical_attrs 100 100 700 0 0 0 0> + , <&key_physical_attrs 100 100 800 0 0 0 0> + , <&key_physical_attrs 100 100 900 0 0 0 0> + , <&key_physical_attrs 100 100 1000 0 0 0 0> + , <&key_physical_attrs 100 100 1100 0 0 0 0> + , <&key_physical_attrs 100 100 1200 0 0 0 0> + , <&key_physical_attrs 200 100 1300 0 0 0 0> + , <&key_physical_attrs 150 100 0 100 0 0 0> + , <&key_physical_attrs 100 100 150 100 0 0 0> + , <&key_physical_attrs 100 100 250 100 0 0 0> + , <&key_physical_attrs 100 100 350 100 0 0 0> + , <&key_physical_attrs 100 100 450 100 0 0 0> + , <&key_physical_attrs 100 100 550 100 0 0 0> + , <&key_physical_attrs 100 100 650 100 0 0 0> + , <&key_physical_attrs 100 100 750 100 0 0 0> + , <&key_physical_attrs 100 100 850 100 0 0 0> + , <&key_physical_attrs 100 100 950 100 0 0 0> + , <&key_physical_attrs 100 100 1050 100 0 0 0> + , <&key_physical_attrs 100 100 1150 100 0 0 0> + , <&key_physical_attrs 100 100 1250 100 0 0 0> + , <&key_physical_attrs 150 100 1350 100 0 0 0> + , <&key_physical_attrs 175 100 0 200 0 0 0> + , <&key_physical_attrs 100 100 175 200 0 0 0> + , <&key_physical_attrs 100 100 275 200 0 0 0> + , <&key_physical_attrs 100 100 375 200 0 0 0> + , <&key_physical_attrs 100 100 475 200 0 0 0> + , <&key_physical_attrs 100 100 575 200 0 0 0> + , <&key_physical_attrs 100 100 675 200 0 0 0> + , <&key_physical_attrs 100 100 775 200 0 0 0> + , <&key_physical_attrs 100 100 875 200 0 0 0> + , <&key_physical_attrs 100 100 975 200 0 0 0> + , <&key_physical_attrs 100 100 1075 200 0 0 0> + , <&key_physical_attrs 100 100 1175 200 0 0 0> + , <&key_physical_attrs 225 100 1275 200 0 0 0> + , <&key_physical_attrs 225 100 0 300 0 0 0> + , <&key_physical_attrs 100 100 225 300 0 0 0> + , <&key_physical_attrs 100 100 325 300 0 0 0> + , <&key_physical_attrs 100 100 425 300 0 0 0> + , <&key_physical_attrs 100 100 525 300 0 0 0> + , <&key_physical_attrs 100 100 625 300 0 0 0> + , <&key_physical_attrs 100 100 725 300 0 0 0> + , <&key_physical_attrs 100 100 825 300 0 0 0> + , <&key_physical_attrs 100 100 925 300 0 0 0> + , <&key_physical_attrs 100 100 1025 300 0 0 0> + , <&key_physical_attrs 100 100 1125 300 0 0 0> + , <&key_physical_attrs 275 100 1225 300 0 0 0> + , <&key_physical_attrs 150 100 0 400 0 0 0> + , <&key_physical_attrs 100 100 150 400 0 0 0> + , <&key_physical_attrs 150 100 250 400 0 0 0> + , <&key_physical_attrs 700 100 400 400 0 0 0> + , <&key_physical_attrs 150 100 1100 400 0 0 0> + , <&key_physical_attrs 100 100 1250 400 0 0 0> + , <&key_physical_attrs 150 100 1350 400 0 0 0> + ; + }; +}; \ No newline at end of file diff --git a/app/dts/layouts/common/60percent/iso.dtsi b/app/dts/layouts/common/60percent/iso.dtsi new file mode 100644 index 00000000..2e3a00d8 --- /dev/null +++ b/app/dts/layouts/common/60percent/iso.dtsi @@ -0,0 +1,73 @@ +#include + +/ { + layout_60_iso: layout_60_iso { + compatible = "zmk,physical-layout"; + display-name = "60% ISO"; + + keys // w h x y rot rx ry + = <&key_physical_attrs 100 100 0 0 0 0 0> + , <&key_physical_attrs 100 100 100 0 0 0 0> + , <&key_physical_attrs 100 100 200 0 0 0 0> + , <&key_physical_attrs 100 100 300 0 0 0 0> + , <&key_physical_attrs 100 100 400 0 0 0 0> + , <&key_physical_attrs 100 100 500 0 0 0 0> + , <&key_physical_attrs 100 100 600 0 0 0 0> + , <&key_physical_attrs 100 100 700 0 0 0 0> + , <&key_physical_attrs 100 100 800 0 0 0 0> + , <&key_physical_attrs 100 100 900 0 0 0 0> + , <&key_physical_attrs 100 100 1000 0 0 0 0> + , <&key_physical_attrs 100 100 1100 0 0 0 0> + , <&key_physical_attrs 100 100 1200 0 0 0 0> + , <&key_physical_attrs 200 100 1300 0 0 0 0> + , <&key_physical_attrs 150 100 0 100 0 0 0> + , <&key_physical_attrs 100 100 150 100 0 0 0> + , <&key_physical_attrs 100 100 250 100 0 0 0> + , <&key_physical_attrs 100 100 350 100 0 0 0> + , <&key_physical_attrs 100 100 450 100 0 0 0> + , <&key_physical_attrs 100 100 550 100 0 0 0> + , <&key_physical_attrs 100 100 650 100 0 0 0> + , <&key_physical_attrs 100 100 750 100 0 0 0> + , <&key_physical_attrs 100 100 850 100 0 0 0> + , <&key_physical_attrs 100 100 950 100 0 0 0> + , <&key_physical_attrs 100 100 1050 100 0 0 0> + , <&key_physical_attrs 100 100 1150 100 0 0 0> + , <&key_physical_attrs 100 100 1250 100 0 0 0> + , <&key_physical_attrs 175 100 0 200 0 0 0> + , <&key_physical_attrs 100 100 175 200 0 0 0> + , <&key_physical_attrs 100 100 275 200 0 0 0> + , <&key_physical_attrs 100 100 375 200 0 0 0> + , <&key_physical_attrs 100 100 475 200 0 0 0> + , <&key_physical_attrs 100 100 575 200 0 0 0> + , <&key_physical_attrs 100 100 675 200 0 0 0> + , <&key_physical_attrs 100 100 775 200 0 0 0> + , <&key_physical_attrs 100 100 875 200 0 0 0> + , <&key_physical_attrs 100 100 975 200 0 0 0> + , <&key_physical_attrs 100 100 1075 200 0 0 0> + , <&key_physical_attrs 100 100 1175 200 0 0 0> + , <&key_physical_attrs 100 100 1275 200 0 0 0> + , <&key_physical_attrs 125 200 1375 100 0 0 0> + , <&key_physical_attrs 125 100 0 300 0 0 0> + , <&key_physical_attrs 100 100 125 300 0 0 0> + , <&key_physical_attrs 100 100 225 300 0 0 0> + , <&key_physical_attrs 100 100 325 300 0 0 0> + , <&key_physical_attrs 100 100 425 300 0 0 0> + , <&key_physical_attrs 100 100 525 300 0 0 0> + , <&key_physical_attrs 100 100 625 300 0 0 0> + , <&key_physical_attrs 100 100 725 300 0 0 0> + , <&key_physical_attrs 100 100 825 300 0 0 0> + , <&key_physical_attrs 100 100 925 300 0 0 0> + , <&key_physical_attrs 100 100 1025 300 0 0 0> + , <&key_physical_attrs 100 100 1125 300 0 0 0> + , <&key_physical_attrs 275 100 1225 300 0 0 0> + , <&key_physical_attrs 125 100 0 400 0 0 0> + , <&key_physical_attrs 125 100 125 400 0 0 0> + , <&key_physical_attrs 125 100 250 400 0 0 0> + , <&key_physical_attrs 625 100 375 400 0 0 0> + , <&key_physical_attrs 125 100 1000 400 0 0 0> + , <&key_physical_attrs 125 100 1125 400 0 0 0> + , <&key_physical_attrs 125 100 1250 400 0 0 0> + , <&key_physical_attrs 125 100 1375 400 0 0 0> + ; + }; +}; \ No newline at end of file diff --git a/app/dts/layouts/common/65percent/65percent.dtsi b/app/dts/layouts/common/65percent/65percent.dtsi new file mode 100644 index 00000000..9e46d315 --- /dev/null +++ b/app/dts/layouts/common/65percent/65percent.dtsi @@ -0,0 +1,72 @@ +#include +#include +#include +#include + +&layout_65_ansi { + status = "disabled"; +}; + +&layout_65_iso { + status = "disabled"; +}; + +&layout_65_all1u { + status = "disabled"; +}; + +&layout_65_hhkb { + status = "disabled"; +}; + +/ { + layouts_common_65_percent_position_map: layouts_common_65_percent_position_map { + compatible = "zmk,physical-layout-position-map"; + + complete; + + layout_65_all1u { + physical-layout = <&layout_65_all1u>; + positions + = < 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15> + , <16 17 18 19 20 21 22 23 24 25 26 27 28 29 30> + , <31 32 33 34 35 36 37 38 39 40 41 42 43 44> + , <45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60> + , <61 62 63 64 65 66 67 68 69 70> + ; + }; + + layout_65_ansi { + physical-layout = <&layout_65_ansi>; + positions + = < 0 1 2 3 4 5 6 7 8 9 10 11 12 13 68 14> + , <15 16 17 18 19 20 21 22 23 24 25 26 27 28 29> + , <30 31 32 33 34 35 36 37 38 39 40 41 42 43> + , <44 69 45 46 47 48 49 50 51 52 53 54 55 70 56 57> + , <58 59 60 61 62 63 64 65 66 67> + ; + }; + + layout_65_hhkb { + physical-layout = <&layout_65_hhkb>; + positions + = < 0 1 2 3 4 5 6 7 8 9 10 11 12 13 65 14> + , <15 16 17 18 19 20 21 22 23 24 25 26 27 28 29> + , <30 31 32 33 34 35 36 37 38 39 40 41 42 43> + , <44 66 45 46 47 48 49 50 51 52 53 54 55 67 68 56> + , <57 58 59 60 61 62 63 69 70 64> + ; + }; + + layout_65_iso { + physical-layout = <&layout_65_iso>; + positions + = < 0 1 2 3 4 5 6 7 8 9 10 11 12 13 69 14> + , <15 16 17 18 19 20 21 22 23 24 25 26 27 70 28> + , <29 30 31 32 33 34 35 36 37 38 39 40 42 43> + , <44 45 46 47 48 49 50 51 52 53 54 55 56 41 57 58> + , <59 60 61 62 63 64 65 66 67 68> + ; + }; + }; +}; \ No newline at end of file diff --git a/app/dts/layouts/common/65percent/all1u.dtsi b/app/dts/layouts/common/65percent/all1u.dtsi new file mode 100644 index 00000000..8ab62ef2 --- /dev/null +++ b/app/dts/layouts/common/65percent/all1u.dtsi @@ -0,0 +1,85 @@ +#include + +/ { + layout_65_all1u: layout_65_all1u { + compatible = "zmk,physical-layout"; + display-name = "65% All 1U"; + + kscan = <&kscan0>; + transform = <&matrix_transform_65_all1u>; + + keys // w h x y rot rx ry + = <&key_physical_attrs 100 100 0 0 0 0 0> + , <&key_physical_attrs 100 100 100 0 0 0 0> + , <&key_physical_attrs 100 100 200 0 0 0 0> + , <&key_physical_attrs 100 100 300 0 0 0 0> + , <&key_physical_attrs 100 100 400 0 0 0 0> + , <&key_physical_attrs 100 100 500 0 0 0 0> + , <&key_physical_attrs 100 100 600 0 0 0 0> + , <&key_physical_attrs 100 100 700 0 0 0 0> + , <&key_physical_attrs 100 100 800 0 0 0 0> + , <&key_physical_attrs 100 100 900 0 0 0 0> + , <&key_physical_attrs 100 100 1000 0 0 0 0> + , <&key_physical_attrs 100 100 1100 0 0 0 0> + , <&key_physical_attrs 100 100 1200 0 0 0 0> + , <&key_physical_attrs 100 100 1300 0 0 0 0> + , <&key_physical_attrs 100 100 1400 0 0 0 0> + , <&key_physical_attrs 100 100 1500 0 0 0 0> + , <&key_physical_attrs 150 100 0 100 0 0 0> + , <&key_physical_attrs 100 100 150 100 0 0 0> + , <&key_physical_attrs 100 100 250 100 0 0 0> + , <&key_physical_attrs 100 100 350 100 0 0 0> + , <&key_physical_attrs 100 100 450 100 0 0 0> + , <&key_physical_attrs 100 100 550 100 0 0 0> + , <&key_physical_attrs 100 100 650 100 0 0 0> + , <&key_physical_attrs 100 100 750 100 0 0 0> + , <&key_physical_attrs 100 100 850 100 0 0 0> + , <&key_physical_attrs 100 100 950 100 0 0 0> + , <&key_physical_attrs 100 100 1050 100 0 0 0> + , <&key_physical_attrs 100 100 1150 100 0 0 0> + , <&key_physical_attrs 100 100 1250 100 0 0 0> + , <&key_physical_attrs 150 100 1350 100 0 0 0> + , <&key_physical_attrs 100 100 1500 100 0 0 0> + , <&key_physical_attrs 175 100 0 200 0 0 0> + , <&key_physical_attrs 100 100 175 200 0 0 0> + , <&key_physical_attrs 100 100 275 200 0 0 0> + , <&key_physical_attrs 100 100 375 200 0 0 0> + , <&key_physical_attrs 100 100 475 200 0 0 0> + , <&key_physical_attrs 100 100 575 200 0 0 0> + , <&key_physical_attrs 100 100 675 200 0 0 0> + , <&key_physical_attrs 100 100 775 200 0 0 0> + , <&key_physical_attrs 100 100 875 200 0 0 0> + , <&key_physical_attrs 100 100 975 200 0 0 0> + , <&key_physical_attrs 100 100 1075 200 0 0 0> + , <&key_physical_attrs 100 100 1175 200 0 0 0> + , <&key_physical_attrs 225 100 1275 200 0 0 0> + , <&key_physical_attrs 100 100 1500 200 0 0 0> + , <&key_physical_attrs 100 100 0 300 0 0 0> + , <&key_physical_attrs 100 100 100 300 0 0 0> + , <&key_physical_attrs 100 100 200 300 0 0 0> + , <&key_physical_attrs 100 100 300 300 0 0 0> + , <&key_physical_attrs 100 100 400 300 0 0 0> + , <&key_physical_attrs 100 100 500 300 0 0 0> + , <&key_physical_attrs 100 100 600 300 0 0 0> + , <&key_physical_attrs 100 100 700 300 0 0 0> + , <&key_physical_attrs 100 100 800 300 0 0 0> + , <&key_physical_attrs 100 100 900 300 0 0 0> + , <&key_physical_attrs 100 100 1000 300 0 0 0> + , <&key_physical_attrs 100 100 1100 300 0 0 0> + , <&key_physical_attrs 100 100 1200 300 0 0 0> + , <&key_physical_attrs 100 100 1300 300 0 0 0> + , <&key_physical_attrs 100 100 1400 300 0 0 0> + , <&key_physical_attrs 100 100 1500 300 0 0 0> + , <&key_physical_attrs 125 100 0 400 0 0 0> + , <&key_physical_attrs 125 100 125 400 0 0 0> + , <&key_physical_attrs 125 100 250 400 0 0 0> + , <&key_physical_attrs 625 100 375 400 0 0 0> + , <&key_physical_attrs 100 100 1000 400 0 0 0> + , <&key_physical_attrs 100 100 1100 400 0 0 0> + , <&key_physical_attrs 100 100 1200 400 0 0 0> + , <&key_physical_attrs 100 100 1300 400 0 0 0> + , <&key_physical_attrs 100 100 1400 400 0 0 0> + , <&key_physical_attrs 100 100 1500 400 0 0 0> + ; + }; +}; \ No newline at end of file diff --git a/app/dts/layouts/common/65percent/ansi.dtsi b/app/dts/layouts/common/65percent/ansi.dtsi new file mode 100644 index 00000000..9685515c --- /dev/null +++ b/app/dts/layouts/common/65percent/ansi.dtsi @@ -0,0 +1,79 @@ +#include + +/ { + layout_65_ansi: layout_65_ansi { + compatible = "zmk,physical-layout"; + display-name = "65% ANSI"; + + keys // w h x y rot rx ry + = <&key_physical_attrs 100 100 0 0 0 0 0> + , <&key_physical_attrs 100 100 100 0 0 0 0> + , <&key_physical_attrs 100 100 200 0 0 0 0> + , <&key_physical_attrs 100 100 300 0 0 0 0> + , <&key_physical_attrs 100 100 400 0 0 0 0> + , <&key_physical_attrs 100 100 500 0 0 0 0> + , <&key_physical_attrs 100 100 600 0 0 0 0> + , <&key_physical_attrs 100 100 700 0 0 0 0> + , <&key_physical_attrs 100 100 800 0 0 0 0> + , <&key_physical_attrs 100 100 900 0 0 0 0> + , <&key_physical_attrs 100 100 1000 0 0 0 0> + , <&key_physical_attrs 100 100 1100 0 0 0 0> + , <&key_physical_attrs 100 100 1200 0 0 0 0> + , <&key_physical_attrs 200 100 1300 0 0 0 0> + , <&key_physical_attrs 100 100 1500 0 0 0 0> + , <&key_physical_attrs 150 100 0 100 0 0 0> + , <&key_physical_attrs 100 100 150 100 0 0 0> + , <&key_physical_attrs 100 100 250 100 0 0 0> + , <&key_physical_attrs 100 100 350 100 0 0 0> + , <&key_physical_attrs 100 100 450 100 0 0 0> + , <&key_physical_attrs 100 100 550 100 0 0 0> + , <&key_physical_attrs 100 100 650 100 0 0 0> + , <&key_physical_attrs 100 100 750 100 0 0 0> + , <&key_physical_attrs 100 100 850 100 0 0 0> + , <&key_physical_attrs 100 100 950 100 0 0 0> + , <&key_physical_attrs 100 100 1050 100 0 0 0> + , <&key_physical_attrs 100 100 1150 100 0 0 0> + , <&key_physical_attrs 100 100 1250 100 0 0 0> + , <&key_physical_attrs 150 100 1350 100 0 0 0> + , <&key_physical_attrs 100 100 1500 100 0 0 0> + , <&key_physical_attrs 175 100 0 200 0 0 0> + , <&key_physical_attrs 100 100 175 200 0 0 0> + , <&key_physical_attrs 100 100 275 200 0 0 0> + , <&key_physical_attrs 100 100 375 200 0 0 0> + , <&key_physical_attrs 100 100 475 200 0 0 0> + , <&key_physical_attrs 100 100 575 200 0 0 0> + , <&key_physical_attrs 100 100 675 200 0 0 0> + , <&key_physical_attrs 100 100 775 200 0 0 0> + , <&key_physical_attrs 100 100 875 200 0 0 0> + , <&key_physical_attrs 100 100 975 200 0 0 0> + , <&key_physical_attrs 100 100 1075 200 0 0 0> + , <&key_physical_attrs 100 100 1175 200 0 0 0> + , <&key_physical_attrs 225 100 1275 200 0 0 0> + , <&key_physical_attrs 100 100 1500 200 0 0 0> + , <&key_physical_attrs 225 100 0 300 0 0 0> + , <&key_physical_attrs 100 100 225 300 0 0 0> + , <&key_physical_attrs 100 100 325 300 0 0 0> + , <&key_physical_attrs 100 100 425 300 0 0 0> + , <&key_physical_attrs 100 100 525 300 0 0 0> + , <&key_physical_attrs 100 100 625 300 0 0 0> + , <&key_physical_attrs 100 100 725 300 0 0 0> + , <&key_physical_attrs 100 100 825 300 0 0 0> + , <&key_physical_attrs 100 100 925 300 0 0 0> + , <&key_physical_attrs 100 100 1025 300 0 0 0> + , <&key_physical_attrs 100 100 1125 300 0 0 0> + , <&key_physical_attrs 175 100 1225 300 0 0 0> + , <&key_physical_attrs 100 100 1400 300 0 0 0> + , <&key_physical_attrs 100 100 1500 300 0 0 0> + , <&key_physical_attrs 125 100 0 400 0 0 0> + , <&key_physical_attrs 125 100 125 400 0 0 0> + , <&key_physical_attrs 125 100 250 400 0 0 0> + , <&key_physical_attrs 625 100 375 400 0 0 0> + , <&key_physical_attrs 100 100 1000 400 0 0 0> + , <&key_physical_attrs 100 100 1100 400 0 0 0> + , <&key_physical_attrs 100 100 1200 400 0 0 0> + , <&key_physical_attrs 100 100 1300 400 0 0 0> + , <&key_physical_attrs 100 100 1400 400 0 0 0> + , <&key_physical_attrs 100 100 1500 400 0 0 0> + ; + }; +}; \ No newline at end of file diff --git a/app/dts/layouts/common/65percent/hhkb.dtsi b/app/dts/layouts/common/65percent/hhkb.dtsi new file mode 100644 index 00000000..cbadad96 --- /dev/null +++ b/app/dts/layouts/common/65percent/hhkb.dtsi @@ -0,0 +1,76 @@ +#include + +/ { + layout_65_hhkb: layout_65_hhkb { + compatible = "zmk,physical-layout"; + display-name = "65% HHKB/Tsangan"; + + keys // w h x y rot rx ry + = <&key_physical_attrs 100 100 0 0 0 0 0> + , <&key_physical_attrs 100 100 100 0 0 0 0> + , <&key_physical_attrs 100 100 200 0 0 0 0> + , <&key_physical_attrs 100 100 300 0 0 0 0> + , <&key_physical_attrs 100 100 400 0 0 0 0> + , <&key_physical_attrs 100 100 500 0 0 0 0> + , <&key_physical_attrs 100 100 600 0 0 0 0> + , <&key_physical_attrs 100 100 700 0 0 0 0> + , <&key_physical_attrs 100 100 800 0 0 0 0> + , <&key_physical_attrs 100 100 900 0 0 0 0> + , <&key_physical_attrs 100 100 1000 0 0 0 0> + , <&key_physical_attrs 100 100 1100 0 0 0 0> + , <&key_physical_attrs 100 100 1200 0 0 0 0> + , <&key_physical_attrs 200 100 1300 0 0 0 0> + , <&key_physical_attrs 100 100 1500 0 0 0 0> + , <&key_physical_attrs 150 100 0 100 0 0 0> + , <&key_physical_attrs 100 100 150 100 0 0 0> + , <&key_physical_attrs 100 100 250 100 0 0 0> + , <&key_physical_attrs 100 100 350 100 0 0 0> + , <&key_physical_attrs 100 100 450 100 0 0 0> + , <&key_physical_attrs 100 100 550 100 0 0 0> + , <&key_physical_attrs 100 100 650 100 0 0 0> + , <&key_physical_attrs 100 100 750 100 0 0 0> + , <&key_physical_attrs 100 100 850 100 0 0 0> + , <&key_physical_attrs 100 100 950 100 0 0 0> + , <&key_physical_attrs 100 100 1050 100 0 0 0> + , <&key_physical_attrs 100 100 1150 100 0 0 0> + , <&key_physical_attrs 100 100 1250 100 0 0 0> + , <&key_physical_attrs 150 100 1350 100 0 0 0> + , <&key_physical_attrs 100 100 1500 100 0 0 0> + , <&key_physical_attrs 175 100 0 200 0 0 0> + , <&key_physical_attrs 100 100 175 200 0 0 0> + , <&key_physical_attrs 100 100 275 200 0 0 0> + , <&key_physical_attrs 100 100 375 200 0 0 0> + , <&key_physical_attrs 100 100 475 200 0 0 0> + , <&key_physical_attrs 100 100 575 200 0 0 0> + , <&key_physical_attrs 100 100 675 200 0 0 0> + , <&key_physical_attrs 100 100 775 200 0 0 0> + , <&key_physical_attrs 100 100 875 200 0 0 0> + , <&key_physical_attrs 100 100 975 200 0 0 0> + , <&key_physical_attrs 100 100 1075 200 0 0 0> + , <&key_physical_attrs 100 100 1175 200 0 0 0> + , <&key_physical_attrs 225 100 1275 200 0 0 0> + , <&key_physical_attrs 100 100 1500 200 0 0 0> + , <&key_physical_attrs 225 100 0 300 0 0 0> + , <&key_physical_attrs 100 100 225 300 0 0 0> + , <&key_physical_attrs 100 100 325 300 0 0 0> + , <&key_physical_attrs 100 100 425 300 0 0 0> + , <&key_physical_attrs 100 100 525 300 0 0 0> + , <&key_physical_attrs 100 100 625 300 0 0 0> + , <&key_physical_attrs 100 100 725 300 0 0 0> + , <&key_physical_attrs 100 100 825 300 0 0 0> + , <&key_physical_attrs 100 100 925 300 0 0 0> + , <&key_physical_attrs 100 100 1025 300 0 0 0> + , <&key_physical_attrs 100 100 1125 300 0 0 0> + , <&key_physical_attrs 275 100 1225 300 0 0 0> + , <&key_physical_attrs 100 100 1500 300 0 0 0> + , <&key_physical_attrs 150 100 0 400 0 0 0> + , <&key_physical_attrs 100 100 150 400 0 0 0> + , <&key_physical_attrs 150 100 250 400 0 0 0> + , <&key_physical_attrs 700 100 400 400 0 0 0> + , <&key_physical_attrs 150 100 1100 400 0 0 0> + , <&key_physical_attrs 100 100 1250 400 0 0 0> + , <&key_physical_attrs 150 100 1350 400 0 0 0> + , <&key_physical_attrs 100 100 1500 400 0 0 0> + ; + }; +}; \ No newline at end of file diff --git a/app/dts/layouts/common/65percent/iso.dtsi b/app/dts/layouts/common/65percent/iso.dtsi new file mode 100644 index 00000000..3395c614 --- /dev/null +++ b/app/dts/layouts/common/65percent/iso.dtsi @@ -0,0 +1,80 @@ +#include + +/ { + layout_65_iso: layout_65_iso { + compatible = "zmk,physical-layout"; + display-name = "65% ISO"; + + keys // w h x y rot rx ry + = <&key_physical_attrs 100 100 0 0 0 0 0> + , <&key_physical_attrs 100 100 100 0 0 0 0> + , <&key_physical_attrs 100 100 200 0 0 0 0> + , <&key_physical_attrs 100 100 300 0 0 0 0> + , <&key_physical_attrs 100 100 400 0 0 0 0> + , <&key_physical_attrs 100 100 500 0 0 0 0> + , <&key_physical_attrs 100 100 600 0 0 0 0> + , <&key_physical_attrs 100 100 700 0 0 0 0> + , <&key_physical_attrs 100 100 800 0 0 0 0> + , <&key_physical_attrs 100 100 900 0 0 0 0> + , <&key_physical_attrs 100 100 1000 0 0 0 0> + , <&key_physical_attrs 100 100 1100 0 0 0 0> + , <&key_physical_attrs 100 100 1200 0 0 0 0> + , <&key_physical_attrs 200 100 1300 0 0 0 0> + , <&key_physical_attrs 100 100 1500 0 0 0 0> + , <&key_physical_attrs 150 100 0 100 0 0 0> + , <&key_physical_attrs 100 100 150 100 0 0 0> + , <&key_physical_attrs 100 100 250 100 0 0 0> + , <&key_physical_attrs 100 100 350 100 0 0 0> + , <&key_physical_attrs 100 100 450 100 0 0 0> + , <&key_physical_attrs 100 100 550 100 0 0 0> + , <&key_physical_attrs 100 100 650 100 0 0 0> + , <&key_physical_attrs 100 100 750 100 0 0 0> + , <&key_physical_attrs 100 100 850 100 0 0 0> + , <&key_physical_attrs 100 100 950 100 0 0 0> + , <&key_physical_attrs 100 100 1050 100 0 0 0> + , <&key_physical_attrs 100 100 1150 100 0 0 0> + , <&key_physical_attrs 100 100 1250 100 0 0 0> + , <&key_physical_attrs 100 100 1500 100 0 0 0> + , <&key_physical_attrs 175 100 0 200 0 0 0> + , <&key_physical_attrs 100 100 175 200 0 0 0> + , <&key_physical_attrs 100 100 275 200 0 0 0> + , <&key_physical_attrs 100 100 375 200 0 0 0> + , <&key_physical_attrs 100 100 475 200 0 0 0> + , <&key_physical_attrs 100 100 575 200 0 0 0> + , <&key_physical_attrs 100 100 675 200 0 0 0> + , <&key_physical_attrs 100 100 775 200 0 0 0> + , <&key_physical_attrs 100 100 875 200 0 0 0> + , <&key_physical_attrs 100 100 975 200 0 0 0> + , <&key_physical_attrs 100 100 1075 200 0 0 0> + , <&key_physical_attrs 100 100 1175 200 0 0 0> + , <&key_physical_attrs 100 100 1275 200 0 0 0> + , <&key_physical_attrs 125 200 1375 100 0 0 0> + , <&key_physical_attrs 100 100 1500 200 0 0 0> + , <&key_physical_attrs 125 100 0 300 0 0 0> + , <&key_physical_attrs 100 100 125 300 0 0 0> + , <&key_physical_attrs 100 100 225 300 0 0 0> + , <&key_physical_attrs 100 100 325 300 0 0 0> + , <&key_physical_attrs 100 100 425 300 0 0 0> + , <&key_physical_attrs 100 100 525 300 0 0 0> + , <&key_physical_attrs 100 100 625 300 0 0 0> + , <&key_physical_attrs 100 100 725 300 0 0 0> + , <&key_physical_attrs 100 100 825 300 0 0 0> + , <&key_physical_attrs 100 100 925 300 0 0 0> + , <&key_physical_attrs 100 100 1025 300 0 0 0> + , <&key_physical_attrs 100 100 1125 300 0 0 0> + , <&key_physical_attrs 175 100 1225 300 0 0 0> + , <&key_physical_attrs 100 100 1400 300 0 0 0> + , <&key_physical_attrs 100 100 1500 300 0 0 0> + , <&key_physical_attrs 125 100 0 400 0 0 0> + , <&key_physical_attrs 125 100 125 400 0 0 0> + , <&key_physical_attrs 125 100 250 400 0 0 0> + , <&key_physical_attrs 625 100 375 400 0 0 0> + , <&key_physical_attrs 100 100 1000 400 0 0 0> + , <&key_physical_attrs 100 100 1100 400 0 0 0> + , <&key_physical_attrs 100 100 1200 400 0 0 0> + , <&key_physical_attrs 100 100 1300 400 0 0 0> + , <&key_physical_attrs 100 100 1400 400 0 0 0> + , <&key_physical_attrs 100 100 1500 400 0 0 0> + ; + }; +}; \ No newline at end of file diff --git a/app/dts/layouts/common/75percent/75percent.dtsi b/app/dts/layouts/common/75percent/75percent.dtsi new file mode 100644 index 00000000..1781fbd3 --- /dev/null +++ b/app/dts/layouts/common/75percent/75percent.dtsi @@ -0,0 +1,59 @@ +#include +#include +#include + +&layout_75_ansi { + status = "disabled"; +}; + +&layout_75_iso { + status = "disabled"; +}; + +&layout_75_all1u { + status = "disabled"; +}; + +/ { + layouts_common_75_percent_position_map: layouts_common_75_percent_position_map { + compatible = "zmk,physical-layout-position-map"; + + complete; + + layout_75_all1u { + physical-layout = <&layout_75_all1u>; + positions + = < 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15> + , <16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31> + , <32 33 34 35 36 37 38 39 40 41 42 43 44 45 46> + , <47 48 49 50 51 52 53 54 55 56 57 58 59 60> + , <61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76> + , <77 78 79 80 81 82 83 84 85 86> + ; + }; + + layout_75_ansi { + physical-layout = <&layout_75_ansi>; + positions + = < 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15> + , <16 17 18 19 20 21 22 23 24 25 26 27 28 29 84 30> + , <31 32 33 34 35 36 37 38 39 40 41 42 43 44 45> + , <46 47 48 49 50 51 52 53 54 55 56 57 58 59> + , <60 85 61 62 63 64 65 66 67 68 69 70 71 86 72 73> + , <74 75 76 77 78 79 80 81 82 83> + ; + }; + + layout_75_iso { + physical-layout = <&layout_75_iso>; + positions + = < 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15> + , <16 17 18 19 20 21 22 23 24 25 26 27 28 29 85 30> + , <31 32 33 34 35 36 37 38 39 40 41 42 43 86 44> + , <45 46 47 48 49 50 51 52 53 54 55 56 58 59> + , <60 61 62 63 64 65 66 67 68 69 70 71 72 57 73 74> + , <75 76 77 78 79 80 81 82 83 84> + ; + }; + }; +}; \ No newline at end of file diff --git a/app/dts/layouts/common/75percent/all1u.dtsi b/app/dts/layouts/common/75percent/all1u.dtsi new file mode 100644 index 00000000..04c12bdb --- /dev/null +++ b/app/dts/layouts/common/75percent/all1u.dtsi @@ -0,0 +1,98 @@ +#include + +/ { + layout_75_all1u: layout_75_all1u { + compatible = "zmk,physical-layout"; + display-name = "75% All 1U"; + + keys // w h x y rot rx ry + = <&key_physical_attrs 100 100 0 0 0 0 0> + , <&key_physical_attrs 100 100 100 0 0 0 0> + , <&key_physical_attrs 100 100 200 0 0 0 0> + , <&key_physical_attrs 100 100 300 0 0 0 0> + , <&key_physical_attrs 100 100 400 0 0 0 0> + , <&key_physical_attrs 100 100 500 0 0 0 0> + , <&key_physical_attrs 100 100 600 0 0 0 0> + , <&key_physical_attrs 100 100 700 0 0 0 0> + , <&key_physical_attrs 100 100 800 0 0 0 0> + , <&key_physical_attrs 100 100 900 0 0 0 0> + , <&key_physical_attrs 100 100 1000 0 0 0 0> + , <&key_physical_attrs 100 100 1100 0 0 0 0> + , <&key_physical_attrs 100 100 1200 0 0 0 0> + , <&key_physical_attrs 100 100 1300 0 0 0 0> + , <&key_physical_attrs 100 100 1400 0 0 0 0> + , <&key_physical_attrs 100 100 1500 0 0 0 0> + , <&key_physical_attrs 100 100 0 100 0 0 0> + , <&key_physical_attrs 100 100 100 100 0 0 0> + , <&key_physical_attrs 100 100 200 100 0 0 0> + , <&key_physical_attrs 100 100 300 100 0 0 0> + , <&key_physical_attrs 100 100 400 100 0 0 0> + , <&key_physical_attrs 100 100 500 100 0 0 0> + , <&key_physical_attrs 100 100 600 100 0 0 0> + , <&key_physical_attrs 100 100 700 100 0 0 0> + , <&key_physical_attrs 100 100 800 100 0 0 0> + , <&key_physical_attrs 100 100 900 100 0 0 0> + , <&key_physical_attrs 100 100 1000 100 0 0 0> + , <&key_physical_attrs 100 100 1100 100 0 0 0> + , <&key_physical_attrs 100 100 1200 100 0 0 0> + , <&key_physical_attrs 100 100 1300 100 0 0 0> + , <&key_physical_attrs 100 100 1400 100 0 0 0> + , <&key_physical_attrs 100 100 1500 100 0 0 0> + , <&key_physical_attrs 150 100 0 200 0 0 0> + , <&key_physical_attrs 100 100 150 200 0 0 0> + , <&key_physical_attrs 100 100 250 200 0 0 0> + , <&key_physical_attrs 100 100 350 200 0 0 0> + , <&key_physical_attrs 100 100 450 200 0 0 0> + , <&key_physical_attrs 100 100 550 200 0 0 0> + , <&key_physical_attrs 100 100 650 200 0 0 0> + , <&key_physical_attrs 100 100 750 200 0 0 0> + , <&key_physical_attrs 100 100 850 200 0 0 0> + , <&key_physical_attrs 100 100 950 200 0 0 0> + , <&key_physical_attrs 100 100 1050 200 0 0 0> + , <&key_physical_attrs 100 100 1150 200 0 0 0> + , <&key_physical_attrs 100 100 1250 200 0 0 0> + , <&key_physical_attrs 150 100 1350 200 0 0 0> + , <&key_physical_attrs 100 100 1500 200 0 0 0> + , <&key_physical_attrs 175 100 0 300 0 0 0> + , <&key_physical_attrs 100 100 175 300 0 0 0> + , <&key_physical_attrs 100 100 275 300 0 0 0> + , <&key_physical_attrs 100 100 375 300 0 0 0> + , <&key_physical_attrs 100 100 475 300 0 0 0> + , <&key_physical_attrs 100 100 575 300 0 0 0> + , <&key_physical_attrs 100 100 675 300 0 0 0> + , <&key_physical_attrs 100 100 775 300 0 0 0> + , <&key_physical_attrs 100 100 875 300 0 0 0> + , <&key_physical_attrs 100 100 975 300 0 0 0> + , <&key_physical_attrs 100 100 1075 300 0 0 0> + , <&key_physical_attrs 100 100 1175 300 0 0 0> + , <&key_physical_attrs 225 100 1275 300 0 0 0> + , <&key_physical_attrs 100 100 1500 300 0 0 0> + , <&key_physical_attrs 100 100 0 400 0 0 0> + , <&key_physical_attrs 100 100 100 400 0 0 0> + , <&key_physical_attrs 100 100 200 400 0 0 0> + , <&key_physical_attrs 100 100 300 400 0 0 0> + , <&key_physical_attrs 100 100 400 400 0 0 0> + , <&key_physical_attrs 100 100 500 400 0 0 0> + , <&key_physical_attrs 100 100 600 400 0 0 0> + , <&key_physical_attrs 100 100 700 400 0 0 0> + , <&key_physical_attrs 100 100 800 400 0 0 0> + , <&key_physical_attrs 100 100 900 400 0 0 0> + , <&key_physical_attrs 100 100 1000 400 0 0 0> + , <&key_physical_attrs 100 100 1100 400 0 0 0> + , <&key_physical_attrs 100 100 1200 400 0 0 0> + , <&key_physical_attrs 100 100 1300 400 0 0 0> + , <&key_physical_attrs 100 100 1400 400 0 0 0> + , <&key_physical_attrs 100 100 1500 400 0 0 0> + , <&key_physical_attrs 125 100 0 500 0 0 0> + , <&key_physical_attrs 125 100 125 500 0 0 0> + , <&key_physical_attrs 125 100 250 500 0 0 0> + , <&key_physical_attrs 625 100 375 500 0 0 0> + , <&key_physical_attrs 100 100 1000 500 0 0 0> + , <&key_physical_attrs 100 100 1100 500 0 0 0> + , <&key_physical_attrs 100 100 1200 500 0 0 0> + , <&key_physical_attrs 100 100 1300 500 0 0 0> + , <&key_physical_attrs 100 100 1400 500 0 0 0> + , <&key_physical_attrs 100 100 1500 500 0 0 0> + ; + }; +}; \ No newline at end of file diff --git a/app/dts/layouts/common/75percent/ansi.dtsi b/app/dts/layouts/common/75percent/ansi.dtsi new file mode 100644 index 00000000..6c9a65c7 --- /dev/null +++ b/app/dts/layouts/common/75percent/ansi.dtsi @@ -0,0 +1,95 @@ +#include + +/ { + layout_75_ansi: layout_75_ansi { + compatible = "zmk,physical-layout"; + display-name = "75% ANSI"; + + keys // w h x y rot rx ry + = <&key_physical_attrs 100 100 0 0 0 0 0> + , <&key_physical_attrs 100 100 100 0 0 0 0> + , <&key_physical_attrs 100 100 200 0 0 0 0> + , <&key_physical_attrs 100 100 300 0 0 0 0> + , <&key_physical_attrs 100 100 400 0 0 0 0> + , <&key_physical_attrs 100 100 500 0 0 0 0> + , <&key_physical_attrs 100 100 600 0 0 0 0> + , <&key_physical_attrs 100 100 700 0 0 0 0> + , <&key_physical_attrs 100 100 800 0 0 0 0> + , <&key_physical_attrs 100 100 900 0 0 0 0> + , <&key_physical_attrs 100 100 1000 0 0 0 0> + , <&key_physical_attrs 100 100 1100 0 0 0 0> + , <&key_physical_attrs 100 100 1200 0 0 0 0> + , <&key_physical_attrs 100 100 1300 0 0 0 0> + , <&key_physical_attrs 100 100 1400 0 0 0 0> + , <&key_physical_attrs 100 100 1500 0 0 0 0> + , <&key_physical_attrs 100 100 0 100 0 0 0> + , <&key_physical_attrs 100 100 100 100 0 0 0> + , <&key_physical_attrs 100 100 200 100 0 0 0> + , <&key_physical_attrs 100 100 300 100 0 0 0> + , <&key_physical_attrs 100 100 400 100 0 0 0> + , <&key_physical_attrs 100 100 500 100 0 0 0> + , <&key_physical_attrs 100 100 600 100 0 0 0> + , <&key_physical_attrs 100 100 700 100 0 0 0> + , <&key_physical_attrs 100 100 800 100 0 0 0> + , <&key_physical_attrs 100 100 900 100 0 0 0> + , <&key_physical_attrs 100 100 1000 100 0 0 0> + , <&key_physical_attrs 100 100 1100 100 0 0 0> + , <&key_physical_attrs 100 100 1200 100 0 0 0> + , <&key_physical_attrs 200 100 1300 100 0 0 0> + , <&key_physical_attrs 100 100 1500 100 0 0 0> + , <&key_physical_attrs 150 100 0 200 0 0 0> + , <&key_physical_attrs 100 100 150 200 0 0 0> + , <&key_physical_attrs 100 100 250 200 0 0 0> + , <&key_physical_attrs 100 100 350 200 0 0 0> + , <&key_physical_attrs 100 100 450 200 0 0 0> + , <&key_physical_attrs 100 100 550 200 0 0 0> + , <&key_physical_attrs 100 100 650 200 0 0 0> + , <&key_physical_attrs 100 100 750 200 0 0 0> + , <&key_physical_attrs 100 100 850 200 0 0 0> + , <&key_physical_attrs 100 100 950 200 0 0 0> + , <&key_physical_attrs 100 100 1050 200 0 0 0> + , <&key_physical_attrs 100 100 1150 200 0 0 0> + , <&key_physical_attrs 100 100 1250 200 0 0 0> + , <&key_physical_attrs 150 100 1350 200 0 0 0> + , <&key_physical_attrs 100 100 1500 200 0 0 0> + , <&key_physical_attrs 175 100 0 300 0 0 0> + , <&key_physical_attrs 100 100 175 300 0 0 0> + , <&key_physical_attrs 100 100 275 300 0 0 0> + , <&key_physical_attrs 100 100 375 300 0 0 0> + , <&key_physical_attrs 100 100 475 300 0 0 0> + , <&key_physical_attrs 100 100 575 300 0 0 0> + , <&key_physical_attrs 100 100 675 300 0 0 0> + , <&key_physical_attrs 100 100 775 300 0 0 0> + , <&key_physical_attrs 100 100 875 300 0 0 0> + , <&key_physical_attrs 100 100 975 300 0 0 0> + , <&key_physical_attrs 100 100 1075 300 0 0 0> + , <&key_physical_attrs 100 100 1175 300 0 0 0> + , <&key_physical_attrs 225 100 1275 300 0 0 0> + , <&key_physical_attrs 100 100 1500 300 0 0 0> + , <&key_physical_attrs 225 100 0 400 0 0 0> + , <&key_physical_attrs 100 100 225 400 0 0 0> + , <&key_physical_attrs 100 100 325 400 0 0 0> + , <&key_physical_attrs 100 100 425 400 0 0 0> + , <&key_physical_attrs 100 100 525 400 0 0 0> + , <&key_physical_attrs 100 100 625 400 0 0 0> + , <&key_physical_attrs 100 100 725 400 0 0 0> + , <&key_physical_attrs 100 100 825 400 0 0 0> + , <&key_physical_attrs 100 100 925 400 0 0 0> + , <&key_physical_attrs 100 100 1025 400 0 0 0> + , <&key_physical_attrs 100 100 1125 400 0 0 0> + , <&key_physical_attrs 175 100 1225 400 0 0 0> + , <&key_physical_attrs 100 100 1400 400 0 0 0> + , <&key_physical_attrs 100 100 1500 400 0 0 0> + , <&key_physical_attrs 125 100 0 500 0 0 0> + , <&key_physical_attrs 125 100 125 500 0 0 0> + , <&key_physical_attrs 125 100 250 500 0 0 0> + , <&key_physical_attrs 625 100 375 500 0 0 0> + , <&key_physical_attrs 100 100 1000 500 0 0 0> + , <&key_physical_attrs 100 100 1100 500 0 0 0> + , <&key_physical_attrs 100 100 1200 500 0 0 0> + , <&key_physical_attrs 100 100 1300 500 0 0 0> + , <&key_physical_attrs 100 100 1400 500 0 0 0> + , <&key_physical_attrs 100 100 1500 500 0 0 0> + ; + }; +}; \ No newline at end of file diff --git a/app/dts/layouts/common/75percent/iso.dtsi b/app/dts/layouts/common/75percent/iso.dtsi new file mode 100644 index 00000000..f3ee0c51 --- /dev/null +++ b/app/dts/layouts/common/75percent/iso.dtsi @@ -0,0 +1,96 @@ +#include + +/ { + layout_75_iso: layout_75_iso { + compatible = "zmk,physical-layout"; + display-name = "75% ISO"; + + keys // w h x y rot rx ry + = <&key_physical_attrs 100 100 0 0 0 0 0> + , <&key_physical_attrs 100 100 100 0 0 0 0> + , <&key_physical_attrs 100 100 200 0 0 0 0> + , <&key_physical_attrs 100 100 300 0 0 0 0> + , <&key_physical_attrs 100 100 400 0 0 0 0> + , <&key_physical_attrs 100 100 500 0 0 0 0> + , <&key_physical_attrs 100 100 600 0 0 0 0> + , <&key_physical_attrs 100 100 700 0 0 0 0> + , <&key_physical_attrs 100 100 800 0 0 0 0> + , <&key_physical_attrs 100 100 900 0 0 0 0> + , <&key_physical_attrs 100 100 1000 0 0 0 0> + , <&key_physical_attrs 100 100 1100 0 0 0 0> + , <&key_physical_attrs 100 100 1200 0 0 0 0> + , <&key_physical_attrs 100 100 1300 0 0 0 0> + , <&key_physical_attrs 100 100 1400 0 0 0 0> + , <&key_physical_attrs 100 100 1500 0 0 0 0> + , <&key_physical_attrs 100 100 0 100 0 0 0> + , <&key_physical_attrs 100 100 100 100 0 0 0> + , <&key_physical_attrs 100 100 200 100 0 0 0> + , <&key_physical_attrs 100 100 300 100 0 0 0> + , <&key_physical_attrs 100 100 400 100 0 0 0> + , <&key_physical_attrs 100 100 500 100 0 0 0> + , <&key_physical_attrs 100 100 600 100 0 0 0> + , <&key_physical_attrs 100 100 700 100 0 0 0> + , <&key_physical_attrs 100 100 800 100 0 0 0> + , <&key_physical_attrs 100 100 900 100 0 0 0> + , <&key_physical_attrs 100 100 1000 100 0 0 0> + , <&key_physical_attrs 100 100 1100 100 0 0 0> + , <&key_physical_attrs 100 100 1200 100 0 0 0> + , <&key_physical_attrs 200 100 1300 100 0 0 0> + , <&key_physical_attrs 100 100 1500 100 0 0 0> + , <&key_physical_attrs 150 100 0 200 0 0 0> + , <&key_physical_attrs 100 100 150 200 0 0 0> + , <&key_physical_attrs 100 100 250 200 0 0 0> + , <&key_physical_attrs 100 100 350 200 0 0 0> + , <&key_physical_attrs 100 100 450 200 0 0 0> + , <&key_physical_attrs 100 100 550 200 0 0 0> + , <&key_physical_attrs 100 100 650 200 0 0 0> + , <&key_physical_attrs 100 100 750 200 0 0 0> + , <&key_physical_attrs 100 100 850 200 0 0 0> + , <&key_physical_attrs 100 100 950 200 0 0 0> + , <&key_physical_attrs 100 100 1050 200 0 0 0> + , <&key_physical_attrs 100 100 1150 200 0 0 0> + , <&key_physical_attrs 100 100 1250 200 0 0 0> + , <&key_physical_attrs 100 100 1500 200 0 0 0> + , <&key_physical_attrs 175 100 0 300 0 0 0> + , <&key_physical_attrs 100 100 175 300 0 0 0> + , <&key_physical_attrs 100 100 275 300 0 0 0> + , <&key_physical_attrs 100 100 375 300 0 0 0> + , <&key_physical_attrs 100 100 475 300 0 0 0> + , <&key_physical_attrs 100 100 575 300 0 0 0> + , <&key_physical_attrs 100 100 675 300 0 0 0> + , <&key_physical_attrs 100 100 775 300 0 0 0> + , <&key_physical_attrs 100 100 875 300 0 0 0> + , <&key_physical_attrs 100 100 975 300 0 0 0> + , <&key_physical_attrs 100 100 1075 300 0 0 0> + , <&key_physical_attrs 100 100 1175 300 0 0 0> + , <&key_physical_attrs 100 100 1275 300 0 0 0> + , <&key_physical_attrs 125 200 1375 200 0 0 0> + , <&key_physical_attrs 100 100 1500 300 0 0 0> + , <&key_physical_attrs 125 100 0 400 0 0 0> + , <&key_physical_attrs 100 100 125 400 0 0 0> + , <&key_physical_attrs 100 100 225 400 0 0 0> + , <&key_physical_attrs 100 100 325 400 0 0 0> + , <&key_physical_attrs 100 100 425 400 0 0 0> + , <&key_physical_attrs 100 100 525 400 0 0 0> + , <&key_physical_attrs 100 100 625 400 0 0 0> + , <&key_physical_attrs 100 100 725 400 0 0 0> + , <&key_physical_attrs 100 100 825 400 0 0 0> + , <&key_physical_attrs 100 100 925 400 0 0 0> + , <&key_physical_attrs 100 100 1025 400 0 0 0> + , <&key_physical_attrs 100 100 1125 400 0 0 0> + , <&key_physical_attrs 175 100 1225 400 0 0 0> + , <&key_physical_attrs 100 100 1400 400 0 0 0> + , <&key_physical_attrs 100 100 1500 400 0 0 0> + , <&key_physical_attrs 125 100 0 500 0 0 0> + , <&key_physical_attrs 125 100 125 500 0 0 0> + , <&key_physical_attrs 125 100 250 500 0 0 0> + , <&key_physical_attrs 625 100 375 500 0 0 0> + , <&key_physical_attrs 100 100 1000 500 0 0 0> + , <&key_physical_attrs 100 100 1100 500 0 0 0> + , <&key_physical_attrs 100 100 1200 500 0 0 0> + , <&key_physical_attrs 100 100 1300 500 0 0 0> + , <&key_physical_attrs 100 100 1400 500 0 0 0> + , <&key_physical_attrs 100 100 1500 500 0 0 0> + ; + }; +}; \ No newline at end of file diff --git a/app/dts/layouts/common/ortho_4x12/1x2u.dtsi b/app/dts/layouts/common/ortho_4x12/1x2u.dtsi new file mode 100644 index 00000000..23646afc --- /dev/null +++ b/app/dts/layouts/common/ortho_4x12/1x2u.dtsi @@ -0,0 +1,58 @@ +#include + +/ { + layout_ortho_4x12_1x2u: layout_ortho_4x12_1x2u { + compatible = "zmk,physical-layout"; + display-name = "40% 1x2U Space"; + + keys // w h x y rot rx ry + = <&key_physical_attrs 100 100 0 0 0 0 0> + , <&key_physical_attrs 100 100 100 0 0 0 0> + , <&key_physical_attrs 100 100 200 0 0 0 0> + , <&key_physical_attrs 100 100 300 0 0 0 0> + , <&key_physical_attrs 100 100 400 0 0 0 0> + , <&key_physical_attrs 100 100 500 0 0 0 0> + , <&key_physical_attrs 100 100 600 0 0 0 0> + , <&key_physical_attrs 100 100 700 0 0 0 0> + , <&key_physical_attrs 100 100 800 0 0 0 0> + , <&key_physical_attrs 100 100 900 0 0 0 0> + , <&key_physical_attrs 100 100 1000 0 0 0 0> + , <&key_physical_attrs 100 100 1100 0 0 0 0> + , <&key_physical_attrs 100 100 0 100 0 0 0> + , <&key_physical_attrs 100 100 100 100 0 0 0> + , <&key_physical_attrs 100 100 200 100 0 0 0> + , <&key_physical_attrs 100 100 300 100 0 0 0> + , <&key_physical_attrs 100 100 400 100 0 0 0> + , <&key_physical_attrs 100 100 500 100 0 0 0> + , <&key_physical_attrs 100 100 600 100 0 0 0> + , <&key_physical_attrs 100 100 700 100 0 0 0> + , <&key_physical_attrs 100 100 800 100 0 0 0> + , <&key_physical_attrs 100 100 900 100 0 0 0> + , <&key_physical_attrs 100 100 1000 100 0 0 0> + , <&key_physical_attrs 100 100 1100 100 0 0 0> + , <&key_physical_attrs 100 100 0 200 0 0 0> + , <&key_physical_attrs 100 100 100 200 0 0 0> + , <&key_physical_attrs 100 100 200 200 0 0 0> + , <&key_physical_attrs 100 100 300 200 0 0 0> + , <&key_physical_attrs 100 100 400 200 0 0 0> + , <&key_physical_attrs 100 100 500 200 0 0 0> + , <&key_physical_attrs 100 100 600 200 0 0 0> + , <&key_physical_attrs 100 100 700 200 0 0 0> + , <&key_physical_attrs 100 100 800 200 0 0 0> + , <&key_physical_attrs 100 100 900 200 0 0 0> + , <&key_physical_attrs 100 100 1000 200 0 0 0> + , <&key_physical_attrs 100 100 1100 200 0 0 0> + , <&key_physical_attrs 100 100 0 300 0 0 0> + , <&key_physical_attrs 100 100 100 300 0 0 0> + , <&key_physical_attrs 100 100 200 300 0 0 0> + , <&key_physical_attrs 100 100 300 300 0 0 0> + , <&key_physical_attrs 100 100 400 300 0 0 0> + , <&key_physical_attrs 200 100 500 300 0 0 0> + , <&key_physical_attrs 100 100 700 300 0 0 0> + , <&key_physical_attrs 100 100 800 300 0 0 0> + , <&key_physical_attrs 100 100 900 300 0 0 0> + , <&key_physical_attrs 100 100 1000 300 0 0 0> + , <&key_physical_attrs 100 100 1100 300 0 0 0> + ; + }; +}; \ No newline at end of file diff --git a/app/dts/layouts/common/ortho_4x12/2x2u.dtsi b/app/dts/layouts/common/ortho_4x12/2x2u.dtsi new file mode 100644 index 00000000..d0917869 --- /dev/null +++ b/app/dts/layouts/common/ortho_4x12/2x2u.dtsi @@ -0,0 +1,57 @@ +#include + +/ { + layout_ortho_4x12_2x2u: layout_ortho_4x12_2x2u { + compatible = "zmk,physical-layout"; + display-name = "40% 2x2U Space"; + + keys // w h x y rot rx ry + = <&key_physical_attrs 100 100 0 0 0 0 0> + , <&key_physical_attrs 100 100 100 0 0 0 0> + , <&key_physical_attrs 100 100 200 0 0 0 0> + , <&key_physical_attrs 100 100 300 0 0 0 0> + , <&key_physical_attrs 100 100 400 0 0 0 0> + , <&key_physical_attrs 100 100 500 0 0 0 0> + , <&key_physical_attrs 100 100 600 0 0 0 0> + , <&key_physical_attrs 100 100 700 0 0 0 0> + , <&key_physical_attrs 100 100 800 0 0 0 0> + , <&key_physical_attrs 100 100 900 0 0 0 0> + , <&key_physical_attrs 100 100 1000 0 0 0 0> + , <&key_physical_attrs 100 100 1100 0 0 0 0> + , <&key_physical_attrs 100 100 0 100 0 0 0> + , <&key_physical_attrs 100 100 100 100 0 0 0> + , <&key_physical_attrs 100 100 200 100 0 0 0> + , <&key_physical_attrs 100 100 300 100 0 0 0> + , <&key_physical_attrs 100 100 400 100 0 0 0> + , <&key_physical_attrs 100 100 500 100 0 0 0> + , <&key_physical_attrs 100 100 600 100 0 0 0> + , <&key_physical_attrs 100 100 700 100 0 0 0> + , <&key_physical_attrs 100 100 800 100 0 0 0> + , <&key_physical_attrs 100 100 900 100 0 0 0> + , <&key_physical_attrs 100 100 1000 100 0 0 0> + , <&key_physical_attrs 100 100 1100 100 0 0 0> + , <&key_physical_attrs 100 100 0 200 0 0 0> + , <&key_physical_attrs 100 100 100 200 0 0 0> + , <&key_physical_attrs 100 100 200 200 0 0 0> + , <&key_physical_attrs 100 100 300 200 0 0 0> + , <&key_physical_attrs 100 100 400 200 0 0 0> + , <&key_physical_attrs 100 100 500 200 0 0 0> + , <&key_physical_attrs 100 100 600 200 0 0 0> + , <&key_physical_attrs 100 100 700 200 0 0 0> + , <&key_physical_attrs 100 100 800 200 0 0 0> + , <&key_physical_attrs 100 100 900 200 0 0 0> + , <&key_physical_attrs 100 100 1000 200 0 0 0> + , <&key_physical_attrs 100 100 1100 200 0 0 0> + , <&key_physical_attrs 100 100 0 300 0 0 0> + , <&key_physical_attrs 100 100 100 300 0 0 0> + , <&key_physical_attrs 100 100 200 300 0 0 0> + , <&key_physical_attrs 100 100 300 300 0 0 0> + , <&key_physical_attrs 200 100 400 300 0 0 0> + , <&key_physical_attrs 200 100 600 300 0 0 0> + , <&key_physical_attrs 100 100 800 300 0 0 0> + , <&key_physical_attrs 100 100 900 300 0 0 0> + , <&key_physical_attrs 100 100 1000 300 0 0 0> + , <&key_physical_attrs 100 100 1100 300 0 0 0> + ; + }; +}; \ No newline at end of file diff --git a/app/dts/layouts/common/ortho_4x12/all1u.dtsi b/app/dts/layouts/common/ortho_4x12/all1u.dtsi new file mode 100644 index 00000000..323821d4 --- /dev/null +++ b/app/dts/layouts/common/ortho_4x12/all1u.dtsi @@ -0,0 +1,59 @@ +#include + +/ { + layout_ortho_4x12_all1u: layout_ortho_4x12_all1u { + compatible = "zmk,physical-layout"; + display-name = "40% All 1U/Grid"; + + keys // w h x y rot rx ry + = <&key_physical_attrs 100 100 0 0 0 0 0> + , <&key_physical_attrs 100 100 100 0 0 0 0> + , <&key_physical_attrs 100 100 200 0 0 0 0> + , <&key_physical_attrs 100 100 300 0 0 0 0> + , <&key_physical_attrs 100 100 400 0 0 0 0> + , <&key_physical_attrs 100 100 500 0 0 0 0> + , <&key_physical_attrs 100 100 600 0 0 0 0> + , <&key_physical_attrs 100 100 700 0 0 0 0> + , <&key_physical_attrs 100 100 800 0 0 0 0> + , <&key_physical_attrs 100 100 900 0 0 0 0> + , <&key_physical_attrs 100 100 1000 0 0 0 0> + , <&key_physical_attrs 100 100 1100 0 0 0 0> + , <&key_physical_attrs 100 100 0 100 0 0 0> + , <&key_physical_attrs 100 100 100 100 0 0 0> + , <&key_physical_attrs 100 100 200 100 0 0 0> + , <&key_physical_attrs 100 100 300 100 0 0 0> + , <&key_physical_attrs 100 100 400 100 0 0 0> + , <&key_physical_attrs 100 100 500 100 0 0 0> + , <&key_physical_attrs 100 100 600 100 0 0 0> + , <&key_physical_attrs 100 100 700 100 0 0 0> + , <&key_physical_attrs 100 100 800 100 0 0 0> + , <&key_physical_attrs 100 100 900 100 0 0 0> + , <&key_physical_attrs 100 100 1000 100 0 0 0> + , <&key_physical_attrs 100 100 1100 100 0 0 0> + , <&key_physical_attrs 100 100 0 200 0 0 0> + , <&key_physical_attrs 100 100 100 200 0 0 0> + , <&key_physical_attrs 100 100 200 200 0 0 0> + , <&key_physical_attrs 100 100 300 200 0 0 0> + , <&key_physical_attrs 100 100 400 200 0 0 0> + , <&key_physical_attrs 100 100 500 200 0 0 0> + , <&key_physical_attrs 100 100 600 200 0 0 0> + , <&key_physical_attrs 100 100 700 200 0 0 0> + , <&key_physical_attrs 100 100 800 200 0 0 0> + , <&key_physical_attrs 100 100 900 200 0 0 0> + , <&key_physical_attrs 100 100 1000 200 0 0 0> + , <&key_physical_attrs 100 100 1100 200 0 0 0> + , <&key_physical_attrs 100 100 0 300 0 0 0> + , <&key_physical_attrs 100 100 100 300 0 0 0> + , <&key_physical_attrs 100 100 200 300 0 0 0> + , <&key_physical_attrs 100 100 300 300 0 0 0> + , <&key_physical_attrs 100 100 400 300 0 0 0> + , <&key_physical_attrs 100 100 500 300 0 0 0> + , <&key_physical_attrs 100 100 600 300 0 0 0> + , <&key_physical_attrs 100 100 700 300 0 0 0> + , <&key_physical_attrs 100 100 800 300 0 0 0> + , <&key_physical_attrs 100 100 900 300 0 0 0> + , <&key_physical_attrs 100 100 1000 300 0 0 0> + , <&key_physical_attrs 100 100 1100 300 0 0 0> + ; + }; +}; \ No newline at end of file diff --git a/app/dts/layouts/common/ortho_4x12/ortho_4x12.dtsi b/app/dts/layouts/common/ortho_4x12/ortho_4x12.dtsi new file mode 100644 index 00000000..0c361b10 --- /dev/null +++ b/app/dts/layouts/common/ortho_4x12/ortho_4x12.dtsi @@ -0,0 +1,53 @@ +#include +#include +#include + +&layout_ortho_4x12_all1u { + status = "disabled"; +}; + +&layout_ortho_4x12_1x2u { + status = "disabled"; +}; + +&layout_ortho_4x12_2x2u { + status = "disabled"; +}; + +/ { + layouts_common_ortho_4x12_position_map: layouts_common_ortho_4x12_position_map { + compatible = "zmk,physical-layout-position-map"; + + complete; + + layout_ortho_4x12_all1u { + physical-layout = <&layout_ortho_4x12_all1u>; + positions + = < 0 1 2 3 4 5 6 7 8 9 10 11> + , <12 13 14 15 16 17 18 19 20 21 22 23> + , <24 25 26 27 28 29 30 31 32 33 34 35> + , <36 37 38 39 40 41 42 43 44 45 46 47> + ; + }; + + layout_ortho_4x12_2x2u { + physical-layout = <&layout_ortho_4x12_2x2u>; + positions + = < 0 1 2 3 4 5 6 7 8 9 10 11> + , <12 13 14 15 16 17 18 19 20 21 22 23> + , <24 25 26 27 28 29 30 31 32 33 34 35> + , <36 37 38 39 40 46 47 41 42 43 44 45> + ; + }; + + layout_ortho_4x12_1x2u { + physical-layout = <&layout_ortho_4x12_1x2u>; + positions + = < 0 1 2 3 4 5 6 7 8 9 10 11> + , <12 13 14 15 16 17 18 19 20 21 22 23> + , <24 25 26 27 28 29 30 31 32 33 34 35> + , <36 37 38 39 40 41 47 42 43 44 45 46> + ; + }; + }; +}; \ No newline at end of file diff --git a/app/dts/layouts/common/ortho_5x12/1x2u.dtsi b/app/dts/layouts/common/ortho_5x12/1x2u.dtsi new file mode 100644 index 00000000..2072cc35 --- /dev/null +++ b/app/dts/layouts/common/ortho_5x12/1x2u.dtsi @@ -0,0 +1,70 @@ +#include + +/ { + layout_ortho_5x12_1x2u: layout_ortho_5x12_1x2u { + compatible = "zmk,physical-layout"; + display-name = "50% 1x2U Space"; + + keys // w h x y rot rx ry + = <&key_physical_attrs 100 100 0 0 0 0 0> + , <&key_physical_attrs 100 100 100 0 0 0 0> + , <&key_physical_attrs 100 100 200 0 0 0 0> + , <&key_physical_attrs 100 100 300 0 0 0 0> + , <&key_physical_attrs 100 100 400 0 0 0 0> + , <&key_physical_attrs 100 100 500 0 0 0 0> + , <&key_physical_attrs 100 100 600 0 0 0 0> + , <&key_physical_attrs 100 100 700 0 0 0 0> + , <&key_physical_attrs 100 100 800 0 0 0 0> + , <&key_physical_attrs 100 100 900 0 0 0 0> + , <&key_physical_attrs 100 100 1000 0 0 0 0> + , <&key_physical_attrs 100 100 1100 0 0 0 0> + , <&key_physical_attrs 100 100 0 100 0 0 0> + , <&key_physical_attrs 100 100 100 100 0 0 0> + , <&key_physical_attrs 100 100 200 100 0 0 0> + , <&key_physical_attrs 100 100 300 100 0 0 0> + , <&key_physical_attrs 100 100 400 100 0 0 0> + , <&key_physical_attrs 100 100 500 100 0 0 0> + , <&key_physical_attrs 100 100 600 100 0 0 0> + , <&key_physical_attrs 100 100 700 100 0 0 0> + , <&key_physical_attrs 100 100 800 100 0 0 0> + , <&key_physical_attrs 100 100 900 100 0 0 0> + , <&key_physical_attrs 100 100 1000 100 0 0 0> + , <&key_physical_attrs 100 100 1100 100 0 0 0> + , <&key_physical_attrs 100 100 0 200 0 0 0> + , <&key_physical_attrs 100 100 100 200 0 0 0> + , <&key_physical_attrs 100 100 200 200 0 0 0> + , <&key_physical_attrs 100 100 300 200 0 0 0> + , <&key_physical_attrs 100 100 400 200 0 0 0> + , <&key_physical_attrs 100 100 500 200 0 0 0> + , <&key_physical_attrs 100 100 600 200 0 0 0> + , <&key_physical_attrs 100 100 700 200 0 0 0> + , <&key_physical_attrs 100 100 800 200 0 0 0> + , <&key_physical_attrs 100 100 900 200 0 0 0> + , <&key_physical_attrs 100 100 1000 200 0 0 0> + , <&key_physical_attrs 100 100 1100 200 0 0 0> + , <&key_physical_attrs 100 100 0 300 0 0 0> + , <&key_physical_attrs 100 100 100 300 0 0 0> + , <&key_physical_attrs 100 100 200 300 0 0 0> + , <&key_physical_attrs 100 100 300 300 0 0 0> + , <&key_physical_attrs 100 100 400 300 0 0 0> + , <&key_physical_attrs 100 100 500 300 0 0 0> + , <&key_physical_attrs 100 100 600 300 0 0 0> + , <&key_physical_attrs 100 100 700 300 0 0 0> + , <&key_physical_attrs 100 100 800 300 0 0 0> + , <&key_physical_attrs 100 100 900 300 0 0 0> + , <&key_physical_attrs 100 100 1000 300 0 0 0> + , <&key_physical_attrs 100 100 1100 300 0 0 0> + , <&key_physical_attrs 100 100 0 400 0 0 0> + , <&key_physical_attrs 100 100 100 400 0 0 0> + , <&key_physical_attrs 100 100 200 400 0 0 0> + , <&key_physical_attrs 100 100 300 400 0 0 0> + , <&key_physical_attrs 100 100 400 400 0 0 0> + , <&key_physical_attrs 200 100 500 400 0 0 0> + , <&key_physical_attrs 100 100 700 400 0 0 0> + , <&key_physical_attrs 100 100 800 400 0 0 0> + , <&key_physical_attrs 100 100 900 400 0 0 0> + , <&key_physical_attrs 100 100 1000 400 0 0 0> + , <&key_physical_attrs 100 100 1100 400 0 0 0> + ; + }; +}; \ No newline at end of file diff --git a/app/dts/layouts/common/ortho_5x12/2x2u.dtsi b/app/dts/layouts/common/ortho_5x12/2x2u.dtsi new file mode 100644 index 00000000..5e55f734 --- /dev/null +++ b/app/dts/layouts/common/ortho_5x12/2x2u.dtsi @@ -0,0 +1,69 @@ +#include + +/ { + layout_ortho_5x12_2x2u: layout_ortho_5x12_2x2u { + compatible = "zmk,physical-layout"; + display-name = "50% 2x2U Space"; + + keys // w h x y rot rx ry + = <&key_physical_attrs 100 100 0 0 0 0 0> + , <&key_physical_attrs 100 100 100 0 0 0 0> + , <&key_physical_attrs 100 100 200 0 0 0 0> + , <&key_physical_attrs 100 100 300 0 0 0 0> + , <&key_physical_attrs 100 100 400 0 0 0 0> + , <&key_physical_attrs 100 100 500 0 0 0 0> + , <&key_physical_attrs 100 100 600 0 0 0 0> + , <&key_physical_attrs 100 100 700 0 0 0 0> + , <&key_physical_attrs 100 100 800 0 0 0 0> + , <&key_physical_attrs 100 100 900 0 0 0 0> + , <&key_physical_attrs 100 100 1000 0 0 0 0> + , <&key_physical_attrs 100 100 1100 0 0 0 0> + , <&key_physical_attrs 100 100 0 100 0 0 0> + , <&key_physical_attrs 100 100 100 100 0 0 0> + , <&key_physical_attrs 100 100 200 100 0 0 0> + , <&key_physical_attrs 100 100 300 100 0 0 0> + , <&key_physical_attrs 100 100 400 100 0 0 0> + , <&key_physical_attrs 100 100 500 100 0 0 0> + , <&key_physical_attrs 100 100 600 100 0 0 0> + , <&key_physical_attrs 100 100 700 100 0 0 0> + , <&key_physical_attrs 100 100 800 100 0 0 0> + , <&key_physical_attrs 100 100 900 100 0 0 0> + , <&key_physical_attrs 100 100 1000 100 0 0 0> + , <&key_physical_attrs 100 100 1100 100 0 0 0> + , <&key_physical_attrs 100 100 0 200 0 0 0> + , <&key_physical_attrs 100 100 100 200 0 0 0> + , <&key_physical_attrs 100 100 200 200 0 0 0> + , <&key_physical_attrs 100 100 300 200 0 0 0> + , <&key_physical_attrs 100 100 400 200 0 0 0> + , <&key_physical_attrs 100 100 500 200 0 0 0> + , <&key_physical_attrs 100 100 600 200 0 0 0> + , <&key_physical_attrs 100 100 700 200 0 0 0> + , <&key_physical_attrs 100 100 800 200 0 0 0> + , <&key_physical_attrs 100 100 900 200 0 0 0> + , <&key_physical_attrs 100 100 1000 200 0 0 0> + , <&key_physical_attrs 100 100 1100 200 0 0 0> + , <&key_physical_attrs 100 100 0 300 0 0 0> + , <&key_physical_attrs 100 100 100 300 0 0 0> + , <&key_physical_attrs 100 100 200 300 0 0 0> + , <&key_physical_attrs 100 100 300 300 0 0 0> + , <&key_physical_attrs 100 100 400 300 0 0 0> + , <&key_physical_attrs 100 100 500 300 0 0 0> + , <&key_physical_attrs 100 100 600 300 0 0 0> + , <&key_physical_attrs 100 100 700 300 0 0 0> + , <&key_physical_attrs 100 100 800 300 0 0 0> + , <&key_physical_attrs 100 100 900 300 0 0 0> + , <&key_physical_attrs 100 100 1000 300 0 0 0> + , <&key_physical_attrs 100 100 1100 300 0 0 0> + , <&key_physical_attrs 100 100 0 400 0 0 0> + , <&key_physical_attrs 100 100 100 400 0 0 0> + , <&key_physical_attrs 100 100 200 400 0 0 0> + , <&key_physical_attrs 100 100 300 400 0 0 0> + , <&key_physical_attrs 200 100 400 400 0 0 0> + , <&key_physical_attrs 200 100 600 400 0 0 0> + , <&key_physical_attrs 100 100 800 400 0 0 0> + , <&key_physical_attrs 100 100 900 400 0 0 0> + , <&key_physical_attrs 100 100 1000 400 0 0 0> + , <&key_physical_attrs 100 100 1100 400 0 0 0> + ; + }; +}; \ No newline at end of file diff --git a/app/dts/layouts/common/ortho_5x12/all1u.dtsi b/app/dts/layouts/common/ortho_5x12/all1u.dtsi new file mode 100644 index 00000000..53afb469 --- /dev/null +++ b/app/dts/layouts/common/ortho_5x12/all1u.dtsi @@ -0,0 +1,71 @@ +#include + +/ { + layout_ortho_5x12_all1u: layout_ortho_5x12_all1u { + compatible = "zmk,physical-layout"; + display-name = "50% All 1U/Grid"; + + keys // w h x y rot rx ry + = <&key_physical_attrs 100 100 0 0 0 0 0> + , <&key_physical_attrs 100 100 100 0 0 0 0> + , <&key_physical_attrs 100 100 200 0 0 0 0> + , <&key_physical_attrs 100 100 300 0 0 0 0> + , <&key_physical_attrs 100 100 400 0 0 0 0> + , <&key_physical_attrs 100 100 500 0 0 0 0> + , <&key_physical_attrs 100 100 600 0 0 0 0> + , <&key_physical_attrs 100 100 700 0 0 0 0> + , <&key_physical_attrs 100 100 800 0 0 0 0> + , <&key_physical_attrs 100 100 900 0 0 0 0> + , <&key_physical_attrs 100 100 1000 0 0 0 0> + , <&key_physical_attrs 100 100 1100 0 0 0 0> + , <&key_physical_attrs 100 100 0 100 0 0 0> + , <&key_physical_attrs 100 100 100 100 0 0 0> + , <&key_physical_attrs 100 100 200 100 0 0 0> + , <&key_physical_attrs 100 100 300 100 0 0 0> + , <&key_physical_attrs 100 100 400 100 0 0 0> + , <&key_physical_attrs 100 100 500 100 0 0 0> + , <&key_physical_attrs 100 100 600 100 0 0 0> + , <&key_physical_attrs 100 100 700 100 0 0 0> + , <&key_physical_attrs 100 100 800 100 0 0 0> + , <&key_physical_attrs 100 100 900 100 0 0 0> + , <&key_physical_attrs 100 100 1000 100 0 0 0> + , <&key_physical_attrs 100 100 1100 100 0 0 0> + , <&key_physical_attrs 100 100 0 200 0 0 0> + , <&key_physical_attrs 100 100 100 200 0 0 0> + , <&key_physical_attrs 100 100 200 200 0 0 0> + , <&key_physical_attrs 100 100 300 200 0 0 0> + , <&key_physical_attrs 100 100 400 200 0 0 0> + , <&key_physical_attrs 100 100 500 200 0 0 0> + , <&key_physical_attrs 100 100 600 200 0 0 0> + , <&key_physical_attrs 100 100 700 200 0 0 0> + , <&key_physical_attrs 100 100 800 200 0 0 0> + , <&key_physical_attrs 100 100 900 200 0 0 0> + , <&key_physical_attrs 100 100 1000 200 0 0 0> + , <&key_physical_attrs 100 100 1100 200 0 0 0> + , <&key_physical_attrs 100 100 0 300 0 0 0> + , <&key_physical_attrs 100 100 100 300 0 0 0> + , <&key_physical_attrs 100 100 200 300 0 0 0> + , <&key_physical_attrs 100 100 300 300 0 0 0> + , <&key_physical_attrs 100 100 400 300 0 0 0> + , <&key_physical_attrs 100 100 500 300 0 0 0> + , <&key_physical_attrs 100 100 600 300 0 0 0> + , <&key_physical_attrs 100 100 700 300 0 0 0> + , <&key_physical_attrs 100 100 800 300 0 0 0> + , <&key_physical_attrs 100 100 900 300 0 0 0> + , <&key_physical_attrs 100 100 1000 300 0 0 0> + , <&key_physical_attrs 100 100 1100 300 0 0 0> + , <&key_physical_attrs 100 100 0 400 0 0 0> + , <&key_physical_attrs 100 100 100 400 0 0 0> + , <&key_physical_attrs 100 100 200 400 0 0 0> + , <&key_physical_attrs 100 100 300 400 0 0 0> + , <&key_physical_attrs 100 100 400 400 0 0 0> + , <&key_physical_attrs 100 100 500 400 0 0 0> + , <&key_physical_attrs 100 100 600 400 0 0 0> + , <&key_physical_attrs 100 100 700 400 0 0 0> + , <&key_physical_attrs 100 100 800 400 0 0 0> + , <&key_physical_attrs 100 100 900 400 0 0 0> + , <&key_physical_attrs 100 100 1000 400 0 0 0> + , <&key_physical_attrs 100 100 1100 400 0 0 0> + ; + }; +}; diff --git a/app/dts/layouts/common/ortho_5x12/ortho_5x12.dtsi b/app/dts/layouts/common/ortho_5x12/ortho_5x12.dtsi new file mode 100644 index 00000000..d1a6df7e --- /dev/null +++ b/app/dts/layouts/common/ortho_5x12/ortho_5x12.dtsi @@ -0,0 +1,56 @@ +#include +#include +#include + +&layout_ortho_5x12_all1u { + status = "disabled"; +}; + +&layout_ortho_5x12_1x2u { + status = "disabled"; +}; + +&layout_ortho_5x12_2x2u { + status = "disabled"; +}; + +/ { + layouts_common_ortho_5x12_position_map: layouts_common_ortho_5x12_position_map { + compatible = "zmk,physical-layout-position-map"; + + complete; + + layout_ortho_5x12_all1u { + physical-layout = <&layout_ortho_5x12_all1u>; + positions + = < 0 1 2 3 4 5 6 7 8 9 10 11> + , <12 13 14 15 16 17 18 19 20 21 22 23> + , <24 25 26 27 28 29 30 31 32 33 34 35> + , <36 37 38 39 40 41 42 43 44 45 46 47> + , <48 49 50 51 52 53 54 55 56 57 58 59> + ; + }; + + layout_ortho_5x12_2x2u { + physical-layout = <&layout_ortho_5x12_2x2u>; + positions + = < 0 1 2 3 4 5 6 7 8 9 10 11> + , <12 13 14 15 16 17 18 19 20 21 22 23> + , <24 25 26 27 28 29 30 31 32 33 34 35> + , <36 37 38 39 40 41 42 43 44 45 46 47> + , <48 49 50 51 52 58 59 53 54 55 56 57> + ; + }; + + layout_ortho_5x12_1x2u { + physical-layout = <&layout_ortho_5x12_1x2u>; + positions + = < 0 1 2 3 4 5 6 7 8 9 10 11> + , <12 13 14 15 16 17 18 19 20 21 22 23> + , <24 25 26 27 28 29 30 31 32 33 34 35> + , <36 37 38 39 40 41 42 43 44 45 46 47> + , <48 49 50 51 52 53 59 54 55 56 57 58> + ; + }; + }; +}; \ No newline at end of file diff --git a/app/dts/layouts/common/tkl/ansi.dtsi b/app/dts/layouts/common/tkl/ansi.dtsi new file mode 100644 index 00000000..639ac471 --- /dev/null +++ b/app/dts/layouts/common/tkl/ansi.dtsi @@ -0,0 +1,98 @@ +#include + +/ { + layout_tkl_ansi: layout_tkl_ansi { + compatible = "zmk,physical-layout"; + display-name = "TKL 87 Key ANSI"; + + keys // w h x y rot rx ry + = <&key_physical_attrs 100 100 0 0 0 0 0> + , <&key_physical_attrs 100 100 200 0 0 0 0> + , <&key_physical_attrs 100 100 300 0 0 0 0> + , <&key_physical_attrs 100 100 400 0 0 0 0> + , <&key_physical_attrs 100 100 500 0 0 0 0> + , <&key_physical_attrs 100 100 650 0 0 0 0> + , <&key_physical_attrs 100 100 750 0 0 0 0> + , <&key_physical_attrs 100 100 850 0 0 0 0> + , <&key_physical_attrs 100 100 950 0 0 0 0> + , <&key_physical_attrs 100 100 1100 0 0 0 0> + , <&key_physical_attrs 100 100 1200 0 0 0 0> + , <&key_physical_attrs 100 100 1300 0 0 0 0> + , <&key_physical_attrs 100 100 1400 0 0 0 0> + , <&key_physical_attrs 100 100 1525 0 0 0 0> + , <&key_physical_attrs 100 100 1625 0 0 0 0> + , <&key_physical_attrs 100 100 1725 0 0 0 0> + , <&key_physical_attrs 100 100 0 150 0 0 0> + , <&key_physical_attrs 100 100 100 150 0 0 0> + , <&key_physical_attrs 100 100 200 150 0 0 0> + , <&key_physical_attrs 100 100 300 150 0 0 0> + , <&key_physical_attrs 100 100 400 150 0 0 0> + , <&key_physical_attrs 100 100 500 150 0 0 0> + , <&key_physical_attrs 100 100 600 150 0 0 0> + , <&key_physical_attrs 100 100 700 150 0 0 0> + , <&key_physical_attrs 100 100 800 150 0 0 0> + , <&key_physical_attrs 100 100 900 150 0 0 0> + , <&key_physical_attrs 100 100 1000 150 0 0 0> + , <&key_physical_attrs 100 100 1100 150 0 0 0> + , <&key_physical_attrs 100 100 1200 150 0 0 0> + , <&key_physical_attrs 200 100 1300 150 0 0 0> + , <&key_physical_attrs 100 100 1525 150 0 0 0> + , <&key_physical_attrs 100 100 1625 150 0 0 0> + , <&key_physical_attrs 100 100 1725 150 0 0 0> + , <&key_physical_attrs 150 100 0 250 0 0 0> + , <&key_physical_attrs 100 100 150 250 0 0 0> + , <&key_physical_attrs 100 100 250 250 0 0 0> + , <&key_physical_attrs 100 100 350 250 0 0 0> + , <&key_physical_attrs 100 100 450 250 0 0 0> + , <&key_physical_attrs 100 100 550 250 0 0 0> + , <&key_physical_attrs 100 100 650 250 0 0 0> + , <&key_physical_attrs 100 100 750 250 0 0 0> + , <&key_physical_attrs 100 100 850 250 0 0 0> + , <&key_physical_attrs 100 100 950 250 0 0 0> + , <&key_physical_attrs 100 100 1050 250 0 0 0> + , <&key_physical_attrs 100 100 1150 250 0 0 0> + , <&key_physical_attrs 100 100 1250 250 0 0 0> + , <&key_physical_attrs 150 100 1350 250 0 0 0> + , <&key_physical_attrs 100 100 1525 250 0 0 0> + , <&key_physical_attrs 100 100 1625 250 0 0 0> + , <&key_physical_attrs 100 100 1725 250 0 0 0> + , <&key_physical_attrs 175 100 0 350 0 0 0> + , <&key_physical_attrs 100 100 175 350 0 0 0> + , <&key_physical_attrs 100 100 275 350 0 0 0> + , <&key_physical_attrs 100 100 375 350 0 0 0> + , <&key_physical_attrs 100 100 475 350 0 0 0> + , <&key_physical_attrs 100 100 575 350 0 0 0> + , <&key_physical_attrs 100 100 675 350 0 0 0> + , <&key_physical_attrs 100 100 775 350 0 0 0> + , <&key_physical_attrs 100 100 875 350 0 0 0> + , <&key_physical_attrs 100 100 975 350 0 0 0> + , <&key_physical_attrs 100 100 1075 350 0 0 0> + , <&key_physical_attrs 100 100 1175 350 0 0 0> + , <&key_physical_attrs 225 100 1275 350 0 0 0> + , <&key_physical_attrs 225 100 0 450 0 0 0> + , <&key_physical_attrs 100 100 225 450 0 0 0> + , <&key_physical_attrs 100 100 325 450 0 0 0> + , <&key_physical_attrs 100 100 425 450 0 0 0> + , <&key_physical_attrs 100 100 525 450 0 0 0> + , <&key_physical_attrs 100 100 625 450 0 0 0> + , <&key_physical_attrs 100 100 725 450 0 0 0> + , <&key_physical_attrs 100 100 825 450 0 0 0> + , <&key_physical_attrs 100 100 925 450 0 0 0> + , <&key_physical_attrs 100 100 1025 450 0 0 0> + , <&key_physical_attrs 100 100 1125 450 0 0 0> + , <&key_physical_attrs 275 100 1225 450 0 0 0> + , <&key_physical_attrs 100 100 1625 450 0 0 0> + , <&key_physical_attrs 125 100 0 550 0 0 0> + , <&key_physical_attrs 125 100 125 550 0 0 0> + , <&key_physical_attrs 125 100 250 550 0 0 0> + , <&key_physical_attrs 625 100 375 550 0 0 0> + , <&key_physical_attrs 125 100 1000 550 0 0 0> + , <&key_physical_attrs 125 100 1125 550 0 0 0> + , <&key_physical_attrs 125 100 1250 550 0 0 0> + , <&key_physical_attrs 125 100 1375 550 0 0 0> + , <&key_physical_attrs 100 100 1525 550 0 0 0> + , <&key_physical_attrs 100 100 1625 550 0 0 0> + , <&key_physical_attrs 100 100 1725 550 0 0 0> + ; + }; +}; From ec32c566ce0b7b5c6557c7ab70bf8347952848d4 Mon Sep 17 00:00:00 2001 From: ReFil <31960031+ReFil@users.noreply.github.com> Date: Mon, 9 Sep 2024 13:57:45 +0100 Subject: [PATCH 033/415] feat(boards): Tofu65 V2 Physical layout --- app/boards/arm/kbdfans_tofu65/kbdfans_tofu65_v2.dts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/boards/arm/kbdfans_tofu65/kbdfans_tofu65_v2.dts b/app/boards/arm/kbdfans_tofu65/kbdfans_tofu65_v2.dts index 60ba1da0..bc6a9d02 100644 --- a/app/boards/arm/kbdfans_tofu65/kbdfans_tofu65_v2.dts +++ b/app/boards/arm/kbdfans_tofu65/kbdfans_tofu65_v2.dts @@ -8,6 +8,8 @@ #include #include +#include + / { chosen { @@ -15,7 +17,7 @@ zephyr,flash = &flash0; zephyr,code-partition = &code_partition; zmk,kscan = &kscan0; - zmk,matrix-transform = &default_transform; + zmk,physical-layout = &layout_65_ansi; }; xtal_clk: xtal-clk { @@ -115,3 +117,6 @@ zephyr_udc0: &usbd { status = "okay"; }; +&layout_65_ansi { + transform = <&default_transform>; +}; From a47f1fe2e173e97c22d9f44cbd5a65889b8b3a0a Mon Sep 17 00:00:00 2001 From: ReFil <31960031+ReFil@users.noreply.github.com> Date: Mon, 9 Sep 2024 14:02:27 +0100 Subject: [PATCH 034/415] feat(boards): nice!60 physical layout --- app/boards/arm/nice60/nice60.dts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/boards/arm/nice60/nice60.dts b/app/boards/arm/nice60/nice60.dts index fec8a678..35eececd 100644 --- a/app/boards/arm/nice60/nice60.dts +++ b/app/boards/arm/nice60/nice60.dts @@ -10,6 +10,8 @@ #include #include +#include + #include "nice60-pinctrl.dtsi" / { @@ -22,7 +24,7 @@ zephyr,flash = &flash0; zmk,battery = &vbatt; zmk,kscan = &kscan0; - zmk,matrix-transform = &default_transform; + zmk,physical-layout = &layout_60_ansi; zmk,underglow = &led_strip; }; @@ -169,3 +171,7 @@ zephyr_udc0: &usbd { }; }; }; + +&layout_60_ansi { + transform = <&default_transform>; +}; From a8f7888f4d6c289deea1cbbc4c1f1ee85cc19d66 Mon Sep 17 00:00:00 2001 From: ReFil <31960031+ReFil@users.noreply.github.com> Date: Thu, 26 Sep 2024 14:29:34 +0100 Subject: [PATCH 035/415] feat(boards): BT60 V1 Physical Layout --- app/boards/arm/bt60/bt60.dtsi | 2 -- app/boards/arm/bt60/bt60_v1.dts | 36 ++++++++++++-------- app/boards/arm/bt60/bt60_v1.keymap | 49 ++++++--------------------- app/boards/arm/bt60/bt60_v1_hs.dts | 8 +++-- app/boards/arm/bt60/bt60_v1_hs.keymap | 10 +++--- 5 files changed, 44 insertions(+), 61 deletions(-) diff --git a/app/boards/arm/bt60/bt60.dtsi b/app/boards/arm/bt60/bt60.dtsi index 83ff3f04..5e176e60 100644 --- a/app/boards/arm/bt60/bt60.dtsi +++ b/app/boards/arm/bt60/bt60.dtsi @@ -17,8 +17,6 @@ zephyr,sram = &sram0; zephyr,flash = &flash0; zmk,battery = &vbatt; - zmk,kscan = &kscan0; - zmk,matrix-transform = &default_transform; }; sensors: sensors { diff --git a/app/boards/arm/bt60/bt60_v1.dts b/app/boards/arm/bt60/bt60_v1.dts index 315d8cce..d7ecb5ae 100644 --- a/app/boards/arm/bt60/bt60_v1.dts +++ b/app/boards/arm/bt60/bt60_v1.dts @@ -6,12 +6,13 @@ /dts-v1/; #include "bt60.dtsi" +#include / { chosen { zmk,kscan = &kscan0; - zmk,matrix-transform = &ansi_transform; + zmk,physical-layout = &layout_60_ansi; }; ansi_transform: keymap_transform_0 { @@ -66,19 +67,6 @@ >; }; - split_transform: keymap_transform_4 { - compatible = "zmk,matrix-transform"; - columns = <15>; - rows = <5>; - 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(0,12) RC(0,13) RC(0,14) - 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(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,6) RC(2,7) RC(2,8) RC(2,9) RC(2,10) RC(2,11) RC(2,13) - RC(3,0) 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,14) - RC(4,0) RC(4,1) RC(4,2) RC(4,6) RC(4,10) RC(4,11) RC(4,12) RC(4,13) - >; - }; - kscan0: kscan_0 { compatible = "zmk,kscan-gpio-matrix"; wakeup-source; @@ -112,3 +100,23 @@ ; }; }; + +&layout_60_ansi { + status = "okay"; + transform = <&ansi_transform>; +}; + +&layout_60_iso { + status = "okay"; + transform = <&iso_transform>; +}; + +&layout_60_all1u { + status = "okay"; + transform = <&all_1u_transform>; +}; + +&layout_60_hhkb { + status = "okay"; + transform = <&hhkb_transform>; +}; diff --git a/app/boards/arm/bt60/bt60_v1.keymap b/app/boards/arm/bt60/bt60_v1.keymap index be3b206a..65442b58 100644 --- a/app/boards/arm/bt60/bt60_v1.keymap +++ b/app/boards/arm/bt60/bt60_v1.keymap @@ -2,26 +2,25 @@ #include #include -#define ANSI true -//#define HHKB true -//#define ISO true -//#define ALL_1U true -//#define SPLIT_BKSP_RSHFT true +#define ANSI +//#define HHKB +//#define ISO +//#define ALL_1U / { chosen { #ifdef ANSI - zmk,matrix-transform = &ansi_transform; - #elif defined(HHKB) - zmk,matrix-transform = &hhkb_transform; + zmk,physical-layout = &layout_60_ansi; #elif defined(ISO) - zmk,matrix-transform = &iso_transform; + zmk,physical-layout = &layout_60_iso; #elif defined(ALL_1U) - zmk,matrix-transform = &all_1u_transform; + zmk,physical-layout = &layout_60_all1u; + #elif defined(HHKB) + zmk,physical-layout = &layout_60_hhkb; #else - zmk,matrix-transform = &split_transform; + #error "Layout not defined, please define a layout by uncommenting the appropriate line in bt60_v1.keymap" #endif }; @@ -148,33 +147,7 @@ sensor-bindings = <&inc_dec_kp C_VOL_UP C_VOL_DN>; }; #else - default_layer { - // ------------------------------------------------------------------------------------------ - // | ESC | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | - | = |BSPC| DEL | - // | TAB | Q | W | E | R | T | Y | U | I | O | P | [ | ] | \ | - // | CAPS | A | S | D | F | G | H | J | K | L | ; | ' | ENTER | - // | SHIFT | Z | X | C | V | B | N | M | , | . | / | SHIFT | 1 | - // | CTL | WIN | ALT | SPACE | ALT | 1 | CTRL | - // ------------------------------------------------------------------------------------------ - bindings = < - &kp ESC &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 &kp MINUS &kp EQUAL &kp BSPC &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 LBKT &kp RBKT &kp BSLH - &kp CLCK &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SEMI &kp SQT &kp RET - &kp LSHFT &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp RSHFT &mo 1 - &kp LCTRL &kp LGUI &kp LALT &kp SPACE &kp RALT &kp RGUI &kp C_MENU &kp RCTRL - >; - sensor-bindings = <&inc_dec_kp C_VOL_UP C_VOL_DN>; - }; - raise { - bindings = < - &kp GRAVE &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 DEL &trans - &trans &trans &kp UP &trans &trans &trans &trans &trans &kp INS &trans &kp PSCRN &kp SLCK &kp PAUSE_BREAK &sys_reset - &trans &kp LEFT &kp DOWN &kp RIGHT &trans &trans &trans &trans &trans &trans &kp HOME &kp PG_UP &bootloader - &kp C_PREV &kp C_VOL_DN &kp C_VOL_UP &kp C_MUTE &trans &trans &trans &trans &trans &kp END &kp PG_DN &kp C_NEXT &trans - &bt BT_PRV &bt BT_NXT &trans &trans &trans &trans &trans &bt BT_CLR - >; - sensor-bindings = <&inc_dec_kp C_VOL_UP C_VOL_DN>; - }; + #error "Layout not defined, please define a layout by uncommenting the appropriate line in bt60_v2.keymap" #endif }; }; diff --git a/app/boards/arm/bt60/bt60_v1_hs.dts b/app/boards/arm/bt60/bt60_v1_hs.dts index 27e38286..23d4d55b 100644 --- a/app/boards/arm/bt60/bt60_v1_hs.dts +++ b/app/boards/arm/bt60/bt60_v1_hs.dts @@ -6,12 +6,12 @@ /dts-v1/; #include "bt60.dtsi" - +#include / { chosen { zmk,kscan = &kscan0; - zmk,matrix-transform = &default_transform; + zmk,physical-layout = &layout_60_ansi; }; default_transform: keymap_transform_0 { @@ -60,3 +60,7 @@ ; }; }; + +&layout_60_ansi { + transform = <&default_transform>; +}; diff --git a/app/boards/arm/bt60/bt60_v1_hs.keymap b/app/boards/arm/bt60/bt60_v1_hs.keymap index f1e483e3..a36246e5 100644 --- a/app/boards/arm/bt60/bt60_v1_hs.keymap +++ b/app/boards/arm/bt60/bt60_v1_hs.keymap @@ -8,14 +8,14 @@ default_layer { // ------------------------------------------------------------------------------------------ - // | ESC | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | - | = | BSPC | DEL - // | TAB | Q | W | E | R | T | Y | U | I | O | P | [ | ] | | | + // | ESC | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | - | = | BSPC | + // | TAB | Q | W | E | R | T | Y | U | I | O | P | [ | ] | | | // | CAPS | A | S | D | F | G | H | J | K | L | ; | ' | ENTER | // | SHIFT | Z | X | C | V | B | N | M | , | . | / | SHIFT | - // | CTL | WIN | ALT | SPACE | ALT | 1 | MENU | CTRL | + // | CTL | WIN | ALT | SPACE | ALT | 1 | MENU | CTRL | // ------------------------------------------------------------------------------------------ bindings = < - &kp ESC &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 &kp MINUS &kp EQUAL &kp BSPC &bt BT_CLR + &kp ESC &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 &kp MINUS &kp EQUAL &kp BSPC &kp TAB &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &kp LBKT &kp RBKT &kp BSLH &kp CLCK &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SEMI &kp SQT &kp RET &kp LSHFT &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp RSHFT @@ -25,7 +25,7 @@ }; raise { bindings = < - &kp GRAVE &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 DEL &trans + &kp GRAVE &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 DEL &trans &trans &kp UP &trans &trans &trans &trans &trans &kp INS &trans &kp PSCRN &kp SLCK &kp PAUSE_BREAK &sys_reset &trans &kp LEFT &kp DOWN &kp RIGHT &trans &trans &trans &trans &trans &trans &kp HOME &kp PG_UP &bootloader &kp C_PREV &kp C_VOL_DN &kp C_VOL_UP &kp C_MUTE &trans &trans &trans &trans &trans &kp END &kp PG_DN &kp C_NEXT From 026be009a62017049a172048a0cdcf6295cdd0be Mon Sep 17 00:00:00 2001 From: ReFil <31960031+ReFil@users.noreply.github.com> Date: Thu, 26 Sep 2024 14:22:47 +0100 Subject: [PATCH 036/415] feat(boards): CKP physical layout --- app/boards/arm/ckp/bt60_v2.dts | 23 ++++++++++++++++++++++- app/boards/arm/ckp/bt60_v2.keymap | 8 ++++---- app/boards/arm/ckp/bt65_v1.dts | 23 ++++++++++++++++++++++- app/boards/arm/ckp/bt65_v1.keymap | 8 ++++---- app/boards/arm/ckp/bt75_v1.dts | 18 +++++++++++++++++- app/boards/arm/ckp/bt75_v1.keymap | 6 +++--- 6 files changed, 72 insertions(+), 14 deletions(-) diff --git a/app/boards/arm/ckp/bt60_v2.dts b/app/boards/arm/ckp/bt60_v2.dts index a3ef75fb..751cad09 100644 --- a/app/boards/arm/ckp/bt60_v2.dts +++ b/app/boards/arm/ckp/bt60_v2.dts @@ -6,6 +6,7 @@ /dts-v1/; #include "ckp.dtsi" +#include / { @@ -13,7 +14,7 @@ compatible = "polarityworks,bt60_v2"; chosen { - zmk,matrix-transform = &ansi_transform; + zmk,physical-layout = &layout_60_ansi; }; @@ -69,3 +70,23 @@ >; }; }; + +&layout_60_ansi { + status = "okay"; + transform = <&ansi_transform>; +}; + +&layout_60_iso { + status = "okay"; + transform = <&iso_transform>; +}; + +&layout_60_all1u { + status = "okay"; + transform = <&all_1u_transform>; +}; + +&layout_60_hhkb { + status = "okay"; + transform = <&hhkb_transform>; +}; diff --git a/app/boards/arm/ckp/bt60_v2.keymap b/app/boards/arm/ckp/bt60_v2.keymap index f72401f6..478cf7bd 100644 --- a/app/boards/arm/ckp/bt60_v2.keymap +++ b/app/boards/arm/ckp/bt60_v2.keymap @@ -12,13 +12,13 @@ / { chosen { #ifdef ANSI - zmk,matrix-transform = &ansi_transform; + zmk,physical-layout = &layout_60_ansi; #elif defined(ISO) - zmk,matrix-transform = &iso_transform; + zmk,physical-layout = &layout_60_iso; #elif defined(ALL_1U) - zmk,matrix-transform = &all_1u_transform; + zmk,physical-layout = &layout_60_all1u; #elif defined(HHKB) - zmk,matrix-transform = &hhkb_transform; + zmk,physical-layout = &layout_60_hhkb; #else #error "Layout not defined, please define a layout by uncommenting the appropriate line in bt60_v2.keymap" #endif diff --git a/app/boards/arm/ckp/bt65_v1.dts b/app/boards/arm/ckp/bt65_v1.dts index f79587ce..cdea235f 100644 --- a/app/boards/arm/ckp/bt65_v1.dts +++ b/app/boards/arm/ckp/bt65_v1.dts @@ -6,6 +6,7 @@ /dts-v1/; #include "ckp.dtsi" +#include / { @@ -13,7 +14,7 @@ compatible = "polarityworks,bt65_v1"; chosen { - zmk,matrix-transform = &ansi_transform; + zmk,physical-layout = &layout_65_ansi; }; @@ -69,3 +70,23 @@ >; }; }; + +&layout_65_ansi { + status = "okay"; + transform = <&ansi_transform>; +}; + +&layout_65_iso { + status = "okay"; + transform = <&iso_transform>; +}; + +&layout_65_all1u { + status = "okay"; + transform = <&all_1u_transform>; +}; + +&layout_65_hhkb { + status = "okay"; + transform = <&hhkb_transform>; +}; diff --git a/app/boards/arm/ckp/bt65_v1.keymap b/app/boards/arm/ckp/bt65_v1.keymap index a4041084..da494143 100644 --- a/app/boards/arm/ckp/bt65_v1.keymap +++ b/app/boards/arm/ckp/bt65_v1.keymap @@ -12,13 +12,13 @@ / { chosen { #ifdef ANSI - zmk,matrix-transform = &ansi_transform; + zmk,physical-layout = &layout_65_ansi; #elif defined(ISO) - zmk,matrix-transform = &iso_transform; + zmk,physical-layout = &layout_65_iso; #elif defined(ALL_1U) - zmk,matrix-transform = &all_1u_transform; + zmk,physical-layout = &layout_65_all1u; #elif defined(HHKB) - zmk,matrix-transform = &hhkb_transform; + zmk,physical-layout = &layout_65_hhkb; #else #error "Layout not defined, please define a layout by uncommenting the appropriate line in bt65_v1.keymap" #endif diff --git a/app/boards/arm/ckp/bt75_v1.dts b/app/boards/arm/ckp/bt75_v1.dts index 41281086..7077aa1d 100644 --- a/app/boards/arm/ckp/bt75_v1.dts +++ b/app/boards/arm/ckp/bt75_v1.dts @@ -6,6 +6,7 @@ /dts-v1/; #include "ckp.dtsi" +#include / { @@ -13,7 +14,7 @@ compatible = "polarityworks,bt75_v1"; chosen { - zmk,matrix-transform = &ansi_transform; + zmk,physical-layout = &layout_75_ansi; }; @@ -59,3 +60,18 @@ >; }; }; + +&layout_75_ansi { + status = "okay"; + transform = <&ansi_transform>; +}; + +&layout_75_iso { + status = "okay"; + transform = <&iso_transform>; +}; + +&layout_75_all1u { + status = "okay"; + transform = <&all_1u_transform>; +}; diff --git a/app/boards/arm/ckp/bt75_v1.keymap b/app/boards/arm/ckp/bt75_v1.keymap index 888dcb64..ff0db7b0 100644 --- a/app/boards/arm/ckp/bt75_v1.keymap +++ b/app/boards/arm/ckp/bt75_v1.keymap @@ -11,11 +11,11 @@ / { chosen { #ifdef ANSI - zmk,matrix-transform = &ansi_transform; + zmk,physical-layout = &layout_75_ansi; #elif defined(ISO) - zmk,matrix-transform = &iso_transform; + zmk,physical-layout = &layout_75_iso; #elif defined(ALL_1U) - zmk,matrix-transform = &all_1u_transform; + zmk,physical-layout = &layout_75_all1u; #else #error "Layout not defined, please define a layout using by uncommenting the appropriate line in bt75_v1.keymap" #endif From 91e1a7cfefc5e49a8d7284b6ac011162c1c1370a Mon Sep 17 00:00:00 2001 From: ReFil <31960031+ReFil@users.noreply.github.com> Date: Mon, 9 Sep 2024 14:09:54 +0100 Subject: [PATCH 037/415] feat(boards): Planck physical layout --- app/boards/arm/planck/planck_rev6.dts | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/app/boards/arm/planck/planck_rev6.dts b/app/boards/arm/planck/planck_rev6.dts index 85b75140..d3aaf8fe 100644 --- a/app/boards/arm/planck/planck_rev6.dts +++ b/app/boards/arm/planck/planck_rev6.dts @@ -9,6 +9,9 @@ #include #include +#include + + / { model = "Plack PCD, rev6"; compatible = "planck,rev6", "st,stm32f303"; @@ -17,7 +20,7 @@ zephyr,sram = &sram0; zephyr,flash = &flash0; zmk,kscan = &kscan0; - zmk,matrix-transform = &layout_grid_transform; + zmk,physical-layout = &layout_ortho_4x12_all1u; }; kscan0: kscan { @@ -137,3 +140,18 @@ zephyr_udc0: &usb { }; }; }; + +&layout_ortho_4x12_all1u { + status = "okay"; + transform = <&layout_grid_transform>; +}; + +&layout_ortho_4x12_1x2u { + status = "okay"; + transform = <&layout_mit_transform>; +}; + +&layout_ortho_4x12_2x2u { + status = "okay"; + transform = <&layout_2x2u_transform>; +}; From e80b1584de667371bc0c67270c7a50f9dad69a97 Mon Sep 17 00:00:00 2001 From: ReFil <31960031+ReFil@users.noreply.github.com> Date: Mon, 9 Sep 2024 14:10:10 +0100 Subject: [PATCH 038/415] feat(boards): Preonic physical layout --- app/boards/arm/preonic/preonic_rev3.dts | 18 +++++++++++++++++- app/boards/arm/preonic/preonic_rev3.keymap | 1 - 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/app/boards/arm/preonic/preonic_rev3.dts b/app/boards/arm/preonic/preonic_rev3.dts index 79f88c33..8032e459 100644 --- a/app/boards/arm/preonic/preonic_rev3.dts +++ b/app/boards/arm/preonic/preonic_rev3.dts @@ -9,6 +9,7 @@ #include #include +#include / { model = "Preonic PCD, rev3"; @@ -18,7 +19,7 @@ zephyr,sram = &sram0; zephyr,flash = &flash0; zmk,kscan = &kscan0; - zmk,matrix-transform = &layout_grid_transform; + zmk,physical-layout = &layout_ortho_5x12_all1u; }; kscan0: kscan_0 { @@ -131,3 +132,18 @@ zephyr_udc0: &usb { }; }; }; + +&layout_ortho_5x12_all1u { + status = "okay"; + transform = <&layout_grid_transform>; +}; + +&layout_ortho_5x12_1x2u { + status = "okay"; + transform = <&layout_mit_transform>; +}; + +&layout_ortho_5x12_2x2u { + status = "okay"; + transform = <&layout_2x2u_transform>; +}; diff --git a/app/boards/arm/preonic/preonic_rev3.keymap b/app/boards/arm/preonic/preonic_rev3.keymap index d25c5ca8..a3d85a94 100644 --- a/app/boards/arm/preonic/preonic_rev3.keymap +++ b/app/boards/arm/preonic/preonic_rev3.keymap @@ -13,7 +13,6 @@ #define RAISE 2 / { - chosen { zmk,matrix-transform = &layout_grid_transform; }; keymap { compatible = "zmk,keymap"; default_layer { From e68abe57d8b63219343c206f9116a70b150a9df4 Mon Sep 17 00:00:00 2001 From: ReFil <31960031+ReFil@users.noreply.github.com> Date: Mon, 9 Sep 2024 14:27:46 +0100 Subject: [PATCH 039/415] feat(shields): Shield physical layouts --- .../boardsource5x12/boardsource5x12.overlay | 22 +++++++++++++++++- app/boards/shields/contra/contra.overlay | 23 ++++++++++++++++++- app/boards/shields/crbn/crbn.overlay | 19 +++++++++++++++ app/boards/shields/m60/m60.overlay | 7 +++++- 4 files changed, 68 insertions(+), 3 deletions(-) diff --git a/app/boards/shields/boardsource5x12/boardsource5x12.overlay b/app/boards/shields/boardsource5x12/boardsource5x12.overlay index 15ae7b68..2e2c22d8 100644 --- a/app/boards/shields/boardsource5x12/boardsource5x12.overlay +++ b/app/boards/shields/boardsource5x12/boardsource5x12.overlay @@ -6,9 +6,25 @@ #include +#include + / { chosen { zmk,kscan = &kscan0; + zmk,physical-layout = &layout_ortho_5x12_all1u; + }; + + matrix_transform_50_all1u: keymap_transform_0 { + compatible = "zmk,matrix-transform"; + columns = <12>; + rows = <5>; + 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,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) + >; }; kscan0: kscan { @@ -40,4 +56,8 @@ , <&pro_micro 6 GPIO_ACTIVE_HIGH> ; }; -}; \ No newline at end of file +}; + +&layout_ortho_5x12_all1u { + transform = <&matrix_transform_50_all1u>; +}; diff --git a/app/boards/shields/contra/contra.overlay b/app/boards/shields/contra/contra.overlay index 45cc3088..e304ea77 100644 --- a/app/boards/shields/contra/contra.overlay +++ b/app/boards/shields/contra/contra.overlay @@ -4,9 +4,26 @@ * SPDX-License-Identifier: MIT */ +#include + +#include + / { chosen { zmk,kscan = &kscan0; + zmk,physical-layout = &layout_ortho_4x12_all1u; + }; + + matrix_transform_40_all1u: keymap_transform_0 { + compatible = "zmk,matrix-transform"; + columns = <12>; + rows = <4>; + 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) + >; }; kscan0: kscan_0 { @@ -37,4 +54,8 @@ , <&pro_micro 10 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> ; }; -}; \ No newline at end of file +}; + +&layout_ortho_4x12_all1u { + transform = <&matrix_transform_40_all1u>; +}; diff --git a/app/boards/shields/crbn/crbn.overlay b/app/boards/shields/crbn/crbn.overlay index c6a2b87c..977bfadc 100644 --- a/app/boards/shields/crbn/crbn.overlay +++ b/app/boards/shields/crbn/crbn.overlay @@ -6,9 +6,24 @@ #include +#include + / { chosen { zmk,kscan = &kscan0; + zmk,physical-layout = &layout_ortho_4x12_all1u; + }; + + matrix_transform_40_all1u: keymap_transform_0 { + compatible = "zmk,matrix-transform"; + columns = <12>; + rows = <4>; + 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) + >; }; kscan0: kscan_0 { @@ -54,3 +69,7 @@ triggers-per-rotation = <20>; }; }; + +&layout_ortho_4x12_all1u { + transform = <&matrix_transform_40_all1u>; +}; diff --git a/app/boards/shields/m60/m60.overlay b/app/boards/shields/m60/m60.overlay index c479233c..15690f52 100644 --- a/app/boards/shields/m60/m60.overlay +++ b/app/boards/shields/m60/m60.overlay @@ -6,10 +6,12 @@ #include +#include + / { chosen { zmk,kscan = &kscan0; - zmk,matrix-transform = &default_transform; + zmk,physical-layout = &layout_60_ansi; }; kscan0: kscan { @@ -58,3 +60,6 @@ RC(6,5) RC(6,6) RC(6,7) RC(7,0) RC(7 }; }; +&layout_60_ansi { + transform = <&default_transform>; +}; From a314128ea8e0d499b1a8118e195326318cbbfd79 Mon Sep 17 00:00:00 2001 From: Nicolas Munnich <98408764+Nick-Munnich@users.noreply.github.com> Date: Mon, 30 Sep 2024 19:06:00 +0200 Subject: [PATCH 040/415] docs: Pull encoders from new shield guide to its own page (#2510) Co-authored-by: Cem Aksoylar --- .../hardware-integration/encoders.md | 76 +++++++++++++++ .../hardware-integration/new-shield.mdx | 94 +------------------ docs/docs/features/encoders.md | 2 +- docs/sidebars.js | 1 + 4 files changed, 79 insertions(+), 94 deletions(-) create mode 100644 docs/docs/development/hardware-integration/encoders.md diff --git a/docs/docs/development/hardware-integration/encoders.md b/docs/docs/development/hardware-integration/encoders.md new file mode 100644 index 00000000..16b489d1 --- /dev/null +++ b/docs/docs/development/hardware-integration/encoders.md @@ -0,0 +1,76 @@ +--- +title: EC11 Encoders +sidebar_label: Encoders +--- + +EC11 encoder support can be added to your board or shield by adding the appropriate lines to your board/shield's configuration (.conf), devicetree (.dtsi/.overlay), and keymap (.keymap) files. + +## Configuration File + +In your configuration file you will need to add the following lines so that the encoders can be enabled/disabled: + +```ini +# Uncomment to enable encoder +# CONFIG_EC11=y +# CONFIG_EC11_TRIGGER_GLOBAL_THREAD=y +``` + +These should be commented by default for encoders that are optional/can be swapped with switches, but can be uncommented if encoders are part of the default design. + +:::note +If building locally for split boards, you may need to add these lines to the specific half's configuration file as well as the combined configuration file, see the [configuration overview](../../config/index.md) for details. +::: + +## Devicetree File + +In your devicetree file you will need to define each sensor with their properties. For split keyboards, do this in the .dtsi file that is shared by all parts; otherwise do it in the .dts (for boards) or .overlay (shields) file, see [configuration overview](../../config/index.md#devicetree-files) for details. Add the following lines: + +```dts + left_encoder: encoder_left { + compatible = "alps,ec11"; + a-gpios = ; + b-gpios = ; + steps = <80>; + status = "disabled"; + }; +``` + +Here you need to replace `PIN_A` and `PIN_B` with the appropriate pins that your PCB utilizes for the encoder(s). See shield overlays section in the [new shield guide](new-shield.mdx#shield-overlays) on the appropriate node label and pin number to use for GPIOs. + +The `steps` property should corresponded to the documented pulses per rotation for the encoders used on the keyboard, typically found on the datasheet of the component. If users use different encoders when they build, the value can be overridden in their keymap. + +Add additional encoders as necessary by duplicating the above lines, replacing `left` with whatever you would like to call your encoder, and updating the pins. + +Once you have defined the encoder sensors, you will have to add them to the list of sensors: + +```dts + sensors: sensors { + compatible = "zmk,keymap-sensors"; + sensors = <&left_encoder &right_encoder>; + triggers-per-rotation = <20>; + }; +``` + +In this example, a `left_encoder` and `right_encoder` are both added. Additional encoders can be added with spaces separating each, and the order they are added here determines the order in which you define their behavior in your keymap. + +In addition, a default value for the number of times the sensors trigger the bound behavior per full rotation is set via the `triggers-per-rotation` property. See [Encoders Config](../../config/encoders.md#devicetree) for more details. + +Add the following lines to the .dts/.overlay file that contains the encoder to enable it: + +```dts +&left_encoder { + status = "okay"; +}; +``` + +Make sure to add this to the .dts/.overlay file, rather than any shared (.dtsi) files. + +## Keymap + +Add the following line to your keymap file to add default encoder behavior bindings: + +```dts +sensor-bindings = <&inc_dec_kp C_VOL_UP C_VOL_DN>; +``` + +Add additional bindings as necessary to match the default number of encoders on your board. See the [Encoders](../../features/encoders.md) and [Keymaps](../../keymaps/index.mdx) documentation pages for more details. diff --git a/docs/docs/development/hardware-integration/new-shield.mdx b/docs/docs/development/hardware-integration/new-shield.mdx index 6d592161..7a74f1be 100644 --- a/docs/docs/development/hardware-integration/new-shield.mdx +++ b/docs/docs/development/hardware-integration/new-shield.mdx @@ -28,9 +28,8 @@ The high level steps are: - Add a default keymap, which users can override in their own configs as needed. - Add a `.zmk.yml` metadata file to document the high level details of your shield, and the features it supports. - Update the `build.yaml` file from the repository template to have some sample builds of the firmware to test. -- Add support for features such as encoders, OLED displays, or RGB underglow. -It may be helpful to review the upstream [shields documentation](https://docs.zephyrproject.org/3.5.0/hardware/porting/shields.html#shields) to get a proper understanding of the underlying system before continuing. +After adding ZMK support for a basic shield using this guide, check the sidebar for guides on adding any additional features (such as encoders) that your keyboard has. It may be helpful to review the upstream [shields documentation](https://docs.zephyrproject.org/3.5.0/hardware/porting/shields.html#shields) to get a proper understanding of the underlying system before continuing. :::note ZMK support for [split keyboards](../../features/split-keyboards.md) requires a few more files than single boards to ensure proper connectivity between the central and peripheral units. Check the following guides thoroughly to ensure that all the files are in place. @@ -502,97 +501,6 @@ include: shield: _right ``` -## Adding Features - -### Encoders - -EC11 encoder support can be added to your board or shield by adding the appropriate lines to your board/shield's configuration (.conf), device tree (.dtsi), overlay (.overlay), and keymap (.keymap) files. - - - - -In your configuration file you will need to add the following lines so that the encoders can be enabled/disabled: - -```ini -# Uncomment to enable encoder -# CONFIG_EC11=y -# CONFIG_EC11_TRIGGER_GLOBAL_THREAD=y -``` - -These should be commented by default for encoders that are optional/can be swapped with switches, but can be uncommented if encoders are part of the default design. - -:::note -If building locally for split boards, you may need to add these lines to the specific half's configuration file as well as the combined configuration file. -::: - - - -In your device tree file you will need to add the following lines to define the encoder sensor: - -```dts - left_encoder: encoder_left { - compatible = "alps,ec11"; - a-gpios = ; - b-gpios = ; - steps = <80>; - status = "disabled"; - }; -``` - -Here you need to replace `PIN_A` and `PIN_B` with the appropriate pins that your PCB utilizes for the encoder(s). See [shield overlays section above](#shield-overlays) on the appropriate node label and pin number to use for GPIOs. - -The `steps` property should corresponded to the documented pulses per rotation for the encoders used on the keyboard, typically found on the datasheet of the component. If users use different encoders when they build, the value can be overridden in their keymap. - -Add additional encoders as necessary by duplicating the above lines, replacing `left` with whatever you would like to call your encoder, and updating the pins. Note that support for peripheral (right) side sensors over BLE is still in progress. - -Once you have defined the encoder sensors, you will have to add them to the list of sensors: - -```dts - sensors: sensors { - compatible = "zmk,keymap-sensors"; - sensors = <&left_encoder &right_encoder>; - triggers-per-rotation = <20>; - }; -``` - -In this example, a left_encoder and right_encoder are both added. Additional encoders can be added with spaces separating each, and the order they are added here determines the order in which you define their behavior in your keymap. - -In addition, a default value for the number of times the sensors trigger the bound behavior per full rotation is set via the `triggers-per-rotation` property. See [Encoders Config](../../config/encoders.md#devicetree) for more details. - - - -Add the following lines to your overlay file(s) to enable the encoder: - -```dts -&left_encoder { - status = "okay"; -}; -``` - -:::note -For split keyboards, make sure to add left hand encoders to the left .overlay file and right hand encoders to the right .overlay file. -::: - - - -Add the following line to your keymap file to add default encoder behavior bindings: - -```dts -sensor-bindings = <&inc_dec_kp C_VOL_UP C_VOL_DN>; -``` - -Add additional bindings as necessary to match the default number of encoders on your board. See the [Encoders](../../features/encoders.md) and [Keymaps](../../keymaps/index.mdx) documentation pages for more details. - - - - ## Testing ### GitHub Actions diff --git a/docs/docs/features/encoders.md b/docs/docs/features/encoders.md index 046973f4..267f2e3d 100644 --- a/docs/docs/features/encoders.md +++ b/docs/docs/features/encoders.md @@ -41,4 +41,4 @@ Here, the left encoder is configured to control volume up and down while the rig ## Adding Encoder Support -See the [New Keyboard Shield](../development/hardware-integration/new-shield.mdx#encoders) documentation for how to add or modify additional encoders to your shield. +See the [Hardware Integration page for encoders](../development/hardware-integration/encoders.md) for instructions on adding them to your keyboard. diff --git a/docs/sidebars.js b/docs/sidebars.js index 8825746f..9f671471 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -129,6 +129,7 @@ module.exports = { "development/hardware-integration/boards-shields-keymaps", "development/hardware-integration/studio-setup", "development/hardware-integration/shift-registers", + "development/hardware-integration/encoders", ], }, { From f618871f53fc146ec166a866249974eedc7f6b3b Mon Sep 17 00:00:00 2001 From: Cem Aksoylar Date: Wed, 28 Aug 2024 21:57:58 -0700 Subject: [PATCH 041/415] feat(shields): Add more shared layouts --- app/boards/shields/kyria/kyria-layout.dtsi | 137 +++++++++++++++++++++ app/dts/layouts/kata0510/lily58.dtsi | 69 +++++++++++ 2 files changed, 206 insertions(+) create mode 100644 app/boards/shields/kyria/kyria-layout.dtsi create mode 100644 app/dts/layouts/kata0510/lily58.dtsi diff --git a/app/boards/shields/kyria/kyria-layout.dtsi b/app/boards/shields/kyria/kyria-layout.dtsi new file mode 100644 index 00000000..59079a86 --- /dev/null +++ b/app/boards/shields/kyria/kyria-layout.dtsi @@ -0,0 +1,137 @@ +#include + +/ { + splitkb_kyria_6col_layout: splitkb_kyria_6col_layout { + compatible = "zmk,physical-layout"; + display-name = "6-column"; + + keys // w h x y rot rx ry + = <&key_physical_attrs 100 100 0 75 0 0 0> + , <&key_physical_attrs 100 100 100 75 0 0 0> + , <&key_physical_attrs 100 100 200 25 0 0 0> + , <&key_physical_attrs 100 100 300 0 0 0 0> + , <&key_physical_attrs 100 100 400 25 0 0 0> + , <&key_physical_attrs 100 100 500 37 0 0 0> + , <&key_physical_attrs 100 100 1100 37 0 0 0> + , <&key_physical_attrs 100 100 1200 25 0 0 0> + , <&key_physical_attrs 100 100 1300 0 0 0 0> + , <&key_physical_attrs 100 100 1400 25 0 0 0> + , <&key_physical_attrs 100 100 1500 75 0 0 0> + , <&key_physical_attrs 100 100 1600 75 0 0 0> + , <&key_physical_attrs 100 100 0 175 0 0 0> + , <&key_physical_attrs 100 100 100 175 0 0 0> + , <&key_physical_attrs 100 100 200 125 0 0 0> + , <&key_physical_attrs 100 100 300 100 0 0 0> + , <&key_physical_attrs 100 100 400 125 0 0 0> + , <&key_physical_attrs 100 100 500 137 0 0 0> + , <&key_physical_attrs 100 100 1100 137 0 0 0> + , <&key_physical_attrs 100 100 1200 125 0 0 0> + , <&key_physical_attrs 100 100 1300 100 0 0 0> + , <&key_physical_attrs 100 100 1400 125 0 0 0> + , <&key_physical_attrs 100 100 1500 175 0 0 0> + , <&key_physical_attrs 100 100 1600 175 0 0 0> + , <&key_physical_attrs 100 100 0 275 0 0 0> + , <&key_physical_attrs 100 100 100 275 0 0 0> + , <&key_physical_attrs 100 100 200 225 0 0 0> + , <&key_physical_attrs 100 100 300 200 0 0 0> + , <&key_physical_attrs 100 100 400 225 0 0 0> + , <&key_physical_attrs 100 100 500 237 0 0 0> + , <&key_physical_attrs 100 100 350 225 3000 400 792> + , <&key_physical_attrs 100 100 350 225 4500 400 792> + , <&key_physical_attrs 100 100 1250 225 (-4500) 1300 792> + , <&key_physical_attrs 100 100 1250 225 (-3000) 1300 792> + , <&key_physical_attrs 100 100 1100 237 0 0 0> + , <&key_physical_attrs 100 100 1200 225 0 0 0> + , <&key_physical_attrs 100 100 1300 200 0 0 0> + , <&key_physical_attrs 100 100 1400 225 0 0 0> + , <&key_physical_attrs 100 100 1500 275 0 0 0> + , <&key_physical_attrs 100 100 1600 275 0 0 0> + , <&key_physical_attrs 100 100 250 325 0 0 0> + , <&key_physical_attrs 100 100 350 325 0 0 0> + , <&key_physical_attrs 100 100 350 325 1500 400 792> + , <&key_physical_attrs 100 100 350 325 3000 400 792> + , <&key_physical_attrs 100 100 350 325 4500 400 792> + , <&key_physical_attrs 100 100 1250 325 (-4500) 1300 792> + , <&key_physical_attrs 100 100 1250 325 (-3000) 1300 792> + , <&key_physical_attrs 100 100 1250 325 (-1500) 1300 792> + , <&key_physical_attrs 100 100 1250 325 0 0 0> + , <&key_physical_attrs 100 100 1350 325 0 0 0> + ; + }; + + splitkb_kyria_5col_layout: splitkb_kyria_5col_layout { + compatible = "zmk,physical-layout"; + display-name = "5-column"; + + keys // w h x y rot rx ry + = <&key_physical_attrs 100 100 0 75 0 0 0> + , <&key_physical_attrs 100 100 100 25 0 0 0> + , <&key_physical_attrs 100 100 200 0 0 0 0> + , <&key_physical_attrs 100 100 300 25 0 0 0> + , <&key_physical_attrs 100 100 400 37 0 0 0> + , <&key_physical_attrs 100 100 1000 37 0 0 0> + , <&key_physical_attrs 100 100 1100 25 0 0 0> + , <&key_physical_attrs 100 100 1200 0 0 0 0> + , <&key_physical_attrs 100 100 1300 25 0 0 0> + , <&key_physical_attrs 100 100 1400 75 0 0 0> + , <&key_physical_attrs 100 100 0 175 0 0 0> + , <&key_physical_attrs 100 100 100 125 0 0 0> + , <&key_physical_attrs 100 100 200 100 0 0 0> + , <&key_physical_attrs 100 100 300 125 0 0 0> + , <&key_physical_attrs 100 100 400 137 0 0 0> + , <&key_physical_attrs 100 100 1000 137 0 0 0> + , <&key_physical_attrs 100 100 1100 125 0 0 0> + , <&key_physical_attrs 100 100 1200 100 0 0 0> + , <&key_physical_attrs 100 100 1300 125 0 0 0> + , <&key_physical_attrs 100 100 1400 175 0 0 0> + , <&key_physical_attrs 100 100 0 275 0 0 0> + , <&key_physical_attrs 100 100 100 225 0 0 0> + , <&key_physical_attrs 100 100 200 200 0 0 0> + , <&key_physical_attrs 100 100 300 225 0 0 0> + , <&key_physical_attrs 100 100 400 237 0 0 0> + , <&key_physical_attrs 100 100 250 225 3000 300 792> + , <&key_physical_attrs 100 100 250 225 4500 300 792> + , <&key_physical_attrs 100 100 1150 225 (-4500) 1200 792> + , <&key_physical_attrs 100 100 1150 225 (-3000) 1200 792> + , <&key_physical_attrs 100 100 1000 237 0 0 0> + , <&key_physical_attrs 100 100 1100 225 0 0 0> + , <&key_physical_attrs 100 100 1200 200 0 0 0> + , <&key_physical_attrs 100 100 1300 225 0 0 0> + , <&key_physical_attrs 100 100 1400 275 0 0 0> + , <&key_physical_attrs 100 100 150 325 0 0 0> + , <&key_physical_attrs 100 100 250 325 0 0 0> + , <&key_physical_attrs 100 100 250 325 1500 300 792> + , <&key_physical_attrs 100 100 250 325 3000 300 792> + , <&key_physical_attrs 100 100 250 325 4500 300 792> + , <&key_physical_attrs 100 100 1150 325 (-4500) 1200 792> + , <&key_physical_attrs 100 100 1150 325 (-3000) 1200 792> + , <&key_physical_attrs 100 100 1150 325 (-1500) 1200 792> + , <&key_physical_attrs 100 100 1150 325 0 0 0> + , <&key_physical_attrs 100 100 1250 325 0 0 0> + ; + }; + + splitkb_kyria_position_map { + compatible = "zmk,physical-layout-position-map"; + + complete; + + twelve { + physical-layout = <&splitkb_kyria_6col_layout>; + positions + = < 0 1 2 3 4 5 6 7 8 9 10 11> + , <12 13 14 15 16 17 18 19 20 21 22 23> + , <24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39> + , < 40 41 42 43 44 45 46 47 48 49 >; + }; + + ten { + physical-layout = <&splitkb_kyria_5col_layout>; + positions + = <44 0 1 2 3 4 5 6 7 8 9 47> + , <45 10 11 12 13 14 15 16 17 18 19 48> + , <46 20 21 22 23 24 25 26 27 28 29 30 31 32 33 49> + , < 34 35 36 37 38 39 40 41 42 43 >; + }; + }; +}; diff --git a/app/dts/layouts/kata0510/lily58.dtsi b/app/dts/layouts/kata0510/lily58.dtsi new file mode 100644 index 00000000..7cb1f25e --- /dev/null +++ b/app/dts/layouts/kata0510/lily58.dtsi @@ -0,0 +1,69 @@ +#include + +/ { + kata0510_lily58_layout: kata0510_lily58_layout { + compatible = "zmk,physical-layout"; + display-name = "Default"; + + keys // w h x y rot rx ry + = <&key_physical_attrs 100 100 0 50 0 0 0> + , <&key_physical_attrs 100 100 100 37 0 0 0> + , <&key_physical_attrs 100 100 200 12 0 0 0> + , <&key_physical_attrs 100 100 300 0 0 0 0> + , <&key_physical_attrs 100 100 400 12 0 0 0> + , <&key_physical_attrs 100 100 500 25 0 0 0> + , <&key_physical_attrs 100 100 1050 25 0 0 0> + , <&key_physical_attrs 100 100 1150 12 0 0 0> + , <&key_physical_attrs 100 100 1250 0 0 0 0> + , <&key_physical_attrs 100 100 1350 12 0 0 0> + , <&key_physical_attrs 100 100 1450 37 0 0 0> + , <&key_physical_attrs 100 100 1550 50 0 0 0> + , <&key_physical_attrs 100 100 0 150 0 0 0> + , <&key_physical_attrs 100 100 100 137 0 0 0> + , <&key_physical_attrs 100 100 200 112 0 0 0> + , <&key_physical_attrs 100 100 300 100 0 0 0> + , <&key_physical_attrs 100 100 400 112 0 0 0> + , <&key_physical_attrs 100 100 500 125 0 0 0> + , <&key_physical_attrs 100 100 1050 125 0 0 0> + , <&key_physical_attrs 100 100 1150 112 0 0 0> + , <&key_physical_attrs 100 100 1250 100 0 0 0> + , <&key_physical_attrs 100 100 1350 112 0 0 0> + , <&key_physical_attrs 100 100 1450 137 0 0 0> + , <&key_physical_attrs 100 100 1550 150 0 0 0> + , <&key_physical_attrs 100 100 0 250 0 0 0> + , <&key_physical_attrs 100 100 100 237 0 0 0> + , <&key_physical_attrs 100 100 200 212 0 0 0> + , <&key_physical_attrs 100 100 300 200 0 0 0> + , <&key_physical_attrs 100 100 400 212 0 0 0> + , <&key_physical_attrs 100 100 500 225 0 0 0> + , <&key_physical_attrs 100 100 1050 225 0 0 0> + , <&key_physical_attrs 100 100 1150 212 0 0 0> + , <&key_physical_attrs 100 100 1250 200 0 0 0> + , <&key_physical_attrs 100 100 1350 212 0 0 0> + , <&key_physical_attrs 100 100 1450 237 0 0 0> + , <&key_physical_attrs 100 100 1550 250 0 0 0> + , <&key_physical_attrs 100 100 0 350 0 0 0> + , <&key_physical_attrs 100 100 100 337 0 0 0> + , <&key_physical_attrs 100 100 200 312 0 0 0> + , <&key_physical_attrs 100 100 300 300 0 0 0> + , <&key_physical_attrs 100 100 400 312 0 0 0> + , <&key_physical_attrs 100 100 500 325 0 0 0> + , <&key_physical_attrs 100 100 600 275 0 0 0> + , <&key_physical_attrs 100 100 950 275 0 0 0> + , <&key_physical_attrs 100 100 1050 325 0 0 0> + , <&key_physical_attrs 100 100 1150 312 0 0 0> + , <&key_physical_attrs 100 100 1250 300 0 0 0> + , <&key_physical_attrs 100 100 1350 312 0 0 0> + , <&key_physical_attrs 100 100 1450 337 0 0 0> + , <&key_physical_attrs 100 100 1550 350 0 0 0> + , <&key_physical_attrs 100 100 250 412 0 0 0> + , <&key_physical_attrs 100 100 350 415 0 0 0> + , <&key_physical_attrs 100 100 450 425 0 0 0> + , <&key_physical_attrs 100 150 575 400 3000 625 475> + , <&key_physical_attrs 100 150 975 400 (-3000) 1025 475> + , <&key_physical_attrs 100 100 1100 425 0 0 0> + , <&key_physical_attrs 100 100 1200 415 0 0 0> + , <&key_physical_attrs 100 100 1300 415 0 0 0> + ; + }; +}; From dafdc44b223c9d9a62dc640e02af169083318af4 Mon Sep 17 00:00:00 2001 From: Cem Aksoylar Date: Wed, 28 Aug 2024 22:10:26 -0700 Subject: [PATCH 042/415] feat(shields): Use new shared layouts --- app/boards/shields/kyria/kyria.dtsi | 12 ++++++++---- app/boards/shields/kyria/kyria_common.dtsi | 4 +++- app/boards/shields/kyria/kyria_rev2.dtsi | 12 ++++++++---- app/boards/shields/kyria/kyria_rev3.dtsi | 12 ++++++++---- app/boards/shields/lily58/lily58.dtsi | 8 +++++++- .../splitkb_aurora_lily58/splitkb_aurora_lily58.dtsi | 8 +++++++- 6 files changed, 41 insertions(+), 15 deletions(-) diff --git a/app/boards/shields/kyria/kyria.dtsi b/app/boards/shields/kyria/kyria.dtsi index 8934776f..72814a9e 100644 --- a/app/boards/shields/kyria/kyria.dtsi +++ b/app/boards/shields/kyria/kyria.dtsi @@ -6,11 +6,15 @@ #include "kyria_common.dtsi" -/ { - chosen { - zmk,matrix-transform = &default_transform; - }; +&splitkb_kyria_6col_layout { + transform = <&default_transform>; +}; +&splitkb_kyria_5col_layout { + transform = <&five_column_transform>; +}; + +/ { default_transform: keymap_transform_0 { compatible = "zmk,matrix-transform"; columns = <16>; diff --git a/app/boards/shields/kyria/kyria_common.dtsi b/app/boards/shields/kyria/kyria_common.dtsi index f662fa1c..661d1ff5 100644 --- a/app/boards/shields/kyria/kyria_common.dtsi +++ b/app/boards/shields/kyria/kyria_common.dtsi @@ -6,11 +6,13 @@ #include +#include "kyria-layout.dtsi" + / { chosen { zephyr,display = &oled; zmk,kscan = &kscan0; - zmk,matrix-transform = &default_transform; + zmk,physical-layout = &splitkb_kyria_6col_layout; }; kscan0: kscan { diff --git a/app/boards/shields/kyria/kyria_rev2.dtsi b/app/boards/shields/kyria/kyria_rev2.dtsi index c2586faf..c1c46bd1 100644 --- a/app/boards/shields/kyria/kyria_rev2.dtsi +++ b/app/boards/shields/kyria/kyria_rev2.dtsi @@ -6,11 +6,15 @@ #include "kyria_common.dtsi" -/ { - chosen { - zmk,matrix-transform = &default_transform; - }; +&splitkb_kyria_6col_layout { + transform = <&default_transform>; +}; +&splitkb_kyria_5col_layout { + transform = <&five_column_transform>; +}; + +/ { default_transform: keymap_transform_0 { compatible = "zmk,matrix-transform"; columns = <16>; diff --git a/app/boards/shields/kyria/kyria_rev3.dtsi b/app/boards/shields/kyria/kyria_rev3.dtsi index c8cd8df9..33395871 100644 --- a/app/boards/shields/kyria/kyria_rev3.dtsi +++ b/app/boards/shields/kyria/kyria_rev3.dtsi @@ -6,11 +6,15 @@ #include "kyria_common.dtsi" -/ { - chosen { - zmk,matrix-transform = &default_transform; - }; +&splitkb_kyria_6col_layout { + transform = <&default_transform>; +}; +&splitkb_kyria_5col_layout { + status = "disabled"; +}; + +/ { default_transform: keymap_transform_0 { compatible = "zmk,matrix-transform"; columns = <14>; diff --git a/app/boards/shields/lily58/lily58.dtsi b/app/boards/shields/lily58/lily58.dtsi index c82b197c..195ab2b7 100644 --- a/app/boards/shields/lily58/lily58.dtsi +++ b/app/boards/shields/lily58/lily58.dtsi @@ -6,11 +6,13 @@ #include +#include + / { chosen { zephyr,display = &oled; zmk,kscan = &kscan0; - zmk,matrix-transform = &default_transform; + zmk,physical-layout = &kata0510_lily58_layout; }; default_transform: keymap_transform_0 { @@ -60,6 +62,10 @@ 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) }; }; +&kata0510_lily58_layout { + transform = <&default_transform>; +}; + &pro_micro_i2c { status = "okay"; diff --git a/app/boards/shields/splitkb_aurora_lily58/splitkb_aurora_lily58.dtsi b/app/boards/shields/splitkb_aurora_lily58/splitkb_aurora_lily58.dtsi index 93625d28..b270890d 100644 --- a/app/boards/shields/splitkb_aurora_lily58/splitkb_aurora_lily58.dtsi +++ b/app/boards/shields/splitkb_aurora_lily58/splitkb_aurora_lily58.dtsi @@ -6,11 +6,13 @@ #include +#include + / { chosen { zephyr,display = &oled; - zmk,matrix-transform = &default_transform; + zmk,physical-layout = &kata0510_lily58_layout; }; default_transform: keymap_transform_0 { @@ -56,6 +58,10 @@ RC(3,0) RC(3,1) RC(3,2) RC(3,3) RC(3,4) RC(3,5) RC(4,1) RC(4,10) RC(3,6) RC(3,7) }; }; +&kata0510_lily58_layout { + transform = <&default_transform>; +}; + &pro_micro_i2c { status = "okay"; From 552d665f58e4f79d1497b977be679fc3fd1a70d2 Mon Sep 17 00:00:00 2001 From: Cem Aksoylar Date: Wed, 28 Aug 2024 22:16:29 -0700 Subject: [PATCH 043/415] feat(boards): Add glove80 and adv360pro layouts --- app/boards/arm/adv360pro/adv360pro.dtsi | 90 +++++++++++++++++++++++- app/boards/arm/glove80/glove80.dtsi | 93 ++++++++++++++++++++++++- 2 files changed, 181 insertions(+), 2 deletions(-) diff --git a/app/boards/arm/adv360pro/adv360pro.dtsi b/app/boards/arm/adv360pro/adv360pro.dtsi index ea68624b..b979e9a5 100644 --- a/app/boards/arm/adv360pro/adv360pro.dtsi +++ b/app/boards/arm/adv360pro/adv360pro.dtsi @@ -11,6 +11,8 @@ #include #include +#include + #include "adv360pro-pinctrl.dtsi" / { @@ -24,7 +26,7 @@ zmk,kscan = &kscan0; zmk,backlight = &backlight; zmk,battery = &vbatt; - zmk,matrix-transform = &default_transform; + zmk,physical-layout = &default_layout; zmk,underglow = &led_strip; }; @@ -44,6 +46,92 @@ >; }; + default_layout: default_layout { + compatible = "zmk,physical-layout"; + display-name = "Default"; + + transform = <&default_transform>; + + keys // w h x y rot rx ry + = <&key_physical_attrs 125 100 0 25 0 0 0> + , <&key_physical_attrs 100 100 125 25 0 0 0> + , <&key_physical_attrs 100 100 225 0 0 0 0> + , <&key_physical_attrs 100 100 325 0 0 0 0> + , <&key_physical_attrs 100 100 425 0 0 0 0> + , <&key_physical_attrs 100 100 525 0 0 0 0> + , <&key_physical_attrs 100 100 625 0 0 0 0> + , <&key_physical_attrs 100 100 1075 0 0 0 0> + , <&key_physical_attrs 100 100 1175 0 0 0 0> + , <&key_physical_attrs 100 100 1275 0 0 0 0> + , <&key_physical_attrs 100 100 1375 0 0 0 0> + , <&key_physical_attrs 100 100 1475 0 0 0 0> + , <&key_physical_attrs 100 100 1575 25 0 0 0> + , <&key_physical_attrs 125 100 1675 25 0 0 0> + , <&key_physical_attrs 125 100 0 125 0 0 0> + , <&key_physical_attrs 100 100 125 125 0 0 0> + , <&key_physical_attrs 100 100 225 100 0 0 0> + , <&key_physical_attrs 100 100 325 100 0 0 0> + , <&key_physical_attrs 100 100 425 100 0 0 0> + , <&key_physical_attrs 100 100 525 100 0 0 0> + , <&key_physical_attrs 100 100 625 100 0 0 0> + , <&key_physical_attrs 100 100 1075 100 0 0 0> + , <&key_physical_attrs 100 100 1175 100 0 0 0> + , <&key_physical_attrs 100 100 1275 100 0 0 0> + , <&key_physical_attrs 100 100 1375 100 0 0 0> + , <&key_physical_attrs 100 100 1475 100 0 0 0> + , <&key_physical_attrs 100 100 1575 125 0 0 0> + , <&key_physical_attrs 125 100 1675 125 0 0 0> + , <&key_physical_attrs 125 100 0 225 0 0 0> + , <&key_physical_attrs 100 100 125 225 0 0 0> + , <&key_physical_attrs 100 100 225 200 0 0 0> + , <&key_physical_attrs 100 100 325 200 0 0 0> + , <&key_physical_attrs 100 100 425 200 0 0 0> + , <&key_physical_attrs 100 100 525 200 0 0 0> + , <&key_physical_attrs 100 100 625 200 0 0 0> + , <&key_physical_attrs 100 100 675 400 1500 525 400> + , <&key_physical_attrs 100 100 775 400 1500 525 400> + , <&key_physical_attrs 100 100 925 400 (-1500) 1275 400> + , <&key_physical_attrs 100 100 1025 400 (-1500) 1275 400> + , <&key_physical_attrs 100 100 1075 200 0 0 0> + , <&key_physical_attrs 100 100 1175 200 0 0 0> + , <&key_physical_attrs 100 100 1275 200 0 0 0> + , <&key_physical_attrs 100 100 1375 200 0 0 0> + , <&key_physical_attrs 100 100 1475 200 0 0 0> + , <&key_physical_attrs 100 100 1575 225 0 0 0> + , <&key_physical_attrs 125 100 1675 225 0 0 0> + , <&key_physical_attrs 125 100 0 325 0 0 0> + , <&key_physical_attrs 100 100 125 325 0 0 0> + , <&key_physical_attrs 100 100 225 300 0 0 0> + , <&key_physical_attrs 100 100 325 300 0 0 0> + , <&key_physical_attrs 100 100 425 300 0 0 0> + , <&key_physical_attrs 100 100 525 300 0 0 0> + , <&key_physical_attrs 100 100 775 500 1500 525 400> + , <&key_physical_attrs 100 100 925 500 (-1500) 1275 400> + , <&key_physical_attrs 100 100 1175 300 0 0 0> + , <&key_physical_attrs 100 100 1275 300 0 0 0> + , <&key_physical_attrs 100 100 1375 300 0 0 0> + , <&key_physical_attrs 100 100 1475 300 0 0 0> + , <&key_physical_attrs 100 100 1575 325 0 0 0> + , <&key_physical_attrs 125 100 1675 325 0 0 0> + , <&key_physical_attrs 125 100 0 425 0 0 0> + , <&key_physical_attrs 100 100 125 425 0 0 0> + , <&key_physical_attrs 100 100 225 400 0 0 0> + , <&key_physical_attrs 100 100 325 400 0 0 0> + , <&key_physical_attrs 100 100 425 400 0 0 0> + , <&key_physical_attrs 100 200 575 500 1500 525 400> + , <&key_physical_attrs 100 200 675 500 1500 525 400> + , <&key_physical_attrs 100 100 775 600 1500 525 400> + , <&key_physical_attrs 100 100 925 600 (-1500) 1275 400> + , <&key_physical_attrs 100 200 1025 500 (-1500) 1275 400> + , <&key_physical_attrs 100 200 1125 500 (-1500) 1275 400> + , <&key_physical_attrs 100 100 1275 400 0 0 0> + , <&key_physical_attrs 100 100 1375 400 0 0 0> + , <&key_physical_attrs 100 100 1475 400 0 0 0> + , <&key_physical_attrs 100 100 1575 425 0 0 0> + , <&key_physical_attrs 125 100 1675 425 0 0 0> + ; + }; + // Node name must match original "EXT_POWER" label to preserve user settings. EXT_POWER { compatible = "zmk,ext-power-generic"; diff --git a/app/boards/arm/glove80/glove80.dtsi b/app/boards/arm/glove80/glove80.dtsi index d51a73ac..fdf890ad 100644 --- a/app/boards/arm/glove80/glove80.dtsi +++ b/app/boards/arm/glove80/glove80.dtsi @@ -8,10 +8,12 @@ #include +#include + / { chosen { zmk,kscan = &kscan0; - zmk,matrix-transform = &default_transform; + zmk,physical-layout = &default_layout; zephyr,code-partition = &code_partition; zephyr,sram = &sram0; zephyr,flash = &flash0; @@ -40,6 +42,95 @@ debounce-release-ms = <20>; }; + default_layout: default_layout { + compatible = "zmk,physical-layout"; + display-name = "Default"; + + transform = <&default_transform>; + + keys // w h x y rot rx ry + = <&key_physical_attrs 100 100 0 50 0 0 0> + , <&key_physical_attrs 100 100 100 50 0 0 0> + , <&key_physical_attrs 100 100 200 0 0 0 0> + , <&key_physical_attrs 100 100 300 0 0 0 0> + , <&key_physical_attrs 100 100 400 0 0 0 0> + , <&key_physical_attrs 100 100 1300 0 0 0 0> + , <&key_physical_attrs 100 100 1400 0 0 0 0> + , <&key_physical_attrs 100 100 1500 0 0 0 0> + , <&key_physical_attrs 100 100 1600 50 0 0 0> + , <&key_physical_attrs 100 100 1700 50 0 0 0> + , <&key_physical_attrs 100 100 0 150 0 0 0> + , <&key_physical_attrs 100 100 100 150 0 0 0> + , <&key_physical_attrs 100 100 200 100 0 0 0> + , <&key_physical_attrs 100 100 300 100 0 0 0> + , <&key_physical_attrs 100 100 400 100 0 0 0> + , <&key_physical_attrs 100 100 500 100 0 0 0> + , <&key_physical_attrs 100 100 1200 100 0 0 0> + , <&key_physical_attrs 100 100 1300 100 0 0 0> + , <&key_physical_attrs 100 100 1400 100 0 0 0> + , <&key_physical_attrs 100 100 1500 100 0 0 0> + , <&key_physical_attrs 100 100 1600 150 0 0 0> + , <&key_physical_attrs 100 100 1700 150 0 0 0> + , <&key_physical_attrs 100 100 0 250 0 0 0> + , <&key_physical_attrs 100 100 100 250 0 0 0> + , <&key_physical_attrs 100 100 200 200 0 0 0> + , <&key_physical_attrs 100 100 300 200 0 0 0> + , <&key_physical_attrs 100 100 400 200 0 0 0> + , <&key_physical_attrs 100 100 500 200 0 0 0> + , <&key_physical_attrs 100 100 1200 200 0 0 0> + , <&key_physical_attrs 100 100 1300 200 0 0 0> + , <&key_physical_attrs 100 100 1400 200 0 0 0> + , <&key_physical_attrs 100 100 1500 200 0 0 0> + , <&key_physical_attrs 100 100 1600 250 0 0 0> + , <&key_physical_attrs 100 100 1700 250 0 0 0> + , <&key_physical_attrs 100 100 0 350 0 0 0> + , <&key_physical_attrs 100 100 100 350 0 0 0> + , <&key_physical_attrs 100 100 200 300 0 0 0> + , <&key_physical_attrs 100 100 300 300 0 0 0> + , <&key_physical_attrs 100 100 400 300 0 0 0> + , <&key_physical_attrs 100 100 500 300 0 0 0> + , <&key_physical_attrs 100 100 1200 300 0 0 0> + , <&key_physical_attrs 100 100 1300 300 0 0 0> + , <&key_physical_attrs 100 100 1400 300 0 0 0> + , <&key_physical_attrs 100 100 1500 300 0 0 0> + , <&key_physical_attrs 100 100 1600 350 0 0 0> + , <&key_physical_attrs 100 100 1700 350 0 0 0> + , <&key_physical_attrs 100 100 0 450 0 0 0> + , <&key_physical_attrs 100 100 100 450 0 0 0> + , <&key_physical_attrs 100 100 200 400 0 0 0> + , <&key_physical_attrs 100 100 300 400 0 0 0> + , <&key_physical_attrs 100 100 400 400 0 0 0> + , <&key_physical_attrs 100 100 500 400 0 0 0> + , <&key_physical_attrs 100 100 400 450 3000 450 925> + , <&key_physical_attrs 100 100 400 450 4500 450 925> + , <&key_physical_attrs 100 100 400 450 6000 450 925> + , <&key_physical_attrs 100 100 1300 450 (-6000) 1350 925> + , <&key_physical_attrs 100 100 1300 450 (-4500) 1350 925> + , <&key_physical_attrs 100 100 1300 450 (-3000) 1350 925> + , <&key_physical_attrs 100 100 1200 400 0 0 0> + , <&key_physical_attrs 100 100 1300 400 0 0 0> + , <&key_physical_attrs 100 100 1400 400 0 0 0> + , <&key_physical_attrs 100 100 1500 400 0 0 0> + , <&key_physical_attrs 100 100 1600 450 0 0 0> + , <&key_physical_attrs 100 100 1700 450 0 0 0> + , <&key_physical_attrs 100 100 0 550 0 0 0> + , <&key_physical_attrs 100 100 100 550 0 0 0> + , <&key_physical_attrs 100 100 200 500 0 0 0> + , <&key_physical_attrs 100 100 300 500 0 0 0> + , <&key_physical_attrs 100 100 400 500 0 0 0> + , <&key_physical_attrs 100 100 400 550 2000 450 925> + , <&key_physical_attrs 100 100 400 550 4000 450 925> + , <&key_physical_attrs 100 100 400 550 6000 450 925> + , <&key_physical_attrs 100 100 1300 550 (-6000) 1350 925> + , <&key_physical_attrs 100 100 1300 550 (-4000) 1350 925> + , <&key_physical_attrs 100 100 1300 550 (-2000) 1350 925> + , <&key_physical_attrs 100 100 1300 500 0 0 0> + , <&key_physical_attrs 100 100 1400 500 0 0 0> + , <&key_physical_attrs 100 100 1500 500 0 0 0> + , <&key_physical_attrs 100 100 1600 550 0 0 0> + , <&key_physical_attrs 100 100 1700 550 0 0 0> + ; + }; }; &adc { From 907b1caaa69b63db874767bf1728f068989d9f46 Mon Sep 17 00:00:00 2001 From: Cem Aksoylar Date: Sat, 28 Sep 2024 14:45:34 -0700 Subject: [PATCH 044/415] refactor(shields): Add physical layout chosen nodes for consistency --- .../shields/splitkb_aurora_corne/splitkb_aurora_corne.dtsi | 1 + .../shields/splitkb_aurora_sofle/splitkb_aurora_sofle.dtsi | 1 + .../shields/splitkb_aurora_sweep/splitkb_aurora_sweep.dtsi | 1 + 3 files changed, 3 insertions(+) diff --git a/app/boards/shields/splitkb_aurora_corne/splitkb_aurora_corne.dtsi b/app/boards/shields/splitkb_aurora_corne/splitkb_aurora_corne.dtsi index d63cdf21..0b0ffdf3 100644 --- a/app/boards/shields/splitkb_aurora_corne/splitkb_aurora_corne.dtsi +++ b/app/boards/shields/splitkb_aurora_corne/splitkb_aurora_corne.dtsi @@ -20,6 +20,7 @@ chosen { zephyr,display = &oled; + zmk,physical-layout = &foostan_corne_6col_layout; }; default_transform: keymap_transform_0 { diff --git a/app/boards/shields/splitkb_aurora_sofle/splitkb_aurora_sofle.dtsi b/app/boards/shields/splitkb_aurora_sofle/splitkb_aurora_sofle.dtsi index e360528f..a40d29ae 100644 --- a/app/boards/shields/splitkb_aurora_sofle/splitkb_aurora_sofle.dtsi +++ b/app/boards/shields/splitkb_aurora_sofle/splitkb_aurora_sofle.dtsi @@ -16,6 +16,7 @@ chosen { zephyr,display = &oled; + zmk,physical-layout = &josefadamcik_sofle_layout; }; default_transform: keymap_transform_0 { diff --git a/app/boards/shields/splitkb_aurora_sweep/splitkb_aurora_sweep.dtsi b/app/boards/shields/splitkb_aurora_sweep/splitkb_aurora_sweep.dtsi index 4e1a0a97..c00b73f9 100644 --- a/app/boards/shields/splitkb_aurora_sweep/splitkb_aurora_sweep.dtsi +++ b/app/boards/shields/splitkb_aurora_sweep/splitkb_aurora_sweep.dtsi @@ -15,6 +15,7 @@ / { chosen { zephyr,display = &oled; + zmk,physical-layout = &cuddlykeyboards_ferris_layout; }; default_transform: keymap_transform_0 { From 608b6458a9a158d51179b6b22b34a5a9b5d2d137 Mon Sep 17 00:00:00 2001 From: Cem Aksoylar Date: Sat, 28 Sep 2024 15:04:47 -0700 Subject: [PATCH 045/415] feat(boards): Add physical layout to Corne-ish Zen --- app/boards/arm/corneish_zen/corneish_zen.dtsi | 12 +++++++++++- app/boards/arm/corneish_zen/corneish_zen.keymap | 4 ++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/app/boards/arm/corneish_zen/corneish_zen.dtsi b/app/boards/arm/corneish_zen/corneish_zen.dtsi index dbd6f93e..119781a2 100644 --- a/app/boards/arm/corneish_zen/corneish_zen.dtsi +++ b/app/boards/arm/corneish_zen/corneish_zen.dtsi @@ -10,6 +10,16 @@ #include +#include + +&foostan_corne_6col_layout { + transform = <&default_transform>; +}; + +&foostan_corne_5col_layout { + transform = <&five_column_transform>; +}; + / { model = "Corne-ish Zen"; compatible = "corneish_zen"; @@ -20,7 +30,7 @@ zephyr,flash = &flash0; zmk,kscan = &kscan0; zmk,display = &epd; - zmk,matrix-transform = &default_transform; + zmk,physical-layout = &foostan_corne_6col_layout; }; default_transform: keymap_transform_0 { diff --git a/app/boards/arm/corneish_zen/corneish_zen.keymap b/app/boards/arm/corneish_zen/corneish_zen.keymap index 8dbb7d3b..d53045eb 100644 --- a/app/boards/arm/corneish_zen/corneish_zen.keymap +++ b/app/boards/arm/corneish_zen/corneish_zen.keymap @@ -11,8 +11,8 @@ / { chosen { - zmk,matrix-transform = &default_transform; - // zmk,matrix-transform = &five_column_transform; + zmk,physical-layout = &foostan_corne_6col_layout; + // zmk,physical-layout = &foostan_corne_5col_layout; }; }; From 59c82ef27a6538408117762f0663a12039ce0b55 Mon Sep 17 00:00:00 2001 From: Cem Aksoylar Date: Mon, 30 Sep 2024 09:45:06 -0700 Subject: [PATCH 046/415] refactor(shields): Use space not hyphen for layout names --- app/boards/shields/kyria/kyria-layout.dtsi | 4 ++-- app/dts/layouts/foostan/corne.dtsi | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/boards/shields/kyria/kyria-layout.dtsi b/app/boards/shields/kyria/kyria-layout.dtsi index 59079a86..4c0c37e7 100644 --- a/app/boards/shields/kyria/kyria-layout.dtsi +++ b/app/boards/shields/kyria/kyria-layout.dtsi @@ -3,7 +3,7 @@ / { splitkb_kyria_6col_layout: splitkb_kyria_6col_layout { compatible = "zmk,physical-layout"; - display-name = "6-column"; + display-name = "6 Column"; keys // w h x y rot rx ry = <&key_physical_attrs 100 100 0 75 0 0 0> @@ -61,7 +61,7 @@ splitkb_kyria_5col_layout: splitkb_kyria_5col_layout { compatible = "zmk,physical-layout"; - display-name = "5-column"; + display-name = "5 Column"; keys // w h x y rot rx ry = <&key_physical_attrs 100 100 0 75 0 0 0> diff --git a/app/dts/layouts/foostan/corne.dtsi b/app/dts/layouts/foostan/corne.dtsi index ddafc789..5a644103 100644 --- a/app/dts/layouts/foostan/corne.dtsi +++ b/app/dts/layouts/foostan/corne.dtsi @@ -3,7 +3,7 @@ / { foostan_corne_6col_layout: foostan_corne_6col_layout { compatible = "zmk,physical-layout"; - display-name = "6-column"; + display-name = "6 Column"; keys // w h x y rot rx ry = <&key_physical_attrs 100 100 0 37 0 0 0> @@ -53,7 +53,7 @@ foostan_corne_5col_layout: foostan_corne_5col_layout { compatible = "zmk,physical-layout"; - display-name = "5-column"; + display-name = "5 Column"; keys // w h x y rot rx ry = <&key_physical_attrs 100 100 0 37 0 0 0> @@ -118,4 +118,4 @@ , < 30 31 32 33 34 35 >; }; }; -}; \ No newline at end of file +}; From 7276fd525ff90a82444a9c6e8e29906bb124fa53 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Mon, 30 Sep 2024 10:21:28 -0600 Subject: [PATCH 047/415] feat: Build asserts for requires studio layout bits. * When building with ZMK Studio, assert that we have physical layouts, and those layouts have key information set. --- app/src/physical_layouts.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/app/src/physical_layouts.c b/app/src/physical_layouts.c index 59077ede..6e719d29 100644 --- a/app/src/physical_layouts.c +++ b/app/src/physical_layouts.c @@ -29,6 +29,11 @@ ZMK_EVENT_IMPL(zmk_physical_layout_selection_changed); #define USE_PHY_LAYOUTS \ (DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) && !DT_HAS_CHOSEN(zmk_matrix_transform)) +BUILD_ASSERT( + !IS_ENABLED(CONFIG_ZMK_STUDIO) || USE_PHY_LAYOUTS, + "ZMK Studio requires physical layouts with key positions, and no chosen zmk,matrix-transform. " + "See https://zmk.dev/docs/development/hardware-integration/studio-setup"); + #if USE_PHY_LAYOUTS #define ZKPA_INIT(i, n) \ @@ -43,6 +48,9 @@ ZMK_EVENT_IMPL(zmk_physical_layout_selection_changed); } #define ZMK_LAYOUT_INST(n) \ + BUILD_ASSERT(!IS_ENABLED(CONFIG_ZMK_STUDIO) || DT_INST_NODE_HAS_PROP(n, keys), \ + "ZMK Studio requires physical layouts with key positions. See " \ + "https://zmk.dev/docs/development/hardware-integration/studio-setup"); \ static const struct zmk_key_physical_attrs const _CONCAT( \ _zmk_physical_layout_keys_, n)[DT_INST_PROP_LEN_OR(n, keys, 0)] = { \ LISTIFY(DT_INST_PROP_LEN_OR(n, keys, 0), ZKPA_INIT, (, ), n)}; \ From 8c21e7766df71e465eb10f4962b602836d1ccb00 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Mon, 30 Sep 2024 10:39:13 -0600 Subject: [PATCH 048/415] feat: Add physical layout to BDN9 rev2. --- app/boards/arm/bdn9/bdn9_rev2.dts | 36 +++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/app/boards/arm/bdn9/bdn9_rev2.dts b/app/boards/arm/bdn9/bdn9_rev2.dts index 12059c41..6274b834 100644 --- a/app/boards/arm/bdn9/bdn9_rev2.dts +++ b/app/boards/arm/bdn9/bdn9_rev2.dts @@ -9,6 +9,10 @@ #include #include +#include + +#include + / { model = "Keeb.io BDN9 rev2"; compatible = "keebio,bdn9", "st,stm32f072"; @@ -20,6 +24,38 @@ zmk,underglow = &led_strip; }; + matrix_transform: matrix_transform { + compatible = "zmk,matrix-transform"; + + compatible = "zmk,matrix-transform"; + columns = <3>; + rows = <3>; + 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) + >; + }; + + physical_layout { + compatible = "zmk,physical-layout"; + + display-name = "BDN9"; + transform = <&matrix_transform>; + + keys // w h x y rot rx ry + = <&key_physical_attrs 100 100 0 0 0 0 0> + , <&key_physical_attrs 100 100 100 0 0 0 0> + , <&key_physical_attrs 100 100 200 0 0 0 0> + , <&key_physical_attrs 100 100 0 100 0 0 0> + , <&key_physical_attrs 100 100 100 100 0 0 0> + , <&key_physical_attrs 100 100 200 100 0 0 0> + , <&key_physical_attrs 100 100 0 200 0 0 0> + , <&key_physical_attrs 100 100 100 200 0 0 0> + , <&key_physical_attrs 100 100 200 200 0 0 0> + ; + }; + kscan: kscan { compatible = "zmk,kscan-gpio-direct"; From ce04352e2f0c3ac7a2e0c51fe80439059bdee432 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Mon, 30 Sep 2024 11:23:15 -0600 Subject: [PATCH 049/415] feat: Add reviung41 physical layout. --- .../shields/reviung41/reviung41.overlay | 8 ++- app/dts/layouts/gtips/reviung41.dtsi | 55 +++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 app/dts/layouts/gtips/reviung41.dtsi diff --git a/app/boards/shields/reviung41/reviung41.overlay b/app/boards/shields/reviung41/reviung41.overlay index f8503fc3..b8a499e9 100644 --- a/app/boards/shields/reviung41/reviung41.overlay +++ b/app/boards/shields/reviung41/reviung41.overlay @@ -6,10 +6,16 @@ #include +#include + +>ips_reviung41_layout { + transform = <&default_transform>; +}; + / { chosen { zmk,kscan = &kscan0; - zmk,matrix-transform = &default_transform; + zmk,physical-layout = >ips_reviung41_layout; }; default_transform: keymap_transform_0 { diff --git a/app/dts/layouts/gtips/reviung41.dtsi b/app/dts/layouts/gtips/reviung41.dtsi new file mode 100644 index 00000000..08f45b3c --- /dev/null +++ b/app/dts/layouts/gtips/reviung41.dtsi @@ -0,0 +1,55 @@ +#include + +/ { + gtips_reviung41_layout: gtips_reviung41_layout { + compatible = "zmk,physical-layout"; + display-name = "reviung41"; + + keys + = <&key_physical_attrs 100 100 000 53 700 400 338> + , <&key_physical_attrs 100 100 100 53 700 400 338> + , <&key_physical_attrs 100 100 200 28 700 400 338> + , <&key_physical_attrs 100 100 300 03 700 400 338> + , <&key_physical_attrs 100 100 400 28 700 400 338> + , <&key_physical_attrs 100 100 500 38 700 400 338> + , <&key_physical_attrs 100 100 700 38 (-700) 900 338> + , <&key_physical_attrs 100 100 800 28 (-700) 900 338> + , <&key_physical_attrs 100 100 900 03 (-700) 900 338> + , <&key_physical_attrs 100 100 1000 28 (-700) 900 338> + , <&key_physical_attrs 100 100 1100 53 (-700) 900 338> + , <&key_physical_attrs 100 100 1200 53 (-700) 900 338> + + , <&key_physical_attrs 100 100 000 153 700 400 338> + , <&key_physical_attrs 100 100 100 153 700 400 338> + , <&key_physical_attrs 100 100 200 128 700 400 338> + , <&key_physical_attrs 100 100 300 103 700 400 338> + , <&key_physical_attrs 100 100 400 128 700 400 338> + , <&key_physical_attrs 100 100 500 138 700 400 338> + , <&key_physical_attrs 100 100 700 138 (-700) 900 338> + , <&key_physical_attrs 100 100 800 128 (-700) 900 338> + , <&key_physical_attrs 100 100 900 103 (-700) 900 338> + , <&key_physical_attrs 100 100 1000 128 (-700) 900 338> + , <&key_physical_attrs 100 100 1100 153 (-700) 900 338> + , <&key_physical_attrs 100 100 1200 153 (-700) 900 338> + + , <&key_physical_attrs 100 100 000 253 700 400 338> + , <&key_physical_attrs 100 100 100 253 700 400 338> + , <&key_physical_attrs 100 100 200 228 700 400 338> + , <&key_physical_attrs 100 100 300 203 700 400 338> + , <&key_physical_attrs 100 100 400 228 700 400 338> + , <&key_physical_attrs 100 100 500 238 700 400 338> + , <&key_physical_attrs 100 100 700 238 (-700) 900 338> + , <&key_physical_attrs 100 100 800 228 (-700) 900 338> + , <&key_physical_attrs 100 100 900 203 (-700) 900 338> + , <&key_physical_attrs 100 100 1000 228 (-700) 900 338> + , <&key_physical_attrs 100 100 1100 253 (-700) 900 338> + , <&key_physical_attrs 100 100 1200 253 (-700) 900 338> + + , <&key_physical_attrs 100 100 339 338 0 0 0> + , <&key_physical_attrs 100 100 450 365 700 500 415> + , <&key_physical_attrs 200 100 555 394 0 0 0> + , <&key_physical_attrs 100 100 760 365 (-700) 710 415> + , <&key_physical_attrs 100 100 871 338 0 0 0> + ; + }; +}; \ No newline at end of file From 99b424bb4b53af922f50bd0e483d722c6b401660 Mon Sep 17 00:00:00 2001 From: Nicolas Munnich <98408764+Nick-Munnich@users.noreply.github.com> Date: Tue, 1 Oct 2024 00:00:55 +0200 Subject: [PATCH 050/415] docs: Streamlined the new shield guide (#2515) * docs: Streamlined the new shield guide --------- Co-authored-by: Cem Aksoylar --- .../hardware-integration/new-shield.mdx | 632 ++++++++++-------- docs/docs/keymap-example-file.md | 26 - 2 files changed, 336 insertions(+), 322 deletions(-) delete mode 100644 docs/docs/keymap-example-file.md diff --git a/docs/docs/development/hardware-integration/new-shield.mdx b/docs/docs/development/hardware-integration/new-shield.mdx index 7a74f1be..1587cbc5 100644 --- a/docs/docs/development/hardware-integration/new-shield.mdx +++ b/docs/docs/development/hardware-integration/new-shield.mdx @@ -4,36 +4,62 @@ title: New Keyboard Shield import Tabs from "@theme/Tabs"; import TabItem from "@theme/TabItem"; -import KeymapExampleFile from "../../keymap-example-file.md"; - import InterconnectTabs from "@site/src/components/interconnect-tabs"; import Metadata from "@site/src/data/hardware-metadata.json"; +export const SplitTabs = (props) => ( + + {/* eslint-disable-next-line */} + {props.children} + + +); + +export const SplitInvisTabs = (props) => ( + + {/* eslint-disable-next-line */} + {props.children} + + +); + :::danger Before reading this section, it is **vital** that you read through our [clean room policy](../contributing/clean-room.md). ::: -## Overview - This guide will walk through the steps necessary to add ZMK support for a keyboard that uses an add-on MCU board (e.g. Pro Micro compatible) to provide the microprocessor. The high level steps are: -- From a template, create a new [Zephyr module](https://docs.zephyrproject.org/3.5.0/develop/modules.html) housed in a git repository containing one or more custom shields. +- Create a new [Zephyr module](https://docs.zephyrproject.org/3.5.0/develop/modules.html) to contain your shield. - Create a new shield directory. - Add the base Kconfig files. -- Add the shield overlay file to define the KSCAN driver for detecting key press/release. -- Add the matrix transform for mapping KSCAN row/column values to key positions in the keymap. -- Add a physical layout definition to select the matrix transform and KSCAN instance. +- Add the shield overlay file defining: + - The keyboard scan driver for detecting key press/release. + - The matrix transform for mapping keyboard scan row/column values to key positions in the keymap. + - The physical layout definition to select the matrix transform and keyboard scan instance. - Add a default keymap, which users can override in their own configs as needed. - Add a `.zmk.yml` metadata file to document the high level details of your shield, and the features it supports. -- Update the `build.yaml` file from the repository template to have some sample builds of the firmware to test. -After adding ZMK support for a basic shield using this guide, check the sidebar for guides on adding any additional features (such as encoders) that your keyboard has. It may be helpful to review the upstream [shields documentation](https://docs.zephyrproject.org/3.5.0/hardware/porting/shields.html#shields) to get a proper understanding of the underlying system before continuing. +Many of the above files will differ depending on whether your keyboard is a unibody or is [split into multiple parts](../../features/split-keyboards.md). -:::note -ZMK support for [split keyboards](../../features/split-keyboards.md) requires a few more files than single boards to ensure proper connectivity between the central and peripheral units. Check the following guides thoroughly to ensure that all the files are in place. -::: +After adding ZMK support for a basic shield using this guide, check the sidebar for guides on adding any additional features (such as encoders) that your keyboard has. +It may be helpful to review the upstream [shields documentation](https://docs.zephyrproject.org/3.5.0/hardware/porting/shields.html#shields) to get a proper understanding of the underlying system before continuing. ## New Zephyr Module Repository @@ -54,12 +80,14 @@ Follow these steps to create your new repository: - Select Public or Private, depending on your preference. - Click the green "Create repository" button -The repository is a combination of the directories and files required of a ZMK config, and those required of a shield module. To create a shield module, the following components are needed: +The repository is a combination of the directories and files required of a ZMK config, and those required of a shield module. +To create a shield module, the following components are needed: - The `boards/shields` directory, where the keyboard's files will go - The `zephyr/module.yml` file, which identifies and describes the module. See the [Zephyr documentation](https://docs.zephyrproject.org/3.5.0/develop/modules.html#module-yaml-file-description) for details on customising this file. For the purposes of creating a shield module, the default found in the template can be left untouched. -Neither of these should be moved out of their parent directory. The other files and directories such as `config` are not necessary for the purposes of a shield module, but rather intended to be used for user configuration and testing. +Neither of these should be moved out of their parent directory. +The other files and directories such as `config` are not necessary for the purposes of a shield module, but rather intended to be used for user configuration and testing. ## New Shield Directory @@ -75,74 +103,90 @@ mkdir boards/shields/ You can check out the [`shields` folder](https://github.com/zmkfirmware/zmk/tree/main/app/boards/shields) in the ZMK repo that houses [the in-tree supported shields](../../hardware.mdx) in order to copy and modify as a starting point. ::: -There are two required Kconfig files that need to be created for your new keyboard -shield to get it picked up for ZMK, `Kconfig.shield` and `Kconfig.defconfig`. +There are two required [Kconfig](https://docs.zephyrproject.org/3.5.0/build/kconfig/index.html) files that need to be created for your new keyboard shield to get it picked up for ZMK, `Kconfig.shield` and `Kconfig.defconfig`. + + ### Kconfig.shield -The `Kconfig.shield` file defines any additional Kconfig settings that may be relevant when using this keyboard. For most keyboards, there is just one additional configuration value for the shield itself. +The `Kconfig.shield` file defines the shield name used to build your keyboard. -```kconfig -config SHIELD_MY_BOARD - def_bool $(shields_list_contains,my_board) + + + +```kconfig title="Kconfig.shield" +# No whitespace after the comma or in your keyboard name! +config SHIELD_MY_KEYBOARD + def_bool $(shields_list_contains,my_keyboard) ``` -:::warning -Kconfig uses only commas for delimiters, and keeps all whitespaces in the function call. Therefore do not add a whitespace after the comma when configuring your shield as this would be treated as  my_board (with a leading whitespace) and will cause issues. -::: +This will set the `SHIELD_MY_KEYBOARD` flag to `y` whenever `my_keyboard` is used as the shield name. +The `SHIELD_MY_KEYBOARD` flag will be used in `Kconfig.defconfig` to set other properties about your shield, so make sure that they match. -This will make sure that a new configuration value named `SHIELD_MY_BOARD` is set to true whenever `my_board` is used as the shield name, either as the `SHIELD` variable [in a local build](../local-toolchain/build-flash.mdx) or in your `build.yaml` file [when using Github Actions](../../customization.md). Note that this configuration value will be used in `Kconfig.defconfig` to set other properties about your shield, so make sure that they match. + + -**For split boards**, you will need to add configurations for the left and right sides. For example, if your split halves are named `my_board_left` and `my_board_right`, it would look like this: +Split keyboards have multiple shield names defined, one for each part. +For example, if your keyboard consists of two halves named `my_keyboard_left` and `my_keyboard_right`, it would look like this: -```kconfig -config SHIELD_MY_BOARD_LEFT - def_bool $(shields_list_contains,my_board_left) +```kconfig title="Kconfig.shield" +# No whitespace after the comma or in your part name! +config SHIELD_MY_KEYBOARD_LEFT + def_bool $(shields_list_contains,my_keyboard_left) -config SHIELD_MY_BOARD_RIGHT - def_bool $(shields_list_contains,my_board_right) +# No whitespace after the comma or in your part name! +config SHIELD_MY_KEYBOARD_RIGHT + def_bool $(shields_list_contains,my_keyboard_right) ``` +This will set the `SHIELD_MY_KEYBOARD_LEFT` flag to `y` whenever `my_keyboard_left` is used as the shield name. +Likewise, when `my_keyboard_right` is used as the shield name the `SHIELD_MY_KEYBOARD_RIGHT` flag is set to `y`. +The `SHIELD_MY_KEYBOARD_LEFT` and `SHIELD_MY_KEYBOARD_RIGHT` flags will be used in `Kconfig.defconfig` to set other properties about your shields, so make sure that they match. + + + + ### Kconfig.defconfig -The `Kconfig.defconfig` file is where overrides for various configuration settings -that make sense to have different defaults when this shield is used. One main item -that usually has a new default value set here is the `ZMK_KEYBOARD_NAME` value, -which controls the display name of the device over USB and BLE. +The `Kconfig.defconfig` file is used to set new defaults for configuration settings when this shield is used. +One main item that usually has a new default value set here is the `ZMK_KEYBOARD_NAME` value, which controls the display name of the device over USB and BLE. -The updated new default values should always be wrapped inside a conditional on the shield config name defined in the `Kconfig.shield` file. Here's the simplest example file. +The updated new default values should always be wrapped inside a conditional on the shield config name defined in the `Kconfig.shield` file. -:::danger -The keyboard name must be less than or equal to 16 characters in length, otherwise the bluetooth advertising might fail and you will not be able to find your keyboard from your device. -::: + + -```kconfig -if SHIELD_MY_BOARD +```kconfig title="Kconfig.defconfig" +if SHIELD_MY_KEYBOARD +# Name must be less than 16 characters long! config ZMK_KEYBOARD_NAME - default "My Board" + default "My Keyboard" endif ``` -For split keyboards, `Kconfig.defconfig` needs to specify a few more options. -Which side is central (usually the left) is determined via the configuration in this file. + + + +For split keyboards, a central side (usually the left) is specified via the configuration in this file. For that side, the keyboard name is assigned and the central config is set. -The peripheral side is typically not assigned a name since only the central will be advertising for connections to other devices. +The peripheral side is not assigned a name. Finally, the split config needs to be set for both sides: -```kconfig -if SHIELD_MY_BOARD_LEFT +```kconfig title="Kconfig.defconfig" +if SHIELD_MY_KEYBOARD_LEFT +# Name must be less than 16 characters long! config ZMK_KEYBOARD_NAME - default "My Board" + default "My Keyboard" config ZMK_SPLIT_ROLE_CENTRAL default y endif -if SHIELD_MY_BOARD_LEFT || SHIELD_MY_BOARD_RIGHT +if SHIELD_MY_KEYBOARD_LEFT || SHIELD_MY_KEYBOARD_RIGHT config ZMK_SPLIT default y @@ -150,33 +194,94 @@ config ZMK_SPLIT endif ``` + + + +### User Configuration Files + +In addition to the `Kconfig.shield` and `Kconfig.defconfig` files, many shields will also define a user configuration file called `my_keyboard.conf`. +This file exists to provide "suggestions" of [configuration settings](../../config/index.md) for a user to select, such as enabling deep sleep. +Note that the name should match the shield/part name defined in the [Kconfig.shield file](#Kconfig.shield). + +:::warning +This file can also be used to set configuration options. +However, if a flag is set in this file, **the user can no longer change it**. +Though sometimes necessary, this method of setting configuration options is discouraged. +The case for which this is necessary is due to be eliminated in the future, making this method redundant. +::: + + + + + +Split keyboards can have multiple `.conf` files, one for each part. For example: + +- `my_keyboard.conf` - Configuration elements affect both halves +- `my_keyboard_left.conf` - Configuration elements only affect left half +- `my_keyboard_left.conf` - Configuration elements only affect right half + +In most case you'll only need to use the .conf file that affects both halves of a split board. + +:::note +The shared configuration in `my_keyboard.conf` is only applied when you are building with a [`zmk-config` folder](../local-toolchain/build-flash.mdx#building-from-zmk-config-folder) and it is present at `config/my_keyboard.conf`. +::: + + + + ## Shield Overlays + + +Shield overlay files contain a devicetree description that is merged with the primary board devicetree description during the firmware building process. +There are three main things that need to be defined in this file: + +- Your keyboard scan (kscan) driver, which determines which GPIO pins to scan for key press events +- Your matrix transform, which acts as a "bridge" between the kscan and the keymap +- Your physical layout, which aggregates the above and (optionally) defines physical key positions so that the keyboard can be used with [ZMK Studio](../../features/studio.md). + + + + +A unibody keyboard will have a single overlay file named `my_keyboard.overlay`, where `my_keyboard` is the shield name defined in the [Kconfig.shield file](#Kconfig.shield). + + + + +A split keyboard will have an overlay file defined for each split part. +For example, if the keyboard is split into a left and a right half, these can be named: + +- `my_keyboard_left.overlay` +- `my_keyboard_right.overlay` + +Here `my_keyboard_left` and `my_keyboard_right` are the shield names defined in the [Kconfig.shield file](#Kconfig.shield). + +Split keyboards often share some of their devicetree description. +The standard approach is to have a core `my_keyboard.dtsi` (devicetree include) file, which is included into each of the shield overlays. + + + + +### Kscan + +The kscan node defines the controller GPIO pins that are used to scan for key press and release events. The pins are referred to using the GPIO labels noted in the pinouts below: + To use GPIO pins that are not part of the interconnects as described above, you can use the GPIO labels that are specific to each controller type. For instance, pins numbered `PX.Y` in nRF52840-based boards can be referred to via `&gpioX Y` labels. An example is `&gpio1 7` for the `P1.07` pin that the nice!nano exposes in the middle of the board. - +The [Keyboard Scan configuration documentation](../../config/kscan.md) has the full details on configuring the kscan driver. + -The `.overlay` is the devicetree description of the keyboard shield that is merged with the primary board devicetree description before the build. For ZMK, this file at a minimum should include the chosen node named `zmk,kscan` that references a KSCAN driver instance. For a simple 3x3 macropad matrix, -this might look something like: +For a simple 3x3 macropad matrix, the kscan might look something like: -```dts +```dts title="my_keyboard.overlay" / { - chosen { - zmk,kscan = &kscan0; - }; - - kscan0: kscan_0 { + kscan0: kscan0 { compatible = "zmk,kscan-gpio-matrix"; diode-direction = "col2row"; wakeup-source; @@ -196,190 +301,162 @@ this might look something like: }; ``` -See the [Keyboard Scan configuration documentation](../../config/kscan.md) for details on configuring the KSCAN driver. - - -### .dtsi files and Shield Overlays (Split Shields) - -Unlike unibody keyboards, split keyboards have a core .dtsi file with shield overlays for each half of the keyboard. -It is preferred to define only the `col-gpios` or `row-gpios` in the common shield .dtsi, depending on the `diode-direction` value. -For `col2row` directed boards like the iris, the shared .dtsi file may look like this: - -```dts -#include +For split keyboards you should define your kscan in `my_keyboard.dtsi`. +If your `row-gpios` or your `col-gpios` (or both) are identical between the parts, then they should also be defined in `my_keyboard.dtsi`. +For example, for a `col2row` 2-part split keyboard (18 keys split into a 3x3 macropad on both halves) where the "row" GPIOs used are the same for both halves: +```dts title="my_keyboard.dtsi" / { - chosen { - zmk,kscan = &kscan0; - zmk,matrix-transform = &default_transform; - }; - - default_transform: keymap_transform_0 { - compatible = "zmk,matrix-transform"; - columns = <16>; - rows = <4>; -// | 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 | -// | SW29 | SW28 | SW27 | SW26 | | SW26 | SW27 | SW28 | SW29 | - 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,2) RC(4,9) RC(3,6) RC(3,7) RC(3,8) RC(3,9) RC(3,10) RC(3,11) - RC(4,3) RC(4,4) RC(4,5) RC(4,6) RC(4,7) RC(4,8) - >; - }; - - kscan0: kscan { + kscan0: kscan0 { compatible = "zmk,kscan-gpio-matrix"; diode-direction = "col2row"; wakeup-source; row-gpios - = <&pro_micro 6 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> // Row A from the schematic file - , <&pro_micro 7 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> // Row B from the schematic file - , <&pro_micro 8 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> // Row C from the schematic file - , <&pro_micro 0 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> // Row D from the schematic file - , <&pro_micro 4 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> // Row E from the schematic file + = <&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)> ; }; }; ``` -:::note -Notice that in addition to the common `row-gpios` that are declared in the kscan, the [matrix transform](#matrix-transform) is defined in the .dtsi. -::: +The missing `col-gpios` would be defined in your `my_keyboard_left.overlay` and `my_keyboard_right.overlay` files. -The missing `col-gpios` would be defined in your `_left.overlay` and `_right.overlay` files. -Keep in mind that the mirrored position of the GPIOs means that the `col-gpios` will appear reversed when the .overlay files are compared to one another. -Furthermore, the column offset for the [matrix transform](#matrix-transform) should be added to the right half of the keyboard's overlay -because the keyboard's switch matrix is read from left to right, top to bottom. -This is exemplified with the iris .overlay files. - -```dts title=iris_left.overlay -#include "iris.dtsi" // Notice that the main dtsi files are included in the overlay. +```dts title="my_keyboard_left.overlay" +#include "my_keyboard.dtsi" // The shared dtsi file is included in the overlay +// Label of the kscan node in the dtsi &kscan0 { col-gpios - = <&pro_micro 19 GPIO_ACTIVE_HIGH> // col1 in the schematic - , <&pro_micro 18 GPIO_ACTIVE_HIGH> // col2 in the schematic - , <&pro_micro 15 GPIO_ACTIVE_HIGH> // col3 in the schematic - , <&pro_micro 14 GPIO_ACTIVE_HIGH> // col4 in the schematic - , <&pro_micro 16 GPIO_ACTIVE_HIGH> // col5 in the schematic - , <&pro_micro 10 GPIO_ACTIVE_HIGH> // col6 in the schematic + = <&pro_micro 19 GPIO_ACTIVE_HIGH> + , <&pro_micro 18 GPIO_ACTIVE_HIGH> + , <&pro_micro 15 GPIO_ACTIVE_HIGH> ; }; ``` -```dts title=iris_right.overlay -#include "iris.dtsi" - -&default_transform { // The matrix transform for this board is 6 columns over because the left half is 6 columns wide according to the matrix. - col-offset = <6>; -}; +```dts title="my_keyboard_right.overlay" +#include "my_keyboard.dtsi" // The shared dtsi file is included in the overlay +// Label of the kscan node in the dtsi &kscan0 { col-gpios - = <&pro_micro 10 GPIO_ACTIVE_HIGH> // col6 in the schematic - , <&pro_micro 16 GPIO_ACTIVE_HIGH> // col5 in the schematic - , <&pro_micro 14 GPIO_ACTIVE_HIGH> // col4 in the schematic - , <&pro_micro 15 GPIO_ACTIVE_HIGH> // col3 in the schematic - , <&pro_micro 18 GPIO_ACTIVE_HIGH> // col2 in the schematic - , <&pro_micro 19 GPIO_ACTIVE_HIGH> // col1 in the schematic + = <&pro_micro 10 GPIO_ACTIVE_HIGH> + , <&pro_micro 11 GPIO_ACTIVE_HIGH> + , <&pro_micro 13 GPIO_ACTIVE_HIGH> ; }; - ``` -See the [Keyboard Scan configuration documentation](../../config/kscan.md) for details on configuring the KSCAN driver. - -### .conf files (Split Shields) - -While unibody boards only have one .conf file that applies configuration characteristics to the entire keyboard, -split keyboards are unique in that they contain multiple .conf files with different scopes. -For example, a split board called `my_awesome_split_board` would have the following files: - -- `my_awesome_split_board.conf` - Configuration elements affect both halves -- `my_awesome_split_board_left.conf` - Configuration elements only affect left half -- `my_awesome_split_board_right.conf` - Configuration elements only affect right half - -In most case you'll only need to use the .conf file that affects both halves of a split board. It's used for adding features like deep-sleep or rotary encoders. - -```ini title=my_awesome_split_board.conf -CONFIG_ZMK_SLEEP=y -``` - -:::note -The shared configuration in `my_awesome_split_board.conf` is only applied when you are building with a [`zmk-config` folder](../local-toolchain/build-flash.mdx#building-from-zmk-config-folder) and when it is present at `config/my_awesome_split_board.conf`. If you are not using a `zmk-config` folder, you will need to include the shared configuration in both `my_awesome_split_board_left.conf` and `my_awesome_split_board_right.conf` files. -::: - - + -## Matrix Transform +### Matrix Transform -Internally ZMK translates all row/column events into "key position" events to maintain a consistent model that works no matter what any possible GPIO matrix may look like for a certain keyboard. This is particularly helpful when: +The matrix transform is used to transform row/column events into "key position" events. -1. To reduce the used pins, an "efficient" number of rows/columns for the GPIO matrix is used, that does _not_ match the physical layout of rows/columns of the actual key switches. -1. For non rectangular keyboards with thumb clusters, non `1u` locations, etc. +When a key is pressed, a kscan event is generated from it with a `row` and a `column` value corresponding to the zero-based indices of the `row-gpios` and `col-gpios` pins that triggered the event, respectively. +Then, the "key position" triggered is the index of the `RC(row, column)` in the matrix transform where `row` and `column` are the indices as mentioned above. +This key position will in turn have a behavior binding associated with it in the keymap. -A "key position" is the numeric index (zero-based) of a given key, which identifies -the logical key location as perceived by the end user. All _keymap_ mappings actually bind behaviors to _key positions_, not to row/column values. + + -The `.overlay` must include a matrix transform that defines this mapping from row/column values to key positions. +The `my_keyboard.overlay` must include a matrix transform that defines this mapping from row/column values to key positions. +Add `#include ` to the top of the file. -Here is an example for the [nice60](https://github.com/Nicell/nice60), which uses an efficient 8x8 GPIO matrix, and uses a transform: +Here is an example of a matrix transform for the previous 3x3 macropad: -```dts -#include +```dts title="my_keyboard.overlay" +#include // Put this with the other includes at the top of your overlay / { - /* define kscan node with label `kscan0`... */ - - default_transform: keymap_transform_0 { + default_transform: keymap_transform0 { compatible = "zmk,matrix-transform"; - columns = <8>; - rows = <8>; -// | MX1 | MX2 | MX3 | MX4 | MX5 | MX6 | MX7 | MX8 | MX9 | MX10 | MX11 | MX12 | MX13 | MX14 | -// | MX15 | MX16 | MX17 | MX18 | MX19 | MX20 | MX21 | MX22 | MX23 | MX34 | MX25 | MX26 | MX27 | MX28 | -// | MX29 | MX30 | MX31 | MX32 | MX33 | MX34 | MX35 | MX36 | MX37 | MX38 | MX39 | MX40 | MX41 | -// | MX42 | MX43 | MX44 | MX45 | MX46 | MX47 | MX48 | MX49 | MX50 | MX51 | MX52 | MX53 | -// | MX54 | MX55 | MX56 | MX57 | MX58 | MX59 | MX60 | MX61 | + columns = <3>; // Length of the "col-gpios" array + rows = <3>; // Length of the "row-gpios" array map = < -RC(3,0) RC(2,0) RC(1,0) RC(0,0) RC(1,1) RC(0,1) RC(0,2) RC(1,3) RC(0,3) RC(1,4) RC(0,4) RC(0,5) RC(1,6) RC(1,7) -RC(4,0) RC(4,1) RC(3,1) RC(2,1) RC(2,2) RC(1,2) RC(2,3) RC(3,4) RC(2,4) RC(2,5) RC(1,5) RC(2,6) RC(2,7) RC(3,7) -RC(5,0) RC(5,1) RC(5,2) RC(4,2) RC(3,2) RC(4,3) RC(3,3) RC(4,4) RC(4,5) RC(3,5) RC(4,6) RC(3,6) RC(4,7) -RC(6,0) RC(6,1) RC(6,2) RC(6,3) RC(5,3) RC(6,4) RC(5,4) RC(6,5) RC(5,5) RC(6,6) RC(5,6) RC(5,7) -RC(7,0) RC(7,1) RC(7,2) RC(7,3) RC(7,5) RC(7,6) RC(6,7) RC(7,7) + // Key 1 | Key 2 | Key 3 + RC(0,0) RC(0,1) RC(0,2) + // Key 4 | Key 5 | Key 6 + RC(1,0) RC(1,1) RC(1,2) + // Key 7 | Key 8 | Key 9 + RC(2,0) RC(2,1) RC(2,2) >; }; - - /* potentially other overlay nodes... */ }; ``` -Some important things to note: + + -- The `#include ` is critical. The `RC` macro is used to generate the internal storage in the matrix transform, and is actually replaced by a C preprocessor before the final devicetree is compiled into ZMK. -- `RC(row, column)` is placed sequentially to define what row and column values that position corresponds to. -- If you have a keyboard with options for `2u` keys in certain positions, ANSI vs. ISO layouts, or break away portions, define one matrix transform for each possible arrangement to be used in the physical layouts. This will allow the users to select the right layout in their keymap files. +Split keyboards should define their matrix transform in the shared `my_keyboard.dtsi`. Add `#include ` to the top of the file. -See the [matrix transform section](../../config/kscan.md#matrix-transform) in the Keyboard Scan configuration documentation for details and more examples of matrix transforms. +Here is an example of a matrix transform for the previous example (18-key double macropad): -## Physical Layout +```dts title="my_keyboard.dtsi" +#include // Put this with the other includes at the top of your dtsi -The physical layout is the top level entity that aggregates all details about a certain possible layout for a keyboard: the matrix transform that defines the set of key positions and what row/column they correspond to, what kscan driver is used for that layout, etc. -For keyboards that support multiple layouts, setting a `chosen` node to a defined physical layout in your keymap will allow selecting the specific layout that you've built. +/ { + default_transform: keymap_transform0 { + compatible = "zmk,matrix-transform"; + columns = <6>; + rows = <3>; + map = < + // LKey 1 |LKey 2 |LKey 3 RKey 1 |RKey 2 |RKey 3 + RC(0,0) RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(0,5) + // LKey 4 |LKey 5 |LKey 6 RKey 4 |RKey 5 |RKey 6 + RC(1,0) RC(1,1) RC(1,2) RC(1,3) RC(1,4) RC(1,5) + // LKey 7 |LKey 8 |LKey 9 RKey 7 |RKey 8 |RKey 9 + RC(2,0) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(2,5) + >; + }; +}; +``` + +The above transform has 6 columns and three rows, while each half of the keyboard only has three columns and three rows. +To allow the kscan matrices to be joined in the matrix transform, an offset is applied to the matrix transform of peripherals. + +```dts title="my_keyboard_right.overlay" +&default_transform { // Offset of 3 because the left side has 3 columns + col-offset = <3>; +}; +``` + +This offset means that when the right half of the keyboard has a key event triggered by the GPIO pins at the indices `0,0` of its `row-gpios` and `col-gpios` arrays respectively, it will interpret it as an `RC(0,3)` event rather than an `RC(0,0)` event. +Additional peripherals would need their columns to be offset by an ever increasing number equal to the sum of the columns in the central + any peripherals that came before it. +You can also apply row offsets with `row-offset`. + + + + +The matrix transform is also used to "correct" pin orderings into something that more closely matches the physical order of keys. Causes of abnormal pin orderings include: + +- To reduce the used pins, an "efficient" number of rows/columns for the GPIO matrix is used, that does _not_ match the physical layout of rows/columns of the actual key switches. +- For non-rectangular keyboards with thumb clusters, non `1u` locations, etc. + +See the [in-tree keyboards](https://github.com/zmkfirmware/zmk/tree/main/app/boards/shields) that ZMK defines for examples of more complex matrix transformations. + +Also see the [matrix transform section](../../config/kscan.md#matrix-transform) in the Keyboard Scan configuration documentation for further details and examples of matrix transforms. + +### Physical Layout + +The physical layout is the top level entity that aggregates all details about a certain possible layout: + +- Your keyboard scan (kscan) driver +- Your matrix transform +- (Optional) Physical key positions + +The physical layout should be placed in the same file as the matrix transform, i.e. `my_keyboard.overlay` for unibodies and `my_keyboard.dtsi` for split keyboards. A physical layout is very basic, e.g.: -``` +```dts / { default_layout: default_layout { compatible = "zmk,physical-layout"; @@ -390,15 +467,11 @@ A physical layout is very basic, e.g.: }; ``` -When supporting multiple layouts, define the multiple layout nodes and then set a `chosen` for the default: +If a keyboard has multiple possible layouts (ex. you can snap off an outer column), then you should define multiple matrix transformations and multiple physical layouts. +If necessary, you can also define multiple kscan instances. -``` +```dts / { - chosen { - zmk,physical-layout = &default_layout; - ... - }; - default_layout: default_layout { compatible = "zmk,physical-layout"; display-name = "Default Layout"; @@ -415,38 +488,73 @@ When supporting multiple layouts, define the multiple layout nodes and then set }; ``` -This way, users can select a different layout by overriding the `zmk,physical-layout` chosen node in their keymap file. +See [ZMK Studio Setup](./studio-setup.md) for information on defining the `keys` property for physical key positions that lets you enable [ZMK Studio](../../features/studio.md) for your keyboard. + +### Chosen Node + +Set the `chosen` node to a defined "default" physical layout. This should also be placed in the same file as the physical layout, i.e. `my_keyboard.overlay` for unibodies and `my_keyboard.dtsi` for split keyboards. + +```dts +/ { + chosen { + zmk,physical-layout = &default_layout; + // Other chosen items + }; +}; +``` + +If you define multiple physical layouts, users can select a different layout by overriding the `zmk,physical-layout` chosen node in their keymap file. :::note -Some keyboards use different GPIO pins for different layouts, and need different kscan nodes created for each layout. -However, if all of your physical layouts use the same `kscan` node under the hood, you can skip setting the `kscan` property on each -layout and instead assign the `zmk,kscan` chosen node to your single kscan instance. +If all of your physical layouts use the same `kscan` node under the hood, you can skip setting the `kscan` property on each layout and instead assign the `zmk,kscan` chosen node to your single kscan instance: + +```dts +/ { + chosen { + zmk,kscan = &kscan0; + zmk,physical-layout = &default_layout; + // Other chosen items + }; +}; +``` + ::: ## Default Keymap -Each keyboard should provide a default keymap to be used when building the firmware, which can be overridden and customized by user configs. For "shield keyboards", this should be placed in the `boards/shields//.keymap` file. The keymap is configured as an additional devicetree overlay that includes the following: +Each keyboard should provide a default keymap to be used when building the firmware, which can be overridden and customized by user configs. +For "shield keyboards", this should be placed in the `boards/shields/my_keyboard/my_keyboard.keymap` file. +The keymap is configured as an additional devicetree overlay that includes the following: -- A node with `compatible = "zmk,keymap"` where each child node is a layer with a `bindings` array that binds each key position to a given behavior (e.g. key press, momentary layer, etc). +Here is an example simple keymap for a 3x3 macropad, with only one layer: -Here is an example simple keymap for the Kyria, with only one layer: +```dts title="my_keyboard.keymap" +/ { + keymap { + compatible = "zmk,keymap"; - + default_layer { // Layer 0 + // ------------------------------------- + // | Z | M | K | + // | A | B | C | + // | D | E | F | + bindings = < + &kp Z &kp M &kp K + &kp A &kp B &kp C + &kp D &kp E &kp F + >; + }; + }; + }; +``` -:::note -The two `#include` lines at the top of the keymap are required in order to bring in the default set of behaviors to make them available to bind, and to import a set of defines for the key codes, so keymaps can use parameters like `N2` or `K` instead of the raw keycode numeric values. -::: - -### Keymap Behaviors - -For documentation on the available behaviors for use in keymaps, see the [overview page for behaviors](../../keymaps/behaviors/index.mdx). +The keymap should match the order of the keys in the [matrix transform](#matrix-transform) exactly, left to right, top to bottom (they are both 1 dimensional arrays rearranged with newline characters for better legibility). +See [Keymaps](../../keymaps/index.mdx) for information on defining keymaps in ZMK. ## Metadata ZMK makes use of an additional metadata YAML file for all boards and shields to provide high level information about the hardware to be incorporated into setup scripts/utilities, website hardware list, etc. -The naming convention for metadata files is `{item_id}.zmk.yml`, where the `item_id` is the board/shield identifier, including version information but excluding any optional split `_left`/`_right` suffix, e.g. `corne.zmk.yml` or `nrfmicro_11.zmk.yml`. - Here is a sample `corne.zmk.yml` file from the repository: ```yaml @@ -465,91 +573,23 @@ siblings: - corne_right ``` -You should place a properly named `foo.zmk.yml` file in the directory next to your other shield values, and fill it out completely and accurately. See [Hardware Metadata Files](hardware-metadata-files.md) for the full details. - -## Build File - -To help you test/verify your firmware, update the `build.yaml` to list your particular board/shield combinations you want built whenever changes are published to GitHub. Open `build.yaml` with your editor and add a combination, e.g.: - -```yaml -# This file generates the GitHub Actions matrix -# For simple board + shield combinations, add them -# to the top level board and shield arrays, for more -# control, add individual board + shield combinations to -# the `include` property, e.g: -# -# board: [ "nice_nano_v2" ] -# shield: [ "corne_left", "corne_right" ] -# include: -# - board: bdn9_rev2 -# - board: nice_nano_v2 -# shield: reviung41 -# ---- -include: - - board: nice_nano_v2 - shield: -``` - -For split keyboards, you will need to specify the halves/siblings separately, e.g.: - -```yaml -include: - - board: mikoto_520 - shield: _left - - board: mikoto_520 - shield: _right -``` +You should place a properly named `my_keyboard.zmk.yml` file in the directory next to your other shield values, and fill it out completely and accurately. +See [Hardware Metadata Files](hardware-metadata-files.md) for the full details. ## Testing +Once you've defined everything as described above, you can build your firmware to make sure everything is working. + ### GitHub Actions -Using GitHub Actions to build your new firmware can save you from doing any local [development setup](../local-toolchain/setup/index.md), -at the expense of a longer feedback loop if there are issues. To push your changes and trigger a build: +To use GitHub Actions to test, push the files defining the keyboard to GitHub. +Next, [update the `build.yaml`](../../customization.md#building-additional-keyboards) of your `zmk-config` to build your keyboard. -- Add all your pending changes with `git add .` -- Commit your changes with `git commit -m "Initial shield"` -- Push the changes to GitHub with `git push` +- If your shield is defined in your `zmk-config`, then the shield should start building. +- If the shield is defined in a separate module, you will need to [adjust your `west.yml` to reference the module](https://zmk.dev/docs/features/modules#building-with-modules). -Once pushed, click on the "Actions" tab of the repo you created in the first step, and you should see a new build running. If the build is successful, there will be a new `firmware.zip` artifact shown on the summary screen you can download that will contain the new `.uf2` files that can be flashed to the device. +### Local Toolchain -### Local Build - -:::note -To build locally, be sure you've followed the [development setup](../local-toolchain/setup/index.md) guide first. -::: - -Once you've fully created the new keyboard shield definition, -you should be able to test with a build command like: - -```sh -west build --pristine -b nice_nano_v2 -- -DSHIELD= -DZMK_EXTRA_MODULES=/full/path/to/your/module -# replace with e.g. _left for split keyboards, then repeat for _right -``` - -The above build command generates a `build/zephyr/zmk.uf2` file that you can flash using the steps from the following section. See the dedicated [building and flashing page](../local-toolchain/build-flash.mdx) for more details. - -### Flashing - -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. If you need to flash an updated -UF2 file with fixes, you can re-enter the bootloader by double tapping the reset button. - -Alternatively, if your board supports flashing and you're not developing from -within a Dockerized environment, enable Device Firmware Upgrade (DFU) mode on -your board and run the following command to test your build: - -```sh -west flash -``` - -Please have a look at documentation specific to -[building and flashing](../local-toolchain/build-flash.mdx) for additional information. - -:::note -Further testing your keyboard shield without altering the root keymap file can be done with the use of `-DZMK_CONFIG` in your `west build` command, -shown [here](../local-toolchain/build-flash.mdx#building-from-zmk-config-folder) -::: +You can also use a local toolchain setup to test your keyboard. +Follow [our guide for getting set up](../local-toolchain/setup/index.md), then follow the [instructions for building and flashing locally](../local-toolchain/build-flash.mdx). +You will need to specify the module of your keyboard when building. diff --git a/docs/docs/keymap-example-file.md b/docs/docs/keymap-example-file.md deleted file mode 100644 index 91213f15..00000000 --- a/docs/docs/keymap-example-file.md +++ /dev/null @@ -1,26 +0,0 @@ -```dts -#include -#include - -/ { - keymap { - compatible = "zmk,keymap"; - - default_layer { -// -------------------------------------------------------------------------------------------------------------------------------------------------------------------- -// | 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 | CTRL+A | CTRL+C | | CTRL+V | CTRL+X | N | M | , | . | / | R CTRL | -// | GUI | DEL | RETURN | SPACE | ESCAPE | | RETURN | 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 LSHIFT &kp Z &kp X &kp C &kp V &kp B &kp LC(A) &kp LC(C) &kp LC(V) &kp LC(X) &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>; - }; - }; -}; -``` From e1958225593d89e575ef4a82a7d346d64c760fda Mon Sep 17 00:00:00 2001 From: Nicolas Munnich Date: Tue, 1 Oct 2024 01:31:17 +0200 Subject: [PATCH 051/415] docs: fixed broken anchors --- docs/docs/development/hardware-integration/new-shield.mdx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/docs/development/hardware-integration/new-shield.mdx b/docs/docs/development/hardware-integration/new-shield.mdx index 1587cbc5..f2be4946 100644 --- a/docs/docs/development/hardware-integration/new-shield.mdx +++ b/docs/docs/development/hardware-integration/new-shield.mdx @@ -201,7 +201,7 @@ endif In addition to the `Kconfig.shield` and `Kconfig.defconfig` files, many shields will also define a user configuration file called `my_keyboard.conf`. This file exists to provide "suggestions" of [configuration settings](../../config/index.md) for a user to select, such as enabling deep sleep. -Note that the name should match the shield/part name defined in the [Kconfig.shield file](#Kconfig.shield). +Note that the name should match the shield/part name defined in the [Kconfig.shield file](#kconfigshield). :::warning This file can also be used to set configuration options. @@ -243,7 +243,7 @@ There are three main things that need to be defined in this file: -A unibody keyboard will have a single overlay file named `my_keyboard.overlay`, where `my_keyboard` is the shield name defined in the [Kconfig.shield file](#Kconfig.shield). +A unibody keyboard will have a single overlay file named `my_keyboard.overlay`, where `my_keyboard` is the shield name defined in the [Kconfig.shield file](#kconfigshield). @@ -254,7 +254,7 @@ For example, if the keyboard is split into a left and a right half, these can be - `my_keyboard_left.overlay` - `my_keyboard_right.overlay` -Here `my_keyboard_left` and `my_keyboard_right` are the shield names defined in the [Kconfig.shield file](#Kconfig.shield). +Here `my_keyboard_left` and `my_keyboard_right` are the shield names defined in the [Kconfig.shield file](#kconfigshield). Split keyboards often share some of their devicetree description. The standard approach is to have a core `my_keyboard.dtsi` (devicetree include) file, which is included into each of the shield overlays. From 90d6285d98692900bb14a6e56befc844d357c18c Mon Sep 17 00:00:00 2001 From: LostQuasar Date: Mon, 30 Sep 2024 22:43:58 -0400 Subject: [PATCH 052/415] blog: Remove reference to spaceman (#2520) --- docs/blog/2023-10-05-zmk-sotf-6.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/blog/2023-10-05-zmk-sotf-6.md b/docs/blog/2023-10-05-zmk-sotf-6.md index 609425ee..b0c8c4d8 100644 --- a/docs/blog/2023-10-05-zmk-sotf-6.md +++ b/docs/blog/2023-10-05-zmk-sotf-6.md @@ -214,7 +214,7 @@ USB HID polling interval now defaults to 1 ms, i.e. a 1000Hz polling rate, thank - Waterfowl [#1554](https://github.com/zmkfirmware/zmk/pull/1554) - [JW2586](https://github.com/JW2586) - Kyria Rev 3 [#1627](https://github.com/zmkfirmware/zmk/pull/1627) - [petejohanson] - Leeloo v2 and Leeloo-Micro [#1762](https://github.com/zmkfirmware/zmk/pull/1762) - [ClicketySplit](https://github.com/ClicketySplit) -- Spaceman Pancake [#1400](https://github.com/zmkfirmware/zmk/pull/1400) - [jasonhazel](https://github.com/jasonhazel) +- Spaceboards Pancake [#1400](https://github.com/zmkfirmware/zmk/pull/1400) - [jasonhazel](https://github.com/jasonhazel) - Reviung5 [#1548](https://github.com/zmkfirmware/zmk/pull/1548) - [zblesk](https://github.com/zblesk) ## New Boards From 73ca365530bc79d03dc64d89adc03b4ccbeeb14e Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Tue, 1 Oct 2024 01:14:44 -0600 Subject: [PATCH 053/415] feat(boards): PM RP2040 flash settings support. --- app/boards/sparkfun_pro_micro_rp2040.conf | 7 +++++++ app/boards/sparkfun_pro_micro_rp2040.overlay | 16 ++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/app/boards/sparkfun_pro_micro_rp2040.conf b/app/boards/sparkfun_pro_micro_rp2040.conf index 21c1893d..354d7007 100644 --- a/app/boards/sparkfun_pro_micro_rp2040.conf +++ b/app/boards/sparkfun_pro_micro_rp2040.conf @@ -2,3 +2,10 @@ CONFIG_CONSOLE=n CONFIG_SERIAL=n CONFIG_UART_CONSOLE=n CONFIG_ZMK_USB=y + +CONFIG_MPU_ALLOW_FLASH_WRITE=y +CONFIG_NVS=y +CONFIG_SETTINGS_NVS=y +CONFIG_FLASH=y +CONFIG_FLASH_PAGE_LAYOUT=y +CONFIG_FLASH_MAP=y \ No newline at end of file diff --git a/app/boards/sparkfun_pro_micro_rp2040.overlay b/app/boards/sparkfun_pro_micro_rp2040.overlay index 72b3adca..21aa7dff 100644 --- a/app/boards/sparkfun_pro_micro_rp2040.overlay +++ b/app/boards/sparkfun_pro_micro_rp2040.overlay @@ -5,3 +5,19 @@ */ &pro_micro_serial { status = "disabled"; }; + +// We override to 2MB for maximum compatibility +&code_partition { + reg = <0x100 (DT_SIZE_M(2) - 0x100 - DT_SIZE_K(512))>; +}; + +&flash0 { + reg = <0x10000000 DT_SIZE_M(2)>; + + partitions { + storage_partition: partition@180000 { + reg = <0x180000 DT_SIZE_K(512)>; + read-only; + }; + }; +}; From 36f146226e598c788a76367686aac3af7c4deccb Mon Sep 17 00:00:00 2001 From: Joel Spadin Date: Mon, 30 Sep 2024 00:16:01 -0500 Subject: [PATCH 054/415] feat(boards)!: refactor common layouts Removed the combined .dtsi file for each group of common layouts, and split the position map across the files in each group. This makes reading the position maps slightly more difficult, but it aligns the common layouts with the keyboard-specific ones such as foostan/corne.dtsi in that simply including each header adds the layout, with no need to set status = "okay". --- app/boards/arm/bt60/bt60_v1.dts | 9 ++- app/boards/arm/ckp/bt60_v2.dts | 9 ++- app/boards/arm/ckp/bt65_v1.dts | 9 ++- app/boards/arm/ckp/bt75_v1.dts | 7 +- app/boards/arm/planck/planck_rev6.dts | 7 +- app/boards/arm/preonic/preonic_rev3.dts | 7 +- .../layouts/common/60percent/60percent.dtsi | 72 ------------------- app/dts/layouts/common/60percent/all1u.dtsi | 16 ++++- app/dts/layouts/common/60percent/ansi.dtsi | 16 ++++- app/dts/layouts/common/60percent/hhkb.dtsi | 16 ++++- app/dts/layouts/common/60percent/iso.dtsi | 16 ++++- .../common/60percent/position_map.dtsi | 7 ++ .../layouts/common/65percent/65percent.dtsi | 72 ------------------- app/dts/layouts/common/65percent/all1u.dtsi | 16 ++++- app/dts/layouts/common/65percent/ansi.dtsi | 16 ++++- app/dts/layouts/common/65percent/hhkb.dtsi | 16 ++++- app/dts/layouts/common/65percent/iso.dtsi | 16 ++++- .../common/65percent/position_map.dtsi | 7 ++ .../layouts/common/75percent/75percent.dtsi | 59 --------------- app/dts/layouts/common/75percent/all1u.dtsi | 17 ++++- app/dts/layouts/common/75percent/ansi.dtsi | 17 ++++- app/dts/layouts/common/75percent/iso.dtsi | 17 ++++- .../common/75percent/position_map.dtsi | 7 ++ app/dts/layouts/common/ortho_4x12/1x2u.dtsi | 15 +++- app/dts/layouts/common/ortho_4x12/2x2u.dtsi | 15 +++- app/dts/layouts/common/ortho_4x12/all1u.dtsi | 15 +++- .../layouts/common/ortho_4x12/ortho_4x12.dtsi | 53 -------------- .../common/ortho_4x12/position_map.dtsi | 7 ++ app/dts/layouts/common/ortho_5x12/1x2u.dtsi | 16 ++++- app/dts/layouts/common/ortho_5x12/2x2u.dtsi | 16 ++++- app/dts/layouts/common/ortho_5x12/all1u.dtsi | 14 ++++ .../layouts/common/ortho_5x12/ortho_5x12.dtsi | 56 --------------- .../common/ortho_5x12/position_map.dtsi | 7 ++ app/dts/layouts/common/tkl/ansi.dtsi | 1 + app/dts/layouts/common/tkl/position_map.dtsi | 7 ++ 35 files changed, 318 insertions(+), 355 deletions(-) delete mode 100644 app/dts/layouts/common/60percent/60percent.dtsi create mode 100644 app/dts/layouts/common/60percent/position_map.dtsi delete mode 100644 app/dts/layouts/common/65percent/65percent.dtsi create mode 100644 app/dts/layouts/common/65percent/position_map.dtsi delete mode 100644 app/dts/layouts/common/75percent/75percent.dtsi create mode 100644 app/dts/layouts/common/75percent/position_map.dtsi delete mode 100644 app/dts/layouts/common/ortho_4x12/ortho_4x12.dtsi create mode 100644 app/dts/layouts/common/ortho_4x12/position_map.dtsi delete mode 100644 app/dts/layouts/common/ortho_5x12/ortho_5x12.dtsi create mode 100644 app/dts/layouts/common/ortho_5x12/position_map.dtsi create mode 100644 app/dts/layouts/common/tkl/position_map.dtsi diff --git a/app/boards/arm/bt60/bt60_v1.dts b/app/boards/arm/bt60/bt60_v1.dts index d7ecb5ae..5790458d 100644 --- a/app/boards/arm/bt60/bt60_v1.dts +++ b/app/boards/arm/bt60/bt60_v1.dts @@ -6,7 +6,10 @@ /dts-v1/; #include "bt60.dtsi" -#include +#include +#include +#include +#include / { @@ -102,21 +105,17 @@ }; &layout_60_ansi { - status = "okay"; transform = <&ansi_transform>; }; &layout_60_iso { - status = "okay"; transform = <&iso_transform>; }; &layout_60_all1u { - status = "okay"; transform = <&all_1u_transform>; }; &layout_60_hhkb { - status = "okay"; transform = <&hhkb_transform>; }; diff --git a/app/boards/arm/ckp/bt60_v2.dts b/app/boards/arm/ckp/bt60_v2.dts index 751cad09..1cdb0307 100644 --- a/app/boards/arm/ckp/bt60_v2.dts +++ b/app/boards/arm/ckp/bt60_v2.dts @@ -6,7 +6,10 @@ /dts-v1/; #include "ckp.dtsi" -#include +#include +#include +#include +#include / { @@ -72,21 +75,17 @@ }; &layout_60_ansi { - status = "okay"; transform = <&ansi_transform>; }; &layout_60_iso { - status = "okay"; transform = <&iso_transform>; }; &layout_60_all1u { - status = "okay"; transform = <&all_1u_transform>; }; &layout_60_hhkb { - status = "okay"; transform = <&hhkb_transform>; }; diff --git a/app/boards/arm/ckp/bt65_v1.dts b/app/boards/arm/ckp/bt65_v1.dts index cdea235f..77e81289 100644 --- a/app/boards/arm/ckp/bt65_v1.dts +++ b/app/boards/arm/ckp/bt65_v1.dts @@ -6,7 +6,10 @@ /dts-v1/; #include "ckp.dtsi" -#include +#include +#include +#include +#include / { @@ -72,21 +75,17 @@ }; &layout_65_ansi { - status = "okay"; transform = <&ansi_transform>; }; &layout_65_iso { - status = "okay"; transform = <&iso_transform>; }; &layout_65_all1u { - status = "okay"; transform = <&all_1u_transform>; }; &layout_65_hhkb { - status = "okay"; transform = <&hhkb_transform>; }; diff --git a/app/boards/arm/ckp/bt75_v1.dts b/app/boards/arm/ckp/bt75_v1.dts index 7077aa1d..7c9ab664 100644 --- a/app/boards/arm/ckp/bt75_v1.dts +++ b/app/boards/arm/ckp/bt75_v1.dts @@ -6,7 +6,9 @@ /dts-v1/; #include "ckp.dtsi" -#include +#include +#include +#include / { @@ -62,16 +64,13 @@ }; &layout_75_ansi { - status = "okay"; transform = <&ansi_transform>; }; &layout_75_iso { - status = "okay"; transform = <&iso_transform>; }; &layout_75_all1u { - status = "okay"; transform = <&all_1u_transform>; }; diff --git a/app/boards/arm/planck/planck_rev6.dts b/app/boards/arm/planck/planck_rev6.dts index d3aaf8fe..2f34571f 100644 --- a/app/boards/arm/planck/planck_rev6.dts +++ b/app/boards/arm/planck/planck_rev6.dts @@ -9,7 +9,9 @@ #include #include -#include +#include +#include +#include / { @@ -142,16 +144,13 @@ zephyr_udc0: &usb { }; &layout_ortho_4x12_all1u { - status = "okay"; transform = <&layout_grid_transform>; }; &layout_ortho_4x12_1x2u { - status = "okay"; transform = <&layout_mit_transform>; }; &layout_ortho_4x12_2x2u { - status = "okay"; transform = <&layout_2x2u_transform>; }; diff --git a/app/boards/arm/preonic/preonic_rev3.dts b/app/boards/arm/preonic/preonic_rev3.dts index 8032e459..0bb0e2ce 100644 --- a/app/boards/arm/preonic/preonic_rev3.dts +++ b/app/boards/arm/preonic/preonic_rev3.dts @@ -9,7 +9,9 @@ #include #include -#include +#include +#include +#include / { model = "Preonic PCD, rev3"; @@ -134,16 +136,13 @@ zephyr_udc0: &usb { }; &layout_ortho_5x12_all1u { - status = "okay"; transform = <&layout_grid_transform>; }; &layout_ortho_5x12_1x2u { - status = "okay"; transform = <&layout_mit_transform>; }; &layout_ortho_5x12_2x2u { - status = "okay"; transform = <&layout_2x2u_transform>; }; diff --git a/app/dts/layouts/common/60percent/60percent.dtsi b/app/dts/layouts/common/60percent/60percent.dtsi deleted file mode 100644 index 03f42e2a..00000000 --- a/app/dts/layouts/common/60percent/60percent.dtsi +++ /dev/null @@ -1,72 +0,0 @@ -#include -#include -#include -#include - -&layout_60_ansi { - status = "disabled"; -}; - -&layout_60_iso { - status = "disabled"; -}; - -&layout_60_all1u { - status = "disabled"; -}; - -&layout_60_hhkb { - status = "disabled"; -}; - -/ { - layouts_common_60_percent_position_map: layouts_common_60_percent_position_map { - compatible = "zmk,physical-layout-position-map"; - - complete; - - layout_60_all1u { - physical-layout = <&layout_60_all1u>; - positions - = < 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14> - , <15 16 17 18 19 20 21 22 23 24 25 26 27 28> - , <29 30 31 32 33 34 35 36 37 38 39 40 41> - , <42 43 44 45 46 47 48 49 50 51 52 53 54 55 56> - , <57 58 59 60 61 62 64 63 65> - ; - }; - - layout_60_ansi { - physical-layout = <&layout_60_ansi>; - positions - = < 0 1 2 3 4 5 6 7 8 9 10 11 12 13 61> - , <14 15 16 17 18 19 20 21 22 23 24 25 26 27> - , <28 29 30 31 32 33 34 35 36 37 38 39 40> - , <41 62 42 43 44 45 46 47 48 49 50 51 52 63 64> - , <53 54 55 56 57 58 60 59 65> - ; - }; - - layout_60_hhkb { - physical-layout = <&layout_60_hhkb>; - positions - = < 0 1 2 3 4 5 6 7 8 9 10 11 12 13 60> - , <14 15 16 17 18 19 20 21 22 23 24 25 26 27> - , <28 29 30 31 32 33 34 35 36 37 38 39 40> - , <41 61 42 43 44 45 46 47 48 49 50 51 52 62 63> - , <53 54 55 56 57 58 59 64 65> - ; - }; - - layout_60_iso { - physical-layout = <&layout_60_iso>; - positions - = < 0 1 2 3 4 5 6 7 8 9 10 11 12 13 62> - , <14 15 16 17 18 19 20 21 22 23 24 25 26 63> - , <27 28 29 30 31 32 33 34 35 36 37 38 40> - , <41 42 43 44 45 46 47 48 49 50 51 52 53 64 65> - , <54 55 56 57 58 59 61 60 39> - ; - }; - }; -}; \ No newline at end of file diff --git a/app/dts/layouts/common/60percent/all1u.dtsi b/app/dts/layouts/common/60percent/all1u.dtsi index 47e3ad38..45431689 100644 --- a/app/dts/layouts/common/60percent/all1u.dtsi +++ b/app/dts/layouts/common/60percent/all1u.dtsi @@ -1,3 +1,4 @@ +#include #include / { @@ -74,4 +75,17 @@ , <&key_physical_attrs 100 100 1400 400 0 0 0> ; }; -}; \ No newline at end of file +}; + +&layouts_common_60_percent_position_map { + layout_60_all1u { + physical-layout = <&layout_60_all1u>; + positions + = < 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14> + , <15 16 17 18 19 20 21 22 23 24 25 26 27 28> + , <29 30 31 32 33 34 35 36 37 38 39 40 41> + , <42 43 44 45 46 47 48 49 50 51 52 53 54 55 56> + , <57 58 59 60 61 62 64 63 65> + ; + }; +}; diff --git a/app/dts/layouts/common/60percent/ansi.dtsi b/app/dts/layouts/common/60percent/ansi.dtsi index 2c8074bc..b3b870c5 100644 --- a/app/dts/layouts/common/60percent/ansi.dtsi +++ b/app/dts/layouts/common/60percent/ansi.dtsi @@ -1,3 +1,4 @@ +#include #include / { @@ -69,4 +70,17 @@ , <&key_physical_attrs 125 100 1375 400 0 0 0> ; }; -}; \ No newline at end of file +}; + +&layouts_common_60_percent_position_map { + layout_60_ansi { + physical-layout = <&layout_60_ansi>; + positions + = < 0 1 2 3 4 5 6 7 8 9 10 11 12 13 61> + , <14 15 16 17 18 19 20 21 22 23 24 25 26 27> + , <28 29 30 31 32 33 34 35 36 37 38 39 40> + , <41 62 42 43 44 45 46 47 48 49 50 51 52 63 64> + , <53 54 55 56 57 58 60 59 65> + ; + }; +}; diff --git a/app/dts/layouts/common/60percent/hhkb.dtsi b/app/dts/layouts/common/60percent/hhkb.dtsi index f14e72be..a3c271e7 100644 --- a/app/dts/layouts/common/60percent/hhkb.dtsi +++ b/app/dts/layouts/common/60percent/hhkb.dtsi @@ -1,3 +1,4 @@ +#include #include / { @@ -68,4 +69,17 @@ , <&key_physical_attrs 150 100 1350 400 0 0 0> ; }; -}; \ No newline at end of file +}; + +&layouts_common_60_percent_position_map { + layout_60_hhkb { + physical-layout = <&layout_60_hhkb>; + positions + = < 0 1 2 3 4 5 6 7 8 9 10 11 12 13 60> + , <14 15 16 17 18 19 20 21 22 23 24 25 26 27> + , <28 29 30 31 32 33 34 35 36 37 38 39 40> + , <41 61 42 43 44 45 46 47 48 49 50 51 52 62 63> + , <53 54 55 56 57 58 59 64 65> + ; + }; +}; diff --git a/app/dts/layouts/common/60percent/iso.dtsi b/app/dts/layouts/common/60percent/iso.dtsi index 2e3a00d8..e1214b58 100644 --- a/app/dts/layouts/common/60percent/iso.dtsi +++ b/app/dts/layouts/common/60percent/iso.dtsi @@ -1,3 +1,4 @@ +#include #include / { @@ -70,4 +71,17 @@ , <&key_physical_attrs 125 100 1375 400 0 0 0> ; }; -}; \ No newline at end of file +}; + +&layouts_common_60_percent_position_map { + layout_60_iso { + physical-layout = <&layout_60_iso>; + positions + = < 0 1 2 3 4 5 6 7 8 9 10 11 12 13 62> + , <14 15 16 17 18 19 20 21 22 23 24 25 26 63> + , <27 28 29 30 31 32 33 34 35 36 37 38 40> + , <41 42 43 44 45 46 47 48 49 50 51 52 53 64 65> + , <54 55 56 57 58 59 61 60 39> + ; + }; +}; diff --git a/app/dts/layouts/common/60percent/position_map.dtsi b/app/dts/layouts/common/60percent/position_map.dtsi new file mode 100644 index 00000000..b8db2d01 --- /dev/null +++ b/app/dts/layouts/common/60percent/position_map.dtsi @@ -0,0 +1,7 @@ +/ { + layouts_common_60_percent_position_map: layouts_common_60_percent_position_map { + compatible = "zmk,physical-layout-position-map"; + + complete; + }; +}; diff --git a/app/dts/layouts/common/65percent/65percent.dtsi b/app/dts/layouts/common/65percent/65percent.dtsi deleted file mode 100644 index 9e46d315..00000000 --- a/app/dts/layouts/common/65percent/65percent.dtsi +++ /dev/null @@ -1,72 +0,0 @@ -#include -#include -#include -#include - -&layout_65_ansi { - status = "disabled"; -}; - -&layout_65_iso { - status = "disabled"; -}; - -&layout_65_all1u { - status = "disabled"; -}; - -&layout_65_hhkb { - status = "disabled"; -}; - -/ { - layouts_common_65_percent_position_map: layouts_common_65_percent_position_map { - compatible = "zmk,physical-layout-position-map"; - - complete; - - layout_65_all1u { - physical-layout = <&layout_65_all1u>; - positions - = < 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15> - , <16 17 18 19 20 21 22 23 24 25 26 27 28 29 30> - , <31 32 33 34 35 36 37 38 39 40 41 42 43 44> - , <45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60> - , <61 62 63 64 65 66 67 68 69 70> - ; - }; - - layout_65_ansi { - physical-layout = <&layout_65_ansi>; - positions - = < 0 1 2 3 4 5 6 7 8 9 10 11 12 13 68 14> - , <15 16 17 18 19 20 21 22 23 24 25 26 27 28 29> - , <30 31 32 33 34 35 36 37 38 39 40 41 42 43> - , <44 69 45 46 47 48 49 50 51 52 53 54 55 70 56 57> - , <58 59 60 61 62 63 64 65 66 67> - ; - }; - - layout_65_hhkb { - physical-layout = <&layout_65_hhkb>; - positions - = < 0 1 2 3 4 5 6 7 8 9 10 11 12 13 65 14> - , <15 16 17 18 19 20 21 22 23 24 25 26 27 28 29> - , <30 31 32 33 34 35 36 37 38 39 40 41 42 43> - , <44 66 45 46 47 48 49 50 51 52 53 54 55 67 68 56> - , <57 58 59 60 61 62 63 69 70 64> - ; - }; - - layout_65_iso { - physical-layout = <&layout_65_iso>; - positions - = < 0 1 2 3 4 5 6 7 8 9 10 11 12 13 69 14> - , <15 16 17 18 19 20 21 22 23 24 25 26 27 70 28> - , <29 30 31 32 33 34 35 36 37 38 39 40 42 43> - , <44 45 46 47 48 49 50 51 52 53 54 55 56 41 57 58> - , <59 60 61 62 63 64 65 66 67 68> - ; - }; - }; -}; \ No newline at end of file diff --git a/app/dts/layouts/common/65percent/all1u.dtsi b/app/dts/layouts/common/65percent/all1u.dtsi index 8ab62ef2..7ff70358 100644 --- a/app/dts/layouts/common/65percent/all1u.dtsi +++ b/app/dts/layouts/common/65percent/all1u.dtsi @@ -1,3 +1,4 @@ +#include #include / { @@ -82,4 +83,17 @@ , <&key_physical_attrs 100 100 1500 400 0 0 0> ; }; -}; \ No newline at end of file +}; + +&layouts_common_65_percent_position_map { + layout_65_all1u { + physical-layout = <&layout_65_all1u>; + positions + = < 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15> + , <16 17 18 19 20 21 22 23 24 25 26 27 28 29 30> + , <31 32 33 34 35 36 37 38 39 40 41 42 43 44> + , <45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60> + , <61 62 63 64 65 66 67 68 69 70> + ; + }; +}; diff --git a/app/dts/layouts/common/65percent/ansi.dtsi b/app/dts/layouts/common/65percent/ansi.dtsi index 9685515c..991a672c 100644 --- a/app/dts/layouts/common/65percent/ansi.dtsi +++ b/app/dts/layouts/common/65percent/ansi.dtsi @@ -1,3 +1,4 @@ +#include #include / { @@ -76,4 +77,17 @@ , <&key_physical_attrs 100 100 1500 400 0 0 0> ; }; -}; \ No newline at end of file +}; + +&layouts_common_65_percent_position_map { + layout_65_ansi { + physical-layout = <&layout_65_ansi>; + positions + = < 0 1 2 3 4 5 6 7 8 9 10 11 12 13 68 14> + , <15 16 17 18 19 20 21 22 23 24 25 26 27 28 29> + , <30 31 32 33 34 35 36 37 38 39 40 41 42 43> + , <44 69 45 46 47 48 49 50 51 52 53 54 55 70 56 57> + , <58 59 60 61 62 63 64 65 66 67> + ; + }; +}; diff --git a/app/dts/layouts/common/65percent/hhkb.dtsi b/app/dts/layouts/common/65percent/hhkb.dtsi index cbadad96..d0684f3c 100644 --- a/app/dts/layouts/common/65percent/hhkb.dtsi +++ b/app/dts/layouts/common/65percent/hhkb.dtsi @@ -1,3 +1,4 @@ +#include #include / { @@ -73,4 +74,17 @@ , <&key_physical_attrs 100 100 1500 400 0 0 0> ; }; -}; \ No newline at end of file +}; + +&layouts_common_65_percent_position_map { + layout_65_hhkb { + physical-layout = <&layout_65_hhkb>; + positions + = < 0 1 2 3 4 5 6 7 8 9 10 11 12 13 65 14> + , <15 16 17 18 19 20 21 22 23 24 25 26 27 28 29> + , <30 31 32 33 34 35 36 37 38 39 40 41 42 43> + , <44 66 45 46 47 48 49 50 51 52 53 54 55 67 68 56> + , <57 58 59 60 61 62 63 69 70 64> + ; + }; +}; diff --git a/app/dts/layouts/common/65percent/iso.dtsi b/app/dts/layouts/common/65percent/iso.dtsi index 3395c614..c94ee1d6 100644 --- a/app/dts/layouts/common/65percent/iso.dtsi +++ b/app/dts/layouts/common/65percent/iso.dtsi @@ -1,3 +1,4 @@ +#include #include / { @@ -77,4 +78,17 @@ , <&key_physical_attrs 100 100 1500 400 0 0 0> ; }; -}; \ No newline at end of file +}; + +&layouts_common_65_percent_position_map { + layout_65_iso { + physical-layout = <&layout_65_iso>; + positions + = < 0 1 2 3 4 5 6 7 8 9 10 11 12 13 69 14> + , <15 16 17 18 19 20 21 22 23 24 25 26 27 70 28> + , <29 30 31 32 33 34 35 36 37 38 39 40 42 43> + , <44 45 46 47 48 49 50 51 52 53 54 55 56 41 57 58> + , <59 60 61 62 63 64 65 66 67 68> + ; + }; +}; diff --git a/app/dts/layouts/common/65percent/position_map.dtsi b/app/dts/layouts/common/65percent/position_map.dtsi new file mode 100644 index 00000000..b761b858 --- /dev/null +++ b/app/dts/layouts/common/65percent/position_map.dtsi @@ -0,0 +1,7 @@ +/ { + layouts_common_65_percent_position_map: layouts_common_65_percent_position_map { + compatible = "zmk,physical-layout-position-map"; + + complete; + }; +}; diff --git a/app/dts/layouts/common/75percent/75percent.dtsi b/app/dts/layouts/common/75percent/75percent.dtsi deleted file mode 100644 index 1781fbd3..00000000 --- a/app/dts/layouts/common/75percent/75percent.dtsi +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include -#include - -&layout_75_ansi { - status = "disabled"; -}; - -&layout_75_iso { - status = "disabled"; -}; - -&layout_75_all1u { - status = "disabled"; -}; - -/ { - layouts_common_75_percent_position_map: layouts_common_75_percent_position_map { - compatible = "zmk,physical-layout-position-map"; - - complete; - - layout_75_all1u { - physical-layout = <&layout_75_all1u>; - positions - = < 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15> - , <16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31> - , <32 33 34 35 36 37 38 39 40 41 42 43 44 45 46> - , <47 48 49 50 51 52 53 54 55 56 57 58 59 60> - , <61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76> - , <77 78 79 80 81 82 83 84 85 86> - ; - }; - - layout_75_ansi { - physical-layout = <&layout_75_ansi>; - positions - = < 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15> - , <16 17 18 19 20 21 22 23 24 25 26 27 28 29 84 30> - , <31 32 33 34 35 36 37 38 39 40 41 42 43 44 45> - , <46 47 48 49 50 51 52 53 54 55 56 57 58 59> - , <60 85 61 62 63 64 65 66 67 68 69 70 71 86 72 73> - , <74 75 76 77 78 79 80 81 82 83> - ; - }; - - layout_75_iso { - physical-layout = <&layout_75_iso>; - positions - = < 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15> - , <16 17 18 19 20 21 22 23 24 25 26 27 28 29 85 30> - , <31 32 33 34 35 36 37 38 39 40 41 42 43 86 44> - , <45 46 47 48 49 50 51 52 53 54 55 56 58 59> - , <60 61 62 63 64 65 66 67 68 69 70 71 72 57 73 74> - , <75 76 77 78 79 80 81 82 83 84> - ; - }; - }; -}; \ No newline at end of file diff --git a/app/dts/layouts/common/75percent/all1u.dtsi b/app/dts/layouts/common/75percent/all1u.dtsi index 04c12bdb..fbba5df6 100644 --- a/app/dts/layouts/common/75percent/all1u.dtsi +++ b/app/dts/layouts/common/75percent/all1u.dtsi @@ -1,3 +1,4 @@ +#include #include / { @@ -95,4 +96,18 @@ , <&key_physical_attrs 100 100 1500 500 0 0 0> ; }; -}; \ No newline at end of file +}; + +&layouts_common_75_percent_position_map { + layout_75_all1u { + physical-layout = <&layout_75_all1u>; + positions + = < 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15> + , <16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31> + , <32 33 34 35 36 37 38 39 40 41 42 43 44 45 46> + , <47 48 49 50 51 52 53 54 55 56 57 58 59 60> + , <61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76> + , <77 78 79 80 81 82 83 84 85 86> + ; + }; +}; diff --git a/app/dts/layouts/common/75percent/ansi.dtsi b/app/dts/layouts/common/75percent/ansi.dtsi index 6c9a65c7..8d949233 100644 --- a/app/dts/layouts/common/75percent/ansi.dtsi +++ b/app/dts/layouts/common/75percent/ansi.dtsi @@ -1,3 +1,4 @@ +#include #include / { @@ -92,4 +93,18 @@ , <&key_physical_attrs 100 100 1500 500 0 0 0> ; }; -}; \ No newline at end of file +}; + +&layouts_common_75_percent_position_map { + layout_75_ansi { + physical-layout = <&layout_75_ansi>; + positions + = < 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15> + , <16 17 18 19 20 21 22 23 24 25 26 27 28 29 84 30> + , <31 32 33 34 35 36 37 38 39 40 41 42 43 44 45> + , <46 47 48 49 50 51 52 53 54 55 56 57 58 59> + , <60 85 61 62 63 64 65 66 67 68 69 70 71 86 72 73> + , <74 75 76 77 78 79 80 81 82 83> + ; + }; +}; diff --git a/app/dts/layouts/common/75percent/iso.dtsi b/app/dts/layouts/common/75percent/iso.dtsi index f3ee0c51..edbb4b40 100644 --- a/app/dts/layouts/common/75percent/iso.dtsi +++ b/app/dts/layouts/common/75percent/iso.dtsi @@ -1,3 +1,4 @@ +#include #include / { @@ -93,4 +94,18 @@ , <&key_physical_attrs 100 100 1500 500 0 0 0> ; }; -}; \ No newline at end of file +}; + +&layouts_common_75_percent_position_map { + layout_75_iso { + physical-layout = <&layout_75_iso>; + positions + = < 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15> + , <16 17 18 19 20 21 22 23 24 25 26 27 28 29 85 30> + , <31 32 33 34 35 36 37 38 39 40 41 42 43 86 44> + , <45 46 47 48 49 50 51 52 53 54 55 56 58 59> + , <60 61 62 63 64 65 66 67 68 69 70 71 72 57 73 74> + , <75 76 77 78 79 80 81 82 83 84> + ; + }; +}; diff --git a/app/dts/layouts/common/75percent/position_map.dtsi b/app/dts/layouts/common/75percent/position_map.dtsi new file mode 100644 index 00000000..d5f9cdbb --- /dev/null +++ b/app/dts/layouts/common/75percent/position_map.dtsi @@ -0,0 +1,7 @@ +/ { + layouts_common_75_percent_position_map: layouts_common_75_percent_position_map { + compatible = "zmk,physical-layout-position-map"; + + complete; + }; +}; diff --git a/app/dts/layouts/common/ortho_4x12/1x2u.dtsi b/app/dts/layouts/common/ortho_4x12/1x2u.dtsi index 23646afc..c3f0c30f 100644 --- a/app/dts/layouts/common/ortho_4x12/1x2u.dtsi +++ b/app/dts/layouts/common/ortho_4x12/1x2u.dtsi @@ -1,3 +1,4 @@ +#include #include / { @@ -55,4 +56,16 @@ , <&key_physical_attrs 100 100 1100 300 0 0 0> ; }; -}; \ No newline at end of file +}; + +&layouts_common_ortho_4x12_position_map { + layout_ortho_4x12_1x2u { + physical-layout = <&layout_ortho_4x12_1x2u>; + positions + = < 0 1 2 3 4 5 6 7 8 9 10 11> + , <12 13 14 15 16 17 18 19 20 21 22 23> + , <24 25 26 27 28 29 30 31 32 33 34 35> + , <36 37 38 39 40 41 47 42 43 44 45 46> + ; + }; +}; diff --git a/app/dts/layouts/common/ortho_4x12/2x2u.dtsi b/app/dts/layouts/common/ortho_4x12/2x2u.dtsi index d0917869..5ee5d423 100644 --- a/app/dts/layouts/common/ortho_4x12/2x2u.dtsi +++ b/app/dts/layouts/common/ortho_4x12/2x2u.dtsi @@ -1,3 +1,4 @@ +#include #include / { @@ -54,4 +55,16 @@ , <&key_physical_attrs 100 100 1100 300 0 0 0> ; }; -}; \ No newline at end of file +}; + +&layouts_common_ortho_4x12_position_map { + layout_ortho_4x12_2x2u { + physical-layout = <&layout_ortho_4x12_2x2u>; + positions + = < 0 1 2 3 4 5 6 7 8 9 10 11> + , <12 13 14 15 16 17 18 19 20 21 22 23> + , <24 25 26 27 28 29 30 31 32 33 34 35> + , <36 37 38 39 40 46 47 41 42 43 44 45> + ; + }; +}; diff --git a/app/dts/layouts/common/ortho_4x12/all1u.dtsi b/app/dts/layouts/common/ortho_4x12/all1u.dtsi index 323821d4..2829d5e3 100644 --- a/app/dts/layouts/common/ortho_4x12/all1u.dtsi +++ b/app/dts/layouts/common/ortho_4x12/all1u.dtsi @@ -1,3 +1,4 @@ +#include #include / { @@ -56,4 +57,16 @@ , <&key_physical_attrs 100 100 1100 300 0 0 0> ; }; -}; \ No newline at end of file +}; + +&layouts_common_ortho_4x12_position_map { + layout_ortho_4x12_all1u { + physical-layout = <&layout_ortho_4x12_all1u>; + positions + = < 0 1 2 3 4 5 6 7 8 9 10 11> + , <12 13 14 15 16 17 18 19 20 21 22 23> + , <24 25 26 27 28 29 30 31 32 33 34 35> + , <36 37 38 39 40 41 42 43 44 45 46 47> + ; + }; +}; diff --git a/app/dts/layouts/common/ortho_4x12/ortho_4x12.dtsi b/app/dts/layouts/common/ortho_4x12/ortho_4x12.dtsi deleted file mode 100644 index 0c361b10..00000000 --- a/app/dts/layouts/common/ortho_4x12/ortho_4x12.dtsi +++ /dev/null @@ -1,53 +0,0 @@ -#include -#include -#include - -&layout_ortho_4x12_all1u { - status = "disabled"; -}; - -&layout_ortho_4x12_1x2u { - status = "disabled"; -}; - -&layout_ortho_4x12_2x2u { - status = "disabled"; -}; - -/ { - layouts_common_ortho_4x12_position_map: layouts_common_ortho_4x12_position_map { - compatible = "zmk,physical-layout-position-map"; - - complete; - - layout_ortho_4x12_all1u { - physical-layout = <&layout_ortho_4x12_all1u>; - positions - = < 0 1 2 3 4 5 6 7 8 9 10 11> - , <12 13 14 15 16 17 18 19 20 21 22 23> - , <24 25 26 27 28 29 30 31 32 33 34 35> - , <36 37 38 39 40 41 42 43 44 45 46 47> - ; - }; - - layout_ortho_4x12_2x2u { - physical-layout = <&layout_ortho_4x12_2x2u>; - positions - = < 0 1 2 3 4 5 6 7 8 9 10 11> - , <12 13 14 15 16 17 18 19 20 21 22 23> - , <24 25 26 27 28 29 30 31 32 33 34 35> - , <36 37 38 39 40 46 47 41 42 43 44 45> - ; - }; - - layout_ortho_4x12_1x2u { - physical-layout = <&layout_ortho_4x12_1x2u>; - positions - = < 0 1 2 3 4 5 6 7 8 9 10 11> - , <12 13 14 15 16 17 18 19 20 21 22 23> - , <24 25 26 27 28 29 30 31 32 33 34 35> - , <36 37 38 39 40 41 47 42 43 44 45 46> - ; - }; - }; -}; \ No newline at end of file diff --git a/app/dts/layouts/common/ortho_4x12/position_map.dtsi b/app/dts/layouts/common/ortho_4x12/position_map.dtsi new file mode 100644 index 00000000..c93a32bd --- /dev/null +++ b/app/dts/layouts/common/ortho_4x12/position_map.dtsi @@ -0,0 +1,7 @@ +/ { + layouts_common_ortho_4x12_position_map: layouts_common_ortho_4x12_position_map { + compatible = "zmk,physical-layout-position-map"; + + complete; + }; +}; diff --git a/app/dts/layouts/common/ortho_5x12/1x2u.dtsi b/app/dts/layouts/common/ortho_5x12/1x2u.dtsi index 2072cc35..5d12ea45 100644 --- a/app/dts/layouts/common/ortho_5x12/1x2u.dtsi +++ b/app/dts/layouts/common/ortho_5x12/1x2u.dtsi @@ -1,3 +1,4 @@ +#include #include / { @@ -67,4 +68,17 @@ , <&key_physical_attrs 100 100 1100 400 0 0 0> ; }; -}; \ No newline at end of file +}; + +&layouts_common_ortho_5x12_position_map { + layout_ortho_5x12_1x2u { + physical-layout = <&layout_ortho_5x12_1x2u>; + positions + = < 0 1 2 3 4 5 6 7 8 9 10 11> + , <12 13 14 15 16 17 18 19 20 21 22 23> + , <24 25 26 27 28 29 30 31 32 33 34 35> + , <36 37 38 39 40 41 42 43 44 45 46 47> + , <48 49 50 51 52 53 59 54 55 56 57 58> + ; + }; +}; diff --git a/app/dts/layouts/common/ortho_5x12/2x2u.dtsi b/app/dts/layouts/common/ortho_5x12/2x2u.dtsi index 5e55f734..26079eb8 100644 --- a/app/dts/layouts/common/ortho_5x12/2x2u.dtsi +++ b/app/dts/layouts/common/ortho_5x12/2x2u.dtsi @@ -1,3 +1,4 @@ +#include #include / { @@ -66,4 +67,17 @@ , <&key_physical_attrs 100 100 1100 400 0 0 0> ; }; -}; \ No newline at end of file +}; + +&layouts_common_ortho_5x12_position_map { + layout_ortho_5x12_2x2u { + physical-layout = <&layout_ortho_5x12_2x2u>; + positions + = < 0 1 2 3 4 5 6 7 8 9 10 11> + , <12 13 14 15 16 17 18 19 20 21 22 23> + , <24 25 26 27 28 29 30 31 32 33 34 35> + , <36 37 38 39 40 41 42 43 44 45 46 47> + , <48 49 50 51 52 58 59 53 54 55 56 57> + ; + }; +}; diff --git a/app/dts/layouts/common/ortho_5x12/all1u.dtsi b/app/dts/layouts/common/ortho_5x12/all1u.dtsi index 53afb469..3b8f7501 100644 --- a/app/dts/layouts/common/ortho_5x12/all1u.dtsi +++ b/app/dts/layouts/common/ortho_5x12/all1u.dtsi @@ -1,3 +1,4 @@ +#include #include / { @@ -69,3 +70,16 @@ ; }; }; + +&layouts_common_ortho_5x12_position_map { + layout_ortho_5x12_all1u { + physical-layout = <&layout_ortho_5x12_all1u>; + positions + = < 0 1 2 3 4 5 6 7 8 9 10 11> + , <12 13 14 15 16 17 18 19 20 21 22 23> + , <24 25 26 27 28 29 30 31 32 33 34 35> + , <36 37 38 39 40 41 42 43 44 45 46 47> + , <48 49 50 51 52 53 54 55 56 57 58 59> + ; + }; +}; diff --git a/app/dts/layouts/common/ortho_5x12/ortho_5x12.dtsi b/app/dts/layouts/common/ortho_5x12/ortho_5x12.dtsi deleted file mode 100644 index d1a6df7e..00000000 --- a/app/dts/layouts/common/ortho_5x12/ortho_5x12.dtsi +++ /dev/null @@ -1,56 +0,0 @@ -#include -#include -#include - -&layout_ortho_5x12_all1u { - status = "disabled"; -}; - -&layout_ortho_5x12_1x2u { - status = "disabled"; -}; - -&layout_ortho_5x12_2x2u { - status = "disabled"; -}; - -/ { - layouts_common_ortho_5x12_position_map: layouts_common_ortho_5x12_position_map { - compatible = "zmk,physical-layout-position-map"; - - complete; - - layout_ortho_5x12_all1u { - physical-layout = <&layout_ortho_5x12_all1u>; - positions - = < 0 1 2 3 4 5 6 7 8 9 10 11> - , <12 13 14 15 16 17 18 19 20 21 22 23> - , <24 25 26 27 28 29 30 31 32 33 34 35> - , <36 37 38 39 40 41 42 43 44 45 46 47> - , <48 49 50 51 52 53 54 55 56 57 58 59> - ; - }; - - layout_ortho_5x12_2x2u { - physical-layout = <&layout_ortho_5x12_2x2u>; - positions - = < 0 1 2 3 4 5 6 7 8 9 10 11> - , <12 13 14 15 16 17 18 19 20 21 22 23> - , <24 25 26 27 28 29 30 31 32 33 34 35> - , <36 37 38 39 40 41 42 43 44 45 46 47> - , <48 49 50 51 52 58 59 53 54 55 56 57> - ; - }; - - layout_ortho_5x12_1x2u { - physical-layout = <&layout_ortho_5x12_1x2u>; - positions - = < 0 1 2 3 4 5 6 7 8 9 10 11> - , <12 13 14 15 16 17 18 19 20 21 22 23> - , <24 25 26 27 28 29 30 31 32 33 34 35> - , <36 37 38 39 40 41 42 43 44 45 46 47> - , <48 49 50 51 52 53 59 54 55 56 57 58> - ; - }; - }; -}; \ No newline at end of file diff --git a/app/dts/layouts/common/ortho_5x12/position_map.dtsi b/app/dts/layouts/common/ortho_5x12/position_map.dtsi new file mode 100644 index 00000000..e292b4e7 --- /dev/null +++ b/app/dts/layouts/common/ortho_5x12/position_map.dtsi @@ -0,0 +1,7 @@ +/ { + layouts_common_ortho_5x12_position_map: layouts_common_ortho_5x12_position_map { + compatible = "zmk,physical-layout-position-map"; + + complete; + }; +}; diff --git a/app/dts/layouts/common/tkl/ansi.dtsi b/app/dts/layouts/common/tkl/ansi.dtsi index 639ac471..83354c4f 100644 --- a/app/dts/layouts/common/tkl/ansi.dtsi +++ b/app/dts/layouts/common/tkl/ansi.dtsi @@ -1,3 +1,4 @@ +#include #include / { diff --git a/app/dts/layouts/common/tkl/position_map.dtsi b/app/dts/layouts/common/tkl/position_map.dtsi new file mode 100644 index 00000000..8ac528e3 --- /dev/null +++ b/app/dts/layouts/common/tkl/position_map.dtsi @@ -0,0 +1,7 @@ +/ { + layouts_common_tkl_position_map: layouts_common_tkl_position_map { + compatible = "zmk,physical-layout-position-map"; + + complete; + }; +}; From 60a8f2934043b98a8fabcd1dd7dce1a4de30c2a9 Mon Sep 17 00:00:00 2001 From: Joel Spadin Date: Tue, 1 Oct 2024 19:07:45 -0500 Subject: [PATCH 055/415] feat(boards)!: refactor Corne layouts Split up the Corne layout files to match the previous commit. --- app/boards/shields/corne/corne.dtsi | 3 +- .../splitkb_aurora_corne.dtsi | 3 +- app/dts/layouts/foostan/corne.dtsi | 121 ------------------ app/dts/layouts/foostan/corne/5column.dtsi | 59 +++++++++ app/dts/layouts/foostan/corne/6column.dtsi | 65 ++++++++++ .../layouts/foostan/corne/position_map.dtsi | 7 + 6 files changed, 135 insertions(+), 123 deletions(-) delete mode 100644 app/dts/layouts/foostan/corne.dtsi create mode 100644 app/dts/layouts/foostan/corne/5column.dtsi create mode 100644 app/dts/layouts/foostan/corne/6column.dtsi create mode 100644 app/dts/layouts/foostan/corne/position_map.dtsi diff --git a/app/boards/shields/corne/corne.dtsi b/app/boards/shields/corne/corne.dtsi index e4339e61..e1dcc058 100644 --- a/app/boards/shields/corne/corne.dtsi +++ b/app/boards/shields/corne/corne.dtsi @@ -6,7 +6,8 @@ #include -#include +#include +#include &foostan_corne_6col_layout { transform = <&default_transform>; diff --git a/app/boards/shields/splitkb_aurora_corne/splitkb_aurora_corne.dtsi b/app/boards/shields/splitkb_aurora_corne/splitkb_aurora_corne.dtsi index 0b0ffdf3..f57cd235 100644 --- a/app/boards/shields/splitkb_aurora_corne/splitkb_aurora_corne.dtsi +++ b/app/boards/shields/splitkb_aurora_corne/splitkb_aurora_corne.dtsi @@ -6,7 +6,8 @@ #include -#include +#include +#include &foostan_corne_6col_layout { transform = <&default_transform>; diff --git a/app/dts/layouts/foostan/corne.dtsi b/app/dts/layouts/foostan/corne.dtsi deleted file mode 100644 index 5a644103..00000000 --- a/app/dts/layouts/foostan/corne.dtsi +++ /dev/null @@ -1,121 +0,0 @@ -#include - -/ { - foostan_corne_6col_layout: foostan_corne_6col_layout { - compatible = "zmk,physical-layout"; - display-name = "6 Column"; - - keys // w h x y rot rx ry - = <&key_physical_attrs 100 100 0 37 0 0 0> - , <&key_physical_attrs 100 100 100 37 0 0 0> - , <&key_physical_attrs 100 100 200 12 0 0 0> - , <&key_physical_attrs 100 100 300 0 0 0 0> - , <&key_physical_attrs 100 100 400 12 0 0 0> - , <&key_physical_attrs 100 100 500 24 0 0 0> - , <&key_physical_attrs 100 100 800 24 0 0 0> - , <&key_physical_attrs 100 100 900 12 0 0 0> - , <&key_physical_attrs 100 100 1000 0 0 0 0> - , <&key_physical_attrs 100 100 1100 12 0 0 0> - , <&key_physical_attrs 100 100 1200 37 0 0 0> - , <&key_physical_attrs 100 100 1300 37 0 0 0> - , <&key_physical_attrs 100 100 0 137 0 0 0> - , <&key_physical_attrs 100 100 100 137 0 0 0> - , <&key_physical_attrs 100 100 200 112 0 0 0> - , <&key_physical_attrs 100 100 300 100 0 0 0> - , <&key_physical_attrs 100 100 400 112 0 0 0> - , <&key_physical_attrs 100 100 500 124 0 0 0> - , <&key_physical_attrs 100 100 800 124 0 0 0> - , <&key_physical_attrs 100 100 900 112 0 0 0> - , <&key_physical_attrs 100 100 1000 100 0 0 0> - , <&key_physical_attrs 100 100 1100 112 0 0 0> - , <&key_physical_attrs 100 100 1200 137 0 0 0> - , <&key_physical_attrs 100 100 1300 137 0 0 0> - , <&key_physical_attrs 100 100 0 237 0 0 0> - , <&key_physical_attrs 100 100 100 237 0 0 0> - , <&key_physical_attrs 100 100 200 212 0 0 0> - , <&key_physical_attrs 100 100 300 200 0 0 0> - , <&key_physical_attrs 100 100 400 212 0 0 0> - , <&key_physical_attrs 100 100 500 224 0 0 0> - , <&key_physical_attrs 100 100 800 224 0 0 0> - , <&key_physical_attrs 100 100 900 212 0 0 0> - , <&key_physical_attrs 100 100 1000 200 0 0 0> - , <&key_physical_attrs 100 100 1100 212 0 0 0> - , <&key_physical_attrs 100 100 1200 237 0 0 0> - , <&key_physical_attrs 100 100 1300 237 0 0 0> - , <&key_physical_attrs 100 100 350 312 0 0 0> - , <&key_physical_attrs 100 100 450 312 1200 450 412> - , <&key_physical_attrs 100 150 548 283 2400 548 433> - , <&key_physical_attrs 100 150 752 283 (-2400) 852 433> - , <&key_physical_attrs 100 100 850 312 (-1200) 950 412> - , <&key_physical_attrs 100 100 950 312 0 0 0> - ; - }; - - foostan_corne_5col_layout: foostan_corne_5col_layout { - compatible = "zmk,physical-layout"; - display-name = "5 Column"; - - keys // w h x y rot rx ry - = <&key_physical_attrs 100 100 0 37 0 0 0> - , <&key_physical_attrs 100 100 100 12 0 0 0> - , <&key_physical_attrs 100 100 200 0 0 0 0> - , <&key_physical_attrs 100 100 300 12 0 0 0> - , <&key_physical_attrs 100 100 400 24 0 0 0> - , <&key_physical_attrs 100 100 700 24 0 0 0> - , <&key_physical_attrs 100 100 800 12 0 0 0> - , <&key_physical_attrs 100 100 900 0 0 0 0> - , <&key_physical_attrs 100 100 1000 12 0 0 0> - , <&key_physical_attrs 100 100 1100 37 0 0 0> - , <&key_physical_attrs 100 100 0 137 0 0 0> - , <&key_physical_attrs 100 100 100 112 0 0 0> - , <&key_physical_attrs 100 100 200 100 0 0 0> - , <&key_physical_attrs 100 100 300 112 0 0 0> - , <&key_physical_attrs 100 100 400 124 0 0 0> - , <&key_physical_attrs 100 100 700 124 0 0 0> - , <&key_physical_attrs 100 100 800 112 0 0 0> - , <&key_physical_attrs 100 100 900 100 0 0 0> - , <&key_physical_attrs 100 100 1000 112 0 0 0> - , <&key_physical_attrs 100 100 1100 137 0 0 0> - , <&key_physical_attrs 100 100 0 237 0 0 0> - , <&key_physical_attrs 100 100 100 212 0 0 0> - , <&key_physical_attrs 100 100 200 200 0 0 0> - , <&key_physical_attrs 100 100 300 212 0 0 0> - , <&key_physical_attrs 100 100 400 224 0 0 0> - , <&key_physical_attrs 100 100 700 224 0 0 0> - , <&key_physical_attrs 100 100 800 212 0 0 0> - , <&key_physical_attrs 100 100 900 200 0 0 0> - , <&key_physical_attrs 100 100 1000 212 0 0 0> - , <&key_physical_attrs 100 100 1100 237 0 0 0> - , <&key_physical_attrs 100 100 250 312 0 0 0> - , <&key_physical_attrs 100 100 350 312 1200 350 412> - , <&key_physical_attrs 100 150 448 283 2400 448 433> - , <&key_physical_attrs 100 150 652 283 (-2400) 752 433> - , <&key_physical_attrs 100 100 750 312 (-1200) 850 412> - , <&key_physical_attrs 100 100 850 312 0 0 0> - ; - }; - - foostan_corne_position_map { - compatible = "zmk,physical-layout-position-map"; - - complete; - - twelve { - physical-layout = <&foostan_corne_6col_layout>; - positions - = < 0 1 2 3 4 5 6 7 8 9 10 11> - , <12 13 14 15 16 17 18 19 20 21 22 23> - , <24 25 26 27 28 29 30 31 32 33 34 35> - , < 36 37 38 39 40 41 >; - }; - - ten { - physical-layout = <&foostan_corne_5col_layout>; - positions - = <36 0 1 2 3 4 5 6 7 8 9 37> - , <38 10 11 12 13 14 15 16 17 18 19 39> - , <40 20 21 22 23 24 25 26 27 28 29 41> - , < 30 31 32 33 34 35 >; - }; - }; -}; diff --git a/app/dts/layouts/foostan/corne/5column.dtsi b/app/dts/layouts/foostan/corne/5column.dtsi new file mode 100644 index 00000000..2d96d0b2 --- /dev/null +++ b/app/dts/layouts/foostan/corne/5column.dtsi @@ -0,0 +1,59 @@ +#include +#include + +/ { + foostan_corne_5col_layout: foostan_corne_5col_layout { + compatible = "zmk,physical-layout"; + display-name = "5 Column"; + + keys // w h x y rot rx ry + = <&key_physical_attrs 100 100 0 37 0 0 0> + , <&key_physical_attrs 100 100 100 12 0 0 0> + , <&key_physical_attrs 100 100 200 0 0 0 0> + , <&key_physical_attrs 100 100 300 12 0 0 0> + , <&key_physical_attrs 100 100 400 24 0 0 0> + , <&key_physical_attrs 100 100 700 24 0 0 0> + , <&key_physical_attrs 100 100 800 12 0 0 0> + , <&key_physical_attrs 100 100 900 0 0 0 0> + , <&key_physical_attrs 100 100 1000 12 0 0 0> + , <&key_physical_attrs 100 100 1100 37 0 0 0> + , <&key_physical_attrs 100 100 0 137 0 0 0> + , <&key_physical_attrs 100 100 100 112 0 0 0> + , <&key_physical_attrs 100 100 200 100 0 0 0> + , <&key_physical_attrs 100 100 300 112 0 0 0> + , <&key_physical_attrs 100 100 400 124 0 0 0> + , <&key_physical_attrs 100 100 700 124 0 0 0> + , <&key_physical_attrs 100 100 800 112 0 0 0> + , <&key_physical_attrs 100 100 900 100 0 0 0> + , <&key_physical_attrs 100 100 1000 112 0 0 0> + , <&key_physical_attrs 100 100 1100 137 0 0 0> + , <&key_physical_attrs 100 100 0 237 0 0 0> + , <&key_physical_attrs 100 100 100 212 0 0 0> + , <&key_physical_attrs 100 100 200 200 0 0 0> + , <&key_physical_attrs 100 100 300 212 0 0 0> + , <&key_physical_attrs 100 100 400 224 0 0 0> + , <&key_physical_attrs 100 100 700 224 0 0 0> + , <&key_physical_attrs 100 100 800 212 0 0 0> + , <&key_physical_attrs 100 100 900 200 0 0 0> + , <&key_physical_attrs 100 100 1000 212 0 0 0> + , <&key_physical_attrs 100 100 1100 237 0 0 0> + , <&key_physical_attrs 100 100 250 312 0 0 0> + , <&key_physical_attrs 100 100 350 312 1200 350 412> + , <&key_physical_attrs 100 150 448 283 2400 448 433> + , <&key_physical_attrs 100 150 652 283 (-2400) 752 433> + , <&key_physical_attrs 100 100 750 312 (-1200) 850 412> + , <&key_physical_attrs 100 100 850 312 0 0 0> + ; + }; +}; + +&layouts_foostan_corne_position_map { + five_column { + physical-layout = <&foostan_corne_5col_layout>; + positions + = <36 0 1 2 3 4 5 6 7 8 9 37> + , <38 10 11 12 13 14 15 16 17 18 19 39> + , <40 20 21 22 23 24 25 26 27 28 29 41> + , < 30 31 32 33 34 35 >; + }; +}; diff --git a/app/dts/layouts/foostan/corne/6column.dtsi b/app/dts/layouts/foostan/corne/6column.dtsi new file mode 100644 index 00000000..bc1a196d --- /dev/null +++ b/app/dts/layouts/foostan/corne/6column.dtsi @@ -0,0 +1,65 @@ +#include +#include + +/ { + foostan_corne_6col_layout: foostan_corne_6col_layout { + compatible = "zmk,physical-layout"; + display-name = "6 Column"; + + keys // w h x y rot rx ry + = <&key_physical_attrs 100 100 0 37 0 0 0> + , <&key_physical_attrs 100 100 100 37 0 0 0> + , <&key_physical_attrs 100 100 200 12 0 0 0> + , <&key_physical_attrs 100 100 300 0 0 0 0> + , <&key_physical_attrs 100 100 400 12 0 0 0> + , <&key_physical_attrs 100 100 500 24 0 0 0> + , <&key_physical_attrs 100 100 800 24 0 0 0> + , <&key_physical_attrs 100 100 900 12 0 0 0> + , <&key_physical_attrs 100 100 1000 0 0 0 0> + , <&key_physical_attrs 100 100 1100 12 0 0 0> + , <&key_physical_attrs 100 100 1200 37 0 0 0> + , <&key_physical_attrs 100 100 1300 37 0 0 0> + , <&key_physical_attrs 100 100 0 137 0 0 0> + , <&key_physical_attrs 100 100 100 137 0 0 0> + , <&key_physical_attrs 100 100 200 112 0 0 0> + , <&key_physical_attrs 100 100 300 100 0 0 0> + , <&key_physical_attrs 100 100 400 112 0 0 0> + , <&key_physical_attrs 100 100 500 124 0 0 0> + , <&key_physical_attrs 100 100 800 124 0 0 0> + , <&key_physical_attrs 100 100 900 112 0 0 0> + , <&key_physical_attrs 100 100 1000 100 0 0 0> + , <&key_physical_attrs 100 100 1100 112 0 0 0> + , <&key_physical_attrs 100 100 1200 137 0 0 0> + , <&key_physical_attrs 100 100 1300 137 0 0 0> + , <&key_physical_attrs 100 100 0 237 0 0 0> + , <&key_physical_attrs 100 100 100 237 0 0 0> + , <&key_physical_attrs 100 100 200 212 0 0 0> + , <&key_physical_attrs 100 100 300 200 0 0 0> + , <&key_physical_attrs 100 100 400 212 0 0 0> + , <&key_physical_attrs 100 100 500 224 0 0 0> + , <&key_physical_attrs 100 100 800 224 0 0 0> + , <&key_physical_attrs 100 100 900 212 0 0 0> + , <&key_physical_attrs 100 100 1000 200 0 0 0> + , <&key_physical_attrs 100 100 1100 212 0 0 0> + , <&key_physical_attrs 100 100 1200 237 0 0 0> + , <&key_physical_attrs 100 100 1300 237 0 0 0> + , <&key_physical_attrs 100 100 350 312 0 0 0> + , <&key_physical_attrs 100 100 450 312 1200 450 412> + , <&key_physical_attrs 100 150 548 283 2400 548 433> + , <&key_physical_attrs 100 150 752 283 (-2400) 852 433> + , <&key_physical_attrs 100 100 850 312 (-1200) 950 412> + , <&key_physical_attrs 100 100 950 312 0 0 0> + ; + }; +}; + +&layouts_foostan_corne_position_map { + twelve { + physical-layout = <&foostan_corne_6col_layout>; + positions + = < 0 1 2 3 4 5 6 7 8 9 10 11> + , <12 13 14 15 16 17 18 19 20 21 22 23> + , <24 25 26 27 28 29 30 31 32 33 34 35> + , < 36 37 38 39 40 41 >; + }; +}; diff --git a/app/dts/layouts/foostan/corne/position_map.dtsi b/app/dts/layouts/foostan/corne/position_map.dtsi new file mode 100644 index 00000000..7cf87d72 --- /dev/null +++ b/app/dts/layouts/foostan/corne/position_map.dtsi @@ -0,0 +1,7 @@ +/ { + layouts_foostan_corne_position_map: layouts_foostan_corne_position_map { + compatible = "zmk,physical-layout-position-map"; + + complete; + }; +}; From c05aed2f19f062d833496b47c76f7b52bf62f346 Mon Sep 17 00:00:00 2001 From: Nicolas Munnich Date: Thu, 3 Oct 2024 15:45:06 +0200 Subject: [PATCH 056/415] fix(boards): Corneish-zen physical layout --- app/boards/arm/corneish_zen/corneish_zen.dtsi | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/boards/arm/corneish_zen/corneish_zen.dtsi b/app/boards/arm/corneish_zen/corneish_zen.dtsi index 119781a2..788b7613 100644 --- a/app/boards/arm/corneish_zen/corneish_zen.dtsi +++ b/app/boards/arm/corneish_zen/corneish_zen.dtsi @@ -10,7 +10,8 @@ #include -#include +#include +#include &foostan_corne_6col_layout { transform = <&default_transform>; From 29b39f2b9f0977098601b201be1942d299b44da5 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Thu, 3 Oct 2024 14:28:05 -0600 Subject: [PATCH 057/415] feat: A few enhancements to our RPC messages. * More fine grained status reporting when saving changes. Needed to we can notify the client if we've got errors saving settings due to running out of space, etc. * Return the max layer name lenght in the keymap payload, for the UI to leverage. --- app/src/keymap.c | 45 ++++++++++++++++++++++--------- app/src/studio/keymap_subsystem.c | 29 +++++++++++++++++--- app/west.yml | 2 +- 3 files changed, 59 insertions(+), 17 deletions(-) diff --git a/app/src/keymap.c b/app/src/keymap.c index ad3c7278..0ea64b34 100644 --- a/app/src/keymap.c +++ b/app/src/keymap.c @@ -432,7 +432,7 @@ int zmk_keymap_check_unsaved_changes(void) { #define LAYER_NAME_SETTINGS_KEY "keymap/l_n/%d" #define LAYER_BINDING_SETTINGS_KEY "keymap/l/%d/%d" -static void save_bindings(void) { +static int save_bindings(void) { for (int l = 0; l < ZMK_KEYMAP_LAYERS_LEN; l++) { uint8_t *pending = zmk_keymap_layer_pending_changes[l]; @@ -461,45 +461,64 @@ static void save_bindings(void) { char setting_name[20]; sprintf(setting_name, LAYER_BINDING_SETTINGS_KEY, l, kp); - settings_save_one(setting_name, &binding_setting, len); + int ret = settings_save_one(setting_name, &binding_setting, len); + if (ret < 0) { + LOG_ERR("Failed to save keymap binding at %d on layer %d (%d)", l, kp, ret); + return ret; + } } } *pending = 0; } + + return 0; } #if IS_ENABLED(CONFIG_ZMK_KEYMAP_LAYER_REORDERING) -static void save_layer_orders(void) { - settings_save_one(LAYER_ORDER_SETTINGS_KEY, keymap_layer_orders, - ARRAY_SIZE(keymap_layer_orders)); +static int save_layer_orders(void) { + int ret = settings_save_one(LAYER_ORDER_SETTINGS_KEY, keymap_layer_orders, + ARRAY_SIZE(keymap_layer_orders)); + if (ret < 0) { + return ret; + } + memcpy(settings_layer_orders, keymap_layer_orders, ARRAY_SIZE(keymap_layer_orders)); + return 0; } #endif // IS_ENABLED(CONFIG_ZMK_KEYMAP_LAYER_REORDERING) -static void save_layer_names(void) { +static int save_layer_names(void) { for (int id = 0; id < ZMK_KEYMAP_LAYERS_LEN; id++) { if (changed_layer_names & BIT(id)) { char setting_name[14]; sprintf(setting_name, LAYER_NAME_SETTINGS_KEY, id); - settings_save_one(setting_name, zmk_keymap_layer_names[id], - strlen(zmk_keymap_layer_names[id])); + int ret = settings_save_one(setting_name, zmk_keymap_layer_names[id], + strlen(zmk_keymap_layer_names[id])); + if (ret < 0) { + return ret; + } } } changed_layer_names = 0; + return 0; } int zmk_keymap_save_changes(void) { - save_bindings(); + int ret = save_bindings(); + if (ret < 0) { + return ret; + } #if IS_ENABLED(CONFIG_ZMK_KEYMAP_LAYER_REORDERING) - save_layer_orders(); + ret = save_layer_orders(); + if (ret < 0) { + return ret; + } #endif // IS_ENABLED(CONFIG_ZMK_KEYMAP_LAYER_REORDERING) - save_layer_names(); - - return 0; + return save_layer_names(); } #if IS_ENABLED(CONFIG_ZMK_KEYMAP_LAYER_REORDERING) diff --git a/app/src/studio/keymap_subsystem.c b/app/src/studio/keymap_subsystem.c index 25297b63..c3a78be0 100644 --- a/app/src/studio/keymap_subsystem.c +++ b/app/src/studio/keymap_subsystem.c @@ -103,6 +103,7 @@ zmk_studio_Response get_keymap(const zmk_studio_Request *req) { resp.layers.funcs.encode = encode_keymap_layers; + resp.max_layer_name_length = CONFIG_ZMK_KEYMAP_LAYER_NAME_MAX_LEN; resp.available_layers = 0; for (zmk_keymap_layer_index_t index = 0; index < ZMK_KEYMAP_LAYERS_LEN; index++) { @@ -174,25 +175,47 @@ zmk_studio_Response check_unsaved_changes(const zmk_studio_Request *req) { return KEYMAP_RESPONSE(check_unsaved_changes, layout_changes > 0 || keymap_changes > 0); } +static void map_errno_to_save_resp(int err, zmk_keymap_SaveChangesResponse *resp) { + resp->which_result = zmk_keymap_SaveChangesResponse_err_tag; + + switch (err) { + case -ENOTSUP: + resp->result.err = zmk_keymap_SaveChangesErrorCode_SAVE_CHANGES_ERR_NOT_SUPPORTED; + break; + case -ENOSPC: + resp->result.err = zmk_keymap_SaveChangesErrorCode_SAVE_CHANGES_ERR_NO_SPACE; + break; + default: + resp->result.err = zmk_keymap_SaveChangesErrorCode_SAVE_CHANGES_ERR_GENERIC; + break; + } +} + zmk_studio_Response save_changes(const zmk_studio_Request *req) { + zmk_keymap_SaveChangesResponse resp = zmk_keymap_SaveChangesResponse_init_zero; + resp.which_result = zmk_keymap_SaveChangesResponse_ok_tag; + resp.result.ok = true; + LOG_DBG(""); int ret = zmk_physical_layouts_save_selected(); if (ret < 0) { LOG_WRN("Failed to save selected physical layout (%d)", ret); - return ZMK_RPC_SIMPLE_ERR(GENERIC); + map_errno_to_save_resp(ret, &resp); + return KEYMAP_RESPONSE(save_changes, resp); } ret = zmk_keymap_save_changes(); if (ret < 0) { LOG_WRN("Failed to save keymap changes (%d)", ret); - return ZMK_RPC_SIMPLE_ERR(GENERIC); + map_errno_to_save_resp(ret, &resp); + return KEYMAP_RESPONSE(save_changes, resp); } raise_zmk_studio_rpc_notification((struct zmk_studio_rpc_notification){ .notification = KEYMAP_NOTIFICATION(unsaved_changes_status_changed, false)}); - return KEYMAP_RESPONSE(save_changes, true); + return KEYMAP_RESPONSE(save_changes, resp); } zmk_studio_Response discard_changes(const zmk_studio_Request *req) { diff --git a/app/west.yml b/app/west.yml index 5737bd00..e6c9758c 100644 --- a/app/west.yml +++ b/app/west.yml @@ -34,7 +34,7 @@ manifest: path: modules/lib/nanopb remote: zephyrproject-rtos - name: zmk-studio-messages - revision: a79267a9661241a6603b6da3d2b3f71e8023a9d9 + revision: 6cb4c283e76209d59c45fbcb218800cd19e9339d path: modules/msgs/zmk-studio-messages remote: zmkfirmware self: From 6cac781adae07e13aab48053d50bfa1fc26856ce Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Thu, 26 Sep 2024 01:09:03 -0600 Subject: [PATCH 058/415] feat: Add basic metadata info to new behavior guide. Co-authored-by: Cem Aksoylar Co-authored-by: Nicolas Munnich <98408764+Nick-Munnich@users.noreply.github.com> --- docs/docs/development/new-behavior.mdx | 107 +++++++++++++++++++++++++ 1 file changed, 107 insertions(+) diff --git a/docs/docs/development/new-behavior.mdx b/docs/docs/development/new-behavior.mdx index 3d50b821..0e67a449 100644 --- a/docs/docs/development/new-behavior.mdx +++ b/docs/docs/development/new-behavior.mdx @@ -293,6 +293,8 @@ Comes in the form `static const struct behavior_driver_api _drive - `.binding_pressed`: Used for behaviors that invoke an action on its keybind press. Set `.binding_pressed` equal to the function typically named [`on__binding_pressed`](#dependencies). - `.binding_released`: Same as above, except for activating on keybind release events. Set `.binding_released` equal to the function typically named [`on__binding_released`](#dependencies). +- `.parameter_metadata`: Defined in ``. Pointer to metadata describing the parameters to use with the behavior so the behavior may be used with [ZMK Studio](../features/studio.md). +- `.get_parameter_metadata`: Defined in ``. Callback function that can dynamically provide/populate the metadata describing the parameters to use with the behavior so the behavior may be used with [ZMK Studio](../features/studio.md). - `.locality`: Defined in ``. Describes how the behavior affects parts of a _split_ keyboard. - `BEHAVIOR_LOCALITY_CENTRAL`: Behavior only affects the central half, which is the case for most keymap-related behavior. - `BEHAVIOR_LOCALITY_EVENT_SOURCE`: Behavior affects only the central _or_ peripheral half depending on which side invoked the behavior binding, such as [reset behaviors](../keymaps/behaviors/reset.md). @@ -301,6 +303,111 @@ Comes in the form `static const struct behavior_driver_api _drive For unibody keyboards, all locality values perform the same as `BEHAVIOR_LOCALITY_GLOBAL`. ::: +##### Behavior metadata + +Behavior metadata documents the possible combinations of parameters that can be used with the behavior when added to your keymap. The metadata structure allows flexibility to specify different kinds of well known parameter types, such as a HID usage, different second parameters passed on the selected first parameter, etc. + +You can see a few examples of how the metadata is implemented in practice for: + +- [Key press](https://github.com/zmkfirmware/zmk/blob/main/app/src/behaviors/behavior_key_press.c#L21) +- [RGB underglow](https://github.com/zmkfirmware/zmk/blob/main/app/src/behaviors/behavior_rgb_underglow.c#L23) +- [Hold-tap](https://github.com/zmkfirmware/zmk/blob/main/app/src/behaviors/behavior_hold_tap.c#L680), which is dynamic based on what behaviors are set up in the hold-tap bindings + +Behavior metadata consists of one or more metadata sets, where each metadata set has a set of values for the parameter(s) used with the behavior. + +For example, a common approach for behaviors is to have a set of possible first parameters that identify the "command" to invoke for the behavior, and the second parameter is a detail/sub-parameter to the action. You can see this with the `&bt` behavior. +In that scenario, all `&bt` "commands" that take a BT profile as a second parameter are grouped into one set, and all commands that take no arguments are grouped into another. + +This allows the ZMK Studio UI to properly show a input for a profile only when the appropriate first "command" selection is made in the UI. Here is a snippet of that setup from the [behavior_bt.c](https://github.com/zmkfirmware/zmk/blob/main/app/src/behaviors/behavior_bt.c#L25) code: + +```c + +#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA) +// Set up the values for commands that take no additional parameter. +static const struct behavior_parameter_value_metadata no_arg_values[] = { + { + .display_name = "Next Profile", + .type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE, + .value = BT_NXT_CMD, + }, + { + .display_name = "Previous Profile", + .type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE, + .value = BT_PRV_CMD, + }, + { + .display_name = "Clear All Profiles", + .type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE, + .value = BT_CLR_ALL_CMD, + }, + { + .display_name = "Clear Selected Profile", + .type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE, + .value = BT_CLR_CMD, + }, +}; + +// Set up the "no arg" metadata set. +static const struct behavior_parameter_metadata_set no_args_set = { + .param1_values = no_arg_values, + .param1_values_len = ARRAY_SIZE(no_arg_values), +}; + +// Set up the possible param1 values for commands that take a profile index for param2 +static const struct behavior_parameter_value_metadata prof_index_param1_values[] = { + { + .display_name = "Select Profile", + .type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE, + .value = BT_SEL_CMD, + }, + { + .display_name = "Disconnect Profile", + .type = BEHAVIOR_PARAMETER_VALUE_TYPE_VALUE, + .value = BT_DISC_CMD, + }, +}; + +// Set up the param2 value metadata for the valid range of possible profiles to pick from. +static const struct behavior_parameter_value_metadata prof_index_param2_values[] = { + { + .display_name = "Profile", + .type = BEHAVIOR_PARAMETER_VALUE_TYPE_RANGE, + .range = {.min = 0, .max = ZMK_BLE_PROFILE_COUNT}, + }, +}; + +// Set up the metadata set for the commands that take a profile for the second parameter. +static const struct behavior_parameter_metadata_set profile_index_metadata_set = { + .param1_values = prof_index_param1_values, + .param1_values_len = ARRAY_SIZE(prof_index_param1_values), + .param2_values = prof_index_param2_values, + .param2_values_len = ARRAY_SIZE(prof_index_param2_values), +}; + +// Finally, expose all the sets in the top level aggregate structure. +static const struct behavior_parameter_metadata_set metadata_sets[] = {no_args_set, + profile_index_metadata_set}; + +static const struct behavior_parameter_metadata metadata = { + .sets_len = ARRAY_SIZE(metadata_sets), + .sets = metadata_sets, +}; + +#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA) + +... Rest of the behavior implementation + +// Add the metadata to the driver API conditionally: + +static const struct behavior_driver_api behavior_bt_driver_api = { + .binding_pressed = on_keymap_binding_pressed, + .binding_released = on_keymap_binding_released, +#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA) + .parameter_metadata = &metadata, +#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_METADATA) +}; +``` + ##### Data pointers (optional) The data `struct` stores additional data required for **each new instance** of the behavior. Regardless of the instance number, `n`, `behavior__data_##n` is typically initialized as an empty `struct`. The data respective to each instance of the behavior can be accessed in functions like [`on__binding_pressed(struct zmk_behavior_binding *binding, struct zmk_behavior_binding_event event)`](#dependencies) by extracting the behavior device from the keybind like so: From 47a17c64d71a1115fb1eb66bf2a7af90463be315 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Mon, 5 Aug 2024 12:12:17 -0600 Subject: [PATCH 059/415] fix: Defer auto enabling of kscan sideband. * Now that device init of kscan sideband is in POST_KERNEL stage, use a separate SYS_INIT for auto enabling the device so processing of early/initial presses from referenced toggle mode kscan devices occurs at the proper time during init. --- app/src/kscan_sideband_behaviors.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/app/src/kscan_sideband_behaviors.c b/app/src/kscan_sideband_behaviors.c index 9f38e0fb..eab7f043 100644 --- a/app/src/kscan_sideband_behaviors.c +++ b/app/src/kscan_sideband_behaviors.c @@ -168,16 +168,11 @@ static int ksbb_init(const struct device *dev) { return -ENODEV; } - if (config->auto_enable) { -#if !IS_ENABLED(CONFIG_PM_DEVICE) - kscan_config(config->kscan, &ksbb_inner_kscan_callback); - kscan_enable_callback(config->kscan); -#else - ksbb_pm_action(dev, PM_DEVICE_ACTION_RESUME); - } else { +#if IS_ENABLED(CONFIG_PM_DEVICE) + if (!config->auto_enable) { pm_device_init_suspended(dev); -#endif } +#endif return 0; } @@ -196,6 +191,16 @@ static const struct kscan_driver_api ksbb_api = { } #define KSBB_INST(n) \ + COND_CODE_1(DT_INST_PROP_OR(n, auto_enable, false), (static int ksbb_auto_enable_##n(void) { \ + const struct device *dev = DEVICE_DT_GET(DT_DRV_INST(n)); \ + COND_CODE_1(IS_ENABLED(CONFIG_PM_DEVICE), \ + (ksbb_pm_action(dev, PM_DEVICE_ACTION_RESUME);), \ + (const struct ksbb_config *config = dev->config; \ + kscan_config(config->kscan, &ksbb_inner_kscan_callback); \ + kscan_enable_callback(config->kscan);)) \ + return 0; \ + } SYS_INIT(ksbb_auto_enable_##n, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);), \ + ()) \ static struct ksbb_entry entries_##n[] = { \ DT_INST_FOREACH_CHILD_STATUS_OKAY_SEP(n, ENTRY, (, ))}; \ const struct ksbb_config ksbb_config_##n = { \ From 4aea919a4d805a0cfafd475e4ee0170c4ea19667 Mon Sep 17 00:00:00 2001 From: Allister MacLeod Date: Tue, 8 Oct 2024 12:27:01 -0400 Subject: [PATCH 060/415] fix(display): Adding length check to layer_label in nice_view status widget. --- app/boards/shields/nice_view/widgets/status.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/boards/shields/nice_view/widgets/status.c b/app/boards/shields/nice_view/widgets/status.c index fa022355..5cbbd91c 100644 --- a/app/boards/shields/nice_view/widgets/status.c +++ b/app/boards/shields/nice_view/widgets/status.c @@ -179,7 +179,7 @@ static void draw_bottom(lv_obj_t *widget, lv_color_t cbuf[], const struct status lv_canvas_draw_rect(canvas, 0, 0, CANVAS_SIZE, CANVAS_SIZE, &rect_black_dsc); // Draw layer - if (state->layer_label == NULL) { + if (state->layer_label == NULL || strlen(state->layer_label) == 0) { char text[10] = {}; sprintf(text, "LAYER %i", state->layer_index); From 6e2d30d589639ca4cebf6831bd8f8fb0423fd7e8 Mon Sep 17 00:00:00 2001 From: Cem Aksoylar Date: Tue, 8 Oct 2024 14:31:35 -0700 Subject: [PATCH 061/415] docs: Add missing hold-trigger-on-release to config --- docs/docs/config/behaviors.md | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/docs/docs/config/behaviors.md b/docs/docs/config/behaviors.md index 6914495f..527d73c6 100644 --- a/docs/docs/config/behaviors.md +++ b/docs/docs/config/behaviors.md @@ -64,18 +64,19 @@ Definition file: [zmk/app/dts/bindings/behaviors/zmk,behavior-hold-tap.yaml](htt Applies to: `compatible = "zmk,behavior-hold-tap"` -| Property | Type | Description | Default | -| ----------------------------- | -------- | -------------------------------------------------------------------------------------------------------------- | ------------------ | -| `#binding-cells` | int | Must be `<2>` | | -| `bindings` | phandles | A list of two behaviors (without parameters): one for hold and one for tap | | -| `flavor` | string | Adjusts how the behavior chooses between hold and tap | `"hold-preferred"` | -| `tapping-term-ms` | int | How long in milliseconds the key must be held to trigger a hold | | -| `quick-tap-ms` | int | Tap twice within this period (in milliseconds) to trigger a tap, even when held | -1 (disabled) | -| `require-prior-idle-ms` | int | Triggers a tap immediately if any non-modifier key was pressed within `require-prior-idle-ms` of the hold-tap. | -1 (disabled) | -| `retro-tap` | bool | Triggers the tap behavior on release if no other key was pressed during a hold | false | -| `hold-while-undecided` | bool | Triggers the hold behavior immediately on press and releases before a tap | false | -| `hold-while-undecided-linger` | bool | Continues to hold the hold behavior until after the tap is released | false | -| `hold-trigger-key-positions` | array | If set, pressing the hold-tap and then any key position _not_ in the list triggers a tap. | | +| Property | Type | Description | Default | +| ----------------------------- | -------- | ------------------------------------------------------------------------------------------------------------- | ------------------ | +| `#binding-cells` | int | Must be `<2>` | | +| `bindings` | phandles | A list of two behaviors (without parameters): one for hold and one for tap | | +| `flavor` | string | Adjusts how the behavior chooses between hold and tap | `"hold-preferred"` | +| `tapping-term-ms` | int | How long in milliseconds the key must be held to trigger a hold | | +| `quick-tap-ms` | int | Tap twice within this period (in milliseconds) to trigger a tap, even when held | -1 (disabled) | +| `require-prior-idle-ms` | int | Triggers a tap immediately if any non-modifier key was pressed within `require-prior-idle-ms` of the hold-tap | -1 (disabled) | +| `retro-tap` | bool | Triggers the tap behavior on release if no other key was pressed during a hold | false | +| `hold-while-undecided` | bool | Triggers the hold behavior immediately on press and releases before a tap | false | +| `hold-while-undecided-linger` | bool | Continues to hold the hold behavior until after the tap is released | false | +| `hold-trigger-key-positions` | array | If set, pressing the hold-tap and then any key position _not_ in the list triggers a tap | | +| `hold-trigger-on-release` | bool | If set, delays the evaluation of `hold-trigger-key-positions` until key release | false | This behavior forwards the first parameter it receives to the parameter of the first behavior specified in `bindings`, and second parameter to the parameter of the second behavior. From 16976db58c33eb3d19acd8d2922cf51603140864 Mon Sep 17 00:00:00 2001 From: Cem Aksoylar Date: Tue, 8 Oct 2024 14:33:57 -0700 Subject: [PATCH 062/415] docs: Fix columns names in kscan config --- docs/docs/config/kscan.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/docs/config/kscan.md b/docs/docs/config/kscan.md index b8a3660b..b4dd9925 100644 --- a/docs/docs/config/kscan.md +++ b/docs/docs/config/kscan.md @@ -216,10 +216,10 @@ Applies to : `compatible = "zmk,kscan-composite"` Definition file: [zmk/app/dts/bindings/zmk,kscan-composite.yaml](https://github.com/zmkfirmware/zmk/blob/main/app/dts/bindings/zmk,kscan-composite.yaml) -| Property | Type | Description | Default | -| -------- | ---- | --------------------------------------------- | ------- | -| `rows` | int | The number of rows in the composite matrix | | -| `cols` | int | The number of columns in the composite matrix | | +| Property | Type | Description | Default | +| --------- | ---- | --------------------------------------------- | ------- | +| `rows` | int | The number of rows in the composite matrix | | +| `columns` | int | The number of columns in the composite matrix | | The `zmk,kscan-composite` node should have one child node per keyboard scan driver that should be composited. Each child node can have the following properties: @@ -331,7 +331,7 @@ Definition file: [zmk/app/dts/bindings/zmk,kscan-mock.yaml](https://github.com/z | `event-period` | int | Milliseconds between each generated event | | | `events` | array | List of key events to simulate | | | `rows` | int | The number of rows in the composite matrix | | -| `cols` | int | The number of columns in the composite matrix | | +| `columns` | int | The number of columns in the composite matrix | | | `exit-after` | bool | Exit the program after running all events | false | The `events` array should be defined using the macros from [app/module/include/dt-bindings/zmk/kscan_mock.h](https://github.com/zmkfirmware/zmk/blob/main/app/module/include/dt-bindings/zmk/kscan_mock.h). From 022ede9d1e7d439edd1d60d3ca455dc3f7c6edd8 Mon Sep 17 00:00:00 2001 From: Cem Aksoylar Date: Tue, 8 Oct 2024 15:05:35 -0700 Subject: [PATCH 063/415] docs: Remove download for settings_reset and note local build --- .../splitpairing/corecoverage.png | Bin 3420 -> 0 bytes .../troubleshooting/connection-issues.mdx | 45 +++--------------- 2 files changed, 6 insertions(+), 39 deletions(-) delete mode 100755 docs/docs/assets/troubleshooting/splitpairing/corecoverage.png diff --git a/docs/docs/assets/troubleshooting/splitpairing/corecoverage.png b/docs/docs/assets/troubleshooting/splitpairing/corecoverage.png deleted file mode 100755 index a2a928be1f8e57c6feabd8b5058aa3b1130b35c6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3420 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 P5dq+ONLZbYeawFWzejJp diff --git a/docs/docs/troubleshooting/connection-issues.mdx b/docs/docs/troubleshooting/connection-issues.mdx index 7de953a9..f8e08541 100644 --- a/docs/docs/troubleshooting/connection-issues.mdx +++ b/docs/docs/troubleshooting/connection-issues.mdx @@ -4,24 +4,6 @@ sidebar_label: Connection Issues description: Troubleshooting wireless connection issues of ZMK devices. --- -import Tabs from "@theme/Tabs"; -import TabItem from "@theme/TabItem"; - -export const Uf2Tabs = (props) => ( - - {/* eslint-disable-next-line */} - {props.children} - - -); - :::tip [USB logging](../development/usb-logging.mdx) can be very helpful for diagnosing issues with ZMK. However, when connected to USB your ZMK device will output to USB by default. To troubleshoot wireless connection issues using logging, you will need to [change the preferred output endpoint](../keymaps/behaviors/outputs.md). ::: @@ -41,14 +23,9 @@ This procedure will erase all settings, such as Bluetooth profiles, output selec ::: -### Acquiring a Reset UF2 +### Building a Reset Firmware -First, acquire the reset UF2 image file with one of the following options: - - - - -Find the `build.yaml` file in your `zmk-config` folder and add an additional settings reset build for the board used by your split keyboard. For example assuming that the config repo is setup for nice!nano v2 with Corne, append the `settings_reset` shield to the `build.yaml` file as follows: +If you are using GitHub Actions to build your firmware as described in the [user setup](../user-setup.mdx), find the `build.yaml` file in your `zmk-config` folder and add an additional settings reset build for the board used by your split keyboard. For example, assuming that the config repo is setup for nice!nano v2 with Corne, append the `settings_reset` shield to the `build.yaml` file as follows: ```yml include: @@ -60,28 +37,18 @@ include: shield: settings_reset ``` -Save the file, commit the changes and push them to GitHub. Download the new firmware zip file build by the latest GitHub Actions job. In it you will find an additional `settings_reset` UF2 image file. +If you are building for an onboard controller keyboard that doesn't use a shield, add a new `shield:` field to its `board:` entry. - +Save the file, commit the changes and push them to GitHub. Download the new firmware zip file that is built by the latest GitHub Actions job. In it you will find an additional `settings_reset` firmware file. - -1. [Open the `Build` workflow](https://github.com/zmkfirmware/zmk/actions/workflows/build.yml?query=event%3Apush+branch%3Amain+is%3Asuccess) from the `Actions` tab of the ZMK GitHub repository. -1. Find one of the results for which the `core-coverage` job ran successfully, indicated by a green checkmark in the "core-coverage" bubble like the image example below. -1. From the next page under "Artifacts", download and unzip the `-settings_reset-zmk` zip file for the UF2 image. - -| ![Successful core-coverage Job](../../docs/assets/troubleshooting/splitpairing/corecoverage.png) | -| :----------------------------------------------------------------------------------------------: | -| An example of a successful core-coverage job which will produce a settings_reset firmware. | - - - +If you use a [local development environment](../development/local-toolchain/setup/index.md) to build firmware instead of GitHub Actions, pass the `-DSHIELD=settings_reset` argument when [building](../development/local-toolchain/build-flash.mdx), omitting all other `-DSHIELD` arguments. ### Reset Split Keyboard Procedure Perform the following steps to reset **_both_** halves of your split keyboard: 1. Put each half of the split keyboard into bootloader mode. -1. Flash one of the halves of the split with the downloaded settings reset UF2 image. +1. Flash one of the halves of the split with the settings reset firmware. 1. Repeat step 2 with the other half of the 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). From 78513af73ee554d7d53e271c36ddad7fab634c6a Mon Sep 17 00:00:00 2001 From: Pete Johanson Date: Thu, 10 Oct 2024 10:36:27 -0600 Subject: [PATCH 064/415] feat(studio): Move to nanopb with minor optimizations. (#2505) * Reduced stack size. --- app/west.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/west.yml b/app/west.yml index e6c9758c..036e012e 100644 --- a/app/west.yml +++ b/app/west.yml @@ -30,9 +30,9 @@ manifest: - edtt - trusted-firmware-m - name: nanopb - revision: 65cbefb4695bc7af1cb733ced99618afb3586b20 + revision: 0a21c7ca2a98c5821d2836e41cc5c520e43fd0c0 path: modules/lib/nanopb - remote: zephyrproject-rtos + remote: zmkfirmware - name: zmk-studio-messages revision: 6cb4c283e76209d59c45fbcb218800cd19e9339d path: modules/msgs/zmk-studio-messages From dab4b2cdf3cf880b4e95e58a983307a90cac9993 Mon Sep 17 00:00:00 2001 From: Pete Johanson Date: Thu, 10 Oct 2024 10:49:51 -0600 Subject: [PATCH 065/415] fix(studio): Reduce stack usage. (#2547) * Imply nanopb setting for reduced stack usage. --- app/src/studio/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/studio/Kconfig b/app/src/studio/Kconfig index d1315070..8d70bde6 100644 --- a/app/src/studio/Kconfig +++ b/app/src/studio/Kconfig @@ -35,6 +35,7 @@ menuconfig ZMK_STUDIO_RPC # These two save stack size imply NANOPB_NO_ERRMSG imply NANOPB_WITHOUT_64BIT + imply NANOPB_NO_ENCODE_SIZE_CHECK imply ZMK_STUDIO_LOCKING if !ARCH_POSIX select CBPRINTF_LIBC_SUBSTS if ARCH_POSIX select SETTINGS From d3f2895744e2cbfc764db9c026dbf2651f181d99 Mon Sep 17 00:00:00 2001 From: Pete Johanson Date: Thu, 10 Oct 2024 11:03:32 -0600 Subject: [PATCH 066/415] refactor: Give position map children labels. (#2544) * To make is easier to reuse layouts and override the position maps for them, add labels to all the position map children in our shared layouts. --- app/dts/layouts/common/60percent/all1u.dtsi | 2 +- app/dts/layouts/common/60percent/ansi.dtsi | 2 +- app/dts/layouts/common/60percent/hhkb.dtsi | 2 +- app/dts/layouts/common/60percent/iso.dtsi | 2 +- app/dts/layouts/common/65percent/all1u.dtsi | 2 +- app/dts/layouts/common/65percent/ansi.dtsi | 2 +- app/dts/layouts/common/65percent/hhkb.dtsi | 2 +- app/dts/layouts/common/65percent/iso.dtsi | 2 +- app/dts/layouts/common/75percent/all1u.dtsi | 2 +- app/dts/layouts/common/75percent/ansi.dtsi | 2 +- app/dts/layouts/common/75percent/iso.dtsi | 2 +- app/dts/layouts/common/ortho_4x12/1x2u.dtsi | 2 +- app/dts/layouts/common/ortho_4x12/2x2u.dtsi | 2 +- app/dts/layouts/common/ortho_4x12/all1u.dtsi | 2 +- app/dts/layouts/common/ortho_5x12/1x2u.dtsi | 2 +- app/dts/layouts/common/ortho_5x12/2x2u.dtsi | 2 +- app/dts/layouts/common/ortho_5x12/all1u.dtsi | 2 +- app/dts/layouts/foostan/corne/5column.dtsi | 2 +- app/dts/layouts/foostan/corne/6column.dtsi | 2 +- 19 files changed, 19 insertions(+), 19 deletions(-) diff --git a/app/dts/layouts/common/60percent/all1u.dtsi b/app/dts/layouts/common/60percent/all1u.dtsi index 45431689..e99f75b5 100644 --- a/app/dts/layouts/common/60percent/all1u.dtsi +++ b/app/dts/layouts/common/60percent/all1u.dtsi @@ -78,7 +78,7 @@ }; &layouts_common_60_percent_position_map { - layout_60_all1u { + layout_60_all1u_posmap: layout_60_all1u { physical-layout = <&layout_60_all1u>; positions = < 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14> diff --git a/app/dts/layouts/common/60percent/ansi.dtsi b/app/dts/layouts/common/60percent/ansi.dtsi index b3b870c5..0d6c6b9e 100644 --- a/app/dts/layouts/common/60percent/ansi.dtsi +++ b/app/dts/layouts/common/60percent/ansi.dtsi @@ -73,7 +73,7 @@ }; &layouts_common_60_percent_position_map { - layout_60_ansi { + layout_60_ansi_posmap: layout_60_ansi { physical-layout = <&layout_60_ansi>; positions = < 0 1 2 3 4 5 6 7 8 9 10 11 12 13 61> diff --git a/app/dts/layouts/common/60percent/hhkb.dtsi b/app/dts/layouts/common/60percent/hhkb.dtsi index a3c271e7..dcefbfc6 100644 --- a/app/dts/layouts/common/60percent/hhkb.dtsi +++ b/app/dts/layouts/common/60percent/hhkb.dtsi @@ -72,7 +72,7 @@ }; &layouts_common_60_percent_position_map { - layout_60_hhkb { + layout_60_hhkb_posmap: layout_60_hhkb { physical-layout = <&layout_60_hhkb>; positions = < 0 1 2 3 4 5 6 7 8 9 10 11 12 13 60> diff --git a/app/dts/layouts/common/60percent/iso.dtsi b/app/dts/layouts/common/60percent/iso.dtsi index e1214b58..1f9ae26d 100644 --- a/app/dts/layouts/common/60percent/iso.dtsi +++ b/app/dts/layouts/common/60percent/iso.dtsi @@ -74,7 +74,7 @@ }; &layouts_common_60_percent_position_map { - layout_60_iso { + layout_60_iso_posmap: layout_60_iso { physical-layout = <&layout_60_iso>; positions = < 0 1 2 3 4 5 6 7 8 9 10 11 12 13 62> diff --git a/app/dts/layouts/common/65percent/all1u.dtsi b/app/dts/layouts/common/65percent/all1u.dtsi index 7ff70358..f5d3121d 100644 --- a/app/dts/layouts/common/65percent/all1u.dtsi +++ b/app/dts/layouts/common/65percent/all1u.dtsi @@ -86,7 +86,7 @@ }; &layouts_common_65_percent_position_map { - layout_65_all1u { + layout_65_all1u_posmap: layout_65_all1u { physical-layout = <&layout_65_all1u>; positions = < 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15> diff --git a/app/dts/layouts/common/65percent/ansi.dtsi b/app/dts/layouts/common/65percent/ansi.dtsi index 991a672c..d6938ce8 100644 --- a/app/dts/layouts/common/65percent/ansi.dtsi +++ b/app/dts/layouts/common/65percent/ansi.dtsi @@ -80,7 +80,7 @@ }; &layouts_common_65_percent_position_map { - layout_65_ansi { + layout_65_ansi_posmap: layout_65_ansi { physical-layout = <&layout_65_ansi>; positions = < 0 1 2 3 4 5 6 7 8 9 10 11 12 13 68 14> diff --git a/app/dts/layouts/common/65percent/hhkb.dtsi b/app/dts/layouts/common/65percent/hhkb.dtsi index d0684f3c..a20fb6dc 100644 --- a/app/dts/layouts/common/65percent/hhkb.dtsi +++ b/app/dts/layouts/common/65percent/hhkb.dtsi @@ -77,7 +77,7 @@ }; &layouts_common_65_percent_position_map { - layout_65_hhkb { + layout_65_hhkb_posmap: layout_65_hhkb { physical-layout = <&layout_65_hhkb>; positions = < 0 1 2 3 4 5 6 7 8 9 10 11 12 13 65 14> diff --git a/app/dts/layouts/common/65percent/iso.dtsi b/app/dts/layouts/common/65percent/iso.dtsi index c94ee1d6..9117b70f 100644 --- a/app/dts/layouts/common/65percent/iso.dtsi +++ b/app/dts/layouts/common/65percent/iso.dtsi @@ -81,7 +81,7 @@ }; &layouts_common_65_percent_position_map { - layout_65_iso { + layout_65_iso_posmap: layout_65_iso { physical-layout = <&layout_65_iso>; positions = < 0 1 2 3 4 5 6 7 8 9 10 11 12 13 69 14> diff --git a/app/dts/layouts/common/75percent/all1u.dtsi b/app/dts/layouts/common/75percent/all1u.dtsi index fbba5df6..702de021 100644 --- a/app/dts/layouts/common/75percent/all1u.dtsi +++ b/app/dts/layouts/common/75percent/all1u.dtsi @@ -99,7 +99,7 @@ }; &layouts_common_75_percent_position_map { - layout_75_all1u { + layout_75_all1u_posmap: layout_75_all1u { physical-layout = <&layout_75_all1u>; positions = < 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15> diff --git a/app/dts/layouts/common/75percent/ansi.dtsi b/app/dts/layouts/common/75percent/ansi.dtsi index 8d949233..0395bd69 100644 --- a/app/dts/layouts/common/75percent/ansi.dtsi +++ b/app/dts/layouts/common/75percent/ansi.dtsi @@ -96,7 +96,7 @@ }; &layouts_common_75_percent_position_map { - layout_75_ansi { + layout_75_ansi_posmap: layout_75_ansi { physical-layout = <&layout_75_ansi>; positions = < 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15> diff --git a/app/dts/layouts/common/75percent/iso.dtsi b/app/dts/layouts/common/75percent/iso.dtsi index edbb4b40..7002b89c 100644 --- a/app/dts/layouts/common/75percent/iso.dtsi +++ b/app/dts/layouts/common/75percent/iso.dtsi @@ -97,7 +97,7 @@ }; &layouts_common_75_percent_position_map { - layout_75_iso { + layout_75_iso_posmap: layout_75_iso { physical-layout = <&layout_75_iso>; positions = < 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15> diff --git a/app/dts/layouts/common/ortho_4x12/1x2u.dtsi b/app/dts/layouts/common/ortho_4x12/1x2u.dtsi index c3f0c30f..451743ff 100644 --- a/app/dts/layouts/common/ortho_4x12/1x2u.dtsi +++ b/app/dts/layouts/common/ortho_4x12/1x2u.dtsi @@ -59,7 +59,7 @@ }; &layouts_common_ortho_4x12_position_map { - layout_ortho_4x12_1x2u { + layout_ortho_4x12_1x2u_posmap: layout_ortho_4x12_1x2u { physical-layout = <&layout_ortho_4x12_1x2u>; positions = < 0 1 2 3 4 5 6 7 8 9 10 11> diff --git a/app/dts/layouts/common/ortho_4x12/2x2u.dtsi b/app/dts/layouts/common/ortho_4x12/2x2u.dtsi index 5ee5d423..69afe35f 100644 --- a/app/dts/layouts/common/ortho_4x12/2x2u.dtsi +++ b/app/dts/layouts/common/ortho_4x12/2x2u.dtsi @@ -58,7 +58,7 @@ }; &layouts_common_ortho_4x12_position_map { - layout_ortho_4x12_2x2u { + layout_ortho_4x12_2x2u_posmap: layout_ortho_4x12_2x2u { physical-layout = <&layout_ortho_4x12_2x2u>; positions = < 0 1 2 3 4 5 6 7 8 9 10 11> diff --git a/app/dts/layouts/common/ortho_4x12/all1u.dtsi b/app/dts/layouts/common/ortho_4x12/all1u.dtsi index 2829d5e3..00e4bded 100644 --- a/app/dts/layouts/common/ortho_4x12/all1u.dtsi +++ b/app/dts/layouts/common/ortho_4x12/all1u.dtsi @@ -60,7 +60,7 @@ }; &layouts_common_ortho_4x12_position_map { - layout_ortho_4x12_all1u { + layout_ortho_4x12_all1u_posmap: layout_ortho_4x12_all1u { physical-layout = <&layout_ortho_4x12_all1u>; positions = < 0 1 2 3 4 5 6 7 8 9 10 11> diff --git a/app/dts/layouts/common/ortho_5x12/1x2u.dtsi b/app/dts/layouts/common/ortho_5x12/1x2u.dtsi index 5d12ea45..bbe101ba 100644 --- a/app/dts/layouts/common/ortho_5x12/1x2u.dtsi +++ b/app/dts/layouts/common/ortho_5x12/1x2u.dtsi @@ -71,7 +71,7 @@ }; &layouts_common_ortho_5x12_position_map { - layout_ortho_5x12_1x2u { + layout_ortho_5x12_1x2u_posmap: layout_ortho_5x12_1x2u { physical-layout = <&layout_ortho_5x12_1x2u>; positions = < 0 1 2 3 4 5 6 7 8 9 10 11> diff --git a/app/dts/layouts/common/ortho_5x12/2x2u.dtsi b/app/dts/layouts/common/ortho_5x12/2x2u.dtsi index 26079eb8..c2f7efb7 100644 --- a/app/dts/layouts/common/ortho_5x12/2x2u.dtsi +++ b/app/dts/layouts/common/ortho_5x12/2x2u.dtsi @@ -70,7 +70,7 @@ }; &layouts_common_ortho_5x12_position_map { - layout_ortho_5x12_2x2u { + layout_ortho_5x12_2x2u_posmap: layout_ortho_5x12_2x2u { physical-layout = <&layout_ortho_5x12_2x2u>; positions = < 0 1 2 3 4 5 6 7 8 9 10 11> diff --git a/app/dts/layouts/common/ortho_5x12/all1u.dtsi b/app/dts/layouts/common/ortho_5x12/all1u.dtsi index 3b8f7501..e8648789 100644 --- a/app/dts/layouts/common/ortho_5x12/all1u.dtsi +++ b/app/dts/layouts/common/ortho_5x12/all1u.dtsi @@ -72,7 +72,7 @@ }; &layouts_common_ortho_5x12_position_map { - layout_ortho_5x12_all1u { + layout_ortho_5x12_all1u_posmap: layout_ortho_5x12_all1u { physical-layout = <&layout_ortho_5x12_all1u>; positions = < 0 1 2 3 4 5 6 7 8 9 10 11> diff --git a/app/dts/layouts/foostan/corne/5column.dtsi b/app/dts/layouts/foostan/corne/5column.dtsi index 2d96d0b2..fe2cd4d1 100644 --- a/app/dts/layouts/foostan/corne/5column.dtsi +++ b/app/dts/layouts/foostan/corne/5column.dtsi @@ -48,7 +48,7 @@ }; &layouts_foostan_corne_position_map { - five_column { + foostan_corne_5col_posmap: five_column { physical-layout = <&foostan_corne_5col_layout>; positions = <36 0 1 2 3 4 5 6 7 8 9 37> diff --git a/app/dts/layouts/foostan/corne/6column.dtsi b/app/dts/layouts/foostan/corne/6column.dtsi index bc1a196d..4747a1e3 100644 --- a/app/dts/layouts/foostan/corne/6column.dtsi +++ b/app/dts/layouts/foostan/corne/6column.dtsi @@ -54,7 +54,7 @@ }; &layouts_foostan_corne_position_map { - twelve { + foostan_corne_6col_posmap: six { physical-layout = <&foostan_corne_6col_layout>; positions = < 0 1 2 3 4 5 6 7 8 9 10 11> From a72327bdff8517fd8d1037a8a918c3d50e45f702 Mon Sep 17 00:00:00 2001 From: Nicolas Munnich <98408764+Nick-Munnich@users.noreply.github.com> Date: Sat, 12 Oct 2024 21:25:45 +0200 Subject: [PATCH 067/415] docs: Physical layout docs improvements (#2533) * docs: Added layout configuration reference page * docs: Refactored and revamped physical layout creation information * docs: Added note in studio features page * docs: added studio_unlock note in features section --------- Co-authored-by: Cem Aksoylar Co-authored-by: Joel Spadin Co-authored-by: Peter Johanson --- .../assets/hardware-integration/numpad.svg | 182 +++++++ docs/docs/config/kscan.md | 167 ------- docs/docs/config/layout.md | 225 +++++++++ .../hardware-integration/new-shield.mdx | 40 +- .../hardware-integration/physical-layouts.md | 452 ++++++++++++++++++ .../hardware-integration/studio-setup.md | 140 ------ docs/docs/features/studio.md | 12 + docs/sidebars.js | 3 +- docs/static/_redirects | 3 +- 9 files changed, 882 insertions(+), 342 deletions(-) create mode 100644 docs/docs/assets/hardware-integration/numpad.svg create mode 100644 docs/docs/config/layout.md create mode 100644 docs/docs/development/hardware-integration/physical-layouts.md delete mode 100644 docs/docs/development/hardware-integration/studio-setup.md diff --git a/docs/docs/assets/hardware-integration/numpad.svg b/docs/docs/assets/hardware-integration/numpad.svg new file mode 100644 index 00000000..073f2864 --- /dev/null +++ b/docs/docs/assets/hardware-integration/numpad.svg @@ -0,0 +1,182 @@ + + + + + + + +0 + + + +1 + + + +2 + + + +3 + + + +4 + + + +5 + + + +6 + + + +7 + + + +8 + + + +9 + + + +10 + + + +11 + + + +12 + + + +13 + + + +14 + + + +15 + + + +16 + + + +17 + + + +18 + + + +19 + + + +0 + + + +1 + + + +2 + + + +3 + + + +4 + + + +5 + + + +6 + + + +7 + + + +8 + + + +9 + + + +10 + + + +11 + + + +12 + + + +13 + + + +14 + + + +15 + + + +16 + + + + diff --git a/docs/docs/config/kscan.md b/docs/docs/config/kscan.md index b4dd9925..dfe22bf4 100644 --- a/docs/docs/config/kscan.md +++ b/docs/docs/config/kscan.md @@ -335,170 +335,3 @@ Definition file: [zmk/app/dts/bindings/zmk,kscan-mock.yaml](https://github.com/z | `exit-after` | bool | Exit the program after running all events | false | The `events` array should be defined using the macros from [app/module/include/dt-bindings/zmk/kscan_mock.h](https://github.com/zmkfirmware/zmk/blob/main/app/module/include/dt-bindings/zmk/kscan_mock.h). - -## Matrix Transform - -Defines a mapping from keymap logical positions to physical matrix positions. - -Transforms should be used any time the physical layout of a keyboard's keys does not match the layout of its electrical matrix and/or when not all positions in the matrix are used. This applies to most non-ortholinear boards. - -Transforms can also be used for keyboards with multiple layouts. You can define multiple matrix transform nodes, one for each layout, and users can select which one they want from the `/chosen` node in their keymaps. - -See the [new shield guide](../development/hardware-integration/new-shield.mdx#matrix-transform) for more documentation on how to define a matrix transform. - -### Devicetree - -Applies to: `compatible = "zmk,matrix-transform"` - -Definition file: [zmk/app/dts/bindings/zmk,matrix-transform.yaml](https://github.com/zmkfirmware/zmk/blob/main/app/dts/bindings/zmk%2Cmatrix-transform.yaml) - -| Property | Type | Description | Default | -| ------------ | ----- | --------------------------------------------------------------------- | ------- | -| `rows` | int | Number of rows in the transformed matrix | | -| `columns` | int | Number of columns in the transformed matrix | | -| `row-offset` | int | Adds an offset to all rows before looking them up in the transform | 0 | -| `col-offset` | int | Adds an offset to all columns before looking them up in the transform | 0 | -| `map` | array | A list of position transforms | | - -The `map` array should be defined using the `RC()` macro from [dt-bindings/zmk/matrix_transform.h](https://github.com/zmkfirmware/zmk/blob/main/app/include/dt-bindings/zmk/matrix_transform.h). It should have one item per logical position in the keymap. Each item should list the physical row and column that should trigger the key in that position. - -### Example: Skipping Unused Positions - -Any keyboard which is not a grid of 1 unit keys will likely have some unused positions in the matrix. A matrix transform can be used to skip the unused positions so users don't have to set them to `&none` in keymaps. - -```dts -// numpad.overlay -/ { - chosen { - zmk,kscan = &kscan0; - zmk,matrix-transform = &default_transform; - }; - - kscan0: kscan { - compatible = "zmk,kscan-gpio-matrix"; - // define row-gpios with 5 elements and col-gpios with 4... - }; - - default_transform: matrix_transform { - compatible = "zmk,matrix-transform"; - rows = <5>; - columns = <4>; - // ┌───┬───┬───┬───┐ - // │NUM│ / │ * │ - │ - // ├───┼───┼───┼───┤ - // │ 7 │ 8 │ 9 │ + │ - // ├───┼───┼───┤ │ - // │ 4 │ 5 │ 6 │ │ - // ├───┼───┼───┼───┤ - // │ 1 │ 2 │ 3 │RET│ - // ├───┴───┼───┤ │ - // │ 0 │ . │ │ - // └───────┴───┴───┘ - map = < - RC(0,0) RC(0,1) RC(0,2) RC(0,3) - RC(1,0) RC(1,1) RC(1,2) RC(1,3) - RC(2,0) RC(2,1) RC(2,2) - RC(3,0) RC(3,1) RC(3,2) RC(3,3) - RC(4,0) RC(4,1) - >; - }; -}; -``` - -```dts -// numpad.keymap -/ { - keymap { - compatible = "zmk,keymap"; - default { - bindings = < - &kp KP_NUM &kp KP_DIV &kp KP_MULT &kp KP_MINUS - &kp KP_N7 &kp KP_N8 &kp KP_N9 &kp KP_PLUS - &kp KP_N4 &kp KP_N5 &kp KP_N6 - &kp KP_N1 &kp KP_N2 &kp KP_N3 &kp KP_ENTER - &kp KP_N0 &kp KP_DOT - >; - }; - } -}; -``` - -### Example: Non-standard Matrix - -Consider a keyboard with a [duplex matrix](https://wiki.ai03.com/books/pcb-design/page/matrices-and-duplex-matrix), where the matrix has twice as many rows and half as many columns as the keyboard has keys. A matrix transform can be used to correct for this so that keymaps can match the layout of the keys, not the layout of the matrix. - -```dts -/ { - chosen { - zmk,kscan = &kscan0; - zmk,matrix-transform = &default_transform; - }; - - kscan0: kscan { - compatible = "zmk,kscan-gpio-matrix"; - // define row-gpios with 12 elements and col-gpios with 8... - }; - - default_transform: matrix_transform { - compatible = "zmk,matrix-transform"; - rows = <6>; - columns = <16>; - // ESC F1 F2 F3 ... - // ` 1 2 3 ... - // Tab Q W E ... - // Caps A S D ... - // Shift Z X C ... - // Ctrl Alt ... - map = < - RC(0,0) RC(1,0) RC(0,1) RC(1,1) // ... - RC(2,0) RC(3,0) RC(2,1) RC(3,1) // ... - RC(4,0) RC(5,0) RC(4,1) RC(5,1) // ... - RC(6,0) RC(7,0) RC(6,1) RC(7,1) // ... - RC(8,0) RC(9,0) RC(8,1) RC(9,1) // ... - RC(10,0) RC(11,0) // ... - >; - }; -}; -``` - -### Example: Charlieplex - -Since a charlieplex driver will never align with a keyboard directly due to the un-addressable positions, a matrix transform should be used to map the pairs to the layout of the keys. -Note that the entire addressable space does not need to be mapped. - -```devicetree -/ { - chosen { - zmk,kscan = &kscan0; - zmk,matrix-transform = &default_transform; - }; - - kscan0: kscan { - compatible = "zmk,kscan-gpio-charlieplex"; - wakeup-source; - - interrupt-gpios = <&pro_micro 21 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN) >; - gpios - = <&pro_micro 16 GPIO_ACTIVE_HIGH> - , <&pro_micro 17 GPIO_ACTIVE_HIGH> - , <&pro_micro 18 GPIO_ACTIVE_HIGH> - , <&pro_micro 19 GPIO_ACTIVE_HIGH> - , <&pro_micro 20 GPIO_ACTIVE_HIGH> - ; // addressable space is 5x5, (minus paired values) - }; - - default_transform: matrix_transform { - compatible = "zmk,matrix-transform"; - rows = <3>; - columns = <5>; - // Q W E R - // A S D F - // Z X C V - map = < - RC(0,1) RC(0,2) RC(0,3) RC(0,4) - RC(1,0) RC(1,2) RC(1,3) RC(1,4) - RC(2,0) RC(2,1) RC(2,3) RC(2,4) - >; - }; -}; -``` diff --git a/docs/docs/config/layout.md b/docs/docs/config/layout.md new file mode 100644 index 00000000..385d60c3 --- /dev/null +++ b/docs/docs/config/layout.md @@ -0,0 +1,225 @@ +--- +title: Layout Configuration +sidebar_label: Layout +--- + +See [Configuration Overview](index.md) for instructions on how to change these settings. + +## Matrix Transform + +Defines a mapping from keymap logical positions to physical [kscan](./kscan.md) positions. + +You can define multiple matrix transform nodes, one for each layout, and users can select which one they want from the `/chosen` node in their keymaps. + +See the [new shield guide](../development/hardware-integration/new-shield.mdx#matrix-transform) for more documentation on how to define a matrix transform. + +### Devicetree + +Applies to: `compatible = "zmk,matrix-transform"` + +Definition file: [zmk/app/dts/bindings/zmk,matrix-transform.yaml](https://github.com/zmkfirmware/zmk/blob/main/app/dts/bindings/zmk%2Cmatrix-transform.yaml) + +| Property | Type | Description | Default | +| ------------ | ----- | --------------------------------------------------------------------- | ------- | +| `rows` | int | Number of rows in the transformed matrix | | +| `columns` | int | Number of columns in the transformed matrix | | +| `row-offset` | int | Adds an offset to all rows before looking them up in the transform | 0 | +| `col-offset` | int | Adds an offset to all columns before looking them up in the transform | 0 | +| `map` | array | A list of position transforms | | + +The `map` array should be defined using the `RC()` macro from [dt-bindings/zmk/matrix_transform.h](https://github.com/zmkfirmware/zmk/blob/main/app/include/dt-bindings/zmk/matrix_transform.h). It should have one item per logical position in the keymap. Each item should list the physical row and column that should trigger the key in that position. + +### Example: Skipping Unused Positions + +Any keyboard which is not a grid of 1 unit keys will likely have some unused positions in the matrix. A matrix transform can be used to skip the unused positions so users don't have to set them to `&none` in keymaps. + +```dts +// numpad.overlay +/ { + chosen { + zmk,kscan = &kscan0; + zmk,matrix-transform = &default_transform; + }; + + kscan0: kscan { + compatible = "zmk,kscan-gpio-matrix"; + // define row-gpios with 5 elements and col-gpios with 4... + }; + + default_transform: matrix_transform { + compatible = "zmk,matrix-transform"; + rows = <5>; + columns = <4>; + // ┌───┬───┬───┬───┐ + // │NUM│ / │ * │ - │ + // ├───┼───┼───┼───┤ + // │ 7 │ 8 │ 9 │ + │ + // ├───┼───┼───┤ │ + // │ 4 │ 5 │ 6 │ │ + // ├───┼───┼───┼───┤ + // │ 1 │ 2 │ 3 │RET│ + // ├───┴───┼───┤ │ + // │ 0 │ . │ │ + // └───────┴───┴───┘ + map = < + RC(0,0) RC(0,1) RC(0,2) RC(0,3) + RC(1,0) RC(1,1) RC(1,2) RC(1,3) + RC(2,0) RC(2,1) RC(2,2) + RC(3,0) RC(3,1) RC(3,2) RC(3,3) + RC(4,0) RC(4,1) + >; + }; +}; +``` + +```dts +// numpad.keymap +/ { + keymap { + compatible = "zmk,keymap"; + default { + bindings = < + &kp KP_NUM &kp KP_DIV &kp KP_MULT &kp KP_MINUS + &kp KP_N7 &kp KP_N8 &kp KP_N9 &kp KP_PLUS + &kp KP_N4 &kp KP_N5 &kp KP_N6 + &kp KP_N1 &kp KP_N2 &kp KP_N3 &kp KP_ENTER + &kp KP_N0 &kp KP_DOT + >; + }; + } +}; +``` + +### Example: Non-standard Matrix + +Consider a keyboard with a [duplex matrix](https://wiki.ai03.com/books/pcb-design/page/matrices-and-duplex-matrix), where the matrix has twice as many rows and half as many columns as the keyboard has keys. A matrix transform can be used to correct for this so that keymaps can match the layout of the keys, not the layout of the matrix. + +```dts +/ { + chosen { + zmk,kscan = &kscan0; + zmk,matrix-transform = &default_transform; + }; + + kscan0: kscan { + compatible = "zmk,kscan-gpio-matrix"; + // define row-gpios with 12 elements and col-gpios with 8... + }; + + default_transform: matrix_transform { + compatible = "zmk,matrix-transform"; + rows = <6>; + columns = <16>; + // ESC F1 F2 F3 ... + // ` 1 2 3 ... + // Tab Q W E ... + // Caps A S D ... + // Shift Z X C ... + // Ctrl Alt ... + map = < + RC(0,0) RC(1,0) RC(0,1) RC(1,1) // ... + RC(2,0) RC(3,0) RC(2,1) RC(3,1) // ... + RC(4,0) RC(5,0) RC(4,1) RC(5,1) // ... + RC(6,0) RC(7,0) RC(6,1) RC(7,1) // ... + RC(8,0) RC(9,0) RC(8,1) RC(9,1) // ... + RC(10,0) RC(11,0) // ... + >; + }; +}; +``` + +### Example: Charlieplex + +Since a charlieplex driver will never align with a keyboard directly due to the un-addressable positions, a matrix transform should be used to map the pairs to the layout of the keys. +Note that the entire addressable space does not need to be mapped. + +```devicetree +/ { + chosen { + zmk,kscan = &kscan0; + zmk,matrix-transform = &default_transform; + }; + + kscan0: kscan { + compatible = "zmk,kscan-gpio-charlieplex"; + wakeup-source; + + interrupt-gpios = <&pro_micro 21 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN) >; + gpios + = <&pro_micro 16 GPIO_ACTIVE_HIGH> + , <&pro_micro 17 GPIO_ACTIVE_HIGH> + , <&pro_micro 18 GPIO_ACTIVE_HIGH> + , <&pro_micro 19 GPIO_ACTIVE_HIGH> + , <&pro_micro 20 GPIO_ACTIVE_HIGH> + ; // addressable space is 5x5, (minus paired values) + }; + + default_transform: matrix_transform { + compatible = "zmk,matrix-transform"; + rows = <3>; + columns = <5>; + // Q W E R + // A S D F + // Z X C V + map = < + RC(0,1) RC(0,2) RC(0,3) RC(0,4) + RC(1,0) RC(1,2) RC(1,3) RC(1,4) + RC(2,0) RC(2,1) RC(2,3) RC(2,4) + >; + }; +}; +``` + +## Physical Layout + +Defines a keyboard layout by joining together a [matrix transform](#matrix-transform), a [keyboard scan](./kscan.md), and a list of physical key properties. +Multiple physical layouts can be defined for keyboards with multiple physical key layouts. +Read through the [page on physical layouts](../development/hardware-integration/physical-layouts.md) for more information. + +### Devicetree + +Applies to: `compatible = zmk,physical-layout` + +Definition file: [zmk/app/dts/bindings/zmk,physical-layout.yaml](https://github.com/zmkfirmware/zmk/blob/main/app/dts/bindings/zmk%2Cphysical-layout.yaml) + +| Property | Type | Description | Default | +| -------------- | ------------- | ---------------------------------------------------------------------------------------------------------------------- | ------- | +| `display-name` | string | The name of this layout, for display purposes | | +| `transform` | phandle | The matrix transform to use along with this layout | | +| `kscan` | phandle | The kscan to use along with this layout. The `zmk,kscan` chosen will be used as a fallback if this property is omitted | | +| `keys` | phandle-array | Array of key physical attributes. | | + +Each element of the `keys` array has the shape `<&key_physical_attrs w h x y r rx ry>`, with the following properties: + +| Property | Type | Description | Unit | +| ---------- | -------- | ------------------------------------ | ------------------------------------------------------- | +| Width | int (>0) | Key(cap) width | [centi-](https://en.wikipedia.org/wiki/Centi-)"keyunit" | +| Height | int (>0) | Key(cap) height | [centi-](https://en.wikipedia.org/wiki/Centi-)"keyunit" | +| X | uint | Key X position (top-left point) | [centi-](https://en.wikipedia.org/wiki/Centi-)"keyunit" | +| Y | uint | Key Y position (top-left point) | [centi-](https://en.wikipedia.org/wiki/Centi-)"keyunit" | +| Rotation | int | Key rotation (positive => clockwise) | [centi-](https://en.wikipedia.org/wiki/Centi-)degree | +| Rotation X | int | Rotation origin X position | [centi-](https://en.wikipedia.org/wiki/Centi-)"keyunit" | +| Rotation Y | int | Rotation origin Y position | [centi-](https://en.wikipedia.org/wiki/Centi-)"keyunit" | + +The `key_physical_attrs` node is defined in [`dts/physical_layouts.dtsi`](https://github.com/zmkfirmware/zmk/blob/main/app/dts/physical_layouts.dtsi) and is mandatory. + +## Physical Layout Position Map + +Defines a mapping between [physical layouts](#physical-layout), allowing key mappings to be preserved in the same locations as previously when using [ZMK Studio](../features/studio.md). Read through the [page on physical layouts](../development/hardware-integration/physical-layouts.md) for more information. + +### Devicetree + +Applies to: `compatible = zmk,physical-layout-position-map` + +Definition file: [zmk/app/dts/bindings/zmk,physical-layout-position-map.yaml](https://github.com/zmkfirmware/zmk/blob/main/app/dts/bindings/zmk%2Cphysical-layout-position-map.yaml) + +| Property | Type | Description | Default | +| ---------- | ------- | ------------------------------------------------------------------------------------------------ | ------- | +| `complete` | boolean | If the mapping complete describes the key mapping, and no position based mapping should be used. | | + +The `zmk,physical-layout-position-map` node should have one child node per physical layout. Each child node should have the following properties: + +| Property | Type | Description | Default | +| ----------------- | ------- | --------------------------------------------------------------------------------- | ------- | +| `physical-layout` | phandle | The physical layout that corresponds to this mapping entry | | +| `positions` | array | Array of key positions that match the same array entry in the other sibling nodes | | diff --git a/docs/docs/development/hardware-integration/new-shield.mdx b/docs/docs/development/hardware-integration/new-shield.mdx index f2be4946..18ce3ade 100644 --- a/docs/docs/development/hardware-integration/new-shield.mdx +++ b/docs/docs/development/hardware-integration/new-shield.mdx @@ -442,19 +442,15 @@ The matrix transform is also used to "correct" pin orderings into something that See the [in-tree keyboards](https://github.com/zmkfirmware/zmk/tree/main/app/boards/shields) that ZMK defines for examples of more complex matrix transformations. -Also see the [matrix transform section](../../config/kscan.md#matrix-transform) in the Keyboard Scan configuration documentation for further details and examples of matrix transforms. +Also see the [matrix transform section](../../config/layout.md#matrix-transform) in the Keyboard Scan configuration documentation for further details and examples of matrix transforms. ### Physical Layout -The physical layout is the top level entity that aggregates all details about a certain possible layout: +Your keyboard will need to have a physical layout defined. +Read through our [dedicated page on physical layouts](./physical-layouts.md) for information on how to define a physical layout. +Physical layouts should be placed in the same file as the matrix transform, i.e. `my_keyboard.overlay` for unibodies and `my_keyboard.dtsi` for split keyboards. -- Your keyboard scan (kscan) driver -- Your matrix transform -- (Optional) Physical key positions - -The physical layout should be placed in the same file as the matrix transform, i.e. `my_keyboard.overlay` for unibodies and `my_keyboard.dtsi` for split keyboards. - -A physical layout is very basic, e.g.: +A very basic physical layout looks like this: ```dts / { @@ -467,29 +463,6 @@ A physical layout is very basic, e.g.: }; ``` -If a keyboard has multiple possible layouts (ex. you can snap off an outer column), then you should define multiple matrix transformations and multiple physical layouts. -If necessary, you can also define multiple kscan instances. - -```dts -/ { - default_layout: default_layout { - compatible = "zmk,physical-layout"; - display-name = "Default Layout"; - transform = <&default_transform>; - kscan = <&kscan0>; - }; - - alt_layout: alt_layout { - compatible = "zmk,physical-layout"; - display-name = "Alternate Layout"; - transform = <&alt_transform>; - kscan = <&alt_kscan0>; - }; -}; -``` - -See [ZMK Studio Setup](./studio-setup.md) for information on defining the `keys` property for physical key positions that lets you enable [ZMK Studio](../../features/studio.md) for your keyboard. - ### Chosen Node Set the `chosen` node to a defined "default" physical layout. This should also be placed in the same file as the physical layout, i.e. `my_keyboard.overlay` for unibodies and `my_keyboard.dtsi` for split keyboards. @@ -503,7 +476,7 @@ Set the `chosen` node to a defined "default" physical layout. This should also b }; ``` -If you define multiple physical layouts, users can select a different layout by overriding the `zmk,physical-layout` chosen node in their keymap file. +If you define multiple physical layouts, users can select a different layout by overriding the `zmk,physical-layout` chosen node in their keymap file or by using [ZMK Studio](../../features/studio.md) if your board is compatible with it. :::note If all of your physical layouts use the same `kscan` node under the hood, you can skip setting the `kscan` property on each layout and instead assign the `zmk,kscan` chosen node to your single kscan instance: @@ -550,6 +523,7 @@ Here is an example simple keymap for a 3x3 macropad, with only one layer: The keymap should match the order of the keys in the [matrix transform](#matrix-transform) exactly, left to right, top to bottom (they are both 1 dimensional arrays rearranged with newline characters for better legibility). See [Keymaps](../../keymaps/index.mdx) for information on defining keymaps in ZMK. +If you wish to use [ZMK Studio](../../features/studio.md) with your keyboard, make sure to assign the [ZMK Studio unlocking behavior](../../keymaps/behaviors/studio-unlock.md) to a key in your keymap. ## Metadata diff --git a/docs/docs/development/hardware-integration/physical-layouts.md b/docs/docs/development/hardware-integration/physical-layouts.md new file mode 100644 index 00000000..873bc714 --- /dev/null +++ b/docs/docs/development/hardware-integration/physical-layouts.md @@ -0,0 +1,452 @@ +--- +title: Physical Layouts +toc_max_heading_level: 4 +--- + +A physical layout is a devicetree entity that aggregates all details about a certain possible keyboard layout. +It contains: + +- A [keyboard scan (kscan) driver](../../config/kscan.md) +- A [matrix transform](../../config/layout.md#matrix-transform) +- (Optional) [Physical key positions](#physical-layout-positions) + +## Basic Physical Layout + +A basic physical layout without the `keys` property looks like this: + +```dts +/ { + default_layout: default_layout { + compatible = "zmk,physical-layout"; + display-name = "Default Layout"; + transform = <&default_transform>; + kscan = <&kscan0>; + }; +}; +``` + +It is given a name, a matrix transform, and a kscan. If all of your physical layouts share the same kscan, then the `kscan` property can be omitted - in this case it needs to be set in the [`chosen` node](./new-shield.mdx#chosen-node). See the [configuration section on physical layouts](../../config/index.md) for reference. + +## (Optional) Keys Property + +:::warning[Alpha Feature] + +[ZMK Studio](../../features/studio.md) support is in alpha. Although best efforts are being made, backwards compatibility during active development is not guaranteed. + +::: + +The `keys` property is required for [ZMK Studio](../../features/studio.md) support. It is used to describe the physical attributes of each key position present in that layout. If this property is used, then you should define the physical layouts and any [position maps](#position-map) in a file called `-layouts.dtsi`. This file should then be imported by the appropriate file, such as an `.overlay`, `.dts`, or a `.dtsi` (last of which is itself imported by one of the previous). + +To pull in the necessary definition for creating physical layouts with the `keys` property, a new include should be added to the top of the devicetree file: + +``` +#include +``` + +Assigned to the `keys` property is an array of key descriptions listed in the same order as keymap bindings, matrix transforms, etc. +A key description has the shape `<&key_physical_attrs w h x y r rx ry>` with the following properties: + +| Property | Type | Description | Unit | +| ---------- | -------- | ------------------------------------ | ------------------------------------------------------- | +| Width | int (>0) | Key(cap) width | [centi-](https://en.wikipedia.org/wiki/Centi-)"keyunit" | +| Height | int (>0) | Key(cap) height | [centi-](https://en.wikipedia.org/wiki/Centi-)"keyunit" | +| X | uint | Key X position (top-left point) | [centi-](https://en.wikipedia.org/wiki/Centi-)"keyunit" | +| Y | uint | Key Y position (top-left point) | [centi-](https://en.wikipedia.org/wiki/Centi-)"keyunit" | +| Rotation | int | Key rotation (positive => clockwise) | [centi-](https://en.wikipedia.org/wiki/Centi-)degree | +| Rotation X | int | Rotation origin X position | [centi-](https://en.wikipedia.org/wiki/Centi-)"keyunit" | +| Rotation Y | int | Rotation origin Y position | [centi-](https://en.wikipedia.org/wiki/Centi-)"keyunit" | + +:::tip +You can specify negative values in devicetree using parentheses around it, e.g. `(-3000)` for a 30 degree counterclockwise rotation. +::: + +### Physical Layout with Keys Example + +Here is an example of a physical layout for a 2x2 macropad: + +```dts +#include + +/ { + macropad_physical_layout: macropad_physical_layout { + compatible = "zmk,physical-layout"; + display-name = "Macro Pad"; + transform = <&default_transform>; + kscan = <&kscan0>; + keys // w h x y rot rx ry + = <&key_physical_attrs 100 100 0 0 0 0 0> + , <&key_physical_attrs 100 100 100 0 0 0 0> + , <&key_physical_attrs 100 100 0 100 0 0 0> + , <&key_physical_attrs 100 100 100 100 0 0 0> + ; + }; +}; +``` + +## Using Predefined Layouts + +ZMK defines a number of popular physical layouts in-tree at [`app/dts/layouts`](https://github.com/zmkfirmware/zmk/tree/main/app/dts/layouts). +To use such layouts, import them and assign their `transform` and (optionally) `kscan` properties. + +Here is an example of using the predefined physical layouts for a keyboard with the same layout as the "ferris": + +```dts +#include + +// Assigning suitable kscan and matrix transforms +&cuddlykeyboards_ferris_layout { + transform = <&default_transform>; + kscan = <&kscan0>; +}; +``` + +Shared physical layouts found in the same folder are defined such that they can be used together, to define [multiple physical layout](#multiple-physical-layouts) options. See below for more information on multiple physical layouts. + +Here is an example of using the predefined physical layouts for a 60% keyboard: + +```dts +#include +#include +#include +#include + + +// Assigning suitable kscan and matrix transforms +&layout_60_ansi { + transform = <&ansi_transform>; + kscan = <&ansi_kscan>; +}; + +&layout_60_iso { + transform = <&iso_transform>; + kscan = <&iso_kscan>; +}; + +&layout_60_all1u { + transform = <&all_1u_transform>; + kscan = <&all_1u_kscan>; +}; + +&layout_60_hhkb { + transform = <&hhkb_transform>; + kscan = <&hhkb_kscan>; +}; +``` + +## Multiple Physical Layouts + +If a keyboard has multiple possible layouts (e.g. you can snap off an outer column), then you should define multiple matrix transformations and multiple physical layouts, one for each possible layout. +If necessary, you can also define multiple kscan instances. + +```dts +// Needed if and only if keys property is used +#include + +/ { + default_layout: default_layout { + compatible = "zmk,physical-layout"; + display-name = "Default Layout"; + transform = <&default_transform>; + kscan = <&kscan0>; + keys = <...>; // List of key positions, optional + }; + + alt_layout: alt_layout { + compatible = "zmk,physical-layout"; + display-name = "Alternate Layout"; + transform = <&alt_transform>; + kscan = <&alt_kscan0>; + keys = <...>; // List of key positions, optional + }; +}; +``` + +### Position Map + +When switching between layouts using [ZMK Studio](../../features/studio.md), an attempt is made to automatically infer bindings for the keys in the new layout from the old layout. Keys with the same physical key properties are given the same binding. This approach has some limitations, so for more accurate transference of bindings a position map is used. + +A position map looks something like this: + +```dts +/ { + position_map { + compatible = "zmk,physical-layout-position-map"; + complete; // Optional, see 'Example non-complete position map' + layout1: layout1 { + physical-layout = <&physical_layout1>; + positions = <...>; // List of positions to map + }; + layout2: layout2 { + physical-layout = <&physical_layout2>; + positions = <...>; // List of positions to map + }; + // Additional layout child nodes + }; +}; +``` + +A child node is defined for every layout the keyboard can have. The `positions` properties each contain an array of indices, which are used to refer to keys in the `keys` array of their corresponding physical layout. A `0` in the `positions` property refers to the first key in the `keys` array, a `1` refers to the second, and so on. + +When switching from one layout to another, say from layout 1 to layout 2, the _orderings_ found in the `positions` arrays are used. The first key in the `positions` array of layout 2 is given the binding assigned to the first key in the `positions` array of layout 1, the second key in the `positions` array of layout 2 is given the binding assigned to the second key in the `positions` array of layout 1, and so on. + +The position map should be marked as `complete` if all desired binding transfers are defined within it. Otherwise, [ZMK Studio](../../features/studio.md) will continue to automatically determine assignments for keys not listed in the position map. See [this example non-complete position map](#example-non-complete-position-map) for why this could be useful. + +See also the [configuration section on position maps](../../config/layout.md#physical-layout-position-map). + +#### Writing a position map + +Start by creating the parent node defining the position map: + +```dts +/ { + keypad_position_map { + compatible = "zmk,physical-layout-position-map"; + complete; // Optional, see 'Example non-complete position map' + + // Child node 1 here + + // Child node 2 here + + // ... + }; +}; +``` + +It is easiest to write the position map by considering one layout to be the "reference" layout, and defining all other position maps with respect to it. The reference layout should usually be the one with the most keys, as that creates a position map where no key bindings are lost when switching to a layout with fewer keys and back. + +Create the child node for the reference layout, and fill the `positions` array by counting upwards, giving it the same order and number of keys as the `keys` property of its physical layout. For a 2x2 macropad the child node would be + +```dts +/ { + keypad_position_map { + // Other properties + + macropad_map: macropad { + physical-layout = <¯opad_layout>; + positions // This is equivalent to `positions = <0 1 2 3>;`, reshaped for readability + = < 0 1 > + , < 2 3 >; + }; + }; +}; +``` + +Next write the child nodes for every other layout with respect to the reference. For keys present in the reference which aren't present in the layout you're writing the child node for, count backwards: The first key that isn't present is given the highest number found in the `positions` array of the reference, the second key that isn't present is given the second highest number, and so on. The below examples show this process more clearly. + +#### Example larger position map + +Consider the following macropad/numpad with two physical layouts: + +![A 4x5 numpad/macropad](../../assets/hardware-integration/numpad.svg) + +Let us first consider each side individually. The "reference" position map of the left side would look like this: + +```dts +/ { + keypad_position_map { + // Other properties + + macropad_map: macropad { + physical-layout = <¯opad_layout>; + positions + = < 0 1 2 3> + , < 4 5 6 7> + , < 8 9 10 11> + , <12 13 14 15> + , <16 17 18 19>; + }; + }; +}; +``` + +Meanwhile, the "reference" position map of the right side with fewer keys would look like this: + +```dts +/ { + keypad_position_map { + // Other properties + + numpad_map: numpad { + physical-layout = <&numpad_layout>; + positions + = < 0 1 2 3> + , < 4 5 6 7> + , < 8 9 10 > + , <11 12 13 14> + , <15 16 >; + }; + }; +}; +``` + +As a reminder, the `positions` property is a one-dimensional array like the `keys` property, formatted nicely through the use of whitespace and angle bracket groupings. + +If the left side with more keys was used as the reference layout, then the overall position map of the keyboard would look like this: + +```dts +/ { + keypad_lossless_position_map { + compatible = "zmk,physical-layout-position-map"; + complete; + + macropad_map: macropad { + physical-layout = <¯opad_layout>; + positions + = < 0 1 2 3> + , < 4 5 6 7> + , < 8 9 10 11> + , <12 13 14 15> + , <16 17 18 19>; + }; + + numpad_map: numpad { + physical-layout = <&numpad_layout>; + positions + = < 0 1 2 3> + , < 4 5 6 7> + , < 8 9 10 19> + , <11 12 13 14> + , <15 18 16 17>; + }; + }; +}; +``` + +The "missing" positions are filled with the "spare" numbers of the layout with more keys. The order in which the spare keys are used is arbitrary and counting backwards is a convenient way to assign them. + +If the right side with fewer keys were used as a reference instead, then the overall position map would look like this: + +```dts +/ { + keypad_lossy_position_map { + compatible = "zmk,physical-layout-position-map"; + complete; + + macropad_map: macropad { + physical-layout = <¯opad_layout>; + positions + = < 0 1 2 3> + , < 4 5 6 7> + , < 8 9 10 > + , <12 13 14 15> + , <16 18 >; + }; + + numpad_map: numpad { + physical-layout = <&numpad_layout>; + positions + = < 0 1 2 3> + , < 4 5 6 7> + , < 8 9 10 > + , <11 12 13 14> + , <15 16 >; + }; + }; +}; +``` + +The above example is "lossy" because (unlike the previous "lossless" example) if a user switches from the macropad layout to the numpad layout _and then_ switches from the numpad layout back to the macropad layout, the assignments to the keys present but not listed in the macropad's map are lost. + +#### Example non-`complete` position map + +Consider the above device again -- most of the positions have identical `keys` properties. For example, the macropad's `12` key and the numpad's `11` key would have the same physical property, and be mapped to each other automatically. The keys whose mappings are unable to be determined automatically are those with different physical characteristics: the 2u high and 2u wide keys, and their corresponding 1u counterparts. + +A non-`complete` position map can be used to assign mappings to only these particular keys: + +```dts +/ { + keypad_lossy_position_map { + compatible = "zmk,physical-layout-position-map"; + + macropad_map: macropad { + physical-layout = <¯opad_layout>; + positions = <7 15 16>; + }; + + numpad_map: numpad { + physical-layout = <&numpad_layout>; + positions = <7 14 15>; + }; + }; +}; +``` + +This is noticably simpler to write, and can be a useful way of saving flash space for memory-constrained devices. The above is a "lossy" mapping, though. While "lossless" non-`complete` mappings are possible, they can be counter-intuitive enough that it may be easier to write the full position map instead. + +For completeness, the equivalent "lossless" non-`complete` position map is shown below: + +```dts +/ { + keypad_lossy_position_map { + compatible = "zmk,physical-layout-position-map"; + + macropad_map: macropad { + physical-layout = <¯opad_layout>; + positions = <7 11 15 19 16 17>; + }; + + numpad_map: numpad { + physical-layout = <&numpad_layout>; + positions = <7 19 14 18 15 17>; + }; + }; +}; +``` + +#### Additional example: corne + +The following is an example of a "lossless" position map which maps the 5-column and 6-column Corne keymap layouts. The 6 column layout is the reference layout. + +```dts + foostan_corne_lossless_position_map { + compatible = "zmk,physical-layout-position-map"; + + complete; + + twelve_map: twelve { + physical-layout = <&foostan_corne_6col_layout>; + positions + = < 0 1 2 3 4 5 6 7 8 9 10 11> + , <12 13 14 15 16 17 18 19 20 21 22 23> + , <24 25 26 27 28 29 30 31 32 33 34 35> + , < 36 37 38 39 40 41 >; + }; + + ten_map: ten { + physical-layout = <&foostan_corne_5col_layout>; + positions + = <41 0 1 2 3 4 5 6 7 8 9 40> + , <39 10 11 12 13 14 15 16 17 18 19 38> + , <37 20 21 22 23 24 25 26 27 28 29 36> + , < 30 31 32 33 34 35 >; + }; + }; +``` + +Meanwhile, the "lossy" version of the same position map with the 5 column version as reference looks like this: + +```dts + foostan_corne_lossy_position_map { + compatible = "zmk,physical-layout-position-map"; + + complete; + + twelve_map: twelve { + physical-layout = <&foostan_corne_6col_layout>; + positions + = < 1 2 3 4 5 6 7 8 9 10> + , <13 14 15 16 17 18 19 20 21 22> + , <25 26 27 28 29 30 31 32 33 34> + , < 36 37 38 39 40 41 >; + }; + + ten_map: ten { + physical-layout = <&foostan_corne_5col_layout>; + positions + = < 0 1 2 3 4 5 6 7 8 9> + , <10 11 12 13 14 15 16 17 18 19> + , <20 21 22 23 24 25 26 27 28 29> + , < 30 31 32 33 34 35 >; + }; + }; +``` diff --git a/docs/docs/development/hardware-integration/studio-setup.md b/docs/docs/development/hardware-integration/studio-setup.md deleted file mode 100644 index dfa80020..00000000 --- a/docs/docs/development/hardware-integration/studio-setup.md +++ /dev/null @@ -1,140 +0,0 @@ ---- -title: ZMK Studio Setup ---- - -:::warning[Alpha Feature] - -ZMK Studio support is in alpha. Although best efforts are being made, backwards compatibility during active development is not guaranteed. - -::: - -This guide will walk you through enabling ZMK Studio support for a keyboard. - -The main additional pieces needed for ZMK Studio support involve additional metadata needed in order -to properly to display the physical layouts available for the particular keyboard. - -# Physical Layout Positions - -Physical layouts are described as part of the [new shield guide](./new-shield.mdx#physical-layout) with the exception of the `keys` property that is required for ZMK Studio support. This is used to describe the physical attributes of each key position present in that layout and its items are listed in the same order as keymap bindings, matrix transforms, etc. The properties available are: - -| Property | Type | Description | Unit | -| ---------- | -------- | ------------------------------------ | ------------------------------------------------------- | -| Width | int (>0) | Key(cap) width | [centi-](https://en.wikipedia.org/wiki/Centi-)"keyunit" | -| Height | int (>0) | Key(cap) height | [centi-](https://en.wikipedia.org/wiki/Centi-)"keyunit" | -| X | uint | Key X position (top-left point) | [centi-](https://en.wikipedia.org/wiki/Centi-)"keyunit" | -| Y | uint | Key Y position (top-left point) | [centi-](https://en.wikipedia.org/wiki/Centi-)"keyunit" | -| Rotation | int | Key rotation (positive => clockwise) | [centi-](https://en.wikipedia.org/wiki/Centi-)degree | -| Rotation X | int | Rotation origin X position | [centi-](https://en.wikipedia.org/wiki/Centi-)"keyunit" | -| Rotation Y | int | Rotation origin Y position | [centi-](https://en.wikipedia.org/wiki/Centi-)"keyunit" | - -:::note -You can specify negative values in devicetree using parentheses around it, e.g. `(-3000)` for a 30 degree counterclockwise rotation. -::: - -## Header Include - -To pull in the necessary definition for creating physical layouts, a new include should be added to the top of the devicetree file: - -``` -#include -``` - -## Example - -Here is an example physical layout for a 2x2 macropad: - -```dts - macropad_physical_layout: macropad_physical_layout { - compatible = "zmk,physical-layout"; - display-name = "Macro Pad"; - - keys // w h x y rot rx ry - = <&key_physical_attrs 100 100 0 0 0 0 0> - , <&key_physical_attrs 100 100 100 0 0 0 0> - , <&key_physical_attrs 100 100 0 100 0 0 0> - , <&key_physical_attrs 100 100 100 100 0 0 0> - ; - }; -``` - -# Position Map - -When switching between layouts with ZMK Studio, the keymap of the previously selected layout is used to populate the keymap in the new layout. To determine which keymap entry maps to which entry in the new layout, keys between the two layouts that share the exact same physical attributes are matched. - -However, keys between layouts might not be in exactly the same positions, in which case a position map can be used. The position map includes a sequence for every relevant layout, and the corresponding entries in `positions` property will be used to determine the mapping between layouts. By default, the physical attribute matching behavior will be used as a fallback for positions not specified in the map, but the `complete` property can be added to the map to specify that no matching fallback should occur. - -:::info - -Key positions in the maps are numbered like the keys in your keymap, starting at 0. So the first position in the layout is position `0`, the next key position is `1`, etc. - -::: - -## Examples - -### Basic Map - -For example, the following position map correctly maps the 5-column and 6-column Corne keymap layouts. - -```dts - foostan_corne_position_map { - compatible = "zmk,physical-layout-position-map"; - - complete; - - twelve { - physical-layout = <&foostan_corne_6col_layout>; - positions - = < 1 2 3 4 5 6 7 8 9 10> - , <13 14 15 16 17 18 19 20 21 22> - , <25 26 27 28 29 30 31 32 33 34> - , < 36 37 38 39 40 41 >; - }; - - ten { - physical-layout = <&foostan_corne_5col_layout>; - positions - = < 0 1 2 3 4 5 6 7 8 9> - , <10 11 12 13 14 15 16 17 18 19> - , <20 21 22 23 24 25 26 27 28 29> - , < 30 31 32 33 34 35 >; - }; - }; -``` - -The first entries in the two mappings have values `1` and `0` respectively, which means that position `1` in the 6-column layout will map to position `0` in the 5-column layout, the second entries show that position `2` in the 6-column layout corresponds to position `1` in the 5-column layout, etc. - -### Full Preserving Map - -The above basic example has one major downside. Because the keys on the outer columns of the 6-column layout aren't mapped into any locations in the 5-column layout, when a user switches to the 5-column layout and then back to the 6-column layout, the bindings for those outer columns will have been lost/dropped at the first step. - -In order to preserve those bindings that are in "missing" keys in other layouts, we can include those locations in the map, but map them "off the end" of the smaller layout key positions. - -Here is a fixed up Corne mapping: - -```dts - foostan_corne_position_map { - compatible = "zmk,physical-layout-position-map"; - - complete; - - twelve { - physical-layout = <&foostan_corne_6col_layout>; - positions - = < 0 1 2 3 4 5 6 7 8 9 10 11> - , <12 13 14 15 16 17 18 19 20 21 22 23> - , <24 25 26 27 28 29 30 31 32 33 34 35> - , < 36 37 38 39 40 41 >; - }; - - ten { - physical-layout = <&foostan_corne_5col_layout>; - positions - = <36 0 1 2 3 4 5 6 7 8 9 37> - , <38 10 11 12 13 14 15 16 17 18 19 39> - , <40 20 21 22 23 24 25 26 27 28 29 41> - , < 30 31 32 33 34 35 >; - }; - }; -``` - -Notice how the outer column positions in the 6-column layout are mapped to positions 36, 37, etc. in the 5-column layout. The 5-column layout only uses key positions up to 35, so those bindings in the outer columns will get migrated into the "extra space" that is ignored by the smaller layout, preserved to get mapped back in place when the user switches back. diff --git a/docs/docs/features/studio.md b/docs/docs/features/studio.md index f8d4059b..4053d3d9 100644 --- a/docs/docs/features/studio.md +++ b/docs/docs/features/studio.md @@ -10,6 +10,10 @@ ZMK Studio support is in alpha. Although best efforts are being made, keeping co ZMK Studio provides runtime update functionality to ZMK powered devices, allowing users to change their keymap layers without flashing new firmware to their keyboards. Studio is still under active development, and is not yet ready for casual end user use. +## Keymap Changes + +To unlock your keyboard to allow ZMK Studio to make changes, you'll need to add a [`&studio_unlock`](../keymaps/behaviors/studio-unlock.md) binding to the keymap. + ## Building Building for ZMK Studio involves two main additional items. @@ -109,3 +113,11 @@ By default, a build with ZMK Studio enabled will only allow as many layers as ar ``` The reserved layers will be ignored during regular ZMK builds but will become available for ZMK Studio enabled builds. + +## Adding ZMK Studio Support to a Keyboard + +To allow ZMK Studio to be used with a keyboard, the keyboard will need to have a physical layout with the `keys` property defined. Relevant information can be found in: + +- The [dedicated page on physical layouts](../development/hardware-integration/physical-layouts.md), informing you how to define one +- The [new shield guide](../development/hardware-integration/new-shield.mdx), informing you how to select a physical layout once defined +- The corresponding [configuration page](../config/layout.md#physical-layout), for reference diff --git a/docs/sidebars.js b/docs/sidebars.js index 9f671471..4c278d4b 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -110,6 +110,7 @@ module.exports = { "config/displays", "config/encoders", "config/keymap", + "config/layout", "config/kscan", "config/power", "config/underglow", @@ -125,9 +126,9 @@ module.exports = { collapsed: true, items: [ "development/hardware-integration/new-shield", + "development/hardware-integration/physical-layouts", "development/hardware-integration/hardware-metadata-files", "development/hardware-integration/boards-shields-keymaps", - "development/hardware-integration/studio-setup", "development/hardware-integration/shift-registers", "development/hardware-integration/encoders", ], diff --git a/docs/static/_redirects b/docs/static/_redirects index f5e8da26..de769e94 100644 --- a/docs/static/_redirects +++ b/docs/static/_redirects @@ -17,4 +17,5 @@ /docs/development/posix-board /docs/development/local-toolchain/posix-board 301 /docs/development/pre-commit /docs/development/local-toolchain/pre-commit 301 /docs/development/tests /docs/development/local-toolchain/tests 301 -/docs/development/guides/new-behavior /docs/development/new-behavior 301 \ No newline at end of file +/docs/development/guides/new-behavior /docs/development/new-behavior 301 +/docs/development/hardware-integration/studio-setup /docs/development/hardware-integration/physical-layouts 301 From 0abc1eaf2323b1494ea566efa941b44ce00e94d2 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Thu, 10 Oct 2024 15:27:17 -0600 Subject: [PATCH 068/415] docs: Add ZMK Studio links. * Add a toplevel ZMK Studio link in our header. * Add link to the web and app releases to the feature page. --- docs/docs/features/studio.md | 6 ++++++ docs/docusaurus.config.js | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/docs/docs/features/studio.md b/docs/docs/features/studio.md index 4053d3d9..6e209a87 100644 --- a/docs/docs/features/studio.md +++ b/docs/docs/features/studio.md @@ -14,6 +14,12 @@ ZMK Studio provides runtime update functionality to ZMK powered devices, allowin To unlock your keyboard to allow ZMK Studio to make changes, you'll need to add a [`&studio_unlock`](../keymaps/behaviors/studio-unlock.md) binding to the keymap. +## Accessing ZMK Studio + +You can use ZMK Studio with Chrome/Edge at https://zmk.studio/. + +To use the native app for Linux, macOS, or Windows, download the appropriate file from the [latest release](https://github.com/zmkfirmware/zmk-studio/releases). + ## Building Building for ZMK Studio involves two main additional items. diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js index 57528240..a1ace059 100644 --- a/docs/docusaurus.config.js +++ b/docs/docusaurus.config.js @@ -62,6 +62,11 @@ module.exports = { label: "Keymap Upgrader", position: "left", }, + { + href: "https://zmk.studio/", + label: "ZMK Studio", + position: "right", + }, { href: "https://github.com/zmkfirmware/zmk", label: "GitHub", From 6cbf25f04a275cb68cddae4846d46fb66824f349 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Thu, 10 Oct 2024 15:35:10 -0600 Subject: [PATCH 069/415] docs: Update Studio status warnings to beta. Co-authored-by: Nicolas Munnich <98408764+Nick-Munnich@users.noreply.github.com> --- docs/docs/config/studio.md | 4 ++-- .../development/hardware-integration/physical-layouts.md | 4 ++-- docs/docs/development/studio-rpc-protocol.md | 4 ++-- docs/docs/features/studio.md | 4 ++-- docs/docs/keymaps/behaviors/studio-unlock.md | 6 ++++-- 5 files changed, 12 insertions(+), 10 deletions(-) diff --git a/docs/docs/config/studio.md b/docs/docs/config/studio.md index ddfb25df..a361cfcd 100644 --- a/docs/docs/config/studio.md +++ b/docs/docs/config/studio.md @@ -3,9 +3,9 @@ title: ZMK Studio Configuration sidebar_label: ZMK Studio --- -:::warning[Alpha Feature] +:::warning[Beta Feature] -ZMK Studio is still in active development and the below information is for development purposes only. For up to date information, join the [ZMK Discord](https://zmk.dev/community/discord/invite) server and discuss in `#studio-development`. +ZMK Studio is in beta. Although every effort has been made to provide a stable experience, you may still encounter issues during use. Please report any issues to [GitHub Issues](https://github.com/zmkfirmware/zmk-studio/issues). ::: diff --git a/docs/docs/development/hardware-integration/physical-layouts.md b/docs/docs/development/hardware-integration/physical-layouts.md index 873bc714..4dd58e8d 100644 --- a/docs/docs/development/hardware-integration/physical-layouts.md +++ b/docs/docs/development/hardware-integration/physical-layouts.md @@ -29,9 +29,9 @@ It is given a name, a matrix transform, and a kscan. If all of your physical lay ## (Optional) Keys Property -:::warning[Alpha Feature] +:::warning[Beta Feature] -[ZMK Studio](../../features/studio.md) support is in alpha. Although best efforts are being made, backwards compatibility during active development is not guaranteed. +ZMK Studio is in beta. Although every effort has been made to provide a stable experience, you may still encounter issues during use. Please report any issues to [GitHub Issues](https://github.com/zmkfirmware/zmk-studio/issues). ::: diff --git a/docs/docs/development/studio-rpc-protocol.md b/docs/docs/development/studio-rpc-protocol.md index 5cfafbba..8054e3cd 100644 --- a/docs/docs/development/studio-rpc-protocol.md +++ b/docs/docs/development/studio-rpc-protocol.md @@ -2,9 +2,9 @@ title: ZMK Studio RPC Protocol --- -:::warning[Alpha Feature] +:::warning[Beta Feature] -ZMK Studio is still in active development, and the below information is for development purposes only. For up to date information, join the [ZMK Discord](https://zmk.dev/community/discord/invite) server and discuss in `#studio-development`. +ZMK Studio is in beta. Although every effort has been made to provide a stable experience, you may still encounter issues during use. Please report any issues to [GitHub Issues](https://github.com/zmkfirmware/zmk-studio/issues). ::: diff --git a/docs/docs/features/studio.md b/docs/docs/features/studio.md index 6e209a87..5b17ec01 100644 --- a/docs/docs/features/studio.md +++ b/docs/docs/features/studio.md @@ -2,9 +2,9 @@ title: ZMK Studio --- -:::warning[Alpha Feature] +:::warning[Beta Feature] -ZMK Studio support is in alpha. Although best efforts are being made, keeping compatibility during active development is not guaranteed. +ZMK Studio is in beta. Although every effort has been made to provide a stable experience, you may still encounter issues during use. Please report any issues to [GitHub Issues](https://github.com/zmkfirmware/zmk-studio/issues). ::: diff --git a/docs/docs/keymaps/behaviors/studio-unlock.md b/docs/docs/keymaps/behaviors/studio-unlock.md index d6e87b83..8871e91d 100644 --- a/docs/docs/keymaps/behaviors/studio-unlock.md +++ b/docs/docs/keymaps/behaviors/studio-unlock.md @@ -3,8 +3,10 @@ title: ZMK Studio Unlock Behavior sidebar_label: ZMK Studio Unlock --- -:::warning -ZMK Studio is still in active development. This behavior is documented in preparation for its general availability. +:::warning[Beta Feature] + +ZMK Studio is in beta. Although every effort has been made to provide a stable experience, you may still encounter issues during use. Please report any issues to [GitHub Issues](https://github.com/zmkfirmware/zmk-studio/issues). + ::: ## Summary From 0adb80c02b846e9fae9b53ff71df3b1071c05573 Mon Sep 17 00:00:00 2001 From: angweekiat Date: Tue, 15 Oct 2024 07:15:45 +0800 Subject: [PATCH 070/415] fix(usb): detect USB power mode to fallback to BLE * Add tracking to see if we ever hit a configured status before suspend, so we can properly track "is connected" even when connected to a suspended/asleep host. --- app/include/zmk/usb.h | 4 +--- app/src/usb.c | 10 ++++++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/app/include/zmk/usb.h b/app/include/zmk/usb.h index 540cdd9c..a5e5089f 100644 --- a/app/include/zmk/usb.h +++ b/app/include/zmk/usb.h @@ -24,6 +24,4 @@ enum zmk_usb_conn_state zmk_usb_get_conn_state(void); static inline bool zmk_usb_is_powered(void) { return zmk_usb_get_conn_state() != ZMK_USB_CONN_NONE; } -static inline bool zmk_usb_is_hid_ready(void) { - return zmk_usb_get_conn_state() == ZMK_USB_CONN_HID; -} +bool zmk_usb_is_hid_ready(void); diff --git a/app/src/usb.c b/app/src/usb.c index cd787618..cf76341e 100644 --- a/app/src/usb.c +++ b/app/src/usb.c @@ -20,6 +20,7 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); static enum usb_dc_status_code usb_status = USB_DC_UNKNOWN; +static bool is_configured; static void raise_usb_status_changed_event(struct k_work *_work) { raise_zmk_usb_conn_state_changed( @@ -49,6 +50,10 @@ enum zmk_usb_conn_state zmk_usb_get_conn_state(void) { } } +bool zmk_usb_is_hid_ready(void) { + return zmk_usb_get_conn_state() == ZMK_USB_CONN_HID && is_configured; +} + void usb_status_cb(enum usb_dc_status_code status, const uint8_t *params) { // Start-of-frame events are too frequent and noisy to notify, and they're // not used within ZMK @@ -62,6 +67,11 @@ void usb_status_cb(enum usb_dc_status_code status, const uint8_t *params) { } #endif usb_status = status; + if (zmk_usb_get_conn_state() == ZMK_USB_CONN_HID) { + is_configured |= usb_status == USB_DC_CONFIGURED; + } else { + is_configured = false; + } k_work_submit(&usb_status_notifier_work); }; From 993a64d5b399b0398fb934a303b0cbfd7a6ea5b1 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Wed, 16 Oct 2024 10:26:15 -0600 Subject: [PATCH 071/415] docs: Better document the layer `display-name` prop. --- docs/docs/config/keymap.md | 2 +- docs/docs/keymap-example.md | 3 +++ docs/docs/keymaps/index.mdx | 3 ++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/docs/config/keymap.md b/docs/docs/config/keymap.md index bcb9e044..b20bdfe4 100644 --- a/docs/docs/config/keymap.md +++ b/docs/docs/config/keymap.md @@ -19,7 +19,7 @@ Each child node can have the following properties: | Property | Type | Description | | ----------------- | ------------- | -------------------------------------------------------------------- | -| `display-name` | string | Name for the layer on displays | +| `display-name` | string | Name for the layer in ZMK Studio and on displays | | `bindings` | phandle-array | List of [key behaviors](../keymaps/index.mdx#behaviors), one per key | | `sensor-bindings` | phandle-array | List of sensor behaviors, one per sensor | diff --git a/docs/docs/keymap-example.md b/docs/docs/keymap-example.md index 57f40762..1b5bdae5 100644 --- a/docs/docs/keymap-example.md +++ b/docs/docs/keymap-example.md @@ -3,6 +3,7 @@ compatible = "zmk,keymap"; default_layer { // Layer 0 + display-name = "Base"; // ---------------------------------------------- // | Z | M | K | // | &mo 1 | LEFT SHIFT | &mo 2 | @@ -12,6 +13,7 @@ >; }; abc { // Layer 1 + display-name = "ABC"; // ---------------------------------------------- // | A | B | C | // | &trans | &trans | &trans | @@ -21,6 +23,7 @@ >; }; xyz { // Layer 2 + display-name = "XYZ"; // ---------------------------------------------- // | X | Y | Z | // | LEFT CTRL | LEFT ALT | &trans | diff --git a/docs/docs/keymaps/index.mdx b/docs/docs/keymaps/index.mdx index 6a5c9698..bbef41ac 100644 --- a/docs/docs/keymaps/index.mdx +++ b/docs/docs/keymaps/index.mdx @@ -130,6 +130,7 @@ Each layer of your keymap will be nested under the keymap node. Here is an examp compatible = "zmk,keymap"; default_layer { // Layer 0 + display-name = "Base"; // ---------------------------------------------- // | Z | M | K | // | A | B | C | @@ -145,7 +146,7 @@ Each layer should have: 1. A `bindings` property that will be a list of [behavior bindings](behaviors/index.mdx), one for each key position for the keyboard. 1. (Optional) A `sensor-bindings` property that will be a list of behavior bindings for each sensor on the keyboard. (Currently, only encoders are supported as sensor hardware, but in the future devices like trackpoints would be supported the same way) -1. (Optional) A `display-name` property that is a string used by certain features, such as the layer status display widget. +1. (Optional) A `display-name` property that is a string used by certain features, such as ZMK Studio and the layer status display widget. ### Multiple Layers From c8841c41198186f0f104c22b97969b4ac91abe62 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Wed, 16 Oct 2024 10:17:07 -0600 Subject: [PATCH 072/415] docs: Add note about .keymap changes when using Studio --- docs/docs/features/studio.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/docs/features/studio.md b/docs/docs/features/studio.md index 5b17ec01..fb7c90cb 100644 --- a/docs/docs/features/studio.md +++ b/docs/docs/features/studio.md @@ -14,6 +14,14 @@ ZMK Studio provides runtime update functionality to ZMK powered devices, allowin To unlock your keyboard to allow ZMK Studio to make changes, you'll need to add a [`&studio_unlock`](../keymaps/behaviors/studio-unlock.md) binding to the keymap. +:::note + +Once using ZMK Studio to manage your keymap, any future changes made to the `.keymap` file for your keyboard will not be applied unless you perform a "Restore Stock Settings" action from the ZMK Studio UI. + +Generally, if you intend to use ZMK Studio, then you should not make any further changes to the `.keymap` file (with the exception of adding new empty layers to then use within ZMK Studio). + +::: + ## Accessing ZMK Studio You can use ZMK Studio with Chrome/Edge at https://zmk.studio/. From bbe4f64bb297964fdac9bd00467e334a45729d2b Mon Sep 17 00:00:00 2001 From: Alexander Krikun Date: Mon, 7 Oct 2024 02:41:21 +0400 Subject: [PATCH 073/415] feat(shields): add physical layouts and update keymap for Jorne Add physical layouts and update the keymap for Joric's Jorne. Layouts are added for all three possible transforms: - Full (with additional pinky key) - 6 column (Corne), re-uses Corne layout - 5 column (Minidox), re-uses Corne layout Keymap update includes quick-tap-ms (essential for this keymap), small guide clarifications, output selection, tri-layer and &studio_unlock. --- app/boards/shields/jorne/jorne.dtsi | 20 +++++- app/boards/shields/jorne/jorne.keymap | 42 ++++++++---- app/boards/shields/jorne/layouts/5column.dtsi | 19 ++++++ app/boards/shields/jorne/layouts/6column.dtsi | 19 ++++++ app/boards/shields/jorne/layouts/full.dtsi | 68 +++++++++++++++++++ .../shields/jorne/layouts/position_map.dtsi | 7 ++ 6 files changed, 160 insertions(+), 15 deletions(-) create mode 100644 app/boards/shields/jorne/layouts/5column.dtsi create mode 100644 app/boards/shields/jorne/layouts/6column.dtsi create mode 100644 app/boards/shields/jorne/layouts/full.dtsi create mode 100644 app/boards/shields/jorne/layouts/position_map.dtsi diff --git a/app/boards/shields/jorne/jorne.dtsi b/app/boards/shields/jorne/jorne.dtsi index e7b81e5f..483b47e4 100644 --- a/app/boards/shields/jorne/jorne.dtsi +++ b/app/boards/shields/jorne/jorne.dtsi @@ -6,11 +6,27 @@ #include +#include "layouts/full.dtsi" +#include "layouts/6column.dtsi" +#include "layouts/5column.dtsi" + +&joric_jorne_full_layout { + transform = <&default_transform>; +}; + +&foostan_corne_6col_layout { + transform = <&crkbd_transform>; +}; + +&foostan_corne_5col_layout { + transform = <&five_column_transform>; +}; + / { chosen { zephyr,display = &oled; zmk,kscan = &kscan0; - zmk,matrix-transform = &default_transform; + zmk,physical-layout = &joric_jorne_full_layout; }; default_transform: keymap_transform_0 { @@ -57,7 +73,7 @@ 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(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(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(3,3) RC(3,4) RC(3,5) RC(3,6) RC(3,7) RC(3,8) + RC(3,3) RC(3,4) RC(3,5) RC(3,6) RC(3,7) RC(3,8) >; }; diff --git a/app/boards/shields/jorne/jorne.keymap b/app/boards/shields/jorne/jorne.keymap index 56ffe617..72d4bde8 100644 --- a/app/boards/shields/jorne/jorne.keymap +++ b/app/boards/shields/jorne/jorne.keymap @@ -7,67 +7,83 @@ #include #include #include +#include #define DEF 0 #define LWR 1 #define RSE 2 #define ADJ 3 +< { quick-tap-ms = <200>; }; +&mt { quick-tap-ms = <200>; }; + / { + conditional_layers { + compatible = "zmk,conditional-layers"; + tri_layer { + if-layers = ; + then-layer = ; + }; + }; + keymap { compatible = "zmk,keymap"; default_layer { + display-name = "MAIN"; // ----------------------------------------------------------------------------------------- // | GUI | ~ | Q | W | E | R | T | | Y | U | I | O | P | [ | GUI/] | // | CTRL | A | S | D | F | G | | H | J | K | L | ; |CTRL/'| -// | LALT | Z | X | C | V | B | | N | M | , | . | / | RALT | +// | LALT | Z | X | C | V | B | | N | M | , | . | / |RALT/\| // | RSE | SPC | LWR | | LWR | BSPC | RSE | bindings = < &kp LWIN &kp GRAVE &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &kp LBKT &mt RWIN RBKT &kp LCTRL &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SEMI &mt RCTRL SQT - &kp LALT &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp BSLH - < RSE TAB &mt LSHFT SPACE < LWR RET < LWR ESC &mt RSHFT BSPC < RSE DEL + &kp LALT &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp COMMA &kp DOT &kp FSLH &mt RALT BSLH + < RSE TAB &mt LSHFT SPACE < LWR RET < LWR ESC &mt RSHFT BSPC < RSE DEL >; }; lower_layer { + display-name = "SYM"; // ----------------------------------------------------------------------------------------- // | | _ | F1 | F2 | F3 | F4 | F5 | | F6 | F7 | F8 | F9 | F10 | F11 | F12 | // | + | ! | @ | # | $ | % | | ^ | & | * | ( | ) | - | // | = | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | | -// | GUI | | SPC | | ENT | | ALT | +// | ADJ | | | | | | ADJ | bindings = < &trans &kp UNDER &kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &mt RGUI F12 &mt LCTRL PLUS &kp EXCL &kp AT &kp HASH &kp DLLR &kp PRCNT &kp CARET &kp AMPS &kp STAR &kp LPAR &kp RPAR &mt RCTRL MINUS &mt LALT EQUAL &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 &trans - < ADJ TAB &trans &trans &trans &trans < ADJ DEL + &trans &trans &trans &trans &trans &trans >; }; raise_layer { + display-name = "NUM"; // ----------------------------------------------------------------------------------------- // | | NMLK | / | 7 | 8 | 9 | - | | VOLU| HOME| PRSC| PGUP| SCLK| CLCK| | -// | CTRL | * | 4 | 5 | 6 | + | | MUT | LEFT| UP | RGHT| INS | APP | +// |CTRL/=| * | 4 | 5 | 6 | + | | MUT | LEFT| UP | RGHT| INS | APP | // | | 0 | 1 | 2 | 3 | . | | VOLD| END | DOWN| PGDN| PAUS| | // | | | ADJ | | ADJ | | | bindings = < &trans &kp KP_NUM &kp KP_SLASH &kp KP_N7 &kp KP_N8 &kp KP_N9 &kp KP_MINUS &kp C_VOL_UP &kp HOME &kp PSCRN &kp PG_UP &kp SLCK &kp CAPS &trans &mt LCTRL EQUAL &kp KP_MULTIPLY &kp KP_N4 &kp KP_N5 &kp KP_N6 &kp KP_PLUS &kp C_MUTE &kp LEFT &kp UP &kp RIGHT &kp INS &mt RCTRL K_APP &trans &kp KP_N0 &kp KP_N1 &kp KP_N2 &kp KP_N3 &kp KP_DOT &kp C_VOL_DN &kp END &kp DOWN &kp PG_DN &kp PAUSE_BREAK &trans - &trans &trans < ADJ RET < ADJ ESC &trans &trans + &trans &trans &trans &trans &trans &trans >; }; adjust_layer { + display-name = "ADJ"; // ----------------------------------------------------------------------------------------- -// | RST | BLDR | | | | | | | | | | | | BLDR | RST | +// | RST | BLDR | STU | | | | | | | | | | STU | BLDR | RST | // | BTCLR| BT0 | BT1 | BT2 | BT3 | BT4 | | BT4 | BT3 | BT2 | BT1 | BT0 | BTCLR| -// | | | | | | | | | | | | | | +// | OUT | | | | | | | | | | | | OUT | // | | | | | | | | bindings = < - &sys_reset &bootloader &none &none &none &none &none &none &none &none &none &none &bootloader &sys_reset - &bt BT_CLR &bt BT_SEL 0 &bt BT_SEL 1 &bt BT_SEL 2 &bt BT_SEL 3 &bt BT_SEL 4 &bt BT_SEL 4 &bt BT_SEL 3 &bt BT_SEL 2 &bt BT_SEL 1 &bt BT_SEL 0 &bt BT_CLR - &none &none &none &none &none &none &none &none &none &none &none &none - &trans &none &trans &trans &none &trans + &sys_reset &bootloader &studio_unlock &none &none &none &none &none &none &none &none &studio_unlock &bootloader &sys_reset + &bt BT_CLR &bt BT_SEL 0 &bt BT_SEL 1 &bt BT_SEL 2 &bt BT_SEL 3 &bt BT_SEL 4 &bt BT_SEL 4 &bt BT_SEL 3 &bt BT_SEL 2 &bt BT_SEL 1 &bt BT_SEL 0 &bt BT_CLR + &out OUT_TOG &none &none &none &none &none &none &none &none &none &none &out OUT_TOG + &trans &none &trans &trans &none &trans >; }; }; diff --git a/app/boards/shields/jorne/layouts/5column.dtsi b/app/boards/shields/jorne/layouts/5column.dtsi new file mode 100644 index 00000000..d9f0f482 --- /dev/null +++ b/app/boards/shields/jorne/layouts/5column.dtsi @@ -0,0 +1,19 @@ +#include +#include + +#include "position_map.dtsi" + +&layouts_foostan_corne_position_map { + status = "disabled"; +}; + +&layouts_joric_jorne_position_map { + joric_jorne_5col_posmap: five { + physical-layout = <&foostan_corne_5col_layout>; + positions + = <36 37 0 1 2 3 4 5 6 7 8 9 38 39> + , < 40 10 11 12 13 14 15 16 17 18 19 41 > + , < 42 20 21 22 23 24 25 26 27 28 29 43 > + , < 30 31 32 33 34 35 >; + }; +}; diff --git a/app/boards/shields/jorne/layouts/6column.dtsi b/app/boards/shields/jorne/layouts/6column.dtsi new file mode 100644 index 00000000..65d4fa85 --- /dev/null +++ b/app/boards/shields/jorne/layouts/6column.dtsi @@ -0,0 +1,19 @@ +#include +#include + +#include "position_map.dtsi" + +&layouts_foostan_corne_position_map { + status = "disabled"; +}; + +&layouts_joric_jorne_position_map { + joric_jorne_6col_posmap: six { + physical-layout = <&foostan_corne_6col_layout>; + positions + = <42 0 1 2 3 4 5 6 7 8 9 10 11 43> + , < 12 13 14 15 16 17 18 19 20 21 22 23 > + , < 24 25 26 27 28 29 30 31 32 33 34 35 > + , < 36 37 38 39 40 41 >; + }; +}; diff --git a/app/boards/shields/jorne/layouts/full.dtsi b/app/boards/shields/jorne/layouts/full.dtsi new file mode 100644 index 00000000..54512298 --- /dev/null +++ b/app/boards/shields/jorne/layouts/full.dtsi @@ -0,0 +1,68 @@ +#include + +#include "position_map.dtsi" + +/ { + joric_jorne_full_layout: joric_jorne_full_layout { + compatible = "zmk,physical-layout"; + display-name = "Full (with pinky)"; + + keys // w h x y rot rx ry + = <&key_physical_attrs 100 100 0 112 0 0 0> + , <&key_physical_attrs 100 100 100 37 0 0 0> + , <&key_physical_attrs 100 100 200 37 0 0 0> + , <&key_physical_attrs 100 100 300 12 0 0 0> + , <&key_physical_attrs 100 100 400 0 0 0 0> + , <&key_physical_attrs 100 100 500 12 0 0 0> + , <&key_physical_attrs 100 100 600 24 0 0 0> + , <&key_physical_attrs 100 100 900 24 0 0 0> + , <&key_physical_attrs 100 100 1000 12 0 0 0> + , <&key_physical_attrs 100 100 1100 0 0 0 0> + , <&key_physical_attrs 100 100 1200 12 0 0 0> + , <&key_physical_attrs 100 100 1300 37 0 0 0> + , <&key_physical_attrs 100 100 1400 37 0 0 0> + , <&key_physical_attrs 100 100 1500 112 0 0 0> + , <&key_physical_attrs 100 100 100 137 0 0 0> + , <&key_physical_attrs 100 100 200 137 0 0 0> + , <&key_physical_attrs 100 100 300 112 0 0 0> + , <&key_physical_attrs 100 100 400 100 0 0 0> + , <&key_physical_attrs 100 100 500 112 0 0 0> + , <&key_physical_attrs 100 100 600 124 0 0 0> + , <&key_physical_attrs 100 100 900 124 0 0 0> + , <&key_physical_attrs 100 100 1000 112 0 0 0> + , <&key_physical_attrs 100 100 1100 100 0 0 0> + , <&key_physical_attrs 100 100 1200 112 0 0 0> + , <&key_physical_attrs 100 100 1300 137 0 0 0> + , <&key_physical_attrs 100 100 1400 137 0 0 0> + , <&key_physical_attrs 100 100 100 237 0 0 0> + , <&key_physical_attrs 100 100 200 237 0 0 0> + , <&key_physical_attrs 100 100 300 212 0 0 0> + , <&key_physical_attrs 100 100 400 200 0 0 0> + , <&key_physical_attrs 100 100 500 212 0 0 0> + , <&key_physical_attrs 100 100 600 224 0 0 0> + , <&key_physical_attrs 100 100 900 224 0 0 0> + , <&key_physical_attrs 100 100 1000 212 0 0 0> + , <&key_physical_attrs 100 100 1100 200 0 0 0> + , <&key_physical_attrs 100 100 1200 212 0 0 0> + , <&key_physical_attrs 100 100 1300 237 0 0 0> + , <&key_physical_attrs 100 100 1400 237 0 0 0> + , <&key_physical_attrs 100 100 450 312 0 0 0> + , <&key_physical_attrs 100 100 550 312 1200 550 412> + , <&key_physical_attrs 100 150 648 283 2400 648 433> + , <&key_physical_attrs 100 150 852 283 (-2400) 952 433> + , <&key_physical_attrs 100 100 950 312 (-1200) 1050 412> + , <&key_physical_attrs 100 100 1050 312 0 0 0> + ; + }; +}; + +&layouts_joric_jorne_position_map { + joric_jorne_full_posmap: full { + physical-layout = <&joric_jorne_full_layout>; + positions + = < 0 1 2 3 4 5 6 7 8 9 10 11 12 13> + , < 14 15 16 17 18 19 20 21 22 23 24 25 > + , < 26 27 28 29 30 31 32 33 34 35 36 37 > + , < 38 39 40 41 42 43 >; + }; +}; diff --git a/app/boards/shields/jorne/layouts/position_map.dtsi b/app/boards/shields/jorne/layouts/position_map.dtsi new file mode 100644 index 00000000..6d183e0b --- /dev/null +++ b/app/boards/shields/jorne/layouts/position_map.dtsi @@ -0,0 +1,7 @@ +/ { + layouts_joric_jorne_position_map: layouts_joric_jorne_position_map { + compatible = "zmk,physical-layout-position-map"; + + complete; + }; +}; From 218a2fff8dddd664ccb9288c176246f5c85d9969 Mon Sep 17 00:00:00 2001 From: Alexander Krikun Date: Mon, 7 Oct 2024 02:58:41 +0400 Subject: [PATCH 074/415] feat(shields): add physical layouts and update keymap for Jian Add physical layouts and update the keymap for King of Hedgehogs' Jian. Layouts are added for all three possible transforms: - Full (with additional pinky key) - 6 column (Corne) - 5 column (Minidox) The layouts are added to be re-usable for the Jiran and other custom boards/shields. Keymap update includes, small guide clarifications, output selection, tri-layer and &studio_unlock. --- app/boards/shields/jian/jian.dtsi | 20 +++++- app/boards/shields/jian/jian.keymap | 37 ++++++++---- app/dts/layouts/kgoh/jian/5column.dtsi | 59 ++++++++++++++++++ app/dts/layouts/kgoh/jian/6column.dtsi | 65 ++++++++++++++++++++ app/dts/layouts/kgoh/jian/full.dtsi | 67 +++++++++++++++++++++ app/dts/layouts/kgoh/jian/position_map.dtsi | 7 +++ 6 files changed, 241 insertions(+), 14 deletions(-) create mode 100644 app/dts/layouts/kgoh/jian/5column.dtsi create mode 100644 app/dts/layouts/kgoh/jian/6column.dtsi create mode 100644 app/dts/layouts/kgoh/jian/full.dtsi create mode 100644 app/dts/layouts/kgoh/jian/position_map.dtsi diff --git a/app/boards/shields/jian/jian.dtsi b/app/boards/shields/jian/jian.dtsi index 439bf93c..4045b6b3 100644 --- a/app/boards/shields/jian/jian.dtsi +++ b/app/boards/shields/jian/jian.dtsi @@ -6,10 +6,26 @@ #include +#include +#include +#include + +&kgoh_jian_full_layout { + transform = <&default_transform>; +}; + +&kgoh_jian_6col_layout { + transform = <&crkbd_transform>; +}; + +&kgoh_jian_5col_layout { + transform = <&five_column_transform>; +}; + / { chosen { zmk,kscan = &kscan0; - zmk,matrix-transform = &default_transform; + zmk,physical-layout = &kgoh_jian_full_layout; }; default_transform: keymap_transform_0 { @@ -56,7 +72,7 @@ RC(0,1) RC(1,2) RC(0,2) RC(0,3) RC(0,4) RC(0,7) RC(0,8) RC(0,9) RC(1,9) RC(0,10) RC(1,1) RC(2,2) RC(1,3) RC(1,4) RC(0,5) RC(0,6) RC(1,7) RC(1,8) RC(2,9) RC(1,10) RC(3,2) RC(3,3) RC(2,3) RC(2,4) RC(1,5) RC(1,6) RC(2,7) RC(2,8) RC(3,8) RC(3,9) - RC(3,4) RC(2,5) RC(3,5) RC(3,6) RC(2,6) RC(3,7) + RC(3,4) RC(2,5) RC(3,5) RC(3,6) RC(2,6) RC(3,7) >; }; diff --git a/app/boards/shields/jian/jian.keymap b/app/boards/shields/jian/jian.keymap index b0235bd7..72d4bde8 100644 --- a/app/boards/shields/jian/jian.keymap +++ b/app/boards/shields/jian/jian.keymap @@ -7,6 +7,7 @@ #include #include #include +#include #define DEF 0 #define LWR 1 @@ -17,60 +18,72 @@ &mt { quick-tap-ms = <200>; }; / { + conditional_layers { + compatible = "zmk,conditional-layers"; + tri_layer { + if-layers = ; + then-layer = ; + }; + }; + keymap { compatible = "zmk,keymap"; default_layer { + display-name = "MAIN"; // ----------------------------------------------------------------------------------------- // | GUI | ~ | Q | W | E | R | T | | Y | U | I | O | P | [ | GUI/] | // | CTRL | A | S | D | F | G | | H | J | K | L | ; |CTRL/'| -// | LALT | Z | X | C | V | B | | N | M | , | . | / | RALT | +// | LALT | Z | X | C | V | B | | N | M | , | . | / |RALT/\| // | RSE | SPC | LWR | | LWR | BSPC | RSE | bindings = < &kp LWIN &kp GRAVE &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &kp LBKT &mt RWIN RBKT &kp LCTRL &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SEMI &mt RCTRL SQT &kp LALT &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp COMMA &kp DOT &kp FSLH &mt RALT BSLH - < RSE TAB &mt LSHFT SPACE < LWR RET < LWR ESC &mt RSHFT BSPC < RSE DEL + < RSE TAB &mt LSHFT SPACE < LWR RET < LWR ESC &mt RSHFT BSPC < RSE DEL >; }; lower_layer { + display-name = "SYM"; // ----------------------------------------------------------------------------------------- // | | _ | F1 | F2 | F3 | F4 | F5 | | F6 | F7 | F8 | F9 | F10 | F11 | F12 | // | + | ! | @ | # | $ | % | | ^ | & | * | ( | ) | - | // | = | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | | -// | GUI | | SPC | | ENT | | ALT | +// | ADJ | | | | | | ADJ | bindings = < &trans &kp UNDER &kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &mt RGUI F12 &mt LCTRL PLUS &kp EXCL &kp AT &kp HASH &kp DLLR &kp PRCNT &kp CARET &kp AMPS &kp STAR &kp LPAR &kp RPAR &mt RCTRL MINUS &mt LALT EQUAL &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 &trans - < ADJ TAB &trans &trans &trans &trans < ADJ DEL + &trans &trans &trans &trans &trans &trans >; }; raise_layer { + display-name = "NUM"; // ----------------------------------------------------------------------------------------- // | | NMLK | / | 7 | 8 | 9 | - | | VOLU| HOME| PRSC| PGUP| SCLK| CLCK| | -// | CTRL | * | 4 | 5 | 6 | + | | MUT | LEFT| UP | RGHT| INS | APP | +// |CTRL/=| * | 4 | 5 | 6 | + | | MUT | LEFT| UP | RGHT| INS | APP | // | | 0 | 1 | 2 | 3 | . | | VOLD| END | DOWN| PGDN| PAUS| | // | | | ADJ | | ADJ | | | bindings = < &trans &kp KP_NUM &kp KP_SLASH &kp KP_N7 &kp KP_N8 &kp KP_N9 &kp KP_MINUS &kp C_VOL_UP &kp HOME &kp PSCRN &kp PG_UP &kp SLCK &kp CAPS &trans &mt LCTRL EQUAL &kp KP_MULTIPLY &kp KP_N4 &kp KP_N5 &kp KP_N6 &kp KP_PLUS &kp C_MUTE &kp LEFT &kp UP &kp RIGHT &kp INS &mt RCTRL K_APP &trans &kp KP_N0 &kp KP_N1 &kp KP_N2 &kp KP_N3 &kp KP_DOT &kp C_VOL_DN &kp END &kp DOWN &kp PG_DN &kp PAUSE_BREAK &trans - &trans &trans < ADJ RET < ADJ ESC &trans &trans + &trans &trans &trans &trans &trans &trans >; }; adjust_layer { + display-name = "ADJ"; // ----------------------------------------------------------------------------------------- -// | RST | BLDR | | | | | | | | | | | | BLDR | RST | +// | RST | BLDR | STU | | | | | | | | | | STU | BLDR | RST | // | BTCLR| BT0 | BT1 | BT2 | BT3 | BT4 | | BT4 | BT3 | BT2 | BT1 | BT0 | BTCLR| -// | | | | | | | | | | | | | | +// | OUT | | | | | | | | | | | | OUT | // | | | | | | | | bindings = < - &sys_reset &bootloader &none &none &none &none &none &none &none &none &none &none &bootloader &sys_reset - &bt BT_CLR &bt BT_SEL 0 &bt BT_SEL 1 &bt BT_SEL 2 &bt BT_SEL 3 &bt BT_SEL 4 &bt BT_SEL 4 &bt BT_SEL 3 &bt BT_SEL 2 &bt BT_SEL 1 &bt BT_SEL 0 &bt BT_CLR - &none &none &none &none &none &none &none &none &none &none &none &none - &trans &none &trans &trans &none &trans + &sys_reset &bootloader &studio_unlock &none &none &none &none &none &none &none &none &studio_unlock &bootloader &sys_reset + &bt BT_CLR &bt BT_SEL 0 &bt BT_SEL 1 &bt BT_SEL 2 &bt BT_SEL 3 &bt BT_SEL 4 &bt BT_SEL 4 &bt BT_SEL 3 &bt BT_SEL 2 &bt BT_SEL 1 &bt BT_SEL 0 &bt BT_CLR + &out OUT_TOG &none &none &none &none &none &none &none &none &none &none &out OUT_TOG + &trans &none &trans &trans &none &trans >; }; }; diff --git a/app/dts/layouts/kgoh/jian/5column.dtsi b/app/dts/layouts/kgoh/jian/5column.dtsi new file mode 100644 index 00000000..c54d07fd --- /dev/null +++ b/app/dts/layouts/kgoh/jian/5column.dtsi @@ -0,0 +1,59 @@ +#include +#include + +/ { + kgoh_jian_5col_layout: kgoh_jian_5col_layout { + compatible = "zmk,physical-layout"; + display-name = "5 Column"; + + keys // w h x y rot rx ry + = <&key_physical_attrs 100 100 0 62 0 0 0> + , <&key_physical_attrs 100 100 100 25 0 0 0> + , <&key_physical_attrs 100 100 200 0 0 0 0> + , <&key_physical_attrs 100 100 300 25 0 0 0> + , <&key_physical_attrs 100 100 400 37 0 0 0> + , <&key_physical_attrs 100 100 800 37 0 0 0> + , <&key_physical_attrs 100 100 900 25 0 0 0> + , <&key_physical_attrs 100 100 1000 0 0 0 0> + , <&key_physical_attrs 100 100 1100 25 0 0 0> + , <&key_physical_attrs 100 100 1200 62 0 0 0> + , <&key_physical_attrs 100 100 0 162 0 0 0> + , <&key_physical_attrs 100 100 100 125 0 0 0> + , <&key_physical_attrs 100 100 200 100 0 0 0> + , <&key_physical_attrs 100 100 300 125 0 0 0> + , <&key_physical_attrs 100 100 400 137 0 0 0> + , <&key_physical_attrs 100 100 800 137 0 0 0> + , <&key_physical_attrs 100 100 900 125 0 0 0> + , <&key_physical_attrs 100 100 1000 100 0 0 0> + , <&key_physical_attrs 100 100 1100 125 0 0 0> + , <&key_physical_attrs 100 100 1200 162 0 0 0> + , <&key_physical_attrs 100 100 0 262 0 0 0> + , <&key_physical_attrs 100 100 100 225 0 0 0> + , <&key_physical_attrs 100 100 200 200 0 0 0> + , <&key_physical_attrs 100 100 300 225 0 0 0> + , <&key_physical_attrs 100 100 400 237 0 0 0> + , <&key_physical_attrs 100 100 800 237 0 0 0> + , <&key_physical_attrs 100 100 900 225 0 0 0> + , <&key_physical_attrs 100 100 1000 200 0 0 0> + , <&key_physical_attrs 100 100 1100 225 0 0 0> + , <&key_physical_attrs 100 100 1200 262 0 0 0> + , <&key_physical_attrs 100 100 300 325 0 0 0> + , <&key_physical_attrs 100 100 400 337 0 0 0> + , <&key_physical_attrs 100 100 500 350 0 0 0> + , <&key_physical_attrs 100 100 700 350 0 0 0> + , <&key_physical_attrs 100 100 800 337 0 0 0> + , <&key_physical_attrs 100 100 900 325 0 0 0> + ; + }; +}; + +&layouts_kgoh_jian_position_map { + kgoh_jian_5col_posmap: five { + physical-layout = <&kgoh_jian_5col_layout>; + positions + = <36 37 0 1 2 3 4 5 6 7 8 9 38 39> + , < 40 10 11 12 13 14 15 16 17 18 19 41 > + , < 42 20 21 22 23 24 25 26 27 28 29 43 > + , < 30 31 32 33 34 35 >; + }; +}; diff --git a/app/dts/layouts/kgoh/jian/6column.dtsi b/app/dts/layouts/kgoh/jian/6column.dtsi new file mode 100644 index 00000000..ec648846 --- /dev/null +++ b/app/dts/layouts/kgoh/jian/6column.dtsi @@ -0,0 +1,65 @@ +#include +#include + +/ { + kgoh_jian_6col_layout: kgoh_jian_6col_layout { + compatible = "zmk,physical-layout"; + display-name = "6 Column"; + + keys // w h x y rot rx ry + = <&key_physical_attrs 100 100 0 75 0 0 0> + , <&key_physical_attrs 100 100 100 62 0 0 0> + , <&key_physical_attrs 100 100 200 25 0 0 0> + , <&key_physical_attrs 100 100 300 0 0 0 0> + , <&key_physical_attrs 100 100 400 25 0 0 0> + , <&key_physical_attrs 100 100 500 37 0 0 0> + , <&key_physical_attrs 100 100 900 37 0 0 0> + , <&key_physical_attrs 100 100 1000 25 0 0 0> + , <&key_physical_attrs 100 100 1100 0 0 0 0> + , <&key_physical_attrs 100 100 1200 25 0 0 0> + , <&key_physical_attrs 100 100 1300 62 0 0 0> + , <&key_physical_attrs 100 100 1400 75 0 0 0> + , <&key_physical_attrs 100 100 0 175 0 0 0> + , <&key_physical_attrs 100 100 100 162 0 0 0> + , <&key_physical_attrs 100 100 200 125 0 0 0> + , <&key_physical_attrs 100 100 300 100 0 0 0> + , <&key_physical_attrs 100 100 400 125 0 0 0> + , <&key_physical_attrs 100 100 500 137 0 0 0> + , <&key_physical_attrs 100 100 900 137 0 0 0> + , <&key_physical_attrs 100 100 1000 125 0 0 0> + , <&key_physical_attrs 100 100 1100 100 0 0 0> + , <&key_physical_attrs 100 100 1200 125 0 0 0> + , <&key_physical_attrs 100 100 1300 162 0 0 0> + , <&key_physical_attrs 100 100 1400 175 0 0 0> + , <&key_physical_attrs 100 100 0 275 0 0 0> + , <&key_physical_attrs 100 100 100 262 0 0 0> + , <&key_physical_attrs 100 100 200 225 0 0 0> + , <&key_physical_attrs 100 100 300 200 0 0 0> + , <&key_physical_attrs 100 100 400 225 0 0 0> + , <&key_physical_attrs 100 100 500 237 0 0 0> + , <&key_physical_attrs 100 100 900 237 0 0 0> + , <&key_physical_attrs 100 100 1000 225 0 0 0> + , <&key_physical_attrs 100 100 1100 200 0 0 0> + , <&key_physical_attrs 100 100 1200 225 0 0 0> + , <&key_physical_attrs 100 100 1300 262 0 0 0> + , <&key_physical_attrs 100 100 1400 275 0 0 0> + , <&key_physical_attrs 100 100 400 325 0 0 0> + , <&key_physical_attrs 100 100 500 337 0 0 0> + , <&key_physical_attrs 100 100 600 350 0 0 0> + , <&key_physical_attrs 100 100 800 350 0 0 0> + , <&key_physical_attrs 100 100 900 337 0 0 0> + , <&key_physical_attrs 100 100 1000 325 0 0 0> + ; + }; +}; + +&layouts_kgoh_jian_position_map { + kgoh_jian_6col_posmap: six { + physical-layout = <&kgoh_jian_6col_layout>; + positions + = <42 0 1 2 3 4 5 6 7 8 9 10 11 43> + , < 12 13 14 15 16 17 18 19 20 21 22 23 > + , < 24 25 26 27 28 29 30 31 32 33 34 35 > + , < 36 37 38 39 40 41 >; + }; +}; diff --git a/app/dts/layouts/kgoh/jian/full.dtsi b/app/dts/layouts/kgoh/jian/full.dtsi new file mode 100644 index 00000000..a16903d3 --- /dev/null +++ b/app/dts/layouts/kgoh/jian/full.dtsi @@ -0,0 +1,67 @@ +#include +#include + +/ { + kgoh_jian_full_layout: kgoh_jian_full_layout { + compatible = "zmk,physical-layout"; + display-name = "Full (with pinky)"; + + keys // w h x y rot rx ry + = <&key_physical_attrs 100 100 0 150 0 0 0> + , <&key_physical_attrs 100 100 100 75 0 0 0> + , <&key_physical_attrs 100 100 200 62 0 0 0> + , <&key_physical_attrs 100 100 300 25 0 0 0> + , <&key_physical_attrs 100 100 400 0 0 0 0> + , <&key_physical_attrs 100 100 500 25 0 0 0> + , <&key_physical_attrs 100 100 600 37 0 0 0> + , <&key_physical_attrs 100 100 1000 37 0 0 0> + , <&key_physical_attrs 100 100 1100 25 0 0 0> + , <&key_physical_attrs 100 100 1200 0 0 0 0> + , <&key_physical_attrs 100 100 1300 25 0 0 0> + , <&key_physical_attrs 100 100 1400 62 0 0 0> + , <&key_physical_attrs 100 100 1500 75 0 0 0> + , <&key_physical_attrs 100 100 1600 150 0 0 0> + , <&key_physical_attrs 100 100 100 175 0 0 0> + , <&key_physical_attrs 100 100 200 162 0 0 0> + , <&key_physical_attrs 100 100 300 125 0 0 0> + , <&key_physical_attrs 100 100 400 100 0 0 0> + , <&key_physical_attrs 100 100 500 125 0 0 0> + , <&key_physical_attrs 100 100 600 137 0 0 0> + , <&key_physical_attrs 100 100 1000 137 0 0 0> + , <&key_physical_attrs 100 100 1100 125 0 0 0> + , <&key_physical_attrs 100 100 1200 100 0 0 0> + , <&key_physical_attrs 100 100 1300 125 0 0 0> + , <&key_physical_attrs 100 100 1400 162 0 0 0> + , <&key_physical_attrs 100 100 1500 175 0 0 0> + , <&key_physical_attrs 100 100 100 275 0 0 0> + , <&key_physical_attrs 100 100 200 262 0 0 0> + , <&key_physical_attrs 100 100 300 225 0 0 0> + , <&key_physical_attrs 100 100 400 200 0 0 0> + , <&key_physical_attrs 100 100 500 225 0 0 0> + , <&key_physical_attrs 100 100 600 237 0 0 0> + , <&key_physical_attrs 100 100 1000 237 0 0 0> + , <&key_physical_attrs 100 100 1100 225 0 0 0> + , <&key_physical_attrs 100 100 1200 200 0 0 0> + , <&key_physical_attrs 100 100 1300 225 0 0 0> + , <&key_physical_attrs 100 100 1400 262 0 0 0> + , <&key_physical_attrs 100 100 1500 275 0 0 0> + , <&key_physical_attrs 100 100 500 325 0 0 0> + , <&key_physical_attrs 100 100 600 337 0 0 0> + , <&key_physical_attrs 100 100 700 350 0 0 0> + , <&key_physical_attrs 100 100 900 350 0 0 0> + , <&key_physical_attrs 100 100 1000 337 0 0 0> + , <&key_physical_attrs 100 100 1100 325 0 0 0> + ; + }; +}; + +&layouts_kgoh_jian_position_map { + kgoh_jian_full_posmap: full { + physical-layout = <&kgoh_jian_full_layout>; + positions + = < 0 1 2 3 4 5 6 7 8 9 10 11 12 13> + , < 14 15 16 17 18 19 20 21 22 23 24 25 > + , < 26 27 28 29 30 31 32 33 34 35 36 37 > + , < 38 39 40 41 42 43 >; + }; +}; diff --git a/app/dts/layouts/kgoh/jian/position_map.dtsi b/app/dts/layouts/kgoh/jian/position_map.dtsi new file mode 100644 index 00000000..126e0772 --- /dev/null +++ b/app/dts/layouts/kgoh/jian/position_map.dtsi @@ -0,0 +1,7 @@ +/ { + layouts_kgoh_jian_position_map: layouts_kgoh_jian_position_map { + compatible = "zmk,physical-layout-position-map"; + + complete; + }; +}; From 11537ebee6df3c07262ba4acd668df9becd1df2f Mon Sep 17 00:00:00 2001 From: Alexander Krikun Date: Mon, 7 Oct 2024 03:59:11 +0400 Subject: [PATCH 075/415] feat(shields): add physical layouts and update keymap for Jiran Add physical layouts and update the keymap for Ladniy's Jiran. Layouts are added for all three possible transforms: - Full (with additional pinky key and number row) - Jian (with additional pinky key), re-uses Jian layout - 6 column (Corne), re-uses Jian layout Keymap update includes &studio_unlock. --- app/boards/shields/jiran/jiran.dtsi | 18 ++++- app/boards/shields/jiran/jiran.keymap | 4 +- app/boards/shields/jiran/layouts/6column.dtsi | 20 +++++ app/boards/shields/jiran/layouts/full.dtsi | 81 +++++++++++++++++++ app/boards/shields/jiran/layouts/jian.dtsi | 24 ++++++ .../shields/jiran/layouts/position_map.dtsi | 7 ++ 6 files changed, 151 insertions(+), 3 deletions(-) create mode 100644 app/boards/shields/jiran/layouts/6column.dtsi create mode 100644 app/boards/shields/jiran/layouts/full.dtsi create mode 100644 app/boards/shields/jiran/layouts/jian.dtsi create mode 100644 app/boards/shields/jiran/layouts/position_map.dtsi diff --git a/app/boards/shields/jiran/jiran.dtsi b/app/boards/shields/jiran/jiran.dtsi index 517cbe5f..d760de17 100644 --- a/app/boards/shields/jiran/jiran.dtsi +++ b/app/boards/shields/jiran/jiran.dtsi @@ -6,10 +6,26 @@ #include +#include "layouts/full.dtsi" +#include "layouts/jian.dtsi" +#include "layouts/6column.dtsi" + +&ladniy_jiran_full_layout { + transform = <&default_transform>; +}; + +&kgoh_jian_full_layout { + transform = <&jian_transform>; +}; + +&kgoh_jian_6col_layout { + transform = <&crkbd_transform>; +}; + / { chosen { zmk,kscan = &kscan0; - zmk,matrix-transform = &default_transform; + zmk,physical-layout = &ladniy_jiran_full_layout; }; default_transform: keymap_transform_0 { diff --git a/app/boards/shields/jiran/jiran.keymap b/app/boards/shields/jiran/jiran.keymap index 6dcd733c..77b943b2 100644 --- a/app/boards/shields/jiran/jiran.keymap +++ b/app/boards/shields/jiran/jiran.keymap @@ -25,11 +25,11 @@ lower_layer { bindings = < &kp GRAVE &kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10 &kp EQUAL - &kp F11 &kp TAB &bt BT_CLR &kp HOME &sys_reset &kp PG_UP &kp C_VOL_UP &kp C_VOL_UP &kp PG_UP &sys_reset &kp HOME &kp INS &kp DEL &kp F12 + &kp F11 &kp TAB &bt BT_CLR &kp HOME &sys_reset &kp PG_UP &kp C_VOL_UP &kp C_VOL_UP &kp PG_UP &studio_unlock &kp HOME &kp INS &kp DEL &kp F12 &kp LSHIFT &bt BT_NXT &kp LEFT &kp UP &kp RIGHT &kp C_MUTE &kp C_MUTE &kp LEFT &kp UP &kp RIGHT &kp PSCRN &mt RSHIFT SLCK &kp LCTRL &bt BT_PRV &kp END &kp DOWN &kp PG_DN &kp C_VOL_DN &kp C_VOL_DN &kp PG_DN &kp DOWN &kp END &kp PAUSE_BREAK &mt RCTRL KP_NUM &trans &kp SPACE &kp LALT &mt RALT RET &kp BSPC &trans >; }; }; -}; \ No newline at end of file +}; diff --git a/app/boards/shields/jiran/layouts/6column.dtsi b/app/boards/shields/jiran/layouts/6column.dtsi new file mode 100644 index 00000000..56e5d32f --- /dev/null +++ b/app/boards/shields/jiran/layouts/6column.dtsi @@ -0,0 +1,20 @@ +#include +#include + +#include "position_map.dtsi" + +&layouts_kgoh_jian_position_map { + status = "disabled"; +}; + +&layouts_ladniy_jiran_position_map { + ladniy_jiran_6col_posmap: six { + physical-layout = <&kgoh_jian_6col_layout>; + positions + = < 42 43 44 45 46 47 48 49 50 51 52 53 > + , <54 0 1 2 3 4 5 6 7 8 9 10 11 55> + , < 12 13 14 15 16 17 18 19 20 21 22 23 > + , < 24 25 26 27 28 29 30 31 32 33 34 35 > + , < 36 37 38 39 40 41 >; + }; +}; diff --git a/app/boards/shields/jiran/layouts/full.dtsi b/app/boards/shields/jiran/layouts/full.dtsi new file mode 100644 index 00000000..205c53fe --- /dev/null +++ b/app/boards/shields/jiran/layouts/full.dtsi @@ -0,0 +1,81 @@ +#include + +#include "position_map.dtsi" + +/ { + ladniy_jiran_full_layout: ladniy_jiran_full_layout { + compatible = "zmk,physical-layout"; + display-name = "Full (with pinky/numbers)"; + + keys // w h x y rot rx ry + = <&key_physical_attrs 100 100 100 75 0 0 0> + , <&key_physical_attrs 100 100 200 62 0 0 0> + , <&key_physical_attrs 100 100 300 25 0 0 0> + , <&key_physical_attrs 100 100 400 0 0 0 0> + , <&key_physical_attrs 100 100 500 25 0 0 0> + , <&key_physical_attrs 100 100 600 37 0 0 0> + , <&key_physical_attrs 100 100 1000 37 0 0 0> + , <&key_physical_attrs 100 100 1100 25 0 0 0> + , <&key_physical_attrs 100 100 1200 0 0 0 0> + , <&key_physical_attrs 100 100 1300 25 0 0 0> + , <&key_physical_attrs 100 100 1400 62 0 0 0> + , <&key_physical_attrs 100 100 1500 75 0 0 0> + , <&key_physical_attrs 100 100 0 250 0 0 0> + , <&key_physical_attrs 100 100 100 175 0 0 0> + , <&key_physical_attrs 100 100 200 162 0 0 0> + , <&key_physical_attrs 100 100 300 125 0 0 0> + , <&key_physical_attrs 100 100 400 100 0 0 0> + , <&key_physical_attrs 100 100 500 125 0 0 0> + , <&key_physical_attrs 100 100 600 137 0 0 0> + , <&key_physical_attrs 100 100 1000 137 0 0 0> + , <&key_physical_attrs 100 100 1100 125 0 0 0> + , <&key_physical_attrs 100 100 1200 100 0 0 0> + , <&key_physical_attrs 100 100 1300 125 0 0 0> + , <&key_physical_attrs 100 100 1400 162 0 0 0> + , <&key_physical_attrs 100 100 1500 175 0 0 0> + , <&key_physical_attrs 100 100 1600 250 0 0 0> + , <&key_physical_attrs 100 100 100 275 0 0 0> + , <&key_physical_attrs 100 100 200 262 0 0 0> + , <&key_physical_attrs 100 100 300 225 0 0 0> + , <&key_physical_attrs 100 100 400 200 0 0 0> + , <&key_physical_attrs 100 100 500 225 0 0 0> + , <&key_physical_attrs 100 100 600 237 0 0 0> + , <&key_physical_attrs 100 100 1000 237 0 0 0> + , <&key_physical_attrs 100 100 1100 225 0 0 0> + , <&key_physical_attrs 100 100 1200 200 0 0 0> + , <&key_physical_attrs 100 100 1300 225 0 0 0> + , <&key_physical_attrs 100 100 1400 262 0 0 0> + , <&key_physical_attrs 100 100 1500 275 0 0 0> + , <&key_physical_attrs 100 100 100 375 0 0 0> + , <&key_physical_attrs 100 100 200 362 0 0 0> + , <&key_physical_attrs 100 100 300 325 0 0 0> + , <&key_physical_attrs 100 100 400 300 0 0 0> + , <&key_physical_attrs 100 100 500 325 0 0 0> + , <&key_physical_attrs 100 100 600 337 0 0 0> + , <&key_physical_attrs 100 100 1000 337 0 0 0> + , <&key_physical_attrs 100 100 1100 325 0 0 0> + , <&key_physical_attrs 100 100 1200 300 0 0 0> + , <&key_physical_attrs 100 100 1300 325 0 0 0> + , <&key_physical_attrs 100 100 1400 362 0 0 0> + , <&key_physical_attrs 100 100 1500 375 0 0 0> + , <&key_physical_attrs 100 100 500 425 0 0 0> + , <&key_physical_attrs 100 100 600 437 0 0 0> + , <&key_physical_attrs 100 100 700 450 0 0 0> + , <&key_physical_attrs 100 100 900 450 0 0 0> + , <&key_physical_attrs 100 100 1000 437 0 0 0> + , <&key_physical_attrs 100 100 1100 425 0 0 0> + ; + }; +}; + +&layouts_ladniy_jiran_position_map { + ladniy_jiran_full_posmap: full { + physical-layout = <&ladniy_jiran_full_layout>; + positions + = < 0 1 2 3 4 5 6 7 8 9 10 11 > + , <12 13 14 15 16 17 18 19 20 21 22 23 24 25> + , < 26 27 28 29 30 31 32 33 34 35 36 37 > + , < 38 39 40 41 42 43 44 45 46 47 48 49 > + , < 50 51 52 53 54 55 >; + }; +}; diff --git a/app/boards/shields/jiran/layouts/jian.dtsi b/app/boards/shields/jiran/layouts/jian.dtsi new file mode 100644 index 00000000..0fefcfce --- /dev/null +++ b/app/boards/shields/jiran/layouts/jian.dtsi @@ -0,0 +1,24 @@ +#include +#include + +#include "position_map.dtsi" + +&kgoh_jian_full_layout { + display-name = "Jian (with pinky)"; +}; + +&layouts_kgoh_jian_position_map { + status = "disabled"; +}; + +&layouts_ladniy_jiran_position_map { + ladniy_jiran_jian_posmap: jian { + physical-layout = <&kgoh_jian_full_layout>; + positions + = < 44 45 46 47 48 49 50 51 52 53 54 55 > + , < 0 1 2 3 4 5 6 7 8 9 10 11 12 13> + , < 14 15 16 17 18 19 20 21 22 23 24 25 > + , < 26 27 28 29 30 31 32 33 34 35 36 37 > + , < 38 39 40 41 42 43 >; + }; +}; diff --git a/app/boards/shields/jiran/layouts/position_map.dtsi b/app/boards/shields/jiran/layouts/position_map.dtsi new file mode 100644 index 00000000..26f63d8e --- /dev/null +++ b/app/boards/shields/jiran/layouts/position_map.dtsi @@ -0,0 +1,7 @@ +/ { + layouts_ladniy_jiran_position_map: layouts_ladniy_jiran_position_map { + compatible = "zmk,physical-layout-position-map"; + + complete; + }; +}; From 7dfc6ab31dc3a7693efeb9f81d34fb9e3721cd8d Mon Sep 17 00:00:00 2001 From: honorless <86894501+lesshonor@users.noreply.github.com> Date: Sat, 5 Oct 2024 23:58:00 -0400 Subject: [PATCH 076/415] refactor(shields): MurphPad * Added matrix transforms and physical layouts for three typical configurations. * Tweaked default keymap to be more immediately useful for ZMK and more closely resemble the default keymaps of non-ZMK firmware. * Board-specific Kconfig settings migrated to main shield file, so they will be exposed to end-users through the setup script. * Tidied formatting and shortened overlong layer labels. * Aligned encoder configuration with current standards. * Corrected default number of RGB LEDs. * Enabled OLED by default in a less authoritarian way. --- app/boards/shields/murphpad/Kconfig.defconfig | 3 + .../shields/murphpad/boards/nice_nano.conf | 3 - .../shields/murphpad/boards/nice_nano.overlay | 2 +- .../murphpad/boards/nice_nano_v2.overlay | 2 +- .../shields/murphpad/murphpad-layout.dtsi | 156 ++++++++++++++++++ app/boards/shields/murphpad/murphpad.conf | 16 +- app/boards/shields/murphpad/murphpad.keymap | 57 +++---- app/boards/shields/murphpad/murphpad.overlay | 73 +++++++- 8 files changed, 264 insertions(+), 48 deletions(-) delete mode 100644 app/boards/shields/murphpad/boards/nice_nano.conf create mode 100644 app/boards/shields/murphpad/murphpad-layout.dtsi diff --git a/app/boards/shields/murphpad/Kconfig.defconfig b/app/boards/shields/murphpad/Kconfig.defconfig index 9d80a139..3d968584 100644 --- a/app/boards/shields/murphpad/Kconfig.defconfig +++ b/app/boards/shields/murphpad/Kconfig.defconfig @@ -6,6 +6,9 @@ if SHIELD_MURPHPAD config ZMK_KEYBOARD_NAME default "MurphPad" +config ZMK_DISPLAY + default y + if ZMK_DISPLAY config I2C diff --git a/app/boards/shields/murphpad/boards/nice_nano.conf b/app/boards/shields/murphpad/boards/nice_nano.conf deleted file mode 100644 index dda71c13..00000000 --- a/app/boards/shields/murphpad/boards/nice_nano.conf +++ /dev/null @@ -1,3 +0,0 @@ -# Uncomment both to enable underglow -CONFIG_ZMK_RGB_UNDERGLOW=y -CONFIG_WS2812_STRIP=y diff --git a/app/boards/shields/murphpad/boards/nice_nano.overlay b/app/boards/shields/murphpad/boards/nice_nano.overlay index be8ff529..21bb17b0 100644 --- a/app/boards/shields/murphpad/boards/nice_nano.overlay +++ b/app/boards/shields/murphpad/boards/nice_nano.overlay @@ -31,7 +31,7 @@ spi-max-frequency = <4000000>; /* WS2812 */ - chain-length = <10>; /* arbitrary; change at will */ + chain-length = <8>; /* number of SMD LED footprints on PCB */ spi-one-frame = <0x70>; spi-zero-frame = <0x40>; diff --git a/app/boards/shields/murphpad/boards/nice_nano_v2.overlay b/app/boards/shields/murphpad/boards/nice_nano_v2.overlay index be8ff529..21bb17b0 100644 --- a/app/boards/shields/murphpad/boards/nice_nano_v2.overlay +++ b/app/boards/shields/murphpad/boards/nice_nano_v2.overlay @@ -31,7 +31,7 @@ spi-max-frequency = <4000000>; /* WS2812 */ - chain-length = <10>; /* arbitrary; change at will */ + chain-length = <8>; /* number of SMD LED footprints on PCB */ spi-one-frame = <0x70>; spi-zero-frame = <0x40>; diff --git a/app/boards/shields/murphpad/murphpad-layout.dtsi b/app/boards/shields/murphpad/murphpad-layout.dtsi new file mode 100644 index 00000000..0ea18d8a --- /dev/null +++ b/app/boards/shields/murphpad/murphpad-layout.dtsi @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2024 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include + +/ { + chosen { + zmk,physical-layout = &all_1u_layout; + }; + + all_1u_layout: keymap_layout_0 { + compatible = "zmk,physical-layout"; + display-name = "Default"; + + transform = <&all_1u_transform>; + + keys // w h x y rot rx ry + = <&key_physical_attrs 100 100 100 0 0 0 0> + , <&key_physical_attrs 100 100 200 0 0 0 0> + , <&key_physical_attrs 100 100 300 0 0 0 0> + , <&key_physical_attrs 100 100 400 0 0 0 0> + , <&key_physical_attrs 100 100 100 100 0 0 0> + , <&key_physical_attrs 100 100 200 100 0 0 0> + , <&key_physical_attrs 100 100 300 100 0 0 0> + , <&key_physical_attrs 100 100 400 100 0 0 0> + , <&key_physical_attrs 100 100 100 200 0 0 0> + , <&key_physical_attrs 100 100 200 200 0 0 0> + , <&key_physical_attrs 100 100 300 200 0 0 0> + , <&key_physical_attrs 100 100 400 200 0 0 0> + , <&key_physical_attrs 100 100 0 275 0 0 0> + , <&key_physical_attrs 100 100 100 300 0 0 0> + , <&key_physical_attrs 100 100 200 300 0 0 0> + , <&key_physical_attrs 100 100 300 300 0 0 0> + , <&key_physical_attrs 100 100 400 300 0 0 0> + , <&key_physical_attrs 100 100 0 400 0 0 0> + , <&key_physical_attrs 100 100 100 400 0 0 0> + , <&key_physical_attrs 100 100 200 400 0 0 0> + , <&key_physical_attrs 100 100 300 400 0 0 0> + , <&key_physical_attrs 100 100 400 400 0 0 0> + , <&key_physical_attrs 100 100 0 500 0 0 0> + , <&key_physical_attrs 100 100 100 500 0 0 0> + , <&key_physical_attrs 100 100 200 500 0 0 0> + , <&key_physical_attrs 100 100 300 500 0 0 0> + , <&key_physical_attrs 100 100 400 500 0 0 0> + , <&key_physical_attrs 100 100 100 700 0 0 0> + , <&key_physical_attrs 100 100 200 700 0 0 0> + , <&key_physical_attrs 100 100 300 700 0 0 0> + ; + + }; + + right_numpad_layout: keymap_layout_1 { + compatible = "zmk,physical-layout"; + display-name = "Right Numpad"; + + transform = <&right_numpad_transform>; + + keys // w h x y rot rx ry + = <&key_physical_attrs 100 100 100 0 0 0 0> + , <&key_physical_attrs 100 100 200 0 0 0 0> + , <&key_physical_attrs 100 100 300 0 0 0 0> + , <&key_physical_attrs 100 100 400 0 0 0 0> + , <&key_physical_attrs 100 100 100 100 0 0 0> + , <&key_physical_attrs 100 100 200 100 0 0 0> + , <&key_physical_attrs 100 100 300 100 0 0 0> + , <&key_physical_attrs 100 100 400 100 0 0 0> + , <&key_physical_attrs 100 200 100 200 0 0 0> + , <&key_physical_attrs 100 100 200 200 0 0 0> + , <&key_physical_attrs 100 100 300 200 0 0 0> + , <&key_physical_attrs 100 100 400 200 0 0 0> + , <&key_physical_attrs 100 100 0 275 0 0 0> + , <&key_physical_attrs 100 100 200 300 0 0 0> + , <&key_physical_attrs 100 100 300 300 0 0 0> + , <&key_physical_attrs 100 100 400 300 0 0 0> + , <&key_physical_attrs 100 100 0 400 0 0 0> + , <&key_physical_attrs 100 200 100 400 0 0 0> + , <&key_physical_attrs 100 100 200 400 0 0 0> + , <&key_physical_attrs 100 100 300 400 0 0 0> + , <&key_physical_attrs 100 100 400 400 0 0 0> + , <&key_physical_attrs 100 100 0 500 0 0 0> + , <&key_physical_attrs 100 100 200 500 0 0 0> + , <&key_physical_attrs 200 100 300 500 0 0 0> + , <&key_physical_attrs 100 100 100 700 0 0 0> + , <&key_physical_attrs 100 100 200 700 0 0 0> + , <&key_physical_attrs 100 100 300 700 0 0 0> + ; + + }; + + left_numpad_layout: keymap_layout_2 { + compatible = "zmk,physical-layout"; + display-name = "Left Numpad"; + + transform = <&left_numpad_transform>; + + keys // w h x y rot rx ry + = <&key_physical_attrs 100 100 100 0 0 0 0> + , <&key_physical_attrs 100 100 200 0 0 0 0> + , <&key_physical_attrs 100 100 300 0 0 0 0> + , <&key_physical_attrs 100 100 400 0 0 0 0> + , <&key_physical_attrs 100 100 100 100 0 0 0> + , <&key_physical_attrs 100 100 200 100 0 0 0> + , <&key_physical_attrs 100 100 300 100 0 0 0> + , <&key_physical_attrs 100 100 400 100 0 0 0> + , <&key_physical_attrs 100 100 100 200 0 0 0> + , <&key_physical_attrs 100 100 200 200 0 0 0> + , <&key_physical_attrs 100 100 300 200 0 0 0> + , <&key_physical_attrs 100 200 400 200 0 0 0> + , <&key_physical_attrs 100 100 0 275 0 0 0> + , <&key_physical_attrs 100 100 100 300 0 0 0> + , <&key_physical_attrs 100 100 200 300 0 0 0> + , <&key_physical_attrs 100 100 300 300 0 0 0> + , <&key_physical_attrs 100 100 0 400 0 0 0> + , <&key_physical_attrs 100 100 100 400 0 0 0> + , <&key_physical_attrs 100 100 200 400 0 0 0> + , <&key_physical_attrs 100 100 300 400 0 0 0> + , <&key_physical_attrs 100 200 400 400 0 0 0> + , <&key_physical_attrs 100 100 0 500 0 0 0> + , <&key_physical_attrs 200 100 100 500 0 0 0> + , <&key_physical_attrs 100 100 300 500 0 0 0> + , <&key_physical_attrs 100 100 100 700 0 0 0> + , <&key_physical_attrs 100 100 200 700 0 0 0> + , <&key_physical_attrs 100 100 300 700 0 0 0> + ; + }; + + position_map { + compatible = "zmk,physical-layout-position-map"; + all_1u_map { + physical-layout = <&all_1u_layout>; + positions + = <11 21 23 25 22 17 18 19 20 13 14 15 8 9 10 27> + , <28 29 16 26 24> + ; + }; + + right_numpad_map { + physical-layout = <&right_numpad_layout>; + positions + = < 8 17 23 22 21 16 18 19 20 13 14 15 9 10 11 24> + , <25 26 27 28 29> + ; + }; + + left_numpad_map { + physical-layout = <&left_numpad_layout>; + positions + = <11 20 22 23 21 16 17 18 19 13 14 15 8 9 10 24> + , <25 26 27 28 29> + ; + }; + }; +}; diff --git a/app/boards/shields/murphpad/murphpad.conf b/app/boards/shields/murphpad/murphpad.conf index bdcd4255..e9236917 100644 --- a/app/boards/shields/murphpad/murphpad.conf +++ b/app/boards/shields/murphpad/murphpad.conf @@ -1,9 +1,15 @@ -# Uncomment to turn on logging, and set ZMK logging to debug output -# CONFIG_ZMK_USB_LOGGING=y +# To enable logging, use the snippet per the documentation. +# Delaying log output may help catch issues close to startup. Uncomment and adjust if necessary (default is 1000ms) +#CONFIG_LOG_PROCESS_THREAD_STARTUP_DELAY_MS=3000 -# Uncomment both to enable encoder +# Uncomment both to enable encoder(s) CONFIG_EC11=y CONFIG_EC11_TRIGGER_GLOBAL_THREAD=y -# Uncomment to enable OLED -CONFIG_ZMK_DISPLAY=y \ No newline at end of file +# Uncomment to disable OLED +#CONFIG_ZMK_DISPLAY=n + +# Uncomment both to enable underglow +# Note that this will only work if an implementation exists for your board; check under the shield folder for board-specific overlays. +#CONFIG_ZMK_RGB_UNDERGLOW=y +#CONFIG_WS2812_STRIP=y diff --git a/app/boards/shields/murphpad/murphpad.keymap b/app/boards/shields/murphpad/murphpad.keymap index fefafb00..d82670a8 100644 --- a/app/boards/shields/murphpad/murphpad.keymap +++ b/app/boards/shields/murphpad/murphpad.keymap @@ -7,16 +7,16 @@ #include #include #include +#include #include - #define TIMEOUT 300 -&encoder_1 { +&middle_left_encoder { status = "okay"; }; -&encoder_2 { +&top_right_encoder { status = "okay"; }; @@ -25,62 +25,59 @@ compatible = "zmk,combos"; combo_btclr { timeout-ms = ; - key-positions = <1 6>; + key-positions = <0 4>; bindings = <&bt BT_CLR>; }; combo_reset { timeout-ms = ; - key-positions = <1 3>; + key-positions = <0 2>; bindings = <&sys_reset>; }; combo_bootloader { timeout-ms = ; - key-positions = <1 2>; + key-positions = <0 1>; bindings = <&bootloader>; }; combo_bt_nxt { timeout-ms = ; - key-positions = <1 4>; + key-positions = <0 3>; bindings = <&bt BT_NXT>; }; }; - sensors: sensors { - compatible = "zmk,keymap-sensors"; - sensors = <&encoder_1 &encoder_2>; - triggers-per-rotation = <20>; - }; - - - keymap0: keymap { + keymap: keymap { compatible = "zmk,keymap"; default_layer { - display-name = "default layer"; + display-name = "default"; bindings = < - &bt BT_CLR &kp TAB &kp F5 &kp LC(LA(C)) &kp LG(D) - &rgb_ug RGB_TOG &kp ESC &kp KP_DIVIDE &kp KP_MULTIPLY &kp KP_MINUS - &rgb_ug RGB_EFF &kp KP_N7 &kp KP_N8 &kp KP_N9 &kp KP_PLUS - &kp C_MUTE &kp KP_N4 &kp KP_N5 &kp KP_N6 &trans - &mo 1 &kp KP_N1 &kp KP_N2 &kp KP_N3 &kp KP_ENTER - &kp BSPC &kp KP_N0 &trans &kp KP_DOT &trans + &kp F1 &kp F2 &kp F3 &kp F4 + &kp KP_NUM &kp KP_DIVIDE &kp KP_MULTIPLY &kp KP_MINUS + &kp KP_N7 &kp KP_N8 &kp KP_N9 &kp KP_PLUS + &kp C_MUTE &kp KP_N4 &kp KP_N5 &kp KP_N6 &trans + &mo 1 &kp KP_N1 &kp KP_N2 &kp KP_N3 &kp KP_ENTER + &kp BSPC &kp KP_N0 &trans &kp KP_DOT &trans + + &bt BT_CLR &rgb_ug RGB_TOG &rgb_ug RGB_EFF >; sensor-bindings = <&inc_dec_kp C_VOL_UP C_VOL_DN &inc_dec_kp PG_UP PG_DN>; }; fn_layer { - display-name = "fn layer"; + display-name = "fn"; bindings = < - &trans &trans &trans &trans &trans - &trans &kp KP_NUM &trans &trans &trans - &trans &trans &trans &trans &trans - &bt BT_CLR &trans &trans &trans &trans - &trans &trans &trans &trans &trans - &kp DEL &trans &trans &trans &trans + &out OUT_TOG &bt BT_PRV &bt BT_NXT &trans + &trans &trans &trans &trans + &rgb_ug RGB_HUD &rgb_ug RGB_SPI &rgb_ug RGB_HUI &trans + &bt BT_CLR &rgb_ug RGB_EFR &rgb_ug RGB_TOG &rgb_ug RGB_EFF &trans + &trans &rgb_ug RGB_BRD &rgb_ug RGB_SPD &rgb_ug RGB_BRI &trans + &kp DEL &rgb_ug RGB_SAD &trans &rgb_ug RGB_SAI &trans + + &trans &trans &trans >; sensor-bindings = <&inc_dec_kp PG_UP PG_DN &inc_dec_kp C_VOL_UP C_VOL_DN>; }; }; -}; \ No newline at end of file +}; diff --git a/app/boards/shields/murphpad/murphpad.overlay b/app/boards/shields/murphpad/murphpad.overlay index e2c9117f..4a45c30c 100644 --- a/app/boards/shields/murphpad/murphpad.overlay +++ b/app/boards/shields/murphpad/murphpad.overlay @@ -6,35 +6,86 @@ #include +#include "murphpad-layout.dtsi" + / { chosen { zephyr,display = &oled; - zmk,kscan = &kscan0; + zmk,kscan = &kscan; + zmk,physical-layouts = &all_1u_layout; }; - kscan0: kscan { + kscan: kscan { compatible = "zmk,kscan-gpio-matrix"; wakeup-source; diode-direction = "col2row"; row-gpios - = <&pro_micro 20 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> + = <&pro_micro 20 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> , <&pro_micro 16 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> , <&pro_micro 14 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> , <&pro_micro 15 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> - , <&pro_micro 18 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> - , <&pro_micro 19 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> + , <&pro_micro 18 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> + , <&pro_micro 19 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> ; col-gpios = <&pro_micro 9 GPIO_ACTIVE_HIGH> , <&pro_micro 6 GPIO_ACTIVE_HIGH> , <&pro_micro 5 GPIO_ACTIVE_HIGH> , <&pro_micro 4 GPIO_ACTIVE_HIGH> - , <&pro_micro 10 GPIO_ACTIVE_HIGH> + , <&pro_micro 10 GPIO_ACTIVE_HIGH> ; }; - encoder_1: encoder_1 { + all_1u_transform: keymap_transform_0 { + compatible = "zmk,matrix-transform"; + columns = <5>; + rows = <6>; + map = < + RC(0,1) RC(0,2) RC(0,3) RC(0,4) + RC(1,1) RC(1,2) RC(1,3) RC(1,4) + RC(2,1) RC(2,2) RC(2,3) RC(2,4) + RC(3,0) RC(3,1) RC(3,2) RC(3,3) RC(3,4) + RC(4,0) RC(4,1) RC(4,2) RC(4,3) RC(4,4) + RC(5,0) RC(5,1) RC(5,2) RC(5,3) RC(5,4) + + RC(0,0) RC(1,0) RC(2,0) + >; + }; + + right_numpad_transform: keymap_transform_1 { + compatible = "zmk,matrix-transform"; + columns = <5>; + rows = <6>; + map = < + RC(0,1) RC(0,2) RC(0,3) RC(0,4) + RC(1,1) RC(1,2) RC(1,3) RC(1,4) + RC(2,1) RC(2,2) RC(2,3) RC(2,4) + RC(3,0) RC(3,2) RC(3,3) RC(3,4) + RC(4,0) RC(4,1) RC(4,2) RC(4,3) RC(4,4) + RC(5,0) RC(5,2) RC(5,4) + + RC(0,0) RC(1,0) RC(2,0) + >; + }; + + left_numpad_transform: keymap_transform_2 { + compatible = "zmk,matrix-transform"; + columns = <5>; + rows = <6>; + map = < + RC(0,1) RC(0,2) RC(0,3) RC(0,4) + RC(1,1) RC(1,2) RC(1,3) RC(1,4) + RC(2,1) RC(2,2) RC(2,3) RC(2,4) + RC(3,0) RC(3,1) RC(3,2) RC(3,3) + RC(4,0) RC(4,1) RC(4,2) RC(4,3) RC(4,4) + RC(5,0) RC(5,1) RC(5,3) + + RC(0,0) RC(1,0) RC(2,0) + >; + }; + + middle_left_encoder: encoder_1: encoder_1 { compatible = "alps,ec11"; a-gpios = <&pro_micro 8 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; b-gpios = <&pro_micro 7 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; @@ -42,7 +93,7 @@ status = "disabled"; }; - encoder_2: encoder_2 { + top_right_encoder: encoder_2: encoder_2 { compatible = "alps,ec11"; a-gpios = <&pro_micro 1 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; b-gpios = <&pro_micro 0 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; @@ -50,6 +101,12 @@ status = "disabled"; }; + sensors: sensors { + compatible = "zmk,keymap-sensors"; + sensors = <&middle_left_encoder &top_right_encoder>; + triggers-per-rotation = <20>; + }; + }; &pro_micro_i2c { From 64c1e1e3ff0ad52226cc32d30a7a2a6b70924662 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Wed, 16 Oct 2024 17:49:54 -0600 Subject: [PATCH 077/415] feat: Add `studio` as a feature option in metadata * Allow boards/shields to indicate ZMK Studio support in the `features` list. --- .../hardware-integration/hardware-metadata-files.md | 1 + schema/hardware-metadata.schema.json | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/docs/development/hardware-integration/hardware-metadata-files.md b/docs/docs/development/hardware-integration/hardware-metadata-files.md index 46fad411..13f51b55 100644 --- a/docs/docs/development/hardware-integration/hardware-metadata-files.md +++ b/docs/docs/development/hardware-integration/hardware-metadata-files.md @@ -95,6 +95,7 @@ Boards and shields should document the sets of hardware features found on them u - `encoder` - Indicates the hardware contains one or more rotary encoders. - `underglow` - Indicates the hardware includes underglow LEDs. - `backlight` - Indicates the hardware includes backlight LEDs. +- `studio` - Indicates the keyboard is ready to use with [ZMK Studio](../../features/studio.md). - `pointer` (future) - Used to indicate the hardware includes one or more pointer inputs, e.g. joystick, touchpad, or trackpoint. ### Siblings diff --git a/schema/hardware-metadata.schema.json b/schema/hardware-metadata.schema.json index 9710c792..e574ca8c 100644 --- a/schema/hardware-metadata.schema.json +++ b/schema/hardware-metadata.schema.json @@ -57,7 +57,8 @@ "encoder", "underglow", "backlight", - "pointer" + "pointer", + "studio" ] } }, From 10868c72f7463184ab3b887e2d0fa06a514a4405 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Wed, 16 Oct 2024 18:00:06 -0600 Subject: [PATCH 078/415] chore: Tag studio enabled boards/shields. --- app/boards/arm/adv360pro/adv360pro.zmk.yml | 1 + app/boards/arm/bt60/bt60_v1.zmk.yml | 1 + app/boards/arm/bt60/bt60_v1_hs.zmk.yml | 1 + app/boards/arm/ckp/bt60_v2.zmk.yml | 1 + app/boards/arm/ckp/bt65_v1.zmk.yml | 1 + app/boards/arm/ckp/bt75_v1.zmk.yml | 1 + app/boards/arm/corneish_zen/corneish_zen_v1.zmk.yml | 1 + app/boards/arm/corneish_zen/corneish_zen_v2.zmk.yml | 1 + app/boards/arm/glove80/glove80.zmk.yml | 1 + app/boards/arm/nice60/nice60.zmk.yml | 1 + app/boards/shields/boardsource5x12/boardsource5x12.zmk.yml | 1 + app/boards/shields/contra/contra.zmk.yml | 1 + app/boards/shields/corne/corne.zmk.yml | 1 + app/boards/shields/cradio/cradio.zmk.yml | 1 + app/boards/shields/crbn/crbn.zmk.yml | 1 + app/boards/shields/hummingbird/hummingbird.zmk.yml | 1 + app/boards/shields/jian/jian.zmk.yml | 1 + app/boards/shields/jiran/jiran.zmk.yml | 1 + app/boards/shields/jorne/jorne.zmk.yml | 1 + app/boards/shields/kyria/kyria.zmk.yml | 1 + app/boards/shields/kyria/kyria_rev3.zmk.yml | 1 + app/boards/shields/lily58/lily58.zmk.yml | 1 + app/boards/shields/m60/m60.zmk.yml | 1 + app/boards/shields/reviung41/reviung41.zmk.yml | 1 + app/boards/shields/sofle/sofle.zmk.yml | 1 + .../shields/splitkb_aurora_corne/splitkb_aurora_corne.zmk.yml | 1 + .../shields/splitkb_aurora_lily58/splitkb_aurora_lily58.zmk.yml | 1 + .../shields/splitkb_aurora_sofle/splitkb_aurora_sofle.zmk.yml | 1 + .../shields/splitkb_aurora_sweep/splitkb_aurora_sweep.zmk.yml | 1 + app/boards/shields/zmk_uno/zmk_uno.zmk.yml | 1 + 30 files changed, 30 insertions(+) diff --git a/app/boards/arm/adv360pro/adv360pro.zmk.yml b/app/boards/arm/adv360pro/adv360pro.zmk.yml index 7d4a4b44..5e882680 100644 --- a/app/boards/arm/adv360pro/adv360pro.zmk.yml +++ b/app/boards/arm/adv360pro/adv360pro.zmk.yml @@ -8,6 +8,7 @@ features: - keys - underglow - backlight + - studio outputs: - usb - ble diff --git a/app/boards/arm/bt60/bt60_v1.zmk.yml b/app/boards/arm/bt60/bt60_v1.zmk.yml index 9909f191..4c0faf9f 100644 --- a/app/boards/arm/bt60/bt60_v1.zmk.yml +++ b/app/boards/arm/bt60/bt60_v1.zmk.yml @@ -6,6 +6,7 @@ arch: arm features: - keys - encoder + - studio outputs: - usb - ble diff --git a/app/boards/arm/bt60/bt60_v1_hs.zmk.yml b/app/boards/arm/bt60/bt60_v1_hs.zmk.yml index bc9acea4..1c61f6b2 100644 --- a/app/boards/arm/bt60/bt60_v1_hs.zmk.yml +++ b/app/boards/arm/bt60/bt60_v1_hs.zmk.yml @@ -6,6 +6,7 @@ arch: arm features: - keys - encoder + - studio outputs: - usb - ble diff --git a/app/boards/arm/ckp/bt60_v2.zmk.yml b/app/boards/arm/ckp/bt60_v2.zmk.yml index faf64205..eef36a4e 100644 --- a/app/boards/arm/ckp/bt60_v2.zmk.yml +++ b/app/boards/arm/ckp/bt60_v2.zmk.yml @@ -8,6 +8,7 @@ features: - encoder - underglow - backlight + - studio outputs: - usb - ble diff --git a/app/boards/arm/ckp/bt65_v1.zmk.yml b/app/boards/arm/ckp/bt65_v1.zmk.yml index f82253b0..b0be40bb 100644 --- a/app/boards/arm/ckp/bt65_v1.zmk.yml +++ b/app/boards/arm/ckp/bt65_v1.zmk.yml @@ -8,6 +8,7 @@ features: - encoder - underglow - backlight + - studio outputs: - usb - ble diff --git a/app/boards/arm/ckp/bt75_v1.zmk.yml b/app/boards/arm/ckp/bt75_v1.zmk.yml index 76e30047..0df500ac 100644 --- a/app/boards/arm/ckp/bt75_v1.zmk.yml +++ b/app/boards/arm/ckp/bt75_v1.zmk.yml @@ -8,6 +8,7 @@ features: - encoder - underglow - backlight + - studio outputs: - usb - ble diff --git a/app/boards/arm/corneish_zen/corneish_zen_v1.zmk.yml b/app/boards/arm/corneish_zen/corneish_zen_v1.zmk.yml index 1f6be20d..8bb5e18e 100644 --- a/app/boards/arm/corneish_zen/corneish_zen_v1.zmk.yml +++ b/app/boards/arm/corneish_zen/corneish_zen_v1.zmk.yml @@ -7,6 +7,7 @@ arch: arm features: - keys - display + - studio outputs: - usb - ble diff --git a/app/boards/arm/corneish_zen/corneish_zen_v2.zmk.yml b/app/boards/arm/corneish_zen/corneish_zen_v2.zmk.yml index 37c1cef4..26981e05 100644 --- a/app/boards/arm/corneish_zen/corneish_zen_v2.zmk.yml +++ b/app/boards/arm/corneish_zen/corneish_zen_v2.zmk.yml @@ -7,6 +7,7 @@ arch: arm features: - keys - display + - studio outputs: - usb - ble diff --git a/app/boards/arm/glove80/glove80.zmk.yml b/app/boards/arm/glove80/glove80.zmk.yml index ca70b7d6..708fa4f2 100644 --- a/app/boards/arm/glove80/glove80.zmk.yml +++ b/app/boards/arm/glove80/glove80.zmk.yml @@ -8,6 +8,7 @@ features: - keys - underglow - backlight + - studio outputs: - usb - ble diff --git a/app/boards/arm/nice60/nice60.zmk.yml b/app/boards/arm/nice60/nice60.zmk.yml index cbcc8130..2847260f 100644 --- a/app/boards/arm/nice60/nice60.zmk.yml +++ b/app/boards/arm/nice60/nice60.zmk.yml @@ -6,6 +6,7 @@ arch: arm features: - keys - underglow + - studio outputs: - usb - ble diff --git a/app/boards/shields/boardsource5x12/boardsource5x12.zmk.yml b/app/boards/shields/boardsource5x12/boardsource5x12.zmk.yml index 6987e27a..83e6b4b1 100644 --- a/app/boards/shields/boardsource5x12/boardsource5x12.zmk.yml +++ b/app/boards/shields/boardsource5x12/boardsource5x12.zmk.yml @@ -6,3 +6,4 @@ url: https://boardsource.xyz/store/5ecb802c86879c9a0c22db61 requires: [pro_micro] features: - keys + - studio diff --git a/app/boards/shields/contra/contra.zmk.yml b/app/boards/shields/contra/contra.zmk.yml index da3a9447..db289833 100644 --- a/app/boards/shields/contra/contra.zmk.yml +++ b/app/boards/shields/contra/contra.zmk.yml @@ -6,3 +6,4 @@ url: https://github.com/ai03-2725/Contra requires: [pro_micro] features: - keys + - studio diff --git a/app/boards/shields/corne/corne.zmk.yml b/app/boards/shields/corne/corne.zmk.yml index 1e8a5fbb..1afc0218 100644 --- a/app/boards/shields/corne/corne.zmk.yml +++ b/app/boards/shields/corne/corne.zmk.yml @@ -9,6 +9,7 @@ features: - keys - display - underglow + - studio siblings: - corne_left - corne_right diff --git a/app/boards/shields/cradio/cradio.zmk.yml b/app/boards/shields/cradio/cradio.zmk.yml index 76cf1ab2..5ccfef0a 100644 --- a/app/boards/shields/cradio/cradio.zmk.yml +++ b/app/boards/shields/cradio/cradio.zmk.yml @@ -7,6 +7,7 @@ requires: [pro_micro] exposes: [i2c_oled] features: - keys + - studio siblings: - cradio_left - cradio_right diff --git a/app/boards/shields/crbn/crbn.zmk.yml b/app/boards/shields/crbn/crbn.zmk.yml index baa73ea0..47c328a3 100644 --- a/app/boards/shields/crbn/crbn.zmk.yml +++ b/app/boards/shields/crbn/crbn.zmk.yml @@ -7,3 +7,4 @@ requires: [pro_micro] features: - keys - encoder + - studio diff --git a/app/boards/shields/hummingbird/hummingbird.zmk.yml b/app/boards/shields/hummingbird/hummingbird.zmk.yml index ee3a8bc8..e9508a85 100644 --- a/app/boards/shields/hummingbird/hummingbird.zmk.yml +++ b/app/boards/shields/hummingbird/hummingbird.zmk.yml @@ -6,3 +6,4 @@ url: https://github.com/PJE66/hummingbird requires: [seeed_xiao] features: - keys + - studio diff --git a/app/boards/shields/jian/jian.zmk.yml b/app/boards/shields/jian/jian.zmk.yml index 84ed69d7..094f49d7 100644 --- a/app/boards/shields/jian/jian.zmk.yml +++ b/app/boards/shields/jian/jian.zmk.yml @@ -6,6 +6,7 @@ url: https://github.com/KGOH/Jian-Info requires: [pro_micro] features: - keys + - studio siblings: - jian_left - jian_right diff --git a/app/boards/shields/jiran/jiran.zmk.yml b/app/boards/shields/jiran/jiran.zmk.yml index 1e21df7c..928042dd 100644 --- a/app/boards/shields/jiran/jiran.zmk.yml +++ b/app/boards/shields/jiran/jiran.zmk.yml @@ -6,6 +6,7 @@ url: https://github.com/Ladniy/jiran requires: [pro_micro] features: - keys + - studio siblings: - jiran_left - jiran_right diff --git a/app/boards/shields/jorne/jorne.zmk.yml b/app/boards/shields/jorne/jorne.zmk.yml index 16efe2ae..c2c63057 100644 --- a/app/boards/shields/jorne/jorne.zmk.yml +++ b/app/boards/shields/jorne/jorne.zmk.yml @@ -9,6 +9,7 @@ features: - keys - display - underglow + - studio siblings: - jorne_left - jorne_right diff --git a/app/boards/shields/kyria/kyria.zmk.yml b/app/boards/shields/kyria/kyria.zmk.yml index 95e6c3b7..ae63f5e7 100644 --- a/app/boards/shields/kyria/kyria.zmk.yml +++ b/app/boards/shields/kyria/kyria.zmk.yml @@ -10,6 +10,7 @@ features: - display - encoder - underglow + - studio siblings: - kyria_left - kyria_right diff --git a/app/boards/shields/kyria/kyria_rev3.zmk.yml b/app/boards/shields/kyria/kyria_rev3.zmk.yml index bf84c82c..9bb66e09 100644 --- a/app/boards/shields/kyria/kyria_rev3.zmk.yml +++ b/app/boards/shields/kyria/kyria_rev3.zmk.yml @@ -10,6 +10,7 @@ features: - display - encoder - underglow + - studio siblings: - kyria_rev3_left - kyria_rev3_right diff --git a/app/boards/shields/lily58/lily58.zmk.yml b/app/boards/shields/lily58/lily58.zmk.yml index 65069a13..b5be126a 100644 --- a/app/boards/shields/lily58/lily58.zmk.yml +++ b/app/boards/shields/lily58/lily58.zmk.yml @@ -8,6 +8,7 @@ exposes: [i2c_oled] features: - keys - display + - studio siblings: - lily58_left - lily58_right diff --git a/app/boards/shields/m60/m60.zmk.yml b/app/boards/shields/m60/m60.zmk.yml index 8050df45..294769df 100644 --- a/app/boards/shields/m60/m60.zmk.yml +++ b/app/boards/shields/m60/m60.zmk.yml @@ -6,3 +6,4 @@ url: https://makerdiary.com/pages/m60-mechanical-keyboard requires: [makerdiary_nrf52840_m2] features: - keys + - studio diff --git a/app/boards/shields/reviung41/reviung41.zmk.yml b/app/boards/shields/reviung41/reviung41.zmk.yml index 9783b9d9..ccbc1f41 100644 --- a/app/boards/shields/reviung41/reviung41.zmk.yml +++ b/app/boards/shields/reviung41/reviung41.zmk.yml @@ -6,3 +6,4 @@ url: https://github.com/gtips/reviung/tree/master/reviung41 requires: [pro_micro] features: - keys + - studio diff --git a/app/boards/shields/sofle/sofle.zmk.yml b/app/boards/shields/sofle/sofle.zmk.yml index 47b66d67..f08689cb 100644 --- a/app/boards/shields/sofle/sofle.zmk.yml +++ b/app/boards/shields/sofle/sofle.zmk.yml @@ -10,6 +10,7 @@ features: - display - encoder - underglow + - studio siblings: - sofle_left - sofle_right diff --git a/app/boards/shields/splitkb_aurora_corne/splitkb_aurora_corne.zmk.yml b/app/boards/shields/splitkb_aurora_corne/splitkb_aurora_corne.zmk.yml index cc141826..242837a4 100644 --- a/app/boards/shields/splitkb_aurora_corne/splitkb_aurora_corne.zmk.yml +++ b/app/boards/shields/splitkb_aurora_corne/splitkb_aurora_corne.zmk.yml @@ -7,6 +7,7 @@ requires: [pro_micro] exposes: [i2c_oled] features: - keys + - studio siblings: - splitkb_aurora_corne_left - splitkb_aurora_corne_right diff --git a/app/boards/shields/splitkb_aurora_lily58/splitkb_aurora_lily58.zmk.yml b/app/boards/shields/splitkb_aurora_lily58/splitkb_aurora_lily58.zmk.yml index 47d49a4c..2e9c5c64 100644 --- a/app/boards/shields/splitkb_aurora_lily58/splitkb_aurora_lily58.zmk.yml +++ b/app/boards/shields/splitkb_aurora_lily58/splitkb_aurora_lily58.zmk.yml @@ -7,6 +7,7 @@ requires: [pro_micro] exposes: [i2c_oled] features: - keys + - studio siblings: - splitkb_aurora_lily58_left - splitkb_aurora_lily58_right 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 index d832d3e1..0f54b4b8 100644 --- a/app/boards/shields/splitkb_aurora_sofle/splitkb_aurora_sofle.zmk.yml +++ b/app/boards/shields/splitkb_aurora_sofle/splitkb_aurora_sofle.zmk.yml @@ -10,6 +10,7 @@ features: - display - encoder - underglow + - studio siblings: - splitkb_aurora_sofle_left - splitkb_aurora_sofle_right diff --git a/app/boards/shields/splitkb_aurora_sweep/splitkb_aurora_sweep.zmk.yml b/app/boards/shields/splitkb_aurora_sweep/splitkb_aurora_sweep.zmk.yml index 97d3c53b..b0295b56 100644 --- a/app/boards/shields/splitkb_aurora_sweep/splitkb_aurora_sweep.zmk.yml +++ b/app/boards/shields/splitkb_aurora_sweep/splitkb_aurora_sweep.zmk.yml @@ -7,6 +7,7 @@ requires: [pro_micro] exposes: [i2c_oled] features: - keys + - studio siblings: - splitkb_aurora_sweep_left - splitkb_aurora_sweep_right diff --git a/app/boards/shields/zmk_uno/zmk_uno.zmk.yml b/app/boards/shields/zmk_uno/zmk_uno.zmk.yml index cee108fa..4893754e 100644 --- a/app/boards/shields/zmk_uno/zmk_uno.zmk.yml +++ b/app/boards/shields/zmk_uno/zmk_uno.zmk.yml @@ -8,3 +8,4 @@ features: - keys - encoder - display + - studio From a6d09f8c00ad6eb46ca0359d7e622264e55686d0 Mon Sep 17 00:00:00 2001 From: Nicolas Munnich Date: Thu, 17 Oct 2024 22:34:27 +0200 Subject: [PATCH 079/415] docs: Added mastodon link in footer --- docs/docusaurus.config.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js index a1ace059..801eac92 100644 --- a/docs/docusaurus.config.js +++ b/docs/docusaurus.config.js @@ -103,6 +103,10 @@ module.exports = { (process.env.URL || "https://zmk.dev") + "/community/discord/invite", }, + { + label: "Mastodon", + href: "https://fosstodon.org/@zmk", + }, { label: "Twitter", href: "https://twitter.com/ZMKFirmware", From ea1a09bf999e8f70a9d45d98e75522d5ce894953 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Thu, 17 Oct 2024 12:24:43 -0600 Subject: [PATCH 080/415] fix: Optimize layout changes by doing runtime mapping * To avoid tons of migration, extra flash writes, etc, we keep the keymaps and settings using a key position index that's tied to the stock layout, and at runtime mapping key positions as needed. --- app/include/zmk/physical_layouts.h | 9 +++++ app/src/keymap.c | 56 +++++++++++++++++++++++++-- app/src/physical_layouts.c | 62 +++++++++++++++++++++++++----- app/src/studio/keymap_subsystem.c | 45 +--------------------- 4 files changed, 115 insertions(+), 57 deletions(-) diff --git a/app/include/zmk/physical_layouts.h b/app/include/zmk/physical_layouts.h index 33004af7..4760b48d 100644 --- a/app/include/zmk/physical_layouts.h +++ b/app/include/zmk/physical_layouts.h @@ -49,3 +49,12 @@ int zmk_physical_layouts_revert_selected(void); int zmk_physical_layouts_get_position_map(uint8_t source, uint8_t dest, size_t map_size, uint32_t map[map_size]); + +/** + * @brief Get a pointer to a position map array for mapping a key position in the selected + * physical layout to the stock/chosen physical layout + * + * @retval a negative errno value in the case of errors + * @retval a positive length of the position map array that map is updated to point to. + */ +int zmk_physical_layouts_get_selected_to_stock_position_map(uint32_t const **map); \ No newline at end of file diff --git a/app/src/keymap.c b/app/src/keymap.c index 0ea64b34..6a6928dd 100644 --- a/app/src/keymap.c +++ b/app/src/keymap.c @@ -13,6 +13,7 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #include #include #include +#include #include #include #include @@ -230,7 +231,26 @@ zmk_keymap_get_layer_binding_at_idx(zmk_keymap_layer_id_t layer_id, uint8_t bind ASSERT_LAYER_VAL(layer_id, NULL) - return &zmk_keymap[layer_id][binding_idx]; + const uint32_t *pos_map; + int ret = zmk_physical_layouts_get_selected_to_stock_position_map(&pos_map); + if (ret < 0) { + LOG_WRN("Failed to get the position map, can't find the right binding to return (%d)", ret); + return NULL; + } + + if (binding_idx >= ret) { + LOG_WRN("Can't return binding for unmapped binding index %d", binding_idx); + return NULL; + } + + uint32_t mapped_idx = pos_map[binding_idx]; + + if (mapped_idx >= ZMK_KEYMAP_LEN) { + LOG_WRN("Binding index %d mapped to an invalid key position %d", binding_idx, mapped_idx); + return NULL; + } + + return &zmk_keymap[layer_id][mapped_idx]; } #if IS_ENABLED(CONFIG_ZMK_KEYMAP_SETTINGS_STORAGE) @@ -247,12 +267,37 @@ int zmk_keymap_set_layer_binding_at_idx(zmk_keymap_layer_id_t layer_id, uint8_t ASSERT_LAYER_VAL(layer_id, -EINVAL) + const uint32_t *pos_map; + int ret = zmk_physical_layouts_get_selected_to_stock_position_map(&pos_map); + if (ret < 0) { + LOG_WRN("Failed to get the mapping to determine where to set the binding (%d)", ret); + return ret; + } + + if (binding_idx >= ret) { + LOG_WRN("Unable to set binding at index %d which isn't mapped", binding_idx); + return -EINVAL; + } + + uint32_t storage_binding_idx = pos_map[binding_idx]; + + if (storage_binding_idx >= ZMK_KEYMAP_LEN) { + LOG_WRN("Can't set layer binding at unmapped/invalid index %d", binding_idx); + return -EINVAL; + } + + if (memcmp(&zmk_keymap[layer_id][storage_binding_idx], &binding, sizeof(binding)) == 0) { + LOG_DBG("Not setting, no change to layer %d at index %d (%d)", layer_id, binding_idx, + storage_binding_idx); + return 0; + } + uint8_t *pending = zmk_keymap_layer_pending_changes[layer_id]; WRITE_BIT(pending[binding_idx / 8], binding_idx % 8, 1); // TODO: Need a mutex to protect access to the keymap data? - memcpy(&zmk_keymap[layer_id][binding_idx], &binding, sizeof(binding)); + memcpy(&zmk_keymap[layer_id][storage_binding_idx], &binding, sizeof(binding)); return 0; } @@ -440,7 +485,8 @@ static int save_bindings(void) { if (pending[kp / 8] & BIT(kp % 8)) { LOG_DBG("Pending save for layer %d at key position %d", l, kp); - struct zmk_behavior_binding *binding = &zmk_keymap[l][kp]; + const struct zmk_behavior_binding *binding = + zmk_keymap_get_layer_binding_at_idx(l, kp); struct zmk_behavior_binding_setting binding_setting = { .behavior_local_id = zmk_behavior_get_local_id(binding->behavior_dev), .param1 = binding->param1, @@ -564,6 +610,7 @@ int zmk_keymap_discard_changes(void) { int zmk_keymap_reset_settings(void) { settings_delete(LAYER_ORDER_SETTINGS_KEY); + for (int l = 0; l < ZMK_KEYMAP_LAYERS_LEN; l++) { char layer_name_setting_name[14]; sprintf(layer_name_setting_name, LAYER_NAME_SETTINGS_KEY, l); @@ -600,7 +647,8 @@ int zmk_keymap_reset_settings(void) { return -ENOTSUP; } int zmk_keymap_apply_position_state(uint8_t source, zmk_keymap_layer_id_t layer_id, uint32_t position, bool pressed, int64_t timestamp) { - const struct zmk_behavior_binding *binding = &zmk_keymap[layer_id][position]; + const struct zmk_behavior_binding *binding = + zmk_keymap_get_layer_binding_at_idx(layer_id, position); struct zmk_behavior_binding_event event = { .layer = layer_id, .position = position, diff --git a/app/src/physical_layouts.c b/app/src/physical_layouts.c index 6e719d29..ceb3b151 100644 --- a/app/src/physical_layouts.c +++ b/app/src/physical_layouts.c @@ -18,6 +18,7 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); +#include #include #include #include @@ -213,6 +214,35 @@ static void zmk_physical_layouts_kscan_process_msgq(struct k_work *item) { } } +static const struct zmk_physical_layout *get_default_layout(void) { + const struct zmk_physical_layout *initial; + +#if USE_PHY_LAYOUTS && DT_HAS_CHOSEN(zmk_physical_layout) + initial = &_CONCAT(_zmk_physical_layout_, DT_CHOSEN(zmk_physical_layout)); +#else + initial = layouts[0]; +#endif + + return initial; +} + +static int get_index_of_layout(const struct zmk_physical_layout *layout) { + for (int i = 0; i < ARRAY_SIZE(layouts); i++) { + if (layouts[i] == layout) { + return i; + } + } + + return -ENODEV; +} + +static uint32_t selected_to_stock_map[ZMK_KEYMAP_LEN]; + +int zmk_physical_layouts_get_selected_to_stock_position_map(uint32_t const **map) { + *map = selected_to_stock_map; + return ZMK_KEYMAP_LEN; +} + int zmk_physical_layouts_select_layout(const struct zmk_physical_layout *dest_layout) { if (!dest_layout) { return -ENODEV; @@ -233,6 +263,15 @@ int zmk_physical_layouts_select_layout(const struct zmk_physical_layout *dest_la } } + int new_idx = get_index_of_layout(dest_layout); + int stock_idx = get_index_of_layout(get_default_layout()); + int ret = zmk_physical_layouts_get_position_map(stock_idx, new_idx, ZMK_KEYMAP_LEN, + selected_to_stock_map); + if (ret < 0) { + LOG_ERR("Failed to refresh the selected to stock mapping (%d)", ret); + return ret; + } + active = dest_layout; if (active->kscan) { @@ -284,15 +323,7 @@ static int8_t saved_selected_index = -1; #endif int zmk_physical_layouts_select_initial(void) { - const struct zmk_physical_layout *initial; - -#if USE_PHY_LAYOUTS && DT_HAS_CHOSEN(zmk_physical_layout) - initial = &_CONCAT(_zmk_physical_layout_, DT_CHOSEN(zmk_physical_layout)); -#else - initial = layouts[0]; -#endif - - int ret = zmk_physical_layouts_select_layout(initial); + int ret = zmk_physical_layouts_select_layout(get_default_layout()); return ret; } @@ -326,6 +357,14 @@ int zmk_physical_layouts_get_position_map(uint8_t source, uint8_t dest, size_t m return -EINVAL; } + if (source == dest) { + for (int i = 0; i < map_size; i++) { + map[i] = i; + } + + return 0; + } + const struct zmk_physical_layout *src_layout = layouts[source]; const struct zmk_physical_layout *dest_layout = layouts[dest]; int max_kp = dest_layout->keys_len; @@ -435,6 +474,11 @@ static int zmk_physical_layouts_init(void) { } #endif // IS_ENABLED(CONFIG_PM_DEVICE) + // Initialize a sane mapping + for (int i = 0; i < ZMK_KEYMAP_LEN; i++) { + selected_to_stock_map[i] = i; + } + return zmk_physical_layouts_select_initial(); } diff --git a/app/src/studio/keymap_subsystem.c b/app/src/studio/keymap_subsystem.c index c3a78be0..4d659def 100644 --- a/app/src/studio/keymap_subsystem.c +++ b/app/src/studio/keymap_subsystem.c @@ -323,47 +323,6 @@ zmk_studio_Response get_physical_layouts(const zmk_studio_Request *req) { return KEYMAP_RESPONSE(get_physical_layouts, resp); } -static void migrate_keymap(const uint8_t old) { - int new = zmk_physical_layouts_get_selected(); - - uint32_t new_to_old_map[ZMK_KEYMAP_LEN]; - int layout_size = - zmk_physical_layouts_get_position_map(old, new, ZMK_KEYMAP_LEN, new_to_old_map); - - if (layout_size < 0) { - return; - } - - for (int l = 0; l < ZMK_KEYMAP_LAYERS_LEN; l++) { - struct zmk_behavior_binding new_layer[ZMK_KEYMAP_LEN]; - - for (int b = 0; b < layout_size; b++) { - uint32_t old_b = new_to_old_map[b]; - - if (old_b == UINT32_MAX) { - memset(&new_layer[b], 0, sizeof(struct zmk_behavior_binding)); - continue; - } - - const struct zmk_behavior_binding *binding = - zmk_keymap_get_layer_binding_at_idx(l, old_b); - - if (!binding) { - memset(&new_layer[b], 0, sizeof(struct zmk_behavior_binding)); - continue; - } - - memcpy(&new_layer[b], binding, sizeof(struct zmk_behavior_binding)); - } - - for (int b = 0; b < layout_size; b++) { - zmk_keymap_set_layer_binding_at_idx(l, b, new_layer[b]); - } - } - - // TODO: Migrate combos? -} - zmk_studio_Response set_active_physical_layout(const zmk_studio_Request *req) { LOG_DBG(""); uint8_t index = (uint8_t)req->subsystem.keymap.request_type.set_active_physical_layout; @@ -379,9 +338,7 @@ zmk_studio_Response set_active_physical_layout(const zmk_studio_Request *req) { } int ret = zmk_physical_layouts_select(index); - if (ret >= 0) { - migrate_keymap(old); - } else { + if (ret < 0) { resp.which_result = zmk_keymap_SetActivePhysicalLayoutResponse_err_tag; resp.result.err = zmk_keymap_SetActivePhysicalLayoutErrorCode_SET_ACTIVE_PHYSICAL_LAYOUT_ERR_GENERIC; From 2e9d72ba6b1c8a2514e0c41861c29dd0fb54bb49 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 19 Oct 2024 14:47:00 +0200 Subject: [PATCH 081/415] chore(deps-dev): bump prettier from 2.8.8 to 3.3.3 in /docs (#2374) Bumps [prettier](https://github.com/prettier/prettier) from 2.8.8 to 3.3.3. - [Release notes](https://github.com/prettier/prettier/releases) - [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md) - [Commits](https://github.com/prettier/prettier/compare/2.8.8...3.3.3) --- updated-dependencies: - dependency-name: prettier dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- docs/package-lock.json | 27 +++++++++++++++++++++------ docs/package.json | 2 +- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/docs/package-lock.json b/docs/package-lock.json index cc4ebcc0..9dc652ec 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -40,7 +40,7 @@ "mustache": "^4.2.0", "null-loader": "^4.0.0", "prebuild-webpack-plugin": "^1.1.1", - "prettier": "^2.8.7", + "prettier": "^3.3.3", "string-replace-loader": "^3.1.0", "typescript": "^5.0.4", "webpack": "^5.94.0" @@ -11398,6 +11398,21 @@ "node": ">=12.0.0" } }, + "node_modules/json-schema-to-typescript/node_modules/prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -18493,16 +18508,16 @@ } }, "node_modules/prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", + "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", "dev": true, "license": "MIT", "bin": { - "prettier": "bin-prettier.js" + "prettier": "bin/prettier.cjs" }, "engines": { - "node": ">=10.13.0" + "node": ">=14" }, "funding": { "url": "https://github.com/prettier/prettier?sponsor=1" diff --git a/docs/package.json b/docs/package.json index 3f0efe58..24f00875 100644 --- a/docs/package.json +++ b/docs/package.json @@ -59,7 +59,7 @@ "mustache": "^4.2.0", "null-loader": "^4.0.0", "prebuild-webpack-plugin": "^1.1.1", - "prettier": "^2.8.7", + "prettier": "^3.3.3", "string-replace-loader": "^3.1.0", "typescript": "^5.0.4", "webpack": "^5.94.0" From 94100e307b177a4e88d10f02fc2120e66b2c7e73 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 19 Oct 2024 14:52:13 +0200 Subject: [PATCH 082/415] chore(deps-dev): bump eslint-config-prettier in /docs (#2127) Bumps [eslint-config-prettier](https://github.com/prettier/eslint-config-prettier) from 8.10.0 to 9.1.0. - [Changelog](https://github.com/prettier/eslint-config-prettier/blob/main/CHANGELOG.md) - [Commits](https://github.com/prettier/eslint-config-prettier/compare/v8.10.0...v9.1.0) --- updated-dependencies: - dependency-name: eslint-config-prettier dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- docs/package-lock.json | 8 ++++---- docs/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/package-lock.json b/docs/package-lock.json index 9dc652ec..aaa816ad 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -33,7 +33,7 @@ "@types/react-helmet": "^6.1.6", "@types/react-router-dom": "^5.1.7", "eslint": "^8.39.0", - "eslint-config-prettier": "^8.8.0", + "eslint-config-prettier": "^9.1.0", "eslint-plugin-mdx": "^3.1.5", "eslint-plugin-react": "^7.33.2", "json-schema-to-typescript": "^13.1.1", @@ -8209,9 +8209,9 @@ } }, "node_modules/eslint-config-prettier": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz", - "integrity": "sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", "dev": true, "license": "MIT", "bin": { diff --git a/docs/package.json b/docs/package.json index 24f00875..8231543a 100644 --- a/docs/package.json +++ b/docs/package.json @@ -52,7 +52,7 @@ "@types/react-helmet": "^6.1.6", "@types/react-router-dom": "^5.1.7", "eslint": "^8.39.0", - "eslint-config-prettier": "^8.8.0", + "eslint-config-prettier": "^9.1.0", "eslint-plugin-mdx": "^3.1.5", "eslint-plugin-react": "^7.33.2", "json-schema-to-typescript": "^13.1.1", From 548fe7f6bd015b07293fcdadb66013a5744195f0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 19 Oct 2024 19:39:26 +0200 Subject: [PATCH 083/415] chore(deps): bump serve-static and express in /docs (#2483) Bumps [serve-static](https://github.com/expressjs/serve-static) and [express](https://github.com/expressjs/express). These dependencies needed to be updated together. Updates `serve-static` from 1.15.0 to 1.16.2 - [Release notes](https://github.com/expressjs/serve-static/releases) - [Changelog](https://github.com/expressjs/serve-static/blob/v1.16.2/HISTORY.md) - [Commits](https://github.com/expressjs/serve-static/compare/v1.15.0...v1.16.2) Updates `express` from 4.19.2 to 4.21.0 - [Release notes](https://github.com/expressjs/express/releases) - [Changelog](https://github.com/expressjs/express/blob/4.21.0/History.md) - [Commits](https://github.com/expressjs/express/compare/4.19.2...4.21.0) --- updated-dependencies: - dependency-name: serve-static dependency-type: indirect - dependency-name: express dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- docs/package-lock.json | 142 +++++++++++++++++------------------------ 1 file changed, 57 insertions(+), 85 deletions(-) diff --git a/docs/package-lock.json b/docs/package-lock.json index aaa816ad..a13cbc47 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -5500,10 +5500,9 @@ } }, "node_modules/body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", - "license": "MIT", + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.5", @@ -5513,7 +5512,7 @@ "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", - "qs": "6.11.0", + "qs": "6.13.0", "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" @@ -5527,7 +5526,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "license": "MIT", "engines": { "node": ">= 0.8" } @@ -5536,7 +5534,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -5545,7 +5542,6 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -5556,8 +5552,7 @@ "node_modules/body-parser/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "node_modules/bonjour-service": { "version": "1.2.1", @@ -6281,7 +6276,6 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "license": "MIT", "engines": { "node": ">= 0.6" } @@ -7534,7 +7528,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "license": "MIT", "engines": { "node": ">= 0.8" } @@ -7552,7 +7545,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "license": "MIT", "engines": { "node": ">= 0.8", "npm": "1.2.8000 || >= 1.4.16" @@ -7791,8 +7783,7 @@ "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "license": "MIT" + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/electron-to-chromium": { "version": "1.5.13", @@ -7838,10 +7829,9 @@ } }, "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "license": "MIT", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "engines": { "node": ">= 0.8" } @@ -8638,7 +8628,6 @@ "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "license": "MIT", "engines": { "node": ">= 0.6" } @@ -8705,37 +8694,36 @@ } }, "node_modules/express": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", - "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", - "license": "MIT", + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", + "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.2", + "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "1.2.0", + "finalhandler": "1.3.1", "fresh": "0.5.2", "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", + "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", + "path-to-regexp": "0.1.10", "proxy-addr": "~2.0.7", - "qs": "6.11.0", + "qs": "6.13.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", + "send": "0.19.0", + "serve-static": "1.16.2", "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "~1.6.18", @@ -8774,10 +8762,9 @@ "license": "MIT" }, "node_modules/express/node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", - "license": "MIT" + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", + "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==" }, "node_modules/express/node_modules/range-parser": { "version": "1.2.1", @@ -8985,13 +8972,12 @@ } }, "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", - "license": "MIT", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", "dependencies": { "debug": "2.6.9", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "on-finished": "2.4.1", "parseurl": "~1.3.3", @@ -9006,7 +8992,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -9014,8 +8999,7 @@ "node_modules/finalhandler/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "node_modules/find-cache-dir": { "version": "4.0.0", @@ -9289,7 +9273,6 @@ "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "license": "MIT", "engines": { "node": ">= 0.6" } @@ -10285,7 +10268,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "license": "MIT", "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", @@ -13979,7 +13961,6 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "license": "MIT", "engines": { "node": ">= 0.6" } @@ -14017,10 +13998,12 @@ } }, "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", - "license": "MIT" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/merge-stream": { "version": "2.0.0", @@ -16701,7 +16684,6 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "license": "MIT", "bin": { "mime": "cli.js" }, @@ -17269,7 +17251,6 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "license": "MIT", "dependencies": { "ee-first": "1.1.1" }, @@ -18685,12 +18666,11 @@ } }, "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "license": "BSD-3-Clause", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", "dependencies": { - "side-channel": "^1.0.4" + "side-channel": "^1.0.6" }, "engines": { "node": ">=0.6" @@ -18762,7 +18742,6 @@ "version": "2.5.2", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", - "license": "MIT", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -18777,7 +18756,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "license": "MIT", "engines": { "node": ">= 0.8" } @@ -18786,7 +18764,6 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -20100,10 +20077,9 @@ } }, "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", - "license": "MIT", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", "dependencies": { "debug": "2.6.9", "depd": "2.0.0", @@ -20127,7 +20103,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -20135,20 +20110,25 @@ "node_modules/send/node_modules/debug/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } }, "node_modules/send/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/send/node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "license": "MIT", "engines": { "node": ">= 0.6" } @@ -20263,15 +20243,14 @@ } }, "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", - "license": "MIT", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", "dependencies": { - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.18.0" + "send": "0.19.0" }, "engines": { "node": ">= 0.8.0" @@ -20313,8 +20292,7 @@ "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "license": "ISC" + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, "node_modules/shallow-clone": { "version": "3.0.1", @@ -20645,7 +20623,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "license": "MIT", "engines": { "node": ">= 0.8" } @@ -21267,7 +21244,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "license": "MIT", "engines": { "node": ">=0.6" } @@ -21352,7 +21328,6 @@ "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "license": "MIT", "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" @@ -21365,7 +21340,6 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "license": "MIT", "engines": { "node": ">= 0.6" } @@ -21374,7 +21348,6 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "license": "MIT", "dependencies": { "mime-db": "1.52.0" }, @@ -21845,7 +21818,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "license": "MIT", "engines": { "node": ">= 0.8" } From b67f8bbe9fbec93a0a8fbef918efe1f96ad6a685 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 19 Oct 2024 19:52:54 +0200 Subject: [PATCH 084/415] chore(deps-dev): bump eslint-plugin-react from 7.35.0 to 7.37.1 in /docs (#2524) Bumps [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) from 7.35.0 to 7.37.1. - [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.35.0...v7.37.1) --- updated-dependencies: - dependency-name: eslint-plugin-react dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- docs/package-lock.json | 9 ++++----- docs/package.json | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/docs/package-lock.json b/docs/package-lock.json index a13cbc47..1df6c577 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -35,7 +35,7 @@ "eslint": "^8.39.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-mdx": "^3.1.5", - "eslint-plugin-react": "^7.33.2", + "eslint-plugin-react": "^7.37.1", "json-schema-to-typescript": "^13.1.1", "mustache": "^4.2.0", "null-loader": "^4.0.0", @@ -8288,11 +8288,10 @@ } }, "node_modules/eslint-plugin-react": { - "version": "7.35.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.35.0.tgz", - "integrity": "sha512-v501SSMOWv8gerHkk+IIQBkcGRGrO2nfybfj5pLxuJNFTPxxA3PSryhXTK+9pNbtkggheDdsC0E9Q8CuPk6JKA==", + "version": "7.37.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.1.tgz", + "integrity": "sha512-xwTnwDqzbDRA8uJ7BMxPs/EXRB3i8ZfnOIp8BsxEQkT0nHPp+WWceqGgo6rKb9ctNi8GJLDT4Go5HAWELa/WMg==", "dev": true, - "license": "MIT", "dependencies": { "array-includes": "^3.1.8", "array.prototype.findlast": "^1.2.5", diff --git a/docs/package.json b/docs/package.json index 8231543a..49984e31 100644 --- a/docs/package.json +++ b/docs/package.json @@ -54,7 +54,7 @@ "eslint": "^8.39.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-mdx": "^3.1.5", - "eslint-plugin-react": "^7.33.2", + "eslint-plugin-react": "^7.37.1", "json-schema-to-typescript": "^13.1.1", "mustache": "^4.2.0", "null-loader": "^4.0.0", From 7f1ee320ab638245bbdae9b1cda5d5c50e2cb16e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 19 Oct 2024 20:01:01 +0200 Subject: [PATCH 085/415] chore(deps): bump cookie and express in /docs (#2570) Bumps [cookie](https://github.com/jshttp/cookie) and [express](https://github.com/expressjs/express). These dependencies needed to be updated together. Updates `cookie` from 0.6.0 to 0.7.1 - [Release notes](https://github.com/jshttp/cookie/releases) - [Commits](https://github.com/jshttp/cookie/compare/v0.6.0...v0.7.1) Updates `express` from 4.19.2 to 4.21.1 - [Release notes](https://github.com/expressjs/express/releases) - [Changelog](https://github.com/expressjs/express/blob/4.21.1/History.md) - [Commits](https://github.com/expressjs/express/compare/4.19.2...4.21.1) --- updated-dependencies: - dependency-name: cookie dependency-type: indirect - dependency-name: express dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- docs/package-lock.json | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/docs/package-lock.json b/docs/package-lock.json index 1df6c577..3b17a9fe 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -6287,10 +6287,9 @@ "license": "MIT" }, "node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", - "license": "MIT", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", "engines": { "node": ">= 0.6" } @@ -8693,16 +8692,16 @@ } }, "node_modules/express": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", - "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==", + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", + "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.6.0", + "cookie": "0.7.1", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", From a057e4c89dfe8838ac3cfcf38ab3cf9f45115d8b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 20 Oct 2024 18:38:11 +0200 Subject: [PATCH 086/415] chore(deps-dev): bump json-schema-to-typescript from 13.1.2 to 15.0.2 in /docs (#2454) * chore(deps-dev): bump json-schema-to-typescript in /docs Bumps [json-schema-to-typescript](https://github.com/bcherny/json-schema-to-typescript) from 13.1.2 to 15.0.2. - [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] * fix: glob types missing --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Nicolas Munnich --- docs/package-lock.json | 416 ++++++++--------------------------------- docs/package.json | 5 +- 2 files changed, 76 insertions(+), 345 deletions(-) diff --git a/docs/package-lock.json b/docs/package-lock.json index 3b17a9fe..40ccefb2 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -28,6 +28,7 @@ "@docusaurus/module-type-aliases": "^3.0.0", "@docusaurus/tsconfig": "^3.0.0", "@docusaurus/types": "^3.0.0", + "@types/glob": "^8.1.0", "@types/js-yaml": "^4.0.5", "@types/react": "^18.2.29", "@types/react-helmet": "^6.1.6", @@ -36,7 +37,7 @@ "eslint-config-prettier": "^9.1.0", "eslint-plugin-mdx": "^3.1.5", "eslint-plugin-react": "^7.37.1", - "json-schema-to-typescript": "^13.1.1", + "json-schema-to-typescript": "^15.0.2", "mustache": "^4.2.0", "null-loader": "^4.0.0", "prebuild-webpack-plugin": "^1.1.1", @@ -361,6 +362,23 @@ "node": ">=6.0.0" } }, + "node_modules/@apidevtools/json-schema-ref-parser": { + "version": "11.7.2", + "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-11.7.2.tgz", + "integrity": "sha512-4gY54eEGEstClvEkGnwVkTkrx0sqwemEFG5OSRRn3tD91XH0+Q8XIkYIfo7IwEWPpJZwILb9GUXeShtplRc/eA==", + "dev": true, + "dependencies": { + "@jsdevtools/ono": "^7.1.3", + "@types/json-schema": "^7.0.15", + "js-yaml": "^4.1.0" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/philsturgeon" + } + }, "node_modules/@babel/code-frame": { "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", @@ -2344,25 +2362,6 @@ "node": ">=6.9.0" } }, - "node_modules/@bcherny/json-schema-ref-parser": { - "version": "10.0.5-fork", - "resolved": "https://registry.npmjs.org/@bcherny/json-schema-ref-parser/-/json-schema-ref-parser-10.0.5-fork.tgz", - "integrity": "sha512-E/jKbPoca1tfUPj3iSbitDZTGnq6FUFjkH6L8U2oDwSuwK1WhnnVtCG7oFOTg/DDnyoXbQYUiUiGOibHqaGVnw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jsdevtools/ono": "^7.1.3", - "@types/json-schema": "^7.0.6", - "call-me-maybe": "^1.0.1", - "js-yaml": "^4.1.0" - }, - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://github.com/sponsors/philsturgeon" - } - }, "node_modules/@braintree/sanitize-url": { "version": "6.0.4", "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-6.0.4.tgz", @@ -3385,8 +3384,7 @@ "version": "7.1.3", "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/@leichtgewicht/ip-codec": { "version": "2.0.5", @@ -4305,13 +4303,13 @@ } }, "node_modules/@types/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==", "dev": true, "license": "MIT", "dependencies": { - "@types/minimatch": "*", + "@types/minimatch": "^5.1.2", "@types/node": "*" } }, @@ -4478,13 +4476,6 @@ "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", "license": "MIT" }, - "node_modules/@types/prettier": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", - "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/prismjs": { "version": "1.26.4", "resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.26.4.tgz", @@ -5127,13 +5118,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", - "dev": true, - "license": "MIT" - }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", @@ -5707,13 +5691,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/call-me-maybe": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", - "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==", - "dev": true, - "license": "MIT" - }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -5988,23 +5965,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cli-color": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-2.0.4.tgz", - "integrity": "sha512-zlnpg0jNcibNrO7GG9IeHH7maWFeCz+Ja1wx/7tZNU5ASSSSZ+/qZciM0/LHCYxSdqv5h2sdbQ/PXYdOuetXvA==", - "dev": true, - "license": "ISC", - "dependencies": { - "d": "^1.0.1", - "es5-ext": "^0.10.64", - "es6-iterator": "^2.0.3", - "memoizee": "^0.4.15", - "timers-ext": "^0.1.7" - }, - "engines": { - "node": ">=0.10" - } - }, "node_modules/cli-table3": { "version": "0.6.5", "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", @@ -6806,20 +6766,6 @@ "cytoscape": "^3.2.0" } }, - "node_modules/d": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.2.tgz", - "integrity": "sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==", - "dev": true, - "license": "ISC", - "dependencies": { - "es5-ext": "^0.10.64", - "type": "^2.7.2" - }, - "engines": { - "node": ">=0.12" - } - }, "node_modules/d3": { "version": "7.9.0", "resolved": "https://registry.npmjs.org/d3/-/d3-7.9.0.tgz", @@ -8046,62 +7992,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es5-ext": { - "version": "0.10.64", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz", - "integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==", - "dev": true, - "hasInstallScript": true, - "license": "ISC", - "dependencies": { - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.3", - "esniff": "^2.0.1", - "next-tick": "^1.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", - "dev": true, - "license": "MIT", - "dependencies": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/es6-symbol": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.4.tgz", - "integrity": "sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==", - "dev": true, - "license": "ISC", - "dependencies": { - "d": "^1.0.2", - "ext": "^1.7.0" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/es6-weak-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", - "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", - "dev": true, - "license": "ISC", - "dependencies": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" - } - }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", @@ -8431,22 +8321,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/esniff": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz", - "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==", - "dev": true, - "license": "ISC", - "dependencies": { - "d": "^1.0.1", - "es5-ext": "^0.10.62", - "event-emitter": "^0.3.5", - "type": "^2.7.2" - }, - "engines": { - "node": ">=0.10" - } - }, "node_modules/espree": { "version": "9.6.1", "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", @@ -8642,17 +8516,6 @@ "node": ">= 0.8" } }, - "node_modules/event-emitter": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", - "dev": true, - "license": "MIT", - "dependencies": { - "d": "1", - "es5-ext": "~0.10.14" - } - }, "node_modules/eventemitter3": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", @@ -8773,16 +8636,6 @@ "node": ">= 0.6" } }, - "node_modules/ext": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", - "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", - "dev": true, - "license": "ISC", - "dependencies": { - "type": "^2.7.2" - } - }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -9387,19 +9240,6 @@ "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==", "license": "ISC" }, - "node_modules/get-stdin": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz", - "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/get-stream": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", @@ -9469,26 +9309,6 @@ "node": ">= 6" } }, - "node_modules/glob-promise": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/glob-promise/-/glob-promise-4.2.2.tgz", - "integrity": "sha512-xcUzJ8NWN5bktoTIX7eOclO1Npxd/dyVqUJxlLIDasT4C7KZyqlPIwkdJ0Ypiy3p2ZKahTjK4M9uC3sNSfNMzw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/glob": "^7.1.3" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "type": "individual", - "url": "https://github.com/sponsors/ahmadnassri" - }, - "peerDependencies": { - "glob": "^7.1.6" - } - }, "node_modules/glob-to-regexp": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", @@ -10977,13 +10797,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-promise": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", - "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", - "dev": true, - "license": "MIT" - }, "node_modules/is-reference": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.2.tgz", @@ -11350,47 +11163,70 @@ "license": "MIT" }, "node_modules/json-schema-to-typescript": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/json-schema-to-typescript/-/json-schema-to-typescript-13.1.2.tgz", - "integrity": "sha512-17G+mjx4nunvOpkPvcz7fdwUwYCEwyH8vR3Ym3rFiQ8uzAL3go+c1306Kk7iGRk8HuXBXqy+JJJmpYl0cvOllw==", + "version": "15.0.2", + "resolved": "https://registry.npmjs.org/json-schema-to-typescript/-/json-schema-to-typescript-15.0.2.tgz", + "integrity": "sha512-+cRBw+bBJ3k783mZroDIgz1pLNPB4hvj6nnbHTWwEVl0dkW8qdZ+M9jWhBb+Y0FAdHvNsXACga3lewGO8lktrw==", "dev": true, - "license": "MIT", "dependencies": { - "@bcherny/json-schema-ref-parser": "10.0.5-fork", - "@types/json-schema": "^7.0.11", - "@types/lodash": "^4.14.182", - "@types/prettier": "^2.6.1", - "cli-color": "^2.0.2", - "get-stdin": "^8.0.0", - "glob": "^7.1.6", - "glob-promise": "^4.2.2", + "@apidevtools/json-schema-ref-parser": "^11.5.5", + "@types/json-schema": "^7.0.15", + "@types/lodash": "^4.17.7", + "glob": "^10.3.12", "is-glob": "^4.0.3", + "js-yaml": "^4.1.0", "lodash": "^4.17.21", - "minimist": "^1.2.6", - "mkdirp": "^1.0.4", - "mz": "^2.7.0", - "prettier": "^2.6.2" + "minimist": "^1.2.8", + "prettier": "^3.2.5" }, "bin": { "json2ts": "dist/src/cli.js" }, "engines": { - "node": ">=12.0.0" + "node": ">=16.0.0" } }, - "node_modules/json-schema-to-typescript/node_modules/prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "node_modules/json-schema-to-typescript/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, - "bin": { - "prettier": "bin-prettier.js" + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/json-schema-to-typescript/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" }, - "engines": { - "node": ">=10.13.0" + "bin": { + "glob": "dist/esm/bin.mjs" }, "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/json-schema-to-typescript/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/json-schema-traverse": { @@ -11717,16 +11553,6 @@ "yallist": "^3.0.2" } }, - "node_modules/lru-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", - "integrity": "sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "es5-ext": "~0.10.2" - } - }, "node_modules/markdown-extensions": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/markdown-extensions/-/markdown-extensions-2.0.0.tgz", @@ -13975,26 +13801,6 @@ "node": ">= 4.0.0" } }, - "node_modules/memoizee": { - "version": "0.4.17", - "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.17.tgz", - "integrity": "sha512-DGqD7Hjpi/1or4F/aYAspXKNm5Yili0QDAFAY4QYvpqpgiY6+1jOfqpmByzjxbWd/T9mChbCArXAbDAsTm5oXA==", - "dev": true, - "license": "ISC", - "dependencies": { - "d": "^1.0.2", - "es5-ext": "^0.10.64", - "es6-weak-map": "^2.0.3", - "event-emitter": "^0.3.5", - "is-promise": "^2.2.2", - "lru-queue": "^0.1.0", - "next-tick": "^1.1.0", - "timers-ext": "^0.1.7" - }, - "engines": { - "node": ">=0.12" - } - }, "node_modules/merge-descriptors": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", @@ -16788,19 +16594,6 @@ "node": ">=16 || 14 >=14.17" } }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "license": "MIT", - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/mri": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", @@ -16848,18 +16641,6 @@ "mustache": "bin/mustache" } }, - "node_modules/mz": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, "node_modules/nanoid": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", @@ -16900,13 +16681,6 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "license": "MIT" }, - "node_modules/next-tick": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", - "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", - "dev": true, - "license": "ISC" - }, "node_modules/no-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", @@ -21156,49 +20930,12 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "license": "MIT" }, - "node_modules/thenify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", - "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "dev": true, - "license": "MIT", - "dependencies": { - "any-promise": "^1.0.0" - } - }, - "node_modules/thenify-all": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", - "dev": true, - "license": "MIT", - "dependencies": { - "thenify": ">= 3.1.0 < 4" - }, - "engines": { - "node": ">=0.8" - } - }, "node_modules/thunky": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", "license": "MIT" }, - "node_modules/timers-ext": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.8.tgz", - "integrity": "sha512-wFH7+SEAcKfJpfLPkrgMPvvwnEtj8W4IurvEyrKsDleXnKLCDw71w8jltvfLa8Rm4qQxxT4jmDBYbJG/z7qoww==", - "dev": true, - "license": "ISC", - "dependencies": { - "es5-ext": "^0.10.64", - "next-tick": "^1.1.0" - }, - "engines": { - "node": ">=0.12" - } - }, "node_modules/tiny-invariant": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", @@ -21290,13 +21027,6 @@ "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "license": "0BSD" }, - "node_modules/type": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/type/-/type-2.7.3.tgz", - "integrity": "sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==", - "dev": true, - "license": "ISC" - }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", diff --git a/docs/package.json b/docs/package.json index 49984e31..2839ffbb 100644 --- a/docs/package.json +++ b/docs/package.json @@ -45,8 +45,9 @@ }, "devDependencies": { "@docusaurus/module-type-aliases": "^3.0.0", - "@docusaurus/types": "^3.0.0", "@docusaurus/tsconfig": "^3.0.0", + "@docusaurus/types": "^3.0.0", + "@types/glob": "^8.1.0", "@types/js-yaml": "^4.0.5", "@types/react": "^18.2.29", "@types/react-helmet": "^6.1.6", @@ -55,7 +56,7 @@ "eslint-config-prettier": "^9.1.0", "eslint-plugin-mdx": "^3.1.5", "eslint-plugin-react": "^7.37.1", - "json-schema-to-typescript": "^13.1.1", + "json-schema-to-typescript": "^15.0.2", "mustache": "^4.2.0", "null-loader": "^4.0.0", "prebuild-webpack-plugin": "^1.1.1", From 7293037f189ae99b663b1bbb108327ec3684c78c Mon Sep 17 00:00:00 2001 From: KingCoinless <33333456+KingCoinless@users.noreply.github.com> Date: Sun, 20 Oct 2024 14:57:00 -0700 Subject: [PATCH 087/415] docs(codes): Android Support: Basic Controls and Input + Display (#603) * docs(codes): Android Support: Basic Controls and Input + Display --------- Co-authored-by: Nicolas Munnich <98408764+Nick-Munnich@users.noreply.github.com> --- docs/src/data/hid.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/src/data/hid.js b/docs/src/data/hid.js index 92b5021f..011f4c0d 100644 --- a/docs/src/data/hid.js +++ b/docs/src/data/hid.js @@ -5024,7 +5024,7 @@ export default [ os: { windows: false, linux: true, - android: null, + android: true, macos: null, ios: null, }, @@ -5150,7 +5150,7 @@ export default [ os: { windows: false, linux: true, - android: null, + android: false, macos: null, ios: null, }, @@ -5171,7 +5171,7 @@ export default [ os: { windows: true, linux: true, - android: null, + android: true, macos: true, ios: true, }, @@ -5192,7 +5192,7 @@ export default [ os: { windows: true, linux: true, - android: null, + android: true, macos: true, ios: true, }, @@ -5213,7 +5213,7 @@ export default [ os: { windows: false, linux: true, - android: null, + android: false, macos: null, ios: null, }, @@ -5234,7 +5234,7 @@ export default [ os: { windows: false, linux: true, - android: null, + android: false, macos: null, ios: null, }, @@ -5255,7 +5255,7 @@ export default [ os: { windows: false, linux: true, - android: null, + android: false, macos: null, ios: null, }, @@ -5276,7 +5276,7 @@ export default [ os: { windows: false, linux: true, - android: null, + android: false, macos: null, ios: null, }, @@ -6011,7 +6011,7 @@ export default [ os: { windows: false, linux: true, - android: null, + android: false, macos: null, ios: null, }, @@ -6179,7 +6179,7 @@ export default [ os: { windows: false, linux: true, - android: null, + android: false, macos: null, ios: null, }, From 8756a064d113f5369068f823ee01de69d8006c82 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 21 Oct 2024 09:01:53 +0200 Subject: [PATCH 088/415] chore(deps-dev): bump webpack from 5.94.0 to 5.95.0 in /docs (#2578) Bumps [webpack](https://github.com/webpack/webpack) from 5.94.0 to 5.95.0. - [Release notes](https://github.com/webpack/webpack/releases) - [Commits](https://github.com/webpack/webpack/compare/v5.94.0...v5.95.0) --- updated-dependencies: - dependency-name: webpack dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- docs/package-lock.json | 9 ++++----- docs/package.json | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/docs/package-lock.json b/docs/package-lock.json index 40ccefb2..b3807a5c 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -44,7 +44,7 @@ "prettier": "^3.3.3", "string-replace-loader": "^3.1.0", "typescript": "^5.0.4", - "webpack": "^5.94.0" + "webpack": "^5.95.0" } }, "node_modules/@algolia/autocomplete-core": { @@ -22055,10 +22055,9 @@ "license": "Apache-2.0" }, "node_modules/webpack": { - "version": "5.94.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.94.0.tgz", - "integrity": "sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==", - "license": "MIT", + "version": "5.95.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.95.0.tgz", + "integrity": "sha512-2t3XstrKULz41MNMBF+cJ97TyHdyQ8HCt//pqErqDvNjU9YQBnZxIHa11VXsi7F3mb5/aO2tuDxdeTPdU7xu9Q==", "dependencies": { "@types/estree": "^1.0.5", "@webassemblyjs/ast": "^1.12.1", diff --git a/docs/package.json b/docs/package.json index 2839ffbb..8897f6d2 100644 --- a/docs/package.json +++ b/docs/package.json @@ -63,6 +63,6 @@ "prettier": "^3.3.3", "string-replace-loader": "^3.1.0", "typescript": "^5.0.4", - "webpack": "^5.94.0" + "webpack": "^5.95.0" } } From 200d98f6231270d127ae009b5485b398482c1ce7 Mon Sep 17 00:00:00 2001 From: Zack Forbing Date: Mon, 21 Oct 2024 09:53:06 -0600 Subject: [PATCH 089/415] feat(shields): QAZ: added three physical layouts * added three physical layouts --------- Co-authored-by: Zack Forbing Co-authored-by: Cem Aksoylar --- app/boards/shields/qaz/qaz-layouts.dtsi | 186 ++++++++++++++++++++++++ app/boards/shields/qaz/qaz.overlay | 32 +++- 2 files changed, 214 insertions(+), 4 deletions(-) create mode 100644 app/boards/shields/qaz/qaz-layouts.dtsi diff --git a/app/boards/shields/qaz/qaz-layouts.dtsi b/app/boards/shields/qaz/qaz-layouts.dtsi new file mode 100644 index 00000000..4080d79e --- /dev/null +++ b/app/boards/shields/qaz/qaz-layouts.dtsi @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2024 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include + +/ { + split_big_bar_layout: split_big_bar_layout { + compatible = "zmk,physical-layout"; + display-name = "Split Big Bar"; + transform = <&split_big_bar_transform>; + kscan = <&kscan0>; + keys // w h x y rot rx ry + = <&key_physical_attrs 100 100 0 0 0 0 0> + , <&key_physical_attrs 100 100 100 0 0 0 0> + , <&key_physical_attrs 100 100 200 0 0 0 0> + , <&key_physical_attrs 100 100 300 0 0 0 0> + , <&key_physical_attrs 100 100 400 0 0 0 0> + , <&key_physical_attrs 100 100 500 0 0 0 0> + , <&key_physical_attrs 100 100 600 0 0 0 0> + , <&key_physical_attrs 100 100 700 0 0 0 0> + , <&key_physical_attrs 100 100 800 0 0 0 0> + , <&key_physical_attrs 125 100 900 0 0 0 0> + + , <&key_physical_attrs 125 100 0 100 0 0 0> + , <&key_physical_attrs 100 100 125 100 0 0 0> + , <&key_physical_attrs 100 100 225 100 0 0 0> + , <&key_physical_attrs 100 100 325 100 0 0 0> + , <&key_physical_attrs 100 100 425 100 0 0 0> + , <&key_physical_attrs 100 100 525 100 0 0 0> + , <&key_physical_attrs 100 100 625 100 0 0 0> + , <&key_physical_attrs 100 100 725 100 0 0 0> + , <&key_physical_attrs 100 100 825 100 0 0 0> + , <&key_physical_attrs 100 100 925 100 0 0 0> + + , <&key_physical_attrs 175 100 0 200 0 0 0> + , <&key_physical_attrs 100 100 175 200 0 0 0> + , <&key_physical_attrs 100 100 275 200 0 0 0> + , <&key_physical_attrs 100 100 375 200 0 0 0> + , <&key_physical_attrs 100 100 475 200 0 0 0> + , <&key_physical_attrs 100 100 575 200 0 0 0> + , <&key_physical_attrs 100 100 675 200 0 0 0> + , <&key_physical_attrs 100 100 775 200 0 0 0> + , <&key_physical_attrs 150 100 875 200 0 0 0> + , <&key_physical_attrs 100 100 0 300 0 0 0> + , <&key_physical_attrs 100 100 100 300 0 0 0> + , <&key_physical_attrs 325 100 200 300 0 0 0> + , <&key_physical_attrs 300 100 525 300 0 0 0> + , <&key_physical_attrs 100 100 825 300 0 0 0> + , <&key_physical_attrs 100 100 925 300 0 0 0> + ; + }; + + split_bar_layout: split_bar_layout { + compatible = "zmk,physical-layout"; + display-name = "Split Bar"; + transform = <&split_bar_transform>; + kscan = <&kscan0>; + keys // w h x y rot rx ry + = <&key_physical_attrs 100 100 0 0 0 0 0> + , <&key_physical_attrs 100 100 100 0 0 0 0> + , <&key_physical_attrs 100 100 200 0 0 0 0> + , <&key_physical_attrs 100 100 300 0 0 0 0> + , <&key_physical_attrs 100 100 400 0 0 0 0> + , <&key_physical_attrs 100 100 500 0 0 0 0> + , <&key_physical_attrs 100 100 600 0 0 0 0> + , <&key_physical_attrs 100 100 700 0 0 0 0> + , <&key_physical_attrs 100 100 800 0 0 0 0> + , <&key_physical_attrs 125 100 900 0 0 0 0> + + , <&key_physical_attrs 125 100 0 100 0 0 0> + , <&key_physical_attrs 100 100 125 100 0 0 0> + , <&key_physical_attrs 100 100 225 100 0 0 0> + , <&key_physical_attrs 100 100 325 100 0 0 0> + , <&key_physical_attrs 100 100 425 100 0 0 0> + , <&key_physical_attrs 100 100 525 100 0 0 0> + , <&key_physical_attrs 100 100 625 100 0 0 0> + , <&key_physical_attrs 100 100 725 100 0 0 0> + , <&key_physical_attrs 100 100 825 100 0 0 0> + , <&key_physical_attrs 100 100 925 100 0 0 0> + + , <&key_physical_attrs 175 100 0 200 0 0 0> + , <&key_physical_attrs 100 100 175 200 0 0 0> + , <&key_physical_attrs 100 100 275 200 0 0 0> + , <&key_physical_attrs 100 100 375 200 0 0 0> + , <&key_physical_attrs 100 100 475 200 0 0 0> + , <&key_physical_attrs 100 100 575 200 0 0 0> + , <&key_physical_attrs 100 100 675 200 0 0 0> + , <&key_physical_attrs 100 100 775 200 0 0 0> + , <&key_physical_attrs 150 100 875 200 0 0 0> + + , <&key_physical_attrs 100 100 0 300 0 0 0> + , <&key_physical_attrs 100 100 100 300 0 0 0> + , <&key_physical_attrs 100 100 200 300 0 0 0> + , <&key_physical_attrs 225 100 300 300 0 0 0> + , <&key_physical_attrs 200 100 525 300 0 0 0> + , <&key_physical_attrs 100 100 725 300 0 0 0> + , <&key_physical_attrs 100 100 825 300 0 0 0> + , <&key_physical_attrs 100 100 925 300 0 0 0> + ; + }; + + big_bar_layout: big_bar_layout { + compatible = "zmk,physical-layout"; + display-name = "Big Bar"; + transform = <&big_bar_transform>; + kscan = <&kscan0>; + keys // w h x y rot rx ry + = <&key_physical_attrs 100 100 0 0 0 0 0> + , <&key_physical_attrs 100 100 100 0 0 0 0> + , <&key_physical_attrs 100 100 200 0 0 0 0> + , <&key_physical_attrs 100 100 300 0 0 0 0> + , <&key_physical_attrs 100 100 400 0 0 0 0> + , <&key_physical_attrs 100 100 500 0 0 0 0> + , <&key_physical_attrs 100 100 600 0 0 0 0> + , <&key_physical_attrs 100 100 700 0 0 0 0> + , <&key_physical_attrs 100 100 800 0 0 0 0> + , <&key_physical_attrs 125 100 900 0 0 0 0> + + , <&key_physical_attrs 125 100 0 100 0 0 0> + , <&key_physical_attrs 100 100 125 100 0 0 0> + , <&key_physical_attrs 100 100 225 100 0 0 0> + , <&key_physical_attrs 100 100 325 100 0 0 0> + , <&key_physical_attrs 100 100 425 100 0 0 0> + , <&key_physical_attrs 100 100 525 100 0 0 0> + , <&key_physical_attrs 100 100 625 100 0 0 0> + , <&key_physical_attrs 100 100 725 100 0 0 0> + , <&key_physical_attrs 100 100 825 100 0 0 0> + , <&key_physical_attrs 100 100 925 100 0 0 0> + + , <&key_physical_attrs 175 100 0 200 0 0 0> + , <&key_physical_attrs 100 100 175 200 0 0 0> + , <&key_physical_attrs 100 100 275 200 0 0 0> + , <&key_physical_attrs 100 100 375 200 0 0 0> + , <&key_physical_attrs 100 100 475 200 0 0 0> + , <&key_physical_attrs 100 100 575 200 0 0 0> + , <&key_physical_attrs 100 100 675 200 0 0 0> + , <&key_physical_attrs 100 100 775 200 0 0 0> + , <&key_physical_attrs 150 100 875 200 0 0 0> + + , <&key_physical_attrs 100 100 0 300 0 0 0> + , <&key_physical_attrs 100 100 100 300 0 0 0> + , <&key_physical_attrs 625 100 200 300 0 0 0> + , <&key_physical_attrs 100 100 825 300 0 0 0> + , <&key_physical_attrs 100 100 925 300 0 0 0> + ; + }; + + position_map { + compatible = "zmk,physical-layout-position-map"; + + complete; + + split_big_bar_posmap { + physical-layout = <&split_big_bar_layout>; + positions + = < 0 1 2 3 4 5 6 7 8 9> + , <10 11 12 13 14 15 16 17 18 19> + , <20 21 22 23 24 25 26 27 28> + , <29 30 35 31 36 33 34 32> + ; + }; + + split_bar_posmap { + physical-layout = <&split_bar_layout>; + positions + = < 0 1 2 3 4 5 6 7 8 9> + , <10 11 12 13 14 15 16 17 18 19> + , <20 21 22 23 24 25 26 27 28> + , <29 30 31 32 34 35 36 33> + ; + }; + + big_bar_posmap { + physical-layout = <&big_bar_layout>; + positions + = < 0 1 2 3 4 5 6 7 8 9> + , <10 11 12 13 14 15 16 17 18 19> + , <20 21 22 23 24 25 26 27 28> + , <29 30 35 34 36 32 33 31> + ; + }; + }; +}; \ No newline at end of file diff --git a/app/boards/shields/qaz/qaz.overlay b/app/boards/shields/qaz/qaz.overlay index 5c76b98f..ca4a0bc1 100644 --- a/app/boards/shields/qaz/qaz.overlay +++ b/app/boards/shields/qaz/qaz.overlay @@ -1,18 +1,19 @@ /* - * Copyright (c) 2020 The ZMK Contributors + * Copyright (c) 2024 The ZMK Contributors * * SPDX-License-Identifier: MIT */ #include +#include "qaz-layouts.dtsi" / { chosen { zmk,kscan = &kscan0; - zmk,matrix-transform = &default_transform; + zmk,physical-layout = &split_bar_layout; }; - default_transform: keymap_transform_0 { + split_bar_transform: split_bar_transform { compatible = "zmk,matrix-transform"; columns = <7>; rows = <6>; @@ -24,6 +25,30 @@ >; }; + split_big_bar_transform: split_big_bar_transform { + compatible = "zmk,matrix-transform"; + columns = <7>; + rows = <6>; + map = < + RC(0,0) RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(0,5) RC(0,6) RC(4,0) RC(4,1) RC(4,2) + RC(1,0) RC(1,1) RC(1,2) RC(1,3) RC(1,4) RC(1,5) RC(1,6) RC(5,0) RC(5,1) RC(5,2) + RC(2,0) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(2,5) RC(2,6) RC(4,3) RC(5,3) + RC(3,0) RC(3,1) RC(3,2) RC(3,5) RC(3,6) RC(4,4) + >; + }; + + big_bar_transform: big_bar_transform { + compatible = "zmk,matrix-transform"; + columns = <7>; + rows = <6>; + map = < + RC(0,0) RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(0,5) RC(0,6) RC(4,0) RC(4,1) RC(4,2) + RC(1,0) RC(1,1) RC(1,2) RC(1,3) RC(1,4) RC(1,5) RC(1,6) RC(5,0) RC(5,1) RC(5,2) + RC(2,0) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(2,5) RC(2,6) RC(4,3) RC(5,3) + RC(3,0) RC(3,1) RC(3,4) RC(3,6) RC(4,4) + >; + }; + kscan0: kscan_0 { compatible = "zmk,kscan-gpio-matrix"; @@ -49,5 +74,4 @@ , <&pro_micro 3 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> ; }; - }; \ No newline at end of file From 369a009d99c797fa80894311337ca0a5a65c86f8 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Mon, 21 Oct 2024 10:08:51 -0600 Subject: [PATCH 090/415] chore(shields): Add studio feature to qaz metadata --- app/boards/shields/qaz/qaz.zmk.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/boards/shields/qaz/qaz.zmk.yml b/app/boards/shields/qaz/qaz.zmk.yml index 3305e3da..05b277db 100644 --- a/app/boards/shields/qaz/qaz.zmk.yml +++ b/app/boards/shields/qaz/qaz.zmk.yml @@ -6,3 +6,4 @@ url: https://www.cbkbd.com/product/qaz-keyboard-kit requires: [pro_micro] features: - keys + - studio From 8ed556df6203d0d9dd438db2034006edf49b6547 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Fri, 18 Oct 2024 15:32:18 -0600 Subject: [PATCH 091/415] chore(studio): Only clear settings for overridden key positions. --- app/src/keymap.c | 41 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/app/src/keymap.c b/app/src/keymap.c index 6a6928dd..cb9529cd 100644 --- a/app/src/keymap.c +++ b/app/src/keymap.c @@ -608,23 +608,58 @@ int zmk_keymap_discard_changes(void) { return ret; } +static int keymap_track_changed_bindings(const char *key, size_t len, settings_read_cb read_cb, + void *cb_arg, void *param) { + const char *next; + if (settings_name_steq(key, "l", &next) && next) { + uint8_t(*state)[ZMK_KEYMAP_LAYERS_LEN][PENDING_ARRAY_SIZE] = + (uint8_t(*)[ZMK_KEYMAP_LAYERS_LEN][PENDING_ARRAY_SIZE])param; + char *endptr; + uint8_t layer = strtoul(next, &endptr, 10); + if (*endptr != '/') { + LOG_WRN("Invalid layer number: %s with endptr %s", next, endptr); + return -EINVAL; + } + + uint8_t key_position = strtoul(endptr + 1, &endptr, 10); + + if (*endptr != '\0') { + LOG_WRN("Invalid key_position number: %s with endptr %s", next, endptr); + return -EINVAL; + } + + WRITE_BIT((*state)[layer][key_position / 8], key_position % 8, 1); + } + return 0; +} + int zmk_keymap_reset_settings(void) { settings_delete(LAYER_ORDER_SETTINGS_KEY); + uint8_t zmk_keymap_layer_changes[ZMK_KEYMAP_LAYERS_LEN][PENDING_ARRAY_SIZE]; + + settings_load_subtree_direct("keymap", keymap_track_changed_bindings, + &zmk_keymap_layer_changes); + for (int l = 0; l < ZMK_KEYMAP_LAYERS_LEN; l++) { char layer_name_setting_name[14]; sprintf(layer_name_setting_name, LAYER_NAME_SETTINGS_KEY, l); settings_delete(layer_name_setting_name); + uint8_t *changes = zmk_keymap_layer_changes[l]; + for (int k = 0; k < ZMK_KEYMAP_LEN; k++) { if (memcmp(&zmk_keymap[l][k], &zmk_stock_keymap[l][k], sizeof(struct zmk_behavior_binding_setting)) == 0) { continue; } - char setting_name[20]; - sprintf(setting_name, LAYER_BINDING_SETTINGS_KEY, l, k); - settings_delete(setting_name); + if (changes[k / 8] & BIT(k % 8)) { + LOG_WRN("CLEAR %d on %d layer", k, l); + char setting_name[20]; + sprintf(setting_name, LAYER_BINDING_SETTINGS_KEY, l, k); + settings_delete(setting_name); + } } } From 4c47d67e635118336d1fac442d0a8263fee8ae6e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 23 Oct 2024 01:39:19 +0200 Subject: [PATCH 092/415] chore(deps-dev): bump typescript from 5.5.4 to 5.6.3 in /docs (#2581) Bumps [typescript](https://github.com/microsoft/TypeScript) from 5.5.4 to 5.6.3. - [Release notes](https://github.com/microsoft/TypeScript/releases) - [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release.yml) - [Commits](https://github.com/microsoft/TypeScript/compare/v5.5.4...v5.6.3) --- updated-dependencies: - dependency-name: typescript dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- docs/package-lock.json | 9 ++++----- docs/package.json | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/docs/package-lock.json b/docs/package-lock.json index b3807a5c..1c33fbf8 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -43,7 +43,7 @@ "prebuild-webpack-plugin": "^1.1.1", "prettier": "^3.3.3", "string-replace-loader": "^3.1.0", - "typescript": "^5.0.4", + "typescript": "^5.6.3", "webpack": "^5.95.0" } }, @@ -21177,10 +21177,9 @@ } }, "node_modules/typescript": { - "version": "5.5.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", - "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", - "license": "Apache-2.0", + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" diff --git a/docs/package.json b/docs/package.json index 8897f6d2..da3211a9 100644 --- a/docs/package.json +++ b/docs/package.json @@ -62,7 +62,7 @@ "prebuild-webpack-plugin": "^1.1.1", "prettier": "^3.3.3", "string-replace-loader": "^3.1.0", - "typescript": "^5.0.4", + "typescript": "^5.6.3", "webpack": "^5.95.0" } } From e9681270d38975e391c22eb832beaebda592a1b3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 23 Oct 2024 01:48:09 +0200 Subject: [PATCH 093/415] chore(deps): bump @mdx-js/react from 3.0.1 to 3.1.0 in /docs (#2580) Bumps [@mdx-js/react](https://github.com/mdx-js/mdx/tree/HEAD/packages/react) from 3.0.1 to 3.1.0. - [Release notes](https://github.com/mdx-js/mdx/releases) - [Changelog](https://github.com/mdx-js/mdx/blob/main/changelog.md) - [Commits](https://github.com/mdx-js/mdx/commits/3.1.0/packages/react) --- updated-dependencies: - dependency-name: "@mdx-js/react" dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- docs/package-lock.json | 9 ++++----- docs/package.json | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/docs/package-lock.json b/docs/package-lock.json index 1c33fbf8..a2a47a50 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -14,7 +14,7 @@ "@fortawesome/fontawesome-svg-core": "^6.4.2", "@fortawesome/free-solid-svg-icons": "^6.4.0", "@fortawesome/react-fontawesome": "^0.2.0", - "@mdx-js/react": "^3.0.0", + "@mdx-js/react": "^3.1.0", "classnames": "^2.2.6", "js-yaml": "^4.1.0", "react": "^18.0.0", @@ -3428,10 +3428,9 @@ } }, "node_modules/@mdx-js/react": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.0.1.tgz", - "integrity": "sha512-9ZrPIU4MGf6et1m1ov3zKf+q9+deetI51zprKB1D/z3NOb+rUxxtEl3mCjW5wTGh6VhRdwPueh1oRzi6ezkA8A==", - "license": "MIT", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.1.0.tgz", + "integrity": "sha512-QjHtSaoameoalGnKDT3FoIl4+9RwyTmo9ZJGBdLOks/YOiWHoRDI3PUwEzOE7kEmGcV3AFcp9K6dYu9rEuKLAQ==", "dependencies": { "@types/mdx": "^2.0.0" }, diff --git a/docs/package.json b/docs/package.json index da3211a9..dbffc4d9 100644 --- a/docs/package.json +++ b/docs/package.json @@ -21,7 +21,7 @@ "@fortawesome/fontawesome-svg-core": "^6.4.2", "@fortawesome/free-solid-svg-icons": "^6.4.0", "@fortawesome/react-fontawesome": "^0.2.0", - "@mdx-js/react": "^3.0.0", + "@mdx-js/react": "^3.1.0", "classnames": "^2.2.6", "js-yaml": "^4.1.0", "react": "^18.0.0", From 0d8b23fccbd343eeaa9162deeb5a3138a0c02327 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 23 Oct 2024 01:49:45 +0200 Subject: [PATCH 094/415] chore(deps): bump mermaid from 10.9.1 to 10.9.3 in /docs (#2584) Bumps [mermaid](https://github.com/mermaid-js/mermaid) from 10.9.1 to 10.9.3. - [Release notes](https://github.com/mermaid-js/mermaid/releases) - [Changelog](https://github.com/mermaid-js/mermaid/blob/develop/CHANGELOG.md) - [Commits](https://github.com/mermaid-js/mermaid/compare/v10.9.1...v10.9.3) --- updated-dependencies: - dependency-name: mermaid dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- docs/package-lock.json | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/package-lock.json b/docs/package-lock.json index a2a47a50..976d3553 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -13824,10 +13824,9 @@ } }, "node_modules/mermaid": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-10.9.1.tgz", - "integrity": "sha512-Mx45Obds5W1UkW1nv/7dHRsbfMM1aOKA2+Pxs/IGHNonygDHwmng8xTHyS9z4KWVi0rbko8gjiBmuwwXQ7tiNA==", - "license": "MIT", + "version": "10.9.3", + "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-10.9.3.tgz", + "integrity": "sha512-V80X1isSEvAewIL3xhmz/rVmc27CVljcsbWxkxlWJWY/1kQa4XOABqpDl2qQLGKzpKm6WbTfUEKImBlUfFYArw==", "dependencies": { "@braintree/sanitize-url": "^6.0.1", "@types/d3-scale": "^4.0.3", @@ -13838,7 +13837,7 @@ "d3-sankey": "^0.12.3", "dagre-d3-es": "7.0.10", "dayjs": "^1.11.7", - "dompurify": "^3.0.5", + "dompurify": "^3.0.5 <3.1.7", "elkjs": "^0.9.0", "katex": "^0.16.9", "khroma": "^2.0.0", From 55c67804eb4fac2c0cb6f04823ee97fec23d2235 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 23 Oct 2024 01:52:19 +0200 Subject: [PATCH 095/415] chore(deps): bump http-proxy-middleware from 2.0.6 to 2.0.7 in /docs (#2585) Bumps [http-proxy-middleware](https://github.com/chimurai/http-proxy-middleware) from 2.0.6 to 2.0.7. - [Release notes](https://github.com/chimurai/http-proxy-middleware/releases) - [Changelog](https://github.com/chimurai/http-proxy-middleware/blob/v2.0.7/CHANGELOG.md) - [Commits](https://github.com/chimurai/http-proxy-middleware/compare/v2.0.6...v2.0.7) --- updated-dependencies: - dependency-name: http-proxy-middleware dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- docs/package-lock.json | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/docs/package-lock.json b/docs/package-lock.json index 976d3553..5b7987ca 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -10117,10 +10117,9 @@ } }, "node_modules/http-proxy-middleware": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", - "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", - "license": "MIT", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.7.tgz", + "integrity": "sha512-fgVY8AV7qU7z/MmXJ/rxwbrtQH4jBQ9m7kp3llF0liB7glmFeVZFBepQb32T3y8n8k2+AEYuMPCpinYW+/CuRA==", "dependencies": { "@types/http-proxy": "^1.17.8", "http-proxy": "^1.18.1", From 5487b108d5bbf6d8707fe9e013cd6b000bac1ee0 Mon Sep 17 00:00:00 2001 From: Nicolas Munnich <98408764+Nick-Munnich@users.noreply.github.com> Date: Wed, 23 Oct 2024 02:16:59 +0200 Subject: [PATCH 096/415] docs: fixing some more broken anchors (#2586) --- docs/docs/config/kscan.md | 12 ++++++------ .../hardware-integration/physical-layouts.md | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/docs/config/kscan.md b/docs/docs/config/kscan.md index dfe22bf4..e3fa8969 100644 --- a/docs/docs/config/kscan.md +++ b/docs/docs/config/kscan.md @@ -27,10 +27,10 @@ If the debounce press/release values are set to any value other than `-1`, they Applies to: [`/chosen` node](https://docs.zephyrproject.org/3.5.0/build/dts/intro-syntax-structure.html#aliases-and-chosen-nodes) -| Property | Type | Description | -| ---------------------- | ---- | ------------------------------------------------------------- | -| `zmk,kscan` | path | The node for the keyboard scan driver to use | -| `zmk,matrix-transform` | path | The node for the [matrix transform](#matrix-transform) to use | +| Property | Type | Description | +| ---------------------- | ---- | ---------------------------------------------------------------------- | +| `zmk,kscan` | path | The node for the keyboard scan driver to use | +| `zmk,matrix-transform` | path | The node for the [matrix transform](layout.md#matrix-transform) to use | ## Demux Driver @@ -94,7 +94,7 @@ Assuming the switches connect each GPIO pin to the ground, the [GPIO flags](http }; ``` -A direct pin defined in the `input-gpios` property is considered a column when used in a [matrix transform](#matrix-transform); e.g. the 5th pin on the list can be referred to using `RC(0,4)`. +A direct pin defined in the `input-gpios` property is considered a column when used in a [matrix transform](layout.md#matrix-transform); e.g. the 5th pin on the list can be referred to using `RC(0,4)`. 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 enable and disable the internal pull up/down resistor as needed when the switch is toggled to minimise power draw. For `toggle-mode` to work correctly each pole of the switch needs a dedicated GPIO pin. @@ -200,7 +200,7 @@ Definition file: [zmk/app/module/dts/bindings/kscan/zmk,kscan-gpio-charlieplex.y | `poll-period-ms` | int | Time between reads in milliseconds when no key is pressed and `interrupt-gpois` is not set. | 10 | | `wakeup-source` | bool | Mark this kscan instance as able to wake the keyboard from deep sleep | n | -Define the transform with a [matrix transform](#matrix-transform). The row is always the driven pin, and the column always the receiving pin (input to the controller). +Define the transform with a [matrix transform](layout.md#matrix-transform). The row is always the driven pin, and the column always the receiving pin (input to the controller). For example, in `RC(5,0)` power flows from the 6th pin in `gpios` to the 1st pin in `gpios`. Exclude all positions where the row and column are the same as these pairs will never be triggered, since no pin can be both input and output at the same time. diff --git a/docs/docs/development/hardware-integration/physical-layouts.md b/docs/docs/development/hardware-integration/physical-layouts.md index 4dd58e8d..7e36574c 100644 --- a/docs/docs/development/hardware-integration/physical-layouts.md +++ b/docs/docs/development/hardware-integration/physical-layouts.md @@ -8,7 +8,7 @@ It contains: - A [keyboard scan (kscan) driver](../../config/kscan.md) - A [matrix transform](../../config/layout.md#matrix-transform) -- (Optional) [Physical key positions](#physical-layout-positions) +- (Optional) [Physical key positions](#optional-keys-property) ## Basic Physical Layout From 428c36bc596b32d056833f5ad51bfb7b26919775 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 23 Oct 2024 13:05:51 +0200 Subject: [PATCH 097/415] chore(deps-dev): bump eslint-plugin-react from 7.37.1 to 7.37.2 in /docs (#2588) Bumps [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) from 7.37.1 to 7.37.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.37.1...v7.37.2) --- updated-dependencies: - dependency-name: eslint-plugin-react dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- docs/package-lock.json | 44 ++++++++++++++++-------------------------- docs/package.json | 2 +- 2 files changed, 18 insertions(+), 28 deletions(-) diff --git a/docs/package-lock.json b/docs/package-lock.json index 5b7987ca..f4542a89 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -36,7 +36,7 @@ "eslint": "^8.39.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-mdx": "^3.1.5", - "eslint-plugin-react": "^7.37.1", + "eslint-plugin-react": "^7.37.2", "json-schema-to-typescript": "^15.0.2", "mustache": "^4.2.0", "null-loader": "^4.0.0", @@ -7904,11 +7904,10 @@ } }, "node_modules/es-iterator-helpers": { - "version": "1.0.19", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz", - "integrity": "sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.1.0.tgz", + "integrity": "sha512-/SurEfycdyssORP/E+bj4sEu1CWw4EmLDsHynHwSXQ7utgbrMRWW195pTrCjFgFCddf/UkYm3oqKPRq5i8bJbw==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -7917,12 +7916,12 @@ "es-set-tostringtag": "^2.0.3", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", - "globalthis": "^1.0.3", + "globalthis": "^1.0.4", "has-property-descriptors": "^1.0.2", "has-proto": "^1.0.3", "has-symbols": "^1.0.3", "internal-slot": "^1.0.7", - "iterator.prototype": "^1.1.2", + "iterator.prototype": "^1.1.3", "safe-array-concat": "^1.1.2" }, "engines": { @@ -8176,9 +8175,9 @@ } }, "node_modules/eslint-plugin-react": { - "version": "7.37.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.1.tgz", - "integrity": "sha512-xwTnwDqzbDRA8uJ7BMxPs/EXRB3i8ZfnOIp8BsxEQkT0nHPp+WWceqGgo6rKb9ctNi8GJLDT4Go5HAWELa/WMg==", + "version": "7.37.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.2.tgz", + "integrity": "sha512-EsTAnj9fLVr/GZleBLFbj/sSuXeWmp1eXIN60ceYnZveqEaUCyW4X+Vh4WTdUhCkW4xutXYqTXCUSyqD4rB75w==", "dev": true, "dependencies": { "array-includes": "^3.1.8", @@ -8186,7 +8185,7 @@ "array.prototype.flatmap": "^1.3.2", "array.prototype.tosorted": "^1.1.4", "doctrine": "^2.1.0", - "es-iterator-helpers": "^1.0.19", + "es-iterator-helpers": "^1.1.0", "estraverse": "^5.3.0", "hasown": "^2.0.2", "jsx-ast-utils": "^2.4.1 || ^3.0.0", @@ -10428,7 +10427,6 @@ "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", "dev": true, - "license": "MIT", "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -10609,7 +10607,6 @@ "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.2" }, @@ -10631,7 +10628,6 @@ "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", "dev": true, - "license": "MIT", "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -10686,7 +10682,6 @@ "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", "dev": true, - "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -10844,7 +10839,6 @@ "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", "dev": true, - "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -10939,7 +10933,6 @@ "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", "dev": true, - "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -10965,7 +10958,6 @@ "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "get-intrinsic": "^1.2.4" @@ -11020,17 +11012,19 @@ } }, "node_modules/iterator.prototype": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", - "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.3.tgz", + "integrity": "sha512-FW5iMbeQ6rBGm/oKgzq2aW4KvAGpxPzYES8N4g4xNXUKpL1mclMvOe+76AcLDTvD+Ze+sOpVhgdAQEKF4L9iGQ==", "dev": true, - "license": "MIT", "dependencies": { "define-properties": "^1.2.1", "get-intrinsic": "^1.2.1", "has-symbols": "^1.0.3", "reflect.getprototypeof": "^1.0.4", "set-function-name": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/jackspeak": { @@ -18879,7 +18873,6 @@ "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -22425,7 +22418,6 @@ "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.4.tgz", "integrity": "sha512-bppkmBSsHFmIMSl8BO9TbsyzsvGjVoppt8xUiGzwiu/bhDCGxnpOKCxgqj6GuyHE0mINMDecBFPlOm2hzY084w==", "dev": true, - "license": "MIT", "dependencies": { "function.prototype.name": "^1.1.6", "has-tostringtag": "^1.0.2", @@ -22451,15 +22443,13 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/which-collection": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", "dev": true, - "license": "MIT", "dependencies": { "is-map": "^2.0.3", "is-set": "^2.0.3", diff --git a/docs/package.json b/docs/package.json index dbffc4d9..23de9f2f 100644 --- a/docs/package.json +++ b/docs/package.json @@ -55,7 +55,7 @@ "eslint": "^8.39.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-mdx": "^3.1.5", - "eslint-plugin-react": "^7.37.1", + "eslint-plugin-react": "^7.37.2", "json-schema-to-typescript": "^15.0.2", "mustache": "^4.2.0", "null-loader": "^4.0.0", From 9a68b2eeb74bf516f8ab33983ac3cbe9401aee14 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 23 Oct 2024 13:07:45 +0200 Subject: [PATCH 098/415] chore(deps-dev): bump @types/react from 18.3.5 to 18.3.12 in /docs (#2587) Bumps [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react) from 18.3.5 to 18.3.12. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react) --- updated-dependencies: - dependency-name: "@types/react" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- docs/package-lock.json | 9 ++++----- docs/package.json | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/docs/package-lock.json b/docs/package-lock.json index f4542a89..9c3885c9 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -30,7 +30,7 @@ "@docusaurus/types": "^3.0.0", "@types/glob": "^8.1.0", "@types/js-yaml": "^4.0.5", - "@types/react": "^18.2.29", + "@types/react": "^18.3.12", "@types/react-helmet": "^6.1.6", "@types/react-router-dom": "^5.1.7", "eslint": "^8.39.0", @@ -4500,10 +4500,9 @@ "license": "MIT" }, "node_modules/@types/react": { - "version": "18.3.5", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.5.tgz", - "integrity": "sha512-WeqMfGJLGuLCqHGYRGHxnKrXcTitc6L/nBUWfWPcTarG3t9PsquqUMuVeXZeca+mglY4Vo5GZjCi0A3Or2lnxA==", - "license": "MIT", + "version": "18.3.12", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.12.tgz", + "integrity": "sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==", "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" diff --git a/docs/package.json b/docs/package.json index 23de9f2f..d1675081 100644 --- a/docs/package.json +++ b/docs/package.json @@ -49,7 +49,7 @@ "@docusaurus/types": "^3.0.0", "@types/glob": "^8.1.0", "@types/js-yaml": "^4.0.5", - "@types/react": "^18.2.29", + "@types/react": "^18.3.12", "@types/react-helmet": "^6.1.6", "@types/react-router-dom": "^5.1.7", "eslint": "^8.39.0", From 87cea76c93fd959d94a16632f6f70209140681ac Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 23 Oct 2024 13:10:34 +0200 Subject: [PATCH 099/415] chore(deps): bump react-toastify from 10.0.5 to 10.0.6 in /docs (#2589) Bumps [react-toastify](https://github.com/fkhadra/react-toastify) from 10.0.5 to 10.0.6. - [Release notes](https://github.com/fkhadra/react-toastify/releases) - [Commits](https://github.com/fkhadra/react-toastify/compare/v10.0.5...v10.0.6) --- updated-dependencies: - dependency-name: react-toastify dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- docs/package-lock.json | 9 ++++----- docs/package.json | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/docs/package-lock.json b/docs/package-lock.json index 9c3885c9..e69fc094 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -21,7 +21,7 @@ "react-async": "^10.0.1", "react-copy-to-clipboard": "^5.0.3", "react-dom": "^18.0.0", - "react-toastify": "^10.0.5", + "react-toastify": "^10.0.6", "web-tree-sitter": "^0.23.0" }, "devDependencies": { @@ -18776,10 +18776,9 @@ } }, "node_modules/react-toastify": { - "version": "10.0.5", - "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-10.0.5.tgz", - "integrity": "sha512-mNKt2jBXJg4O7pSdbNUfDdTsK9FIdikfsIE/yUCxbAEXl4HMyJaivrVFcn3Elvt5xvCQYhUZm+hqTIu1UXM3Pw==", - "license": "MIT", + "version": "10.0.6", + "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-10.0.6.tgz", + "integrity": "sha512-yYjp+omCDf9lhZcrZHKbSq7YMuK0zcYkDFTzfRFgTXkTFHZ1ToxwAonzA4JI5CxA91JpjFLmwEsZEgfYfOqI1A==", "dependencies": { "clsx": "^2.1.0" }, diff --git a/docs/package.json b/docs/package.json index d1675081..58aa6a43 100644 --- a/docs/package.json +++ b/docs/package.json @@ -28,7 +28,7 @@ "react-async": "^10.0.1", "react-copy-to-clipboard": "^5.0.3", "react-dom": "^18.0.0", - "react-toastify": "^10.0.5", + "react-toastify": "^10.0.6", "web-tree-sitter": "^0.23.0" }, "browserslist": { From 7ee25c795934692df42b823f024bc846cf9c60b1 Mon Sep 17 00:00:00 2001 From: Nicolas Munnich Date: Wed, 23 Oct 2024 11:10:42 +0200 Subject: [PATCH 100/415] chore: updated path-to-regexp --- docs/package-lock.json | 36 ++++++++++-------------------------- 1 file changed, 10 insertions(+), 26 deletions(-) diff --git a/docs/package-lock.json b/docs/package-lock.json index e69fc094..2b0c829c 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -8692,15 +8692,6 @@ "integrity": "sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw==", "license": "MIT" }, - "node_modules/fast-url-parser": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", - "integrity": "sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==", - "license": "MIT", - "dependencies": { - "punycode": "^1.3.2" - } - }, "node_modules/fastq": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", @@ -17391,9 +17382,9 @@ "license": "ISC" }, "node_modules/path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.9.0.tgz", + "integrity": "sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g==", "license": "MIT", "dependencies": { "isarray": "0.0.1" @@ -18406,12 +18397,6 @@ "node": ">= 0.10" } }, - "node_modules/punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", - "license": "MIT" - }, "node_modules/pupa": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/pupa/-/pupa-3.1.0.tgz", @@ -19903,25 +19888,24 @@ } }, "node_modules/serve-handler": { - "version": "6.1.5", - "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.5.tgz", - "integrity": "sha512-ijPFle6Hwe8zfmBxJdE+5fta53fdIY0lHISJvuikXB3VYFafRjMRpOffSPvCYsbKyBA7pvy9oYr/BT1O3EArlg==", + "version": "6.1.6", + "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.6.tgz", + "integrity": "sha512-x5RL9Y2p5+Sh3D38Fh9i/iQ5ZK+e4xuXRd/pGbM4D13tgo/MGwbttUk8emytcr1YYzBYs+apnUngBDFYfpjPuQ==", "license": "MIT", "dependencies": { "bytes": "3.0.0", "content-disposition": "0.5.2", - "fast-url-parser": "1.1.3", "mime-types": "2.1.18", "minimatch": "3.1.2", "path-is-inside": "1.0.2", - "path-to-regexp": "2.2.1", + "path-to-regexp": "3.3.0", "range-parser": "1.2.0" } }, "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", - "integrity": "sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.3.0.tgz", + "integrity": "sha512-qyCH421YQPS2WFDxDjftfc1ZR5WKQzVzqsp4n9M2kQhVOo/ByahFoUNJfl58kOcEGfQ//7weFTDhm+ss8Ecxgw==", "license": "MIT" }, "node_modules/serve-index": { From f0a3947044e82df6778b293a78c07677df4b56e1 Mon Sep 17 00:00:00 2001 From: Joel Spadin Date: Sat, 26 Oct 2024 02:55:09 -0500 Subject: [PATCH 101/415] Update web-tree-sitter and tweak keymap upgrader (#2593) * fix(docs): Fix TypeScript import diagnostics Set the TypeScript module resolution mode to "bundler" so it correctly resolves imports in .ts files instead of showing errors in IDEs. * chore(docs): Update web-tree-sitter Updated web-tree-sitter, and switched from having a copy of tree-sitter-devicetree.wasm in the repo to using the latest version of the tree-sitter-devicetree module, which now contains the .wasm file. * fix(docs): Make keymap upgrader resize vertically only Changed the textarea in the keymap ugprader to allow only vertical resizing. This better fits the layout of the page, and it prevents you from shrinking the box horizontally to the point where it doesn't fit anything. --- docs/package-lock.json | 61 ++++++++++++++++-- docs/package.json | 3 +- .../KeymapUpgrader/styles.module.css | 1 + docs/src/keymap-upgrade/parser.ts | 7 +- docs/static/tree-sitter-devicetree.wasm | Bin 160438 -> 0 bytes docs/tsconfig.json | 1 + 6 files changed, 67 insertions(+), 6 deletions(-) delete mode 100644 docs/static/tree-sitter-devicetree.wasm diff --git a/docs/package-lock.json b/docs/package-lock.json index 2b0c829c..e76c779b 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -22,7 +22,8 @@ "react-copy-to-clipboard": "^5.0.3", "react-dom": "^18.0.0", "react-toastify": "^10.0.6", - "web-tree-sitter": "^0.23.0" + "tree-sitter-devicetree": "^0.12.1", + "web-tree-sitter": "^0.24.3" }, "devDependencies": { "@docusaurus/module-type-aliases": "^3.0.0", @@ -16672,6 +16673,15 @@ "tslib": "^2.0.3" } }, + "node_modules/node-addon-api": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.2.1.tgz", + "integrity": "sha512-vmEOvxwiH8tlOcv4SyE8RH34rI5/nWVaigUeAUPawC6f0+HoDthwI0vkMu4tbtsZrXq6QXFfrkhjofzKEs5tpA==", + "license": "MIT", + "engines": { + "node": "^18 || ^20 || >= 21" + } + }, "node_modules/node-emoji": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-2.1.3.tgz", @@ -16696,6 +16706,17 @@ "node": ">= 6.13.0" } }, + "node_modules/node-gyp-build": { + "version": "4.8.2", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.2.tgz", + "integrity": "sha512-IRUxE4BVsHWXkV/SFOut4qTlagw2aM8T5/vnTsmrHJvVoKueJHRc/JaFND7QDDc61kLYUJ6qlZM3sqTSyx2dTw==", + "license": "MIT", + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, "node_modules/node-releases": { "version": "2.0.18", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", @@ -20964,6 +20985,37 @@ "node": ">=6" } }, + "node_modules/tree-sitter": { + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/tree-sitter/-/tree-sitter-0.21.1.tgz", + "integrity": "sha512-7dxoA6kYvtgWw80265MyqJlkRl4yawIjO7S5MigytjELkX43fV2WsAXzsNfO7sBpPPCF5Gp0+XzHk0DwLCq3xQ==", + "hasInstallScript": true, + "license": "MIT", + "peer": true, + "dependencies": { + "node-addon-api": "^8.0.0", + "node-gyp-build": "^4.8.0" + } + }, + "node_modules/tree-sitter-devicetree": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/tree-sitter-devicetree/-/tree-sitter-devicetree-0.12.1.tgz", + "integrity": "sha512-JccTH8TmgO9B4tAaCEZ8O7yOEtoixBRRnNZYO8W9tnNsv29Y+avsN6V8li2CfwooB1eqZIEbsPLKxN/e7bG+Cg==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-addon-api": "^8.2.1", + "node-gyp-build": "^4.8.2" + }, + "peerDependencies": { + "tree-sitter": "^0.21.0" + }, + "peerDependenciesMeta": { + "tree_sitter": { + "optional": true + } + } + }, "node_modules/trim-lines": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", @@ -22015,9 +22067,10 @@ } }, "node_modules/web-tree-sitter": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/web-tree-sitter/-/web-tree-sitter-0.23.0.tgz", - "integrity": "sha512-p1T+ju2H30fpVX2q5yr+Wv/NfdMMWMjQp9Q+4eEPrHAJpPFh9DPfI2Yr9L1f5SA5KPE+g1cNUqPbpihxUDzmVw==" + "version": "0.24.3", + "resolved": "https://registry.npmjs.org/web-tree-sitter/-/web-tree-sitter-0.24.3.tgz", + "integrity": "sha512-uR9YNewr1S2EzPKE+y39nAwaTyobBaZRG/IsfkB/OT4v0lXtNj5WjtHKgn2h7eOYUWIZh5rK9Px7tI6S9CRKdA==", + "license": "MIT" }, "node_modules/web-worker": { "version": "1.3.0", diff --git a/docs/package.json b/docs/package.json index 58aa6a43..1a086def 100644 --- a/docs/package.json +++ b/docs/package.json @@ -29,7 +29,8 @@ "react-copy-to-clipboard": "^5.0.3", "react-dom": "^18.0.0", "react-toastify": "^10.0.6", - "web-tree-sitter": "^0.23.0" + "tree-sitter-devicetree": "^0.12.1", + "web-tree-sitter": "^0.24.3" }, "browserslist": { "production": [ diff --git a/docs/src/components/KeymapUpgrader/styles.module.css b/docs/src/components/KeymapUpgrader/styles.module.css index 31e06b97..f44cf323 100644 --- a/docs/src/components/KeymapUpgrader/styles.module.css +++ b/docs/src/components/KeymapUpgrader/styles.module.css @@ -9,6 +9,7 @@ font-size: var(--ifm-font-size-base); line-height: var(--ifm-pre-line-height); tab-size: 4; + resize: vertical; color: var(--ifm-pre-color); background-color: var(--ifm-pre-background); diff --git a/docs/src/keymap-upgrade/parser.ts b/docs/src/keymap-upgrade/parser.ts index 52d6e981..b496d1d5 100644 --- a/docs/src/keymap-upgrade/parser.ts +++ b/docs/src/keymap-upgrade/parser.ts @@ -5,6 +5,11 @@ const TREE_SITTER_WASM_URL = new URL( import.meta.url ); +const TREE_SITTER_DEVICETREE_WASM_URL = new URL( + "/node_modules/tree-sitter-devicetree/tree-sitter-devicetree.wasm", + import.meta.url +); + export let Devicetree: Parser.Language; export async function initParser() { @@ -17,7 +22,7 @@ export async function initParser() { return prefix + path; }, }); - Devicetree = await Parser.Language.load("/tree-sitter-devicetree.wasm"); + Devicetree = await Parser.Language.load(TREE_SITTER_DEVICETREE_WASM_URL.href); } export function createParser() { diff --git a/docs/static/tree-sitter-devicetree.wasm b/docs/static/tree-sitter-devicetree.wasm deleted file mode 100644 index 885c5274ba287206b7d7fb93ec0f8741e4c7f32c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 160438 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

CLxH0co!>n(IzgAe97YCC|@S#6UWBM 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


;ldz%Gf|)3sAinV~+wK z17(Uc)&*D$6fD75TVOh1m1OK{;4R<~(5e(;uK+&+=agn_5b!lns|;gL0PBEL%QDs- zSPEp9W9&{~CXjY2W7h%i0EdB#$}=_+_!($Yfw95BHlR*L#(D!AfQpqEyB}B%6s^oy zM_>++QH8M^fl0vMz@=3g8x8COnx4kk5MT#TzZzpt0ULoT)fsybSOt`*!Pq^(d>~&< z#%=+o0LOqUYB4qjH~_Rbov{~zoxqv385;n60aUBQ*dxFipmbfvIs=Pw3fF8gQU?s2_yetg_CQ}?46qpZ2KWmo(Gax)Tm$p~ zh5%E6Pk^6*jB~&ZXbH3fdIPTm3xF-aAt1XE))KfBxCa;jya_A;wgP_v#Tzr$0Jsw9 z3Oox;09F9s0sjJJnxNKz>wx=#A;1)14e$dHIhU~tz zD}k=ScwiZD1Sr-5$1>0c=mLxdHUW9gXRH#?6u2392zU`#1ndA%9f01zYrt$^1Mmw_@*>0!Tmd`|yaLPs)&f5Q_Qi~q1I_`i0lEQ$ zfbqZ*;A`Ly;FL?SrvMiMoq@r?V&H4w51`VeSa0ASpdauCupamsNWTp602c!tfZo7s zz-(YEka;=w0-!Z;C(sLc6_^Qp3hV<)UxE4ut^_&*1A%eCBH$+=tqo)4fyTgfz;Nr+TY(3G7k~-CQs67#Hz5D@$Rltba6Ql+cm@~;EC4nFdx7*D@R|TL1Udl2fDeEz zzyYA#jd)E2+5q>NWT?)frh}9KqufSU=%P5SO@$76uFJD(}7mN z{lIg;Jm53nXQ0IGIEMgw0B-&OP{0h@tefs76~&VWY1)j(&UKkzy*2Urj60j!QVo`43xWk5&Z zNnivp9asZ=4`kkj^#yJKo&??o)&jo+rSHaTF>nts1egPC1JdrnJ^@??bOnY33xV%} z%ucWeTmf_eo&_cXtAJgAeJ}U}O@Uj1$ADLXIlw012vEE;UiX2kf%||LfGNPoz#bq^ z7pxI*K5z%{BrqCS0DKAj2^8&$^#R%doq&G8>%d%KJMb4!q#O2Wpf%7AcpP{cm+uz&_v@kogeS7N`u=1I`030d4>~06l;wf#-l%fwzJ8fhE9N;49z<;CBFD zc*C-Q(m*xfOrQmD1#k;+5AY!H6fguB4NL;&0Ly_5z&7A#;4qN(2-XWY6{rQA1GECJ z2HFB$fJcFWz)QebU=lC~SPpCewgEo_hk>+5VGlSJs0Ew@v;wXM+5%mGM}dLBOTbuQ zDzE@p4Qv9w1AYbm0rEbEH3TXFb%Aq%i-GHb_P~8WFW^~V1TY?$0ek?g0lols0tbL& zK)%PZR{~Xl`ao0QQs73QBXB>^8yF0X1l|HB12ciez-nMUum#u-`~>_C90Ssy!0RGV z3aAX!1{wk_fJ=evfVMy! zIiMO)A7}!!0@?sK0qudVz{5aa;5p!BU<@z;m;o#VRs!pRuYjGv&%i<82=E_}=SkEY zP!uQwR03)M^?-&zQ=k=a8E_47GtdsW2j~tw1oQ&>1J4030waO3zy#nuU^cJ_SPpy) zd>-FYr6? zH(>R}u>%wWiUZ|%3bY6A1$qFF0KI{M!1KUxU=;8sFbS9r z%mqFGRsw5*jlkEycfcNCKkz4T3`lzlbqf>*N&yvsYCs*}EZ|(AC2$FF6>uZa7Pt%O z3OoQj4m<@60)_%3fH#1*fhoXDU;(fU_y|}Jd;x3&b^*TtzX5*%tRK!RfPz3Vpe#@s zs0q{u&HmPMz#qU-AkrUu6p#&+1j+-a0kwfMfhNHDz{S9ozzx9dKu4ep&=YtJ=nFgp3;|vN zUI)ellY#ev`M^?OHSj608Q2Q!1bzk%0!M)VfII_m`~yXSGC(Du22c-Z2s8y+0ha;S z05=2efO~-Mz(YVUpg-^&@FHOT<9FDL>xXH0mJZ}WKQA6L@t7aT0t%teKkMb!b@{zq zCD1R4=lqIrS@g>TmGGQjc|8r!YXGO?c^#l0a0dEk0p|csfTk=B*K;krz{$V_2q6vbyQ#Zdtz@d?Y?Id2hqLac$Whc$0Le^KCSDvAfwl ztP}nwuruqzy0UJpJG)Ok6W?Cgf#!E)PvDzcp2XkR^kIG3Q`ngLyT?JWwI|H zxtu?jkMg;kAM_~g$Vc6dlqLHyr(@=S!x+zLP#pZ6N6wM+<)f7IM=nbS_&&lpxc3>k z$N0(RxP0XE{GQ7(eVogrUoPj*-Q!Y^KT5dgN*(#g?Qrm1$>;i`w8O{cbN(pjc*)#j z+?RxVjO)uWX;-%y^qkw1`us6yz8u$e+( z=S#VJo<7&_x$Z+g5A!H}>zv%r-F?X=9zSxf?nlqn|HkLFu%>R*@sPRa@IK$$^trsx zGSv)?@P$Oe3Wu-pUb3O-3DJL$wAKH^Kv@R;Pd!6f0VHn)^v(G z&-oai#~-+n8*{=ezpna3fRrY;-qzH2zHuGQwjw9TJ$xg6tQDS09(p`I!92Wl~q#mVK}J+=uidAHC*D`>B2` z?l^QmaiGZgs1eMookYpc!FQe=hvgf_4houW}O#Ts|Dos=u_x= zbT(>MT#qh=tI}lwer>t}P!K);>(SNmUZ@7HRGZhMYeFKfTGzvCb6uQU*TW1k_iSiX zgH97j&M>ZG*Mujo)tKFiYunrv_xFL-!oa;{MK}E8zS(xVQ>l6VJGX z>dy7@CYVzfv-&}&9<|HjQO<_~ndu$q;&StRp*-SQz&1Q4hTsDu*XA9Uuwumie zAFw5CDO-knrI)i6Y$aR8R?`&) z`-W|0+t{~kJKF*M@7Yeai|uAVupikT_7nRV8Y|d7_AA@Z4zPplH}*R_1gk4y{}Xs! z1%IEhWALy63@mFg*eqn}))szeW680Tdg|p+fi(_>- zk3+01VkwU3ieRP6Am*aT5$ALS>$wT6zJqoV*!U1**_0i=);w1QtxWuvf&VsR_GaY& zi1izA5Siy%TxS*Xehm3P06Y8fd<$0MOZF`uf5qcAtk6DG=?bdTuc%VLMy>Ly-QgSy z^C0C%!Y5dJQOBR7Zht~P_fTzoPZe!hJE^L7A)?<=#|PnYKYZ+?I^PWqUh^wid%J_( z5xCpF2WXF$Kko>1!1Md@Uq_Pi_EGyW`*HgTyO;f>-P`Vi_9?rc-QONy544{K_{eki zU_8D6^s$FQV=yF-VMc$flvKP{SOYLR$hj_LESY@xaKeE@@9~0K$@nd^~{h9qa z`k&+R3wsOw_XR!U{m<_{Z?pPe4b6Um6=jbujhMe;`qM6x0UBZVTT;42pj0|g+>h?IzwjFiIsGLf>- zi$u6iCT16mREbn|Myp0@LaPMk6hd1Qx@Vw06XT_zoj1}5zW8Vvj247$CTz5%+3Ati zq<0D|TkueT{9gsnHhhJ3?{UZG%10nA*but!LSrE`gwAr8&I(VReUV=y`y&S; z2P3~levcd?%ZFk6ugKq#f57TPaQhFQth8nDy9ypxf_L7u6=0J;tw7p`@Led4+bEn? zB&}%LVT_hY`zKN=t#sNv#F96S^XFI$ZdKB%ru_}hvk>b_Fz0$pz<)~Qu#<_rX=lUJ zVQ4l^n*u$NiRNjA(iTNprY!|Oo(ZmZ2o^3&n+{HY!FJKKh2VE>+A2ujkKC9x6A{fq zzLq<)+reu4wBI5f(++_5eppzJ`8<+tX{FMZM0%vnhPTCdTnN2K(%QqqWohrz3bjmY zp4K;QF7nVg?LAnT26pqnrg_?YtQD6ofb>N$TuRb+9qB$uN3l1+k7P4@61i$-)|I5Z1DgP(mbyFwTO$nUK;tn9PQx0u;dR7s4TtxqMOsm2++f{JB zTZOexTaA62KMVdRH26&MEGLaBY=NEAI3JU%Eo+3|#3TRlr?PM1?hgJhI((E=qW$~R z%<&$seqGo65w3nWF<%)x!!JM3DIeqvn3)BFEbb{=3-6k8kap4kPj0TB}>6j8(gT+D%F&SDk= zEX(dJjxMw7&Mb-|KVZCynJWr{39k`zLQz4z=5!TvzGh5_Isac(b#-_dp5MP8YI@%K z&N+3ey1Hg|nCXW9Vc-M6gE3yKLLUL%7xo`#@(XkNLa;XLq`hZ-o6vlTt4h7*bJcpy z>#Fsd-&N~1&#TsJzMFa#vnBax-dDBP{I6QC^Pp-Roex#(bzW4h*ZEO3zRr`X_Bvlw zuYY#)`FqwkgE2qv0=Hv+^@KhHe6Ks+QG5D!q|@UDKf`?JjQPA0+B-92ALd&XxnsQE z>08T)&-48{+j4R~PXj;c#wE%x%dfoB%VUF$1%G%dN_O{kMyoLVH!ub3E{SxSN zpg#}(!*M*GUxW9+c91a6;m`HpQ`=KNKKjNi#`A6Hd)oHwgOo5g z-s<|MH_j7Zuk}vq+8t>32Jg-ONHI<9&@&OZK|ber|oX z>xLpNS+Dh@YQ5Hxs`Xk=s@7{=samh~rE0y_8B?!fHowm4mkl@`K7Xw{RqeI@RE@87 zsH(lzpNzeqPg)16)@wbeTCa7XYQ5Hns`XkYs@7}0s9LXe!_=#|@$q?T{is^6b);&& z))Q0j!ldS_)|IOET2EB(=UW&??@v|d@+i5z=P+U?>+yBlR3wY1VZB@geJoxN4#WC) z5A2@;f8#iA@ICNXi2pV683+4qv7Yt^e~x%hfFB1x2L3nrQSc++`QQh^cY^N#-wvJ) zz8QQAcne{8Ocb_iB{`jTX z-?0??=ay3ctE>0xP@L!cOR2A0%KA8BDeL2TONrAjvp(t+Qh zbExUALh!o*0a792menn zKM#d|6nGf;Y50$XUIxDb`{SWs13nSFH+VnrIPf!Q?^x*L!KZ=yg3ka?25$;}7VV!8 z{UY!b@Ko?dmhC|{$2mT4^t!D{uw=bnzpK{kb-Zf5UeBx6>vg&)@g7`yF#=s$sP0Dl1f5d0DN z;|zy2BW<(3`Iw`MFjp_#{PNRnF~>Uma}j$z58ZRD56`xrkJ#%u=$^eEj>!6Zj&%J( zI%f=G46b(^SKI=gmWiiddqbZEz8ZX$V;jXhL>#wwCG0PU{Y>bWfoFr6-!&OMtUXvc zm|w5DE#{~q%~>2J=ZAzza{>jz1|V=J$pSrO8%+-dyaKo499%ls7JGf`G{lvSks zXRp_o{8GB-SRW$Y{7TzxVNJwd&zt#`Za-qL*A}I(ocMe8dI!vJ&l%nPGCgYF>SC|g zn)$X$qI=HhsrhL23 zTrH(X?DZORyq8aO&t5kdG14!#BMibN_)zKVC*##2V%3^0wA>xK*vUayYwWuvy623( z4s>y>x9OSs@AIvVIM$ETv()jZjX0z0_{RQ5PakiS-`XiX;@IEtTF}K_uQ9sTS0CSV ztebo_zhgb(jIQ-Hqo>zf^sff}v+b>s@;CX2^~HG#IbJL*ZSf6Z`)6;CpqYzy?+NY9-6=2pPW0zTE_jg^R-9H-ozLCcpVLIkm#Nx z-Rz95x7QUu-0N4YUz&M6(-l&{n_Jh!{}Sj^!52G@<3}6^_$TbA!2TlW7lJPUGoSOJ zKj89@+n)jb*$jud(`@G6Jk04LQs(_+R1tI3zc8nZR+-nsSdTc?b&)J>i5{`n^JB8Q zXRqgU(J5_-f5cwT>%vjy{eW*DtgE$H%eX&z#PjUq)gWKbu@3*5Y(BcWjvLR&UKhy$ zp9($=d?NU4@MQ2<@HFrQ$9@2Goe#75@$%nsNq9qRneZHNH~6mvUKzYP*nR&ciQg6a zKFD__{@z*{d^7C70Pmjp`$<=yLVF*8KLmdSJ`m$E2s{ux0Nfw^9pZlu{b2NGKk&Zb zy}^5dhl39S?+^YR`SpYTCiG3AFND4k^g8ec;8)@QI(T=C*FoUj5bp@+M}a58z9;mq zj%^m^;cDb_mh+GGvoQZgBHo(dt@G;E*rr=G$ z8-sg+Hv<0;_*%@TOELdvf@grQgZ~ZCuL0i(zR9tDG!JiJzFyW&+!2`0q;96M1T7u{=c&E!~GT4o>DG8SXcOg|Mgk_ycv)5=Y|pc z{B1n*t$MeGOYpF$U9UT~lT1}%?qof7P#NX^|Hzre_5Qr_cD^0`ZD_|~$vDep;^=A* znehtq$j5WkuCBP6vDXz$9sB;~4zZR#kC1FG@~hE^^Y$F~Yacz+f33yw9530ATUhY`_l*h z_hWoJLXSB1KM(OAg8wk&`#btaUVwP7Bi?l6e;e#uUA}RCH#&c7Whx_%^e{KkK1<$L zI=1szJ~mldcspO8tQXx~f8zLeV7$yao}T|b(f`$8Pws*K9BNyNn+uxZPu|Vh#|~#8 z-$S5xgx(ok3;qoK%R~PK@z;jFCG?-c-C+MM^bM_^9KTa+KDzRD=I;mn?g4)9A@6s= zTOzLeT-koUu1Lx8e*=E6fnNdFB9C{`zo9suz2N^f{J#Rf4EqI$e;4A9fW2-4s4eMV zC-92k&fo=zw-WR&;FZBs;r}J{JCT0_>{o&PYT&iNYlC;jcZQ#YQ{{;LUcszIt;tfOof51M3o&(o_TM&OJcy%0~MjW4Q5w8RIRK(jEycO)1 z0sjrW9C%~!_85=tG8~$lO=wHj7stAD1lE`N89)7>4%%5CyexQk@R6B#VQv!gaICu| z*zeaR=j-r{pY8$x9s&Lb#&2{vJABw@w$eWPJu?nr{wSwM24TJ~!@7$D_-z+I4!DeCYo+zI<`~#l zTziqOyPjn1b*B!TS6{;aE!h9z^f=xM@Sl(Qc6O$}`VI%|&G$OeuM1tEo9{)X^`6kT zcKO*yV|llENWIP+fqd2g9|>L)yfxZ;ETf0H?C}b7+2g6ZwPfsdHB<0r;DZ&gZSoq5$W@FC+I&x{}FsH z;{O2seCQW|F9d%N|0&S_3BDLS6?_SJ26!g;a_|-4E5TQRuLjQoUjzOZ_(t$e;Mw5M zF*@3V-{2>} zdm*1j@H4P~1biU+-v<40@LbqG2>loE7vQJC?}JxH{FT5RFrL4`e|z-*SLhA!KO6ib z+N&VmpO_z~gP%it%YzR^{CnWP7!A+; z?*aZ6{vq=D8Tzu|6A`Zk`U>dpL(sQ{|E}Pj!OifW2i_6(=6mkx^=b#`L%|<_KLjsE ze;&Ym*#h?S(SBEq?@q9P6!zCbe*pUR(C>%7cSa9u&GAXTx2(GdX7nJK2fhpO1|$DF zq3;O&4(Jad{)6DT;O{WruV%*EU3VinpLN$q_}`FW8%!A`>w~LFcz@*o721C+6Hj*q zMgR7LegJqL;!THs5BLb=a|PPF6ZW@*zsZc3?$!zYNASbQ?+56=BHs7VJAxO2$07d{ zGaS}d#Oe8I*5~x`DuG9XKSO(;g5QGuJ7DwoU%I`+!EYd*`Tj!M-hBTe%|pPi!~bfG z=WEbk1rI{Jf#6qQzYX-Q!CQgvg8vJc51+t(Gw`P1GI#=b68LiPQ^@B@@VT%*ADsPu zhVCj0eK+s~oNtrBr+`ldpA9|-d@lGr@WtRuz?Xujfv*H#1-=?Q3w$H^Ch%S@ROM)mw0Vfq(9sOaW6K&<9nX+!eWz-mi<8bR5SNf_Spljj3;LFT}=$=5oPw$2`ihSSkc&>`R(>L1U#{tkbABw>KsZ zo_qKw(aB&YsF_pc!g1||QbQpqlpE?>bznTZqhiLSpot&@H>VRWlp5o-Tq=#a&+M?^ z$Y8MURy%NDFmOOHU_j7+K+s)}{q2?beV?ObG&hbdlr~owcV?=!)^gsYnME0VyViMi#2;j`~0Hm8%;~sjebF2H@3Zfclri>%_^atJ0rCuZ99E;jWpwe;4IszPbG6S?5b%u&>{D5PoKP^H{^Oh4V_ppUuF!DhP0!6v%* zL9d`^PyG;l{h+(K(Q&-luPo}NDfwr=w5Ru#nSW`6zxG@$L=mjL8c1W(++U04>`lz{ zza^7Tt9tIO(|vIvT#d^r$<5k3ue3qh{r~km9XWQ4$Nn!o=_H%eBRlsFK=)zSE0=k5 zvyqDV)M6Qx34@iow!zDV!4>+`Y_Q&*kI+ZJ`|D%)MJk;y6|WZt&E3PGRpq@N&fYrx z9}kP%e|=f2R(}-?wz#YIQ?#G1 zy2aYRtTIVumdYk76=krudyOYIv*>%?QMY8=) zn#u(#Q&ncDoU8J*Y`SSbOJ$KhayPkrp>nXEFH&1u zXkV*#x@$j0rJ%AR+OZ~4?xnIw_XupTb&MFJUzp6Z=lHSIu?fGhF wTkRWFT2$Uu*+Oh9jN_W)xWCpzk{`A`v3p{ diff --git a/docs/tsconfig.json b/docs/tsconfig.json index e3f649ee..b8e14486 100644 --- a/docs/tsconfig.json +++ b/docs/tsconfig.json @@ -3,6 +3,7 @@ "include": ["src/"], "compilerOptions": { "types": ["node", "@docusaurus/theme-classic"], + "moduleResolution": "Bundler", "esModuleInterop": true, "resolveJsonModule": true, "strict": true, From 7d8dd64cdc2f75f421638c6876de2e9f71e24df2 Mon Sep 17 00:00:00 2001 From: Nicolas Munnich <98408764+Nick-Munnich@users.noreply.github.com> Date: Sun, 27 Oct 2024 02:31:47 +0200 Subject: [PATCH 102/415] docs: Added a page on pin control for ZMK (#2508) * docs(feat): Added a page on pin control for ZMK * Added note on HAL modules * docs: Added images of boards --------- Co-authored-by: Cem Aksoylar --- .../hardware-integration/new-shield.mdx | 2 +- .../hardware-integration/pinctrl.mdx | 530 ++++++++++++++++++ .../hardware-integration/shift-registers.md | 71 +-- docs/sidebars.js | 1 + docs/src/components/interconnect-tabs.tsx | 18 +- 5 files changed, 541 insertions(+), 81 deletions(-) create mode 100644 docs/docs/development/hardware-integration/pinctrl.mdx diff --git a/docs/docs/development/hardware-integration/new-shield.mdx b/docs/docs/development/hardware-integration/new-shield.mdx index 18ce3ade..2f4cd05c 100644 --- a/docs/docs/development/hardware-integration/new-shield.mdx +++ b/docs/docs/development/hardware-integration/new-shield.mdx @@ -266,7 +266,7 @@ The standard approach is to have a core `my_keyboard.dtsi` (devicetree include) The kscan node defines the controller GPIO pins that are used to scan for key press and release events. The pins are referred to using the GPIO labels noted in the pinouts below: - + To use GPIO pins that are not part of the interconnects as described above, you can use the GPIO labels that are specific to each controller type. For instance, pins numbered `PX.Y` in nRF52840-based boards can be referred to via `&gpioX Y` labels. diff --git a/docs/docs/development/hardware-integration/pinctrl.mdx b/docs/docs/development/hardware-integration/pinctrl.mdx new file mode 100644 index 00000000..0f06ae58 --- /dev/null +++ b/docs/docs/development/hardware-integration/pinctrl.mdx @@ -0,0 +1,530 @@ +--- +title: Board Pin Control +sidebar_label: Pin Control +--- + +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; +import InterconnectTabs from "@site/src/components/interconnect-tabs"; +import Metadata from "@site/src/data/hardware-metadata.json"; + +:::info +This page exists to provide a guide to [Pin Control](https://docs.zephyrproject.org/3.5.0/hardware/pinctrl/index.html#pin-control) for ZMK users and designers. Refer to [Zephyr's page on Pin Control](https://docs.zephyrproject.org/3.5.0/hardware/pinctrl/index.html#pin-control) for elaboration and more details on any of the points raised here. +::: + +A basic keyboard design as introduced in the [new shield guide](./new-shield.mdx) only uses its pins for the keyboard matrix. Many keyboard designs make use of advanced components or functionality, such as displays or shift registers. This results in the keyboard making use of communication protocols such as (but not limited to) SPI, I2C, or UART. Configuring pins for the usage of advanced functionality such as drivers for the previously named protocols is referred to as "Pin Control". + +:::warning +The details of pin control can vary from vendor to vendor. An attempt was made to be as general as possible, but it isn't possible to cover all possible cases. The approaches for the nRF52840 and RP2040 MCUs/SoCs are documented in their entirety below. For other MCUs/SoCs, please refer to the [Zephyr documentation](https://docs.zephyrproject.org/3.5.0/index.html) and the examples and other files found in-tree of [ZMK](https://github.com/zmkfirmware/zmk/tree/main/app/boards) and [ZMK's fork of Zephyr](https://github.com/zmkfirmware/zephyr). +::: + +## Boards, Shields, and Modules + +Pin control is always defined for a _board_, never for a shield: + +- If you are defining a keyboard that is a _board_, then you will be editing and adding on to the files in your keyboard's folder as usual. +- If your keyboard consists of a _board and a shield_, then you should define a new folder inside of your shield's folder called `boards`. You will need to add a `.overlay` for each board to be used with said shield. Take for example the file structure of the "sofle" shield: + ```plaintext + boards/shields/sofle/ + ├── boards/ + │ ├── nice_nano.overlay + │ ├── nice_nano_v2.overlay + │ ├── nrfmicro_11.overlay + │ └── nrfmicro_13.overlay + └── + ``` + Note that you will need to define a separate overlay _for each_ of the boards to be used with the shield. + +:::info +Assume that the shield that you are using is found in-tree of ZMK or within an external module, and _does not_ contain the overlay for the board that you wish to use. +If this is the case, then you should fork the source repository and add the overlay to the fork. Use said fork to build your firmware, and potentially submit a PR to upstream. +::: + +## Predefined Nodes + +Many boards will already have some pins configured for particular protocols. We recommend using these pins whenever possible. + + + +Note that some boards may have these pins configured to fit the above pinouts, rather than the capabilities of the MCU. Most notably, boards using the nRF52840 often end up putting low-frequency pins at the locations of the SPI buses above. More on low-frequency pins in the next section. + +## Pin Selection + +Prior to setting up pin control, you will want to make sure that the pins you use are suitable for the driver that you are using. For this purpose, you will most likely need to consult the datasheet of your MCU/SoC directly. Different MCUs/SoCs have different restrictions in regards to this. The nRF52840 and RP2040 are excellent examples: + +- The nRF52840 has its pins marked as either low frequency or high frequency. + - Using low frequency pins at a frequency of over 10KHz can cause reliability issues with the wireless antenna, making them unideal for I2C, UART, and (most of) SPI. + - High frequency pins can be used for almost all protocols that the nRF52840 is capable of, without restrictions. The exception is QSPI, which is restricted to specific high frequency pins (QSPI is mostly irrelevant for keyboard designs). +- The RP2040 supports two SPI buses labeled SPI0 and SPI1, two I2C buses labeled I2C0 and I2C1, and two UART buses labeled UART0 and UART1. It restricts its pins to particular functions for each of these. For example, pin 0 can be used as the RX pin of SPI0, the TX pin of UART0, or the SDA pin of I2C0.

You will need to make sure that the pins you select all lie on the same bus and fulfil each of the functions necessary for the bus to function. So for a fully functioning SPI0 bus, you would need to select a SPI0 RX pin, a SPI0 TX pin, and a SPI0 SCK pin.

The RP2040 also comes with programmable input/output blocks (PIO) that can be used to emulate protocols such as (but not limited to) the previously named protocols. Using PIO adds some complexity though, and there are a limited number of PIO blocks, so it is recommended that you stick to the predefined buses where possible. + +Note that not all peripherals require all pins to be defined - for example, there are plenty of SPI devices which do not require either the MISO (Main In, Sub Out) or the MOSI (Main Out, Sub In) pin. + +## Pin Control File + +Pin control consists of two parts: + +1. Defining and grouping the pins together for a driver +2. Augmenting a driver/bus node and assigning pin groups to it + +It is standard to do this in two separate files. Create a file called `-pinctrl.dtsi`, which will be used for the first part. This file will later be imported into your board's `.dts`. If you are configuring pin control for a [shield](#boards-shields-and-modules), it is common to write the contents of both parts into the `.overlay` file directly. + +### MCU/SoC Pinctrl Bindings Files + +The specifics of pin control for a particular MCU/SoC are presented via a [devicetree bindings](https://docs.zephyrproject.org/latest/build/dts/bindings-intro.html) file, found under `zephyr/dts/bindings/pinctrl/`. + +- The nRF52840 uses the `zephyr/dts/bindings/pinctrl/nordic,nrf-pinctrl.yaml` file. +- The RP2040 uses the `zephyr/dts/bindings/pinctrl/raspberrypi,pico-pinctrl.yaml` file. + +These files often contain useful comments on pin control for their devices, and so can be worth a read in addition to this page. + +### MCU/SoC Pinctrl Bindings Headers + +MCUs/SoCs will also have pinctrl header files found under `zephyr/include/zephyr/dt-bindings/pinctrl/`. You will want to make sure that the header file corresponding to your MCU/SoC is imported into your board's `.dts`/`.overlay`. For the nRF52840, your board should already be importing a file such as `nordic/nrf52840_qiaa.dtsi`, which includes the pinctrl header via the following inclusions: + +```plaintext +nrf-pinctrl.h -> nrf_common.dtsi -> nrf52840.dtsi -> nrf52840_qiaa.dtsi +``` + +The corresponding file for the RP2040 (`rpi_pico/rp2040.dtsi`), however, does not include the pinctrl header. Hence you will need to import said header at the top of your `-pinctrl.dtsi` file: + +```dts title="-pinctrl.dtsi" +#include +``` + +If you are configuring pin control for a [shield](#boards-shields-and-modules), then this file may already be imported by the board's definition, in which case you shouldn't re-include it here. + +:::info +Some MCUs/SoCs may have their headers located in a Zephyr HAL module. See for example the [Atmel HAL module](https://github.com/zephyrproject-rtos/hal_atmel/tree/master/include/dt-bindings/pinctrl). +::: + +### Pinctrl Node + +All of your configuration will happen by adjusting the `pinctrl` node. Changes are made like so: + +```dts title="-pinctrl.dtsi" +&pinctrl { + /* your modifications go here */ +}; +``` + +Within said node, you will configure one or more child nodes for the buses. You will want to define the child nodes according to the instructions in the `pinctrl.yaml` file. +The child nodes that you define should be named appropriately. The common naming schema is `usageNumber_state`. For example, `uart0_default`. + +Child nodes are (generally, there are[exceptions](https://docs.zephyrproject.org/3.5.0/hardware/pinctrl/index.html#pin-configuration)) expected to contain one or more subnodes typically named "groupX". These are for grouping together pins that should be assigned the same state, such as enabling an internal pull-up. +Below are some examples of SPI child nodes for the nRF52840 and the RP2040. Further examples are contained within the comments of the respecting `pinctrl.yaml` files. + + + +```dts title="-pinctrl.dtsi" +&pinctrl { + /* configuration for spi0 device, default state */ + spi0_default: spi0_default { + /* node name is arbitrary */ + group1 { + /* main role: configure P0.01 as SPI clock, P0.02 as SPI MOSI, P0.03 as SPI MISO */ + psels = , + , + ; + }; + }; + + /* configuration for spi0 device, sleep state */ + spi0_sleep: spi0_sleep { + group1 { + /* main role: configure P0.01 as SPI clock, P0.02 as SPI MOSI, P0.03 as SPI MISO */ + psels = , + , + ; + low-power-enable; + }; + }; + +}; + +```` +Pins are always selected via assignments to `psels`. `NRF_PSEL` is a helper macro with the following arguments: +- Pin function configuration. This is the `name` portion of one of the `NRF_FUNC_{name}` macros found in `zephyr/include/zephyr/dt-bindings/pinctrl/nrf-pinctrl.h`. +- Port (0 or 1). +- Pin (0 to 31). + +The following pin properties can be assigned to groups: + +- `bias-disable`: Disable pull-up/down (default behavior, not required). +- `bias-pull-up`: Enable pull-up resistor. +- `bias-pull-down`: Enable pull-down resistor. +- `low-power-enable`: Configure pin as an input with input buffer disconnected. + +Note that bias options are mutually exclusive. + +There is an additional child node for the "sleep" state, configuring the pins for low power. More on states will be explained later. + + +```dts title="-pinctrl.dtsi" +&pinctrl { + /* configuration for spi0 device, default state */ + spi0_default: spi0_default { + group1 { + /* configure P18 as SPI0 clock, P19 as SPI0 MOSI */ + pinmux = , ; + }; + group2 { + /* configure P16 as SPI0 MISO */ + pinmux = ; + /* enable input on pin 1 */ + input-enable; + }; + }; + + /* configuration for an spi device using PIO0, default state */ + pio0_spi_default: pio0_spi_default { + group1 { + /* Configure P13 and P14 for PIO, to be used for MOSI and SCK */ + pinmux = , ; + }; + group2 { + /* Configure P16 for PIO to be used for MISO with input */ + pinmux = ; + input-enable; + }; + }; +}; +```` + +The values that can be listed in `pinmux` to assign functionality to pins are listed in `zephyr/include/zephyr/dt-bindings/pinctrl/rpi-pico-rp2040-pinctrl.h`. + +The following pin properties can be assigned to groups: + +- `bias-disable`: Disable pull-up/down (default, not required). +- `bias-pull-up`: Enable pull-up resistor. +- `bias-pull-down`: Enable pull-down resistor. +- `input-enable`: Enable input from the pin. +- `input-schmitt-enable`: Enable input hysteresis. +- `drive-strength`: Set the drive strength of the pin, in milliamps. Possible values are: 2, 4, 8, 12 (default: 4mA) +- `slew-rate`: If set to 0, slew rate is set to slow. If set to 1, it is set to fast. + + + + +## Driver/Bus Node + +Once pin control for a driver/bus has been defined, you'll need to adjust another node defining the driver/bus. This adjustment can be done in a number of places by convention: + +- If defining a unique board, `.dts` +- If defining boards with multiple revisions/versions that share pin control, `-common.dtsi` (which is then included by each `_.dtsi`) +- If [configuring boards for a shield](#boards-shields-and-modules), directly in the `.overlay` file + +You'll want to identify the correct node for you to be changing. The nRF52840 has nodes defined in `dts/arm/nordic/nrf52840.dtsi`, while the RP2040 has nodes defined in `dts/arm/rpi_pico/rp2040.dtsi`. Always be aware of and account for other devices on your node, there may be some which you did not add yourself. + +Adjust the node like so: + + + +```dts title=".dts" +&spi0 { + compatible = "nordic,nrf-spim"; + pinctrl-0 = <&spi0_default>; + pinctrl-1 = <&spi0_sleep>; + pinctrl-names = "default", "sleep"; +}; +``` + + +```dts title=".dts" +&spi0 { + pinctrl-0 = <&spi0_default>; + pinctrl-names = "default"; +}; +``` + + +This assigns the pins defined in the previous section's examples to the `spi0` node. + +Notice that the nRF52840 assigns two items. This is because nodes making use of pin control come with two states by default (though they can have more), a `default` state and a `sleep` state. The nRF52840 can put pins into a "low power state", to reduce power consumption while on sleep. If the RP2040 node made use of pullup or pulldown resistors which had a risk of power leakage while asleep, then it would also define an additional `pinctrl` child node and assign it like in the nRF52840 example. + +The nRF52840 example also changes the `compatible` assignment to use SPIM rather than SPI, since it is taking on the "main" role. Check the datasheet for more information about SPIM. The RP2040 makes no such distinction. + +### Alias + +You may wish to provide an alias to the node for various reasons: + +- Compatibility with other boards, if defining for a shield +- Compatibility with an interconnect +- Easier personal use + +Aliases are assigned like so: + +```dts + my_alias_spi: &spi0 {}; +``` + +### Usage + +Once you have defined your node, you make use of it by further adjusting the node. You will most likely need to enable the node, as most nodes come disabled: + +```dts +&spi0 { + status = "okay"; +}; +``` + +You would then want to make any adjustments to the node that are necessary, for example adjusting the clock speed. See the Zephyr API documentation for your `compatible` property to see the available properties for customisation. It is recommended to read through the [description of important properties](https://docs.zephyrproject.org/3.5.0/build/dts/intro-syntax-structure.html#dt-important-props), potentially with the addition of [this blog post](https://interrupt.memfault.com/blog/practical_zephyr_dt#zephyrs-dts-skeleton-and-addressing) if `#address-cells` is confusing you. + +For SPI specifically, you would create a child node within your SPI bus for each device making use of the SPI bus. + +```dts +&spi0 { + cs-gpios = <&gpio0 15 GPIO_ACTIVE_LOW>, <&gpio0 17 GPIO_ACTIVE_LOW>; + device1: device@0 { + compatible = "manufacturer,device"; + reg = <0>; + spi-max-frequency = <1000000>; /* conservatively set to 1MHz */ + }; + device2: device@1 { + compatible = "manufacturer,device"; + reg = <1>; + spi-max-frequency = <1000000>; /* conservatively set to 1MHz */ + }; +}; +``` + +Additional information on configuring specific devices for use with SPI buses or similar can be found in other pages of the ZMK documentation, or in the Zephyr documentation. + +### RP2040 PIO + +The [previous RP2040 example](#pinctrl-node) also configured pins for use with an RP2040 PIO block. To use PIO with SPI (or another purpose) you'll need to adjust the `pio0` or `pio1` nodes as follows: + +```dts title=".dts" +#include "-pinctrl.dtsi" + +&pio0 { + /* enables this PIO block */ + status = "okay"; + pio0_spi: pio0_spi { + /* Assign pinctrl to node */ + pinctrl-0 = <&pio0_spi_default>; + pinctrl-names = "default"; + compatible = "raspberrypi,pico-spi-pio"; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&system_clk>; + clock-frequency = <4000000>; + /* These pins should be the same as in pinctrl */ + miso-gpios = <&gpio0 12 0>; + clk-gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>; + mosi-gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>; + + cs-gpios = <...>; // List of chip select gpios, one for each device + /* Nodes using the bus go here */ + }; +}; +``` + +Depending on the desired usage for PIO, you will want to adjust the `compatible` property and the SPI-specific properties (`miso-gpios`, `clk-gpios`, `mosi-gpios`). See the Zephyr API documentation for information about alternative PIO drivers. Once defined, SPI can be used via PIO as presented in the previous subsection, referring to `pio0_spi` (or similar) instead of `spi0`. + +### Additional examples + +Below are examples for UART and I2C, as the other two most common usages for pin control. + +#### UART nRF52840 + +In the pin control file: + +```dts +&pinctrl { + /* configuration for uart0 device, default state */ + uart0_default: uart0_default { + group1 { + /* configure P0.1 as UART_TX and P0.2 as UART_RTS */ + psels = , ; + }; + group2 { + /* configure P0.3 as UART_RX and P0.4 as UART_CTS */ + psels = , ; + /* both P0.3 and P0.4 are configured with pull-up */ + bias-pull-up; + }; + }; +}; +``` + +In the main file: + +```dts +#include "-pinctrl.dtsi" + +&uart0 { + pinctrl-0 = <&uart0_default>; + pinctrl-names = "default"; +}; +``` + +#### UART rp2040 + +In the pin control file: + +```dts +#include + +&pinctrl { + /* configuration for the usart0 "default" state */ + uart0_default: uart0_default { + group1 { + /* configure P0 as UART0 TX */ + pinmux = ; + }; + group2 { + /* configure P1 as UART0 RX */ + pinmux = ; + /* enable input on pin 1 */ + input-enable; + }; + }; +}; +``` + +In the main file: + +```dts +#include "-pinctrl.dtsi" + +&uart0 { + pinctrl-0 = <&uart0_default>; + pinctrl-names = "default"; +}; +``` + +#### UART RP2040 PIO + +In the pin control file: + +```dts +#include + +&pinctrl { + /* configuration for the uart0 "default" state */ + pio0_uart_default: pio0_uart_default { + /* tx pin, NAME IS NOT ARBITRARY */ + tx_pins { + /* configure P0 as UART0 TX */ + pinmux = ; + }; + /* rx pin, NAME IS NOT ARBITRARY */ + rx_pins { + /* configure P1 as UART0 RX */ + pinmux = ; + /* enable input on pin 1 */ + input-enable; + bias-pull-up; + }; + }; +}; +``` + +In the main file: + +```dts +#include "-pinctrl.dtsi" + +&pio0 { + status = "okay"; + + pio0_uart: serial { + status = "okay"; + compatible = "raspberrypi,pico-uart-pio"; + pinctrl-0 = <&pio0_uart_default>; + pinctrl-names = "default"; + current-speed = <115200>; + }; +}; +``` + +#### I2C nRF52840 + +Specifically for an I2C controller, aka Nordic TWIM. + +In the pin control file: + +```dts +&pinctrl { + /* configuration for i2c0 device, default state */ + i2c0_default: i2c0_default { + group1 { + psels = , + ; + }; + }; + + i2c0_sleep: i2c0_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; +}; +``` + +In the main file: + +```dts +#include "-pinctrl.dtsi" + +&i2c0 { + compatible = "nordic,nrf-twim"; // I2C controller instead of generic + status = "okay"; + pinctrl-0 = <&i2c0_default>; + pinctrl-1 = <&i2c0_sleep>; + pinctrl-names = "default", "sleep"; + clock-frequency = ; + + /* Nodes using the bus go here */ +}; +``` + +#### I2C RP2040 + +In the pin control file: + +```dts +#include + +&pinctrl { + /* configuration for the i2c0 "default" state */ + i2c0_default: i2c0_default { + group1 { + pinmux = , ; + input-enable; + input-schmitt-enable; + }; + }; +}; +``` + +In the main file: + +```dts +#include "-pinctrl.dtsi" + +&i2c0 { + status = "okay"; + pinctrl-0 = <&i2c0_default>; + pinctrl-names = "default"; + clock-frequency = ; + + /* Nodes using the bus go here */ +}; +``` + +#### I2C RP2040 PIO + +Zephyr currently does not have support for I2C using RP2040 PIO. diff --git a/docs/docs/development/hardware-integration/shift-registers.md b/docs/docs/development/hardware-integration/shift-registers.md index 0b575bc5..f2bd9977 100644 --- a/docs/docs/development/hardware-integration/shift-registers.md +++ b/docs/docs/development/hardware-integration/shift-registers.md @@ -29,76 +29,9 @@ ZMK allows you to daisy-chain up to four shift registers. Below is a fragment of ## Configuration -In ZMK, the SPI bus of your MCU is used to communicate with shift registers, using MOSI for SIPO shift registers and MISO for PISO shift registers. Thus you will first need to ensure that your board has SPI configured accordingly. Some boards, such as Seeed Studio's Xiao series, already has particular pins defined and configured for SPI (these can be changed if the MCU allows for alternative selections of SPI pins). Others, such as the nice!nano or any custom board, will need to be configured by you manually. Shift registers can share the SPI bus with other devices with no issues. +In ZMK, the SPI bus of your MCU is used to communicate with shift registers, using MOSI for SIPO shift registers and MISO for PISO shift registers. See [Pin Control](./pinctrl.mdx) for information on configuring the SPI bus. Shift registers can share the SPI bus with other devices with no issues. -### Configuring the SPI bus - -Configuring the pins directly varies depending on your architecture. Presented are methods for overwriting the default SPI bus definitions for boards running the nRF52840 MCU. Alternative MCUs will be similar; refer to the [Zephyr documentation](https://docs.zephyrproject.org/3.5.0/hardware/pinctrl/index.html) for these. Also refer to [Zephyr documentation](https://docs.zephyrproject.org/3.5.0/hardware/pinctrl/index.html) if you are defining a new bus rather than reconfiguring an existing one. - -:::info -This section can be skipped if you are using the default pins for SPI of a board, e.g. for the Seeed Studio Xiao the pin D8 for the clock signal and D10 for the data signal. However, if you are not making use of the MISO pin and wish to use said pin for alternative purposes, you will need to override the definition. -::: - -First, identify the high frequency pins that you are using for SPI by their port and pin number. This example will assume that: - -- Your SPI clock pin is port 1, pin 11 -- Your SPI MOSI pin is port 1, pin 12 - -Next, you'll need to identify the node label of the SPI bus you're overwriting. Look through your board's devicetree files, following the includes, for a node with `compatible = "nordic,nrf-spi";`. This node should have some properties marked as `pinctrl-X`, where `X` is a number. For example, you might find a node like below: - -```dts title="boards/arm/seeeduino_xiao_ble/seeeduino_xiao_ble.dts" -&spi2 { - compatible = "nordic,nrf-spi"; - pinctrl-0 = <&spi2_default>; - pinctrl-1 = <&spi2_sleep>; - pinctrl-names = "default", "sleep"; -}; -``` - -You will need to overwrite the pinctrl nodes to use your desired pins. Look through the devicetree files once again, this time looking for `spi2_default` and `spi2_sleep` (or the equivalently named nodes for your board). You should find nodes that look similar to below: - -```dts title="boards/arm/seeeduino_xiao_ble/seeeduino_xiao_ble-pinctrl.dtsi" -spi2_default: spi2_default { - group1 { - psels = , - , - ; - }; -}; - -spi2_sleep: spi2_sleep { - group1 { - psels = , - , - ; - low-power-enable; - }; -}; -``` - -Overwrite the pin definitions like so: - -```dts -&spi2_default { - group1 { - psels = , - ; - }; -}; - -&spi2_sleep { - group1 { - psels = , - ; - }; -}; -``` - -Note that for convenience, ZMK gives the `spi2` node of the Seeed Studio XIAO series the label `xiao_spi`. - -:::tip -If you are making a shield, add a `/boards/.overlay` file rather than editing the board's files directly. This will then be included in your board's definition when you build with your shield. -::: +Some boards, such as Seeed Studio's Xiao series, already has particular pins defined and configured for SPI (these can be changed if the MCU allows for alternative selections of SPI pins). Others, such as the nice!nano or any custom board, will need to be configured by you manually. ### Enable SPI diff --git a/docs/sidebars.js b/docs/sidebars.js index 4c278d4b..fa820f90 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -129,6 +129,7 @@ module.exports = { "development/hardware-integration/physical-layouts", "development/hardware-integration/hardware-metadata-files", "development/hardware-integration/boards-shields-keymaps", + "development/hardware-integration/pinctrl", "development/hardware-integration/shift-registers", "development/hardware-integration/encoders", ], diff --git a/docs/src/components/interconnect-tabs.tsx b/docs/src/components/interconnect-tabs.tsx index 8a7a0a4e..b18c4491 100644 --- a/docs/src/components/interconnect-tabs.tsx +++ b/docs/src/components/interconnect-tabs.tsx @@ -6,25 +6,21 @@ import { groupedMetadata, InterconnectDetails } from "./hardware-utils"; interface InterconnectTabsProps { items: HardwareMetadata[]; + gpio: Boolean; } -function mapInterconnect(interconnect: Interconnect) { +function mapInterconnect(interconnect: Interconnect, gpio: Boolean) { let content = require(`@site/src/data/interconnects/${interconnect.id}/design_guideline.md`); let imageUrl = require(`@site/docs/assets/interconnects/${interconnect.id}/pinout.png`); - return ( - - - - {interconnect.node_labels && ( + {gpio && } + {interconnect.node_labels && !gpio && ( <> +

The following node labels are available: