Merge branch 'main' into advantage360
This commit is contained in:
commit
6a4f0bfe65
10 changed files with 200 additions and 101 deletions
|
@ -5,6 +5,7 @@ zephyr_library_named(zmk__drivers__kscan)
|
|||
zephyr_library_include_directories(${CMAKE_SOURCE_DIR}/include)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_ZMK_KSCAN_GPIO_DRIVER debounce.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_ZMK_KSCAN_GPIO_DRIVER kscan_gpio.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_ZMK_KSCAN_GPIO_MATRIX kscan_gpio_matrix.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_ZMK_KSCAN_GPIO_DIRECT kscan_gpio_direct.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_ZMK_KSCAN_GPIO_DEMUX kscan_gpio_demux.c)
|
||||
|
|
33
app/drivers/kscan/kscan_gpio.c
Normal file
33
app/drivers/kscan/kscan_gpio.c
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright (c) 2022 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include "kscan_gpio.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
static int compare_ports(const void *a, const void *b) {
|
||||
const struct kscan_gpio *gpio_a = a;
|
||||
const struct kscan_gpio *gpio_b = b;
|
||||
|
||||
return gpio_a->spec.port - gpio_b->spec.port;
|
||||
}
|
||||
|
||||
void kscan_gpio_list_sort_by_port(struct kscan_gpio_list *list) {
|
||||
qsort(list->gpios, list->len, sizeof(list->gpios[0]), compare_ports);
|
||||
}
|
||||
|
||||
int kscan_gpio_pin_get(const struct kscan_gpio *gpio, struct kscan_gpio_port_state *state) {
|
||||
if (gpio->spec.port != state->port) {
|
||||
state->port = gpio->spec.port;
|
||||
|
||||
const int err = gpio_port_get(state->port, &state->value);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return (state->value & BIT(gpio->spec.pin)) != 0;
|
||||
}
|
61
app/drivers/kscan/kscan_gpio.h
Normal file
61
app/drivers/kscan/kscan_gpio.h
Normal file
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright (c) 2022 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/drivers/gpio.h>
|
||||
#include <zephyr/dt-bindings/gpio/gpio.h>
|
||||
#include <zephyr/sys/util.h>
|
||||
|
||||
struct kscan_gpio {
|
||||
struct gpio_dt_spec spec;
|
||||
/** The index of the GPIO in the devicetree *-gpios array. */
|
||||
size_t index;
|
||||
};
|
||||
|
||||
/** GPIO_DT_SPEC_GET_BY_IDX(), but for a struct kscan_gpio. */
|
||||
#define KSCAN_GPIO_GET_BY_IDX(node_id, prop, idx) \
|
||||
((struct kscan_gpio){.spec = GPIO_DT_SPEC_GET_BY_IDX(node_id, prop, idx), .index = idx})
|
||||
|
||||
struct kscan_gpio_list {
|
||||
struct kscan_gpio *gpios;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
/** Define a kscan_gpio_list from a compile-time GPIO array. */
|
||||
#define KSCAN_GPIO_LIST(gpio_array) \
|
||||
((struct kscan_gpio_list){.gpios = gpio_array, .len = ARRAY_SIZE(gpio_array)})
|
||||
|
||||
struct kscan_gpio_port_state {
|
||||
const struct device *port;
|
||||
gpio_port_value_t value;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sorts a GPIO list by port so it can be used with kscan_gpio_pin_get().
|
||||
*/
|
||||
void kscan_gpio_list_sort_by_port(struct kscan_gpio_list *list);
|
||||
|
||||
/**
|
||||
* Get logical level of an input pin.
|
||||
*
|
||||
* This is equivalent to gpio_pin_get() except that, when iterating through the
|
||||
* pins in a list which is sorted by kscan_gpio_list_sort_by_port(), it only
|
||||
* performs one read per port instead of one read per pin.
|
||||
*
|
||||
* @param gpio The input pin to read.
|
||||
* @param state An object to track state between reads. Must be zero-initialized before the first
|
||||
* use.
|
||||
*
|
||||
* @retval 1 If pin logical value is 1 / active.
|
||||
* @retval 0 If pin logical value is 0 / inactive.
|
||||
* @retval -EIO I/O error when accessing an external GPIO chip.
|
||||
* @retval -EWOULDBLOCK if operation would block.
|
||||
*/
|
||||
int kscan_gpio_pin_get(const struct kscan_gpio *gpio, struct kscan_gpio_port_state *state);
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
#include "debounce.h"
|
||||
#include "kscan_gpio.h"
|
||||
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/devicetree.h>
|
||||
|
@ -41,7 +42,7 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
|||
|
||||
#define INST_INPUTS_LEN(n) DT_INST_PROP_LEN(n, input_gpios)
|
||||
#define KSCAN_DIRECT_INPUT_CFG_INIT(idx, inst_idx) \
|
||||
GPIO_DT_SPEC_GET_BY_IDX(DT_DRV_INST(inst_idx), input_gpios, idx)
|
||||
KSCAN_GPIO_GET_BY_IDX(DT_DRV_INST(inst_idx), input_gpios, idx)
|
||||
|
||||
struct kscan_direct_irq_callback {
|
||||
const struct device *dev;
|
||||
|
@ -50,6 +51,7 @@ struct kscan_direct_irq_callback {
|
|||
|
||||
struct kscan_direct_data {
|
||||
const struct device *dev;
|
||||
struct kscan_gpio_list inputs;
|
||||
kscan_callback_t callback;
|
||||
struct k_work_delayable work;
|
||||
#if USE_INTERRUPTS
|
||||
|
@ -62,17 +64,7 @@ struct kscan_direct_data {
|
|||
struct debounce_state *pin_state;
|
||||
};
|
||||
|
||||
struct kscan_gpio_list {
|
||||
const struct gpio_dt_spec *gpios;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
/** Define a kscan_gpio_list from a compile-time GPIO array. */
|
||||
#define KSCAN_GPIO_LIST(gpio_array) \
|
||||
((struct kscan_gpio_list){.gpios = gpio_array, .len = ARRAY_SIZE(gpio_array)})
|
||||
|
||||
struct kscan_direct_config {
|
||||
struct kscan_gpio_list inputs;
|
||||
struct debounce_config debounce_config;
|
||||
int32_t debounce_scan_period_ms;
|
||||
int32_t poll_period_ms;
|
||||
|
@ -81,10 +73,10 @@ struct kscan_direct_config {
|
|||
|
||||
#if USE_INTERRUPTS
|
||||
static int kscan_direct_interrupt_configure(const struct device *dev, const gpio_flags_t flags) {
|
||||
const struct kscan_direct_config *config = dev->config;
|
||||
const struct kscan_direct_data *data = dev->data;
|
||||
|
||||
for (int i = 0; i < config->inputs.len; i++) {
|
||||
const struct gpio_dt_spec *gpio = &config->inputs.gpios[i];
|
||||
for (int i = 0; i < data->inputs.len; i++) {
|
||||
const struct gpio_dt_spec *gpio = &data->inputs.gpios[i].spec;
|
||||
|
||||
int err = gpio_pin_interrupt_configure_dt(gpio, flags);
|
||||
if (err) {
|
||||
|
@ -134,16 +126,16 @@ static gpio_flags_t kscan_gpio_get_extra_flags(const struct gpio_dt_spec *gpio,
|
|||
|
||||
static int kscan_inputs_set_flags(const struct kscan_gpio_list *inputs,
|
||||
const struct gpio_dt_spec *active_gpio) {
|
||||
gpio_flags_t extra_flags;
|
||||
for (int i = 0; i < inputs->len; i++) {
|
||||
extra_flags = GPIO_INPUT | kscan_gpio_get_extra_flags(&inputs->gpios[i],
|
||||
&inputs->gpios[i] == active_gpio);
|
||||
const bool active = &inputs->gpios[i].spec == active_gpio;
|
||||
const gpio_flags_t extra_flags =
|
||||
GPIO_INPUT | kscan_gpio_get_extra_flags(&inputs->gpios[i].spec, active);
|
||||
LOG_DBG("Extra flags equal to: %d", extra_flags);
|
||||
|
||||
int err = gpio_pin_configure_dt(&inputs->gpios[i], extra_flags);
|
||||
int err = gpio_pin_configure_dt(&inputs->gpios[i].spec, extra_flags);
|
||||
if (err) {
|
||||
LOG_ERR("Unable to configure flags on pin %d on %s", inputs->gpios[i].pin,
|
||||
inputs->gpios[i].port->name);
|
||||
LOG_ERR("Unable to configure flags on pin %d on %s", inputs->gpios[i].spec.pin,
|
||||
inputs->gpios[i].spec.port->name);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
@ -179,28 +171,35 @@ static int kscan_direct_read(const struct device *dev) {
|
|||
const struct kscan_direct_config *config = dev->config;
|
||||
|
||||
// Read the inputs.
|
||||
for (int i = 0; i < config->inputs.len; i++) {
|
||||
const struct gpio_dt_spec *gpio = &config->inputs.gpios[i];
|
||||
struct kscan_gpio_port_state state = {0};
|
||||
|
||||
const bool active = gpio_pin_get_dt(gpio);
|
||||
for (int i = 0; i < data->inputs.len; i++) {
|
||||
const struct kscan_gpio *gpio = &data->inputs.gpios[i];
|
||||
|
||||
debounce_update(&data->pin_state[i], active, config->debounce_scan_period_ms,
|
||||
const int active = kscan_gpio_pin_get(gpio, &state);
|
||||
if (active < 0) {
|
||||
LOG_ERR("Failed to read port %s: %i", gpio->spec.port->name, active);
|
||||
return active;
|
||||
}
|
||||
|
||||
debounce_update(&data->pin_state[gpio->index], active, config->debounce_scan_period_ms,
|
||||
&config->debounce_config);
|
||||
}
|
||||
|
||||
// Process the new state.
|
||||
bool continue_scan = false;
|
||||
|
||||
for (int i = 0; i < config->inputs.len; i++) {
|
||||
struct debounce_state *state = &data->pin_state[i];
|
||||
for (int i = 0; i < data->inputs.len; i++) {
|
||||
const struct kscan_gpio *gpio = &data->inputs.gpios[i];
|
||||
struct debounce_state *state = &data->pin_state[gpio->index];
|
||||
|
||||
if (debounce_get_changed(state)) {
|
||||
const bool pressed = debounce_is_pressed(state);
|
||||
|
||||
LOG_DBG("Sending event at 0,%i state %s", i, pressed ? "on" : "off");
|
||||
data->callback(dev, 0, i, pressed);
|
||||
LOG_DBG("Sending event at 0,%i state %s", gpio->index, pressed ? "on" : "off");
|
||||
data->callback(dev, 0, gpio->index, pressed);
|
||||
if (config->toggle_mode && pressed) {
|
||||
kscan_inputs_set_flags(&config->inputs, &config->inputs.gpios[i]);
|
||||
kscan_inputs_set_flags(&data->inputs, &gpio->spec);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -289,10 +288,11 @@ static int kscan_direct_init_input_inst(const struct device *dev, const struct g
|
|||
}
|
||||
|
||||
static int kscan_direct_init_inputs(const struct device *dev) {
|
||||
const struct kscan_direct_data *data = dev->data;
|
||||
const struct kscan_direct_config *config = dev->config;
|
||||
|
||||
for (int i = 0; i < config->inputs.len; i++) {
|
||||
const struct gpio_dt_spec *gpio = &config->inputs.gpios[i];
|
||||
for (int i = 0; i < data->inputs.len; i++) {
|
||||
const struct gpio_dt_spec *gpio = &data->inputs.gpios[i].spec;
|
||||
int err = kscan_direct_init_input_inst(dev, gpio, i, config->toggle_mode);
|
||||
if (err) {
|
||||
return err;
|
||||
|
@ -307,6 +307,9 @@ static int kscan_direct_init(const struct device *dev) {
|
|||
|
||||
data->dev = dev;
|
||||
|
||||
// Sort inputs by port so we can read each port just once per scan.
|
||||
kscan_gpio_list_sort_by_port(&data->inputs);
|
||||
|
||||
kscan_direct_init_inputs(dev);
|
||||
|
||||
k_work_init_delayable(&data->work, kscan_direct_work_handler);
|
||||
|
@ -326,7 +329,7 @@ static const struct kscan_driver_api kscan_direct_api = {
|
|||
BUILD_ASSERT(INST_DEBOUNCE_RELEASE_MS(n) <= DEBOUNCE_COUNTER_MAX, \
|
||||
"ZMK_KSCAN_DEBOUNCE_RELEASE_MS or debounce-release-ms is too large"); \
|
||||
\
|
||||
static const struct gpio_dt_spec kscan_direct_inputs_##n[] = { \
|
||||
static struct kscan_gpio kscan_direct_inputs_##n[] = { \
|
||||
LISTIFY(INST_INPUTS_LEN(n), KSCAN_DIRECT_INPUT_CFG_INIT, (, ), n)}; \
|
||||
\
|
||||
static struct debounce_state kscan_direct_state_##n[INST_INPUTS_LEN(n)]; \
|
||||
|
@ -335,10 +338,11 @@ static const struct kscan_driver_api kscan_direct_api = {
|
|||
(static struct kscan_direct_irq_callback kscan_direct_irqs_##n[INST_INPUTS_LEN(n)];)) \
|
||||
\
|
||||
static struct kscan_direct_data kscan_direct_data_##n = { \
|
||||
.pin_state = kscan_direct_state_##n, COND_INTERRUPTS((.irqs = kscan_direct_irqs_##n, ))}; \
|
||||
.inputs = KSCAN_GPIO_LIST(kscan_direct_inputs_##n), \
|
||||
.pin_state = kscan_direct_state_##n, \
|
||||
COND_INTERRUPTS((.irqs = kscan_direct_irqs_##n, ))}; \
|
||||
\
|
||||
static struct kscan_direct_config kscan_direct_config_##n = { \
|
||||
.inputs = KSCAN_GPIO_LIST(kscan_direct_inputs_##n), \
|
||||
.debounce_config = \
|
||||
{ \
|
||||
.debounce_press_ms = INST_DEBOUNCE_PRESS_MS(n), \
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
#include "debounce.h"
|
||||
#include "kscan_gpio.h"
|
||||
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/devicetree.h>
|
||||
|
@ -50,9 +51,9 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
|||
COND_CODE_1(CONFIG_ZMK_KSCAN_MATRIX_POLLING, pollcode, intcode)
|
||||
|
||||
#define KSCAN_GPIO_ROW_CFG_INIT(idx, inst_idx) \
|
||||
GPIO_DT_SPEC_GET_BY_IDX(DT_DRV_INST(inst_idx), row_gpios, idx)
|
||||
KSCAN_GPIO_GET_BY_IDX(DT_DRV_INST(inst_idx), row_gpios, idx)
|
||||
#define KSCAN_GPIO_COL_CFG_INIT(idx, inst_idx) \
|
||||
GPIO_DT_SPEC_GET_BY_IDX(DT_DRV_INST(inst_idx), col_gpios, idx)
|
||||
KSCAN_GPIO_GET_BY_IDX(DT_DRV_INST(inst_idx), col_gpios, idx)
|
||||
|
||||
enum kscan_diode_direction {
|
||||
KSCAN_ROW2COL,
|
||||
|
@ -66,6 +67,7 @@ struct kscan_matrix_irq_callback {
|
|||
|
||||
struct kscan_matrix_data {
|
||||
const struct device *dev;
|
||||
struct kscan_gpio_list inputs;
|
||||
kscan_callback_t callback;
|
||||
struct k_work_delayable work;
|
||||
#if USE_INTERRUPTS
|
||||
|
@ -76,26 +78,16 @@ struct kscan_matrix_data {
|
|||
int64_t scan_time;
|
||||
/**
|
||||
* Current state of the matrix as a flattened 2D array of length
|
||||
* (config->rows.len * config->cols.len)
|
||||
* (config->rows * config->cols)
|
||||
*/
|
||||
struct debounce_state *matrix_state;
|
||||
};
|
||||
|
||||
struct kscan_gpio_list {
|
||||
const struct gpio_dt_spec *gpios;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
/** Define a kscan_gpio_list from a compile-time GPIO array. */
|
||||
#define KSCAN_GPIO_LIST(gpio_array) \
|
||||
((struct kscan_gpio_list){.gpios = gpio_array, .len = ARRAY_SIZE(gpio_array)})
|
||||
|
||||
struct kscan_matrix_config {
|
||||
struct kscan_gpio_list rows;
|
||||
struct kscan_gpio_list cols;
|
||||
struct kscan_gpio_list inputs;
|
||||
struct kscan_gpio_list outputs;
|
||||
struct debounce_config debounce_config;
|
||||
size_t rows;
|
||||
size_t cols;
|
||||
int32_t debounce_scan_period_ms;
|
||||
int32_t poll_period_ms;
|
||||
enum kscan_diode_direction diode_direction;
|
||||
|
@ -105,10 +97,10 @@ struct kscan_matrix_config {
|
|||
* Get the index into a matrix state array from a row and column.
|
||||
*/
|
||||
static int state_index_rc(const struct kscan_matrix_config *config, const int row, const int col) {
|
||||
__ASSERT(row < config->rows.len, "Invalid row %i", row);
|
||||
__ASSERT(col < config->cols.len, "Invalid column %i", col);
|
||||
__ASSERT(row < config->rows, "Invalid row %i", row);
|
||||
__ASSERT(col < config->cols, "Invalid column %i", col);
|
||||
|
||||
return (col * config->rows.len) + row;
|
||||
return (col * config->rows) + row;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -125,7 +117,7 @@ static int kscan_matrix_set_all_outputs(const struct device *dev, const int valu
|
|||
const struct kscan_matrix_config *config = dev->config;
|
||||
|
||||
for (int i = 0; i < config->outputs.len; i++) {
|
||||
const struct gpio_dt_spec *gpio = &config->outputs.gpios[i];
|
||||
const struct gpio_dt_spec *gpio = &config->outputs.gpios[i].spec;
|
||||
|
||||
int err = gpio_pin_set_dt(gpio, value);
|
||||
if (err) {
|
||||
|
@ -139,10 +131,10 @@ static int kscan_matrix_set_all_outputs(const struct device *dev, const int valu
|
|||
|
||||
#if USE_INTERRUPTS
|
||||
static int kscan_matrix_interrupt_configure(const struct device *dev, const gpio_flags_t flags) {
|
||||
const struct kscan_matrix_config *config = dev->config;
|
||||
const struct kscan_matrix_data *data = dev->data;
|
||||
|
||||
for (int i = 0; i < config->inputs.len; i++) {
|
||||
const struct gpio_dt_spec *gpio = &config->inputs.gpios[i];
|
||||
for (int i = 0; i < data->inputs.len; i++) {
|
||||
const struct gpio_dt_spec *gpio = &data->inputs.gpios[i].spec;
|
||||
|
||||
int err = gpio_pin_interrupt_configure_dt(gpio, flags);
|
||||
if (err) {
|
||||
|
@ -226,32 +218,37 @@ static int kscan_matrix_read(const struct device *dev) {
|
|||
const struct kscan_matrix_config *config = dev->config;
|
||||
|
||||
// Scan the matrix.
|
||||
for (int o = 0; o < config->outputs.len; o++) {
|
||||
const struct gpio_dt_spec *out_gpio = &config->outputs.gpios[o];
|
||||
for (int i = 0; i < config->outputs.len; i++) {
|
||||
const struct kscan_gpio *out_gpio = &config->outputs.gpios[i];
|
||||
|
||||
int err = gpio_pin_set_dt(out_gpio, 1);
|
||||
int err = gpio_pin_set_dt(&out_gpio->spec, 1);
|
||||
if (err) {
|
||||
LOG_ERR("Failed to set output %i active: %i", o, err);
|
||||
LOG_ERR("Failed to set output %i active: %i", out_gpio->index, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
#if CONFIG_ZMK_KSCAN_MATRIX_WAIT_BEFORE_INPUTS > 0
|
||||
k_busy_wait(CONFIG_ZMK_KSCAN_MATRIX_WAIT_BEFORE_INPUTS);
|
||||
#endif
|
||||
struct kscan_gpio_port_state state = {0};
|
||||
|
||||
for (int i = 0; i < config->inputs.len; i++) {
|
||||
const struct gpio_dt_spec *in_gpio = &config->inputs.gpios[i];
|
||||
for (int j = 0; j < data->inputs.len; j++) {
|
||||
const struct kscan_gpio *in_gpio = &data->inputs.gpios[j];
|
||||
|
||||
const int index = state_index_io(config, i, o);
|
||||
const bool active = gpio_pin_get_dt(in_gpio);
|
||||
const int index = state_index_io(config, in_gpio->index, out_gpio->index);
|
||||
const int active = kscan_gpio_pin_get(in_gpio, &state);
|
||||
if (active < 0) {
|
||||
LOG_ERR("Failed to read port %s: %i", in_gpio->spec.port->name, active);
|
||||
return active;
|
||||
}
|
||||
|
||||
debounce_update(&data->matrix_state[index], active, config->debounce_scan_period_ms,
|
||||
&config->debounce_config);
|
||||
}
|
||||
|
||||
err = gpio_pin_set_dt(out_gpio, 0);
|
||||
err = gpio_pin_set_dt(&out_gpio->spec, 0);
|
||||
if (err) {
|
||||
LOG_ERR("Failed to set output %i inactive: %i", o, err);
|
||||
LOG_ERR("Failed to set output %i inactive: %i", out_gpio->index, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -263,8 +260,8 @@ static int kscan_matrix_read(const struct device *dev) {
|
|||
// Process the new state.
|
||||
bool continue_scan = false;
|
||||
|
||||
for (int r = 0; r < config->rows.len; r++) {
|
||||
for (int c = 0; c < config->cols.len; c++) {
|
||||
for (int r = 0; r < config->rows; r++) {
|
||||
for (int c = 0; c < config->cols; c++) {
|
||||
const int index = state_index_rc(config, r, c);
|
||||
struct debounce_state *state = &data->matrix_state[index];
|
||||
|
||||
|
@ -329,28 +326,28 @@ static int kscan_matrix_disable(const struct device *dev) {
|
|||
#endif
|
||||
}
|
||||
|
||||
static int kscan_matrix_init_input_inst(const struct device *dev, const struct gpio_dt_spec *gpio,
|
||||
const int index) {
|
||||
if (!device_is_ready(gpio->port)) {
|
||||
LOG_ERR("GPIO is not ready: %s", gpio->port->name);
|
||||
static int kscan_matrix_init_input_inst(const struct device *dev, const struct kscan_gpio *gpio) {
|
||||
if (!device_is_ready(gpio->spec.port)) {
|
||||
LOG_ERR("GPIO is not ready: %s", gpio->spec.port->name);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
int err = gpio_pin_configure_dt(gpio, GPIO_INPUT);
|
||||
int err = gpio_pin_configure_dt(&gpio->spec, GPIO_INPUT);
|
||||
if (err) {
|
||||
LOG_ERR("Unable to configure pin %u on %s for input", gpio->pin, gpio->port->name);
|
||||
LOG_ERR("Unable to configure pin %u on %s for input", gpio->spec.pin,
|
||||
gpio->spec.port->name);
|
||||
return err;
|
||||
}
|
||||
|
||||
LOG_DBG("Configured pin %u on %s for input", gpio->pin, gpio->port->name);
|
||||
LOG_DBG("Configured pin %u on %s for input", gpio->spec.pin, gpio->spec.port->name);
|
||||
|
||||
#if USE_INTERRUPTS
|
||||
struct kscan_matrix_data *data = dev->data;
|
||||
struct kscan_matrix_irq_callback *irq = &data->irqs[index];
|
||||
struct kscan_matrix_irq_callback *irq = &data->irqs[gpio->index];
|
||||
|
||||
irq->dev = dev;
|
||||
gpio_init_callback(&irq->callback, kscan_matrix_irq_callback_handler, BIT(gpio->pin));
|
||||
err = gpio_add_callback(gpio->port, &irq->callback);
|
||||
gpio_init_callback(&irq->callback, kscan_matrix_irq_callback_handler, BIT(gpio->spec.pin));
|
||||
err = gpio_add_callback(gpio->spec.port, &irq->callback);
|
||||
if (err) {
|
||||
LOG_ERR("Error adding the callback to the input device: %i", err);
|
||||
return err;
|
||||
|
@ -361,11 +358,11 @@ static int kscan_matrix_init_input_inst(const struct device *dev, const struct g
|
|||
}
|
||||
|
||||
static int kscan_matrix_init_inputs(const struct device *dev) {
|
||||
const struct kscan_matrix_config *config = dev->config;
|
||||
const struct kscan_matrix_data *data = dev->data;
|
||||
|
||||
for (int i = 0; i < config->inputs.len; i++) {
|
||||
const struct gpio_dt_spec *gpio = &config->inputs.gpios[i];
|
||||
int err = kscan_matrix_init_input_inst(dev, gpio, i);
|
||||
for (int i = 0; i < data->inputs.len; i++) {
|
||||
const struct kscan_gpio *gpio = &data->inputs.gpios[i];
|
||||
int err = kscan_matrix_init_input_inst(dev, gpio);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
@ -396,7 +393,7 @@ static int kscan_matrix_init_outputs(const struct device *dev) {
|
|||
const struct kscan_matrix_config *config = dev->config;
|
||||
|
||||
for (int i = 0; i < config->outputs.len; i++) {
|
||||
const struct gpio_dt_spec *gpio = &config->outputs.gpios[i];
|
||||
const struct gpio_dt_spec *gpio = &config->outputs.gpios[i].spec;
|
||||
int err = kscan_matrix_init_output_inst(dev, gpio);
|
||||
if (err) {
|
||||
return err;
|
||||
|
@ -411,6 +408,9 @@ static int kscan_matrix_init(const struct device *dev) {
|
|||
|
||||
data->dev = dev;
|
||||
|
||||
// Sort inputs by port so we can read each port just once per scan.
|
||||
kscan_gpio_list_sort_by_port(&data->inputs);
|
||||
|
||||
kscan_matrix_init_inputs(dev);
|
||||
kscan_matrix_init_outputs(dev);
|
||||
kscan_matrix_set_all_outputs(dev, 0);
|
||||
|
@ -432,10 +432,10 @@ static const struct kscan_driver_api kscan_matrix_api = {
|
|||
BUILD_ASSERT(INST_DEBOUNCE_RELEASE_MS(n) <= DEBOUNCE_COUNTER_MAX, \
|
||||
"ZMK_KSCAN_DEBOUNCE_RELEASE_MS or debounce-release-ms is too large"); \
|
||||
\
|
||||
static const struct gpio_dt_spec kscan_matrix_rows_##n[] = { \
|
||||
static struct kscan_gpio kscan_matrix_rows_##n[] = { \
|
||||
LISTIFY(INST_ROWS_LEN(n), KSCAN_GPIO_ROW_CFG_INIT, (, ), n)}; \
|
||||
\
|
||||
static const struct gpio_dt_spec kscan_matrix_cols_##n[] = { \
|
||||
static struct kscan_gpio kscan_matrix_cols_##n[] = { \
|
||||
LISTIFY(INST_COLS_LEN(n), KSCAN_GPIO_COL_CFG_INIT, (, ), n)}; \
|
||||
\
|
||||
static struct debounce_state kscan_matrix_state_##n[INST_MATRIX_LEN(n)]; \
|
||||
|
@ -444,14 +444,14 @@ static const struct kscan_driver_api kscan_matrix_api = {
|
|||
(static struct kscan_matrix_irq_callback kscan_matrix_irqs_##n[INST_INPUTS_LEN(n)];)) \
|
||||
\
|
||||
static struct kscan_matrix_data kscan_matrix_data_##n = { \
|
||||
.inputs = \
|
||||
KSCAN_GPIO_LIST(COND_DIODE_DIR(n, (kscan_matrix_cols_##n), (kscan_matrix_rows_##n))), \
|
||||
.matrix_state = kscan_matrix_state_##n, \
|
||||
COND_INTERRUPTS((.irqs = kscan_matrix_irqs_##n, ))}; \
|
||||
\
|
||||
static struct kscan_matrix_config kscan_matrix_config_##n = { \
|
||||
.rows = KSCAN_GPIO_LIST(kscan_matrix_rows_##n), \
|
||||
.cols = KSCAN_GPIO_LIST(kscan_matrix_cols_##n), \
|
||||
.inputs = \
|
||||
KSCAN_GPIO_LIST(COND_DIODE_DIR(n, (kscan_matrix_cols_##n), (kscan_matrix_rows_##n))), \
|
||||
.rows = ARRAY_SIZE(kscan_matrix_rows_##n), \
|
||||
.cols = ARRAY_SIZE(kscan_matrix_cols_##n), \
|
||||
.outputs = \
|
||||
KSCAN_GPIO_LIST(COND_DIODE_DIR(n, (kscan_matrix_rows_##n), (kscan_matrix_cols_##n))), \
|
||||
.debounce_config = \
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
#if ZMK_BLE_IS_CENTRAL
|
||||
#define ZMK_BLE_PROFILE_COUNT (CONFIG_BT_MAX_PAIRED - 1)
|
||||
#define ZMK_BLE_SPLIT_PERIPHERAL_COUNT 1
|
||||
#define ZMK_SPLIT_BLE_PERIPHERAL_COUNT 1
|
||||
#else
|
||||
#define ZMK_BLE_PROFILE_COUNT CONFIG_BT_MAX_PAIRED
|
||||
#endif
|
||||
|
|
|
@ -218,7 +218,7 @@ int zmk_keymap_apply_position_state(uint8_t source, int layer, uint32_t position
|
|||
#endif
|
||||
case BEHAVIOR_LOCALITY_GLOBAL:
|
||||
#if ZMK_BLE_IS_CENTRAL
|
||||
for (int i = 0; i < ZMK_BLE_SPLIT_PERIPHERAL_COUNT; i++) {
|
||||
for (int i = 0; i < ZMK_SPLIT_BLE_PERIPHERAL_COUNT; i++) {
|
||||
zmk_split_bt_invoke_behavior(i, &binding, event, pressed);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -21,11 +21,11 @@ config ZMK_SPLIT_BLE_CENTRAL_POSITION_QUEUE_SIZE
|
|||
int "Max number of key position state events to queue when received from peripherals"
|
||||
default 5
|
||||
|
||||
config ZMK_BLE_SPLIT_CENTRAL_SPLIT_RUN_STACK_SIZE
|
||||
config ZMK_SPLIT_BLE_CENTRAL_SPLIT_RUN_STACK_SIZE
|
||||
int "BLE split central write thread stack size"
|
||||
default 512
|
||||
|
||||
config ZMK_BLE_SPLIT_CENTRAL_SPLIT_RUN_QUEUE_SIZE
|
||||
config ZMK_SPLIT_BLE_CENTRAL_SPLIT_RUN_QUEUE_SIZE
|
||||
int "Max number of behavior run events to queue to send to the peripheral(s)"
|
||||
default 5
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ struct peripheral_slot {
|
|||
uint8_t changed_positions[POSITION_STATE_DATA_LEN];
|
||||
};
|
||||
|
||||
static struct peripheral_slot peripherals[ZMK_BLE_SPLIT_PERIPHERAL_COUNT];
|
||||
static struct peripheral_slot peripherals[ZMK_SPLIT_BLE_PERIPHERAL_COUNT];
|
||||
|
||||
static const struct bt_uuid_128 split_service_uuid = BT_UUID_INIT_128(ZMK_SPLIT_BT_SERVICE_UUID);
|
||||
|
||||
|
@ -65,7 +65,7 @@ void peripheral_event_work_callback(struct k_work *work) {
|
|||
K_WORK_DEFINE(peripheral_event_work, peripheral_event_work_callback);
|
||||
|
||||
int peripheral_slot_index_for_conn(struct bt_conn *conn) {
|
||||
for (int i = 0; i < ZMK_BLE_SPLIT_PERIPHERAL_COUNT; i++) {
|
||||
for (int i = 0; i < ZMK_SPLIT_BLE_PERIPHERAL_COUNT; i++) {
|
||||
if (peripherals[i].conn == conn) {
|
||||
return i;
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ struct peripheral_slot *peripheral_slot_for_conn(struct bt_conn *conn) {
|
|||
}
|
||||
|
||||
int release_peripheral_slot(int index) {
|
||||
if (index < 0 || index >= ZMK_BLE_SPLIT_PERIPHERAL_COUNT) {
|
||||
if (index < 0 || index >= ZMK_SPLIT_BLE_PERIPHERAL_COUNT) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -131,7 +131,7 @@ int release_peripheral_slot(int index) {
|
|||
}
|
||||
|
||||
int reserve_peripheral_slot() {
|
||||
for (int i = 0; i < ZMK_BLE_SPLIT_PERIPHERAL_COUNT; i++) {
|
||||
for (int i = 0; i < ZMK_SPLIT_BLE_PERIPHERAL_COUNT; i++) {
|
||||
if (peripherals[i].state == PERIPHERAL_SLOT_STATE_OPEN) {
|
||||
// Be sure the slot is fully reinitialized.
|
||||
release_peripheral_slot(i);
|
||||
|
@ -504,7 +504,7 @@ static struct bt_conn_cb conn_callbacks = {
|
|||
};
|
||||
|
||||
K_THREAD_STACK_DEFINE(split_central_split_run_q_stack,
|
||||
CONFIG_ZMK_BLE_SPLIT_CENTRAL_SPLIT_RUN_STACK_SIZE);
|
||||
CONFIG_ZMK_SPLIT_BLE_CENTRAL_SPLIT_RUN_STACK_SIZE);
|
||||
|
||||
struct k_work_q split_central_split_run_q;
|
||||
|
||||
|
@ -515,7 +515,7 @@ struct zmk_split_run_behavior_payload_wrapper {
|
|||
|
||||
K_MSGQ_DEFINE(zmk_split_central_split_run_msgq,
|
||||
sizeof(struct zmk_split_run_behavior_payload_wrapper),
|
||||
CONFIG_ZMK_BLE_SPLIT_CENTRAL_SPLIT_RUN_QUEUE_SIZE, 4);
|
||||
CONFIG_ZMK_SPLIT_BLE_CENTRAL_SPLIT_RUN_QUEUE_SIZE, 4);
|
||||
|
||||
void split_central_split_run_callback(struct k_work *work) {
|
||||
struct zmk_split_run_behavior_payload_wrapper payload_wrapper;
|
||||
|
|
|
@ -97,8 +97,8 @@ Following split keyboard settings are defined in [zmk/app/src/split/Kconfig](htt
|
|||
| `CONFIG_ZMK_SPLIT_BLE` | bool | Use BLE to communicate between split keyboard halves | y |
|
||||
| `CONFIG_ZMK_SPLIT_ROLE_CENTRAL` | bool | `y` for central device, `n` for peripheral | |
|
||||
| `CONFIG_ZMK_SPLIT_BLE_CENTRAL_POSITION_QUEUE_SIZE` | int | Max number of key state events to queue when received from peripherals | 5 |
|
||||
| `CONFIG_ZMK_BLE_SPLIT_CENTRAL_SPLIT_RUN_STACK_SIZE` | int | Stack size of the BLE split central write thread | 512 |
|
||||
| `CONFIG_ZMK_BLE_SPLIT_CENTRAL_SPLIT_RUN_QUEUE_SIZE` | int | Max number of behavior run events to queue to send to the peripheral(s) | 5 |
|
||||
| `CONFIG_ZMK_SPLIT_BLE_CENTRAL_SPLIT_RUN_STACK_SIZE` | int | Stack size of the BLE split central write thread | 512 |
|
||||
| `CONFIG_ZMK_SPLIT_BLE_CENTRAL_SPLIT_RUN_QUEUE_SIZE` | int | Max number of behavior run events to queue to send to the peripheral(s) | 5 |
|
||||
| `CONFIG_ZMK_SPLIT_BLE_PERIPHERAL_STACK_SIZE` | int | Stack size of the BLE split peripheral notify thread | 650 |
|
||||
| `CONFIG_ZMK_SPLIT_BLE_PERIPHERAL_PRIORITY` | int | Priority of the BLE split peripheral notify thread | 5 |
|
||||
| `CONFIG_ZMK_SPLIT_BLE_PERIPHERAL_POSITION_QUEUE_SIZE` | int | Max number of key state events to queue to send to the central | 10 |
|
||||
|
|
Loading…
Add table
Reference in a new issue