Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(kscan): Add toggle-mode to updated direct-wire kscan #1305

Merged
merged 6 commits into from
May 19, 2022
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
39 changes: 35 additions & 4 deletions app/drivers/kscan/kscan_gpio_direct.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ struct kscan_direct_config {
struct debounce_config debounce_config;
int32_t debounce_scan_period_ms;
int32_t poll_period_ms;
bool toggle_mode;
};

#if USE_INTERRUPTS
Expand Down Expand Up @@ -124,6 +125,32 @@ static void kscan_direct_irq_callback_handler(const struct device *port, struct
}
#endif

static gpio_flags_t kscan_gpio_get_extra_flags(const struct gpio_dt_spec *gpio, bool active) {
gpio_flags_t flags = BIT(0) & gpio->dt_flags;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need to return the first bit here at all, since that will be set in the DT still. We need to check it, but not include in the "extra" flags we'll use.

Minor thing, but in case we end up using this some other way later, good to really only just return the extra flags we need, not also include the active bit.

if (!active) {
flags |= flags ? GPIO_PULL_UP : GPIO_PULL_DOWN;
}
return flags;
}

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);
LOG_DBG("Extra flags equal to: %d", extra_flags);

int err = gpio_pin_configure_dt(&inputs->gpios[i], extra_flags);
if (err) {
LOG_ERR("Unable to configure flags on pin %d on %s", inputs->gpios[i].pin,
inputs->gpios[i].port->name);
return err;
}
}
return 0;
}

static void kscan_direct_read_continue(const struct device *dev) {
const struct kscan_direct_config *config = dev->config;
struct kscan_direct_data *data = dev->data;
Expand Down Expand Up @@ -173,6 +200,9 @@ static int kscan_direct_read(const struct device *dev) {

LOG_DBG("Sending event at 0,%i state %s", i, pressed ? "on" : "off");
data->callback(dev, 0, i, pressed);
if (config->toggle_mode && pressed) {
kscan_inputs_set_flags(&config->inputs, &config->inputs.gpios[i]);
}
}

continue_scan = continue_scan || debounce_is_active(state);
Expand Down Expand Up @@ -229,13 +259,13 @@ static int kscan_direct_disable(const struct device *dev) {
}

static int kscan_direct_init_input_inst(const struct device *dev, const struct gpio_dt_spec *gpio,
const int index) {
const int index, bool toggle_mode) {
if (!device_is_ready(gpio->port)) {
LOG_ERR("GPIO is not ready: %s", gpio->port->name);
return -ENODEV;
}

int err = gpio_pin_configure_dt(gpio, GPIO_INPUT);
int err = gpio_pin_configure_dt(
gpio, GPIO_INPUT | (toggle_mode ? kscan_gpio_get_extra_flags(gpio, false) : 0));
if (err) {
LOG_ERR("Unable to configure pin %u on %s for input", gpio->pin, gpio->port->name);
return err;
Expand Down Expand Up @@ -264,7 +294,7 @@ static int kscan_direct_init_inputs(const struct device *dev) {

for (int i = 0; i < config->inputs.len; i++) {
const struct gpio_dt_spec *gpio = &config->inputs.gpios[i];
int err = kscan_direct_init_input_inst(dev, gpio, i);
int err = kscan_direct_init_input_inst(dev, gpio, i, config->toggle_mode);
if (err) {
return err;
}
Expand Down Expand Up @@ -317,6 +347,7 @@ static const struct kscan_driver_api kscan_direct_api = {
}, \
.debounce_scan_period_ms = DT_INST_PROP(n, debounce_scan_period_ms), \
.poll_period_ms = DT_INST_PROP(n, poll_period_ms), \
.toggle_mode = DT_INST_PROP(n, toggle_mode), \
}; \
\
DEVICE_DT_INST_DEFINE(n, &kscan_direct_init, NULL, &kscan_direct_data_##n, \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,6 @@ properties:
type: int
default: 10
description: Time between reads in milliseconds when no key is pressed and ZMK_KSCAN_DIRECT_POLLING is enabled.
toggle-mode:
type: boolean
description: Enable toggle-switch mode.