/* * Copyright (c) 2022, Felipe Neves * * SPDX-License-Identifier: Apache-2.0 */ #define DT_DRV_COMPAT ams_as5600 #include #include #include #include #include #include #include #include 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 #define AS5600_MILLION_UNIT 1000000 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) % AS5600_PULSES_PER_REV) * (AS5600_MILLION_UNIT / 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 DEVICE_API(sensor, 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)