sensor: rm3100: Add ODR build-time setting through DTS property
Using pre-defined values displayed on datasheet's table 5-4 for CMM Update Rates. Please note that datasheet specifies these Update-Rates may have up to 7% standard deviation, which may be significant for certain applications. Signed-off-by: Luis Ubieda <luisf@croxel.com>
This commit is contained in:
parent
c1f3e2c712
commit
4dfe251986
6 changed files with 157 additions and 7 deletions
|
@ -12,6 +12,9 @@
|
|||
#include <zephyr/rtio/rtio.h>
|
||||
#include <zephyr/rtio/work.h>
|
||||
#include <zephyr/sys/check.h>
|
||||
#include <zephyr/sys/byteorder.h>
|
||||
|
||||
#include <zephyr/dt-bindings/sensor/rm3100.h>
|
||||
|
||||
#include "rm3100.h"
|
||||
#include "rm3100_reg.h"
|
||||
|
@ -130,6 +133,7 @@ static DEVICE_API(sensor, rm3100_driver_api) = {
|
|||
|
||||
static int rm3100_init(const struct device *dev)
|
||||
{
|
||||
struct rm3100_data *data = dev->data;
|
||||
uint8_t val;
|
||||
int err;
|
||||
|
||||
|
@ -145,6 +149,36 @@ static int rm3100_init(const struct device *dev)
|
|||
}
|
||||
LOG_DBG("RM3100 chip ID confirmed: 0x%02x", val);
|
||||
|
||||
uint16_t cycle_count[] = {
|
||||
sys_be16_to_cpu(RM3100_CYCLE_COUNT_DEFAULT),
|
||||
sys_be16_to_cpu(RM3100_CYCLE_COUNT_DEFAULT),
|
||||
sys_be16_to_cpu(RM3100_CYCLE_COUNT_DEFAULT)
|
||||
};
|
||||
|
||||
/** Setting ODR requires adjusting Cycle-count should it be 600-HZ ODR,
|
||||
* because at default cycle-count, the max ODR is 440 Hz, which will
|
||||
* override our setting.
|
||||
*/
|
||||
if (data->settings.odr == RM3100_DT_ODR_600) {
|
||||
cycle_count[0] = sys_be16_to_cpu(RM3100_CYCLE_COUNT_HIGH_ODR);
|
||||
cycle_count[1] = sys_be16_to_cpu(RM3100_CYCLE_COUNT_HIGH_ODR);
|
||||
cycle_count[2] = sys_be16_to_cpu(RM3100_CYCLE_COUNT_HIGH_ODR);
|
||||
}
|
||||
err = rm3100_bus_write(dev, RM3100_REG_CCX_MSB,
|
||||
(uint8_t *)cycle_count, sizeof(cycle_count));
|
||||
if (err < 0) {
|
||||
LOG_ERR("Failed to set cycle count: %d", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
val = data->settings.odr;
|
||||
|
||||
err = rm3100_bus_write(dev, RM3100_REG_TMRC, &val, 1);
|
||||
if (err < 0) {
|
||||
LOG_ERR("Failed to set ODR: %d", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
/** Enable Continuous measurement on all axis */
|
||||
val = RM3100_CMM_ALL_AXIS;
|
||||
|
||||
|
@ -169,6 +203,9 @@ static int rm3100_init(const struct device *dev)
|
|||
.iodev = &rm3100_bus_##inst, \
|
||||
.ctx = &rm3100_rtio_ctx_##inst, \
|
||||
}, \
|
||||
.settings = { \
|
||||
.odr = DT_INST_PROP(inst, odr), \
|
||||
}, \
|
||||
}; \
|
||||
\
|
||||
SENSOR_DEVICE_DT_INST_DEFINE(inst, rm3100_init, NULL, \
|
||||
|
|
|
@ -20,6 +20,7 @@ struct rm3100_encoded_data {
|
|||
struct {
|
||||
uint64_t timestamp;
|
||||
uint8_t channels : 3;
|
||||
uint16_t cycle_count;
|
||||
} header;
|
||||
union {
|
||||
uint8_t payload[RM3100_TOTAL_BYTES];
|
||||
|
@ -41,6 +42,9 @@ struct rm3100_data {
|
|||
struct rtio_iodev *iodev;
|
||||
struct rtio *ctx;
|
||||
} rtio;
|
||||
struct {
|
||||
uint8_t odr;
|
||||
} settings;
|
||||
};
|
||||
|
||||
#endif /* ZEPHYR_DRIVERS_SENSOR_PNI_RM3100_H_ */
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <zephyr/drivers/sensor_clock.h>
|
||||
#include <zephyr/sys/util.h>
|
||||
#include <zephyr/sys/byteorder.h>
|
||||
#include <zephyr/dt-bindings/sensor/rm3100.h>
|
||||
#include "rm3100.h"
|
||||
|
||||
uint8_t rm3100_encode_channel(enum sensor_channel chan)
|
||||
|
@ -33,12 +34,19 @@ int rm3100_encode(const struct device *dev,
|
|||
size_t num_channels,
|
||||
uint8_t *buf)
|
||||
{
|
||||
const struct rm3100_data *data = dev->data;
|
||||
struct rm3100_encoded_data *edata = (struct rm3100_encoded_data *)buf;
|
||||
uint64_t cycles;
|
||||
int err;
|
||||
|
||||
edata->header.channels = 0;
|
||||
|
||||
if (data->settings.odr == RM3100_DT_ODR_600) {
|
||||
edata->header.cycle_count = RM3100_CYCLE_COUNT_HIGH_ODR;
|
||||
} else {
|
||||
edata->header.cycle_count = RM3100_CYCLE_COUNT_DEFAULT;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < num_channels; i++) {
|
||||
edata->header.channels |= rm3100_encode_channel(channels[i].chan_type);
|
||||
}
|
||||
|
@ -105,9 +113,11 @@ static int rm3100_decoder_get_frame_count(const uint8_t *buffer,
|
|||
return -1;
|
||||
}
|
||||
|
||||
static int rm3100_convert_raw_to_q31(uint32_t raw_reading, q31_t *out, int8_t *shift)
|
||||
static int rm3100_convert_raw_to_q31(uint16_t cycle_count, uint32_t raw_reading,
|
||||
q31_t *out, int8_t *shift)
|
||||
{
|
||||
int64_t value;
|
||||
uint8_t divider;
|
||||
|
||||
raw_reading = sys_be24_to_cpu(raw_reading);
|
||||
value = sign_extend(raw_reading, 23);
|
||||
|
@ -115,9 +125,18 @@ static int rm3100_convert_raw_to_q31(uint32_t raw_reading, q31_t *out, int8_t *s
|
|||
/** Convert to Gauss, assuming 1 LSB = 75 uT, given default Cycle-Counting (200).
|
||||
* We can represent the largest sample (2^23 LSB) in Gauss with 11 bits.
|
||||
*/
|
||||
*shift = 11;
|
||||
if (cycle_count == RM3100_CYCLE_COUNT_DEFAULT) {
|
||||
*shift = 11;
|
||||
divider = 75;
|
||||
} else {
|
||||
/** Otherwise, it's 1 LSB = 38 uT at Cycle-counting for 600 Hz ODR (100):
|
||||
* 12-bits max value.
|
||||
*/
|
||||
*shift = 12;
|
||||
divider = 38;
|
||||
}
|
||||
|
||||
int64_t micro_tesla_scaled = ((int64_t)value << (31 - *shift)) / 75;
|
||||
int64_t micro_tesla_scaled = ((int64_t)value << (31 - *shift)) / divider;
|
||||
int64_t gauss_scaled = (int64_t)micro_tesla_scaled / 100;
|
||||
|
||||
*out = gauss_scaled;
|
||||
|
@ -166,7 +185,8 @@ static int rm3100_decoder_decode(const uint8_t *buffer,
|
|||
raw_reading = edata->magn.z;
|
||||
}
|
||||
|
||||
rm3100_convert_raw_to_q31(raw_reading, &out->readings->value, &out->shift);
|
||||
rm3100_convert_raw_to_q31(
|
||||
edata->header.cycle_count, raw_reading, &out->readings->value, &out->shift);
|
||||
|
||||
*fit = 1;
|
||||
return 1;
|
||||
|
@ -182,9 +202,12 @@ static int rm3100_decoder_decode(const uint8_t *buffer,
|
|||
out->header.base_timestamp_ns = edata->header.timestamp;
|
||||
out->header.reading_count = 1;
|
||||
|
||||
rm3100_convert_raw_to_q31(edata->magn.x, &out->readings[0].x, &out->shift);
|
||||
rm3100_convert_raw_to_q31(edata->magn.y, &out->readings[0].y, &out->shift);
|
||||
rm3100_convert_raw_to_q31(edata->magn.z, &out->readings[0].z, &out->shift);
|
||||
rm3100_convert_raw_to_q31(
|
||||
edata->header.cycle_count, edata->magn.x, &out->readings[0].x, &out->shift);
|
||||
rm3100_convert_raw_to_q31(
|
||||
edata->header.cycle_count, edata->magn.y, &out->readings[0].y, &out->shift);
|
||||
rm3100_convert_raw_to_q31(
|
||||
edata->header.cycle_count, edata->magn.z, &out->readings[0].z, &out->shift);
|
||||
|
||||
*fit = 1;
|
||||
return 1;
|
||||
|
|
|
@ -10,6 +10,13 @@
|
|||
|
||||
/* RM3100 register addresses */
|
||||
#define RM3100_REG_CMM 0x01 /* Continuous measurement mode */
|
||||
#define RM3100_REG_CCX_MSB 0x04 /* Cycle Count X LSB */
|
||||
#define RM3100_REG_CCX_LSB 0x05 /* Cycle Count X MSB */
|
||||
#define RM3100_REG_CCY_MSB 0x06 /* Cycle Count Y LSB */
|
||||
#define RM3100_REG_CCY_LSB 0x07 /* Cycle Count Y MSB */
|
||||
#define RM3100_REG_CCZ_MSB 0x08 /* Cycle Count Z LSB */
|
||||
#define RM3100_REG_CCZ_LSB 0x09 /* Cycle Count Z MSB */
|
||||
#define RM3100_REG_TMRC 0x0B /* Continuous Mode Update Rate */
|
||||
#define RM3100_REG_MX 0x24 /* Measurement results X (3 bytes) */
|
||||
#define RM3100_REG_MY 0x27 /* Measurement results Y (3 bytes) */
|
||||
#define RM3100_REG_MZ 0x2A /* Measurement results Z (3 bytes) */
|
||||
|
@ -21,4 +28,8 @@
|
|||
|
||||
#define RM3100_CMM_ALL_AXIS 0x71
|
||||
|
||||
#define RM3100_CYCLE_COUNT_DEFAULT 0x00C8 /* Default Cycle Count value */
|
||||
#define RM3100_CYCLE_COUNT_HIGH_ODR 0x0064 /* Cycle count value required for 600 Hz ODR */
|
||||
|
||||
|
||||
#endif /* ZEPHYR_DRIVERS_SENSOR_PNI_RM3100_REG_H_ */
|
||||
|
|
|
@ -7,7 +7,43 @@ description: |
|
|||
|
||||
The RM3100 can use either I2C or SPI as a communication bus.
|
||||
This driver currently supports I2C only.
|
||||
When setting the odr property in a .dts or .dtsi file you may include rm3100.h
|
||||
and use the macros defined there.
|
||||
|
||||
Example:
|
||||
#include <zephyr/dt-bindings/sensor/rm3100.h>
|
||||
|
||||
&i2c0 {
|
||||
rm3100@20 {
|
||||
compatible = "pni,rm3100";
|
||||
reg = <0x20>;
|
||||
odr = <RM3100_DT_ODR_600>;
|
||||
};
|
||||
};
|
||||
|
||||
compatible: "pni,rm3100"
|
||||
|
||||
include: [sensor-device.yaml, i2c-device.yaml]
|
||||
|
||||
properties:
|
||||
odr:
|
||||
type: int
|
||||
default: 0x96
|
||||
description: |
|
||||
The output data rate (ODR) of the sensor in Hz.
|
||||
Default is power-on setting.
|
||||
enum:
|
||||
- 0x92 # RM33100_DT_ODR_600
|
||||
- 0x93 # RM33100_DT_ODR_300
|
||||
- 0x94 # RM33100_DT_ODR_150
|
||||
- 0x95 # RM33100_DT_ODR_75
|
||||
- 0x96 # RM33100_DT_ODR_37_5
|
||||
- 0x97 # RM33100_DT_ODR_18
|
||||
- 0x98 # RM33100_DT_ODR_9
|
||||
- 0x99 # RM33100_DT_ODR_4_5
|
||||
- 0x9A # RM33100_DT_ODR_2_3
|
||||
- 0x9B # RM33100_DT_ODR_1_2
|
||||
- 0x9C # RM33100_DT_ODR_0_6
|
||||
- 0x9D # RM33100_DT_ODR_0_3
|
||||
- 0x9E # RM33100_DT_ODR_0_015
|
||||
- 0x9F # RM33100_DT_ODR_0_0075
|
||||
|
|
39
include/zephyr/dt-bindings/sensor/rm3100.h
Normal file
39
include/zephyr/dt-bindings/sensor/rm3100.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Intel Corporation
|
||||
* Copyright (c) 2025 Croxel Inc.
|
||||
* Copyright (c) 2025 CogniPilot Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_PNI_RM3100_H_
|
||||
#define ZEPHYR_INCLUDE_DT_BINDINGS_PNI_RM3100_H_
|
||||
|
||||
/**
|
||||
* @defgroup RM3100 PNI DT Options
|
||||
* @ingroup sensor_interface
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup RM3100_ODR Output data rate options
|
||||
* @{
|
||||
*/
|
||||
#define RM3100_DT_ODR_600 0x92
|
||||
#define RM3100_DT_ODR_300 0x93
|
||||
#define RM3100_DT_ODR_150 0x94
|
||||
#define RM3100_DT_ODR_75 0x95
|
||||
#define RM3100_DT_ODR_37_5 0x96
|
||||
#define RM3100_DT_ODR_18 0x97
|
||||
#define RM3100_DT_ODR_9 0x98
|
||||
#define RM3100_DT_ODR_4_5 0x99
|
||||
#define RM3100_DT_ODR_2_3 0x9A
|
||||
#define RM3100_DT_ODR_1_2 0x9B
|
||||
#define RM3100_DT_ODR_0_6 0x9C
|
||||
#define RM3100_DT_ODR_0_3 0x9D
|
||||
#define RM3100_DT_ODR_0_015 0x9E
|
||||
#define RM3100_DT_ODR_0_0075 0x9F
|
||||
/** @} */
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_PNI_RM3100_H_ */
|
Loading…
Add table
Add a link
Reference in a new issue