From 31af9646e6d1316cd960d8cff98c524c2f25934a Mon Sep 17 00:00:00 2001 From: Jason Chestnut Date: Wed, 23 Sep 2020 16:05:29 -0400 Subject: [PATCH 01/61] Adding kconfig flag for enabling matrix polling (vs interrupts) on the matrix gpio driver. --- app/drivers/zephyr/Kconfig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/drivers/zephyr/Kconfig b/app/drivers/zephyr/Kconfig index 0237846a..a5b6d20c 100644 --- a/app/drivers/zephyr/Kconfig +++ b/app/drivers/zephyr/Kconfig @@ -9,6 +9,10 @@ config ZMK_KSCAN_GPIO_POLLING bool "Poll for key event triggers instead of using interrupts" default n +config ZMK_KSCAN_GPIO_MATRIX_POLLING + bool "Poll for key event triggers instead of using interrupts on matrix boards." + default n + endif config ZMK_KSCAN_INIT_PRIORITY From 53425aa3c4719908eb8e6ed23057188f4e502237 Mon Sep 17 00:00:00 2001 From: Jason Chestnut Date: Thu, 24 Sep 2020 07:55:32 -0400 Subject: [PATCH 02/61] Rename kscan direct wired driver polling kscan flag in preparationfor addition of new matrix driver flag that enables polling. --- app/drivers/zephyr/Kconfig | 4 ++-- app/drivers/zephyr/kscan_gpio_direct.c | 18 +++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/app/drivers/zephyr/Kconfig b/app/drivers/zephyr/Kconfig index a5b6d20c..0bf6c0a6 100644 --- a/app/drivers/zephyr/Kconfig +++ b/app/drivers/zephyr/Kconfig @@ -5,11 +5,11 @@ config ZMK_KSCAN_GPIO_DRIVER if ZMK_KSCAN_GPIO_DRIVER -config ZMK_KSCAN_GPIO_POLLING +config ZMK_KSCAN_MATRIX_POLLING bool "Poll for key event triggers instead of using interrupts" default n -config ZMK_KSCAN_GPIO_MATRIX_POLLING +config ZMK_KSCAN_DIRECT_POLLING bool "Poll for key event triggers instead of using interrupts on matrix boards." default n diff --git a/app/drivers/zephyr/kscan_gpio_direct.c b/app/drivers/zephyr/kscan_gpio_direct.c index 1e5ab59e..7ba3399b 100644 --- a/app/drivers/zephyr/kscan_gpio_direct.c +++ b/app/drivers/zephyr/kscan_gpio_direct.c @@ -33,9 +33,9 @@ struct kscan_gpio_config { }; struct kscan_gpio_data { -#if defined(CONFIG_ZMK_KSCAN_GPIO_POLLING) +#if defined(ZMK_KSCAN_DIRECT_POLLING) struct k_timer poll_timer; -#endif /* defined(CONFIG_ZMK_KSCAN_GPIO_POLLING) */ +#endif /* defined(ZMK_KSCAN_DIRECT_POLLING) */ kscan_callback_t callback; union work_reference work; struct device *dev; @@ -53,7 +53,7 @@ static const struct kscan_gpio_item_config *kscan_gpio_input_configs(struct devi return cfg->inputs; } -#if !defined(CONFIG_ZMK_KSCAN_GPIO_POLLING) +#if !defined(ZMK_KSCAN_DIRECT_POLLING) struct kscan_gpio_irq_callback { union work_reference *work; @@ -101,7 +101,7 @@ static void kscan_gpio_irq_callback_handler(struct device *dev, struct gpio_call } } -#else /* !defined(CONFIG_ZMK_KSCAN_GPIO_POLLING) */ +#else /* !defined(ZMK_KSCAN_DIRECT_POLLING) */ static void kscan_gpio_timer_handler(struct k_timer *timer) { struct kscan_gpio_data *data = CONTAINER_OF(timer, struct kscan_gpio_data, poll_timer); @@ -120,7 +120,7 @@ static int kscan_gpio_direct_disable(struct device *dev) { return 0; } -#endif /* defined(CONFIG_ZMK_KSCAN_GPIO_POLLING) */ +#endif /* defined(ZMK_KSCAN_DIRECT_POLLING) */ static int kscan_gpio_direct_configure(struct device *dev, kscan_callback_t callback) { struct kscan_gpio_data *data = dev->driver_data; @@ -173,7 +173,7 @@ static const struct kscan_driver_api gpio_driver_api = { #define INST_INPUT_LEN(n) DT_INST_PROP_LEN(n, input_gpios) #define GPIO_INST_INIT(n) \ - COND_CODE_0(CONFIG_ZMK_KSCAN_GPIO_POLLING, \ + COND_CODE_0(ZMK_KSCAN_DIRECT_POLLING, \ (static struct kscan_gpio_irq_callback irq_callbacks_##n[INST_INPUT_LEN(n)];), ()) \ static struct kscan_gpio_data kscan_gpio_data_##n = { \ .inputs = {[INST_INPUT_LEN(n) - 1] = NULL}}; \ @@ -195,7 +195,7 @@ static const struct kscan_driver_api gpio_driver_api = { return err; \ } \ COND_CODE_0( \ - CONFIG_ZMK_KSCAN_GPIO_POLLING, \ + ZMK_KSCAN_DIRECT_POLLING, \ (irq_callbacks_##n[i].work = &data->work; \ irq_callbacks_##n[i].debounce_period = cfg->debounce_period; \ gpio_init_callback(&irq_callbacks_##n[i].callback, \ @@ -208,7 +208,7 @@ static const struct kscan_driver_api gpio_driver_api = { ()) \ } \ data->dev = dev; \ - COND_CODE_1(CONFIG_ZMK_KSCAN_GPIO_POLLING, \ + COND_CODE_1(ZMK_KSCAN_DIRECT_POLLING, \ (k_timer_init(&data->poll_timer, kscan_gpio_timer_handler, NULL);), ()) \ if (cfg->debounce_period > 0) { \ k_delayed_work_init(&data->work.delayed, kscan_gpio_work_handler); \ @@ -227,4 +227,4 @@ static const struct kscan_driver_api gpio_driver_api = { DT_INST_FOREACH_STATUS_OKAY(GPIO_INST_INIT) -#endif /* DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) */ \ No newline at end of file +#endif /* DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) */ From 5c4705d465d4b5f742299cf77f549186c9cc7933 Mon Sep 17 00:00:00 2001 From: Jason Chestnut Date: Thu, 24 Sep 2020 14:30:47 -0400 Subject: [PATCH 03/61] Add new matrix scan flag and implementation in the gpio matrix driver. --- app/boards/arm/planck/Kconfig.defconfig | 3 + .../clueboard_california/Kconfig.defconfig | 2 +- app/drivers/zephyr/Kconfig | 6 +- app/drivers/zephyr/kscan_gpio_matrix.c | 133 ++++++++++++------ 4 files changed, 95 insertions(+), 49 deletions(-) diff --git a/app/boards/arm/planck/Kconfig.defconfig b/app/boards/arm/planck/Kconfig.defconfig index 6f5bf525..913c1c13 100644 --- a/app/boards/arm/planck/Kconfig.defconfig +++ b/app/boards/arm/planck/Kconfig.defconfig @@ -11,4 +11,7 @@ config ZMK_KEYBOARD_NAME config ZMK_USB default y +config ZMK_KSCAN_MATRIX_POLLING + default y + endif # BOARD_PLANCK_REV6 diff --git a/app/boards/shields/clueboard_california/Kconfig.defconfig b/app/boards/shields/clueboard_california/Kconfig.defconfig index 2408f9ff..e101ea76 100644 --- a/app/boards/shields/clueboard_california/Kconfig.defconfig +++ b/app/boards/shields/clueboard_california/Kconfig.defconfig @@ -8,7 +8,7 @@ config ZMK_KEYBOARD_NAME # across A & B controllers, and STM32F303CCT6 can't enable # interrutps for multiple controllers for the same "line" # for the external interrupts. -config ZMK_KSCAN_GPIO_POLLING +config ZMK_KSCAN_DIRECT_POLLING default y endif diff --git a/app/drivers/zephyr/Kconfig b/app/drivers/zephyr/Kconfig index 0bf6c0a6..c5ff3a66 100644 --- a/app/drivers/zephyr/Kconfig +++ b/app/drivers/zephyr/Kconfig @@ -6,11 +6,11 @@ config ZMK_KSCAN_GPIO_DRIVER if ZMK_KSCAN_GPIO_DRIVER config ZMK_KSCAN_MATRIX_POLLING - bool "Poll for key event triggers instead of using interrupts" - default n + bool "Poll for key event triggers instead of using interrupts on matrix boards." + default y config ZMK_KSCAN_DIRECT_POLLING - bool "Poll for key event triggers instead of using interrupts on matrix boards." + bool "Poll for key event triggers instead of using interrupts on direct wired boards." default n endif diff --git a/app/drivers/zephyr/kscan_gpio_matrix.c b/app/drivers/zephyr/kscan_gpio_matrix.c index 634f694c..46616ff5 100644 --- a/app/drivers/zephyr/kscan_gpio_matrix.c +++ b/app/drivers/zephyr/kscan_gpio_matrix.c @@ -31,6 +31,8 @@ struct kscan_gpio_item_config { #define _KSCAN_GPIO_ROW_CFG_INIT(idx, n) _KSCAN_GPIO_ITEM_CFG_INIT(n, row_gpios, idx) #define _KSCAN_GPIO_COL_CFG_INIT(idx, n) _KSCAN_GPIO_ITEM_CFG_INIT(n, col_gpios, idx) +#if !defined(ZMK_KSCAN_MATRIX_POLLING) +/* Set up for interrupt-based input. */ static int kscan_gpio_config_interrupts(struct device **devices, const struct kscan_gpio_item_config *configs, size_t len, gpio_flags_t flags) { @@ -48,6 +50,61 @@ static int kscan_gpio_config_interrupts(struct device **devices, return 0; } + +#define KSCAN_GPIO_MATRIX_ENABLE(n) \ +static int kscan_gpio_matrix_enable(struct device *dev) { \ + return kscan_gpio_config_interrupts(kscan_gpio_input_devices_##n(dev), \ + kscan_gpio_input_configs_##n(dev), INST_INPUT_LEN(n), \ + GPIO_INT_DEBOUNCE | GPIO_INT_EDGE_BOTH); \ +} \ + +#define KSCAN_GPIO_MATRIX_DISABLE(n) \ +static int kscan_gpio_matrix_disable(struct device *dev) { \ + return kscan_gpio_config_interrupts(kscan_gpio_input_devices_##n(dev), \ + kscan_gpio_input_configs_##n(dev), INST_INPUT_LEN(n), \ + GPIO_INT_DISABLE); \ +} \ + +#define KSCAN_GPIO_CALLBACK_HANDLER(n) \ +static void kscan_gpio_irq_callback_handler_##n(struct device *dev, struct gpio_callback *cb, \ + gpio_port_pins_t pin) { \ + struct kscan_gpio_irq_callback_##n *data = \ + CONTAINER_OF(cb, struct kscan_gpio_irq_callback_##n, callback); \ + COND_CODE_0(DT_INST_PROP(n, debounce_period), ({ k_work_submit(data->work); }), ({ \ + k_delayed_work_cancel(data->work); \ + k_delayed_work_submit(data->work, \ + K_MSEC(DT_INST_PROP(n, debounce_period))); \ + })) \ +} \ + +#else /* !defined(ZMK_KSCAN_MATRIX_POLLING) */ +/* Set up for matrix scanning. */ + +static void kscan_gpio_timer_handler(struct k_timer *timer) { + struct kscan_gpio_data *data = CONTAINER_OF(timer, struct kscan_gpio_data, poll_timer); + + k_work_submit(&data->work.direct); +} + +#define KSCAN_GPIO_MATRIX_ENABLE(n) \ +static int kscan_gpio_matrix_enable(struct device *dev) { \ + struct kscan_gpio_data *data = dev->driver_data; \ + k_timer_start(&data->poll_timer, K_MSEC(10), K_MSEC(10)); \ + return 0; \ +} \ + +#define KSCAN_GPIO_MATRIX_DISABLE(n) \ +static int kscan_gpio_matrix_disable(struct device *dev) { \ + struct kscan_gpio_data *data = dev->driver_data; \ + k_timer_stop(&data->poll_timer, K_MSEC(10), K_MSEC(10)); \ + return 0; \ +} \ + +#define KSCAN_GPIO_MATRIX_ENABLE(n) \ + + +#endif /* !defined(ZMK_KSCAN_MATRIX_POLLING) */ + #define INST_MATRIX_ROWS(n) DT_INST_PROP_LEN(n, row_gpios) #define INST_MATRIX_COLS(n) DT_INST_PROP_LEN(n, col_gpios) #define INST_OUTPUT_LEN(n) \ @@ -58,17 +115,22 @@ static int kscan_gpio_config_interrupts(struct device **devices, (INST_MATRIX_ROWS(n))) #define GPIO_INST_INIT(n) \ - struct kscan_gpio_irq_callback_##n { \ - struct COND_CODE_0(DT_INST_PROP(n, debounce_period), (k_work), (k_delayed_work)) * work; \ - struct gpio_callback callback; \ - }; \ - static struct kscan_gpio_irq_callback_##n irq_callbacks_##n[INST_INPUT_LEN(n)]; \ + COND_CODE_0( \ + ZMK_KSCAN_MATRIX_POLLING, \ + (struct kscan_gpio_irq_callback_##n { \ + struct COND_CODE_0(DT_INST_PROP(n, debounce_period), (k_work), (k_delayed_work)) * work; \ + struct gpio_callback callback; \ + }; \ + static struct kscan_gpio_irq_callback_##n irq_callbacks_##n[INST_INPUT_LEN(n)]; \ + KSCAN_GPIO_ENTABLE_INTERRUPTS(n)), \ + ()) \ struct kscan_gpio_config_##n { \ struct kscan_gpio_item_config rows[INST_MATRIX_ROWS(n)]; \ struct kscan_gpio_item_config cols[INST_MATRIX_COLS(n)]; \ }; \ struct kscan_gpio_data_##n { \ - kscan_callback_t callback; \ + COND_CODE_1(ZMK_KSCAN_MATRIX_POLLING, \ + (struct k_timer poll_timer;),(kscan_callback_t callback;)) \ struct COND_CODE_0(DT_INST_PROP(n, debounce_period), (k_work), (k_delayed_work)) work; \ bool matrix_state[INST_MATRIX_ROWS(n)][INST_MATRIX_COLS(n)]; \ struct device *rows[INST_MATRIX_ROWS(n)]; \ @@ -96,16 +158,6 @@ static int kscan_gpio_config_interrupts(struct device **devices, return ( \ COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (cfg->rows), (cfg->cols))); \ } \ - static int kscan_gpio_enable_interrupts_##n(struct device *dev) { \ - return kscan_gpio_config_interrupts(kscan_gpio_input_devices_##n(dev), \ - kscan_gpio_input_configs_##n(dev), INST_INPUT_LEN(n), \ - GPIO_INT_DEBOUNCE | GPIO_INT_EDGE_BOTH); \ - } \ - static int kscan_gpio_disable_interrupts_##n(struct device *dev) { \ - return kscan_gpio_config_interrupts(kscan_gpio_input_devices_##n(dev), \ - kscan_gpio_input_configs_##n(dev), INST_INPUT_LEN(n), \ - GPIO_INT_DISABLE); \ - } \ static void kscan_gpio_set_output_state_##n(struct device *dev, int value) { \ for (int i = 0; i < INST_OUTPUT_LEN(n); i++) { \ struct device *in_dev = kscan_gpio_output_devices_##n(dev)[i]; \ @@ -128,7 +180,7 @@ static int kscan_gpio_config_interrupts(struct device **devices, /* Disable our interrupts temporarily while we scan, to avoid */ \ /* re-entry while we iterate columns and set them active one by one */ \ /* to get pressed state for each matrix cell. */ \ - kscan_gpio_disable_interrupts_##n(dev); \ + COND_CODE_0(ZMK_KSCAN_MATRIX_POLLING, (kscan_gpio_disable_interrupts_##n(dev);), ()) \ kscan_gpio_set_output_state_##n(dev, 0); \ for (int o = 0; o < INST_OUTPUT_LEN(n); o++) { \ struct device *out_dev = kscan_gpio_output_devices_##n(dev)[o]; \ @@ -146,7 +198,7 @@ static int kscan_gpio_config_interrupts(struct device **devices, /* Set all our outputs as active again, then re-enable interrupts, */ \ /* so we can trigger interrupts again for future press/release */ \ kscan_gpio_set_output_state_##n(dev, 1); \ - kscan_gpio_enable_interrupts_##n(dev); \ + COND_CODE_0(ZMK_KSCAN_MATRIX_POLLING, (kscan_gpio_enable_interrupts_##n(dev);), ()) \ for (int r = 0; r < INST_MATRIX_ROWS(n); r++) { \ for (int c = 0; c < INST_MATRIX_COLS(n); c++) { \ bool pressed = read_state[r][c]; \ @@ -172,16 +224,7 @@ static int kscan_gpio_config_interrupts(struct device **devices, struct kscan_gpio_data_##n *data = CONTAINER_OF(work, struct kscan_gpio_data_##n, work); \ kscan_gpio_read_##n(data->dev); \ } \ - static void kscan_gpio_irq_callback_handler_##n(struct device *dev, struct gpio_callback *cb, \ - gpio_port_pins_t pin) { \ - struct kscan_gpio_irq_callback_##n *data = \ - CONTAINER_OF(cb, struct kscan_gpio_irq_callback_##n, callback); \ - COND_CODE_0(DT_INST_PROP(n, debounce_period), ({ k_work_submit(data->work); }), ({ \ - k_delayed_work_cancel(data->work); \ - k_delayed_work_submit(data->work, \ - K_MSEC(DT_INST_PROP(n, debounce_period))); \ - })) \ - } \ + COND_CODE_0(ZMK_KSCAN_MATRIX_POLLING, (KSCAN_GPIO_CALLBACK_HANDLER(n)), ()) \ static struct kscan_gpio_data_##n kscan_gpio_data_##n = { \ .rows = {[INST_MATRIX_ROWS(n) - 1] = NULL}, .cols = {[INST_MATRIX_COLS(n) - 1] = NULL}}; \ static int kscan_gpio_configure_##n(struct device *dev, kscan_callback_t callback) { \ @@ -192,13 +235,8 @@ static int kscan_gpio_config_interrupts(struct device **devices, data->callback = callback; \ return 0; \ }; \ - static int kscan_gpio_enable_##n(struct device *dev) { \ - int err = kscan_gpio_enable_interrupts_##n(dev); \ - if (err) { \ - return err; \ - } \ - return kscan_gpio_read_##n(dev); \ - }; \ + KSCAN_GPIO_MATRIX_ENABLE(n) \ + KSCAN_GPIO_MATRIX_DISABLE(n) \ static int kscan_gpio_init_##n(struct device *dev) { \ struct kscan_gpio_data_##n *data = dev->driver_data; \ int err; \ @@ -215,16 +253,21 @@ static int kscan_gpio_config_interrupts(struct device **devices, LOG_ERR("Unable to configure pin %d on %s for input", in_cfg->pin, in_cfg->label); \ return err; \ } \ - irq_callbacks_##n[i].work = &data->work; \ - gpio_init_callback(&irq_callbacks_##n[i].callback, \ - kscan_gpio_irq_callback_handler_##n, BIT(in_cfg->pin)); \ - err = gpio_add_callback(input_devices[i], &irq_callbacks_##n[i].callback); \ - if (err) { \ - LOG_ERR("Error adding the callback to the column device"); \ - return err; \ - } \ + COND_CODE_0( \ + ZMK_KSCAN_MATRIX_POLLING, \ + (irq_callbacks_##n[i].work = &data->work; \ + gpio_init_callback(&irq_callbacks_##n[i].callback, \ + kscan_gpio_irq_callback_handler_##n, BIT(in_cfg->pin)); \ + err = gpio_add_callback(input_devices[i], &irq_callbacks_##n[i].callback); \ + if (err) { \ + LOG_ERR("Error adding the callback to the column device"); \ + return err; \ + }), \ + ()) \ } \ struct device **output_devices = kscan_gpio_output_devices_##n(dev); \ + COND_CODE_1(ZMK_KSCAN_MATRIX_POLLING, \ + (k_timer_init(&data->poll_timer, kscan_gpio_timer_handler, NULL);), ()) \ for (int o = 0; o < INST_OUTPUT_LEN(n); o++) { \ const struct kscan_gpio_item_config *out_cfg = &kscan_gpio_output_configs_##n(dev)[o]; \ output_devices[o] = device_get_binding(out_cfg->label); \ @@ -247,8 +290,8 @@ static int kscan_gpio_config_interrupts(struct device **devices, } \ static const struct kscan_driver_api gpio_driver_api_##n = { \ .config = kscan_gpio_configure_##n, \ - .enable_callback = kscan_gpio_enable_##n, \ - .disable_callback = kscan_gpio_disable_interrupts_##n, \ + .enable_callback = kscan_gpio_matrix_enable, \ + .disable_callback = kscan_gpio_matrix_disable, \ }; \ static const struct kscan_gpio_config_##n kscan_gpio_config_##n = { \ .rows = {UTIL_LISTIFY(INST_MATRIX_ROWS(n), _KSCAN_GPIO_ROW_CFG_INIT, n)}, \ From 966830562182bca5645ec5c7f44c1e7390408bdd Mon Sep 17 00:00:00 2001 From: Jason Chestnut Date: Thu, 24 Sep 2020 17:35:51 -0400 Subject: [PATCH 04/61] Restore original matrix driver to correct implementation errors. --- app/drivers/zephyr/kscan_gpio_matrix.c | 133 +++++++++---------------- 1 file changed, 45 insertions(+), 88 deletions(-) diff --git a/app/drivers/zephyr/kscan_gpio_matrix.c b/app/drivers/zephyr/kscan_gpio_matrix.c index 46616ff5..634f694c 100644 --- a/app/drivers/zephyr/kscan_gpio_matrix.c +++ b/app/drivers/zephyr/kscan_gpio_matrix.c @@ -31,8 +31,6 @@ struct kscan_gpio_item_config { #define _KSCAN_GPIO_ROW_CFG_INIT(idx, n) _KSCAN_GPIO_ITEM_CFG_INIT(n, row_gpios, idx) #define _KSCAN_GPIO_COL_CFG_INIT(idx, n) _KSCAN_GPIO_ITEM_CFG_INIT(n, col_gpios, idx) -#if !defined(ZMK_KSCAN_MATRIX_POLLING) -/* Set up for interrupt-based input. */ static int kscan_gpio_config_interrupts(struct device **devices, const struct kscan_gpio_item_config *configs, size_t len, gpio_flags_t flags) { @@ -50,61 +48,6 @@ static int kscan_gpio_config_interrupts(struct device **devices, return 0; } - -#define KSCAN_GPIO_MATRIX_ENABLE(n) \ -static int kscan_gpio_matrix_enable(struct device *dev) { \ - return kscan_gpio_config_interrupts(kscan_gpio_input_devices_##n(dev), \ - kscan_gpio_input_configs_##n(dev), INST_INPUT_LEN(n), \ - GPIO_INT_DEBOUNCE | GPIO_INT_EDGE_BOTH); \ -} \ - -#define KSCAN_GPIO_MATRIX_DISABLE(n) \ -static int kscan_gpio_matrix_disable(struct device *dev) { \ - return kscan_gpio_config_interrupts(kscan_gpio_input_devices_##n(dev), \ - kscan_gpio_input_configs_##n(dev), INST_INPUT_LEN(n), \ - GPIO_INT_DISABLE); \ -} \ - -#define KSCAN_GPIO_CALLBACK_HANDLER(n) \ -static void kscan_gpio_irq_callback_handler_##n(struct device *dev, struct gpio_callback *cb, \ - gpio_port_pins_t pin) { \ - struct kscan_gpio_irq_callback_##n *data = \ - CONTAINER_OF(cb, struct kscan_gpio_irq_callback_##n, callback); \ - COND_CODE_0(DT_INST_PROP(n, debounce_period), ({ k_work_submit(data->work); }), ({ \ - k_delayed_work_cancel(data->work); \ - k_delayed_work_submit(data->work, \ - K_MSEC(DT_INST_PROP(n, debounce_period))); \ - })) \ -} \ - -#else /* !defined(ZMK_KSCAN_MATRIX_POLLING) */ -/* Set up for matrix scanning. */ - -static void kscan_gpio_timer_handler(struct k_timer *timer) { - struct kscan_gpio_data *data = CONTAINER_OF(timer, struct kscan_gpio_data, poll_timer); - - k_work_submit(&data->work.direct); -} - -#define KSCAN_GPIO_MATRIX_ENABLE(n) \ -static int kscan_gpio_matrix_enable(struct device *dev) { \ - struct kscan_gpio_data *data = dev->driver_data; \ - k_timer_start(&data->poll_timer, K_MSEC(10), K_MSEC(10)); \ - return 0; \ -} \ - -#define KSCAN_GPIO_MATRIX_DISABLE(n) \ -static int kscan_gpio_matrix_disable(struct device *dev) { \ - struct kscan_gpio_data *data = dev->driver_data; \ - k_timer_stop(&data->poll_timer, K_MSEC(10), K_MSEC(10)); \ - return 0; \ -} \ - -#define KSCAN_GPIO_MATRIX_ENABLE(n) \ - - -#endif /* !defined(ZMK_KSCAN_MATRIX_POLLING) */ - #define INST_MATRIX_ROWS(n) DT_INST_PROP_LEN(n, row_gpios) #define INST_MATRIX_COLS(n) DT_INST_PROP_LEN(n, col_gpios) #define INST_OUTPUT_LEN(n) \ @@ -115,22 +58,17 @@ static int kscan_gpio_matrix_disable(struct device *dev) { (INST_MATRIX_ROWS(n))) #define GPIO_INST_INIT(n) \ - COND_CODE_0( \ - ZMK_KSCAN_MATRIX_POLLING, \ - (struct kscan_gpio_irq_callback_##n { \ - struct COND_CODE_0(DT_INST_PROP(n, debounce_period), (k_work), (k_delayed_work)) * work; \ - struct gpio_callback callback; \ - }; \ - static struct kscan_gpio_irq_callback_##n irq_callbacks_##n[INST_INPUT_LEN(n)]; \ - KSCAN_GPIO_ENTABLE_INTERRUPTS(n)), \ - ()) \ + struct kscan_gpio_irq_callback_##n { \ + struct COND_CODE_0(DT_INST_PROP(n, debounce_period), (k_work), (k_delayed_work)) * work; \ + struct gpio_callback callback; \ + }; \ + static struct kscan_gpio_irq_callback_##n irq_callbacks_##n[INST_INPUT_LEN(n)]; \ struct kscan_gpio_config_##n { \ struct kscan_gpio_item_config rows[INST_MATRIX_ROWS(n)]; \ struct kscan_gpio_item_config cols[INST_MATRIX_COLS(n)]; \ }; \ struct kscan_gpio_data_##n { \ - COND_CODE_1(ZMK_KSCAN_MATRIX_POLLING, \ - (struct k_timer poll_timer;),(kscan_callback_t callback;)) \ + kscan_callback_t callback; \ struct COND_CODE_0(DT_INST_PROP(n, debounce_period), (k_work), (k_delayed_work)) work; \ bool matrix_state[INST_MATRIX_ROWS(n)][INST_MATRIX_COLS(n)]; \ struct device *rows[INST_MATRIX_ROWS(n)]; \ @@ -158,6 +96,16 @@ static int kscan_gpio_matrix_disable(struct device *dev) { return ( \ COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (cfg->rows), (cfg->cols))); \ } \ + static int kscan_gpio_enable_interrupts_##n(struct device *dev) { \ + return kscan_gpio_config_interrupts(kscan_gpio_input_devices_##n(dev), \ + kscan_gpio_input_configs_##n(dev), INST_INPUT_LEN(n), \ + GPIO_INT_DEBOUNCE | GPIO_INT_EDGE_BOTH); \ + } \ + static int kscan_gpio_disable_interrupts_##n(struct device *dev) { \ + return kscan_gpio_config_interrupts(kscan_gpio_input_devices_##n(dev), \ + kscan_gpio_input_configs_##n(dev), INST_INPUT_LEN(n), \ + GPIO_INT_DISABLE); \ + } \ static void kscan_gpio_set_output_state_##n(struct device *dev, int value) { \ for (int i = 0; i < INST_OUTPUT_LEN(n); i++) { \ struct device *in_dev = kscan_gpio_output_devices_##n(dev)[i]; \ @@ -180,7 +128,7 @@ static int kscan_gpio_matrix_disable(struct device *dev) { /* Disable our interrupts temporarily while we scan, to avoid */ \ /* re-entry while we iterate columns and set them active one by one */ \ /* to get pressed state for each matrix cell. */ \ - COND_CODE_0(ZMK_KSCAN_MATRIX_POLLING, (kscan_gpio_disable_interrupts_##n(dev);), ()) \ + kscan_gpio_disable_interrupts_##n(dev); \ kscan_gpio_set_output_state_##n(dev, 0); \ for (int o = 0; o < INST_OUTPUT_LEN(n); o++) { \ struct device *out_dev = kscan_gpio_output_devices_##n(dev)[o]; \ @@ -198,7 +146,7 @@ static int kscan_gpio_matrix_disable(struct device *dev) { /* Set all our outputs as active again, then re-enable interrupts, */ \ /* so we can trigger interrupts again for future press/release */ \ kscan_gpio_set_output_state_##n(dev, 1); \ - COND_CODE_0(ZMK_KSCAN_MATRIX_POLLING, (kscan_gpio_enable_interrupts_##n(dev);), ()) \ + kscan_gpio_enable_interrupts_##n(dev); \ for (int r = 0; r < INST_MATRIX_ROWS(n); r++) { \ for (int c = 0; c < INST_MATRIX_COLS(n); c++) { \ bool pressed = read_state[r][c]; \ @@ -224,7 +172,16 @@ static int kscan_gpio_matrix_disable(struct device *dev) { struct kscan_gpio_data_##n *data = CONTAINER_OF(work, struct kscan_gpio_data_##n, work); \ kscan_gpio_read_##n(data->dev); \ } \ - COND_CODE_0(ZMK_KSCAN_MATRIX_POLLING, (KSCAN_GPIO_CALLBACK_HANDLER(n)), ()) \ + static void kscan_gpio_irq_callback_handler_##n(struct device *dev, struct gpio_callback *cb, \ + gpio_port_pins_t pin) { \ + struct kscan_gpio_irq_callback_##n *data = \ + CONTAINER_OF(cb, struct kscan_gpio_irq_callback_##n, callback); \ + COND_CODE_0(DT_INST_PROP(n, debounce_period), ({ k_work_submit(data->work); }), ({ \ + k_delayed_work_cancel(data->work); \ + k_delayed_work_submit(data->work, \ + K_MSEC(DT_INST_PROP(n, debounce_period))); \ + })) \ + } \ static struct kscan_gpio_data_##n kscan_gpio_data_##n = { \ .rows = {[INST_MATRIX_ROWS(n) - 1] = NULL}, .cols = {[INST_MATRIX_COLS(n) - 1] = NULL}}; \ static int kscan_gpio_configure_##n(struct device *dev, kscan_callback_t callback) { \ @@ -235,8 +192,13 @@ static int kscan_gpio_matrix_disable(struct device *dev) { data->callback = callback; \ return 0; \ }; \ - KSCAN_GPIO_MATRIX_ENABLE(n) \ - KSCAN_GPIO_MATRIX_DISABLE(n) \ + static int kscan_gpio_enable_##n(struct device *dev) { \ + int err = kscan_gpio_enable_interrupts_##n(dev); \ + if (err) { \ + return err; \ + } \ + return kscan_gpio_read_##n(dev); \ + }; \ static int kscan_gpio_init_##n(struct device *dev) { \ struct kscan_gpio_data_##n *data = dev->driver_data; \ int err; \ @@ -253,21 +215,16 @@ static int kscan_gpio_matrix_disable(struct device *dev) { LOG_ERR("Unable to configure pin %d on %s for input", in_cfg->pin, in_cfg->label); \ return err; \ } \ - COND_CODE_0( \ - ZMK_KSCAN_MATRIX_POLLING, \ - (irq_callbacks_##n[i].work = &data->work; \ - gpio_init_callback(&irq_callbacks_##n[i].callback, \ - kscan_gpio_irq_callback_handler_##n, BIT(in_cfg->pin)); \ - err = gpio_add_callback(input_devices[i], &irq_callbacks_##n[i].callback); \ - if (err) { \ - LOG_ERR("Error adding the callback to the column device"); \ - return err; \ - }), \ - ()) \ + irq_callbacks_##n[i].work = &data->work; \ + gpio_init_callback(&irq_callbacks_##n[i].callback, \ + kscan_gpio_irq_callback_handler_##n, BIT(in_cfg->pin)); \ + err = gpio_add_callback(input_devices[i], &irq_callbacks_##n[i].callback); \ + if (err) { \ + LOG_ERR("Error adding the callback to the column device"); \ + return err; \ + } \ } \ struct device **output_devices = kscan_gpio_output_devices_##n(dev); \ - COND_CODE_1(ZMK_KSCAN_MATRIX_POLLING, \ - (k_timer_init(&data->poll_timer, kscan_gpio_timer_handler, NULL);), ()) \ for (int o = 0; o < INST_OUTPUT_LEN(n); o++) { \ const struct kscan_gpio_item_config *out_cfg = &kscan_gpio_output_configs_##n(dev)[o]; \ output_devices[o] = device_get_binding(out_cfg->label); \ @@ -290,8 +247,8 @@ static int kscan_gpio_matrix_disable(struct device *dev) { } \ static const struct kscan_driver_api gpio_driver_api_##n = { \ .config = kscan_gpio_configure_##n, \ - .enable_callback = kscan_gpio_matrix_enable, \ - .disable_callback = kscan_gpio_matrix_disable, \ + .enable_callback = kscan_gpio_enable_##n, \ + .disable_callback = kscan_gpio_disable_interrupts_##n, \ }; \ static const struct kscan_gpio_config_##n kscan_gpio_config_##n = { \ .rows = {UTIL_LISTIFY(INST_MATRIX_ROWS(n), _KSCAN_GPIO_ROW_CFG_INIT, n)}, \ From b1dce208f8accab56c7864e01cff70a88bc39b3f Mon Sep 17 00:00:00 2001 From: Jason Chestnut Date: Fri, 25 Sep 2020 11:29:21 -0400 Subject: [PATCH 05/61] Add matrix polling logic to matrix GPIO driver. --- app/drivers/zephyr/Kconfig | 2 +- app/drivers/zephyr/kscan_gpio_matrix.c | 65 +++++++++++++++++++------- 2 files changed, 48 insertions(+), 19 deletions(-) diff --git a/app/drivers/zephyr/Kconfig b/app/drivers/zephyr/Kconfig index c5ff3a66..0534cab2 100644 --- a/app/drivers/zephyr/Kconfig +++ b/app/drivers/zephyr/Kconfig @@ -7,7 +7,7 @@ if ZMK_KSCAN_GPIO_DRIVER config ZMK_KSCAN_MATRIX_POLLING bool "Poll for key event triggers instead of using interrupts on matrix boards." - default y + default n config ZMK_KSCAN_DIRECT_POLLING bool "Poll for key event triggers instead of using interrupts on direct wired boards." diff --git a/app/drivers/zephyr/kscan_gpio_matrix.c b/app/drivers/zephyr/kscan_gpio_matrix.c index 634f694c..8c6cabd8 100644 --- a/app/drivers/zephyr/kscan_gpio_matrix.c +++ b/app/drivers/zephyr/kscan_gpio_matrix.c @@ -31,7 +31,8 @@ struct kscan_gpio_item_config { #define _KSCAN_GPIO_ROW_CFG_INIT(idx, n) _KSCAN_GPIO_ITEM_CFG_INIT(n, row_gpios, idx) #define _KSCAN_GPIO_COL_CFG_INIT(idx, n) _KSCAN_GPIO_ITEM_CFG_INIT(n, col_gpios, idx) -static int kscan_gpio_config_interrupts(struct device **devices, +COND_CODE_0(ZMK_KSCAN_MATRIX_POLLING, +(static int kscan_gpio_config_interrupts(struct device **devices, const struct kscan_gpio_item_config *configs, size_t len, gpio_flags_t flags) { for (int i = 0; i < len; i++) { @@ -47,7 +48,8 @@ static int kscan_gpio_config_interrupts(struct device **devices, } return 0; -} +}), ()) + #define INST_MATRIX_ROWS(n) DT_INST_PROP_LEN(n, row_gpios) #define INST_MATRIX_COLS(n) DT_INST_PROP_LEN(n, col_gpios) #define INST_OUTPUT_LEN(n) \ @@ -69,6 +71,7 @@ static int kscan_gpio_config_interrupts(struct device **devices, }; \ struct kscan_gpio_data_##n { \ kscan_callback_t callback; \ + COND_CODE_0(ZMK_KSCAN_MATRIX_POLLING, (), (struct k_timer poll_timer;)) \ struct COND_CODE_0(DT_INST_PROP(n, debounce_period), (k_work), (k_delayed_work)) work; \ bool matrix_state[INST_MATRIX_ROWS(n)][INST_MATRIX_COLS(n)]; \ struct device *rows[INST_MATRIX_ROWS(n)]; \ @@ -96,16 +99,17 @@ static int kscan_gpio_config_interrupts(struct device **devices, return ( \ COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (cfg->rows), (cfg->cols))); \ } \ - static int kscan_gpio_enable_interrupts_##n(struct device *dev) { \ - return kscan_gpio_config_interrupts(kscan_gpio_input_devices_##n(dev), \ + COND_CODE_0(ZMK_KSCAN_MATRIX_POLLING, \ + (static int kscan_gpio_enable_interrupts_##n(struct device *dev) { \ + return kscan_gpio_config_interrupts(kscan_gpio_input_devices_##n(dev), \ kscan_gpio_input_configs_##n(dev), INST_INPUT_LEN(n), \ GPIO_INT_DEBOUNCE | GPIO_INT_EDGE_BOTH); \ - } \ - static int kscan_gpio_disable_interrupts_##n(struct device *dev) { \ - return kscan_gpio_config_interrupts(kscan_gpio_input_devices_##n(dev), \ + } \ + static int kscan_gpio_disable_interrupts_##n(struct device *dev) { \ + return kscan_gpio_config_interrupts(kscan_gpio_input_devices_##n(dev), \ kscan_gpio_input_configs_##n(dev), INST_INPUT_LEN(n), \ GPIO_INT_DISABLE); \ - } \ + }), ()) \ static void kscan_gpio_set_output_state_##n(struct device *dev, int value) { \ for (int i = 0; i < INST_OUTPUT_LEN(n); i++) { \ struct device *in_dev = kscan_gpio_output_devices_##n(dev)[i]; \ @@ -128,7 +132,8 @@ static int kscan_gpio_config_interrupts(struct device **devices, /* Disable our interrupts temporarily while we scan, to avoid */ \ /* re-entry while we iterate columns and set them active one by one */ \ /* to get pressed state for each matrix cell. */ \ - kscan_gpio_disable_interrupts_##n(dev); \ + COND_CODE_0(ZMK_KSCAN_MATRIX_POLLING, \ + (kscan_gpio_disable_interrupts_##n(dev);),()) \ kscan_gpio_set_output_state_##n(dev, 0); \ for (int o = 0; o < INST_OUTPUT_LEN(n); o++) { \ struct device *out_dev = kscan_gpio_output_devices_##n(dev)[o]; \ @@ -143,10 +148,11 @@ static int kscan_gpio_config_interrupts(struct device **devices, } \ gpio_pin_set(out_dev, out_cfg->pin, 0); \ } \ - /* Set all our outputs as active again, then re-enable interrupts, */ \ - /* so we can trigger interrupts again for future press/release */ \ + /* Set all our outputs as active again. */ \ kscan_gpio_set_output_state_##n(dev, 1); \ - kscan_gpio_enable_interrupts_##n(dev); \ + /*Re-enable interrupts so that they can be triggered again for future press/release*/ \ + COND_CODE_0(ZMK_KSCAN_MATRIX_POLLING, \ + (kscan_gpio_enable_interrupts_##n(dev);), ()) \ for (int r = 0; r < INST_MATRIX_ROWS(n); r++) { \ for (int c = 0; c < INST_MATRIX_COLS(n); c++) { \ bool pressed = read_state[r][c]; \ @@ -190,15 +196,34 @@ static int kscan_gpio_config_interrupts(struct device **devices, return -EINVAL; \ } \ data->callback = callback; \ + LOG_DBG("Configured GPIO %d", n); \ return 0; \ }; \ static int kscan_gpio_enable_##n(struct device *dev) { \ - int err = kscan_gpio_enable_interrupts_##n(dev); \ - if (err) { \ - return err; \ - } \ - return kscan_gpio_read_##n(dev); \ + COND_CODE_0(ZMK_KSCAN_MATRIX_POLLING, \ + (int err = kscan_gpio_enable_interrupts_##n(dev); \ + if (err) { \ + return err; \ + } \ + return kscan_gpio_read_##n(dev);), \ + (struct kscan_gpio_data_##n *data = dev->driver_data; \ + k_timer_start(&data->poll_timer, K_MSEC(10), K_MSEC(10)); \ + return 0;)) \ + }; \ + static int kscan_gpio_disable_##n(struct device *dev) { \ + COND_CODE_0(ZMK_KSCAN_MATRIX_POLLING, \ + (return kscan_gpio_disable_interrupts_##n(dev);), \ + (struct kscan_gpio_data_##n *data = dev->driver_data; \ + k_timer_stop(&data->poll_timer); \ + return 0;)) \ }; \ + COND_CODE_0(ZMK_KSCAN_MATRIX_POLLING, (), \ + (static void kscan_gpio_timer_handler(struct k_timer *timer) { \ + struct kscan_gpio_data_##n *data = \ + CONTAINER_OF(timer, struct kscan_gpio_data_##n, poll_timer); \ + k_work_submit(&data->work.work); \ + LOG_DBG("Submitted work in timer handler."); \ + })) \ static int kscan_gpio_init_##n(struct device *dev) { \ struct kscan_gpio_data_##n *data = dev->driver_data; \ int err; \ @@ -214,6 +239,8 @@ static int kscan_gpio_config_interrupts(struct device **devices, if (err) { \ LOG_ERR("Unable to configure pin %d on %s for input", in_cfg->pin, in_cfg->label); \ return err; \ + } else { \ + LOG_DBG("Configured pin %d on %s for input", in_cfg->pin, in_cfg->label); \ } \ irq_callbacks_##n[i].work = &data->work; \ gpio_init_callback(&irq_callbacks_##n[i].callback, \ @@ -241,6 +268,8 @@ static int kscan_gpio_config_interrupts(struct device **devices, } \ } \ data->dev = dev; \ + COND_CODE_0(ZMK_KSCAN_MATRIX_POLLING, (), \ + (k_timer_init(&data->poll_timer, kscan_gpio_timer_handler, NULL);)) \ (COND_CODE_0(DT_INST_PROP(n, debounce_period), (k_work_init), (k_delayed_work_init)))( \ &data->work, kscan_gpio_work_handler_##n); \ return 0; \ @@ -248,7 +277,7 @@ static int kscan_gpio_config_interrupts(struct device **devices, static const struct kscan_driver_api gpio_driver_api_##n = { \ .config = kscan_gpio_configure_##n, \ .enable_callback = kscan_gpio_enable_##n, \ - .disable_callback = kscan_gpio_disable_interrupts_##n, \ + .disable_callback = kscan_gpio_disable_##n, \ }; \ static const struct kscan_gpio_config_##n kscan_gpio_config_##n = { \ .rows = {UTIL_LISTIFY(INST_MATRIX_ROWS(n), _KSCAN_GPIO_ROW_CFG_INIT, n)}, \ From cca8337f0562afbfb11de5af92ba5dc3c9334991 Mon Sep 17 00:00:00 2001 From: Jason Chestnut Date: Wed, 23 Sep 2020 16:05:29 -0400 Subject: [PATCH 06/61] Add support to GPIO matrix driver for matrix polling, rather than interrupt-based IO. - Add ZMK_KSCAN_MATRIX_POLLING config flag to Kconfig - Update matrix driver code to use the above flag to conditionally add the handling code for polling operations. --- app/boards/arm/planck/Kconfig.defconfig | 3 + .../clueboard_california/Kconfig.defconfig | 2 +- app/drivers/zephyr/Kconfig | 8 ++- app/drivers/zephyr/kscan_gpio_direct.c | 18 +++--- app/drivers/zephyr/kscan_gpio_matrix.c | 63 +++++++++++++------ 5 files changed, 64 insertions(+), 30 deletions(-) diff --git a/app/boards/arm/planck/Kconfig.defconfig b/app/boards/arm/planck/Kconfig.defconfig index 6f5bf525..913c1c13 100644 --- a/app/boards/arm/planck/Kconfig.defconfig +++ b/app/boards/arm/planck/Kconfig.defconfig @@ -11,4 +11,7 @@ config ZMK_KEYBOARD_NAME config ZMK_USB default y +config ZMK_KSCAN_MATRIX_POLLING + default y + endif # BOARD_PLANCK_REV6 diff --git a/app/boards/shields/clueboard_california/Kconfig.defconfig b/app/boards/shields/clueboard_california/Kconfig.defconfig index 2408f9ff..e101ea76 100644 --- a/app/boards/shields/clueboard_california/Kconfig.defconfig +++ b/app/boards/shields/clueboard_california/Kconfig.defconfig @@ -8,7 +8,7 @@ config ZMK_KEYBOARD_NAME # across A & B controllers, and STM32F303CCT6 can't enable # interrutps for multiple controllers for the same "line" # for the external interrupts. -config ZMK_KSCAN_GPIO_POLLING +config ZMK_KSCAN_DIRECT_POLLING default y endif diff --git a/app/drivers/zephyr/Kconfig b/app/drivers/zephyr/Kconfig index 0237846a..0534cab2 100644 --- a/app/drivers/zephyr/Kconfig +++ b/app/drivers/zephyr/Kconfig @@ -5,10 +5,14 @@ config ZMK_KSCAN_GPIO_DRIVER if ZMK_KSCAN_GPIO_DRIVER -config ZMK_KSCAN_GPIO_POLLING - bool "Poll for key event triggers instead of using interrupts" +config ZMK_KSCAN_MATRIX_POLLING + bool "Poll for key event triggers instead of using interrupts on matrix boards." default n +config ZMK_KSCAN_DIRECT_POLLING + bool "Poll for key event triggers instead of using interrupts on direct wired boards." + default n + endif config ZMK_KSCAN_INIT_PRIORITY diff --git a/app/drivers/zephyr/kscan_gpio_direct.c b/app/drivers/zephyr/kscan_gpio_direct.c index 1e5ab59e..7ba3399b 100644 --- a/app/drivers/zephyr/kscan_gpio_direct.c +++ b/app/drivers/zephyr/kscan_gpio_direct.c @@ -33,9 +33,9 @@ struct kscan_gpio_config { }; struct kscan_gpio_data { -#if defined(CONFIG_ZMK_KSCAN_GPIO_POLLING) +#if defined(ZMK_KSCAN_DIRECT_POLLING) struct k_timer poll_timer; -#endif /* defined(CONFIG_ZMK_KSCAN_GPIO_POLLING) */ +#endif /* defined(ZMK_KSCAN_DIRECT_POLLING) */ kscan_callback_t callback; union work_reference work; struct device *dev; @@ -53,7 +53,7 @@ static const struct kscan_gpio_item_config *kscan_gpio_input_configs(struct devi return cfg->inputs; } -#if !defined(CONFIG_ZMK_KSCAN_GPIO_POLLING) +#if !defined(ZMK_KSCAN_DIRECT_POLLING) struct kscan_gpio_irq_callback { union work_reference *work; @@ -101,7 +101,7 @@ static void kscan_gpio_irq_callback_handler(struct device *dev, struct gpio_call } } -#else /* !defined(CONFIG_ZMK_KSCAN_GPIO_POLLING) */ +#else /* !defined(ZMK_KSCAN_DIRECT_POLLING) */ static void kscan_gpio_timer_handler(struct k_timer *timer) { struct kscan_gpio_data *data = CONTAINER_OF(timer, struct kscan_gpio_data, poll_timer); @@ -120,7 +120,7 @@ static int kscan_gpio_direct_disable(struct device *dev) { return 0; } -#endif /* defined(CONFIG_ZMK_KSCAN_GPIO_POLLING) */ +#endif /* defined(ZMK_KSCAN_DIRECT_POLLING) */ static int kscan_gpio_direct_configure(struct device *dev, kscan_callback_t callback) { struct kscan_gpio_data *data = dev->driver_data; @@ -173,7 +173,7 @@ static const struct kscan_driver_api gpio_driver_api = { #define INST_INPUT_LEN(n) DT_INST_PROP_LEN(n, input_gpios) #define GPIO_INST_INIT(n) \ - COND_CODE_0(CONFIG_ZMK_KSCAN_GPIO_POLLING, \ + COND_CODE_0(ZMK_KSCAN_DIRECT_POLLING, \ (static struct kscan_gpio_irq_callback irq_callbacks_##n[INST_INPUT_LEN(n)];), ()) \ static struct kscan_gpio_data kscan_gpio_data_##n = { \ .inputs = {[INST_INPUT_LEN(n) - 1] = NULL}}; \ @@ -195,7 +195,7 @@ static const struct kscan_driver_api gpio_driver_api = { return err; \ } \ COND_CODE_0( \ - CONFIG_ZMK_KSCAN_GPIO_POLLING, \ + ZMK_KSCAN_DIRECT_POLLING, \ (irq_callbacks_##n[i].work = &data->work; \ irq_callbacks_##n[i].debounce_period = cfg->debounce_period; \ gpio_init_callback(&irq_callbacks_##n[i].callback, \ @@ -208,7 +208,7 @@ static const struct kscan_driver_api gpio_driver_api = { ()) \ } \ data->dev = dev; \ - COND_CODE_1(CONFIG_ZMK_KSCAN_GPIO_POLLING, \ + COND_CODE_1(ZMK_KSCAN_DIRECT_POLLING, \ (k_timer_init(&data->poll_timer, kscan_gpio_timer_handler, NULL);), ()) \ if (cfg->debounce_period > 0) { \ k_delayed_work_init(&data->work.delayed, kscan_gpio_work_handler); \ @@ -227,4 +227,4 @@ static const struct kscan_driver_api gpio_driver_api = { DT_INST_FOREACH_STATUS_OKAY(GPIO_INST_INIT) -#endif /* DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) */ \ No newline at end of file +#endif /* DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) */ diff --git a/app/drivers/zephyr/kscan_gpio_matrix.c b/app/drivers/zephyr/kscan_gpio_matrix.c index 634f694c..72709ba0 100644 --- a/app/drivers/zephyr/kscan_gpio_matrix.c +++ b/app/drivers/zephyr/kscan_gpio_matrix.c @@ -31,7 +31,8 @@ struct kscan_gpio_item_config { #define _KSCAN_GPIO_ROW_CFG_INIT(idx, n) _KSCAN_GPIO_ITEM_CFG_INIT(n, row_gpios, idx) #define _KSCAN_GPIO_COL_CFG_INIT(idx, n) _KSCAN_GPIO_ITEM_CFG_INIT(n, col_gpios, idx) -static int kscan_gpio_config_interrupts(struct device **devices, +COND_CODE_0(ZMK_KSCAN_MATRIX_POLLING, +(static int kscan_gpio_config_interrupts(struct device **devices, const struct kscan_gpio_item_config *configs, size_t len, gpio_flags_t flags) { for (int i = 0; i < len; i++) { @@ -47,7 +48,8 @@ static int kscan_gpio_config_interrupts(struct device **devices, } return 0; -} +}), ()) + #define INST_MATRIX_ROWS(n) DT_INST_PROP_LEN(n, row_gpios) #define INST_MATRIX_COLS(n) DT_INST_PROP_LEN(n, col_gpios) #define INST_OUTPUT_LEN(n) \ @@ -69,6 +71,7 @@ static int kscan_gpio_config_interrupts(struct device **devices, }; \ struct kscan_gpio_data_##n { \ kscan_callback_t callback; \ + COND_CODE_0(ZMK_KSCAN_MATRIX_POLLING, (), (struct k_timer poll_timer;)) \ struct COND_CODE_0(DT_INST_PROP(n, debounce_period), (k_work), (k_delayed_work)) work; \ bool matrix_state[INST_MATRIX_ROWS(n)][INST_MATRIX_COLS(n)]; \ struct device *rows[INST_MATRIX_ROWS(n)]; \ @@ -96,16 +99,17 @@ static int kscan_gpio_config_interrupts(struct device **devices, return ( \ COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (cfg->rows), (cfg->cols))); \ } \ - static int kscan_gpio_enable_interrupts_##n(struct device *dev) { \ - return kscan_gpio_config_interrupts(kscan_gpio_input_devices_##n(dev), \ + COND_CODE_0(ZMK_KSCAN_MATRIX_POLLING, \ + (static int kscan_gpio_enable_interrupts_##n(struct device *dev) { \ + return kscan_gpio_config_interrupts(kscan_gpio_input_devices_##n(dev), \ kscan_gpio_input_configs_##n(dev), INST_INPUT_LEN(n), \ GPIO_INT_DEBOUNCE | GPIO_INT_EDGE_BOTH); \ - } \ - static int kscan_gpio_disable_interrupts_##n(struct device *dev) { \ - return kscan_gpio_config_interrupts(kscan_gpio_input_devices_##n(dev), \ + } \ + static int kscan_gpio_disable_interrupts_##n(struct device *dev) { \ + return kscan_gpio_config_interrupts(kscan_gpio_input_devices_##n(dev), \ kscan_gpio_input_configs_##n(dev), INST_INPUT_LEN(n), \ GPIO_INT_DISABLE); \ - } \ + }), ()) \ static void kscan_gpio_set_output_state_##n(struct device *dev, int value) { \ for (int i = 0; i < INST_OUTPUT_LEN(n); i++) { \ struct device *in_dev = kscan_gpio_output_devices_##n(dev)[i]; \ @@ -128,7 +132,8 @@ static int kscan_gpio_config_interrupts(struct device **devices, /* Disable our interrupts temporarily while we scan, to avoid */ \ /* re-entry while we iterate columns and set them active one by one */ \ /* to get pressed state for each matrix cell. */ \ - kscan_gpio_disable_interrupts_##n(dev); \ + COND_CODE_0(ZMK_KSCAN_MATRIX_POLLING, \ + (kscan_gpio_disable_interrupts_##n(dev);),()) \ kscan_gpio_set_output_state_##n(dev, 0); \ for (int o = 0; o < INST_OUTPUT_LEN(n); o++) { \ struct device *out_dev = kscan_gpio_output_devices_##n(dev)[o]; \ @@ -143,10 +148,11 @@ static int kscan_gpio_config_interrupts(struct device **devices, } \ gpio_pin_set(out_dev, out_cfg->pin, 0); \ } \ - /* Set all our outputs as active again, then re-enable interrupts, */ \ - /* so we can trigger interrupts again for future press/release */ \ + /* Set all our outputs as active again. */ \ kscan_gpio_set_output_state_##n(dev, 1); \ - kscan_gpio_enable_interrupts_##n(dev); \ + /*Re-enable interrupts so that they can be triggered again for future press/release*/ \ + COND_CODE_0(ZMK_KSCAN_MATRIX_POLLING, \ + (kscan_gpio_enable_interrupts_##n(dev);), ()) \ for (int r = 0; r < INST_MATRIX_ROWS(n); r++) { \ for (int c = 0; c < INST_MATRIX_COLS(n); c++) { \ bool pressed = read_state[r][c]; \ @@ -193,12 +199,29 @@ static int kscan_gpio_config_interrupts(struct device **devices, return 0; \ }; \ static int kscan_gpio_enable_##n(struct device *dev) { \ - int err = kscan_gpio_enable_interrupts_##n(dev); \ - if (err) { \ - return err; \ - } \ - return kscan_gpio_read_##n(dev); \ + COND_CODE_0(ZMK_KSCAN_MATRIX_POLLING, \ + (int err = kscan_gpio_enable_interrupts_##n(dev); \ + if (err) { \ + return err; \ + } \ + return kscan_gpio_read_##n(dev);), \ + (struct kscan_gpio_data_##n *data = dev->driver_data; \ + k_timer_start(&data->poll_timer, K_MSEC(10), K_MSEC(10)); \ + return 0;)) \ + }; \ + static int kscan_gpio_disable_##n(struct device *dev) { \ + COND_CODE_0(ZMK_KSCAN_MATRIX_POLLING, \ + (return kscan_gpio_disable_interrupts_##n(dev);), \ + (struct kscan_gpio_data_##n *data = dev->driver_data; \ + k_timer_stop(&data->poll_timer); \ + return 0;)) \ }; \ + COND_CODE_0(ZMK_KSCAN_MATRIX_POLLING, (), \ + (static void kscan_gpio_timer_handler(struct k_timer *timer) { \ + struct kscan_gpio_data_##n *data = \ + CONTAINER_OF(timer, struct kscan_gpio_data_##n, poll_timer); \ + k_work_submit(&data->work.work); \ + })) \ static int kscan_gpio_init_##n(struct device *dev) { \ struct kscan_gpio_data_##n *data = dev->driver_data; \ int err; \ @@ -214,6 +237,8 @@ static int kscan_gpio_config_interrupts(struct device **devices, if (err) { \ LOG_ERR("Unable to configure pin %d on %s for input", in_cfg->pin, in_cfg->label); \ return err; \ + } else { \ + LOG_DBG("Configured pin %d on %s for input", in_cfg->pin, in_cfg->label); \ } \ irq_callbacks_##n[i].work = &data->work; \ gpio_init_callback(&irq_callbacks_##n[i].callback, \ @@ -241,6 +266,8 @@ static int kscan_gpio_config_interrupts(struct device **devices, } \ } \ data->dev = dev; \ + COND_CODE_0(ZMK_KSCAN_MATRIX_POLLING, (), \ + (k_timer_init(&data->poll_timer, kscan_gpio_timer_handler, NULL);)) \ (COND_CODE_0(DT_INST_PROP(n, debounce_period), (k_work_init), (k_delayed_work_init)))( \ &data->work, kscan_gpio_work_handler_##n); \ return 0; \ @@ -248,7 +275,7 @@ static int kscan_gpio_config_interrupts(struct device **devices, static const struct kscan_driver_api gpio_driver_api_##n = { \ .config = kscan_gpio_configure_##n, \ .enable_callback = kscan_gpio_enable_##n, \ - .disable_callback = kscan_gpio_disable_interrupts_##n, \ + .disable_callback = kscan_gpio_disable_##n, \ }; \ static const struct kscan_gpio_config_##n kscan_gpio_config_##n = { \ .rows = {UTIL_LISTIFY(INST_MATRIX_ROWS(n), _KSCAN_GPIO_ROW_CFG_INIT, n)}, \ From 9392c4f9ffbe815a44d007cf85a2a17955f46edb Mon Sep 17 00:00:00 2001 From: jason Date: Sun, 27 Sep 2020 21:27:30 -0400 Subject: [PATCH 07/61] Fix preprocessor flag issues for pull request. --- app/drivers/zephyr/kscan_gpio_direct.c | 16 ++++++++-------- app/drivers/zephyr/kscan_gpio_matrix.c | 23 ++++++++++++----------- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/app/drivers/zephyr/kscan_gpio_direct.c b/app/drivers/zephyr/kscan_gpio_direct.c index 7ba3399b..c3414fbf 100644 --- a/app/drivers/zephyr/kscan_gpio_direct.c +++ b/app/drivers/zephyr/kscan_gpio_direct.c @@ -33,9 +33,9 @@ struct kscan_gpio_config { }; struct kscan_gpio_data { -#if defined(ZMK_KSCAN_DIRECT_POLLING) +#if defined(CONFIG_ZMK_KSCAN_DIRECT_POLLING) struct k_timer poll_timer; -#endif /* defined(ZMK_KSCAN_DIRECT_POLLING) */ +#endif /* defined(CONFIG_ZMK_KSCAN_DIRECT_POLLING) */ kscan_callback_t callback; union work_reference work; struct device *dev; @@ -53,7 +53,7 @@ static const struct kscan_gpio_item_config *kscan_gpio_input_configs(struct devi return cfg->inputs; } -#if !defined(ZMK_KSCAN_DIRECT_POLLING) +#if !defined(CONFIG_ZMK_KSCAN_DIRECT_POLLING) struct kscan_gpio_irq_callback { union work_reference *work; @@ -101,7 +101,7 @@ static void kscan_gpio_irq_callback_handler(struct device *dev, struct gpio_call } } -#else /* !defined(ZMK_KSCAN_DIRECT_POLLING) */ +#else /* !defined(CONFIG_ZMK_KSCAN_DIRECT_POLLING) */ static void kscan_gpio_timer_handler(struct k_timer *timer) { struct kscan_gpio_data *data = CONTAINER_OF(timer, struct kscan_gpio_data, poll_timer); @@ -120,7 +120,7 @@ static int kscan_gpio_direct_disable(struct device *dev) { return 0; } -#endif /* defined(ZMK_KSCAN_DIRECT_POLLING) */ +#endif /* defined(CONFIG_ZMK_KSCAN_DIRECT_POLLING) */ static int kscan_gpio_direct_configure(struct device *dev, kscan_callback_t callback) { struct kscan_gpio_data *data = dev->driver_data; @@ -173,7 +173,7 @@ static const struct kscan_driver_api gpio_driver_api = { #define INST_INPUT_LEN(n) DT_INST_PROP_LEN(n, input_gpios) #define GPIO_INST_INIT(n) \ - COND_CODE_0(ZMK_KSCAN_DIRECT_POLLING, \ + COND_CODE_0(CONFIG_ZMK_KSCAN_DIRECT_POLLING, \ (static struct kscan_gpio_irq_callback irq_callbacks_##n[INST_INPUT_LEN(n)];), ()) \ static struct kscan_gpio_data kscan_gpio_data_##n = { \ .inputs = {[INST_INPUT_LEN(n) - 1] = NULL}}; \ @@ -195,7 +195,7 @@ static const struct kscan_driver_api gpio_driver_api = { return err; \ } \ COND_CODE_0( \ - ZMK_KSCAN_DIRECT_POLLING, \ + CONFIG_ZMK_KSCAN_DIRECT_POLLING, \ (irq_callbacks_##n[i].work = &data->work; \ irq_callbacks_##n[i].debounce_period = cfg->debounce_period; \ gpio_init_callback(&irq_callbacks_##n[i].callback, \ @@ -208,7 +208,7 @@ static const struct kscan_driver_api gpio_driver_api = { ()) \ } \ data->dev = dev; \ - COND_CODE_1(ZMK_KSCAN_DIRECT_POLLING, \ + COND_CODE_1(CONFIG_ZMK_KSCAN_DIRECT_POLLING, \ (k_timer_init(&data->poll_timer, kscan_gpio_timer_handler, NULL);), ()) \ if (cfg->debounce_period > 0) { \ k_delayed_work_init(&data->work.delayed, kscan_gpio_work_handler); \ diff --git a/app/drivers/zephyr/kscan_gpio_matrix.c b/app/drivers/zephyr/kscan_gpio_matrix.c index e581d33e..b940c6da 100644 --- a/app/drivers/zephyr/kscan_gpio_matrix.c +++ b/app/drivers/zephyr/kscan_gpio_matrix.c @@ -31,8 +31,8 @@ struct kscan_gpio_item_config { #define _KSCAN_GPIO_ROW_CFG_INIT(idx, n) _KSCAN_GPIO_ITEM_CFG_INIT(n, row_gpios, idx) #define _KSCAN_GPIO_COL_CFG_INIT(idx, n) _KSCAN_GPIO_ITEM_CFG_INIT(n, col_gpios, idx) -COND_CODE_0(ZMK_KSCAN_MATRIX_POLLING, -(static int kscan_gpio_config_interrupts(struct device **devices, +#ifdef CONFIG_ZMK_KSCAN_MATRIX_POLLING +static int kscan_gpio_config_interrupts(struct device **devices, const struct kscan_gpio_item_config *configs, size_t len, gpio_flags_t flags) { for (int i = 0; i < len; i++) { @@ -48,7 +48,8 @@ COND_CODE_0(ZMK_KSCAN_MATRIX_POLLING, } return 0; -}), ()) +} +#endif #define INST_MATRIX_ROWS(n) DT_INST_PROP_LEN(n, row_gpios) #define INST_MATRIX_COLS(n) DT_INST_PROP_LEN(n, col_gpios) @@ -71,7 +72,7 @@ COND_CODE_0(ZMK_KSCAN_MATRIX_POLLING, }; \ struct kscan_gpio_data_##n { \ kscan_callback_t callback; \ - COND_CODE_0(ZMK_KSCAN_MATRIX_POLLING, (), (struct k_timer poll_timer;)) \ + COND_CODE_0(CONFIG_ZMK_KSCAN_MATRIX_POLLING, (), (struct k_timer poll_timer;)) \ struct COND_CODE_0(DT_INST_PROP(n, debounce_period), (k_work), (k_delayed_work)) work; \ bool matrix_state[INST_MATRIX_ROWS(n)][INST_MATRIX_COLS(n)]; \ struct device *rows[INST_MATRIX_ROWS(n)]; \ @@ -99,7 +100,7 @@ COND_CODE_0(ZMK_KSCAN_MATRIX_POLLING, return ( \ COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (cfg->rows), (cfg->cols))); \ } \ - COND_CODE_0(ZMK_KSCAN_MATRIX_POLLING, \ + COND_CODE_0(CONFIG_ZMK_KSCAN_MATRIX_POLLING, \ (static int kscan_gpio_enable_interrupts_##n(struct device *dev) { \ return kscan_gpio_config_interrupts(kscan_gpio_input_devices_##n(dev), \ kscan_gpio_input_configs_##n(dev), INST_INPUT_LEN(n), \ @@ -132,7 +133,7 @@ COND_CODE_0(ZMK_KSCAN_MATRIX_POLLING, /* Disable our interrupts temporarily while we scan, to avoid */ \ /* re-entry while we iterate columns and set them active one by one */ \ /* to get pressed state for each matrix cell. */ \ - COND_CODE_0(ZMK_KSCAN_MATRIX_POLLING, \ + COND_CODE_0(CONFIG_ZMK_KSCAN_MATRIX_POLLING, \ (kscan_gpio_disable_interrupts_##n(dev);),()) \ kscan_gpio_set_output_state_##n(dev, 0); \ for (int o = 0; o < INST_OUTPUT_LEN(n); o++) { \ @@ -151,7 +152,7 @@ COND_CODE_0(ZMK_KSCAN_MATRIX_POLLING, /* Set all our outputs as active again. */ \ kscan_gpio_set_output_state_##n(dev, 1); \ /*Re-enable interrupts so that they can be triggered again for future press/release*/ \ - COND_CODE_0(ZMK_KSCAN_MATRIX_POLLING, \ + COND_CODE_0(CONFIG_ZMK_KSCAN_MATRIX_POLLING, \ (kscan_gpio_enable_interrupts_##n(dev);), ()) \ for (int r = 0; r < INST_MATRIX_ROWS(n); r++) { \ for (int c = 0; c < INST_MATRIX_COLS(n); c++) { \ @@ -200,7 +201,7 @@ COND_CODE_0(ZMK_KSCAN_MATRIX_POLLING, return 0; \ }; \ static int kscan_gpio_enable_##n(struct device *dev) { \ - COND_CODE_0(ZMK_KSCAN_MATRIX_POLLING, \ + COND_CODE_0(CONFIG_ZMK_KSCAN_MATRIX_POLLING, \ (int err = kscan_gpio_enable_interrupts_##n(dev); \ if (err) { \ return err; \ @@ -211,13 +212,13 @@ COND_CODE_0(ZMK_KSCAN_MATRIX_POLLING, return 0;)) \ }; \ static int kscan_gpio_disable_##n(struct device *dev) { \ - COND_CODE_0(ZMK_KSCAN_MATRIX_POLLING, \ + COND_CODE_0(CONFIG_ZMK_KSCAN_MATRIX_POLLING, \ (return kscan_gpio_disable_interrupts_##n(dev);), \ (struct kscan_gpio_data_##n *data = dev->driver_data; \ k_timer_stop(&data->poll_timer); \ return 0;)) \ }; \ - COND_CODE_0(ZMK_KSCAN_MATRIX_POLLING, (), \ + COND_CODE_0(CONFIG_ZMK_KSCAN_MATRIX_POLLING, (), \ (static void kscan_gpio_timer_handler(struct k_timer *timer) { \ struct kscan_gpio_data_##n *data = \ CONTAINER_OF(timer, struct kscan_gpio_data_##n, poll_timer); \ @@ -267,7 +268,7 @@ COND_CODE_0(ZMK_KSCAN_MATRIX_POLLING, } \ } \ data->dev = dev; \ - COND_CODE_0(ZMK_KSCAN_MATRIX_POLLING, (), \ + COND_CODE_0(CONFIG_ZMK_KSCAN_MATRIX_POLLING, (), \ (k_timer_init(&data->poll_timer, kscan_gpio_timer_handler, NULL);)) \ (COND_CODE_0(DT_INST_PROP(n, debounce_period), (k_work_init), (k_delayed_work_init)))( \ &data->work, kscan_gpio_work_handler_##n); \ From c2a861c0e6a731fd92368768a9b07d5feac7d374 Mon Sep 17 00:00:00 2001 From: Jason Chestnut Date: Mon, 28 Sep 2020 08:24:51 -0400 Subject: [PATCH 08/61] Modify preprocessor directives to use basic #if !defined() rather than Zephyr macros where appropriate. --- app/drivers/zephyr/kscan_gpio_matrix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/drivers/zephyr/kscan_gpio_matrix.c b/app/drivers/zephyr/kscan_gpio_matrix.c index b940c6da..5fa618bc 100644 --- a/app/drivers/zephyr/kscan_gpio_matrix.c +++ b/app/drivers/zephyr/kscan_gpio_matrix.c @@ -31,7 +31,7 @@ struct kscan_gpio_item_config { #define _KSCAN_GPIO_ROW_CFG_INIT(idx, n) _KSCAN_GPIO_ITEM_CFG_INIT(n, row_gpios, idx) #define _KSCAN_GPIO_COL_CFG_INIT(idx, n) _KSCAN_GPIO_ITEM_CFG_INIT(n, col_gpios, idx) -#ifdef CONFIG_ZMK_KSCAN_MATRIX_POLLING +#if !defined(CONFIG_ZMK_KSCAN_MATRIX_POLLING) static int kscan_gpio_config_interrupts(struct device **devices, const struct kscan_gpio_item_config *configs, size_t len, gpio_flags_t flags) { From e993378b2a1705f97a5cca95d16810ab766f8d94 Mon Sep 17 00:00:00 2001 From: Pete Johanson Date: Thu, 1 Oct 2020 11:24:57 -0400 Subject: [PATCH 09/61] chore: Fix some accidental formatting issues. --- app/drivers/zephyr/kscan_gpio_matrix.c | 69 ++++++++++++-------------- 1 file changed, 32 insertions(+), 37 deletions(-) diff --git a/app/drivers/zephyr/kscan_gpio_matrix.c b/app/drivers/zephyr/kscan_gpio_matrix.c index 5fa618bc..62008e32 100644 --- a/app/drivers/zephyr/kscan_gpio_matrix.c +++ b/app/drivers/zephyr/kscan_gpio_matrix.c @@ -72,7 +72,7 @@ static int kscan_gpio_config_interrupts(struct device **devices, }; \ struct kscan_gpio_data_##n { \ kscan_callback_t callback; \ - COND_CODE_0(CONFIG_ZMK_KSCAN_MATRIX_POLLING, (), (struct k_timer poll_timer;)) \ + COND_CODE_0(CONFIG_ZMK_KSCAN_MATRIX_POLLING, (), (struct k_timer poll_timer;)) \ struct COND_CODE_0(DT_INST_PROP(n, debounce_period), (k_work), (k_delayed_work)) work; \ bool matrix_state[INST_MATRIX_ROWS(n)][INST_MATRIX_COLS(n)]; \ struct device *rows[INST_MATRIX_ROWS(n)]; \ @@ -100,17 +100,18 @@ static int kscan_gpio_config_interrupts(struct device **devices, return ( \ COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (cfg->rows), (cfg->cols))); \ } \ - COND_CODE_0(CONFIG_ZMK_KSCAN_MATRIX_POLLING, \ - (static int kscan_gpio_enable_interrupts_##n(struct device *dev) { \ - return kscan_gpio_config_interrupts(kscan_gpio_input_devices_##n(dev), \ - kscan_gpio_input_configs_##n(dev), INST_INPUT_LEN(n), \ - GPIO_INT_DEBOUNCE | GPIO_INT_EDGE_BOTH); \ - } \ - static int kscan_gpio_disable_interrupts_##n(struct device *dev) { \ - return kscan_gpio_config_interrupts(kscan_gpio_input_devices_##n(dev), \ - kscan_gpio_input_configs_##n(dev), INST_INPUT_LEN(n), \ - GPIO_INT_DISABLE); \ - }), ()) \ + COND_CODE_0(CONFIG_ZMK_KSCAN_MATRIX_POLLING, \ + ( \ + static int kscan_gpio_enable_interrupts_##n(struct device *dev) { \ + return kscan_gpio_config_interrupts( \ + kscan_gpio_input_devices_##n(dev), kscan_gpio_input_configs_##n(dev), \ + INST_INPUT_LEN(n), GPIO_INT_DEBOUNCE | GPIO_INT_EDGE_BOTH); \ + } static int kscan_gpio_disable_interrupts_##n(struct device *dev) { \ + return kscan_gpio_config_interrupts(kscan_gpio_input_devices_##n(dev), \ + kscan_gpio_input_configs_##n(dev), \ + INST_INPUT_LEN(n), GPIO_INT_DISABLE); \ + }), \ + ()) \ static void kscan_gpio_set_output_state_##n(struct device *dev, int value) { \ for (int i = 0; i < INST_OUTPUT_LEN(n); i++) { \ struct device *in_dev = kscan_gpio_output_devices_##n(dev)[i]; \ @@ -133,8 +134,8 @@ static int kscan_gpio_config_interrupts(struct device **devices, /* Disable our interrupts temporarily while we scan, to avoid */ \ /* re-entry while we iterate columns and set them active one by one */ \ /* to get pressed state for each matrix cell. */ \ - COND_CODE_0(CONFIG_ZMK_KSCAN_MATRIX_POLLING, \ - (kscan_gpio_disable_interrupts_##n(dev);),()) \ + COND_CODE_0(CONFIG_ZMK_KSCAN_MATRIX_POLLING, (kscan_gpio_disable_interrupts_##n(dev);), \ + ()) \ kscan_gpio_set_output_state_##n(dev, 0); \ for (int o = 0; o < INST_OUTPUT_LEN(n); o++) { \ struct device *out_dev = kscan_gpio_output_devices_##n(dev)[o]; \ @@ -152,8 +153,7 @@ static int kscan_gpio_config_interrupts(struct device **devices, /* Set all our outputs as active again. */ \ kscan_gpio_set_output_state_##n(dev, 1); \ /*Re-enable interrupts so that they can be triggered again for future press/release*/ \ - COND_CODE_0(CONFIG_ZMK_KSCAN_MATRIX_POLLING, \ - (kscan_gpio_enable_interrupts_##n(dev);), ()) \ + COND_CODE_0(CONFIG_ZMK_KSCAN_MATRIX_POLLING, (kscan_gpio_enable_interrupts_##n(dev);), ()) \ for (int r = 0; r < INST_MATRIX_ROWS(n); r++) { \ for (int c = 0; c < INST_MATRIX_COLS(n); c++) { \ bool pressed = read_state[r][c]; \ @@ -201,29 +201,24 @@ static int kscan_gpio_config_interrupts(struct device **devices, return 0; \ }; \ static int kscan_gpio_enable_##n(struct device *dev) { \ - COND_CODE_0(CONFIG_ZMK_KSCAN_MATRIX_POLLING, \ - (int err = kscan_gpio_enable_interrupts_##n(dev); \ - if (err) { \ - return err; \ - } \ - return kscan_gpio_read_##n(dev);), \ - (struct kscan_gpio_data_##n *data = dev->driver_data; \ - k_timer_start(&data->poll_timer, K_MSEC(10), K_MSEC(10)); \ - return 0;)) \ + COND_CODE_0(CONFIG_ZMK_KSCAN_MATRIX_POLLING, \ + (int err = kscan_gpio_enable_interrupts_##n(dev); \ + if (err) { return err; } return kscan_gpio_read_##n(dev);), \ + (struct kscan_gpio_data_##n *data = dev->driver_data; \ + k_timer_start(&data->poll_timer, K_MSEC(10), K_MSEC(10)); return 0;)) \ }; \ static int kscan_gpio_disable_##n(struct device *dev) { \ - COND_CODE_0(CONFIG_ZMK_KSCAN_MATRIX_POLLING, \ - (return kscan_gpio_disable_interrupts_##n(dev);), \ - (struct kscan_gpio_data_##n *data = dev->driver_data; \ - k_timer_stop(&data->poll_timer); \ - return 0;)) \ + COND_CODE_0(CONFIG_ZMK_KSCAN_MATRIX_POLLING, \ + (return kscan_gpio_disable_interrupts_##n(dev);), \ + (struct kscan_gpio_data_##n *data = dev->driver_data; \ + k_timer_stop(&data->poll_timer); return 0;)) \ }; \ - COND_CODE_0(CONFIG_ZMK_KSCAN_MATRIX_POLLING, (), \ - (static void kscan_gpio_timer_handler(struct k_timer *timer) { \ - struct kscan_gpio_data_##n *data = \ - CONTAINER_OF(timer, struct kscan_gpio_data_##n, poll_timer); \ - k_work_submit(&data->work.work); \ - })) \ + COND_CODE_0(CONFIG_ZMK_KSCAN_MATRIX_POLLING, (), \ + (static void kscan_gpio_timer_handler(struct k_timer *timer) { \ + struct kscan_gpio_data_##n *data = \ + CONTAINER_OF(timer, struct kscan_gpio_data_##n, poll_timer); \ + k_work_submit(&data->work.work); \ + })) \ static int kscan_gpio_init_##n(struct device *dev) { \ struct kscan_gpio_data_##n *data = dev->driver_data; \ int err; \ @@ -268,7 +263,7 @@ static int kscan_gpio_config_interrupts(struct device **devices, } \ } \ data->dev = dev; \ - COND_CODE_0(CONFIG_ZMK_KSCAN_MATRIX_POLLING, (), \ + COND_CODE_0(CONFIG_ZMK_KSCAN_MATRIX_POLLING, (), \ (k_timer_init(&data->poll_timer, kscan_gpio_timer_handler, NULL);)) \ (COND_CODE_0(DT_INST_PROP(n, debounce_period), (k_work_init), (k_delayed_work_init)))( \ &data->work, kscan_gpio_work_handler_##n); \ From 694b24ca86d315d6dcf906088a1a3d03d57579c0 Mon Sep 17 00:00:00 2001 From: Pete Johanson Date: Thu, 1 Oct 2020 11:31:02 -0400 Subject: [PATCH 10/61] fix(ci): Lint detected changes to drivers dir. --- .github/workflows/clang-format-lint.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/clang-format-lint.yml b/.github/workflows/clang-format-lint.yml index 061bc3da..70ae9863 100644 --- a/.github/workflows/clang-format-lint.yml +++ b/.github/workflows/clang-format-lint.yml @@ -6,11 +6,15 @@ on: - "app/boards/**/*.c" - "app/include/**/*.h" - "app/src/**" + - "app/drivers/**/*.c" + - "app/drivers/**/*.h" pull_request: paths: - "app/boards/**/*.c" - "app/include/**/*.h" - "app/src/**" + - "app/drivers/**/*.c" + - "app/drivers/**/*.h" jobs: build: From 028dfae92e2b0900514182f096959b07a7204ab3 Mon Sep 17 00:00:00 2001 From: Pete Johanson Date: Thu, 1 Oct 2020 11:40:49 -0400 Subject: [PATCH 11/61] chore: Fix remaining formatting issues. --- app/drivers/zephyr/kscan_gpio_direct.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/drivers/zephyr/kscan_gpio_direct.c b/app/drivers/zephyr/kscan_gpio_direct.c index c3414fbf..d6dab4d1 100644 --- a/app/drivers/zephyr/kscan_gpio_direct.c +++ b/app/drivers/zephyr/kscan_gpio_direct.c @@ -173,7 +173,7 @@ static const struct kscan_driver_api gpio_driver_api = { #define INST_INPUT_LEN(n) DT_INST_PROP_LEN(n, input_gpios) #define GPIO_INST_INIT(n) \ - COND_CODE_0(CONFIG_ZMK_KSCAN_DIRECT_POLLING, \ + COND_CODE_0(CONFIG_ZMK_KSCAN_DIRECT_POLLING, \ (static struct kscan_gpio_irq_callback irq_callbacks_##n[INST_INPUT_LEN(n)];), ()) \ static struct kscan_gpio_data kscan_gpio_data_##n = { \ .inputs = {[INST_INPUT_LEN(n) - 1] = NULL}}; \ @@ -195,7 +195,7 @@ static const struct kscan_driver_api gpio_driver_api = { return err; \ } \ COND_CODE_0( \ - CONFIG_ZMK_KSCAN_DIRECT_POLLING, \ + CONFIG_ZMK_KSCAN_DIRECT_POLLING, \ (irq_callbacks_##n[i].work = &data->work; \ irq_callbacks_##n[i].debounce_period = cfg->debounce_period; \ gpio_init_callback(&irq_callbacks_##n[i].callback, \ @@ -208,7 +208,7 @@ static const struct kscan_driver_api gpio_driver_api = { ()) \ } \ data->dev = dev; \ - COND_CODE_1(CONFIG_ZMK_KSCAN_DIRECT_POLLING, \ + COND_CODE_1(CONFIG_ZMK_KSCAN_DIRECT_POLLING, \ (k_timer_init(&data->poll_timer, kscan_gpio_timer_handler, NULL);), ()) \ if (cfg->debounce_period > 0) { \ k_delayed_work_init(&data->work.delayed, kscan_gpio_work_handler); \ From 9a3d515583997a78b41ab9d2b84e8b56126dda09 Mon Sep 17 00:00:00 2001 From: Pete Johanson Date: Thu, 1 Oct 2020 15:40:39 -0400 Subject: [PATCH 12/61] fix(docs): Link to nice!nano product page itself. --- docs/docs/hardware.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/hardware.md b/docs/docs/hardware.md index 236aa972..faac57c6 100644 --- a/docs/docs/hardware.md +++ b/docs/docs/hardware.md @@ -16,7 +16,7 @@ That being said, there are currently only a few specific [boards](/docs/faq#what ## Boards -- [nice!nano](https://docs.nicekeyboards.com/#/nice!nano/) (`nice_nano`) +- [nice!nano](https://nicekeyboards.com/products/nice-nano-v1-0) (`nice_nano`) - [nrfMicro](https://github.com/joric/nrfmicro) (`nrfmicro_13`, `nrfmicro_11`, `nrfmicro_11_flipped`) - [BlueMicro840](https://store.jpconstantineau.com/#/group/bluemicro) (`bluemicro840_v1`) - [QMK Proton-C](https://qmk.fm/proton-c/) (`proton_c`) From 307a8d09db78b95c858c41bd5549c721da7eb1f8 Mon Sep 17 00:00:00 2001 From: Pete Johanson Date: Thu, 1 Oct 2020 17:18:01 -0400 Subject: [PATCH 13/61] feat(usb): Function to access latest USB status. * To be leveraged by upcoming power management work. --- app/include/zmk/usb_hid.h | 2 ++ app/src/usb_hid.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/app/include/zmk/usb_hid.h b/app/include/zmk/usb_hid.h index 7ee26298..83a45407 100644 --- a/app/include/zmk/usb_hid.h +++ b/app/include/zmk/usb_hid.h @@ -14,4 +14,6 @@ int zmk_usb_hid_init(); +enum usb_dc_status_code zmk_usb_hid_get_status(); + int zmk_usb_hid_send_report(u8_t *report, size_t len); diff --git a/app/src/usb_hid.c b/app/src/usb_hid.c index 530ffea8..64addaea 100644 --- a/app/src/usb_hid.c +++ b/app/src/usb_hid.c @@ -28,6 +28,8 @@ static const struct hid_ops ops = { .int_in_ready = in_ready_cb, }; +enum usb_dc_status_code zmk_usb_hid_get_status() { return usb_status; } + int zmk_usb_hid_send_report(const u8_t *report, size_t len) { switch (usb_status) { case USB_DC_SUSPEND: From c68e3d3e42b9ff1722b2c2b9728f5d3b85784a45 Mon Sep 17 00:00:00 2001 From: Dev Date: Thu, 1 Oct 2020 11:26:54 +0530 Subject: [PATCH 14/61] Add missing licensing header Fixes #205 --- app/include/dt-bindings/zmk/keys.h | 5 +++++ app/include/dt-bindings/zmk/kscan-mock.h | 6 ++++++ app/include/dt-bindings/zmk/matrix-transform.h | 5 +++++ app/include/dt-bindings/zmk/rgb.h | 5 +++++ app/include/zmk/split/bluetooth/service.h | 6 ++++++ app/include/zmk/split/bluetooth/uuid.h | 6 ++++++ 6 files changed, 33 insertions(+) diff --git a/app/include/dt-bindings/zmk/keys.h b/app/include/dt-bindings/zmk/keys.h index d3dd6341..a3b22297 100644 --- a/app/include/dt-bindings/zmk/keys.h +++ b/app/include/dt-bindings/zmk/keys.h @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ #pragma once diff --git a/app/include/dt-bindings/zmk/kscan-mock.h b/app/include/dt-bindings/zmk/kscan-mock.h index d481899f..eff218b2 100644 --- a/app/include/dt-bindings/zmk/kscan-mock.h +++ b/app/include/dt-bindings/zmk/kscan-mock.h @@ -1,3 +1,9 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + #pragma once #define ZMK_MOCK_IS_PRESS(v) ((v & (0x01 << 31)) != 0) diff --git a/app/include/dt-bindings/zmk/matrix-transform.h b/app/include/dt-bindings/zmk/matrix-transform.h index 4fd3e6c9..2989cb60 100644 --- a/app/include/dt-bindings/zmk/matrix-transform.h +++ b/app/include/dt-bindings/zmk/matrix-transform.h @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ #define KT_ROW(item) (item >> 8) #define KT_COL(item) (item & 0xFF) diff --git a/app/include/dt-bindings/zmk/rgb.h b/app/include/dt-bindings/zmk/rgb.h index c2efda88..eb721807 100644 --- a/app/include/dt-bindings/zmk/rgb.h +++ b/app/include/dt-bindings/zmk/rgb.h @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ #define RGB_TOG 0 #define RGB_HUI 1 diff --git a/app/include/zmk/split/bluetooth/service.h b/app/include/zmk/split/bluetooth/service.h index 954e0cdd..c2be512f 100644 --- a/app/include/zmk/split/bluetooth/service.h +++ b/app/include/zmk/split/bluetooth/service.h @@ -1,3 +1,9 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + #pragma once int zmk_split_bt_position_pressed(u8_t position); diff --git a/app/include/zmk/split/bluetooth/uuid.h b/app/include/zmk/split/bluetooth/uuid.h index a8dfbf62..a31884d9 100644 --- a/app/include/zmk/split/bluetooth/uuid.h +++ b/app/include/zmk/split/bluetooth/uuid.h @@ -1,3 +1,9 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + #pragma once #include From dfb4f1277d66b58de5473c46ed04cf3d7c102b30 Mon Sep 17 00:00:00 2001 From: Pete Johanson Date: Fri, 2 Oct 2020 23:17:53 -0400 Subject: [PATCH 15/61] fix(docs): Proper emphasis of MUST NOT. --- docs/docs/dev-clean-room.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/docs/dev-clean-room.md b/docs/docs/dev-clean-room.md index c11171c8..2f301ec7 100644 --- a/docs/docs/dev-clean-room.md +++ b/docs/docs/dev-clean-room.md @@ -6,7 +6,7 @@ sidebar_label: Clean Room :::warning -Anyone wanting to contribute code to ZMK _must_ read this, and adhere to the steps outlines in order to not violate any licenses/copyright of other projects +Anyone wanting to contribute code to ZMK _MUST_ read this, and adhere to the steps outlines in order to not violate any licenses/copyright of other projects ::: @@ -22,8 +22,8 @@ or duplicating any of the GPL code found in those other projects, even though th Contributors to ZMK must adhere to the following standard. -- Implementations of features for ZMK _MUST_ not reuse any existing code from any projects not licensed with the MIT license. -- Contributors _MUST_ not study or refer to any GPL licensed source code while working on ZMK. +- Implementations of features for ZMK _MUST NOT_ reuse any existing code from any projects not licensed with the MIT license. +- Contributors _MUST NOT_ study or refer to any GPL licensed source code while working on ZMK. - Contributors _MAY_ read the documentation from other GPL licensed projects, to gain a broad understanding of the behavior of certain features in order to implement equivalent features for ZMK. - Contributors _MAY_ refer to the [QMK Configurator](https://config.qmk.fm/) to inspect existing layouts/keymaps for keyboards, and re-implement them for ZMK. From f6f8abe05514c3588c4aa4a56897462c377bcab6 Mon Sep 17 00:00:00 2001 From: Joel Spadin Date: Sat, 26 Sep 2020 18:39:13 -0500 Subject: [PATCH 16/61] fix(ec11): allow more than one encoder Fixes "device.h:101:11: error: redefinition of '__device_ec11'" in firmware that has more than one encoder. --- app/drivers/zephyr/ec11.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/drivers/zephyr/ec11.c b/app/drivers/zephyr/ec11.c index a4e96c24..00d00905 100644 --- a/app/drivers/zephyr/ec11.c +++ b/app/drivers/zephyr/ec11.c @@ -142,7 +142,7 @@ int ec11_init(struct device *dev) { .b_flags = DT_INST_GPIO_FLAGS(n, b_gpios), \ COND_CODE_0(DT_INST_NODE_HAS_PROP(n, resolution), (1), (DT_INST_PROP(n, resolution))), \ }; \ - DEVICE_AND_API_INIT(ec11, DT_INST_LABEL(n), ec11_init, &ec11_data_##n, &ec11_cfg_##n, \ + DEVICE_AND_API_INIT(ec11_##n, DT_INST_LABEL(n), ec11_init, &ec11_data_##n, &ec11_cfg_##n, \ POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, &ec11_driver_api); DT_INST_FOREACH_STATUS_OKAY(EC11_INST) \ No newline at end of file From fc5915b2001c80df5ab2db72b04d86a083e27556 Mon Sep 17 00:00:00 2001 From: Joel Spadin Date: Sun, 4 Oct 2020 12:33:12 -0500 Subject: [PATCH 17/61] improvement(kscan): use ARRAY_SIZE macro --- app/src/kscan_composite.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/app/src/kscan_composite.c b/app/src/kscan_composite.c index 02491407..f8e8d604 100644 --- a/app/src/kscan_composite.c +++ b/app/src/kscan_composite.c @@ -38,8 +38,7 @@ struct kscan_composite_data { }; static int kscan_composite_enable_callback(struct device *dev) { - for (int i = 0; i < sizeof(kscan_composite_children) / sizeof(kscan_composite_children[0]); - i++) { + for (int i = 0; i < ARRAY_SIZE(kscan_composite_children); i++) { const struct kscan_composite_child_config *cfg = &kscan_composite_children[i]; kscan_enable_callback(device_get_binding(cfg->label)); @@ -48,8 +47,7 @@ static int kscan_composite_enable_callback(struct device *dev) { } static int kscan_composite_disable_callback(struct device *dev) { - for (int i = 0; i < sizeof(kscan_composite_children) / sizeof(kscan_composite_children[0]); - i++) { + for (int i = 0; i < ARRAY_SIZE(kscan_composite_children); i++) { const struct kscan_composite_child_config *cfg = &kscan_composite_children[i]; kscan_disable_callback(device_get_binding(cfg->label)); @@ -63,8 +61,7 @@ static void kscan_composite_child_callback(struct device *child_dev, u32_t row, struct device *dev = device_get_binding(DT_INST_LABEL(0)); struct kscan_composite_data *data = dev->driver_data; - for (int i = 0; i < sizeof(kscan_composite_children) / sizeof(kscan_composite_children[0]); - i++) { + for (int i = 0; i < ARRAY_SIZE(kscan_composite_children); i++) { const struct kscan_composite_child_config *cfg = &kscan_composite_children[i]; if (device_get_binding(cfg->label) != child_dev) { @@ -82,8 +79,7 @@ static int kscan_composite_configure(struct device *dev, kscan_callback_t callba return -EINVAL; } - for (int i = 0; i < sizeof(kscan_composite_children) / sizeof(kscan_composite_children[0]); - i++) { + for (int i = 0; i < ARRAY_SIZE(kscan_composite_children); i++) { const struct kscan_composite_child_config *cfg = &kscan_composite_children[i]; kscan_config(device_get_binding(cfg->label), &kscan_composite_child_callback); From 4121b07f7f75b81cf1d533632fde858074b0fc03 Mon Sep 17 00:00:00 2001 From: Joel Spadin Date: Sun, 4 Oct 2020 14:03:55 -0500 Subject: [PATCH 18/61] fix(kscan): fix direct GPIO when using interrupts Fixed initializing interrupts for direct GPIO when CONFIG_ZMK_KSCAN_DIRECT_POLLING is not enabled. IS_ENABLED() is needed to map the possibly-undefined value to 0 or 1 so COND_CODE_0() and COND_CODE_1() work. --- app/drivers/zephyr/kscan_gpio_direct.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/drivers/zephyr/kscan_gpio_direct.c b/app/drivers/zephyr/kscan_gpio_direct.c index d6dab4d1..4818c995 100644 --- a/app/drivers/zephyr/kscan_gpio_direct.c +++ b/app/drivers/zephyr/kscan_gpio_direct.c @@ -173,7 +173,7 @@ static const struct kscan_driver_api gpio_driver_api = { #define INST_INPUT_LEN(n) DT_INST_PROP_LEN(n, input_gpios) #define GPIO_INST_INIT(n) \ - COND_CODE_0(CONFIG_ZMK_KSCAN_DIRECT_POLLING, \ + COND_CODE_0(IS_ENABLED(CONFIG_ZMK_KSCAN_DIRECT_POLLING), \ (static struct kscan_gpio_irq_callback irq_callbacks_##n[INST_INPUT_LEN(n)];), ()) \ static struct kscan_gpio_data kscan_gpio_data_##n = { \ .inputs = {[INST_INPUT_LEN(n) - 1] = NULL}}; \ @@ -195,7 +195,7 @@ static const struct kscan_driver_api gpio_driver_api = { return err; \ } \ COND_CODE_0( \ - CONFIG_ZMK_KSCAN_DIRECT_POLLING, \ + IS_ENABLED(CONFIG_ZMK_KSCAN_DIRECT_POLLING), \ (irq_callbacks_##n[i].work = &data->work; \ irq_callbacks_##n[i].debounce_period = cfg->debounce_period; \ gpio_init_callback(&irq_callbacks_##n[i].callback, \ @@ -208,7 +208,7 @@ static const struct kscan_driver_api gpio_driver_api = { ()) \ } \ data->dev = dev; \ - COND_CODE_1(CONFIG_ZMK_KSCAN_DIRECT_POLLING, \ + COND_CODE_1(IS_ENABLED(CONFIG_ZMK_KSCAN_DIRECT_POLLING), \ (k_timer_init(&data->poll_timer, kscan_gpio_timer_handler, NULL);), ()) \ if (cfg->debounce_period > 0) { \ k_delayed_work_init(&data->work.delayed, kscan_gpio_work_handler); \ From 31e481954f1e22e42bde4b71753e279cdd4c77ed Mon Sep 17 00:00:00 2001 From: Kevin Date: Sun, 4 Oct 2020 17:03:56 -0700 Subject: [PATCH 19/61] fix(docs): Fixed Python environment variables and commands for Windows setup --- docs/docs/dev-setup.md | 111 +++++++++++++++++++++-------------------- 1 file changed, 57 insertions(+), 54 deletions(-) diff --git a/docs/docs/dev-setup.md b/docs/docs/dev-setup.md index 1d7d703b..2e232f89 100644 --- a/docs/docs/dev-setup.md +++ b/docs/docs/dev-setup.md @@ -12,16 +12,16 @@ groupId="operating-systems" defaultValue="debian" values={[ {label: 'Debian/Ubuntu', value: 'debian'}, -{label: 'Raspberry OS', value: 'raspberryos'}, -{label: 'Fedora', value: 'fedora'}, {label: 'Windows', value: 'win'}, {label: 'macOS', value: 'mac'}, +{label: 'Raspberry OS', value: 'raspberryos'}, +{label: 'Fedora', value: 'fedora'}, ] }>{props.children}); ## Prerequisites -A unix-like environment with the following base packages installed: +ZMK requires the following base packages to first be installed: - Git - Python 3 @@ -34,6 +34,7 @@ A unix-like environment with the following base packages installed: + On Debian and Ubuntu, we'll use `apt` to install our base dependencies: First, if you haven't updated recently, or if this is a new install, @@ -74,7 +75,8 @@ or download and install CMake version 3.13.1 or newer manually. ::: -On Raspberry OS, we'll use apt to install our base dependencies: + +On Raspberry OS, we'll use `apt` to install our base dependencies: First, if you haven't updated recently, or if this is a new install, you should update to get the latest package information: @@ -185,14 +187,39 @@ brew install cmake ninja python3 ccache dtc git wget `west` is the [Zephyr™ meta-tool](https://docs.zephyrproject.org/2.3.0/guides/west/index.html) used to configure and build Zephyr™ applications. -West can be installed by using the `pip` python package manager. +West can be installed by using the `pip` python package manager. The [Zephyr™ instructions](https://docs.zephyrproject.org/latest/guides/west/install.html#installing-west) are summarized here: + + + ```sh pip3 install --user -U west ``` -:::danger pip user packages -If you haven't done so yet, you may need to add the Python Pip user package directory to your `PATH` otherwise your computer will not be able to find the `west` command. + + + +In `cmd.exe` as **Administrator**: + +```sh +pip3 install -U west +``` + +Once `west` is installed, close Command Prompt and open a new session as a **user** for the remainder of the instructions. +:::note +**For Windows, do not use the `--user` argument** that Linux uses otherwise `west` will be installed in a different location and the below instructions for adding Python `pip` will no longer apply. +::: + + + + +:::danger `pip` user packages +If you haven't done so yet, you may need to add the Python `pip` package directory to your `PATH` otherwise your computer will not be able to find the `west` command. ::: 1. See the [Environment Variables](#environment-variables) section on how to get to the Environment Variables page. -3. Click "Edit..." and then "New" to add the directory where your west.exe is located. By default this should be something like `C:\Python38\Scripts`. +2. Under "System variables" select the "Path" variable. Click "Edit..." and then "New" to add the directory where your `west.exe` is located. By default this should be `C:\Python##\Scripts` where ## is your Python version number. +3. Close Command Prompt and open a new session for the changes to take effect, or run `refreshenv`. @@ -279,7 +307,7 @@ The installation will prompt with several questions about installation location, #### GNU ARM Embedded -Since the Zephyr™ SDK is not available for Windows, we recommending following the steps to install the [GNU ARM Embedded](https://docs.zephyrproject.org/2.3.0/getting_started/toolchain_3rd_party_x_compilers.html#gnu-arm-embedded). +Since the Zephyr™ SDK is not available for Windows, we recommending following the [Zephyr documentation](https://docs.zephyrproject.org/2.3.0/getting_started/toolchain_3rd_party_x_compilers.html#gnu-arm-embedded) to install a GNU ARM Embedded build. Note the warnings regarding installing the toolchain into a path with spaces, and make sure to follow the steps to add the environment variables which are also summarized with screenshots in the [Environment Variables](#environment-variables) section below. @@ -308,7 +336,7 @@ The transient instructions must be run to build firmware using the current shell ### Source Code -Next, you'll need to clone the ZMK source repository if you haven't already: +Next, you'll need to clone the ZMK source repository if you haven't already. Navigate to the folder you would like to place your `zmk` directory in and run the following command: ``` git clone https://github.com/zmkfirmware/zmk.git @@ -358,12 +386,17 @@ pip3 install --user -r zephyr/scripts/requirements-base.txt ### Environment Variables -#### For GNU ARM Embedded on Windows + + -On Windows, you will have to set two environment variables for ZMK to build properly: `ZEPHYR_TOOLCHAIN_VARIANT` and `GNUARMEMB_TOOLCHAIN_PATH`. +#### For GNU ARM Embedded on Windows -
- Steps to Update Environment Variables +On Windows, only two environment variables need to be set for ZMK to build properly: `ZEPHYR_TOOLCHAIN_VARIANT` and `GNUARMEMB_TOOLCHAIN_PATH`. 1. Open Start Menu and type 'env' to find the 'Edit the system environment variables' option. Open it. @@ -381,11 +414,15 @@ On Windows, you will have to set two environment variables for ZMK to build prop ![Adding Zephyr toolchain variable](assets/env-var/zephyr_toolchain.png) -5. Create another variable with variable name 'GNUARMEMB_TOOLCHAIN_PATH' and value set to wherever you installed your toolchain. Click OK to save. +5. Create another variable with variable name 'GNUARMEMB_TOOLCHAIN_PATH' and value set to wherever you installed your toolchain. **Make sure this path does not contain any spaces.** If it does, rename the folder and update here. Click OK to save. ![Adding GNUARMEMB variable](assets/env-var/gnuarmemb.png) -
+6. Close Command Prompt and reopen, or run `refreshenv` to apply the changes. + +
+ + #### For Zephyr @@ -396,48 +433,10 @@ We suggest two main [options](https://docs.zephyrproject.org/2.3.0/guides/env_va To load the Zephyr environment properly for just one transient shell, run the following from your ZMK checkout directory: - - - -``` -source zephyr/zephyr-env.sh -``` - - - - - -``` -source zephyr/zephyr-env.sh -``` - - - - - ``` source zephyr/zephyr-env.sh ``` - - - - -``` -source zephyr/zephyr-env.sh -``` - - - - - -``` -source zephyr/zephyr-env.cmd -``` - - - - ##### All Shells To load the environment variables for your shell every time, @@ -469,3 +468,7 @@ cat ~/.zephyrrc >> ~/.zshrc
+ +
+ + From 6427e64df3e889325ea471ff98f185f5eee27027 Mon Sep 17 00:00:00 2001 From: Kevin Date: Sun, 4 Oct 2020 17:10:34 -0700 Subject: [PATCH 20/61] fix(docs): Reorganized section in Windows setup --- docs/docs/dev-setup.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/docs/dev-setup.md b/docs/docs/dev-setup.md index 2e232f89..4891f5af 100644 --- a/docs/docs/dev-setup.md +++ b/docs/docs/dev-setup.md @@ -210,11 +210,12 @@ In `cmd.exe` as **Administrator**: pip3 install -U west ``` -Once `west` is installed, close Command Prompt and open a new session as a **user** for the remainder of the instructions. :::note **For Windows, do not use the `--user` argument** that Linux uses otherwise `west` will be installed in a different location and the below instructions for adding Python `pip` will no longer apply. ::: +Once `west` is installed, close Command Prompt and open a new session as a **user** for the remainder of the instructions. + From bbf5a5905a973d6d23457d2e7bf15bf6bac234c3 Mon Sep 17 00:00:00 2001 From: Pete Johanson Date: Sun, 4 Oct 2020 18:18:44 -0400 Subject: [PATCH 21/61] refactor(usb): Report USB status w/o HID output. --- app/CMakeLists.txt | 2 +- app/Kconfig | 6 +++++- app/include/zmk/{usb_hid.h => usb.h} | 6 +++--- app/src/endpoints.c | 2 +- app/src/{usb_hid.c => usb.c} | 19 +++++++++++++------ 5 files changed, 23 insertions(+), 12 deletions(-) rename app/include/zmk/{usb_hid.h => usb.h} (73%) rename app/src/{usb_hid.c => usb.c} (77%) diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 3e0560b7..5c77c54f 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -54,7 +54,7 @@ target_sources_ifdef(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL app PRIVATE src/split/ target_sources_ifdef(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL app PRIVATE src/split/bluetooth/central.c) target_sources_ifdef(CONFIG_ZMK_KSCAN_MOCK_DRIVER app PRIVATE src/kscan_mock.c) target_sources_ifdef(CONFIG_ZMK_KSCAN_COMPOSITE_DRIVER app PRIVATE src/kscan_composite.c) -target_sources_ifdef(CONFIG_ZMK_USB app PRIVATE src/usb_hid.c) +target_sources_ifdef(CONFIG_USB app PRIVATE src/usb.c) target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/hog.c) target_sources_ifdef(CONFIG_ZMK_RGB_UNDERGLOW app PRIVATE src/rgb_underglow.c) target_sources(app PRIVATE src/endpoints.c) diff --git a/app/Kconfig b/app/Kconfig index ccd40da5..9398fce1 100644 --- a/app/Kconfig +++ b/app/Kconfig @@ -21,12 +21,16 @@ menuconfig ZMK_USB select USB_DEVICE_STACK select USB_DEVICE_HID -if ZMK_USB +if USB config ZMK_USB_INIT_PRIORITY int "Init Priority" default 50 +endif + +if ZMK_USB + config USB_NUMOF_EP_WRITE_RETRIES default 10 diff --git a/app/include/zmk/usb_hid.h b/app/include/zmk/usb.h similarity index 73% rename from app/include/zmk/usb_hid.h rename to app/include/zmk/usb.h index 83a45407..452fd54d 100644 --- a/app/include/zmk/usb_hid.h +++ b/app/include/zmk/usb.h @@ -12,8 +12,8 @@ #include #include -int zmk_usb_hid_init(); - -enum usb_dc_status_code zmk_usb_hid_get_status(); +enum usb_dc_status_code zmk_usb_get_status(); +#ifdef CONFIG_ZMK_USB int zmk_usb_hid_send_report(u8_t *report, size_t len); +#endif /* CONFIG_ZMK_USB */ \ No newline at end of file diff --git a/app/src/endpoints.c b/app/src/endpoints.c index ae785870..79d294ef 100644 --- a/app/src/endpoints.c +++ b/app/src/endpoints.c @@ -6,7 +6,7 @@ #include #include -#include +#include #include #include diff --git a/app/src/usb_hid.c b/app/src/usb.c similarity index 77% rename from app/src/usb_hid.c rename to app/src/usb.c index 64addaea..434b3d4d 100644 --- a/app/src/usb_hid.c +++ b/app/src/usb.c @@ -18,6 +18,8 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); static enum usb_dc_status_code usb_status = USB_DC_UNKNOWN; +#ifdef CONFIG_ZMK_USB + static struct device *hid_dev; static K_SEM_DEFINE(hid_sem, 1, 1); @@ -28,8 +30,6 @@ static const struct hid_ops ops = { .int_in_ready = in_ready_cb, }; -enum usb_dc_status_code zmk_usb_hid_get_status() { return usb_status; } - int zmk_usb_hid_send_report(const u8_t *report, size_t len) { switch (usb_status) { case USB_DC_SUSPEND: @@ -51,11 +51,16 @@ int zmk_usb_hid_send_report(const u8_t *report, size_t len) { } } -void usb_hid_status_cb(enum usb_dc_status_code status, const u8_t *params) { usb_status = status; }; +#endif /* CONFIG_ZMK_USB */ + +enum usb_dc_status_code zmk_usb_get_status() { return usb_status; } -static int zmk_usb_hid_init(struct device *_arg) { +void usb_status_cb(enum usb_dc_status_code status, const u8_t *params) { usb_status = status; }; + +static int zmk_usb_init(struct device *_arg) { int usb_enable_ret; +#ifdef CONFIG_ZMK_USB hid_dev = device_get_binding("HID_0"); if (hid_dev == NULL) { LOG_ERR("Unable to locate HID device"); @@ -66,7 +71,9 @@ static int zmk_usb_hid_init(struct device *_arg) { usb_hid_init(hid_dev); - usb_enable_ret = usb_enable(usb_hid_status_cb); +#endif /* CONFIG_ZMK_USB */ + + usb_enable_ret = usb_enable(usb_status_cb); if (usb_enable_ret != 0) { LOG_ERR("Unable to enable USB"); @@ -76,4 +83,4 @@ static int zmk_usb_hid_init(struct device *_arg) { return 0; } -SYS_INIT(zmk_usb_hid_init, APPLICATION, CONFIG_ZMK_USB_INIT_PRIORITY); +SYS_INIT(zmk_usb_init, APPLICATION, CONFIG_ZMK_USB_INIT_PRIORITY); From 9be566603e2eb248fbaa7af65cba42d5c06dbd33 Mon Sep 17 00:00:00 2001 From: Pete Johanson Date: Thu, 6 Aug 2020 09:30:31 -0400 Subject: [PATCH 22/61] feat(kscan): Use PORT events for kscan matrix interrupts * Lower power usage compared to regular interrupts on nrf52. --- app/boards/arm/nice_nano/nice_nano.dts | 4 ++++ app/drivers/zephyr/kscan_gpio_matrix.c | 16 ++++++++++------ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/app/boards/arm/nice_nano/nice_nano.dts b/app/boards/arm/nice_nano/nice_nano.dts index 2e9556b8..3ffb0ea8 100644 --- a/app/boards/arm/nice_nano/nice_nano.dts +++ b/app/boards/arm/nice_nano/nice_nano.dts @@ -31,6 +31,10 @@ }; +&gpiote { + status = "okay"; +}; + &gpio0 { status = "okay"; }; diff --git a/app/drivers/zephyr/kscan_gpio_matrix.c b/app/drivers/zephyr/kscan_gpio_matrix.c index 62008e32..cd793243 100644 --- a/app/drivers/zephyr/kscan_gpio_matrix.c +++ b/app/drivers/zephyr/kscan_gpio_matrix.c @@ -64,6 +64,7 @@ static int kscan_gpio_config_interrupts(struct device **devices, struct kscan_gpio_irq_callback_##n { \ struct COND_CODE_0(DT_INST_PROP(n, debounce_period), (k_work), (k_delayed_work)) * work; \ struct gpio_callback callback; \ + struct device *dev; \ }; \ static struct kscan_gpio_irq_callback_##n irq_callbacks_##n[INST_INPUT_LEN(n)]; \ struct kscan_gpio_config_##n { \ @@ -105,7 +106,7 @@ static int kscan_gpio_config_interrupts(struct device **devices, static int kscan_gpio_enable_interrupts_##n(struct device *dev) { \ return kscan_gpio_config_interrupts( \ kscan_gpio_input_devices_##n(dev), kscan_gpio_input_configs_##n(dev), \ - INST_INPUT_LEN(n), GPIO_INT_DEBOUNCE | GPIO_INT_EDGE_BOTH); \ + INST_INPUT_LEN(n), GPIO_INT_LEVEL_ACTIVE); \ } static int kscan_gpio_disable_interrupts_##n(struct device *dev) { \ return kscan_gpio_config_interrupts(kscan_gpio_input_devices_##n(dev), \ kscan_gpio_input_configs_##n(dev), \ @@ -113,10 +114,13 @@ static int kscan_gpio_config_interrupts(struct device **devices, }), \ ()) \ static void kscan_gpio_set_output_state_##n(struct device *dev, int value) { \ + int err; \ for (int i = 0; i < INST_OUTPUT_LEN(n); i++) { \ struct device *in_dev = kscan_gpio_output_devices_##n(dev)[i]; \ const struct kscan_gpio_item_config *cfg = &kscan_gpio_output_configs_##n(dev)[i]; \ - gpio_pin_set(in_dev, cfg->pin, value); \ + if ((err = gpio_pin_set(in_dev, cfg->pin, value))) { \ + LOG_DBG("FAILED TO SET OUTPUT %d to %d", cfg->pin, err); \ + } \ } \ } \ static void kscan_gpio_set_matrix_state_##n( \ @@ -134,8 +138,6 @@ static int kscan_gpio_config_interrupts(struct device **devices, /* Disable our interrupts temporarily while we scan, to avoid */ \ /* re-entry while we iterate columns and set them active one by one */ \ /* to get pressed state for each matrix cell. */ \ - COND_CODE_0(CONFIG_ZMK_KSCAN_MATRIX_POLLING, (kscan_gpio_disable_interrupts_##n(dev);), \ - ()) \ kscan_gpio_set_output_state_##n(dev, 0); \ for (int o = 0; o < INST_OUTPUT_LEN(n); o++) { \ struct device *out_dev = kscan_gpio_output_devices_##n(dev)[o]; \ @@ -152,8 +154,6 @@ static int kscan_gpio_config_interrupts(struct device **devices, } \ /* Set all our outputs as active again. */ \ kscan_gpio_set_output_state_##n(dev, 1); \ - /*Re-enable interrupts so that they can be triggered again for future press/release*/ \ - COND_CODE_0(CONFIG_ZMK_KSCAN_MATRIX_POLLING, (kscan_gpio_enable_interrupts_##n(dev);), ()) \ for (int r = 0; r < INST_MATRIX_ROWS(n); r++) { \ for (int c = 0; c < INST_MATRIX_COLS(n); c++) { \ bool pressed = read_state[r][c]; \ @@ -172,6 +172,8 @@ static int kscan_gpio_config_interrupts(struct device **devices, k_delayed_work_cancel(&data->work); \ k_delayed_work_submit(&data->work, K_MSEC(5)); \ })) \ + } else { \ + kscan_gpio_enable_interrupts_##n(dev); \ } \ return 0; \ } \ @@ -183,6 +185,7 @@ static int kscan_gpio_config_interrupts(struct device **devices, gpio_port_pins_t pin) { \ struct kscan_gpio_irq_callback_##n *data = \ CONTAINER_OF(cb, struct kscan_gpio_irq_callback_##n, callback); \ + kscan_gpio_disable_interrupts_##n(data->dev); \ COND_CODE_0(DT_INST_PROP(n, debounce_period), ({ k_work_submit(data->work); }), ({ \ k_delayed_work_cancel(data->work); \ k_delayed_work_submit(data->work, \ @@ -238,6 +241,7 @@ static int kscan_gpio_config_interrupts(struct device **devices, LOG_DBG("Configured pin %d on %s for input", in_cfg->pin, in_cfg->label); \ } \ irq_callbacks_##n[i].work = &data->work; \ + irq_callbacks_##n[i].dev = dev; \ gpio_init_callback(&irq_callbacks_##n[i].callback, \ kscan_gpio_irq_callback_handler_##n, BIT(in_cfg->pin)); \ err = gpio_add_callback(input_devices[i], &irq_callbacks_##n[i].callback); \ From c54decd1443a41bd68905256db6286d51324c8e4 Mon Sep 17 00:00:00 2001 From: Mega Mind <68985133+megamind4089@users.noreply.github.com> Date: Thu, 1 Oct 2020 23:57:16 +0800 Subject: [PATCH 23/61] Added Makerdiary M.2 module --- app/boards/arm/nrf52840_m2/CMakeLists.txt | 13 +++ app/boards/arm/nrf52840_m2/Kconfig | 10 ++ app/boards/arm/nrf52840_m2/Kconfig.board | 10 ++ app/boards/arm/nrf52840_m2/Kconfig.defconfig | 30 ++++++ app/boards/arm/nrf52840_m2/board.cmake | 9 ++ app/boards/arm/nrf52840_m2/nrf52840_m2.dts | 97 +++++++++++++++++++ app/boards/arm/nrf52840_m2/nrf52840_m2.yaml | 15 +++ .../arm/nrf52840_m2/nrf52840_m2_defconfig | 23 +++++ 8 files changed, 207 insertions(+) create mode 100644 app/boards/arm/nrf52840_m2/CMakeLists.txt create mode 100644 app/boards/arm/nrf52840_m2/Kconfig create mode 100644 app/boards/arm/nrf52840_m2/Kconfig.board create mode 100644 app/boards/arm/nrf52840_m2/Kconfig.defconfig create mode 100644 app/boards/arm/nrf52840_m2/board.cmake create mode 100644 app/boards/arm/nrf52840_m2/nrf52840_m2.dts create mode 100644 app/boards/arm/nrf52840_m2/nrf52840_m2.yaml create mode 100644 app/boards/arm/nrf52840_m2/nrf52840_m2_defconfig diff --git a/app/boards/arm/nrf52840_m2/CMakeLists.txt b/app/boards/arm/nrf52840_m2/CMakeLists.txt new file mode 100644 index 00000000..84b2ab99 --- /dev/null +++ b/app/boards/arm/nrf52840_m2/CMakeLists.txt @@ -0,0 +1,13 @@ +# +# Copyright (c) 2020 The ZMK Contributors +# SPDX-License-Identifier: MIT +# + +set_property(GLOBAL APPEND PROPERTY extra_post_build_commands + COMMAND ${PYTHON_EXECUTABLE} ${ZEPHYR_BASE}/../tools/uf2/utils/uf2conv.py + -c + -b 0x26000 + -f 0xADA52840 + -o ${PROJECT_BINARY_DIR}/${CONFIG_KERNEL_BIN_NAME}.uf2 + ${PROJECT_BINARY_DIR}/${CONFIG_KERNEL_BIN_NAME}.bin +) diff --git a/app/boards/arm/nrf52840_m2/Kconfig b/app/boards/arm/nrf52840_m2/Kconfig new file mode 100644 index 00000000..faff4925 --- /dev/null +++ b/app/boards/arm/nrf52840_m2/Kconfig @@ -0,0 +1,10 @@ +# +# Copyright (c) 2020 The ZMK Contributors +# SPDX-License-Identifier: MIT +# + +config BOARD_ENABLE_DCDC + bool "Enable DCDC mode" + select SOC_DCDC_NRF52X + default y + depends on BOARD_NRF52840_M2 diff --git a/app/boards/arm/nrf52840_m2/Kconfig.board b/app/boards/arm/nrf52840_m2/Kconfig.board new file mode 100644 index 00000000..6ade68c1 --- /dev/null +++ b/app/boards/arm/nrf52840_m2/Kconfig.board @@ -0,0 +1,10 @@ +# Maker Diary nrf52840 M.2 board configuration +# +# Copyright (c) 2020 The ZMK Contributors +# SPDX-License-Identifier: MIT +# + +config BOARD_NRF52840_M2 + bool "nrf52480_m2" + depends on SOC_NRF52840_QIAA + diff --git a/app/boards/arm/nrf52840_m2/Kconfig.defconfig b/app/boards/arm/nrf52840_m2/Kconfig.defconfig new file mode 100644 index 00000000..98fcd083 --- /dev/null +++ b/app/boards/arm/nrf52840_m2/Kconfig.defconfig @@ -0,0 +1,30 @@ +# +# Copyright (c) 2020 The ZMK Contributors +# SPDX-License-Identifier: MIT +# + +if BOARD_NRF52840_M2 + +config BOARD + default "nrf52480_m2" + +if USB + +config USB_NRFX + default y + +config USB_DEVICE_STACK + default y + +endif # USB + +config BT_CTLR + default BT + +config ZMK_BLE + default y + +config ZMK_USB + default y + +endif # BOARD_NRF52840_M2 diff --git a/app/boards/arm/nrf52840_m2/board.cmake b/app/boards/arm/nrf52840_m2/board.cmake new file mode 100644 index 00000000..f521e2c0 --- /dev/null +++ b/app/boards/arm/nrf52840_m2/board.cmake @@ -0,0 +1,9 @@ +# +# Copyright (c) 2020 The ZMK Contributors +# SPDX-License-Identifier: MIT +# + +board_runner_args(nrfjprog "--nrf-family=NRF52" "--softreset") + +include(${ZEPHYR_BASE}/boards/common/blackmagicprobe.board.cmake) +include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake) diff --git a/app/boards/arm/nrf52840_m2/nrf52840_m2.dts b/app/boards/arm/nrf52840_m2/nrf52840_m2.dts new file mode 100644 index 00000000..fb5b0ff6 --- /dev/null +++ b/app/boards/arm/nrf52840_m2/nrf52840_m2.dts @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * SPDX-License-Identifier: MIT + */ + +/dts-v1/; +#include + +/ { + model = "Makerdiary nRF52840 M.2 module"; + compatible = "makerdiary,nrf52840_m2"; + + chosen { + zephyr,code-partition = &code_partition; + //zephyr,console = &uart0; + //zephyr,bt-mon-uart = &uart0; + //zephyr,bt-c2h-uart = &uart0; + zephyr,sram = &sram0; + zephyr,flash = &flash0; + }; + + leds { + compatible = "gpio-leds"; + red_led: led_0 { + gpios = <&gpio0 30 GPIO_ACTIVE_HIGH>; + label = "Red LED"; + }; + green_led: led_1 { + gpios = <&gpio0 29 GPIO_ACTIVE_HIGH>; + label = "Green LED"; + }; + blue_led: led_2 { + gpios = <&gpio0 31 GPIO_ACTIVE_HIGH>; + label = "Blue LED"; + }; + }; + +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; + +&uart0 { + compatible = "nordic,nrf-uart"; + status = "okay"; + current-speed = <115200>; + tx-pin = <16>; + rx-pin = <15>; + rts-pin = <14>; + cts-pin = <13>; +}; + +&usbd { + compatible = "nordic,nrf-usbd"; + status = "okay"; +}; + + +&flash0 { + /* + * For more information, see: + * http://docs.zephyrproject.org/latest/devices/dts/flash_partitions.html + */ + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + boot_partition: partition@0 { + label = "adafruit_boot"; + reg = <0x000000000 0x0000C000>; + }; + code_partition: partition@26000 { + label = "code_partition"; + reg = <0x00026000 0x000d2000>; + }; + + /* + * The flash starting at 0x000f8000 and ending at + * 0x000fffff is reserved for use by the application. + */ + + /* + * Storage partition will be used by FCB/LittleFS/NVS + * if enabled. + */ + storage_partition: partition@f8000 { + label = "storage"; + reg = <0x000f8000 0x00008000>; + }; + }; +}; diff --git a/app/boards/arm/nrf52840_m2/nrf52840_m2.yaml b/app/boards/arm/nrf52840_m2/nrf52840_m2.yaml new file mode 100644 index 00000000..0a999bbf --- /dev/null +++ b/app/boards/arm/nrf52840_m2/nrf52840_m2.yaml @@ -0,0 +1,15 @@ +identifier: nrf52840_m2 +name: Makerdiary nRF52840 M.2 module +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb + - xtools +supported: + - adc + - usb_device + - ble + - ieee802154 + - pwm + - watchdog diff --git a/app/boards/arm/nrf52840_m2/nrf52840_m2_defconfig b/app/boards/arm/nrf52840_m2/nrf52840_m2_defconfig new file mode 100644 index 00000000..e74438b7 --- /dev/null +++ b/app/boards/arm/nrf52840_m2/nrf52840_m2_defconfig @@ -0,0 +1,23 @@ +# +# Copyright (c) 2020 The ZMK Contributors +# SPDX-License-Identifier: MIT +# + +CONFIG_SOC_SERIES_NRF52X=y +CONFIG_SOC_NRF52840_QIAA=y +CONFIG_BOARD_NRF52840_M2=y + +# Enable MPU +CONFIG_ARM_MPU=y + +# enable GPIO +CONFIG_GPIO=y + +CONFIG_USE_DT_CODE_PARTITION=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 From 9d06c730ba8b70429ecb67d3ff502ed1fde584bd Mon Sep 17 00:00:00 2001 From: Mega Mind <68985133+megamind4089@users.noreply.github.com> Date: Fri, 2 Oct 2020 00:18:30 +0800 Subject: [PATCH 24/61] Added Makerdiary M60 keyboard --- app/boards/shields/m60/Kconfig.defconfig | 10 ++++ app/boards/shields/m60/Kconfig.shield | 5 ++ app/boards/shields/m60/m60.conf | 0 app/boards/shields/m60/m60.keymap | 26 ++++++++++ app/boards/shields/m60/m60.overlay | 65 ++++++++++++++++++++++++ app/boards/shields/m60/readme.md | 15 ++++++ 6 files changed, 121 insertions(+) create mode 100644 app/boards/shields/m60/Kconfig.defconfig create mode 100644 app/boards/shields/m60/Kconfig.shield create mode 100644 app/boards/shields/m60/m60.conf create mode 100644 app/boards/shields/m60/m60.keymap create mode 100644 app/boards/shields/m60/m60.overlay create mode 100644 app/boards/shields/m60/readme.md diff --git a/app/boards/shields/m60/Kconfig.defconfig b/app/boards/shields/m60/Kconfig.defconfig new file mode 100644 index 00000000..e358a587 --- /dev/null +++ b/app/boards/shields/m60/Kconfig.defconfig @@ -0,0 +1,10 @@ + +if SHIELD_M60 + +config ZMK_KEYBOARD_NAME + default "m60" + +config ZMK_KSCAN_MATRIX_POLLING + default y + +endif diff --git a/app/boards/shields/m60/Kconfig.shield b/app/boards/shields/m60/Kconfig.shield new file mode 100644 index 00000000..4ed58c49 --- /dev/null +++ b/app/boards/shields/m60/Kconfig.shield @@ -0,0 +1,5 @@ +# Copyright (c) 2020 The ZMK Contributors +# SPDX-License-Identifier: MIT + +config SHIELD_M60 + def_bool $(shields_list_contains,m60) diff --git a/app/boards/shields/m60/m60.conf b/app/boards/shields/m60/m60.conf new file mode 100644 index 00000000..e69de29b diff --git a/app/boards/shields/m60/m60.keymap b/app/boards/shields/m60/m60.keymap new file mode 100644 index 00000000..aa0fa75e --- /dev/null +++ b/app/boards/shields/m60/m60.keymap @@ -0,0 +1,26 @@ +#include +#include +#include + +/ { + keymap0: keymap { + compatible = "zmk,keymap"; + + default_layer { +// ------------------------------------------------------------------------------------------ +// | ESC | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | - | = | BKSP | +// | 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 | MO(1) | WIN | CTRL | +// ------------------------------------------------------------------------------------------ + bindings = < + &kp ESC &kp NUM_1 &kp NUM_2 &kp NUM_3 &kp NUM_4 &kp NUM_5 &kp NUM_6 &kp NUM_7 &kp NUM_8 &kp NUM_9 &kp NUM_0 &kp MINUS &kp EQL &kp BKSP + &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 SCLN &kp QUOT &kp RET + &kp LSFT &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp CMMA &kp DOT &kp FSLH &kp RSFT + &kp LCTL &kp LGUI &kp LALT &kp SPC &kp RALT &mo 1 &kp RGUI &kp RCTL + >; + }; + }; +}; diff --git a/app/boards/shields/m60/m60.overlay b/app/boards/shields/m60/m60.overlay new file mode 100644 index 00000000..c20d4525 --- /dev/null +++ b/app/boards/shields/m60/m60.overlay @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ +#include + +/ { + chosen { + zmk,kscan = &kscan0; + zmk,matrix_transform = &default_transform; + }; + + kscan0: kscan { + compatible = "zmk,kscan-gpio-matrix"; + label = "KSCAN"; + + diode-direction = "col2row"; + row-gpios + = <&gpio0 5 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> + , <&gpio0 6 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> + , <&gpio0 7 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> + , <&gpio0 8 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> + , <&gpio1 9 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> + , <&gpio1 8 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> + , <&gpio0 12 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> + , <&gpio0 11 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> + ; + col-gpios + = <&gpio0 19 GPIO_ACTIVE_HIGH> + , <&gpio0 20 GPIO_ACTIVE_HIGH> + , <&gpio0 21 GPIO_ACTIVE_HIGH> + , <&gpio0 22 GPIO_ACTIVE_HIGH> + , <&gpio0 23 GPIO_ACTIVE_HIGH> + , <&gpio0 24 GPIO_ACTIVE_HIGH> + , <&gpio0 25 GPIO_ACTIVE_HIGH> + , <&gpio0 26 GPIO_ACTIVE_HIGH> + ; + }; + + default_transform: keymap_transform_0 { + 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 | MX24 | 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 | + 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(1,0) RC(1,1) RC(1,2) RC(1,3) RC(1,4) RC(1,5) +RC(3,3) RC(3,2) RC(3,1) RC(3,0) RC(2,7) RC(2,6) RC(2,5) RC(2,4) RC(2,3) RC(2,2) RC(2,1) RC(2,0) RC(1,7) RC(1,6) +RC(3,4) RC(3,5) RC(3,6) RC(3,7) 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(5,0) +RC(6,4) RC(6,3) RC(6,2) RC(6,1) RC(6,0) RC(5,7) RC(5,6) RC(5,5) RC(5,4) RC(5,3) RC(5,2) RC(5,1) +RC(6,5) RC(6,6) RC(6,7) RC(7,0) RC(7,1) RC(7,2) RC(7,3) RC(7,4) + >; + }; + + bt_unpair_combo: bt_unpair_combo { + compatible = "zmk,bt-unpair-combo"; + key-positions = <0 53>; + }; + +}; + diff --git a/app/boards/shields/m60/readme.md b/app/boards/shields/m60/readme.md new file mode 100644 index 00000000..7eaf226d --- /dev/null +++ b/app/boards/shields/m60/readme.md @@ -0,0 +1,15 @@ +# [Makerdiary M60](https://wiki.makerdiary.com/m60) + +A 60% ANSI keyboard designed and manufactured by Makerdiary. +http://makerdairy.com + +## Features + +- Per key RGB LED. +- Uses makerdiary M.2 nRF52840 module +- Matrix wiring + +## Hardware Notes + +https://wiki.makerdiary.com/m60/developer_guide/hardware/ + From e2299836bccf21bf56a4d34c5ed2f53a2fa21da2 Mon Sep 17 00:00:00 2001 From: Mega Mind <68985133+megamind4089@users.noreply.github.com> Date: Sat, 3 Oct 2020 17:35:17 +0800 Subject: [PATCH 25/61] Update contributors in all keymap files --- .../clueboard_california/clueboard_california.keymap | 6 ++++++ app/boards/shields/corne/corne.keymap | 6 ++++++ app/boards/shields/iris/iris.keymap | 2 +- app/boards/shields/kyria/kyria.keymap | 6 ++++++ app/boards/shields/lily58/lily58.keymap | 6 ++++++ app/boards/shields/m60/Kconfig.defconfig | 4 ++++ app/boards/shields/m60/Kconfig.shield | 2 ++ app/boards/shields/m60/m60.keymap | 6 ++++++ app/boards/shields/m60/m60.overlay | 1 + app/boards/shields/romac/romac.keymap | 2 +- app/boards/shields/sofle/sofle.keymap | 6 ++++++ app/boards/shields/splitreus62/splitreus62.keymap | 3 ++- 12 files changed, 47 insertions(+), 3 deletions(-) diff --git a/app/boards/shields/clueboard_california/clueboard_california.keymap b/app/boards/shields/clueboard_california/clueboard_california.keymap index 7a84b119..44a0b076 100644 --- a/app/boards/shields/clueboard_california/clueboard_california.keymap +++ b/app/boards/shields/clueboard_california/clueboard_california.keymap @@ -1,3 +1,9 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + #include #include diff --git a/app/boards/shields/corne/corne.keymap b/app/boards/shields/corne/corne.keymap index 5f0f15f0..64d4a001 100644 --- a/app/boards/shields/corne/corne.keymap +++ b/app/boards/shields/corne/corne.keymap @@ -1,3 +1,9 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + #include #include #include diff --git a/app/boards/shields/iris/iris.keymap b/app/boards/shields/iris/iris.keymap index 6042ad7b..8b06b1b7 100644 --- a/app/boards/shields/iris/iris.keymap +++ b/app/boards/shields/iris/iris.keymap @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Pete Johanson, Kurtis Lew + * Copyright (c) 2020 The ZMK Contributors * * SPDX-License-Identifier: MIT */ diff --git a/app/boards/shields/kyria/kyria.keymap b/app/boards/shields/kyria/kyria.keymap index f689ef62..ac0d13f0 100644 --- a/app/boards/shields/kyria/kyria.keymap +++ b/app/boards/shields/kyria/kyria.keymap @@ -1,3 +1,9 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + #include #include diff --git a/app/boards/shields/lily58/lily58.keymap b/app/boards/shields/lily58/lily58.keymap index 61c19f86..997a1248 100644 --- a/app/boards/shields/lily58/lily58.keymap +++ b/app/boards/shields/lily58/lily58.keymap @@ -1,3 +1,9 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + #include #include #include diff --git a/app/boards/shields/m60/Kconfig.defconfig b/app/boards/shields/m60/Kconfig.defconfig index e358a587..56695b96 100644 --- a/app/boards/shields/m60/Kconfig.defconfig +++ b/app/boards/shields/m60/Kconfig.defconfig @@ -1,3 +1,7 @@ +# +# Copyright (c) 2020 The ZMK Contributors +# SPDX-License-Identifier: MIT +# if SHIELD_M60 diff --git a/app/boards/shields/m60/Kconfig.shield b/app/boards/shields/m60/Kconfig.shield index 4ed58c49..47a28e24 100644 --- a/app/boards/shields/m60/Kconfig.shield +++ b/app/boards/shields/m60/Kconfig.shield @@ -1,5 +1,7 @@ +# # Copyright (c) 2020 The ZMK Contributors # SPDX-License-Identifier: MIT +# config SHIELD_M60 def_bool $(shields_list_contains,m60) diff --git a/app/boards/shields/m60/m60.keymap b/app/boards/shields/m60/m60.keymap index aa0fa75e..16ad2470 100644 --- a/app/boards/shields/m60/m60.keymap +++ b/app/boards/shields/m60/m60.keymap @@ -1,3 +1,9 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + #include #include #include diff --git a/app/boards/shields/m60/m60.overlay b/app/boards/shields/m60/m60.overlay index c20d4525..babae2db 100644 --- a/app/boards/shields/m60/m60.overlay +++ b/app/boards/shields/m60/m60.overlay @@ -3,6 +3,7 @@ * * SPDX-License-Identifier: MIT */ + #include / { diff --git a/app/boards/shields/romac/romac.keymap b/app/boards/shields/romac/romac.keymap index 97ea9c54..31e1ce82 100644 --- a/app/boards/shields/romac/romac.keymap +++ b/app/boards/shields/romac/romac.keymap @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Pete Johanson, Richard Jones + * Copyright (c) 2020 The ZMK Contributors * * SPDX-License-Identifier: MIT */ diff --git a/app/boards/shields/sofle/sofle.keymap b/app/boards/shields/sofle/sofle.keymap index 1cbe742c..e2ebc1aa 100644 --- a/app/boards/shields/sofle/sofle.keymap +++ b/app/boards/shields/sofle/sofle.keymap @@ -1,3 +1,9 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + #include #include #include diff --git a/app/boards/shields/splitreus62/splitreus62.keymap b/app/boards/shields/splitreus62/splitreus62.keymap index 920e61ad..07dd2ad6 100644 --- a/app/boards/shields/splitreus62/splitreus62.keymap +++ b/app/boards/shields/splitreus62/splitreus62.keymap @@ -1,9 +1,10 @@ /* - * Copyright (c) 2020 Derek Schmell + * Copyright (c) 2020 The ZMK Contributors * * SPDX-License-Identifier: MIT */ + #include #include From b8cb5f939a3c018af13de7727c15d7765ea1f1c1 Mon Sep 17 00:00:00 2001 From: Mega Mind <68985133+megamind4089@users.noreply.github.com> Date: Sat, 3 Oct 2020 18:21:22 +0800 Subject: [PATCH 26/61] M60 keymap update and misc changes * Updated M60 keymap * Make nrfjproj as default runner * Remove the polling config --- app/boards/arm/nrf52840_m2/board.cmake | 2 +- app/boards/shields/m60/Kconfig.defconfig | 3 --- app/boards/shields/m60/m60.keymap | 12 +++++++++++- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/app/boards/arm/nrf52840_m2/board.cmake b/app/boards/arm/nrf52840_m2/board.cmake index f521e2c0..55b44e27 100644 --- a/app/boards/arm/nrf52840_m2/board.cmake +++ b/app/boards/arm/nrf52840_m2/board.cmake @@ -5,5 +5,5 @@ board_runner_args(nrfjprog "--nrf-family=NRF52" "--softreset") -include(${ZEPHYR_BASE}/boards/common/blackmagicprobe.board.cmake) include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake) +include(${ZEPHYR_BASE}/boards/common/blackmagicprobe.board.cmake) diff --git a/app/boards/shields/m60/Kconfig.defconfig b/app/boards/shields/m60/Kconfig.defconfig index 56695b96..e31d5a53 100644 --- a/app/boards/shields/m60/Kconfig.defconfig +++ b/app/boards/shields/m60/Kconfig.defconfig @@ -8,7 +8,4 @@ if SHIELD_M60 config ZMK_KEYBOARD_NAME default "m60" -config ZMK_KSCAN_MATRIX_POLLING - default y - endif diff --git a/app/boards/shields/m60/m60.keymap b/app/boards/shields/m60/m60.keymap index 16ad2470..cbe356c2 100644 --- a/app/boards/shields/m60/m60.keymap +++ b/app/boards/shields/m60/m60.keymap @@ -15,7 +15,7 @@ default_layer { // ------------------------------------------------------------------------------------------ // | ESC | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | - | = | BKSP | -// | TAB | Q | W | E | R | T | Y | U | I | O | P | [ | ] | "|" | +// | 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 | MO(1) | WIN | CTRL | @@ -28,5 +28,15 @@ &kp LCTL &kp LGUI &kp LALT &kp SPC &kp RALT &mo 1 &kp RGUI &kp RCTL >; }; + + fn_layer { + bindings = < +&kp GRAV &kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12 &bootloader +&trans &bt BT_CLR &none &none &none &none &none &none &none &none &none &none &none &reset +&trans &bt BT_SEL 0 &bt BT_SEL 1 &bt BT_SEL 2 &bt BT_SEL 3 &bt BT_SEL 4 &kp LARW &kp DARW &kp UARW &kp RARW &none &none &trans +&trans &none &none &none &none &none &none &none &none &none &none &trans +&trans &trans &trans &trans &trans &trans &trans &trans + >; + }; }; }; From 4de7cc45de18f791ecbb361bfc2330a45e97d79e Mon Sep 17 00:00:00 2001 From: Pete Johanson Date: Mon, 5 Oct 2020 09:43:05 -0400 Subject: [PATCH 27/61] feat(setup): Add M.2 and M60 to setup scripts. --- docs/static/setup.ps1 | 10 +++++----- docs/static/setup.sh | 6 ++++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/docs/static/setup.ps1 b/docs/static/setup.ps1 index 3946e66c..dc7b18c9 100644 --- a/docs/static/setup.ps1 +++ b/docs/static/setup.ps1 @@ -63,8 +63,8 @@ $repo_path = "https://github.com/zmkfirmware/zmk-config-split-template.git" $title = "ZMK Config Setup:" $prompt = "Pick an MCU board" -$options = "nice!nano", "QMK Proton-C", "BlueMicro840 (v1)" -$boards = "nice_nano", "proton_c", "bluemicro840_v1" +$options = "nice!nano", "QMK Proton-C", "BlueMicro840 (v1)", "makerdiary nRF52840 M.2" +$boards = "nice_nano", "proton_c", "bluemicro840_v1", "nrf52840_m2" Write-Host "$title" Write-Host "" @@ -78,9 +78,9 @@ Write-Host "Keyboard Shield Selection:" $prompt = "Pick a keyboard" # TODO: Add support for "Other" and linking to docs on adding custom shields in user config repos. -$options = "Kyria", "Lily58", "Corne", "Splitreus62", "Sofle", "Iris", "RoMac" -$names = "kyria", "lily58", "corne", "splitreus62", "sofle", "iris", "romac" -$splits = "y", "y", "y", "y", "y", "y", "n" +$options = "Kyria", "Lily58", "Corne", "Splitreus62", "Sofle", "Iris", "RoMac", "makerdiary M60" +$names = "kyria", "lily58", "corne", "splitreus62", "sofle", "iris", "romac", "m60" +$splits = "y", "y", "y", "y", "y", "y", "n", "n" $choice = Get-Choice-From-Options -Options $options -Prompt $prompt $shield_title = $($options[$choice]) diff --git a/docs/static/setup.sh b/docs/static/setup.sh index 5bf36451..9e989644 100644 --- a/docs/static/setup.sh +++ b/docs/static/setup.sh @@ -26,7 +26,7 @@ repo_path="https://github.com/zmkfirmware/zmk-config-split-template.git" title="ZMK Config Setup:" prompt="Pick an MCU board:" -options=("nice!nano" "QMK Proton-C" "BlueMicro840 (v1)") +options=("nice!nano" "QMK Proton-C" "BlueMicro840 (v1)" "makerdiary nRF52840 M.2") echo "$title" echo "" @@ -39,6 +39,7 @@ select opt in "${options[@]}" "Quit"; do 1 ) board="nice_nano"; break;; 2 ) board="proton_c"; break;; 3 ) board="bluemicro840_v1"; break;; + 3 ) board="nrf52840_m2"; break;; $(( ${#options[@]}+1 )) ) echo "Goodbye!"; exit 1;; *) echo "Invalid option. Try another one."; continue;; @@ -50,7 +51,7 @@ echo "" echo "Keyboard Shield Selection:" prompt="Pick an keyboard:" -options=("Kyria" "Lily58" "Corne" "Splitreus62" "Sofle" "Iris" "RoMac") +options=("Kyria" "Lily58" "Corne" "Splitreus62" "Sofle" "Iris" "RoMac" "makerdiary M60") PS3="$prompt " # TODO: Add support for "Other" and linking to docs on adding custom shields in user config repos. @@ -66,6 +67,7 @@ select opt in "${options[@]}" "Quit"; do 5 ) shield_title="Sofle" shield="sofle"; split="y"; break;; 6 ) shield_title="Iris" shield="iris"; split="y"; break;; 7 ) shield_title="RoMac" shield="romac"; split="n"; break;; + 7 ) shield_title="M60" shield="m60"; split="n"; break;; # Add link to docs on adding your own custom shield in your ZMK config! # $(( ${#options[@]}+1 )) ) echo "Other!"; break;; From ce59223efe9062ac1da77bae93a3578ce0463b66 Mon Sep 17 00:00:00 2001 From: Pete Johanson Date: Mon, 5 Oct 2020 23:40:29 -0400 Subject: [PATCH 28/61] fix(shields): Typo in makerdiary URL. --- app/boards/shields/m60/readme.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/boards/shields/m60/readme.md b/app/boards/shields/m60/readme.md index 7eaf226d..e801c788 100644 --- a/app/boards/shields/m60/readme.md +++ b/app/boards/shields/m60/readme.md @@ -1,7 +1,7 @@ # [Makerdiary M60](https://wiki.makerdiary.com/m60) A 60% ANSI keyboard designed and manufactured by Makerdiary. -http://makerdairy.com +http://makerdiary.com ## Features @@ -12,4 +12,3 @@ http://makerdairy.com ## Hardware Notes https://wiki.makerdiary.com/m60/developer_guide/hardware/ - From a7496ab06425cab7de5fc7164b4ce5a34dd7107b Mon Sep 17 00:00:00 2001 From: Pete Johanson Date: Fri, 2 Oct 2020 02:09:38 -0400 Subject: [PATCH 29/61] feat(power): Initial deep sleep work. * New ZMK_SLEEP Kconfig symbol to enable the functionality. * Switch to PORT events that allows wake from deep sleep. * Initial basic power management policy, with idle ms, and ignoring deep sleep if we detect a USB connection. --- app/CMakeLists.txt | 1 + app/Kconfig | 20 +++++++- app/drivers/zephyr/kscan_gpio_matrix.c | 58 ++++++++++++---------- app/include/dt-bindings/zmk/bt.h | 2 +- app/src/power.c | 69 ++++++++++++++++++++++++++ 5 files changed, 121 insertions(+), 29 deletions(-) create mode 100644 app/src/power.c diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 5c77c54f..3e59d751 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -23,6 +23,7 @@ zephyr_linker_sources(RODATA include/linker/zmk-events.ld) # Add your source file to the "app" target. This must come after # find_package(Zephyr) which defines the target. target_include_directories(app PRIVATE include) +target_sources_ifdef(CONFIG_ZMK_SLEEP app PRIVATE src/power.c) target_sources(app PRIVATE src/kscan.c) target_sources(app PRIVATE src/matrix_transform.c) target_sources(app PRIVATE src/hid.c) diff --git a/app/Kconfig b/app/Kconfig index 9398fce1..edf58670 100644 --- a/app/Kconfig +++ b/app/Kconfig @@ -76,6 +76,25 @@ endif endmenu +menuconfig ZMK_SLEEP + bool "Enable deep sleep support" + imply USB + +if ZMK_SLEEP + +config SYS_POWER_DEEP_SLEEP_STATES + default y + +choice SYS_PM_POLICY + default SYS_PM_POLICY_APP +endchoice + +config ZMK_IDLE_SLEEP_TIMEOUT + int "Milliseconds to wait to sleep when going idle" + default 900000 + +endif + config ZMK_DISPLAY bool "ZMK display support" default n @@ -112,7 +131,6 @@ config ZMK_SPLIT_BLE_ROLE_CENTRAL config ZMK_SPLIT_BLE_ROLE_PERIPHERAL bool "Peripheral" - select BT_KEYS_OVERWRITE_OLDEST if ZMK_SPLIT_BLE_ROLE_PERIPHERAL diff --git a/app/drivers/zephyr/kscan_gpio_matrix.c b/app/drivers/zephyr/kscan_gpio_matrix.c index cd793243..a0b22e4a 100644 --- a/app/drivers/zephyr/kscan_gpio_matrix.c +++ b/app/drivers/zephyr/kscan_gpio_matrix.c @@ -73,7 +73,7 @@ static int kscan_gpio_config_interrupts(struct device **devices, }; \ struct kscan_gpio_data_##n { \ kscan_callback_t callback; \ - COND_CODE_0(CONFIG_ZMK_KSCAN_MATRIX_POLLING, (), (struct k_timer poll_timer;)) \ + COND_CODE_1(CONFIG_ZMK_KSCAN_MATRIX_POLLING, (struct k_timer poll_timer;), ()) \ struct COND_CODE_0(DT_INST_PROP(n, debounce_period), (k_work), (k_delayed_work)) work; \ bool matrix_state[INST_MATRIX_ROWS(n)][INST_MATRIX_COLS(n)]; \ struct device *rows[INST_MATRIX_ROWS(n)]; \ @@ -101,7 +101,7 @@ static int kscan_gpio_config_interrupts(struct device **devices, return ( \ COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (cfg->rows), (cfg->cols))); \ } \ - COND_CODE_0(CONFIG_ZMK_KSCAN_MATRIX_POLLING, \ + COND_CODE_1(CONFIG_ZMK_KSCAN_MATRIX_POLLING, (), \ ( \ static int kscan_gpio_enable_interrupts_##n(struct device *dev) { \ return kscan_gpio_config_interrupts( \ @@ -111,8 +111,7 @@ static int kscan_gpio_config_interrupts(struct device **devices, return kscan_gpio_config_interrupts(kscan_gpio_input_devices_##n(dev), \ kscan_gpio_input_configs_##n(dev), \ INST_INPUT_LEN(n), GPIO_INT_DISABLE); \ - }), \ - ()) \ + })) \ static void kscan_gpio_set_output_state_##n(struct device *dev, int value) { \ int err; \ for (int i = 0; i < INST_OUTPUT_LEN(n); i++) { \ @@ -173,7 +172,8 @@ static int kscan_gpio_config_interrupts(struct device **devices, k_delayed_work_submit(&data->work, K_MSEC(5)); \ })) \ } else { \ - kscan_gpio_enable_interrupts_##n(dev); \ + COND_CODE_1(CONFIG_ZMK_KSCAN_MATRIX_POLLING, (), \ + (kscan_gpio_enable_interrupts_##n(dev);)) \ } \ return 0; \ } \ @@ -181,17 +181,20 @@ static int kscan_gpio_config_interrupts(struct device **devices, struct kscan_gpio_data_##n *data = CONTAINER_OF(work, struct kscan_gpio_data_##n, work); \ kscan_gpio_read_##n(data->dev); \ } \ - static void kscan_gpio_irq_callback_handler_##n(struct device *dev, struct gpio_callback *cb, \ - gpio_port_pins_t pin) { \ - struct kscan_gpio_irq_callback_##n *data = \ - CONTAINER_OF(cb, struct kscan_gpio_irq_callback_##n, callback); \ - kscan_gpio_disable_interrupts_##n(data->dev); \ - COND_CODE_0(DT_INST_PROP(n, debounce_period), ({ k_work_submit(data->work); }), ({ \ - k_delayed_work_cancel(data->work); \ - k_delayed_work_submit(data->work, \ - K_MSEC(DT_INST_PROP(n, debounce_period))); \ - })) \ - } \ + COND_CODE_1(CONFIG_ZMK_KSCAN_MATRIX_POLLING, (), \ + (static void kscan_gpio_irq_callback_handler_##n( \ + struct device *dev, struct gpio_callback *cb, gpio_port_pins_t pin) { \ + struct kscan_gpio_irq_callback_##n *data = \ + CONTAINER_OF(cb, struct kscan_gpio_irq_callback_##n, callback); \ + kscan_gpio_disable_interrupts_##n(data->dev); \ + COND_CODE_0(DT_INST_PROP(n, debounce_period), \ + ({ k_work_submit(data->work); }), ({ \ + k_delayed_work_cancel(data->work); \ + k_delayed_work_submit( \ + data->work, K_MSEC(DT_INST_PROP(n, debounce_period))); \ + })) \ + })) \ + \ static struct kscan_gpio_data_##n kscan_gpio_data_##n = { \ .rows = {[INST_MATRIX_ROWS(n) - 1] = NULL}, .cols = {[INST_MATRIX_COLS(n) - 1] = NULL}}; \ static int kscan_gpio_configure_##n(struct device *dev, kscan_callback_t callback) { \ @@ -204,24 +207,25 @@ static int kscan_gpio_config_interrupts(struct device **devices, return 0; \ }; \ static int kscan_gpio_enable_##n(struct device *dev) { \ - COND_CODE_0(CONFIG_ZMK_KSCAN_MATRIX_POLLING, \ - (int err = kscan_gpio_enable_interrupts_##n(dev); \ - if (err) { return err; } return kscan_gpio_read_##n(dev);), \ + COND_CODE_1(CONFIG_ZMK_KSCAN_MATRIX_POLLING, \ (struct kscan_gpio_data_##n *data = dev->driver_data; \ - k_timer_start(&data->poll_timer, K_MSEC(10), K_MSEC(10)); return 0;)) \ + k_timer_start(&data->poll_timer, K_MSEC(10), K_MSEC(10)); return 0;), \ + (int err = kscan_gpio_enable_interrupts_##n(dev); \ + if (err) { return err; } return kscan_gpio_read_##n(dev);)) \ }; \ static int kscan_gpio_disable_##n(struct device *dev) { \ - COND_CODE_0(CONFIG_ZMK_KSCAN_MATRIX_POLLING, \ - (return kscan_gpio_disable_interrupts_##n(dev);), \ + COND_CODE_1(CONFIG_ZMK_KSCAN_MATRIX_POLLING, \ (struct kscan_gpio_data_##n *data = dev->driver_data; \ - k_timer_stop(&data->poll_timer); return 0;)) \ + k_timer_stop(&data->poll_timer); return 0;), \ + (return kscan_gpio_disable_interrupts_##n(dev);)) \ }; \ - COND_CODE_0(CONFIG_ZMK_KSCAN_MATRIX_POLLING, (), \ + COND_CODE_1(CONFIG_ZMK_KSCAN_MATRIX_POLLING, \ (static void kscan_gpio_timer_handler(struct k_timer *timer) { \ struct kscan_gpio_data_##n *data = \ CONTAINER_OF(timer, struct kscan_gpio_data_##n, poll_timer); \ k_work_submit(&data->work.work); \ - })) \ + }), \ + ()) \ static int kscan_gpio_init_##n(struct device *dev) { \ struct kscan_gpio_data_##n *data = dev->driver_data; \ int err; \ @@ -267,8 +271,8 @@ static int kscan_gpio_config_interrupts(struct device **devices, } \ } \ data->dev = dev; \ - COND_CODE_0(CONFIG_ZMK_KSCAN_MATRIX_POLLING, (), \ - (k_timer_init(&data->poll_timer, kscan_gpio_timer_handler, NULL);)) \ + COND_CODE_1(CONFIG_ZMK_KSCAN_MATRIX_POLLING, \ + (k_timer_init(&data->poll_timer, kscan_gpio_timer_handler, NULL);), ()) \ (COND_CODE_0(DT_INST_PROP(n, debounce_period), (k_work_init), (k_delayed_work_init)))( \ &data->work, kscan_gpio_work_handler_##n); \ return 0; \ diff --git a/app/include/dt-bindings/zmk/bt.h b/app/include/dt-bindings/zmk/bt.h index 05fd65c8..a403d35d 100644 --- a/app/include/dt-bindings/zmk/bt.h +++ b/app/include/dt-bindings/zmk/bt.h @@ -18,4 +18,4 @@ defines these aliases up front. #define BT_CLR BT_CLR_CMD 0 #define BT_NXT BT_NXT_CMD 0 #define BT_PRV BT_PRV_CMD 0 -#define BT_SEL BT_SEL_CMD \ No newline at end of file +#define BT_SEL BT_SEL_CMD diff --git a/app/src/power.c b/app/src/power.c new file mode 100644 index 00000000..73b3f123 --- /dev/null +++ b/app/src/power.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include +#include +#include + +#include + +LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); + +#include +#include +#include +#include + +static u32_t power_last_uptime; + +#define MAX_IDLE_MS CONFIG_ZMK_IDLE_SLEEP_TIMEOUT + +bool is_usb_power_present() { +#ifdef CONFIG_USB + enum usb_dc_status_code usb_status = zmk_usb_get_status(); + switch (usb_status) { + case USB_DC_DISCONNECTED: + case USB_DC_UNKNOWN: + return false; + default: + return true; + } +#else + return false; +#endif /* CONFIG_USB */ +} + +enum power_states sys_pm_policy_next_state(s32_t ticks) { +#ifdef CONFIG_SYS_POWER_DEEP_SLEEP_STATES +#ifdef CONFIG_HAS_SYS_POWER_STATE_DEEP_SLEEP_1 + s32_t current = k_uptime_get(); + if (power_last_uptime > 0 && !is_usb_power_present() && + current - power_last_uptime > MAX_IDLE_MS) { + return SYS_POWER_STATE_DEEP_SLEEP_1; + } +#endif /* CONFIG_HAS_SYS_POWER_STATE_DEEP_SLEEP_1 */ +#endif /* CONFIG_SYS_POWER_DEEP_SLEEP_STATES */ + + return SYS_POWER_STATE_ACTIVE; +} + +int power_event_listener(const struct zmk_event_header *eh) { + power_last_uptime = k_uptime_get(); + + return 0; +} + +int power_init() { + power_last_uptime = k_uptime_get(); + + return 0; +} + +ZMK_LISTENER(power, power_event_listener); +ZMK_SUBSCRIPTION(power, position_state_changed); +ZMK_SUBSCRIPTION(power, sensor_event); + +SYS_INIT(power_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY); \ No newline at end of file From 2300ce306afadebd5f1987acf8ded6ac228f68e8 Mon Sep 17 00:00:00 2001 From: Ben Huddleston <40238853+BenHuddleston@users.noreply.github.com> Date: Wed, 7 Oct 2020 22:25:21 +0100 Subject: [PATCH 30/61] Correct typo in previous profile behaviour binding in bluetooth.md --- docs/docs/behavior/bluetooth.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/behavior/bluetooth.md b/docs/docs/behavior/bluetooth.md index f802a9a2..8bde71bf 100644 --- a/docs/docs/behavior/bluetooth.md +++ b/docs/docs/behavior/bluetooth.md @@ -66,7 +66,7 @@ The bluetooth behavior completes an bluetooth action given on press. 1. Behavior binding to select the previous profile: ``` - &bt BT_NXT + &bt BT_PRV ``` 1. Behavior binding to select the 2nd profile (passed parameters are [zero based](https://en.wikipedia.org/wiki/Zero-based_numbering)): From f3eaa7e4247321042618a732596f842e5bb104da Mon Sep 17 00:00:00 2001 From: Kellen Carey Date: Wed, 7 Oct 2020 20:40:04 -0700 Subject: [PATCH 31/61] working shield, need to improve default keymap --- app/boards/shields/microdox/Kconfig.defconfig | 58 +++++++++++++++ app/boards/shields/microdox/Kconfig.shield | 9 +++ .../shields/microdox/boards/nice_nano.overlay | 29 ++++++++ app/boards/shields/microdox/microdox.conf | 6 ++ app/boards/shields/microdox/microdox.dtsi | 71 +++++++++++++++++++ app/boards/shields/microdox/microdox.keymap | 57 +++++++++++++++ .../shields/microdox/microdox_left.conf | 2 + .../shields/microdox/microdox_left.overlay | 22 ++++++ .../shields/microdox/microdox_right.conf | 2 + .../shields/microdox/microdox_right.overlay | 26 +++++++ 10 files changed, 282 insertions(+) create mode 100644 app/boards/shields/microdox/Kconfig.defconfig create mode 100644 app/boards/shields/microdox/Kconfig.shield create mode 100644 app/boards/shields/microdox/boards/nice_nano.overlay create mode 100644 app/boards/shields/microdox/microdox.conf create mode 100644 app/boards/shields/microdox/microdox.dtsi create mode 100644 app/boards/shields/microdox/microdox.keymap create mode 100644 app/boards/shields/microdox/microdox_left.conf create mode 100644 app/boards/shields/microdox/microdox_left.overlay create mode 100644 app/boards/shields/microdox/microdox_right.conf create mode 100644 app/boards/shields/microdox/microdox_right.overlay diff --git a/app/boards/shields/microdox/Kconfig.defconfig b/app/boards/shields/microdox/Kconfig.defconfig new file mode 100644 index 00000000..218443f9 --- /dev/null +++ b/app/boards/shields/microdox/Kconfig.defconfig @@ -0,0 +1,58 @@ + +if SHIELD_MICRODOX_LEFT + +config ZMK_KEYBOARD_NAME + default "Microdox Left" + +endif + + +if SHIELD_MICRODOX_RIGHT + +config ZMK_KEYBOARD_NAME + default "Microdox Right" + +endif + +if SHIELD_MICRODOX_LEFT || SHIELD_MICRODOX_RIGHT + +config ZMK_SPLIT + default y + +if ZMK_DISPLAY + +config I2C + default y + +config SSD1306 + default y + +config SSD1306_REVERSE_MODE + default y + +endif # ZMK_DISPLAY + +if LVGL + +config LVGL_HOR_RES + default 128 + +config LVGL_VER_RES + default 32 + +config LVGL_VDB_SIZE + default 64 + +config LVGL_DPI + default 148 + +config LVGL_BITS_PER_PIXEL + default 1 + +choice LVGL_COLOR_DEPTH + default LVGL_COLOR_DEPTH_1 +endchoice + +endif # LVGL + +endif diff --git a/app/boards/shields/microdox/Kconfig.shield b/app/boards/shields/microdox/Kconfig.shield new file mode 100644 index 00000000..7d7148de --- /dev/null +++ b/app/boards/shields/microdox/Kconfig.shield @@ -0,0 +1,9 @@ +# Copyright (c) 2020 Pete Johanson +# Copyright (c) 2020 Kellen Carey +# SPDX-License-Identifier: MIT + +config SHIELD_MICRODOX_LEFT + def_bool $(shields_list_contains,microdox_left) + +config SHIELD_MICRODOX_RIGHT + def_bool $(shields_list_contains,microdox_right) diff --git a/app/boards/shields/microdox/boards/nice_nano.overlay b/app/boards/shields/microdox/boards/nice_nano.overlay new file mode 100644 index 00000000..c7c3eb8e --- /dev/null +++ b/app/boards/shields/microdox/boards/nice_nano.overlay @@ -0,0 +1,29 @@ +&spi1 { + compatible = "nordic,nrf-spi"; + /* Cannot be used together with i2c0. */ + status = "okay"; + mosi-pin = <6>; + // Unused pins, needed for SPI definition, but not used by the ws2812 driver itself. + sck-pin = <5>; + miso-pin = <7>; + + led_strip: ws2812@0 { + compatible = "worldsemi,ws2812-spi"; + label = "SK6812mini"; + + /* SPI */ + reg = <0>; /* ignored, but necessary for SPI bindings */ + spi-max-frequency = <4000000>; + + /* WS2812 */ + chain-length = <6>; /* There are per-key RGB, but the first 6 are underglow */ + spi-one-frame = <0x70>; + spi-zero-frame = <0x40>; + }; +}; + +/ { + chosen { + zmk,underglow = &led_strip; + }; +}; diff --git a/app/boards/shields/microdox/microdox.conf b/app/boards/shields/microdox/microdox.conf new file mode 100644 index 00000000..b79385bd --- /dev/null +++ b/app/boards/shields/microdox/microdox.conf @@ -0,0 +1,6 @@ +# Uncomment the following lines to enable the Corne RGB Underglow +# ZMK_RGB_UNDERGLOW=y +# CONFIG_WS2812_STRIP=y + +# Uncomment the following line to enable the Corne OLED Display +# CONFIG_ZMK_DISPLAY=y diff --git a/app/boards/shields/microdox/microdox.dtsi b/app/boards/shields/microdox/microdox.dtsi new file mode 100644 index 00000000..bf7950df --- /dev/null +++ b/app/boards/shields/microdox/microdox.dtsi @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2020 Pete Johanson + * Copyright (c) 2020 Kellen Carey + * + * SPDX-License-Identifier: MIT + */ + +#include + +/ { + chosen { + zmk,kscan = &kscan0; + zmk,matrix_transform = &default_transform; + }; + + default_transform: keymap_transform_0 { + compatible = "zmk,matrix-transform"; + columns = <10>; + rows = <4>; +// | SW1 | SW2 | SW3 | SW4 | SW5 | | SW5 | SW4 | SW3 | SW2 | SW1 | +// | SW6 | SW7 | SW8 | SW9 | SW10 | | SW10 | SW9 | SW8 | SW7 | SW6 | +// | SW11 | SW12 | SW13 | SW14 | SW15 | | SW15 | SW14 | SW13 | SW12 | SW11 | +// | SW16 | SW17 | SW18 | | SW18 | SW17 | SW16 | + map = < +RC(0,0) RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(0,5) RC(0,6) RC(0,7) RC(0,8) RC(0,9) +RC(1,0) RC(1,1) RC(1,2) RC(1,3) RC(1,4) RC(1,5) RC(1,6) RC(1,7) RC(1,8) RC(1,9) +RC(2,0) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(2,5) RC(2,6) RC(2,7) RC(2,8) RC(2,9) + RC(3,2) RC(3,3) RC(3,4) RC(3,5) RC(3,6) RC(3,7) + >; + }; + + kscan0: kscan { + compatible = "zmk,kscan-gpio-matrix"; + label = "KSCAN"; + + diode-direction = "col2row"; + row-gpios + = <&pro_micro_d 16 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> + , <&pro_micro_d 10 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> + , <&pro_micro_d 8 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> + , <&pro_micro_d 9 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> + ; + + }; + + bt_unpair_combo: bt_unpair_combo { + compatible = "zmk,bt-unpair-combo"; + }; + + // TODO: per-key RGB node(s)? +}; + +&pro_micro_i2c { + status = "okay"; + + oled: ssd1306@3c { + compatible = "solomon,ssd1306fb"; + reg = <0x3c>; + label = "DISPLAY"; + width = <128>; + height = <32>; + segment-offset = <0>; + page-offset = <0>; + display-offset = <0>; + multiplex-ratio = <31>; + segment-remap; + com-invdir; + com-sequential; + prechargep = <0x22>; + }; +}; diff --git a/app/boards/shields/microdox/microdox.keymap b/app/boards/shields/microdox/microdox.keymap new file mode 100644 index 00000000..fa43a637 --- /dev/null +++ b/app/boards/shields/microdox/microdox.keymap @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include +#include +#include + +/ { + keymap { + compatible = "zmk,keymap"; + + default_layer { +// ----------------------------------------------------------------------------------------- +// | TAB | Q | W | E | R | T | | Y | U | I | O | P | BKSP | +// | CTRL | A | S | D | F | G | | H | J | K | L | ; | ' | +// | SHFT | Z | X | C | V | B | | N | M | , | . | / | SHFT | +// | GUI | LWR | SPC | | ENT | RSE | ALT | + bindings = < + &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P + &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SCLN + &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp CMMA &kp DOT &kp FSLH + &kp LGUI &mo 1 &kp SPC &kp RET &mo 2 &kp RALT + >; + }; + lower_layer { +// ----------------------------------------------------------------------------------------- +// | ESC | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | BKSP | +// | BTCLR| BT1 | BT2 | BT3 | BT4 | BT5 | | LFT | DWN | UP | RGT | | | +// | SHFT | | | | | | | | | | | | | +// | GUI | | SPC | | ENT | | ALT | + bindings = < + &kp NUM_1 &kp NUM_2 &kp NUM_3 &kp NUM_4 &kp NUM_5 &kp NUM_6 &kp NUM_7 &kp NUM_8 &kp NUM_9 &kp NUM_0 + &bt BT_SEL 0 &bt BT_SEL 1 &bt BT_SEL 2 &bt BT_SEL 3 &bt BT_SEL 4 &kp LARW &kp DARW &kp UARW &kp RARW &trans + &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans + &kp LGUI &trans &kp SPC &kp RET &trans &kp RALT + >; + }; + + raise_layer { +// ----------------------------------------------------------------------------------------- +// | ESC | ! | @ | # | $ | % | | ^ | & | * | ( | ) | BKSP | +// | CTRL | | | | | | | - | = | { | } | "|" | ` | +// | SHFT | | | | | | | _ | + | [ | ] | \ | ~ | // TODO: Fix this row when &mkp is committed +// | GUI | | SPC | | ENT | | ALT | + bindings = < + &kp BANG &kp ATSN &kp HASH &kp CURU &kp PRCT &kp CRRT &kp AMPS &kp KMLT &kp LPRN &kp RPRN + &trans &trans &trans &trans &trans &kp MINUS &kp EQL &kp LBKT &kp RBKT &kp PIPE + &trans &trans &trans &trans &trans &trans &trans &trans &trans &kp BSLH + &kp LGUI &trans &kp SPC &kp RET &trans &kp RALT + >; + }; + }; +}; + diff --git a/app/boards/shields/microdox/microdox_left.conf b/app/boards/shields/microdox/microdox_left.conf new file mode 100644 index 00000000..1e028a78 --- /dev/null +++ b/app/boards/shields/microdox/microdox_left.conf @@ -0,0 +1,2 @@ +CONFIG_ZMK_SPLIT=y +CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL=y diff --git a/app/boards/shields/microdox/microdox_left.overlay b/app/boards/shields/microdox/microdox_left.overlay new file mode 100644 index 00000000..0a3f823a --- /dev/null +++ b/app/boards/shields/microdox/microdox_left.overlay @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2020 Pete Johanson + * Copyright (c) 2020 Kellen Carey + * + * SPDX-License-Identifier: MIT + */ + +#include "microdox.dtsi" + +&kscan0 { + col-gpios + = <&pro_micro_a 3 GPIO_ACTIVE_HIGH> + , <&pro_micro_a 2 GPIO_ACTIVE_HIGH> + , <&pro_micro_a 1 GPIO_ACTIVE_HIGH> + , <&pro_micro_a 0 GPIO_ACTIVE_HIGH> + , <&pro_micro_d 15 GPIO_ACTIVE_HIGH> + ; +}; + +&bt_unpair_combo { + key-positions = <0 38>; +}; diff --git a/app/boards/shields/microdox/microdox_right.conf b/app/boards/shields/microdox/microdox_right.conf new file mode 100644 index 00000000..990cf7c0 --- /dev/null +++ b/app/boards/shields/microdox/microdox_right.conf @@ -0,0 +1,2 @@ +CONFIG_ZMK_SPLIT=y +CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL=y diff --git a/app/boards/shields/microdox/microdox_right.overlay b/app/boards/shields/microdox/microdox_right.overlay new file mode 100644 index 00000000..2638a398 --- /dev/null +++ b/app/boards/shields/microdox/microdox_right.overlay @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2020 Pete Johanson + * Copyright (c) 2020 Kellen Carey + * + * SPDX-License-Identifier: MIT + */ + +#include "microdox.dtsi" + +&default_transform { + col-offset = <5>; +}; + +&kscan0 { + col-gpios + = <&pro_micro_d 15 GPIO_ACTIVE_HIGH> + , <&pro_micro_a 0 GPIO_ACTIVE_HIGH> + , <&pro_micro_a 1 GPIO_ACTIVE_HIGH> + , <&pro_micro_a 2 GPIO_ACTIVE_HIGH> + , <&pro_micro_a 3 GPIO_ACTIVE_HIGH> + ; +}; + +&bt_unpair_combo { + key-positions = <9 35>; +}; From ca29c40206031f95525c29750650013efc0e56f1 Mon Sep 17 00:00:00 2001 From: Kellen Carey Date: Wed, 7 Oct 2020 21:22:08 -0700 Subject: [PATCH 32/61] clean up keymap --- app/boards/shields/microdox/microdox.keymap | 52 +++++++++++++-------- 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/app/boards/shields/microdox/microdox.keymap b/app/boards/shields/microdox/microdox.keymap index fa43a637..916141c7 100644 --- a/app/boards/shields/microdox/microdox.keymap +++ b/app/boards/shields/microdox/microdox.keymap @@ -14,37 +14,37 @@ default_layer { // ----------------------------------------------------------------------------------------- -// | TAB | Q | W | E | R | T | | Y | U | I | O | P | BKSP | -// | CTRL | A | S | D | F | G | | H | J | K | L | ; | ' | -// | SHFT | Z | X | C | V | B | | N | M | , | . | / | SHFT | -// | GUI | LWR | SPC | | ENT | RSE | ALT | +// | Q | W | E | R | T | | Y | U | I | O | P | +// | A | S | D | F | G | | H | J | K | L | ; | +// | Z | X | C | V | B | | N | M | , | . | / | +// | GUI | NAV | SHFT | | SPC | SYM | ALT | bindings = < &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SCLN &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp CMMA &kp DOT &kp FSLH - &kp LGUI &mo 1 &kp SPC &kp RET &mo 2 &kp RALT + &kp LGUI &mo 1 &kp LSFT &kp SPC &mo 2 &kp RALT >; }; - lower_layer { + nav_layer { // ----------------------------------------------------------------------------------------- -// | ESC | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | BKSP | -// | BTCLR| BT1 | BT2 | BT3 | BT4 | BT5 | | LFT | DWN | UP | RGT | | | -// | SHFT | | | | | | | | | | | | | -// | GUI | | SPC | | ENT | | ALT | +// | | | ESC | ~ | | | TAB | HOME | UP | END | DEL | +// | | GUI | ALT | CTRL | NUM | | / | LEFT | DOWN | RGT | BKSP | +// | | | | | | | \ | ENT | | | | +// | | | | | | | | bindings = < - &kp NUM_1 &kp NUM_2 &kp NUM_3 &kp NUM_4 &kp NUM_5 &kp NUM_6 &kp NUM_7 &kp NUM_8 &kp NUM_9 &kp NUM_0 - &bt BT_SEL 0 &bt BT_SEL 1 &bt BT_SEL 2 &bt BT_SEL 3 &bt BT_SEL 4 &kp LARW &kp DARW &kp UARW &kp RARW &trans - &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans - &kp LGUI &trans &kp SPC &kp RET &trans &kp RALT + &trans &trans &kp ESC &kp TILD &trans &kp TAB &kp HOME &kp UARW &kp END &kp DEL + &trans &kp GUI &kp RALT &kp LCTL &mo 3 &kp FSLH &kp LARW &kp DARW &kp RARW &kp BKSP + &trans &trans &trans &trans &trans &kp BSLH &kp RET &trans &trans &trans + &trans &trans &trans &trans &trans &trans >; }; - raise_layer { + sym_layer { // ----------------------------------------------------------------------------------------- -// | ESC | ! | @ | # | $ | % | | ^ | & | * | ( | ) | BKSP | -// | CTRL | | | | | | | - | = | { | } | "|" | ` | -// | SHFT | | | | | | | _ | + | [ | ] | \ | ~ | // TODO: Fix this row when &mkp is committed -// | GUI | | SPC | | ENT | | ALT | +// | ! | @ | # | $ | % | | ^ | & | * | ( | ) | +// | | | | | | | - | = | { | } | "|" | +// | | | | | | | _ | + | [ | ] | \ | +// | GUI | | SPC | | ENT | | ALT | bindings = < &kp BANG &kp ATSN &kp HASH &kp CURU &kp PRCT &kp CRRT &kp AMPS &kp KMLT &kp LPRN &kp RPRN &trans &trans &trans &trans &trans &kp MINUS &kp EQL &kp LBKT &kp RBKT &kp PIPE @@ -52,6 +52,20 @@ &kp LGUI &trans &kp SPC &kp RET &trans &kp RALT >; }; + + num_layer { +// ----------------------------------------------------------------------------------------- +// | | | | | | | A | 7 | 8 | 9 | D | +// | | | | | | | B | 4 | 5 | 6 | E | +// | | | | | | | C | 1 | 2 | 3 | F | +// | | | | | 0 | . | | + bindings = < + &trans &trans &trans &trans &trans &kp A &kp NUM_7 &kp NUM_8 &kp NUM_9 &kp D + &trans &trans &trans &trans &trans &kp B &kp NUM_4 &kp NUM_5 &kp NUM_6 &kp E + &trans &trans &trans &trans &trans &kp C &kp NUM_1 &kp NUM_2 &kp NUM_3 &kp F + &trans &trans &trans &kp NUM_0 &kp DOT &trans + >; + }; }; }; From a8d48b043d0913e2f4e15d34547989d78b1b8088 Mon Sep 17 00:00:00 2001 From: Tyler Walker Date: Thu, 8 Oct 2020 18:42:55 -0400 Subject: [PATCH 33/61] add benign uf2 transfer error for macOS to troubleshooting --- .../assets/troubleshooting/filetransfer/mac.png | Bin 0 -> 26499 bytes docs/docs/troubleshooting.md | 4 ++++ 2 files changed, 4 insertions(+) create mode 100644 docs/docs/assets/troubleshooting/filetransfer/mac.png diff --git a/docs/docs/assets/troubleshooting/filetransfer/mac.png b/docs/docs/assets/troubleshooting/filetransfer/mac.png new file mode 100644 index 0000000000000000000000000000000000000000..f28ca8d78369ec7b4cdfb2fd20f7cd3032cb454c GIT binary patch literal 26499 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 K-1SHt4qw0YvK zKP>!>Xk%-u8faH#=;zm1V%iM3=u(S0wsZ+9-v!N8H+eHrrFg`bj*cYPrx848hQDLrtq4~f6++39!a9?5Bga1X% zqD%_n0EaFQOaE=>{{#|BI0~EjN!h=nnZGPSnGiHr^grg~13EZ7G|tyIU!$!TJ0ZqE3BHxTVl=46jH4Zr#JzuK(c!5F{yd1}h;+B~^Z^GN4o{x&8Hj1~{?{rO$_1&eMp1Cruxh>6U+IdW*-AEY z=6!1UQ~mcg`}^}j=AY{TFXsq25+SD<0f%&6D@2K5b)R#~WgnbiozD s6yremh$rlNrBw!%Hq(IW@cR|IqqMH+OVD`db!TWrIaS%x2j(IF2R8r@?f?J) literal 0 HcmV?d00001 diff --git a/docs/docs/troubleshooting.md b/docs/docs/troubleshooting.md index deb89b64..2e5e9899 100644 --- a/docs/docs/troubleshooting.md +++ b/docs/docs/troubleshooting.md @@ -19,6 +19,10 @@ Variations of the warnings shown below occur when flashing the `.uf2` | :-------------------------------------------------------------------------------: | | An example of the file transfer error on Linux | +| ![Example Error Screen](../docs/assets/troubleshooting/filetransfer/mac.png) | +| :-------------------------------------------------------------------------------: | +| An example of the file transfer error on MacOS | + ### CMake Error From ea05df029086a47d0b0e33fe882801009e3b6872 Mon Sep 17 00:00:00 2001 From: Kevin Date: Thu, 8 Oct 2020 21:44:32 -0700 Subject: [PATCH 34/61] docs: Added link to clarify where to add sensor-bindings code --- docs/docs/dev-guide-new-shield.md | 10 +++++++--- docs/docs/feature/encoders.md | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/docs/docs/dev-guide-new-shield.md b/docs/docs/dev-guide-new-shield.md index 01aad30c..1ba572c5 100644 --- a/docs/docs/dev-guide-new-shield.md +++ b/docs/docs/dev-guide-new-shield.md @@ -238,7 +238,6 @@ If building locally for split boards, you may need to add these lines to the spe In your device tree file you will need to add the following lines to define the encoder sensor: - ``` left_encoder: encoder_left { compatible = "alps,ec11"; @@ -248,6 +247,7 @@ left_encoder: encoder_left { resolution = <4>; }; ``` + Here you will have to replace PIN_A and PIN_B with the appropriate pins that your PCB utilizes for the encoder(s). For keyboards that use the Pro Micro or any of the Pro Micro replacements, Sparkfun's [Pro Micro Hookup Guide](https://learn.sparkfun.com/tutorials/pro-micro--fio-v3-hookup-guide/hardware-overview-pro-micro) has a pinout diagram that can be useful to determine the right pins. Reference either the blue numbers labeled "Arduino" (digital pins) or the green numbers labeled "Analog" (analog pins). For pins that are labeled as both digital and analog, refer to your specific board's .dtsi file to determine how you should refer to that pin. 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. @@ -279,12 +279,15 @@ For split keyboards, make sure to add left hand encoders to the left .overlay fi -Add the following line to your keymap file to add default encoder behavior bindings: +Add the following line to each layer of your keymap file to add default encoder behavior bindings: ``` sensor-bindings = <&inc_dec_cp M_VOLU M_VOLD>; ``` -Add additional bindings as necessary to match the default number of encoders on your board. See the [Encoders](/docs/feature/encoders) and [Keymap](/docs/feature/keymaps) feature documentation for more details. + +This should be placed after the regular key bindings but within the layer (see the [Default Keymap section](/docs/dev-guide-new-shield#default-keymap) above for an example of where). + +Add additional bindings as necessary to match the default number of encoders on your board. Details on the syntax can be found in the [Encoders](/docs/feature/encoders) and [Keymap](/docs/feature/keymaps) feature documentation. @@ -333,6 +336,7 @@ jobs: - board: proton_c shield: clueboard_california ``` + :::note Notice that both the left and right halves of a split board need to be added to the list of shields for proper error checking. :::note diff --git a/docs/docs/feature/encoders.md b/docs/docs/feature/encoders.md index 38ff9d31..9caccc2f 100644 --- a/docs/docs/feature/encoders.md +++ b/docs/docs/feature/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](/docs/dev-guide-new-shield) documentation for how to add or modify additional encoders to your shield. +See the [New Keyboard Shield](/docs/dev-guide-new-shield#encoders) documentation for how to add or modify additional encoders to your shield. From 59a804f751a2eec2b62b91fbde1f69535376d63c Mon Sep 17 00:00:00 2001 From: Pete Johanson Date: Fri, 9 Oct 2020 01:05:50 -0400 Subject: [PATCH 35/61] fix(actions): Upload UF2 for all compatible boards --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 454ab796..60c337de 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -75,7 +75,7 @@ jobs: args: 'build "-s app -b ${{ matrix.board }} -- -DSHIELD=${{ matrix.shield }}"' - name: Archive Build uses: actions/upload-artifact@v2 - if: ${{ matrix.board == 'nice_nano' }} + if: ${{ matrix.board != 'proton_c' }} with: name: "${{ matrix.board }}-${{ matrix.shield }}-zmk-uf2" path: build/zephyr/zmk.uf2 From a9ec1148e50ff0601f82c9eb55b90c33e7c70dab Mon Sep 17 00:00:00 2001 From: kurtis-lew Date: Thu, 8 Oct 2020 22:16:53 -0700 Subject: [PATCH 36/61] Added -DZMK_CONFIG Documentation --- docs/docs/dev-build.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docs/docs/dev-build.md b/docs/docs/dev-build.md index 816468e2..a7c1cd91 100644 --- a/docs/docs/dev-build.md +++ b/docs/docs/dev-build.md @@ -84,6 +84,19 @@ west build -d build/right -b nice_nano -- -DSHIELD=kyria_right ``` This produces `left` and `right` subfolders under the `build` directory and two separate .uf2 files. For future work on a specific half, use the `-d` parameter again to ensure you are building into the correct location. +### Building from `zmk-config` Folder + +Instead of building .uf2 files using the default keymap and config files, you can build directly from your [`zmk-config` folder](user-setup.md) by adding +`-DZMK_CONFIG="C:/the/absolute/path/config"` to your `west build` command. **Notice that this path should point to the folder labelled `config` within your `zmk-config` folder.** + + +For instance, building kyria firmware from a user `myUser`'s `zmk-config` folder on Windows 10 may look something like this: + +``` +west build -b nice_nano -- -DSHIELD=kyria_left -DZMK_CONFIG="C:/Users/myUser/Documents/Github/zmk-config/config" +``` + + ## Flashing Once built, the previously supplied parameters will be remembered so you can run the following to flash your From 49315c2f6df6c17966dafa5a97668774a6a65bb0 Mon Sep 17 00:00:00 2001 From: kurtis-lew Date: Thu, 8 Oct 2020 22:18:53 -0700 Subject: [PATCH 37/61] Addressing Issue #181 --- docs/docs/dev-guide-new-shield.md | 135 ++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) diff --git a/docs/docs/dev-guide-new-shield.md b/docs/docs/dev-guide-new-shield.md index 01aad30c..ee489155 100644 --- a/docs/docs/dev-guide-new-shield.md +++ b/docs/docs/dev-guide-new-shield.md @@ -21,6 +21,10 @@ The high level steps are: It may be helpful to review the upstream [shields documentation](https://docs.zephyrproject.org/2.3.0/guides/porting/shields.html#shields) to get a proper understanding of the underlying system before continuing. +:::note +ZMK support for split keyboards 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. +::: + ## New Shield Directory Shields for Zephyr applications go into the `boards/shields/` directory; since ZMK's Zephyr application lives in the `app/` subdirectory of the repository, that means the new shield directory should be: @@ -45,6 +49,16 @@ config SHIELD_MY_BOARD This will make sure the new configuration `SHIELD_MY_BOARD` is set to true whenever `my_board` is added as a shield in your build. + +**For split boards**, you will need to add configurations for the left and right sides. +``` +config SHIELD_MY_BOARD_LEFT + def_bool $(shields_list_contains,my_board_left) + +config SHIELD_MY_BOARD_RIGHT + def_bool $(shields_list_contains,my_board_right) +``` + ### Kconfig.defconfig The `Kconfig.defconfig` file is where overrides for various configuration settings @@ -63,6 +77,26 @@ config ZMK_KEYBOARD_NAME endif ``` + +Similarly to defining the halves of a split board in `Kconfig.shield` it is important to set the `ZMK_KEYBOARD_NAME` for each half of a split keyboard. + +``` +if SHIELD_MY_BOARD_LEFT + +config ZMK_KEYBOARD_NAME + default "My Awesome Keyboard Left" + +endif + +if SHIELD_MY_BOARD_RIGHT + +config ZMK_KEYBOARD_NAME + default "My Awesome Keyboard Right" + +endif +``` + + ## Shield Overlay ![Labelled Pro Micro pins](assets/pro-micro/pro-micro-pins-labelled.jpg) @@ -98,6 +132,74 @@ this might look something like: }; ``` +:::note +For split keyboards, it is preferred to define only the `col-gpios` or `row-gpios` in the common shield .dtsi, depending on the diode-direction. +For `col2row` directed boards like the iris, a sample kscan in the .dtsi folder would look like this: + +``` +kscan0: kscan { + compatible = "zmk,kscan-gpio-matrix"; + label = "KSCAN"; + + diode-direction = "col2row"; + row-gpios + = <&pro_micro_d 6 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> + , <&pro_micro_d 7 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> + , <&pro_micro_d 8 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> + , <&pro_micro_d 0 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> + , <&pro_micro_d 4 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> + ; + + }; +``` + +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. +This is exemplified with the iris .overlay files. + +``` +// iris_left.overlay + +#include "iris.dtsi" // Notice that the main dtsi files are included in the overlay. + +&kscan0 { + col-gpios + = <&pro_micro_a 1 GPIO_ACTIVE_HIGH> + , <&pro_micro_a 0 GPIO_ACTIVE_HIGH> + , <&pro_micro_d 15 GPIO_ACTIVE_HIGH> + , <&pro_micro_d 14 GPIO_ACTIVE_HIGH> + , <&pro_micro_d 16 GPIO_ACTIVE_HIGH> + , <&pro_micro_d 10 GPIO_ACTIVE_HIGH> + ; +}; +``` + +``` +// iris_right.overlay + +#include "iris.dtsi" + +&default_transform { // The matrix transform for this board is 6 columns over because the matrix on the left side is 6 columns wide. + col-offset = <6>; +}; + +&kscan0 { + col-gpios + = <&pro_micro_d 10 GPIO_ACTIVE_HIGH> //&pro_micro_a 1 in the left side + , <&pro_micro_d 16 GPIO_ACTIVE_HIGH> //&pro_micro_a 0 in the left side + , <&pro_micro_d 14 GPIO_ACTIVE_HIGH> //&pro_micro_d 15 in the left side + , <&pro_micro_d 15 GPIO_ACTIVE_HIGH> //&pro_micro_d 14 in the left side + , <&pro_micro_a 0 GPIO_ACTIVE_HIGH> //&pro_micro_d 16 in the left side + , <&pro_micro_a 1 GPIO_ACTIVE_HIGH> //&pro_micro_d 10 in the left side + ; +}; + +``` + +Split keyboards, will often use [Matrix Transform](#optional-matrix-transform) to account for their thumb clusters and other oddities. + +::: + ## (Optional) 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: @@ -289,6 +391,39 @@ Add additional bindings as necessary to match the default number of encoders on +## (Split Keyboards Only) .conf files + +While normal boards only have one .conf file that applies configuration characteristics to the entire board, 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 + +The discrete .conf files for each half allows the user to define the central and peripheral sides of the split, like so: + +``` +// Central Half + +CONFIG_ZMK_SPLIT=y +CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL=y +``` + +``` +// Peripheral Half + +CONFIG_ZMK_SPLIT=y +CONFIG_ZMK_SPLIT_BLE_ROLE_Peripheral=y +``` + +Using the .conf file that affects both halves of a split board would be for circumstances like deep-sleep or _. + +``` +// Global .conf + +CONFIG_ZMK_SLEEP=y +``` + ## Testing Once you've fully created the new keyboard shield definition, From dbda99a3788fb27d258a7c5b9c8f56638f190d65 Mon Sep 17 00:00:00 2001 From: kurtis-lew Date: Thu, 8 Oct 2020 22:19:26 -0700 Subject: [PATCH 38/61] Addressed Issue #181 --- docs/docs/dev-guide-new-shield.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/docs/dev-guide-new-shield.md b/docs/docs/dev-guide-new-shield.md index ee489155..b8f1a194 100644 --- a/docs/docs/dev-guide-new-shield.md +++ b/docs/docs/dev-guide-new-shield.md @@ -403,14 +403,14 @@ with different scopes. For example, a split board called `my_awesome_split_board The discrete .conf files for each half allows the user to define the central and peripheral sides of the split, like so: ``` -// Central Half +// Central Half (Usually the left side: my_awesome_split_board_left.conf) CONFIG_ZMK_SPLIT=y CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL=y ``` ``` -// Peripheral Half +// Peripheral Half (Usually the right side: my_awesome_split_board_right.conf) CONFIG_ZMK_SPLIT=y CONFIG_ZMK_SPLIT_BLE_ROLE_Peripheral=y @@ -419,7 +419,7 @@ CONFIG_ZMK_SPLIT_BLE_ROLE_Peripheral=y Using the .conf file that affects both halves of a split board would be for circumstances like deep-sleep or _. ``` -// Global .conf +// my_awesome_split_board.conf CONFIG_ZMK_SLEEP=y ``` From c27d3c66f150a0adfa19a2dd6c2bd64544c261a7 Mon Sep 17 00:00:00 2001 From: kurtis-lew Date: Thu, 8 Oct 2020 22:21:49 -0700 Subject: [PATCH 39/61] Removed blank space --- docs/docs/dev-guide-new-shield.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/dev-guide-new-shield.md b/docs/docs/dev-guide-new-shield.md index b8f1a194..9c0a2651 100644 --- a/docs/docs/dev-guide-new-shield.md +++ b/docs/docs/dev-guide-new-shield.md @@ -416,7 +416,7 @@ CONFIG_ZMK_SPLIT=y CONFIG_ZMK_SPLIT_BLE_ROLE_Peripheral=y ``` -Using the .conf file that affects both halves of a split board would be for circumstances like deep-sleep or _. +Using the .conf file that affects both halves of a split board would be for circumstances like deep-sleep. ``` // my_awesome_split_board.conf From a58a8412c7335df27077cc9647444f014b6a094e Mon Sep 17 00:00:00 2001 From: kurtis-lew Date: Fri, 9 Oct 2020 08:15:38 -0700 Subject: [PATCH 40/61] Documented Issue #220 --- docs/docs/bond-reset.md | 4 ++-- docs/docs/troubleshooting.md | 13 +++++++++++++ docs/sidebars.js | 1 - 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/docs/docs/bond-reset.md b/docs/docs/bond-reset.md index 1ba79ee0..504fd72a 100644 --- a/docs/docs/bond-reset.md +++ b/docs/docs/bond-reset.md @@ -1,7 +1,7 @@ --- id: bond-reset -title: Reset BLE Connections -sidebar_label: BLE Reset +title: Reset BLE Connections (DEPRECATED) +sidebar_label: BLE Reset (DEPRECATED) --- Known as a 'bond reset', each keyboard has a special key combination independent of the user defined key map which will diff --git a/docs/docs/troubleshooting.md b/docs/docs/troubleshooting.md index deb89b64..8dd12614 100644 --- a/docs/docs/troubleshooting.md +++ b/docs/docs/troubleshooting.md @@ -59,3 +59,16 @@ After opening the `.dts.pre.tmp:` and scrolling down to the | ![Healthy Keymap Temp](../docs/assets/troubleshooting/keymaps/healthyEDIT.png) | | :-------------------------------------------------------------------------------: | | A properly defined keymap with successful compilation. As shown in red, the corrected keycode (`&kp SPC`) references the proper Usage ID defined in the [USB HID Usage Tables](https://www.usb.org/document-library/hid-usage-tables-12)| + +### Split Keyboard Halves Unable to Pair + +The previous method of pairing split keyboard halves involved a **BLE Reset** with a specific combination of held keys that would remove all bluetooth profile information from the keyboard. +Since then, a much simpler procedure of performing a bluetooth reset for split keyboards has come about, without the need for any file modification: + +1. Log into Github and download the "settings clear" UF2 image from latest GH actions from the `main` of ZMK +1. Put both sides into bootloader mode +1. Flash both sides with the "settings clear" UF2 images from step 1. After, put both sides into bootloader mode again. +1. Flash the actual image for each half of the split keyboard + +After completing these steps, pair the halves of the split keyboard together by resetting them at the same time. Most commonly, this is done by grounding the reset pins +for each of your keyboard's microcontrollers or pressing the reset buttons at the same time. \ No newline at end of file diff --git a/docs/sidebars.js b/docs/sidebars.js index ace7fa17..93ce2264 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -6,7 +6,6 @@ module.exports = { "faq", "user-setup", "customization", - "bond-reset", "troubleshooting" ], Features: [ From aca801d90ffcc12076244626dc0d4b239df25ab4 Mon Sep 17 00:00:00 2001 From: kurtis-lew Date: Fri, 9 Oct 2020 08:19:08 -0700 Subject: [PATCH 41/61] Revert "Removed blank space" This reverts commit c27d3c66f150a0adfa19a2dd6c2bd64544c261a7. --- docs/docs/dev-guide-new-shield.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/dev-guide-new-shield.md b/docs/docs/dev-guide-new-shield.md index 9c0a2651..b8f1a194 100644 --- a/docs/docs/dev-guide-new-shield.md +++ b/docs/docs/dev-guide-new-shield.md @@ -416,7 +416,7 @@ CONFIG_ZMK_SPLIT=y CONFIG_ZMK_SPLIT_BLE_ROLE_Peripheral=y ``` -Using the .conf file that affects both halves of a split board would be for circumstances like deep-sleep. +Using the .conf file that affects both halves of a split board would be for circumstances like deep-sleep or _. ``` // my_awesome_split_board.conf From 429c9dc464c38bb0604a3ebe55151b451580d8ca Mon Sep 17 00:00:00 2001 From: kurtis-lew Date: Fri, 9 Oct 2020 08:19:40 -0700 Subject: [PATCH 42/61] Revert "Addressed Issue #181" This reverts commit dbda99a3788fb27d258a7c5b9c8f56638f190d65. --- docs/docs/dev-guide-new-shield.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/docs/dev-guide-new-shield.md b/docs/docs/dev-guide-new-shield.md index b8f1a194..ee489155 100644 --- a/docs/docs/dev-guide-new-shield.md +++ b/docs/docs/dev-guide-new-shield.md @@ -403,14 +403,14 @@ with different scopes. For example, a split board called `my_awesome_split_board The discrete .conf files for each half allows the user to define the central and peripheral sides of the split, like so: ``` -// Central Half (Usually the left side: my_awesome_split_board_left.conf) +// Central Half CONFIG_ZMK_SPLIT=y CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL=y ``` ``` -// Peripheral Half (Usually the right side: my_awesome_split_board_right.conf) +// Peripheral Half CONFIG_ZMK_SPLIT=y CONFIG_ZMK_SPLIT_BLE_ROLE_Peripheral=y @@ -419,7 +419,7 @@ CONFIG_ZMK_SPLIT_BLE_ROLE_Peripheral=y Using the .conf file that affects both halves of a split board would be for circumstances like deep-sleep or _. ``` -// my_awesome_split_board.conf +// Global .conf CONFIG_ZMK_SLEEP=y ``` From e03b51fe2ea5dfbedcc7747ac64899b5d0999a04 Mon Sep 17 00:00:00 2001 From: kurtis-lew Date: Fri, 9 Oct 2020 08:19:46 -0700 Subject: [PATCH 43/61] Revert "Addressing Issue #181" This reverts commit 49315c2f6df6c17966dafa5a97668774a6a65bb0. --- docs/docs/dev-guide-new-shield.md | 135 ------------------------------ 1 file changed, 135 deletions(-) diff --git a/docs/docs/dev-guide-new-shield.md b/docs/docs/dev-guide-new-shield.md index ee489155..01aad30c 100644 --- a/docs/docs/dev-guide-new-shield.md +++ b/docs/docs/dev-guide-new-shield.md @@ -21,10 +21,6 @@ The high level steps are: It may be helpful to review the upstream [shields documentation](https://docs.zephyrproject.org/2.3.0/guides/porting/shields.html#shields) to get a proper understanding of the underlying system before continuing. -:::note -ZMK support for split keyboards 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. -::: - ## New Shield Directory Shields for Zephyr applications go into the `boards/shields/` directory; since ZMK's Zephyr application lives in the `app/` subdirectory of the repository, that means the new shield directory should be: @@ -49,16 +45,6 @@ config SHIELD_MY_BOARD This will make sure the new configuration `SHIELD_MY_BOARD` is set to true whenever `my_board` is added as a shield in your build. - -**For split boards**, you will need to add configurations for the left and right sides. -``` -config SHIELD_MY_BOARD_LEFT - def_bool $(shields_list_contains,my_board_left) - -config SHIELD_MY_BOARD_RIGHT - def_bool $(shields_list_contains,my_board_right) -``` - ### Kconfig.defconfig The `Kconfig.defconfig` file is where overrides for various configuration settings @@ -77,26 +63,6 @@ config ZMK_KEYBOARD_NAME endif ``` - -Similarly to defining the halves of a split board in `Kconfig.shield` it is important to set the `ZMK_KEYBOARD_NAME` for each half of a split keyboard. - -``` -if SHIELD_MY_BOARD_LEFT - -config ZMK_KEYBOARD_NAME - default "My Awesome Keyboard Left" - -endif - -if SHIELD_MY_BOARD_RIGHT - -config ZMK_KEYBOARD_NAME - default "My Awesome Keyboard Right" - -endif -``` - - ## Shield Overlay ![Labelled Pro Micro pins](assets/pro-micro/pro-micro-pins-labelled.jpg) @@ -132,74 +98,6 @@ this might look something like: }; ``` -:::note -For split keyboards, it is preferred to define only the `col-gpios` or `row-gpios` in the common shield .dtsi, depending on the diode-direction. -For `col2row` directed boards like the iris, a sample kscan in the .dtsi folder would look like this: - -``` -kscan0: kscan { - compatible = "zmk,kscan-gpio-matrix"; - label = "KSCAN"; - - diode-direction = "col2row"; - row-gpios - = <&pro_micro_d 6 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> - , <&pro_micro_d 7 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> - , <&pro_micro_d 8 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> - , <&pro_micro_d 0 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> - , <&pro_micro_d 4 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> - ; - - }; -``` - -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. -This is exemplified with the iris .overlay files. - -``` -// iris_left.overlay - -#include "iris.dtsi" // Notice that the main dtsi files are included in the overlay. - -&kscan0 { - col-gpios - = <&pro_micro_a 1 GPIO_ACTIVE_HIGH> - , <&pro_micro_a 0 GPIO_ACTIVE_HIGH> - , <&pro_micro_d 15 GPIO_ACTIVE_HIGH> - , <&pro_micro_d 14 GPIO_ACTIVE_HIGH> - , <&pro_micro_d 16 GPIO_ACTIVE_HIGH> - , <&pro_micro_d 10 GPIO_ACTIVE_HIGH> - ; -}; -``` - -``` -// iris_right.overlay - -#include "iris.dtsi" - -&default_transform { // The matrix transform for this board is 6 columns over because the matrix on the left side is 6 columns wide. - col-offset = <6>; -}; - -&kscan0 { - col-gpios - = <&pro_micro_d 10 GPIO_ACTIVE_HIGH> //&pro_micro_a 1 in the left side - , <&pro_micro_d 16 GPIO_ACTIVE_HIGH> //&pro_micro_a 0 in the left side - , <&pro_micro_d 14 GPIO_ACTIVE_HIGH> //&pro_micro_d 15 in the left side - , <&pro_micro_d 15 GPIO_ACTIVE_HIGH> //&pro_micro_d 14 in the left side - , <&pro_micro_a 0 GPIO_ACTIVE_HIGH> //&pro_micro_d 16 in the left side - , <&pro_micro_a 1 GPIO_ACTIVE_HIGH> //&pro_micro_d 10 in the left side - ; -}; - -``` - -Split keyboards, will often use [Matrix Transform](#optional-matrix-transform) to account for their thumb clusters and other oddities. - -::: - ## (Optional) 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: @@ -391,39 +289,6 @@ Add additional bindings as necessary to match the default number of encoders on -## (Split Keyboards Only) .conf files - -While normal boards only have one .conf file that applies configuration characteristics to the entire board, 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 - -The discrete .conf files for each half allows the user to define the central and peripheral sides of the split, like so: - -``` -// Central Half - -CONFIG_ZMK_SPLIT=y -CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL=y -``` - -``` -// Peripheral Half - -CONFIG_ZMK_SPLIT=y -CONFIG_ZMK_SPLIT_BLE_ROLE_Peripheral=y -``` - -Using the .conf file that affects both halves of a split board would be for circumstances like deep-sleep or _. - -``` -// Global .conf - -CONFIG_ZMK_SLEEP=y -``` - ## Testing Once you've fully created the new keyboard shield definition, From 7128808bbafd198a2d3b7275a9a029d4a58d5bc6 Mon Sep 17 00:00:00 2001 From: kurtis-lew Date: Fri, 9 Oct 2020 08:19:50 -0700 Subject: [PATCH 44/61] Revert "Added -DZMK_CONFIG Documentation" This reverts commit a9ec1148e50ff0601f82c9eb55b90c33e7c70dab. --- docs/docs/dev-build.md | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/docs/docs/dev-build.md b/docs/docs/dev-build.md index a7c1cd91..816468e2 100644 --- a/docs/docs/dev-build.md +++ b/docs/docs/dev-build.md @@ -84,19 +84,6 @@ west build -d build/right -b nice_nano -- -DSHIELD=kyria_right ``` This produces `left` and `right` subfolders under the `build` directory and two separate .uf2 files. For future work on a specific half, use the `-d` parameter again to ensure you are building into the correct location. -### Building from `zmk-config` Folder - -Instead of building .uf2 files using the default keymap and config files, you can build directly from your [`zmk-config` folder](user-setup.md) by adding -`-DZMK_CONFIG="C:/the/absolute/path/config"` to your `west build` command. **Notice that this path should point to the folder labelled `config` within your `zmk-config` folder.** - - -For instance, building kyria firmware from a user `myUser`'s `zmk-config` folder on Windows 10 may look something like this: - -``` -west build -b nice_nano -- -DSHIELD=kyria_left -DZMK_CONFIG="C:/Users/myUser/Documents/Github/zmk-config/config" -``` - - ## Flashing Once built, the previously supplied parameters will be remembered so you can run the following to flash your From e53320a687a8b402fac3ed972a776993495a2f9a Mon Sep 17 00:00:00 2001 From: Pete Johanson Date: Fri, 9 Oct 2020 11:57:34 -0400 Subject: [PATCH 45/61] fix(docs): Remove hanging footnote. --- docs/docs/behavior/bluetooth.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/behavior/bluetooth.md b/docs/docs/behavior/bluetooth.md index 8bde71bf..be0fb23c 100644 --- a/docs/docs/behavior/bluetooth.md +++ b/docs/docs/behavior/bluetooth.md @@ -24,7 +24,7 @@ Here is a table describing the command for each define: | Define | Action | | ------------ | ---------------------------------------------------------------------------------------------- | -| `BT_CLR_CMD` | Clear bond information between the keyboard and host for the selected profile [^1] | +| `BT_CLR_CMD` | Clear bond information between the keyboard and host for the selected profile. | | `BT_NXT_CMD` | Switch to the next profile, cycling through to the first one when the end is reached. | | `BT_PRV_CMD` | Switch to the previous profile, cycling through to the last one when the beginning is reached. | | `BT_SEL_CMD` | Select the 0-indexed profile by number. | From 0b125c028c65ff4a5e326760a7d0ac0f8941899c Mon Sep 17 00:00:00 2001 From: Kellen Carey Date: Fri, 9 Oct 2020 11:48:06 -0700 Subject: [PATCH 46/61] address pr comments --- app/boards/shields/microdox/Kconfig.defconfig | 2 ++ app/boards/shields/microdox/Kconfig.shield | 3 +-- .../shields/microdox/boards/nice_nano.overlay | 5 +++++ app/boards/shields/microdox/microdox.dtsi | 7 +------ app/boards/shields/microdox/microdox.keymap | 16 +++++++++------- .../shields/microdox/microdox_left.overlay | 4 ---- .../shields/microdox/microdox_right.overlay | 4 ---- 7 files changed, 18 insertions(+), 23 deletions(-) diff --git a/app/boards/shields/microdox/Kconfig.defconfig b/app/boards/shields/microdox/Kconfig.defconfig index 218443f9..4840eceb 100644 --- a/app/boards/shields/microdox/Kconfig.defconfig +++ b/app/boards/shields/microdox/Kconfig.defconfig @@ -1,3 +1,5 @@ +# Copyright (c) 2020 The ZMK Contributors +# SPDX-License-Identifier: MIT if SHIELD_MICRODOX_LEFT diff --git a/app/boards/shields/microdox/Kconfig.shield b/app/boards/shields/microdox/Kconfig.shield index 7d7148de..ac79eab6 100644 --- a/app/boards/shields/microdox/Kconfig.shield +++ b/app/boards/shields/microdox/Kconfig.shield @@ -1,5 +1,4 @@ -# Copyright (c) 2020 Pete Johanson -# Copyright (c) 2020 Kellen Carey +# Copyright (c) 2020 The ZMK Contributors # SPDX-License-Identifier: MIT config SHIELD_MICRODOX_LEFT diff --git a/app/boards/shields/microdox/boards/nice_nano.overlay b/app/boards/shields/microdox/boards/nice_nano.overlay index c7c3eb8e..58cd8613 100644 --- a/app/boards/shields/microdox/boards/nice_nano.overlay +++ b/app/boards/shields/microdox/boards/nice_nano.overlay @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ &spi1 { compatible = "nordic,nrf-spi"; /* Cannot be used together with i2c0. */ diff --git a/app/boards/shields/microdox/microdox.dtsi b/app/boards/shields/microdox/microdox.dtsi index bf7950df..55c67dd3 100644 --- a/app/boards/shields/microdox/microdox.dtsi +++ b/app/boards/shields/microdox/microdox.dtsi @@ -1,6 +1,5 @@ /* - * Copyright (c) 2020 Pete Johanson - * Copyright (c) 2020 Kellen Carey + * Copyright (c) 2020 The ZMK Contributors * * SPDX-License-Identifier: MIT */ @@ -43,10 +42,6 @@ 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) }; - bt_unpair_combo: bt_unpair_combo { - compatible = "zmk,bt-unpair-combo"; - }; - // TODO: per-key RGB node(s)? }; diff --git a/app/boards/shields/microdox/microdox.keymap b/app/boards/shields/microdox/microdox.keymap index 916141c7..5747771b 100644 --- a/app/boards/shields/microdox/microdox.keymap +++ b/app/boards/shields/microdox/microdox.keymap @@ -27,15 +27,15 @@ }; nav_layer { // ----------------------------------------------------------------------------------------- -// | | | ESC | ~ | | | TAB | HOME | UP | END | DEL | -// | | GUI | ALT | CTRL | NUM | | / | LEFT | DOWN | RGT | BKSP | -// | | | | | | | \ | ENT | | | | +// |BTCLR| | ESC | ~ | | | TAB | HOME | UP | END | DEL | +// | BT1 | GUI | ALT | CTRL | NUM | | / | LEFT | DOWN | RGT | BKSP | +// | BT2 | | | | | | \ | ENT | | | | // | | | | | | | | bindings = < - &trans &trans &kp ESC &kp TILD &trans &kp TAB &kp HOME &kp UARW &kp END &kp DEL - &trans &kp GUI &kp RALT &kp LCTL &mo 3 &kp FSLH &kp LARW &kp DARW &kp RARW &kp BKSP - &trans &trans &trans &trans &trans &kp BSLH &kp RET &trans &trans &trans - &trans &trans &trans &trans &trans &trans + &bt BT_CLR &trans &kp ESC &kp TILD &trans &kp TAB &kp HOME &kp UARW &kp END &kp DEL + &bt BT_SEL 0 &kp GUI &kp RALT &kp LCTL &mo 3 &kp FSLH &kp LARW &kp DARW &kp RARW &kp BKSP + &bt BT_SEL 1 &trans &trans &trans &trans &kp BSLH &kp RET &trans &trans &trans + &trans &trans &trans &trans &trans &trans >; }; @@ -53,6 +53,8 @@ >; }; +// This layer is unreachable until "tri layer state" is sorted out. +// Leaving it here for completeness. num_layer { // ----------------------------------------------------------------------------------------- // | | | | | | | A | 7 | 8 | 9 | D | diff --git a/app/boards/shields/microdox/microdox_left.overlay b/app/boards/shields/microdox/microdox_left.overlay index 0a3f823a..07dc0d26 100644 --- a/app/boards/shields/microdox/microdox_left.overlay +++ b/app/boards/shields/microdox/microdox_left.overlay @@ -16,7 +16,3 @@ , <&pro_micro_d 15 GPIO_ACTIVE_HIGH> ; }; - -&bt_unpair_combo { - key-positions = <0 38>; -}; diff --git a/app/boards/shields/microdox/microdox_right.overlay b/app/boards/shields/microdox/microdox_right.overlay index 2638a398..a0d86013 100644 --- a/app/boards/shields/microdox/microdox_right.overlay +++ b/app/boards/shields/microdox/microdox_right.overlay @@ -20,7 +20,3 @@ , <&pro_micro_a 3 GPIO_ACTIVE_HIGH> ; }; - -&bt_unpair_combo { - key-positions = <9 35>; -}; From a695d0d3596817834f7465e029d0205fc9235499 Mon Sep 17 00:00:00 2001 From: Kellen Carey Date: Fri, 9 Oct 2020 12:18:57 -0700 Subject: [PATCH 47/61] oops --- app/boards/shields/microdox/microdox_left.overlay | 3 +-- app/boards/shields/microdox/microdox_right.overlay | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/app/boards/shields/microdox/microdox_left.overlay b/app/boards/shields/microdox/microdox_left.overlay index 07dc0d26..4d0378e5 100644 --- a/app/boards/shields/microdox/microdox_left.overlay +++ b/app/boards/shields/microdox/microdox_left.overlay @@ -1,6 +1,5 @@ /* - * Copyright (c) 2020 Pete Johanson - * Copyright (c) 2020 Kellen Carey + * Copyright (c) 2020 The ZMK Contributors * * SPDX-License-Identifier: MIT */ diff --git a/app/boards/shields/microdox/microdox_right.overlay b/app/boards/shields/microdox/microdox_right.overlay index a0d86013..c5622b25 100644 --- a/app/boards/shields/microdox/microdox_right.overlay +++ b/app/boards/shields/microdox/microdox_right.overlay @@ -1,6 +1,5 @@ /* - * Copyright (c) 2020 Pete Johanson - * Copyright (c) 2020 Kellen Carey + * Copyright (c) 2020 The ZMK Contributors * * SPDX-License-Identifier: MIT */ From 81a4ffef7efb45f30c74802dca97d949312a1785 Mon Sep 17 00:00:00 2001 From: Pete Johanson Date: Fri, 9 Oct 2020 15:44:39 -0400 Subject: [PATCH 48/61] feat(setup): Add Microdox to setup scripts. --- docs/static/setup.ps1 | 6 +++--- docs/static/setup.sh | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/static/setup.ps1 b/docs/static/setup.ps1 index dc7b18c9..abdb6981 100644 --- a/docs/static/setup.ps1 +++ b/docs/static/setup.ps1 @@ -78,9 +78,9 @@ Write-Host "Keyboard Shield Selection:" $prompt = "Pick a keyboard" # TODO: Add support for "Other" and linking to docs on adding custom shields in user config repos. -$options = "Kyria", "Lily58", "Corne", "Splitreus62", "Sofle", "Iris", "RoMac", "makerdiary M60" -$names = "kyria", "lily58", "corne", "splitreus62", "sofle", "iris", "romac", "m60" -$splits = "y", "y", "y", "y", "y", "y", "n", "n" +$options = "Kyria", "Lily58", "Corne", "Splitreus62", "Sofle", "Iris", "RoMac", "makerdiary M60", "Microdox" +$names = "kyria", "lily58", "corne", "splitreus62", "sofle", "iris", "romac", "m60", "microdox" +$splits = "y", "y", "y", "y", "y", "y", "n", "n", "y" $choice = Get-Choice-From-Options -Options $options -Prompt $prompt $shield_title = $($options[$choice]) diff --git a/docs/static/setup.sh b/docs/static/setup.sh index 9e989644..49ed3eb2 100644 --- a/docs/static/setup.sh +++ b/docs/static/setup.sh @@ -51,7 +51,7 @@ echo "" echo "Keyboard Shield Selection:" prompt="Pick an keyboard:" -options=("Kyria" "Lily58" "Corne" "Splitreus62" "Sofle" "Iris" "RoMac" "makerdiary M60") +options=("Kyria" "Lily58" "Corne" "Splitreus62" "Sofle" "Iris" "RoMac" "makerdiary M60" "Microdox") PS3="$prompt " # TODO: Add support for "Other" and linking to docs on adding custom shields in user config repos. @@ -67,7 +67,8 @@ select opt in "${options[@]}" "Quit"; do 5 ) shield_title="Sofle" shield="sofle"; split="y"; break;; 6 ) shield_title="Iris" shield="iris"; split="y"; break;; 7 ) shield_title="RoMac" shield="romac"; split="n"; break;; - 7 ) shield_title="M60" shield="m60"; split="n"; break;; + 8 ) shield_title="M60" shield="m60"; split="n"; break;; + 9 ) shield_title="Microdox" shield="microdox"; split="y"; break;; # Add link to docs on adding your own custom shield in your ZMK config! # $(( ${#options[@]}+1 )) ) echo "Other!"; break;; From 1f2bdf639f3790ef6d36575c4a477d340b9fd393 Mon Sep 17 00:00:00 2001 From: kurtis-lew Date: Fri, 9 Oct 2020 12:57:07 -0700 Subject: [PATCH 49/61] Adjusted Wording, Added link to GH Actions --- docs/docs/troubleshooting.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/docs/docs/troubleshooting.md b/docs/docs/troubleshooting.md index 8dd12614..7395ff57 100644 --- a/docs/docs/troubleshooting.md +++ b/docs/docs/troubleshooting.md @@ -62,13 +62,17 @@ After opening the `.dts.pre.tmp:` and scrolling down to the ### Split Keyboard Halves Unable to Pair -The previous method of pairing split keyboard halves involved a **BLE Reset** with a specific combination of held keys that would remove all bluetooth profile information from the keyboard. +Previously, pairing split keyboard halves involved a **BLE Reset** via a combination of held keys that removed all bluetooth profile information from the keyboard. Since then, a much simpler procedure of performing a bluetooth reset for split keyboards has come about, without the need for any file modification: -1. Log into Github and download the "settings clear" UF2 image from latest GH actions from the `main` of ZMK -1. Put both sides into bootloader mode -1. Flash both sides with the "settings clear" UF2 images from step 1. After, put both sides into bootloader mode again. -1. Flash the actual image for each half of the split keyboard +**New Procedure:** + +1. Log into Github and download the "settings clear" UF2 image from the [latest build in Github Actions](https://github.com/zmkfirmware/zmk/actions?query=workflow%3ABuild+branch%3Amain) +1. Put each half of the split keyboard into bootloader mode +1. Flash one of the halves of the split with the "settings clear" UF2 image from step 1. Immediately after flashing "settings clear" to the chosen half, immediately put it into bootloader mode +to avoid accidental bonding between the halves. +1. Repeat step 3 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) After completing these steps, pair the halves of the split keyboard together by resetting them at the same time. Most commonly, this is done by grounding the reset pins for each of your keyboard's microcontrollers or pressing the reset buttons at the same time. \ No newline at end of file From 4d81b10ba7047a4dbd63cfe33ac879ecf437e108 Mon Sep 17 00:00:00 2001 From: Mega Mind <68985133+megamind4089@users.noreply.github.com> Date: Tue, 6 Oct 2020 15:52:21 +0800 Subject: [PATCH 50/61] Added driver to control the external power output This PR adds support to control the external power output from controllers like nice!nano, nRFMicro etc I have implemented based on my understanding of Pete suggestion on this feature. Testing done: Tested by enabling and disabling the ext_power from application and verified Verified the application does not crash with boards that does not have ext_power support Note: I did not test this in nice!nano since I don't have the boards. Will get help from others once the behavior PR is up Next Steps: Create a behavior PR to control enable/disable ext_power --- app/CMakeLists.txt | 1 + app/Kconfig | 4 + app/boards/arm/nice_nano/nice_nano.dts | 5 + app/boards/arm/nrfmicro/nrfmicro_11.dts | 5 + .../arm/nrfmicro/nrfmicro_11_flipped.dts | 5 + app/boards/arm/nrfmicro/nrfmicro_13.dts | 5 + app/boards/arm/nrfmicro/pinmux.c | 11 -- .../zmk,behavior-sensor-rotate-key-press.yaml | 2 +- app/dts/bindings/zmk,ext-power-generic.yaml | 20 ++++ app/dts/bindings/zmk,keymap-sensors.yaml | 5 + app/include/drivers/ext_power.h | 104 ++++++++++++++++++ app/src/ext_power_generic.c | 91 +++++++++++++++ app/src/main.c | 9 ++ 13 files changed, 255 insertions(+), 12 deletions(-) create mode 100644 app/dts/bindings/zmk,ext-power-generic.yaml create mode 100644 app/include/drivers/ext_power.h create mode 100644 app/src/ext_power_generic.c diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 3e59d751..31d28f57 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -31,6 +31,7 @@ target_sources(app PRIVATE src/sensors.c) target_sources_ifdef(CONFIG_ZMK_DISPLAY app PRIVATE src/display.c) target_sources(app PRIVATE src/event_manager.c) target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/ble_unpair_combo.c) +target_sources_ifdef(CONFIG_ZMK_EXT_POWER app PRIVATE src/ext_power_generic.c) target_sources(app PRIVATE src/events/position_state_changed.c) target_sources(app PRIVATE src/events/keycode_state_changed.c) target_sources(app PRIVATE src/events/modifiers_state_changed.c) diff --git a/app/Kconfig b/app/Kconfig index edf58670..fca49124 100644 --- a/app/Kconfig +++ b/app/Kconfig @@ -95,6 +95,10 @@ config ZMK_IDLE_SLEEP_TIMEOUT endif +config ZMK_EXT_POWER + bool "Enable support to control external power output" + default y + config ZMK_DISPLAY bool "ZMK display support" default n diff --git a/app/boards/arm/nice_nano/nice_nano.dts b/app/boards/arm/nice_nano/nice_nano.dts index 3ffb0ea8..0538b1df 100644 --- a/app/boards/arm/nice_nano/nice_nano.dts +++ b/app/boards/arm/nice_nano/nice_nano.dts @@ -29,6 +29,11 @@ }; }; + ext-power { + compatible = "zmk,ext-power-generic"; + label = "EXT_POWER"; + control-gpios = <&gpio0 13 GPIO_ACTIVE_LOW>; + }; }; &gpiote { diff --git a/app/boards/arm/nrfmicro/nrfmicro_11.dts b/app/boards/arm/nrfmicro/nrfmicro_11.dts index 95bd8adc..87c650e1 100644 --- a/app/boards/arm/nrfmicro/nrfmicro_11.dts +++ b/app/boards/arm/nrfmicro/nrfmicro_11.dts @@ -26,6 +26,11 @@ }; }; + ext-power { + compatible = "zmk,ext-power-generic"; + label = "EXT_POWER"; + control-gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>; + }; }; &gpio0 { diff --git a/app/boards/arm/nrfmicro/nrfmicro_11_flipped.dts b/app/boards/arm/nrfmicro/nrfmicro_11_flipped.dts index 85693a8b..ea15b819 100644 --- a/app/boards/arm/nrfmicro/nrfmicro_11_flipped.dts +++ b/app/boards/arm/nrfmicro/nrfmicro_11_flipped.dts @@ -26,6 +26,11 @@ }; }; + ext-power { + compatible = "zmk,ext-power-generic"; + label = "EXT_POWER"; + control-gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>; + }; }; &gpio0 { diff --git a/app/boards/arm/nrfmicro/nrfmicro_13.dts b/app/boards/arm/nrfmicro/nrfmicro_13.dts index 95bd8adc..ef439462 100644 --- a/app/boards/arm/nrfmicro/nrfmicro_13.dts +++ b/app/boards/arm/nrfmicro/nrfmicro_13.dts @@ -26,6 +26,11 @@ }; }; + ext-power { + compatible = "zmk,ext-power-generic"; + label = "EXT_POWER"; + control-gpios = <&gpio1 9 GPIO_ACTIVE_LOW>; + }; }; &gpio0 { diff --git a/app/boards/arm/nrfmicro/pinmux.c b/app/boards/arm/nrfmicro/pinmux.c index 4e330b65..30117d0f 100644 --- a/app/boards/arm/nrfmicro/pinmux.c +++ b/app/boards/arm/nrfmicro/pinmux.c @@ -14,25 +14,14 @@ static int pinmux_nrfmicro_init(struct device *port) { ARG_UNUSED(port); - struct device *p1 = device_get_binding("GPIO_1"); - #if CONFIG_BOARD_NRFMICRO_13 struct device *p0 = device_get_binding("GPIO_0"); - // enable EXT_VCC (use 0 for nRFMicro 1.3, use 1 for nRFMicro 1.1) - gpio_pin_configure(p1, 9, GPIO_OUTPUT); - gpio_pin_set(p1, 9, 0); - #if CONFIG_BOARD_NRFMICRO_CHARGER gpio_pin_configure(p0, 5, GPIO_OUTPUT); gpio_pin_set(p0, 5, 0); #else gpio_pin_configure(p0, 5, GPIO_INPUT); #endif - -#else - // enable EXT_VCC (use 0 for nRFMicro 1.3, use 1 for nRFMicro 1.1) - gpio_pin_configure(p1, 9, GPIO_OUTPUT); - gpio_pin_set(p1, 9, 1); #endif return 0; } diff --git a/app/dts/bindings/behaviors/zmk,behavior-sensor-rotate-key-press.yaml b/app/dts/bindings/behaviors/zmk,behavior-sensor-rotate-key-press.yaml index bbf35373..6b339107 100644 --- a/app/dts/bindings/behaviors/zmk,behavior-sensor-rotate-key-press.yaml +++ b/app/dts/bindings/behaviors/zmk,behavior-sensor-rotate-key-press.yaml @@ -1,4 +1,4 @@ -# Copyright (c) 2020, Pete Johanson +# Copyright (c) 2020, The ZMK Contributors # SPDX-License-Identifier: MIT description: Sensor rotate key press/release behavior diff --git a/app/dts/bindings/zmk,ext-power-generic.yaml b/app/dts/bindings/zmk,ext-power-generic.yaml new file mode 100644 index 00000000..5a38a09a --- /dev/null +++ b/app/dts/bindings/zmk,ext-power-generic.yaml @@ -0,0 +1,20 @@ +# +# Copyright (c) 2020, The ZMK Contributors +# SPDX-License-Identifier: MIT +# + +description: | + Generic driver for controlling the external power output + by toggling the control-gpio pin status + (Only in supported hardware) + +compatible: "zmk,ext-power-generic" + +properties: + control-gpios: + type: phandle-array + required: true + label: + type: string + required: true + diff --git a/app/dts/bindings/zmk,keymap-sensors.yaml b/app/dts/bindings/zmk,keymap-sensors.yaml index c56361d1..86ae5c22 100644 --- a/app/dts/bindings/zmk,keymap-sensors.yaml +++ b/app/dts/bindings/zmk,keymap-sensors.yaml @@ -1,3 +1,8 @@ +# +# Copyright (c) 2020, The ZMK Contributors +# SPDX-License-Identifier: MIT +# + description: | Allows defining the collection of sensors bound in the keymap layers diff --git a/app/include/drivers/ext_power.h b/app/include/drivers/ext_power.h new file mode 100644 index 00000000..6c1923e8 --- /dev/null +++ b/app/include/drivers/ext_power.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#pragma once + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @cond INTERNAL_HIDDEN + * + * Behavior driver API definition and system call entry points. + * + * (Internal use only.) + */ + +typedef int (*ext_power_enable_t)(struct device *dev); +typedef int (*ext_power_disable_t)(struct device *dev); +typedef int (*ext_power_get_t)(struct device *dev); + +__subsystem struct ext_power_api { + ext_power_enable_t enable; + ext_power_disable_t disable; + ext_power_get_t get; +}; +/** + * @endcond + */ + +/** + * @brief Enable the external power output + * @param dev Pointer to the device structure for the driver instance. + * + * @retval 0 If successful. + * @retval Negative errno code if failure. + */ +__syscall int ext_power_enable(struct device *dev); + +static inline int z_impl_ext_power_enable(struct device *dev) { + const struct ext_power_api *api = (const struct ext_power_api *)dev->driver_api; + + if (api->enable == NULL) { + return -ENOTSUP; + } + + return api->enable(dev); +} + +/** + * @brief Disable the external power output + * @param dev Pointer to the device structure for the driver instance. + * + * @retval 0 If successful. + * @retval Negative errno code if failure. + */ +__syscall int ext_power_disable(struct device *dev); + +static inline int z_impl_ext_power_disable(struct device *dev) { + const struct ext_power_api *api = (const struct ext_power_api *)dev->driver_api; + + if (api->disable == NULL) { + return -ENOTSUP; + } + + return api->disable(dev); +} + +/** + * @brief Get the current status of the external power output + * @param dev Pointer to the device structure for the driver instance. + * + * @retval 0 If ext power is disabled. + * @retval 1 if ext power is enabled. + * @retval Negative errno code if failure. + */ +__syscall int ext_power_get(struct device *dev); + +static inline int z_impl_ext_power_get(struct device *dev) { + const struct ext_power_api *api = (const struct ext_power_api *)dev->driver_api; + + if (api->get == NULL) { + return -ENOTSUP; + } + + return api->get(dev); +} + +#ifdef __cplusplus +} +#endif + +/** + * @} + */ + +#include diff --git a/app/src/ext_power_generic.c b/app/src/ext_power_generic.c new file mode 100644 index 00000000..48170304 --- /dev/null +++ b/app/src/ext_power_generic.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#define DT_DRV_COMPAT zmk_ext_power_generic + +#include +#include +#include +#include + +#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) + +#include +LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); + +struct ext_power_generic_config { + const char *label; + const u8_t pin; + const u8_t flags; +}; + +struct ext_power_generic_data { + struct device *gpio; + bool status; +}; + +static int ext_power_generic_enable(struct device *dev) { + struct ext_power_generic_data *data = dev->driver_data; + const struct ext_power_generic_config *config = dev->config_info; + + if (gpio_pin_set(data->gpio, config->pin, 1)) { + LOG_WRN("Failed to set ext-power control pin"); + return -EIO; + } + data->status = true; + return 0; +} + +static int ext_power_generic_disable(struct device *dev) { + struct ext_power_generic_data *data = dev->driver_data; + const struct ext_power_generic_config *config = dev->config_info; + + if (gpio_pin_set(data->gpio, config->pin, 0)) { + LOG_WRN("Failed to clear ext-power control pin"); + return -EIO; + } + data->status = false; + return 0; +} + +static int ext_power_generic_get(struct device *dev) { + struct ext_power_generic_data *data = dev->driver_data; + return data->status; +} + +static int ext_power_generic_init(struct device *dev) { + struct ext_power_generic_data *data = dev->driver_data; + const struct ext_power_generic_config *config = dev->config_info; + + data->gpio = device_get_binding(config->label); + if (data->gpio == NULL) { + LOG_ERR("Failed to get ext-power control device"); + return -EINVAL; + } + + if (gpio_pin_configure(data->gpio, config->pin, config->flags | GPIO_OUTPUT)) { + LOG_ERR("Failed to configure ext-power control pin"); + return -EIO; + } + + return 0; +} + +static const struct ext_power_generic_config config = { + .label = DT_INST_GPIO_LABEL(0, control_gpios), + .pin = DT_INST_GPIO_PIN(0, control_gpios), + .flags = DT_INST_GPIO_FLAGS(0, control_gpios)}; + +static struct ext_power_generic_data data = {.status = false}; + +static const struct ext_power_api api = {.enable = ext_power_generic_enable, + .disable = ext_power_generic_disable, + .get = ext_power_generic_get}; + +DEVICE_AND_API_INIT(ext_power_generic, DT_INST_LABEL(0), ext_power_generic_init, &data, &config, + APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &api); + +#endif /* DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) */ diff --git a/app/src/main.c b/app/src/main.c index dca923e9..0551356d 100644 --- a/app/src/main.c +++ b/app/src/main.c @@ -15,16 +15,25 @@ LOG_MODULE_REGISTER(zmk, CONFIG_ZMK_LOG_LEVEL); #include #include #include +#include #define ZMK_KSCAN_DEV DT_LABEL(ZMK_MATRIX_NODE_ID) void main(void) { + struct device *ext_power; LOG_INF("Welcome to ZMK!\n"); if (zmk_kscan_init(ZMK_KSCAN_DEV) != 0) { return; } + // Enable the external VCC output + ext_power = device_get_binding("EXT_POWER"); + if (ext_power != NULL) { + const struct ext_power_api *ext_power_api = ext_power->driver_api; + ext_power_api->enable(ext_power); + } + #ifdef CONFIG_ZMK_DISPLAY zmk_display_init(); From 9231f6c57beb6bfabc030f9debcb659dd964634e Mon Sep 17 00:00:00 2001 From: Idan Gazit Date: Thu, 24 Sep 2020 09:52:00 -0700 Subject: [PATCH 51/61] Add VSCode devcontainer configuration --- .devcontainer/Dockerfile | 1 + .devcontainer/devcontainer.json | 6 ++++++ 2 files changed, 7 insertions(+) create mode 100644 .devcontainer/Dockerfile create mode 100644 .devcontainer/devcontainer.json diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 00000000..ba4e1223 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1 @@ +FROM zmkfirmware/zephyr-west-action-arm \ No newline at end of file diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 00000000..74505346 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,6 @@ +{ + "name": "ZMK Development", + "dockerFile": "Dockerfile", + "extensions": ["ms-vscode.cpptools"] +} + From 5bd09b586e153185850fe468b19fdd0eb534f35d Mon Sep 17 00:00:00 2001 From: Idan Gazit Date: Wed, 30 Sep 2020 23:23:42 -0700 Subject: [PATCH 52/61] Remove Dockerfile in favor of image Per the docs, we can directly specify an image in devcontainer.json: https://code.visualstudio.com/docs/remote/devcontainerjson-reference --- .devcontainer/Dockerfile | 1 - .devcontainer/devcontainer.json | 5 +++-- 2 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 .devcontainer/Dockerfile diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile deleted file mode 100644 index ba4e1223..00000000 --- a/.devcontainer/Dockerfile +++ /dev/null @@ -1 +0,0 @@ -FROM zmkfirmware/zephyr-west-action-arm \ No newline at end of file diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 74505346..bbf44bc7 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,6 +1,7 @@ { "name": "ZMK Development", - "dockerFile": "Dockerfile", - "extensions": ["ms-vscode.cpptools"] + "image": "zmkfirmware/zephyr-west-action-arm", + "extensions": ["ms-vscode.cpptools"], + "runArgs": ["--security-opt", "label=disable"] } From 9b29f9b861464a8a0eba78f25058cded118b84d5 Mon Sep 17 00:00:00 2001 From: Idan Gazit Date: Thu, 1 Oct 2020 06:52:33 +0000 Subject: [PATCH 53/61] Install SSH and GPG into container Brings back the dockerfile so we can install SSH and GPG into it. This fixes git actions with SSH remotes, and GPG signing now works out of the box. This commit was made from inside the container! --- .devcontainer/Dockerfile | 8 ++++++++ .devcontainer/devcontainer.json | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 .devcontainer/Dockerfile diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 00000000..abbe54ac --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,8 @@ +from zmkfirmware/zephyr-west-action-arm + +RUN apt-get -y update && \ + apt-get -y upgrade && \ + apt-get install --no-install-recommends -y \ + ssh \ + gpg && \ + rm -rf /var/lib/apt/lists/* \ No newline at end of file diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index bbf44bc7..f21465df 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,6 +1,6 @@ { "name": "ZMK Development", - "image": "zmkfirmware/zephyr-west-action-arm", + "dockerFile": "Dockerfile", "extensions": ["ms-vscode.cpptools"], "runArgs": ["--security-opt", "label=disable"] } From 42d1915ced3f7ec8a74cf5be506438d2bf07a7d3 Mon Sep 17 00:00:00 2001 From: Idan Gazit Date: Thu, 1 Oct 2020 06:56:18 +0000 Subject: [PATCH 54/61] Use spaces, not tabs --- .devcontainer/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index abbe54ac..cf62b5a3 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,7 +1,7 @@ from zmkfirmware/zephyr-west-action-arm RUN apt-get -y update && \ - apt-get -y upgrade && \ + apt-get -y upgrade && \ apt-get install --no-install-recommends -y \ ssh \ gpg && \ From 15614a946fac635a27ba94a4f32450c67016e5b2 Mon Sep 17 00:00:00 2001 From: Idan Gazit Date: Thu, 1 Oct 2020 00:41:33 -0700 Subject: [PATCH 55/61] WIP docs for docker development --- docs/docs/dev-setup.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/docs/docs/dev-setup.md b/docs/docs/dev-setup.md index 4891f5af..be3d6f95 100644 --- a/docs/docs/dev-setup.md +++ b/docs/docs/dev-setup.md @@ -16,6 +16,7 @@ values={[ {label: 'macOS', value: 'mac'}, {label: 'Raspberry OS', value: 'raspberryos'}, {label: 'Fedora', value: 'fedora'}, +{label: 'VS Code & Docker', value: 'docker'}, ] }>{props.children}); @@ -178,6 +179,20 @@ Homebrew is required to install the system dependencies. If you haven't done so, brew install cmake ninja python3 ccache dtc git wget ``` + + + +This setup leverages the same [image which is used by the GitHub action](https://github.com/zmkfirmware/zephyr-west-action) for local development. Beyond the benefits of [dev/prod parity](https://12factor.net/dev-prod-parity), this approach is also the easiest to set up. No toolchain or dependencies are necessary when using Docker; the container image you'll be using already has the toolchain installed and set up to use. + + +1. Install [Docker Desktop](https://www.docker.com/products/docker-desktop) for your operating system. +2. Install [VS Code](https://code.visualstudio.com/) +3. Install the [Remote - Containers extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) + +:::info +The docker container includes `west` and the compilation toolchain. If you're using docker and VS Code, you can skip right to [Source Code](#source-code). +::: +
@@ -323,6 +338,11 @@ Please be sure to read the [additional setup instructions](https://docs.zephyrpr ::: + + + +You're already set up: the toolchain is installed and configured inside the docker container. + From 63931a706870652e649346e4052a9fb1b105ff5b Mon Sep 17 00:00:00 2001 From: Idan Gazit Date: Tue, 6 Oct 2020 08:51:25 -0700 Subject: [PATCH 56/61] Accept suggestions Co-authored-by: Pete Johanson --- .devcontainer/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index cf62b5a3..160b1481 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,8 +1,8 @@ -from zmkfirmware/zephyr-west-action-arm +FROM zmkfirmware/zephyr-west-action-arm RUN apt-get -y update && \ apt-get -y upgrade && \ apt-get install --no-install-recommends -y \ ssh \ gpg && \ - rm -rf /var/lib/apt/lists/* \ No newline at end of file + rm -rf /var/lib/apt/lists/* From db40fbad598b6f84472cb2921df89f1a46fc6b5c Mon Sep 17 00:00:00 2001 From: Idan Gazit Date: Fri, 9 Oct 2020 17:49:42 -0700 Subject: [PATCH 57/61] Conditionally source zephyr-env.sh in .bashrc --- .devcontainer/.bashrc | 6 ++++++ .devcontainer/Dockerfile | 3 +++ 2 files changed, 9 insertions(+) create mode 100644 .devcontainer/.bashrc diff --git a/.devcontainer/.bashrc b/.devcontainer/.bashrc new file mode 100644 index 00000000..6a6ea691 --- /dev/null +++ b/.devcontainer/.bashrc @@ -0,0 +1,6 @@ +export LS_OPTIONS='-F --color=auto' +eval "`dircolors`" +alias ls='ls $LS_OPTIONS' +if [ -f /workspaces/zmk/zephyr/zephyr-env.sh ]; then + source /workspaces/zmk/zephyr/zephyr-env.sh +fi diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 160b1481..184aae9a 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -6,3 +6,6 @@ RUN apt-get -y update && \ ssh \ gpg && \ rm -rf /var/lib/apt/lists/* + +COPY .bashrc tmp +RUN mv /tmp/.bashrc ~/.bashrc From 63ad5b7c089f13a5b5d5514514cc9ad7e798d3e8 Mon Sep 17 00:00:00 2001 From: Idan Gazit Date: Sat, 10 Oct 2020 01:42:50 +0000 Subject: [PATCH 58/61] Inject $WORKSPACE_DIR into container This permits users to check ZMK out into arbitrarily-named directories --- .devcontainer/.bashrc | 4 ++-- .devcontainer/devcontainer.json | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.devcontainer/.bashrc b/.devcontainer/.bashrc index 6a6ea691..855ea755 100644 --- a/.devcontainer/.bashrc +++ b/.devcontainer/.bashrc @@ -1,6 +1,6 @@ export LS_OPTIONS='-F --color=auto' eval "`dircolors`" alias ls='ls $LS_OPTIONS' -if [ -f /workspaces/zmk/zephyr/zephyr-env.sh ]; then - source /workspaces/zmk/zephyr/zephyr-env.sh +if [ -f "$WORKSPACE_DIR/zephyr/zephyr-env.sh" ]; then + source "$WORKSPACE_DIR/zephyr/zephyr-env.sh" fi diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index f21465df..940b78b8 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -2,6 +2,7 @@ "name": "ZMK Development", "dockerFile": "Dockerfile", "extensions": ["ms-vscode.cpptools"], - "runArgs": ["--security-opt", "label=disable"] + "runArgs": ["--security-opt", "label=disable"], + "containerEnv": {"WORKSPACE_DIR": "${containerWorkspaceFolder}"} } From 5c00c97e9a1647e2676586c303d19c5559e2e2f1 Mon Sep 17 00:00:00 2001 From: Idan Gazit Date: Fri, 9 Oct 2020 18:48:41 -0700 Subject: [PATCH 59/61] Wrap up documentation --- .../assets/dev-setup/vscode_devcontainer.png | Bin 0 -> 20773 bytes docs/docs/dev-setup.md | 62 ++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 docs/docs/assets/dev-setup/vscode_devcontainer.png diff --git a/docs/docs/assets/dev-setup/vscode_devcontainer.png b/docs/docs/assets/dev-setup/vscode_devcontainer.png new file mode 100644 index 0000000000000000000000000000000000000000..e5c22b0ac4f8080f47725e570a6bdca990470627 GIT binary patch literal 20773 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 literal 0 HcmV?d00001 diff --git a/docs/docs/dev-setup.md b/docs/docs/dev-setup.md index be3d6f95..6ef0f020 100644 --- a/docs/docs/dev-setup.md +++ b/docs/docs/dev-setup.md @@ -369,12 +369,63 @@ Since ZMK is built as a Zephyr™ application, the next step is to use `west` to initialize and update your workspace. The ZMK Zephyr™ application is in the `app/` source directory: + #### Step into the repository + + + +```sh +cd zmk +``` + + + + +```sh +cd zmk +``` + + + + +```sh +cd zmk +``` + + + + +```sh +cd zmk +``` + + + + ```sh cd zmk ``` + + + + +Open the `zmk` checkout folder in VS Code. The repository includes a configuration for containerized development, so an alert will pop up: + +![VS Code Dev Container Configuration Alert](assets/dev-setup/vscode_devcontainer.png) + +Click `Reopen in Container` in order to reopen the VS Code with the running container. + +The first time you do this on your machine, it will pull the docker image down from the registry and build the container. Subsequent launches are much faster! + +:::caution +All subsequent steps must be performed from the VS Code terminal _inside_ the container. +::: + + + + #### Initialize West ```sh @@ -393,6 +444,17 @@ section again for links to how to do this west update ``` +:::tip +This step pulls down quite a bit of tooling. Go grab a cup of coffee, it can take 10-15 minutes even on a good internet connection! +::: + +:::info +If you're using Docker, you're done with setup! You must restart the container at this point. The easiest way to do so is to close the VS Code window, verify that the container has stopped in Docker Dashboard, and reopen the container with VS Code. + +Once your container is restarted, proceed to [Building and Flashing](./dev-build.md). +::: + + #### Export Zephyr™ Core ```sh From 5401afc002ba086ca964aa7a164fbc6dbd1898b1 Mon Sep 17 00:00:00 2001 From: Idan Gazit Date: Fri, 9 Oct 2020 19:10:07 -0700 Subject: [PATCH 60/61] Skip toolchain for docker --- docs/docs/dev-setup.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/docs/docs/dev-setup.md b/docs/docs/dev-setup.md index 6ef0f020..114fe0b3 100644 --- a/docs/docs/dev-setup.md +++ b/docs/docs/dev-setup.md @@ -338,11 +338,6 @@ Please be sure to read the [additional setup instructions](https://docs.zephyrpr ::: - - - -You're already set up: the toolchain is installed and configured inside the docker container. - From fc6c01fd6941ec795710d66ead9e17d5dfbaa19d Mon Sep 17 00:00:00 2001 From: Kurtis Lew Date: Fri, 9 Oct 2020 20:56:52 -0700 Subject: [PATCH 61/61] -DZMK_CONFIG Documentation (#255) feat(docs): `-DZMK_CONFIG` Documentation --- docs/docs/dev-build.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docs/docs/dev-build.md b/docs/docs/dev-build.md index 816468e2..83ed8cb9 100644 --- a/docs/docs/dev-build.md +++ b/docs/docs/dev-build.md @@ -84,6 +84,19 @@ west build -d build/right -b nice_nano -- -DSHIELD=kyria_right ``` This produces `left` and `right` subfolders under the `build` directory and two separate .uf2 files. For future work on a specific half, use the `-d` parameter again to ensure you are building into the correct location. +### Building from `zmk-config` Folder + +Instead of building .uf2 files using the default keymap and config files, you can build directly from your [`zmk-config` folder](user-setup#github-repo) by adding +`-DZMK_CONFIG="C:/the/absolute/path/config"` to your `west build` command. **Notice that this path should point to the folder labelled `config` within your `zmk-config` folder.** + + +For instance, building kyria firmware from a user `myUser`'s `zmk-config` folder on Windows 10 may look something like this: + +``` +west build -b nice_nano -- -DSHIELD=kyria_left -DZMK_CONFIG="C:/Users/myUser/Documents/Github/zmk-config/config" +``` + + ## Flashing Once built, the previously supplied parameters will be remembered so you can run the following to flash your