|
|
@ -51,29 +51,10 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); |
|
|
|
#define COND_POLL_OR_INTERRUPTS(pollcode, intcode) \ |
|
|
|
#define COND_POLL_OR_INTERRUPTS(pollcode, intcode) \ |
|
|
|
COND_CODE_1(CONFIG_ZMK_KSCAN_MATRIX_POLLING, pollcode, intcode) |
|
|
|
COND_CODE_1(CONFIG_ZMK_KSCAN_MATRIX_POLLING, pollcode, intcode) |
|
|
|
|
|
|
|
|
|
|
|
// TODO (Zephr 2.6): replace the following
|
|
|
|
|
|
|
|
// kscan_gpio_dt_spec -> gpio_dt_spec
|
|
|
|
|
|
|
|
// KSCAN_GPIO_DT_SPEC_GET_BY_IDX -> GPIO_DT_SPEC_GET_BY_IDX
|
|
|
|
|
|
|
|
// gpio_pin_get -> gpio_pin_get_dt
|
|
|
|
|
|
|
|
// gpio_pin_set -> gpio_pin_set_dt
|
|
|
|
|
|
|
|
// gpio_pin_interrupt_configure -> gpio_pin_interrupt_configure_dt
|
|
|
|
|
|
|
|
struct kscan_gpio_dt_spec { |
|
|
|
|
|
|
|
const struct device *port; |
|
|
|
|
|
|
|
gpio_pin_t pin; |
|
|
|
|
|
|
|
gpio_dt_flags_t dt_flags; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define KSCAN_GPIO_DT_SPEC_GET_BY_IDX(node_id, prop, idx) \ |
|
|
|
|
|
|
|
{ \
|
|
|
|
|
|
|
|
.port = DEVICE_DT_GET(DT_GPIO_CTLR_BY_IDX(node_id, prop, idx)), \
|
|
|
|
|
|
|
|
.pin = DT_GPIO_PIN_BY_IDX(node_id, prop, idx), \
|
|
|
|
|
|
|
|
.dt_flags = DT_GPIO_FLAGS_BY_IDX(node_id, prop, idx), \
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define KSCAN_GPIO_ROW_CFG_INIT(idx, inst_idx) \ |
|
|
|
#define KSCAN_GPIO_ROW_CFG_INIT(idx, inst_idx) \ |
|
|
|
KSCAN_GPIO_DT_SPEC_GET_BY_IDX(DT_DRV_INST(inst_idx), row_gpios, idx), |
|
|
|
GPIO_DT_SPEC_GET_BY_IDX(DT_DRV_INST(inst_idx), row_gpios, idx), |
|
|
|
#define KSCAN_GPIO_COL_CFG_INIT(idx, inst_idx) \ |
|
|
|
#define KSCAN_GPIO_COL_CFG_INIT(idx, inst_idx) \ |
|
|
|
KSCAN_GPIO_DT_SPEC_GET_BY_IDX(DT_DRV_INST(inst_idx), col_gpios, idx), |
|
|
|
GPIO_DT_SPEC_GET_BY_IDX(DT_DRV_INST(inst_idx), col_gpios, idx), |
|
|
|
|
|
|
|
|
|
|
|
enum kscan_diode_direction { |
|
|
|
enum kscan_diode_direction { |
|
|
|
KSCAN_ROW2COL, |
|
|
|
KSCAN_ROW2COL, |
|
|
@ -103,7 +84,7 @@ struct kscan_matrix_data { |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
struct kscan_gpio_list { |
|
|
|
struct kscan_gpio_list { |
|
|
|
const struct kscan_gpio_dt_spec *gpios; |
|
|
|
const struct gpio_dt_spec *gpios; |
|
|
|
size_t len; |
|
|
|
size_t len; |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
@ -146,9 +127,9 @@ static int kscan_matrix_set_all_outputs(const struct device *dev, const int valu |
|
|
|
const struct kscan_matrix_config *config = dev->config; |
|
|
|
const struct kscan_matrix_config *config = dev->config; |
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < config->outputs.len; i++) { |
|
|
|
for (int i = 0; i < config->outputs.len; i++) { |
|
|
|
const struct kscan_gpio_dt_spec *gpio = &config->outputs.gpios[i]; |
|
|
|
const struct gpio_dt_spec *gpio = &config->outputs.gpios[i]; |
|
|
|
|
|
|
|
|
|
|
|
int err = gpio_pin_set(gpio->port, gpio->pin, value); |
|
|
|
int err = gpio_pin_set_dt(gpio, value); |
|
|
|
if (err) { |
|
|
|
if (err) { |
|
|
|
LOG_ERR("Failed to set output %i to %i: %i", i, value, err); |
|
|
|
LOG_ERR("Failed to set output %i to %i: %i", i, value, err); |
|
|
|
return err; |
|
|
|
return err; |
|
|
@ -163,9 +144,9 @@ static int kscan_matrix_interrupt_configure(const struct device *dev, const gpio |
|
|
|
const struct kscan_matrix_config *config = dev->config; |
|
|
|
const struct kscan_matrix_config *config = dev->config; |
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < config->inputs.len; i++) { |
|
|
|
for (int i = 0; i < config->inputs.len; i++) { |
|
|
|
const struct kscan_gpio_dt_spec *gpio = &config->inputs.gpios[i]; |
|
|
|
const struct gpio_dt_spec *gpio = &config->inputs.gpios[i]; |
|
|
|
|
|
|
|
|
|
|
|
int err = gpio_pin_interrupt_configure(gpio->port, gpio->pin, flags); |
|
|
|
int err = gpio_pin_interrupt_configure_dt(gpio, flags); |
|
|
|
if (err) { |
|
|
|
if (err) { |
|
|
|
LOG_ERR("Unable to configure interrupt for pin %u on %s", gpio->pin, gpio->port->name); |
|
|
|
LOG_ERR("Unable to configure interrupt for pin %u on %s", gpio->pin, gpio->port->name); |
|
|
|
return err; |
|
|
|
return err; |
|
|
@ -248,25 +229,25 @@ static int kscan_matrix_read(const struct device *dev) { |
|
|
|
|
|
|
|
|
|
|
|
// Scan the matrix.
|
|
|
|
// Scan the matrix.
|
|
|
|
for (int o = 0; o < config->outputs.len; o++) { |
|
|
|
for (int o = 0; o < config->outputs.len; o++) { |
|
|
|
const struct kscan_gpio_dt_spec *out_gpio = &config->outputs.gpios[o]; |
|
|
|
const struct gpio_dt_spec *out_gpio = &config->outputs.gpios[o]; |
|
|
|
|
|
|
|
|
|
|
|
int err = gpio_pin_set(out_gpio->port, out_gpio->pin, 1); |
|
|
|
int err = gpio_pin_set_dt(out_gpio, 1); |
|
|
|
if (err) { |
|
|
|
if (err) { |
|
|
|
LOG_ERR("Failed to set output %i active: %i", o, err); |
|
|
|
LOG_ERR("Failed to set output %i active: %i", o, err); |
|
|
|
return err; |
|
|
|
return err; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < config->inputs.len; i++) { |
|
|
|
for (int i = 0; i < config->inputs.len; i++) { |
|
|
|
const struct kscan_gpio_dt_spec *in_gpio = &config->inputs.gpios[i]; |
|
|
|
const struct gpio_dt_spec *in_gpio = &config->inputs.gpios[i]; |
|
|
|
|
|
|
|
|
|
|
|
const int index = state_index_io(config, i, o); |
|
|
|
const int index = state_index_io(config, i, o); |
|
|
|
const bool active = gpio_pin_get(in_gpio->port, in_gpio->pin); |
|
|
|
const bool active = gpio_pin_get_dt(in_gpio); |
|
|
|
|
|
|
|
|
|
|
|
debounce_update(&data->matrix_state[index], active, config->debounce_scan_period_ms, |
|
|
|
debounce_update(&data->matrix_state[index], active, config->debounce_scan_period_ms, |
|
|
|
&config->debounce_config); |
|
|
|
&config->debounce_config); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
err = gpio_pin_set(out_gpio->port, out_gpio->pin, 0); |
|
|
|
err = gpio_pin_set_dt(out_gpio, 0); |
|
|
|
if (err) { |
|
|
|
if (err) { |
|
|
|
LOG_ERR("Failed to set output %i inactive: %i", o, err); |
|
|
|
LOG_ERR("Failed to set output %i inactive: %i", o, err); |
|
|
|
return err; |
|
|
|
return err; |
|
|
@ -342,14 +323,14 @@ static int kscan_matrix_disable(const struct device *dev) { |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static int kscan_matrix_init_input_inst(const struct device *dev, |
|
|
|
static int kscan_matrix_init_input_inst(const struct device *dev, const struct gpio_dt_spec *gpio, |
|
|
|
const struct kscan_gpio_dt_spec *gpio, const int index) { |
|
|
|
const int index) { |
|
|
|
if (!device_is_ready(gpio->port)) { |
|
|
|
if (!device_is_ready(gpio->port)) { |
|
|
|
LOG_ERR("GPIO is not ready: %s", gpio->port->name); |
|
|
|
LOG_ERR("GPIO is not ready: %s", gpio->port->name); |
|
|
|
return -ENODEV; |
|
|
|
return -ENODEV; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int err = gpio_pin_configure(gpio->port, gpio->pin, GPIO_INPUT | gpio->dt_flags); |
|
|
|
int err = gpio_pin_configure_dt(gpio, GPIO_INPUT); |
|
|
|
if (err) { |
|
|
|
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->pin, gpio->port->name); |
|
|
|
return err; |
|
|
|
return err; |
|
|
@ -377,7 +358,7 @@ static int kscan_matrix_init_inputs(const struct device *dev) { |
|
|
|
const struct kscan_matrix_config *config = dev->config; |
|
|
|
const struct kscan_matrix_config *config = dev->config; |
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < config->inputs.len; i++) { |
|
|
|
for (int i = 0; i < config->inputs.len; i++) { |
|
|
|
const struct kscan_gpio_dt_spec *gpio = &config->inputs.gpios[i]; |
|
|
|
const struct gpio_dt_spec *gpio = &config->inputs.gpios[i]; |
|
|
|
int err = kscan_matrix_init_input_inst(dev, gpio, i); |
|
|
|
int err = kscan_matrix_init_input_inst(dev, gpio, i); |
|
|
|
if (err) { |
|
|
|
if (err) { |
|
|
|
return err; |
|
|
|
return err; |
|
|
@ -388,13 +369,13 @@ static int kscan_matrix_init_inputs(const struct device *dev) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static int kscan_matrix_init_output_inst(const struct device *dev, |
|
|
|
static int kscan_matrix_init_output_inst(const struct device *dev, |
|
|
|
const struct kscan_gpio_dt_spec *gpio) { |
|
|
|
const struct gpio_dt_spec *gpio) { |
|
|
|
if (!device_is_ready(gpio->port)) { |
|
|
|
if (!device_is_ready(gpio->port)) { |
|
|
|
LOG_ERR("GPIO is not ready: %s", gpio->port->name); |
|
|
|
LOG_ERR("GPIO is not ready: %s", gpio->port->name); |
|
|
|
return -ENODEV; |
|
|
|
return -ENODEV; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int err = gpio_pin_configure(gpio->port, gpio->pin, GPIO_OUTPUT | gpio->dt_flags); |
|
|
|
int err = gpio_pin_configure_dt(gpio, GPIO_OUTPUT); |
|
|
|
if (err) { |
|
|
|
if (err) { |
|
|
|
LOG_ERR("Unable to configure pin %u on %s for output", gpio->pin, gpio->port->name); |
|
|
|
LOG_ERR("Unable to configure pin %u on %s for output", gpio->pin, gpio->port->name); |
|
|
|
return err; |
|
|
|
return err; |
|
|
@ -409,7 +390,7 @@ static int kscan_matrix_init_outputs(const struct device *dev) { |
|
|
|
const struct kscan_matrix_config *config = dev->config; |
|
|
|
const struct kscan_matrix_config *config = dev->config; |
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < config->outputs.len; i++) { |
|
|
|
for (int i = 0; i < config->outputs.len; i++) { |
|
|
|
const struct kscan_gpio_dt_spec *gpio = &config->outputs.gpios[i]; |
|
|
|
const struct gpio_dt_spec *gpio = &config->outputs.gpios[i]; |
|
|
|
int err = kscan_matrix_init_output_inst(dev, gpio); |
|
|
|
int err = kscan_matrix_init_output_inst(dev, gpio); |
|
|
|
if (err) { |
|
|
|
if (err) { |
|
|
|
return err; |
|
|
|
return err; |
|
|
@ -445,10 +426,10 @@ static const struct kscan_driver_api kscan_matrix_api = { |
|
|
|
BUILD_ASSERT(INST_DEBOUNCE_RELEASE_MS(index) <= DEBOUNCE_COUNTER_MAX, \
|
|
|
|
BUILD_ASSERT(INST_DEBOUNCE_RELEASE_MS(index) <= DEBOUNCE_COUNTER_MAX, \
|
|
|
|
"ZMK_KSCAN_DEBOUNCE_RELEASE_MS or debounce-release-ms is too large"); \
|
|
|
|
"ZMK_KSCAN_DEBOUNCE_RELEASE_MS or debounce-release-ms is too large"); \
|
|
|
|
\
|
|
|
|
\
|
|
|
|
static const struct kscan_gpio_dt_spec kscan_matrix_rows_##index[] = { \
|
|
|
|
static const struct gpio_dt_spec kscan_matrix_rows_##index[] = { \
|
|
|
|
UTIL_LISTIFY(INST_ROWS_LEN(index), KSCAN_GPIO_ROW_CFG_INIT, index)}; \
|
|
|
|
UTIL_LISTIFY(INST_ROWS_LEN(index), KSCAN_GPIO_ROW_CFG_INIT, index)}; \
|
|
|
|
\
|
|
|
|
\
|
|
|
|
static const struct kscan_gpio_dt_spec kscan_matrix_cols_##index[] = { \
|
|
|
|
static const struct gpio_dt_spec kscan_matrix_cols_##index[] = { \
|
|
|
|
UTIL_LISTIFY(INST_COLS_LEN(index), KSCAN_GPIO_COL_CFG_INIT, index)}; \
|
|
|
|
UTIL_LISTIFY(INST_COLS_LEN(index), KSCAN_GPIO_COL_CFG_INIT, index)}; \
|
|
|
|
\
|
|
|
|
\
|
|
|
|
static struct debounce_state kscan_matrix_state_##index[INST_MATRIX_LEN(index)]; \
|
|
|
|
static struct debounce_state kscan_matrix_state_##index[INST_MATRIX_LEN(index)]; \
|
|
|
|