EN11 is actually EC11, some sample work.

This commit is contained in:
Pete Johanson 2020-07-20 20:54:58 -04:00
parent 331bfa7052
commit 109c69cbab
11 changed files with 237 additions and 247 deletions

View File

@ -8,10 +8,11 @@
/ {
encoder: encoder0 {
compatible = "alps,en11";
compatible = "alps,ec11";
label = "Rotary Encoder";
a-gpios = <&pro_micro_d 5 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>;
b-gpios = <&pro_micro_d 9 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>;
resolution = <4>;
};
};

View File

@ -7,6 +7,6 @@ if(CONFIG_ZMK_KSCAN_GPIO_DRIVER)
kscan_gpio_direct.c
)
zephyr_library_sources_ifdef(CONFIG_EN11 en11.c)
zephyr_library_sources_ifdef(CONFIG_EN11_TRIGGER en11_trigger.c)
zephyr_library_sources_ifdef(CONFIG_EC11 ec11.c)
zephyr_library_sources_ifdef(CONFIG_EC11_TRIGGER ec11_trigger.c)
endif()

View File

@ -17,50 +17,50 @@ config ZMK_KSCAN_INIT_PRIORITY
help
Keyboard scan device driver initialization priority.
menuconfig EN11
bool "EN11 Incremental Encoder Sensor"
menuconfig EC11
bool "EC11 Incremental Encoder Sensor"
depends on GPIO
help
Enable driver for EN11 incremental encoder sensors.
Enable driver for EC11 incremental encoder sensors.
if EN11
if EC11
choice
prompt "Trigger mode"
default EN11_TRIGGER_NONE
default EC11_TRIGGER_NONE
help
Specify the type of triggering to be used by the driver.
config EN11_TRIGGER_NONE
config EC11_TRIGGER_NONE
bool "No trigger"
config EN11_TRIGGER_GLOBAL_THREAD
config EC11_TRIGGER_GLOBAL_THREAD
bool "Use global thread"
depends on GPIO
select EN11_TRIGGER
select EC11_TRIGGER
config EN11_TRIGGER_OWN_THREAD
config EC11_TRIGGER_OWN_THREAD
bool "Use own thread"
depends on GPIO
select EN11_TRIGGER
select EC11_TRIGGER
endchoice
config EN11_TRIGGER
config EC11_TRIGGER
bool
config EN11_THREAD_PRIORITY
config EC11_THREAD_PRIORITY
int "Thread priority"
depends on EN11_TRIGGER_OWN_THREAD
depends on EC11_TRIGGER_OWN_THREAD
default 10
help
Priority of thread used by the driver to handle interrupts.
config EN11_THREAD_STACK_SIZE
config EC11_THREAD_STACK_SIZE
int "Thread stack size"
depends on EN11_TRIGGER_OWN_THREAD
depends on EC11_TRIGGER_OWN_THREAD
default 1024
help
Stack size of thread used by the driver to handle interrupts.
endif # EN11
endif # EC11

View File

@ -1,7 +1,7 @@
description: |
Sensor driver for the Alps en11 rotary encoder
Sensor driver for the Alps EC11 rotary encoder
compatible: "alps,en11"
compatible: "alps,ec11"
properties:
label:
@ -15,3 +15,7 @@ properties:
type: phandle-array
required: true
description: A pin for the encoder
resolution:
type: int
description: Number of pulses per tick
required: false

132
app/drivers/zephyr/ec11.c Normal file
View File

