summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/boards/shields/kyria/kyria_left.overlay12
-rw-r--r--app/drivers/zephyr/CMakeLists.txt3
-rw-r--r--app/drivers/zephyr/Kconfig47
-rw-r--r--app/drivers/zephyr/dts/bindings/alps,en11.yaml17
-rw-r--r--app/drivers/zephyr/en11.c110
-rw-r--r--app/drivers/zephyr/en11.h61
-rw-r--r--app/drivers/zephyr/en11_trigger.c210
-rw-r--r--app/src/drivers/sensors/en11/CMakeLists.txt6
-rw-r--r--app/src/drivers/sensors/en11/Kconfig52
-rw-r--r--app/src/main.c24
10 files changed, 542 insertions, 0 deletions
diff --git a/app/boards/shields/kyria/kyria_left.overlay b/app/boards/shields/kyria/kyria_left.overlay
index c6305bd..393b9d8 100644
--- a/app/boards/shields/kyria/kyria_left.overlay
+++ b/app/boards/shields/kyria/kyria_left.overlay
@@ -6,6 +6,18 @@
#include "kyria.dtsi"
+/ {
+ sensors {
+ encoder: encoder0 {
+ compatible = "alps,en11";
+ label = "Rotary Encoder";
+ a-gpios = <&pro_micro_d 5 GPIO_ACTIVE_HIGH>;
+ b-gpios = <&pro_micro_d 9 GPIO_ACTIVE_HIGH>;
+ };
+ };
+
+};
+
&kscan0 {
col-gpios
= <&pro_micro_a 3 GPIO_ACTIVE_HIGH>
diff --git a/app/drivers/zephyr/CMakeLists.txt b/app/drivers/zephyr/CMakeLists.txt
index 983828f..5966419 100644
--- a/app/drivers/zephyr/CMakeLists.txt
+++ b/app/drivers/zephyr/CMakeLists.txt
@@ -6,4 +6,7 @@ if(CONFIG_ZMK_KSCAN_GPIO_DRIVER)
kscan_gpio_matrix.c
kscan_gpio_direct.c
)
+
+ zephyr_library_sources_ifdef(CONFIG_EN11 en11.c)
+ zephyr_library_sources_ifdef(CONFIG_EN11_TRIGGER en11_trigger.c)
endif()
diff --git a/app/drivers/zephyr/Kconfig b/app/drivers/zephyr/Kconfig
index cd526e8..00a43d2 100644
--- a/app/drivers/zephyr/Kconfig
+++ b/app/drivers/zephyr/Kconfig
@@ -17,3 +17,50 @@ config ZMK_KSCAN_INIT_PRIORITY
help
Keyboard scan device driver initialization priority.
+menuconfig EN11
+ bool "EN11 Incremental Encoder Sensor"
+ depends on GPIO
+ help
+ Enable driver for EN11 incremental encoder sensors.
+
+if EN11
+
+choice
+ prompt "Trigger mode"
+ default EN11_TRIGGER_NONE
+ help
+ Specify the type of triggering to be used by the driver.
+
+config EN11_TRIGGER_NONE
+ bool "No trigger"
+
+config EN11_TRIGGER_GLOBAL_THREAD
+ bool "Use global thread"
+ depends on GPIO
+ select EN11_TRIGGER
+
+config EN11_TRIGGER_OWN_THREAD
+ bool "Use own thread"
+ depends on GPIO
+ select EN11_TRIGGER
+
+endchoice
+
+config EN11_TRIGGER
+ bool
+
+config EN11_THREAD_PRIORITY
+ int "Thread priority"
+ depends on EN11_TRIGGER_OWN_THREAD
+ default 10
+ help
+ Priority of thread used by the driver to handle interrupts.
+
+config EN11_THREAD_STACK_SIZE
+ int "Thread stack size"
+ depends on EN11_TRIGGER_OWN_THREAD
+ default 1024
+ help
+ Stack size of thread used by the driver to handle interrupts.
+
+endif # EN11
diff --git a/app/drivers/zephyr/dts/bindings/alps,en11.yaml b/app/drivers/zephyr/dts/bindings/alps,en11.yaml
new file mode 100644
index 0000000..1d1de3a
--- /dev/null
+++ b/app/drivers/zephyr/dts/bindings/alps,en11.yaml
@@ -0,0 +1,17 @@
+description: |
+ Sensor driver for the Alps en11 rotary encoder
+
+compatible: "alps,en11"
+
+properties:
+ label:
+ type: string
+ required: true
+ a-gpios:
+ type: phandle-array
+ required: true
+ description: A pin for the encoder
+ b-gpios:
+ type: phandle-array
+ required: true
+ description: A pin for the encoder
diff --git a/app/drivers/zephyr/en11.c b/app/drivers/zephyr/en11.c
new file mode 100644
index 0000000..e6c6b74
--- /dev/null
+++ b/app/drivers/zephyr/en11.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2020 Peter Johanson
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#define DT_DRV_COMPAT alps_en11
+
+#include <device.h>
+#include <drivers/gpio.h>
+#include <sys/util.h>
+#include <kernel.h>
+#include <drivers/sensor.h>
+#include <sys/__assert.h>
+#include <logging/log.h>
+
+#include "en11.h"
+
+LOG_MODULE_REGISTER(EN11, CONFIG_SENSOR_LOG_LEVEL);
+
+static int en11_sample_fetch(struct device *dev, enum sensor_channel chan)
+{
+ struct en11_data *drv_data = dev->driver_data;
+ u16_t val;
+
+ __ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_AMBIENT_TEMP);
+
+ // if (en11_reg_read(drv_data, EN11_REG_TOBJ, &val) < 0) {
+ // return -EIO;
+ // }
+
+ // if (val & EN11_DATA_INVALID_BIT) {
+ // return -EIO;
+ // }
+
+ // drv_data->sample = arithmetic_shift_right((s16_t)val, 2);
+
+ return 0;
+}
+
+static int en11_channel_get(struct device *dev,
+ enum sensor_channel chan,
+ struct sensor_value *val)
+{
+ struct en11_data *drv_data = dev->driver_data;
+ // s32_t uval;
+
+ // if (chan != SENSOR_CHAN_AMBIENT_TEMP) {
+ // return -ENOTSUP;
+ // }
+
+ // uval = (s32_t)drv_data->sample * EN11_TEMP_SCALE;
+ // val->val1 = uval / 1000000;
+ // val->val2 = uval % 1000000;
+
+ return 0;
+}
+
+static const struct sensor_driver_api en11_driver_api = {
+#ifdef CONFIG_EN11_TRIGGER
+ .trigger_set = en11_trigger_set,
+#endif
+ .sample_fetch = en11_sample_fetch,
+ .channel_get = en11_channel_get,
+};
+
+int en11_init(struct device *dev)
+{
+ struct en11_data *drv_data = dev->driver_data;
+ const struct en11_config *drv_cfg = dev->config_info;
+
+ LOG_DBG("");
+
+ drv_data->a = device_get_binding(drv_cfg->a_label);
+ if (drv_data->a == NULL) {
+ LOG_ERR("Failed to get pointer to A GPIO device");
+ return -EINVAL;
+ }
+
+ drv_data->b = device_get_binding(drv_cfg->b_label);
+ if (drv_data->b == NULL) {
+ LOG_ERR("Failed to get pointer to B GPIO device");
+ return -EINVAL;
+ }
+
+#ifdef CONFIG_EN11_TRIGGER
+ if (en11_init_interrupt(dev) < 0) {
+ LOG_DBG("Failed to initialize interrupt!");
+ return -EIO;
+ }
+#endif
+
+ return 0;
+}
+
+struct en11_data en11_data;
+
+const struct en11_config en11_cfg = {
+ .a_label = DT_INST_GPIO_LABEL(0, a_gpios),
+ .a_pin = DT_INST_GPIO_PIN(0, a_gpios),
+ .a_flags = DT_INST_GPIO_FLAGS(0, a_gpios),
+ .b_label = DT_INST_GPIO_LABEL(0, b_gpios),
+ .b_pin = DT_INST_GPIO_PIN(0, b_gpios),
+ .b_flags = DT_INST_GPIO_FLAGS(0, b_gpios),
+};
+
+DEVICE_AND_API_INIT(en11, DT_INST_LABEL(0), en11_init,
+ &en11_data,
+ &en11_cfg, POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY,
+ &en11_driver_api);
diff --git a/app/drivers/zephyr/en11.h b/app/drivers/zephyr/en11.h
new file mode 100644
index 0000000..e8b2f21
--- /dev/null
+++ b/app/drivers/zephyr/en11.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2020 Peter Johanson
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#pragma once
+
+#include <device.h>
+#include <drivers/gpio.h>
+#include <sys/util.h>
+
+struct en11_config {
+ const char *a_label;
+ const u8_t a_pin;
+ const u8_t a_flags;
+
+ const char *b_label;
+ const u8_t b_pin;
+ const u8_t b_flags;
+};
+
+enum en11_pin_state {
+ EN11_A_PIN_STATE,
+ EN11_B_PIN_STATE
+};
+
+struct en11_data {
+ struct device *a;
+ struct device *b;
+ u8_t ab_state;
+ s16_t sample;
+
+#ifdef CONFIG_EN11_TRIGGER
+ struct device *gpio;
+ struct gpio_callback a_gpio_cb;
+ struct gpio_callback b_gpio_cb;
+ struct device *dev;
+
+ sensor_trigger_handler_t handler;
+ struct sensor_trigger trigger;
+
+#if defined(CONFIG_EN11_TRIGGER_OWN_THREAD)
+ K_THREAD_STACK_MEMBER(thread_stack, CONFIG_EN11_THREAD_STACK_SIZE);
+ struct k_sem gpio_sem;
+ struct k_thread thread;
+#elif defined(CONFIG_EN11_TRIGGER_GLOBAL_THREAD)
+ struct k_work work;
+#endif
+
+#endif /* CONFIG_EN11_TRIGGER */
+};
+
+#ifdef CONFIG_EN11_TRIGGER
+
+int en11_trigger_set(struct device *dev,
+ const struct sensor_trigger *trig,
+ sensor_trigger_handler_t handler);
+
+int en11_init_interrupt(struct device *dev);
+#endif
diff --git a/app/drivers/zephyr/en11_trigger.c b/app/drivers/zephyr/en11_trigger.c
new file mode 100644
index 0000000..d210431
--- /dev/null
+++ b/app/drivers/zephyr/en11_trigger.c
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define DT_DRV_COMPAT alps_en11
+
+#include <device.h>
+#include <drivers/gpio.h>
+#include <sys/util.h>
+#include <kernel.h>
+#include <drivers/sensor.h>
+
+#include "en11.h"
+
+extern struct en11_data en11_driver;
+
+#include <logging/log.h>
+LOG_MODULE_DECLARE(EN11, CONFIG_SENSOR_LOG_LEVEL);
+
+static inline void setup_int(struct device *dev,
+ bool enable)
+{
+ struct en11_data *data = dev->driver_data;
+ const struct en11_config *cfg = dev->config_info;
+
+ LOG_DBG("enabled %s", (enable ? "true" : "false"));
+
+ if (gpio_pin_interrupt_configure(data->a,
+ cfg->a_pin,
+ enable
+ ? GPIO_INT_EDGE_BOTH
+ : GPIO_INT_DISABLE)) {
+ LOG_WRN("Unable to set A pin GPIO interrupt");
+ }
+
+ if (gpio_pin_interrupt_configure(data->b,
+ cfg->b_pin,
+ enable
+ ? GPIO_INT_EDGE_BOTH
+ : GPIO_INT_DISABLE)) {
+ LOG_WRN("Unable to set A pin GPIO interrupt");
+ }
+}
+
+static void en11_a_gpio_callback(struct device *dev,
+ struct gpio_callback *cb, u32_t pins)
+{
+ struct en11_data *drv_data =
+ CONTAINER_OF(cb, struct en11_data, a_gpio_cb);
+
+ LOG_DBG("");
+
+ setup_int(drv_data->dev, false);
+
+#if defined(CONFIG_EN11_TRIGGER_OWN_THREAD)
+ k_sem_give(&drv_data->gpio_sem);
+#elif defined(CONFIG_EN11_TRIGGER_GLOBAL_THREAD)
+ k_work_submit(&drv_data->work);
+#endif
+}
+
+static void en11_b_gpio_callback(struct device *dev,
+ struct gpio_callback *cb, u32_t pins)
+{
+ struct en11_data *drv_data =
+ CONTAINER_OF(cb, struct en11_data, b_gpio_cb);
+
+ LOG_DBG("");
+
+ setup_int(drv_data->dev, false);
+
+#if defined(CONFIG_EN11_TRIGGER_OWN_THREAD)
+ k_sem_give(&drv_data->gpio_sem);
+#elif defined(CONFIG_EN11_TRIGGER_GLOBAL_THREAD)
+ k_work_submit(&drv_data->work);
+#endif
+}
+
+static void en11_thread_cb(void *arg)
+{
+ struct device *dev = arg;
+ struct en11_data *drv_data = dev->driver_data;
+ const struct en11_config *cfg = dev->config_info;
+ u16_t status;
+
+ // gpio_pin_get(drv_data->a, cfg->a_pin)
+
+ // if (en11_reg_read(drv_data, EN11_REG_STATUS, &status) < 0) {
+ // return;
+ // }
+
+ // if (status & EN11_DATA_READY_INT_BIT &&
+ // drv_data->drdy_handler != NULL) {
+ // drv_data->drdy_handler(dev, &drv_data->drdy_trigger);
+ // }
+
+ // if (status & EN11_TOBJ_TH_INT_BITS &&
+ // drv_data->th_handler != NULL) {
+ // drv_data->th_handler(dev, &drv_data->th_trigger);
+ // }
+
+ setup_int(dev, true);
+}
+
+#ifdef CONFIG_EN11_TRIGGER_OWN_THREAD
+static void en11_thread(int dev_ptr, int unused)
+{
+ struct device *dev = INT_TO_POINTER(dev_ptr);
+ struct en11_data *drv_data = dev->driver_data;
+
+ ARG_UNUSED(unused);
+
+ while (1) {
+ k_sem_take(&drv_data->gpio_sem, K_FOREVER);
+ en11_thread_cb(dev);
+ }
+}
+#endif
+
+#ifdef CONFIG_EN11_TRIGGER_GLOBAL_THREAD
+static void en11_work_cb(struct k_work *work)
+{
+ struct en11_data *drv_data =
+ CONTAINER_OF(work, struct en11_data, work);
+
+ LOG_DBG("");
+
+ en11_thread_cb(drv_data->dev);
+}
+#endif
+
+int en11_trigger_set(struct device *dev,
+ const struct sensor_trigger *trig,
+ sensor_trigger_handler_t handler)
+{
+ struct en11_data *drv_data = dev->driver_data;
+
+ setup_int(dev, false);
+
+ drv_data->trigger = *trig;
+ drv_data->handler = handler;
+
+ setup_int(dev, true);
+
+ return 0;
+}
+
+int en11_init_interrupt(struct device *dev)
+{
+ struct en11_data *drv_data = dev->driver_data;
+ const struct en11_config *drv_cfg = dev->config_info;
+
+ /* setup gpio interrupt */
+
+ LOG_DBG("A: %s %d B: %s %d", drv_cfg->a_label, drv_cfg->a_pin, drv_cfg->b_label, drv_cfg->b_pin);
+
+ gpio_pin_configure(drv_data->a, drv_cfg->a_pin,
+ drv_cfg->a_flags
+ | GPIO_INPUT);
+
+ if (gpio_pin_set(drv_data->a, drv_cfg->a_pin, 1)) {
+ LOG_DBG("Failed to set A active!");
+ return -EIO;
+ }
+
+ gpio_init_callback(&drv_data->a_gpio_cb,
+ en11_a_gpio_callback,
+ BIT(drv_cfg->a_pin));
+
+ if (gpio_add_callback(drv_data->a, &drv_data->a_gpio_cb) < 0) {
+ LOG_DBG("Failed to set A callback!");
+ return -EIO;
+ }
+
+ gpio_pin_configure(drv_data->b, drv_cfg->b_pin,
+ drv_cfg->b_flags
+ | GPIO_INPUT);
+
+ if (gpio_pin_set(drv_data->b, drv_cfg->b_pin, 1)) {
+ LOG_DBG("Failed to set B active!");
+ return -EIO;
+ }
+
+ gpio_init_callback(&drv_data->b_gpio_cb,
+ en11_b_gpio_callback,
+ BIT(drv_cfg->b_pin));
+
+ if (gpio_add_callback(drv_data->b, &drv_data->b_gpio_cb) < 0) {
+ LOG_DBG("Failed to set B callback!");
+ return -EIO;
+ }
+
+ LOG_DBG("A Pin? %d, B Pin? %d", gpio_pin_get(drv_data->a, drv_cfg->a_pin), gpio_pin_get(drv_data->b, drv_cfg->b_pin));
+
+#if defined(CONFIG_EN11_TRIGGER_OWN_THREAD)
+ k_sem_init(&drv_data->gpio_sem, 0, UINT_MAX);
+
+ k_thread_create(&drv_data->thread, drv_data->thread_stack,
+ CONFIG_EN11_THREAD_STACK_SIZE,
+ (k_thread_entry_t)en11_thread, dev,
+ 0, NULL, K_PRIO_COOP(CONFIG_EN11_THREAD_PRIORITY),
+ 0, K_NO_WAIT);
+#elif defined(CONFIG_EN11_TRIGGER_GLOBAL_THREAD)
+ drv_data->work.handler = en11_work_cb;
+#endif
+
+ return 0;
+}
diff --git a/app/src/drivers/sensors/en11/CMakeLists.txt b/app/src/drivers/sensors/en11/CMakeLists.txt
new file mode 100644
index 0000000..4c538ca
--- /dev/null
+++ b/app/src/drivers/sensors/en11/CMakeLists.txt
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+
+zephyr_library()
+
+zephyr_library_sources_ifdef(CONFIG_EN11 en11.c)
+zephyr_library_sources_ifdef(CONFIG_EN11_TRIGGER en11_trigger.c)
diff --git a/app/src/drivers/sensors/en11/Kconfig b/app/src/drivers/sensors/en11/Kconfig
new file mode 100644
index 0000000..84fec95
--- /dev/null
+++ b/app/src/drivers/sensors/en11/Kconfig
@@ -0,0 +1,52 @@
+# EN11 incremental encoder sensor configuration options
+
+# Copyright (c) 2020 Peter Johanson
+# SPDX-License-Identifier: MIT
+
+menuconfig EN11
+ bool "EN11 Incremental Encoder Sensor"
+ depends on GPIO
+ help
+ Enable driver for EN11 incremental encoder sensors.
+
+if EN11
+
+choice
+ prompt "Trigger mode"
+ default EN11_TRIGGER_NONE
+ help
+ Specify the type of triggering to be used by the driver.
+
+config EN11_TRIGGER_NONE
+ bool "No trigger"
+
+config EN11_TRIGGER_GLOBAL_THREAD
+ bool "Use global thread"
+ depends on GPIO
+ select EN11_TRIGGER
+
+config EN11_TRIGGER_OWN_THREAD
+ bool "Use own thread"
+ depends on GPIO
+ select EN11_TRIGGER
+
+endchoice
+
+config EN11_TRIGGER
+ bool
+
+config EN11_THREAD_PRIORITY
+ int "Thread priority"
+ depends on EN11_TRIGGER_OWN_THREAD
+ default 10
+ help
+ Priority of thread used by the driver to handle interrupts.
+
+config EN11_THREAD_STACK_SIZE
+ int "Thread stack size"
+ depends on EN11_TRIGGER_OWN_THREAD
+ default 1024
+ help
+ Stack size of thread used by the driver to handle interrupts.
+
+endif # EN11
diff --git a/app/src/main.c b/app/src/main.c
index 92ecc8b..f42c7c4 100644
--- a/app/src/main.c
+++ b/app/src/main.c
@@ -8,6 +8,7 @@
#include <device.h>
#include <devicetree.h>
#include <settings/settings.h>
+#include <drivers/sensor.h>
#include <logging/log.h>
LOG_MODULE_REGISTER(zmk, CONFIG_ZMK_LOG_LEVEL);
@@ -18,6 +19,27 @@ LOG_MODULE_REGISTER(zmk, CONFIG_ZMK_LOG_LEVEL);
#define ZMK_KSCAN_DEV DT_LABEL(ZMK_MATRIX_NODE_ID)
+static struct sensor_trigger trigger;
+
+void encoder_change(struct device *dev, struct sensor_trigger *trigger)
+{
+ LOG_DBG("");
+}
+
+void init_sensor()
+{
+ struct device *dev = device_get_binding("Rotary Encoder");
+ if (!dev) {
+ LOG_DBG("NO ENCODER!");
+ return;
+ }
+
+ trigger.type = SENSOR_TRIG_DATA_READY;
+ trigger.chan = SENSOR_CHAN_ROTATION;
+
+ sensor_trigger_set(dev, &trigger, encoder_change);
+}
+
void main(void)
{
printk("Welcome to ZMK!\n");
@@ -31,4 +53,6 @@ void main(void)
#ifdef CONFIG_SETTINGS
settings_load();
#endif
+
+ init_sensor();
}