blob: c5775e74701bf0c88cb28664fbe69a7b907f71cd [file] [log] [blame]
/*
* 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)