@ -0,0 +1,132 @@
/*
* Copyright (c) 2020 Peter Johanson
*
* SPDX-License-Identifier: MIT
*/
#define DT_DRV_COMPAT alps_ec11
#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 "ec11.h"
LOG_MODULE_REGISTER(EC11, CONFIG_SENSOR_LOG_LEVEL);
static int ec11_sample_fetch(struct device *dev, enum sensor_channel chan)
{
struct ec11_data *drv_data = dev->driver_data;
const struct ec11_config *drv_cfg = dev->config_info;
u8_t val;
u8_t delta;
__ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_ROTATION);
val = (gpio_pin_get(drv_data->a, drv_cfg->a_pin) << 1) | gpio_pin_get(drv_data->b, drv_cfg->b_pin);
LOG_DBG("prev: %d, new: %d", drv_data->ab_state, val);
switch(val | (drv_data->ab_state << 2)) {
case 0b0001: case 0b0111: case 0b1110:
LOG_DBG("+1");
delta = 1;
break;
default:
LOG_DBG("FIGURE IT OUT!");
break;
}
LOG_DBG("Delta: %d", delta);
// if (ec11_reg_read(drv_data, EC11_REG_TOBJ, &val) < 0) {
// return -EIO;
// }
// if (val & EC11_DATA_INVALID_BIT) {
// return -EIO;
// }
// drv_data->sample = arithmetic_shift_right((s16_t)val, 2);
return 0;
}
static int ec11_channel_get(struct device *dev,
enum sensor_channel chan,
struct sensor_value *val)
{
struct ec11_data *drv_data = dev->driver_data;
// s32_t uval;
// if (chan != SENSOR_CHAN_AMBIENT_TEMP) {
// return -ENOTSUP;
// }
// uval = (s32_t)drv_data->sample * EC11_TEMP_SCALE;
// val->val1 = uval / 1000000;
// val->val2 = uval % 1000000;
return 0;
}
static const struct sensor_driver_api ec11_driver_api = {
#ifdef CONFIG_EC11_TRIGGER
.trigger_set = ec11_trigger_set,
#endif
.sample_fetch = ec11_sample_fetch,
.channel_get = ec11_channel_get,
};
int ec11_init(struct device *dev)
{
struct ec11_data *drv_data = dev->driver_data;
const struct ec11_config *drv_cfg = dev->config_info;
LOG_DBG("resolution %d", drv_cfg->resolution);
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_EC11_TRIGGER
if (ec11_init_interrupt(dev) < 0) {
LOG_DBG("Failed to initialize interrupt!");
return -EIO;
}
#endif
return 0;
}
struct ec11_data ec11_data;
const struct ec11_config ec11_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),
COND_CODE_0(DT_INST_NODE_HAS_PROP(0, resolution), (1), (DT_INST_PROP(0, resolution))),
};
DEVICE_AND_API_INIT(ec11, DT_INST_LABEL(0), ec11_init,
&ec11_data,
&ec11_cfg, POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY,
&ec11_driver_api);

View File

