cd04926d6b
magnetic angle sensor driver. Signed-off-by: Felipe Neves <felipe.neves@linaro.org>
100 lines
2.3 KiB
C
100 lines
2.3 KiB
C
/*
|
|
* Copyright (c) 2022, Felipe Neves
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#define DT_DRV_COMPAT ams_as5600
|
|
|
|
#include <errno.h>
|
|
#include <zephyr/sys/__assert.h>
|
|
#include <zephyr/sys/util.h>
|
|
#include <zephyr/device.h>
|
|
#include <zephyr/init.h>
|
|
#include <zephyr/drivers/sensor.h>
|
|
#include <zephyr/drivers/i2c.h>
|
|
#include <zephyr/logging/log.h>
|
|
LOG_MODULE_REGISTER(ams_as5600, CONFIG_SENSOR_LOG_LEVEL);
|
|
|
|
#define AS5600_ANGLE_REGISTER_H 0x0E
|
|
#define AS5600_FULL_ANGLE 360
|
|
#define AS5600_PULSES_PER_REV 4096
|
|
|
|
struct as5600_dev_cfg {
|
|
struct i2c_dt_spec i2c_port;
|
|
};
|
|
|
|
/* Device run time data */
|
|
struct as5600_dev_data {
|
|
uint16_t position;
|
|
};
|
|
|
|
static int as5600_fetch(const struct device *dev, enum sensor_channel chan)
|
|
{
|
|
struct as5600_dev_data *dev_data = dev->data;
|
|
const struct as5600_dev_cfg *dev_cfg = dev->config;
|
|
|
|
uint8_t read_data[2] = {0, 0};
|
|
uint8_t angle_reg = AS5600_ANGLE_REGISTER_H;
|
|
|
|
int err = i2c_write_read_dt(&dev_cfg->i2c_port,
|
|
&angle_reg,
|
|
1,
|
|
&read_data,
|
|
sizeof(read_data));
|
|
|
|
/* invalid readings preserves the last good value */
|
|
if (!err) {
|
|
dev_data->position = ((uint16_t)read_data[0] << 8) | read_data[1];
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
static int as5600_get(const struct device *dev, enum sensor_channel chan,
|
|
struct sensor_value *val)
|
|
{
|
|
struct as5600_dev_data *dev_data = dev->data;
|
|
|
|
if (chan == SENSOR_CHAN_ROTATION) {
|
|
val->val1 = ((int32_t)dev_data->position * AS5600_FULL_ANGLE) /
|
|
AS5600_PULSES_PER_REV;
|
|
|
|
val->val2 = ((int32_t)dev_data->position * AS5600_FULL_ANGLE) -
|
|
(val->val1 * AS5600_PULSES_PER_REV);
|
|
} else {
|
|
return -ENOTSUP;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int as5600_initialize(const struct device *dev)
|
|
{
|
|
struct as5600_dev_data *const dev_data = dev->data;
|
|
|
|
dev_data->position = 0;
|
|
|
|
LOG_INF("Device %s initialized", dev->name);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static const struct sensor_driver_api as5600_driver_api = {
|
|
.sample_fetch = as5600_fetch,
|
|
.channel_get = as5600_get,
|
|
};
|
|
|
|
#define AS5600_INIT(n) \
|
|
static struct as5600_dev_data as5600_data##n; \
|
|
static const struct as5600_dev_cfg as5600_cfg##n = {\
|
|
.i2c_port = I2C_DT_SPEC_INST_GET(n) \
|
|
}; \
|
|
\
|
|
SENSOR_DEVICE_DT_INST_DEFINE(n, as5600_initialize, NULL, \
|
|
&as5600_data##n, &as5600_cfg##n, \
|
|
POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, \
|
|
&as5600_driver_api);
|
|
|
|
DT_INST_FOREACH_STATUS_OKAY(AS5600_INIT)
|