From 1751470785a110729afc01f3947b406bc40ceb43 Mon Sep 17 00:00:00 2001 From: Pete Johanson Date: Mon, 15 Jun 2020 17:03:34 -0400 Subject: [PATCH] Initial work on keymap transforms for non-standard matrixes. * Allows "gaps" for keyboards like Kyra. * Allows keyboards with matrixes that don't map the logical key locations to have normal looking keymaps when defined. --- app/boards/shields/kyria/Kconfig.defconfig | 7 + app/boards/shields/kyria/Kconfig.shield | 5 + .../kyria/keymaps/default/include/keymap.h | 5 + .../shields/kyria/keymaps/default/keymap.c | 34 + .../kyria/keymaps/default/keymap.overlay | 50 ++ app/boards/shields/kyria/kyria.conf | 0 app/boards/shields/kyria/kyria.overlay | 75 ++ app/dts/bindings/zmk,keymap-transform.yaml | 9 + app/dts/bindings/zmk,keymap.yaml | 4 + .../dt-bindings/zmk/keymap-transform.h | 13 + app/include/zmk/util.h | 777 ++++++++++++++++++ app/src/keymap.c | 49 ++ 12 files changed, 1028 insertions(+) create mode 100644 app/boards/shields/kyria/Kconfig.defconfig create mode 100644 app/boards/shields/kyria/Kconfig.shield create mode 100644 app/boards/shields/kyria/keymaps/default/include/keymap.h create mode 100644 app/boards/shields/kyria/keymaps/default/keymap.c create mode 100644 app/boards/shields/kyria/keymaps/default/keymap.overlay create mode 100644 app/boards/shields/kyria/kyria.conf create mode 100644 app/boards/shields/kyria/kyria.overlay create mode 100644 app/dts/bindings/zmk,keymap-transform.yaml create mode 100644 app/include/dt-bindings/zmk/keymap-transform.h create mode 100644 app/include/zmk/util.h diff --git a/app/boards/shields/kyria/Kconfig.defconfig b/app/boards/shields/kyria/Kconfig.defconfig new file mode 100644 index 00000000..0bd35625 --- /dev/null +++ b/app/boards/shields/kyria/Kconfig.defconfig @@ -0,0 +1,7 @@ + +if SHIELD_KYRIA + +config ZMK_KEYBOARD_NAME + default "Kyria" + +endif diff --git a/app/boards/shields/kyria/Kconfig.shield b/app/boards/shields/kyria/Kconfig.shield new file mode 100644 index 00000000..598fc81e --- /dev/null +++ b/app/boards/shields/kyria/Kconfig.shield @@ -0,0 +1,5 @@ +# Copyright (c) 2020 Pete Johanson +# SPDX-License-Identifier: MIT + +config SHIELD_KYRIA + def_bool $(shields_list_contains,kyria) diff --git a/app/boards/shields/kyria/keymaps/default/include/keymap.h b/app/boards/shields/kyria/keymaps/default/include/keymap.h new file mode 100644 index 00000000..01cd9e5b --- /dev/null +++ b/app/boards/shields/kyria/keymaps/default/include/keymap.h @@ -0,0 +1,5 @@ + +#include + +#define CC_RAIS ZC_CSTM(1) +#define CC_LOWR ZC_CSTM(2) \ No newline at end of file diff --git a/app/boards/shields/kyria/keymaps/default/keymap.c b/app/boards/shields/kyria/keymaps/default/keymap.c new file mode 100644 index 00000000..067cd08e --- /dev/null +++ b/app/boards/shields/kyria/keymaps/default/keymap.c @@ -0,0 +1,34 @@ + +#include +#include +#include + +bool zmk_handle_key_user(struct zmk_key_event *key_event) +{ + switch (key_event->key) + { + case CC_LOWR: + if (key_event->pressed) + { + zmk_keymap_layer_activate(1); + } + else + { + zmk_keymap_layer_deactivate(1); + } + + return false; + case CC_RAIS: + if (key_event->pressed) + { + zmk_keymap_layer_activate(2); + } + else + { + zmk_keymap_layer_deactivate(2); + } + return false; + } + + return true; +}; diff --git a/app/boards/shields/kyria/keymaps/default/keymap.overlay b/app/boards/shields/kyria/keymaps/default/keymap.overlay new file mode 100644 index 00000000..62c842d3 --- /dev/null +++ b/app/boards/shields/kyria/keymaps/default/keymap.overlay @@ -0,0 +1,50 @@ +#include +#include +#include + +/ { + chosen { + zmk,keymap = &keymap0; + }; + + keymap0: keymap { + compatible = "zmk,keymap"; + label ="Default Kyria Keymap"; + layers = <&default>; + transform = <&default_transform>; + }; + + default_transform: keymap_transform_0 { + compatible = "zmk,keymap-transform"; + map = < + IDENTITY_ROW(0, 6) OFFSET_ROW(6, 0, 6) + IDENTITY_ROW(1, 6) OFFSET_ROW(6, 1, 6) + IDENTITY_ROW(2, 8) OFFSET_ROW(8, 2, 8) + OFFSET_ROW(3, 3, 5) OFFSET_ROW(8, 3, 5) + >; + }; + + five_column_transform: keymap_transform_1 { + compatible = "zmk,keymap-transform"; + map = < + IDENTITY_ROW(0, 5) OFFSET_ROW(5, 0, 5) + IDENTITY_ROW(1, 5) OFFSET_ROW(6, 1, 5) + IDENTITY_ROW(2, 7) OFFSET_ROW(7, 2, 7) + OFFSET_ROW(2, 3, 5) OFFSET_ROW(7, 3, 5) + >; + }; + + layers { + compatible = "zmk,layers"; + + default: layer_0 { + label = "DEFAULT"; + keys = < + KC_ESC KC_Q KC_W KC_E KC_R KC_T KC_Y KC_U KC_I KC_O KC_P KC_PIPE + KC_BKSP KC_A KC_S KC_D KC_F KC_G KC_H KC_J KC_K KC_L KC_SCLN KC_QUOT + KC_LSFT KC_Z KC_X KC_C KC_V KC_B KC_LSFT KC_LSFT KC_LSFT KC_LSFT KC_N KC_M KC_CMMA KC_DOT KC_BSLH KC_MIN + KC_LGUI KC_DEL KC_RET KC_SPC KC_ESC KC_RET KC_SPC KC_TAB KC_BKSP KC_RALT + >; + }; + }; +}; diff --git a/app/boards/shields/kyria/kyria.conf b/app/boards/shields/kyria/kyria.conf new file mode 100644 index 00000000..e69de29b diff --git a/app/boards/shields/kyria/kyria.overlay b/app/boards/shields/kyria/kyria.overlay new file mode 100644 index 00000000..af4e591c --- /dev/null +++ b/app/boards/shields/kyria/kyria.overlay @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2020 Pete Johanson + * + * SPDX-License-Identifier: MIT + */ + +/ { + chosen { + zmk,kscan = &kscan0; + }; + + kscan0: kscan_comp { + compatible = "zmk,kscan-composite"; + + label = "KSCAN_COMP"; + rows = <4>; + columns = <16>; + + left { + kscan = <&kscan_left>; + }; + + right { + kscan = <&kscan_right>; + // TODO: Actually put this in the kscan driver, so it can report + // HID events directly to host if plugged in directly. + column-offset = <8>; + }; + }; + + kscan_left: kscan_left { + compatible = "gpio-kscan"; + label = "KSCAN_LEFT"; + + diode-direction = "row2col"; + row-gpios = <&pro_micro_pins 8 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>, + <&pro_micro_pins 7 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>, + <&pro_micro_pins 6 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>, + <&pro_micro_pins 4 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + + col-gpios = <&pro_micro_pins 10 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>, + <&pro_micro_pins 16 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>, + <&pro_micro_pins 14 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>, + <&pro_micro_pins 15 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>, + <&pro_micro_pins 18 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>, + <&pro_micro_pins 19 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>, + <&pro_micro_pins 20 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>, + <&pro_micro_pins 21 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + }; + + kscan_right: kscan_right { + compatible = "gpio-kscan"; + label = "KSCAN_RIGHT"; + + diode-direction = "row2col"; + row-gpios = <&pro_micro_pins 8 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>, + <&pro_micro_pins 7 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>, + <&pro_micro_pins 6 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>, + <&pro_micro_pins 4 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + + col-gpios = <&pro_micro_pins 21 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>, + <&pro_micro_pins 20 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>, + <&pro_micro_pins 19 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>, + <&pro_micro_pins 18 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>, + <&pro_micro_pins 15 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>, + <&pro_micro_pins 14 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>, + <&pro_micro_pins 16 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>, + <&pro_micro_pins 10 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + }; + + // TODO: Encoder node(s) + // TODO: OLED node + // TODO: RGB node(s) +}; + diff --git a/app/dts/bindings/zmk,keymap-transform.yaml b/app/dts/bindings/zmk,keymap-transform.yaml new file mode 100644 index 00000000..24c3836e --- /dev/null +++ b/app/dts/bindings/zmk,keymap-transform.yaml @@ -0,0 +1,9 @@ +description: | + Defines a mapping from keymap logical positions to matrix physical positions + +compatible: "zmk,keymap-transform" + +properties: + map: + type: array + required: true diff --git a/app/dts/bindings/zmk,keymap.yaml b/app/dts/bindings/zmk,keymap.yaml index 8c56f93c..b9517a34 100644 --- a/app/dts/bindings/zmk,keymap.yaml +++ b/app/dts/bindings/zmk,keymap.yaml @@ -4,6 +4,10 @@ description: | compatible: "zmk,keymap" properties: + transform: + type: phandle + required: false + label: type: string required: true diff --git a/app/include/dt-bindings/zmk/keymap-transform.h b/app/include/dt-bindings/zmk/keymap-transform.h new file mode 100644 index 00000000..af19c21e --- /dev/null +++ b/app/include/dt-bindings/zmk/keymap-transform.h @@ -0,0 +1,13 @@ + +#include + +#define KT_ROW(item) (item >> 8) +#define KT_COL(item) (item & 0xFF) + +#define _ROW_COL(row, col) (((row) << 8) + (col)) + +#define _IDENTITY_ENTRY(col, row) _ROW_COL(row, col) +#define IDENTITY_ROW(row, count) UTIL_LISTIFY(count, _IDENTITY_ENTRY, row) + +#define _OFFSET_ENTRY(col, offset, row) _ROW_COL(row, col + offset) +#define OFFSET_ROW(offset, row, count) UTIL_LISTIFY(count, _OFFSET_ENTRY, offset, row) \ No newline at end of file diff --git a/app/include/zmk/util.h b/app/include/zmk/util.h new file mode 100644 index 00000000..0436b6fb --- /dev/null +++ b/app/include/zmk/util.h @@ -0,0 +1,777 @@ +/* + * Copyright (c) 2011-2014, Wind River Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +/** @brief Return larger value of two provided expressions. + * + * @note Arguments are evaluated twice. See Z_MAX for GCC only, single + * evaluation version. + */ +#ifndef MAX +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#endif + +/** @brief Return smaller value of two provided expressions. + * + * @note Arguments are evaluated twice. See Z_MIN for GCC only, single + * evaluation version. + */ +#ifndef MIN +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#endif + +#define BIT(n) (1UL << (n)) + +/** 64-bit unsigned integer with bit position _n set */ +#define BIT64(_n) (1ULL << (_n)) + +/** + * @brief Macro sets or clears bit depending on boolean value + * + * @param var Variable to be altered + * @param bit Bit number + * @param set Value 0 clears bit, any other value sets bit + */ +#define WRITE_BIT(var, bit, set) \ + ((var) = (set) ? ((var) | BIT(bit)) : ((var) & ~BIT(bit))) + +#define BIT_MASK(n) (BIT(n) - 1) + +/** + * @brief Macro with empty replacement list + * + * This trivial definition is provided to use where macro is expected + * to evaluate to empty replacement string or when it is needed to + * cheat checkpatch. + * + * Examples + * + * #define LIST_ITEM(n) , item##n + * + * would cause error with checkpatch, but: + * + * #define LIST_TIEM(n) EMPTY, item##m + * + * would not. + */ +#define EMPTY + +/** + * @brief Get first argument from variable list of arguments + */ +#define GET_ARG1(arg1, ...) arg1 + +/** + * @brief Get second argument from variable list of arguments + */ +#define GET_ARG2(arg1, arg2, ...) arg2 + +/** + * @brief Get all arguments except the first one. + */ +#define GET_ARGS_LESS_1(val, ...) __VA_ARGS__ + +/** + * Macros for doing code-generation with the preprocessor. + * + * Generally it is better to generate code with the preprocessor than + * to copy-paste code or to generate code with the build system / + * python script's etc. + * + * http://stackoverflow.com/a/12540675 + */ +#define UTIL_EMPTY(...) +#define UTIL_DEFER(...) __VA_ARGS__ UTIL_EMPTY() +#define UTIL_OBSTRUCT(...) __VA_ARGS__ UTIL_DEFER(UTIL_EMPTY)() +#define UTIL_EXPAND(...) __VA_ARGS__ + +#define UTIL_EVAL(...) UTIL_EVAL1(UTIL_EVAL1(UTIL_EVAL1(__VA_ARGS__))) +#define UTIL_EVAL1(...) UTIL_EVAL2(UTIL_EVAL2(UTIL_EVAL2(__VA_ARGS__))) +#define UTIL_EVAL2(...) UTIL_EVAL3(UTIL_EVAL3(UTIL_EVAL3(__VA_ARGS__))) +#define UTIL_EVAL3(...) UTIL_EVAL4(UTIL_EVAL4(UTIL_EVAL4(__VA_ARGS__))) +#define UTIL_EVAL4(...) UTIL_EVAL5(UTIL_EVAL5(UTIL_EVAL5(__VA_ARGS__))) +#define UTIL_EVAL5(...) __VA_ARGS__ + +#define UTIL_CAT(a, ...) UTIL_PRIMITIVE_CAT(a, __VA_ARGS__) +#define UTIL_PRIMITIVE_CAT(a, ...) a##__VA_ARGS__ + +#define UTIL_INC(x) UTIL_PRIMITIVE_CAT(UTIL_INC_, x) +#define UTIL_INC_0 1 +#define UTIL_INC_1 2 +#define UTIL_INC_2 3 +#define UTIL_INC_3 4 +#define UTIL_INC_4 5 +#define UTIL_INC_5 6 +#define UTIL_INC_6 7 +#define UTIL_INC_7 8 +#define UTIL_INC_8 9 +#define UTIL_INC_9 10 +#define UTIL_INC_10 11 +#define UTIL_INC_11 12 +#define UTIL_INC_12 13 +#define UTIL_INC_13 14 +#define UTIL_INC_14 15 +#define UTIL_INC_15 16 +#define UTIL_INC_16 17 +#define UTIL_INC_17 18 +#define UTIL_INC_18 19 +#define UTIL_INC_19 20 +#define UTIL_INC_20 21 +#define UTIL_INC_21 22 +#define UTIL_INC_22 23 +#define UTIL_INC_23 24 +#define UTIL_INC_24 25 +#define UTIL_INC_25 26 +#define UTIL_INC_26 27 +#define UTIL_INC_27 28 +#define UTIL_INC_28 29 +#define UTIL_INC_29 30 +#define UTIL_INC_30 31 +#define UTIL_INC_31 32 +#define UTIL_INC_32 33 +#define UTIL_INC_33 34 +#define UTIL_INC_34 35 +#define UTIL_INC_35 36 +#define UTIL_INC_36 37 +#define UTIL_INC_37 38 +#define UTIL_INC_38 39 +#define UTIL_INC_39 40 +#define UTIL_INC_40 41 +#define UTIL_INC_41 42 +#define UTIL_INC_42 43 +#define UTIL_INC_43 44 +#define UTIL_INC_44 45 +#define UTIL_INC_45 46 +#define UTIL_INC_46 47 +#define UTIL_INC_47 48 +#define UTIL_INC_48 49 +#define UTIL_INC_49 50 +#define UTIL_INC_50 51 +#define UTIL_INC_51 52 +#define UTIL_INC_52 53 +#define UTIL_INC_53 54 +#define UTIL_INC_54 55 +#define UTIL_INC_55 56 +#define UTIL_INC_56 57 +#define UTIL_INC_57 58 +#define UTIL_INC_58 59 +#define UTIL_INC_59 60 +#define UTIL_INC_50 51 +#define UTIL_INC_51 52 +#define UTIL_INC_52 53 +#define UTIL_INC_53 54 +#define UTIL_INC_54 55 +#define UTIL_INC_55 56 +#define UTIL_INC_56 57 +#define UTIL_INC_57 58 +#define UTIL_INC_58 59 +#define UTIL_INC_59 60 +#define UTIL_INC_60 61 +#define UTIL_INC_61 62 +#define UTIL_INC_62 63 +#define UTIL_INC_63 64 +#define UTIL_INC_64 65 +#define UTIL_INC_65 66 +#define UTIL_INC_66 67 +#define UTIL_INC_67 68 +#define UTIL_INC_68 69 +#define UTIL_INC_69 70 +#define UTIL_INC_70 71 +#define UTIL_INC_71 72 +#define UTIL_INC_72 73 +#define UTIL_INC_73 74 +#define UTIL_INC_74 75 +#define UTIL_INC_75 76 +#define UTIL_INC_76 77 +#define UTIL_INC_77 78 +#define UTIL_INC_78 79 +#define UTIL_INC_79 80 +#define UTIL_INC_80 81 +#define UTIL_INC_81 82 +#define UTIL_INC_82 83 +#define UTIL_INC_83 84 +#define UTIL_INC_84 85 +#define UTIL_INC_85 86 +#define UTIL_INC_86 87 +#define UTIL_INC_87 88 +#define UTIL_INC_88 89 +#define UTIL_INC_89 90 +#define UTIL_INC_90 91 +#define UTIL_INC_91 92 +#define UTIL_INC_92 93 +#define UTIL_INC_93 94 +#define UTIL_INC_94 95 +#define UTIL_INC_95 96 +#define UTIL_INC_96 97 +#define UTIL_INC_97 98 +#define UTIL_INC_98 99 +#define UTIL_INC_99 100 + +#define UTIL_DEC(x) UTIL_PRIMITIVE_CAT(UTIL_DEC_, x) +#define UTIL_DEC_0 0 +#define UTIL_DEC_1 0 +#define UTIL_DEC_2 1 +#define UTIL_DEC_3 2 +#define UTIL_DEC_4 3 +#define UTIL_DEC_5 4 +#define UTIL_DEC_6 5 +#define UTIL_DEC_7 6 +#define UTIL_DEC_8 7 +#define UTIL_DEC_9 8 +#define UTIL_DEC_10 9 +#define UTIL_DEC_11 10 +#define UTIL_DEC_12 11 +#define UTIL_DEC_13 12 +#define UTIL_DEC_14 13 +#define UTIL_DEC_15 14 +#define UTIL_DEC_16 15 +#define UTIL_DEC_17 16 +#define UTIL_DEC_18 17 +#define UTIL_DEC_19 18 +#define UTIL_DEC_20 19 +#define UTIL_DEC_21 20 +#define UTIL_DEC_22 21 +#define UTIL_DEC_23 22 +#define UTIL_DEC_24 23 +#define UTIL_DEC_25 24 +#define UTIL_DEC_26 25 +#define UTIL_DEC_27 26 +#define UTIL_DEC_28 27 +#define UTIL_DEC_29 28 +#define UTIL_DEC_30 29 +#define UTIL_DEC_31 30 +#define UTIL_DEC_32 31 +#define UTIL_DEC_33 32 +#define UTIL_DEC_34 33 +#define UTIL_DEC_35 34 +#define UTIL_DEC_36 35 +#define UTIL_DEC_37 36 +#define UTIL_DEC_38 37 +#define UTIL_DEC_39 38 +#define UTIL_DEC_40 39 +#define UTIL_DEC_41 40 +#define UTIL_DEC_42 41 +#define UTIL_DEC_43 42 +#define UTIL_DEC_44 43 +#define UTIL_DEC_45 44 +#define UTIL_DEC_46 45 +#define UTIL_DEC_47 46 +#define UTIL_DEC_48 47 +#define UTIL_DEC_49 48 +#define UTIL_DEC_50 49 +#define UTIL_DEC_51 50 +#define UTIL_DEC_52 51 +#define UTIL_DEC_53 52 +#define UTIL_DEC_54 53 +#define UTIL_DEC_55 54 +#define UTIL_DEC_56 55 +#define UTIL_DEC_57 56 +#define UTIL_DEC_58 57 +#define UTIL_DEC_59 58 +#define UTIL_DEC_60 59 +#define UTIL_DEC_61 60 +#define UTIL_DEC_62 61 +#define UTIL_DEC_63 62 +#define UTIL_DEC_64 63 +#define UTIL_DEC_65 64 +#define UTIL_DEC_66 65 +#define UTIL_DEC_67 66 +#define UTIL_DEC_68 67 +#define UTIL_DEC_69 68 +#define UTIL_DEC_70 69 +#define UTIL_DEC_71 70 +#define UTIL_DEC_72 71 +#define UTIL_DEC_73 72 +#define UTIL_DEC_74 73 +#define UTIL_DEC_75 74 +#define UTIL_DEC_76 75 +#define UTIL_DEC_77 76 +#define UTIL_DEC_78 77 +#define UTIL_DEC_79 78 +#define UTIL_DEC_80 79 +#define UTIL_DEC_81 80 +#define UTIL_DEC_82 81 +#define UTIL_DEC_83 82 +#define UTIL_DEC_84 83 +#define UTIL_DEC_85 84 +#define UTIL_DEC_86 85 +#define UTIL_DEC_87 86 +#define UTIL_DEC_88 87 +#define UTIL_DEC_89 88 +#define UTIL_DEC_90 89 +#define UTIL_DEC_91 90 +#define UTIL_DEC_92 91 +#define UTIL_DEC_93 92 +#define UTIL_DEC_94 93 +#define UTIL_DEC_95 94 +#define UTIL_DEC_96 95 +#define UTIL_DEC_97 96 +#define UTIL_DEC_98 97 +#define UTIL_DEC_99 98 +#define UTIL_DEC_100 99 +#define UTIL_DEC_101 100 +#define UTIL_DEC_102 101 +#define UTIL_DEC_103 102 +#define UTIL_DEC_104 103 +#define UTIL_DEC_105 104 +#define UTIL_DEC_106 105 +#define UTIL_DEC_107 106 +#define UTIL_DEC_108 107 +#define UTIL_DEC_109 108 +#define UTIL_DEC_110 109 +#define UTIL_DEC_111 110 +#define UTIL_DEC_112 111 +#define UTIL_DEC_113 112 +#define UTIL_DEC_114 113 +#define UTIL_DEC_115 114 +#define UTIL_DEC_116 115 +#define UTIL_DEC_117 116 +#define UTIL_DEC_118 117 +#define UTIL_DEC_119 118 +#define UTIL_DEC_120 119 +#define UTIL_DEC_121 120 +#define UTIL_DEC_122 121 +#define UTIL_DEC_123 122 +#define UTIL_DEC_124 123 +#define UTIL_DEC_125 124 +#define UTIL_DEC_126 125 +#define UTIL_DEC_127 126 +#define UTIL_DEC_128 127 +#define UTIL_DEC_129 128 +#define UTIL_DEC_130 129 +#define UTIL_DEC_131 130 +#define UTIL_DEC_132 131 +#define UTIL_DEC_133 132 +#define UTIL_DEC_134 133 +#define UTIL_DEC_135 134 +#define UTIL_DEC_136 135 +#define UTIL_DEC_137 136 +#define UTIL_DEC_138 137 +#define UTIL_DEC_139 138 +#define UTIL_DEC_140 139 +#define UTIL_DEC_141 140 +#define UTIL_DEC_142 141 +#define UTIL_DEC_143 142 +#define UTIL_DEC_144 143 +#define UTIL_DEC_145 144 +#define UTIL_DEC_146 145 +#define UTIL_DEC_147 146 +#define UTIL_DEC_148 147 +#define UTIL_DEC_149 148 +#define UTIL_DEC_150 149 +#define UTIL_DEC_151 150 +#define UTIL_DEC_152 151 +#define UTIL_DEC_153 152 +#define UTIL_DEC_154 153 +#define UTIL_DEC_155 154 +#define UTIL_DEC_156 155 +#define UTIL_DEC_157 156 +#define UTIL_DEC_158 157 +#define UTIL_DEC_159 158 +#define UTIL_DEC_160 159 +#define UTIL_DEC_161 160 +#define UTIL_DEC_162 161 +#define UTIL_DEC_163 162 +#define UTIL_DEC_164 163 +#define UTIL_DEC_165 164 +#define UTIL_DEC_166 165 +#define UTIL_DEC_167 166 +#define UTIL_DEC_168 167 +#define UTIL_DEC_169 168 +#define UTIL_DEC_170 169 +#define UTIL_DEC_171 170 +#define UTIL_DEC_172 171 +#define UTIL_DEC_173 172 +#define UTIL_DEC_174 173 +#define UTIL_DEC_175 174 +#define UTIL_DEC_176 175 +#define UTIL_DEC_177 176 +#define UTIL_DEC_178 177 +#define UTIL_DEC_179 178 +#define UTIL_DEC_180 179 +#define UTIL_DEC_181 180 +#define UTIL_DEC_182 181 +#define UTIL_DEC_183 182 +#define UTIL_DEC_184 183 +#define UTIL_DEC_185 184 +#define UTIL_DEC_186 185 +#define UTIL_DEC_187 186 +#define UTIL_DEC_188 187 +#define UTIL_DEC_189 188 +#define UTIL_DEC_190 189 +#define UTIL_DEC_191 190 +#define UTIL_DEC_192 191 +#define UTIL_DEC_193 192 +#define UTIL_DEC_194 193 +#define UTIL_DEC_195 194 +#define UTIL_DEC_196 195 +#define UTIL_DEC_197 196 +#define UTIL_DEC_198 197 +#define UTIL_DEC_199 198 +#define UTIL_DEC_200 199 +#define UTIL_DEC_201 200 +#define UTIL_DEC_202 201 +#define UTIL_DEC_203 202 +#define UTIL_DEC_204 203 +#define UTIL_DEC_205 204 +#define UTIL_DEC_206 205 +#define UTIL_DEC_207 206 +#define UTIL_DEC_208 207 +#define UTIL_DEC_209 208 +#define UTIL_DEC_210 209 +#define UTIL_DEC_211 210 +#define UTIL_DEC_212 211 +#define UTIL_DEC_213 212 +#define UTIL_DEC_214 213 +#define UTIL_DEC_215 214 +#define UTIL_DEC_216 215 +#define UTIL_DEC_217 216 +#define UTIL_DEC_218 217 +#define UTIL_DEC_219 218 +#define UTIL_DEC_220 219 +#define UTIL_DEC_221 220 +#define UTIL_DEC_222 221 +#define UTIL_DEC_223 222 +#define UTIL_DEC_224 223 +#define UTIL_DEC_225 224 +#define UTIL_DEC_226 225 +#define UTIL_DEC_227 226 +#define UTIL_DEC_228 227 +#define UTIL_DEC_229 228 +#define UTIL_DEC_230 229 +#define UTIL_DEC_231 230 +#define UTIL_DEC_232 231 +#define UTIL_DEC_233 232 +#define UTIL_DEC_234 233 +#define UTIL_DEC_235 234 +#define UTIL_DEC_236 235 +#define UTIL_DEC_237 236 +#define UTIL_DEC_238 237 +#define UTIL_DEC_239 238 +#define UTIL_DEC_240 239 +#define UTIL_DEC_241 240 +#define UTIL_DEC_242 241 +#define UTIL_DEC_243 242 +#define UTIL_DEC_244 243 +#define UTIL_DEC_245 244 +#define UTIL_DEC_246 245 +#define UTIL_DEC_247 246 +#define UTIL_DEC_248 247 +#define UTIL_DEC_249 248 +#define UTIL_DEC_250 249 +#define UTIL_DEC_251 250 +#define UTIL_DEC_252 251 +#define UTIL_DEC_253 252 +#define UTIL_DEC_254 253 +#define UTIL_DEC_255 254 +#define UTIL_DEC_256 255 + +#define UTIL_CHECK_N(x, n, ...) n +#define UTIL_CHECK(...) UTIL_CHECK_N(__VA_ARGS__, 0,) + +#define UTIL_NOT(x) UTIL_CHECK(UTIL_PRIMITIVE_CAT(UTIL_NOT_, x)) +#define UTIL_NOT_0 ~, 1, + +#define UTIL_COMPL(b) UTIL_PRIMITIVE_CAT(UTIL_COMPL_, b) +#define UTIL_COMPL_0 1 +#define UTIL_COMPL_1 0 + +#define UTIL_BOOL(x) UTIL_COMPL(UTIL_NOT(x)) + +#define UTIL_IIF(c) UTIL_PRIMITIVE_CAT(UTIL_IIF_, c) +#define UTIL_IIF_0(t, ...) __VA_ARGS__ +#define UTIL_IIF_1(t, ...) t + +#define UTIL_IF(c) UTIL_IIF(UTIL_BOOL(c)) + +/* + * These are like || and &&, but they do evaluation and + * short-circuiting at preprocessor time instead of runtime. + * + * UTIL_OR(foo, bar) is sometimes a replacement for (foo || bar) + * when "bar" is an expression that would cause a build + * error when "foo" is true. + * + * UTIL_AND(foo, bar) is sometimes a replacement for (foo && bar) + * when "bar" is an expression that would cause a build + * error when "foo" is false. + */ +#define UTIL_OR(a, b) COND_CODE_1(UTIL_BOOL(a), (a), (b)) +#define UTIL_AND(a, b) COND_CODE_1(UTIL_BOOL(a), (b), (0)) + +#define UTIL_EAT(...) +#define UTIL_EXPAND(...) __VA_ARGS__ +#define UTIL_WHEN(c) UTIL_IF(c)(UTIL_EXPAND, UTIL_EAT) + +#define UTIL_REPEAT(count, macro, ...) \ + UTIL_WHEN(count) \ + ( \ + UTIL_OBSTRUCT(UTIL_REPEAT_INDIRECT) () \ + ( \ + UTIL_DEC(count), macro, __VA_ARGS__ \ + ) \ + UTIL_OBSTRUCT(macro) \ + ( \ + UTIL_DEC(count), __VA_ARGS__ \ + ) \ + ) +#define UTIL_REPEAT_INDIRECT() UTIL_REPEAT + +/** + * @brief Generates a sequence of code. + * + * Useful for generating code like; + * + * NRF_PWM0, NRF_PWM1, NRF_PWM2, + * + * @arg LEN: The length of the sequence. Must be defined and less than + * 20. + * + * @arg F(i, ...): A macro function that accepts at least two arguments. + * F is called repeatedly, the first argument is the index in the sequence, + * the variable list of arguments passed to UTIL_LISTIFY are passed through + * to F. + * + * Example: + * + * \#define FOO(i, _) NRF_PWM ## i , + * { UTIL_LISTIFY(PWM_COUNT, FOO) } + * The above two lines will generate the below: + * { NRF_PWM0 , NRF_PWM1 , } + * + * @note Calling UTIL_LISTIFY with undefined arguments has undefined + * behavior. + */ +#define UTIL_LISTIFY(LEN, F, ...) UTIL_EVAL(UTIL_REPEAT(LEN, F, __VA_ARGS__)) + +/* Set of internal macros used for FOR_EACH series of macros. */ +#define Z_FOR_EACH_IDX(count, n, macro, semicolon, fixed_arg0, fixed_arg1, ...)\ + UTIL_WHEN(count) \ + ( \ + UTIL_OBSTRUCT(macro) \ + ( \ + fixed_arg0, fixed_arg1, n, GET_ARG1(__VA_ARGS__)\ + )semicolon \ + UTIL_OBSTRUCT(Z_FOR_EACH_IDX_INDIRECT) () \ + ( \ + UTIL_DEC(count), UTIL_INC(n), macro, semicolon, \ + fixed_arg0, fixed_arg1, \ + GET_ARGS_LESS_1(__VA_ARGS__) \ + ) \ + ) + +#define Z_FOR_EACH_IDX_INDIRECT() Z_FOR_EACH_IDX + +#define Z_FOR_EACH_IDX2(count, iter, macro, sc, fixed_arg0, fixed_arg1, ...) \ + UTIL_EVAL(Z_FOR_EACH_IDX(count, iter, macro, sc,\ + fixed_arg0, fixed_arg1, __VA_ARGS__)) + +#define Z_FOR_EACH_SWALLOW_NOTHING(F, fixed_arg, index, arg) \ + F(index, arg, fixed_arg) + +#define Z_FOR_EACH_SWALLOW_FIXED_ARG(F, fixed_arg, index, arg) F(index, arg) + +#define Z_FOR_EACH_SWALLOW_INDEX_FIXED_ARG(F, fixed_arg, index, arg) F(arg) +#define Z_FOR_EACH_SWALLOW_INDEX(F, fixed_arg, index, arg) F(arg, fixed_arg) + +/** + * @brief Calls macro F for each provided argument with index as first argument + * and nth parameter as the second argument. + * + * Example: + * + * #define F(idx, x) int a##idx = x; + * FOR_EACH_IDX(F, 4, 5, 6) + * + * will result in following code: + * + * int a0 = 4; + * int a1 = 5; + * int a2 = 6; + * + * @param F Macro takes index and first argument and nth variable argument as + * the second one. + * @param ... Variable list of argument. For each argument macro F is executed. + */ +#define FOR_EACH_IDX(F, ...) \ + Z_FOR_EACH_IDX2(NUM_VA_ARGS_LESS_1(__VA_ARGS__, _), \ + 0, Z_FOR_EACH_SWALLOW_FIXED_ARG, /*no ;*/, \ + F, 0, __VA_ARGS__) + +/** + * @brief Calls macro F for each provided argument with index as first argument + * and nth parameter as the second argument and fixed argument as the + * third one. + * + * Example: + * + * #define F(idx, x, fixed_arg) int fixed_arg##idx = x; + * FOR_EACH_IDX_FIXED_ARG(F, a, 4, 5, 6) + * + * will result in following code: + * + * int a0 = 4; + * int a1 = 5; + * int a2 = 6; + * + * @param F Macro takes index and first argument and nth variable argument as + * the second one and fixed argumnet as the third. + * @param fixed_arg Fixed argument passed to F macro. + * @param ... Variable list of argument. For each argument macro F is executed. + */ +#define FOR_EACH_IDX_FIXED_ARG(F, fixed_arg, ...) \ + Z_FOR_EACH_IDX2(NUM_VA_ARGS_LESS_1(__VA_ARGS__, _), \ + 0, Z_FOR_EACH_SWALLOW_NOTHING, /*no ;*/, \ + F, fixed_arg, __VA_ARGS__) + +/** + * @brief Calls macro F for each provided argument. + * + * Example: + * + * #define F(x) int a##x; + * FOR_EACH(F, 4, 5, 6) + * + * will result in following code: + * + * int a4; + * int a5; + * int a6; + * + * @param F Macro takes nth variable argument as the argument. + * @param ... Variable list of argument. For each argument macro F is executed. + */ +#define FOR_EACH(F, ...) \ + Z_FOR_EACH_IDX2(NUM_VA_ARGS_LESS_1(__VA_ARGS__, _), \ + 0, Z_FOR_EACH_SWALLOW_INDEX_FIXED_ARG, /*no ;*/, \ + F, 0, __VA_ARGS__) + +/** + * @brief Calls macro F for each provided argument with additional fixed + * argument. + * + * After each iteration semicolon is added. + * + * Example: + * + * static void func(int val, void *dev); + * FOR_EACH_FIXED_ARG(func, dev, 4, 5, 6) + * + * will result in following code: + * + * func(4, dev); + * func(5, dev); + * func(6, dev); + * + * @param F Macro takes nth variable argument as the first parameter and + * fixed argument as the second parameter. + * @param fixed_arg Fixed argument forward to macro execution for each argument. + * @param ... Variable list of argument. For each argument macro F is executed. + */ +#define FOR_EACH_FIXED_ARG(F, fixed_arg, ...) \ + Z_FOR_EACH_IDX2(NUM_VA_ARGS_LESS_1(__VA_ARGS__, _), \ + 0, Z_FOR_EACH_SWALLOW_INDEX, ;, \ + F, fixed_arg, __VA_ARGS__) + +/**@brief Implementation details for NUM_VAR_ARGS */ +#define NUM_VA_ARGS_LESS_1_IMPL( \ + _ignored, \ + _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, N, ...) N + +/** + * @brief Macro to get the number of arguments in a call variadic macro call. + * First argument is not counted. + * + * param[in] ... List of arguments + * + * @retval Number of variadic arguments in the argument list + */ +#define NUM_VA_ARGS_LESS_1(...) \ + NUM_VA_ARGS_LESS_1_IMPL(__VA_ARGS__, 63, 62, 61, \ + 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, \ + 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, \ + 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, \ + 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, \ + 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, \ + 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, ~) + +/** + * Macro that process all arguments using given macro + * + * @deprecated Use FOR_EACH instead. + * + * @param ... Macro name to be used for argument processing followed by + * arguments to process. Macro should have following + * form: MACRO(argument). + * + * @return All arguments processed by given macro + */ +#define MACRO_MAP(...) __DEPRECATED_MACRO FOR_EACH(__VA_ARGS__) + +/** + * @brief Mapping macro that pastes results together + * + * Like @ref MACRO_MAP(), but pastes the results together into a + * single token by repeated application of @ref UTIL_CAT(). + * + * For example, with this macro FOO: + * + * #define FOO(x) item_##x##_ + * + * MACRO_MAP_CAT(FOO, a, b, c) expands to the token: + * + * item_a_item_b_item_c_ + * + * @param ... Macro to expand on each argument, followed by its + * arguments. (The macro should take exactly one argument.) + * @return The results of expanding the macro on each argument, all pasted + * together + */ +#define MACRO_MAP_CAT(...) MACRO_MAP_CAT_(__VA_ARGS__) +#define MACRO_MAP_CAT_(...) \ + /* To make sure it works also for 2 arguments in total */ \ + MACRO_MAP_CAT_N(NUM_VA_ARGS_LESS_1(__VA_ARGS__), __VA_ARGS__) + +/** + * @brief Mapping macro that pastes a fixed number of results together + * + * Similar to @ref MACRO_MAP_CAT(), but expects a fixed number of + * arguments. If more arguments are given than are expected, the rest + * are ignored. + * + * @param N Number of arguments to map + * @param ... Macro to expand on each argument, followed by its + * arguments. (The macro should take exactly one argument.) + * @return The results of expanding the macro on each argument, all pasted + * together + */ +#define MACRO_MAP_CAT_N(N, ...) MACRO_MAP_CAT_N_(N, __VA_ARGS__) +#define MACRO_MAP_CAT_N_(N, ...) UTIL_CAT(MACRO_MC_, N)(__VA_ARGS__,) + +#define MACRO_MC_0(...) +#define MACRO_MC_1(m, a, ...) m(a) +#define MACRO_MC_2(m, a, ...) UTIL_CAT(m(a), MACRO_MC_1(m, __VA_ARGS__,)) +#define MACRO_MC_3(m, a, ...) UTIL_CAT(m(a), MACRO_MC_2(m, __VA_ARGS__,)) +#define MACRO_MC_4(m, a, ...) UTIL_CAT(m(a), MACRO_MC_3(m, __VA_ARGS__,)) +#define MACRO_MC_5(m, a, ...) UTIL_CAT(m(a), MACRO_MC_4(m, __VA_ARGS__,)) +#define MACRO_MC_6(m, a, ...) UTIL_CAT(m(a), MACRO_MC_5(m, __VA_ARGS__,)) +#define MACRO_MC_7(m, a, ...) UTIL_CAT(m(a), MACRO_MC_6(m, __VA_ARGS__,)) +#define MACRO_MC_8(m, a, ...) UTIL_CAT(m(a), MACRO_MC_7(m, __VA_ARGS__,)) +#define MACRO_MC_9(m, a, ...) UTIL_CAT(m(a), MACRO_MC_8(m, __VA_ARGS__,)) +#define MACRO_MC_10(m, a, ...) UTIL_CAT(m(a), MACRO_MC_9(m, __VA_ARGS__,)) +#define MACRO_MC_11(m, a, ...) UTIL_CAT(m(a), MACRO_MC_10(m, __VA_ARGS__,)) +#define MACRO_MC_12(m, a, ...) UTIL_CAT(m(a), MACRO_MC_11(m, __VA_ARGS__,)) +#define MACRO_MC_13(m, a, ...) UTIL_CAT(m(a), MACRO_MC_12(m, __VA_ARGS__,)) +#define MACRO_MC_14(m, a, ...) UTIL_CAT(m(a), MACRO_MC_13(m, __VA_ARGS__,)) +#define MACRO_MC_15(m, a, ...) UTIL_CAT(m(a), MACRO_MC_14(m, __VA_ARGS__,)) + diff --git a/app/src/keymap.c b/app/src/keymap.c index 569a2cc7..a1ed3ff8 100644 --- a/app/src/keymap.c +++ b/app/src/keymap.c @@ -2,10 +2,57 @@ #include LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #include +#include +#include static u32_t zmk_keymap_layer_state = 0; static u8_t zmk_keymap_layer_default = 0; +#if DT_NODE_HAS_PROP(ZMK_KEYMAP_NODE, transform) +#define ZMK_KEYMAP_TRANSFORM_NODE DT_PHANDLE(ZMK_KEYMAP_NODE, transform) +#define ZMK_KEYMAP_LEN DT_PROP_LEN(ZMK_KEYMAP_TRANSFORM_NODE, map) + +#define _TRANSFORM_ENTRY(i, l) \ + [(KT_ROW(DT_PROP_BY_IDX(ZMK_KEYMAP_TRANSFORM_NODE, map, i)) * ZMK_MATRIX_COLS) + KT_COL(DT_PROP_BY_IDX(ZMK_KEYMAP_TRANSFORM_NODE, map, i))] = DT_PROP_BY_IDX(DT_PHANDLE_BY_IDX(ZMK_KEYMAP_NODE, layers, l), keys, i), + +#define TRANSFORMED_LAYER(idx) \ + { UTIL_LISTIFY(ZMK_KEYMAP_LEN, _TRANSFORM_ENTRY, idx) } + +static zmk_key zmk_keymap[ZMK_KEYMAP_LAYERS_LEN][ZMK_MATRIX_ROWS * ZMK_MATRIX_COLS] = { +#if DT_PROP_HAS_IDX(ZMK_KEYMAP_NODE, layers, 0) + TRANSFORMED_LAYER(0), +#endif +#if DT_PROP_HAS_IDX(ZMK_KEYMAP_NODE, layers, 1) + TRANSFORMED_LAYER(1), +#endif +#if DT_PROP_HAS_IDX(ZMK_KEYMAP_NODE, layers, 2) + TRANSFORMED_LAYER(2), +#endif +#if DT_PROP_HAS_IDX(ZMK_KEYMAP_NODE, layers, 3) + TRANSFORMED_LAYER(3), +#endif +#if DT_PROP_HAS_IDX(ZMK_KEYMAP_NODE, layers, 4) + TRANSFORMED_LAYER(4), +#endif +#if DT_PROP_HAS_IDX(ZMK_KEYMAP_NODE, layers, 5) + TRANSFORMED_LAYER(5), +#endif +#if DT_PROP_HAS_IDX(ZMK_KEYMAP_NODE, layers, 6) + TRANSFORMED_LAYER(6), +#endif +#if DT_PROP_HAS_IDX(ZMK_KEYMAP_NODE, layers, 7) + TRANSFORMED_LAYER(7), +#endif +#if DT_PROP_HAS_IDX(ZMK_KEYMAP_NODE, layers, 8) + TRANSFORMED_LAYER(8), +#endif +#if DT_PROP_HAS_IDX(ZMK_KEYMAP_NODE, layers, 9) + TRANSFORMED_LAYER(9), +#endif +}; + +#else + static zmk_key zmk_keymap[ZMK_KEYMAP_LAYERS_LEN][ZMK_MATRIX_ROWS * ZMK_MATRIX_COLS] = { #if DT_PROP_HAS_IDX(ZMK_KEYMAP_NODE, layers, 0) DT_PROP_BY_PHANDLE_IDX(ZMK_KEYMAP_NODE, layers, 0, keys), @@ -33,6 +80,8 @@ static zmk_key zmk_keymap[ZMK_KEYMAP_LAYERS_LEN][ZMK_MATRIX_ROWS * ZMK_MATRIX_CO #endif }; +#endif + #define SET_LAYER_STATE(layer, state) \ if (layer >= 32) \ { \