@ -10,7 +10,7 @@
#include <drivers/gpio.h>
#include <sys/util.h>
struct en11_config {
struct ec11_config {
const char *a_label;
const u8_t a_pin;
const u8_t a_flags;
@ -18,20 +18,23 @@ struct en11_config {
const char *b_label;
const u8_t b_pin;
const u8_t b_flags;
const u8_t resolution;
};
enum en11_pin_state {
EN11_A_PIN_STATE,
EN11_B_PIN_STATE
enum ec11_pin_state {
EC11_A_PIN_STATE,
EC11_B_PIN_STATE
};
struct en11_data {
struct ec11_data {
struct device *a;
struct device *b;
u8_t ab_state;
s16_t sample;
s16_t pulse_state;
s16_t tick_state;
#ifdef CONFIG_EN11_TRIGGER
#ifdef CONFIG_EC11_TRIGGER
struct device *gpio;
struct gpio_callback a_gpio_cb;
struct gpio_callback b_gpio_cb;
@ -40,22 +43,22 @@ struct en11_data {
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);
#if defined(CONFIG_EC11_TRIGGER_OWN_THREAD)
K_THREAD_STACK_MEMBER(thread_stack, CONFIG_EC11_THREAD_STACK_SIZE);
struct k_sem gpio_sem;
struct k_thread thread;
#elif defined(CONFIG_EN11_TRIGGER_GLOBAL_THREAD)
#elif defined(CONFIG_EC11_TRIGGER_GLOBAL_THREAD)
struct k_work work;
#endif
#endif /* CONFIG_EN11_TRIGGER */
#endif /* CONFIG_EC11_TRIGGER */
};
#ifdef CONFIG_EN11_TRIGGER
#ifdef CONFIG_EC11_TRIGGER
int en11_trigger_set(struct device *dev,
int ec11_trigger_set(struct device *dev,
const struct sensor_trigger *trig,
sensor_trigger_handler_t handler);
int en11_init_interrupt(struct device *dev);
int ec11_init_interrupt(struct device *dev);
#endif

View File

@ -4,7 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
#define DT_DRV_COMPAT alps_en11
#define DT_DRV_COMPAT alps_ec11
#include <device.h>
#include <drivers/gpio.h>
@ -12,18 +12,18 @@
#include <kernel.h>
#include <drivers/sensor.h>
#include "en11.h"
#include "ec11.h"
extern struct en11_data en11_driver;
extern struct ec11_data ec11_driver;
#include <logging/log.h>
LOG_MODULE_DECLARE(EN11, CONFIG_SENSOR_LOG_LEVEL);
LOG_MODULE_DECLARE(EC11, 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;
struct ec11_data *data = dev->driver_data;
const struct ec11_config *cfg = dev->config_info;
LOG_DBG("enabled %s", (enable ? "true" : "false"));
@ -44,59 +44,60 @@ static inline void setup_int(struct device *dev,
}
}
static void en11_a_gpio_callback(struct device *dev,
static void ec11_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);
struct ec11_data *drv_data =
CONTAINER_OF(cb, struct ec11_data, a_gpio_cb);
LOG_DBG("");
setup_int(drv_data->dev, false);
#if defined(CONFIG_EN11_TRIGGER_OWN_THREAD)
#if defined(CONFIG_EC11_TRIGGER_OWN_THREAD)
k_sem_give(&drv_data->gpio_sem);
#elif defined(CONFIG_EN11_TRIGGER_GLOBAL_THREAD)
#elif defined(CONFIG_EC11_TRIGGER_GLOBAL_THREAD)
k_work_submit(&drv_data->work);
#endif
}
static void en11_b_gpio_callback(struct device *dev,
static void ec11_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);
struct ec11_data *drv_data =
CONTAINER_OF(cb, struct ec11_data, b_gpio_cb);
LOG_DBG("");
setup_int(drv_data->dev, false);
#if defined(CONFIG_EN11_TRIGGER_OWN_THREAD)
#if defined(CONFIG_EC11_TRIGGER_OWN_THREAD)
k_sem_give(&drv_data->gpio_sem);
#elif defined(CONFIG_EN11_TRIGGER_GLOBAL_THREAD)
#elif defined(CONFIG_EC11_TRIGGER_GLOBAL_THREAD)
k_work_submit(&drv_data->work);
#endif
}
static void en11_thread_cb(void *arg)
static void ec11_thread_cb(void *arg)
{
struct device *dev = arg;
struct en11_data *drv_data = dev->driver_data;
const struct en11_config *cfg = dev->config_info;
struct ec11_data *drv_data = dev->driver_data;
const struct ec11_config *cfg = dev->config_info;
u16_t status;
drv_data->handler(dev, &drv_data->trigger);
// gpio_pin_get(drv_data->a, cfg->a_pin)
// if (en11_reg_read(drv_data, EN11_REG_STATUS, &status) < 0) {
// if (ec11_reg_read(drv_data, EC11_REG_STATUS, &status) < 0) {
// return;
// }
// if (status & EN11_DATA_READY_INT_BIT &&
// if (status & EC11_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 &&
// if (status & EC11_TOBJ_TH_INT_BITS &&
// drv_data->th_handler != NULL) {
// drv_data->th_handler(dev, &drv_data->th_trigger);
// }
@ -104,41 +105,43 @@ static void en11_thread_cb(void *arg)
setup_int(dev, true);
}
#ifdef CONFIG_EN11_TRIGGER_OWN_THREAD
static void en11_thread(int dev_ptr, int unused)
#ifdef CONFIG_EC11_TRIGGER_OWN_THREAD
static void ec11_thread(int dev_ptr, int unused)
{
struct device *dev = INT_TO_POINTER(dev_ptr);
struct en11_data *drv_data = dev->driver_data;
struct ec11_data *drv_data = dev->driver_data;
ARG_UNUSED(unused);
while (1) {
k_sem_take(&drv_data->gpio_sem, K_FOREVER);
en11_thread_cb(dev);
ec11_thread_cb(dev);
}
}
#endif
#ifdef CONFIG_EN11_TRIGGER_GLOBAL_THREAD
static void en11_work_cb(struct k_work *work)
#ifdef CONFIG_EC11_TRIGGER_GLOBAL_THREAD
static void ec11_work_cb(struct k_work *work)
{
struct en11_data *drv_data =
CONTAINER_OF(work, struct en11_data, work);
struct ec11_data *drv_data =
CONTAINER_OF(work, struct ec11_data, work);
LOG_DBG("");
en11_thread_cb(drv_data->dev);
ec11_thread_cb(drv_data->dev);
}
#endif
int en11_trigger_set(struct device *dev,
int ec11_trigger_set(struct device *dev,
const struct sensor_trigger *trig,
sensor_trigger_handler_t handler)
{
struct en11_data *drv_data = dev->driver_data;
struct ec11_data *drv_data = dev->driver_data;
setup_int(dev, false);
k_msleep(5);
drv_data->trigger = *trig;
drv_data->handler = handler;
@ -147,10 +150,10 @@ int en11_trigger_set(struct device *dev,
return 0;
}
int en11_init_interrupt(struct device *dev)
int ec11_init_interrupt(struct device *dev)
{
struct en11_data *drv_data = dev->driver_data;
const struct en11_config *drv_cfg = dev->config_info;
struct ec11_data *drv_data = dev->driver_data;
const struct ec11_config *drv_cfg = dev->config_info;
drv_data->dev = dev;
/* setup gpio interrupt */
@ -165,7 +168,7 @@ int en11_init_interrupt(struct device *dev)
}
gpio_init_callback(&drv_data->a_gpio_cb,
en11_a_gpio_callback,
ec11_a_gpio_callback,
BIT(drv_cfg->a_pin));
if (gpio_add_callback(drv_data->a, &drv_data->a_gpio_cb) < 0) {
@ -181,7 +184,7 @@ int en11_init_interrupt(struct device *dev)
}
gpio_init_callback(&drv_data->b_gpio_cb,
en11_b_gpio_callback,
ec11_b_gpio_callback,
BIT(drv_cfg->b_pin));
if (gpio_add_callback(drv_data->b, &drv_data->b_gpio_cb) < 0) {
@ -191,16 +194,16 @@ int en11_init_interrupt(struct device *dev)
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)
#if defined(CONFIG_EC11_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),
CONFIG_EC11_THREAD_STACK_SIZE,
(k_thread_entry_t)ec11_thread, dev,
0, NULL, K_PRIO_COOP(CONFIG_EC11_THREAD_PRIORITY),
0, K_NO_WAIT);
#elif defined(CONFIG_EN11_TRIGGER_GLOBAL_THREAD)
drv_data->work.handler = en11_work_cb;
#elif defined(CONFIG_EC11_TRIGGER_GLOBAL_THREAD)
k_work_init(&drv_data->work, ec11_work_cb);
#endif
return 0;

View File

@ -1,110 +0,0 @@
/*
* 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);

View File

@ -1,6 +0,0 @@
# 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)

View File

@ -1,52 +0,0 @@
# 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

View File

@ -23,7 +23,22 @@ static struct sensor_trigger trigger;
void encoder_change(struct device *dev, struct sensor_trigger *trigger)
{
int err;
struct sensor_value value;
LOG_DBG("");
err = sensor_sample_fetch(dev);
if (err) {
LOG_ERR("Failed to fetch new EC11 sample");
return;
}
err = sensor_channel_get(dev, SENSOR_CHAN_ROTATION, &value);
if (err) {
LOG_DBG("Failed to get the sample for EC11 %d", err);
return;
}
}
void init_sensor()