Skip to content

Commit 4dfe251

Browse files
ubiedakartben
authored andcommitted
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>
1 parent c1f3e2c commit 4dfe251

File tree

6 files changed

+157
-7
lines changed

6 files changed

+157
-7
lines changed

drivers/sensor/pni/rm3100/rm3100.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
#include <zephyr/rtio/rtio.h>
1313
#include <zephyr/rtio/work.h>
1414
#include <zephyr/sys/check.h>
15+
#include <zephyr/sys/byteorder.h>
16+
17+
#include <zephyr/dt-bindings/sensor/rm3100.h>
1518

1619
#include "rm3100.h"
1720
#include "rm3100_reg.h"
@@ -130,6 +133,7 @@ static DEVICE_API(sensor, rm3100_driver_api) = {
130133

131134
static int rm3100_init(const struct device *dev)
132135
{
136+
struct rm3100_data *data = dev->data;
133137
uint8_t val;
134138
int err;
135139

@@ -145,6 +149,36 @@ static int rm3100_init(const struct device *dev)
145149
}
146150
LOG_DBG("RM3100 chip ID confirmed: 0x%02x", val);
147151

152+
uint16_t cycle_count[] = {
153+
sys_be16_to_cpu(RM3100_CYCLE_COUNT_DEFAULT),
154+
sys_be16_to_cpu(RM3100_CYCLE_COUNT_DEFAULT),
155+
sys_be16_to_cpu(RM3100_CYCLE_COUNT_DEFAULT)
156+
};
157+
158+
/** Setting ODR requires adjusting Cycle-count should it be 600-HZ ODR,
159+
* because at default cycle-count, the max ODR is 440 Hz, which will
160+
* override our setting.
161+
*/
162+
if (data->settings.odr == RM3100_DT_ODR_600) {
163+
cycle_count[0] = sys_be16_to_cpu(RM3100_CYCLE_COUNT_HIGH_ODR);
164+
cycle_count[1] = sys_be16_to_cpu(RM3100_CYCLE_COUNT_HIGH_ODR);
165+
cycle_count[2] = sys_be16_to_cpu(RM3100_CYCLE_COUNT_HIGH_ODR);
166+
}
167+
err = rm3100_bus_write(dev, RM3100_REG_CCX_MSB,
168+
(uint8_t *)cycle_count, sizeof(cycle_count));
169+
if (err < 0) {
170+
LOG_ERR("Failed to set cycle count: %d", err);
171+
return err;
172+
}
173+
174+
val = data->settings.odr;
175+
176+
err = rm3100_bus_write(dev, RM3100_REG_TMRC, &val, 1);
177+
if (err < 0) {
178+
LOG_ERR("Failed to set ODR: %d", err);
179+
return err;
180+
}
181+
148182
/** Enable Continuous measurement on all axis */
149183
val = RM3100_CMM_ALL_AXIS;
150184

@@ -169,6 +203,9 @@ static int rm3100_init(const struct device *dev)
169203
.iodev = &rm3100_bus_##inst, \
170204
.ctx = &rm3100_rtio_ctx_##inst, \
171205
}, \
206+
.settings = { \
207+
.odr = DT_INST_PROP(inst, odr), \
208+
}, \
172209
}; \
173210
\
174211
SENSOR_DEVICE_DT_INST_DEFINE(inst, rm3100_init, NULL, \

drivers/sensor/pni/rm3100/rm3100.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ struct rm3100_encoded_data {
2020
struct {
2121
uint64_t timestamp;
2222
uint8_t channels : 3;
23+
uint16_t cycle_count;
2324
} header;
2425
union {
2526
uint8_t payload[RM3100_TOTAL_BYTES];
@@ -41,6 +42,9 @@ struct rm3100_data {
4142
struct rtio_iodev *iodev;
4243
struct rtio *ctx;
4344
} rtio;
45+
struct {
46+
uint8_t odr;
47+
} settings;
4448
};
4549

4650
#endif /* ZEPHYR_DRIVERS_SENSOR_PNI_RM3100_H_ */

drivers/sensor/pni/rm3100/rm3100_decoder.c

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <zephyr/drivers/sensor_clock.h>
1010
#include <zephyr/sys/util.h>
1111
#include <zephyr/sys/byteorder.h>
12+
#include <zephyr/dt-bindings/sensor/rm3100.h>
1213
#include "rm3100.h"
1314

1415
uint8_t rm3100_encode_channel(enum sensor_channel chan)
@@ -33,12 +34,19 @@ int rm3100_encode(const struct device *dev,
3334
size_t num_channels,
3435
uint8_t *buf)
3536
{
37+
const struct rm3100_data *data = dev->data;
3638
struct rm3100_encoded_data *edata = (struct rm3100_encoded_data *)buf;
3739
uint64_t cycles;
3840
int err;
3941

4042
edata->header.channels = 0;
4143

44+
if (data->settings.odr == RM3100_DT_ODR_600) {
45+
edata->header.cycle_count = RM3100_CYCLE_COUNT_HIGH_ODR;
46+
} else {
47+
edata->header.cycle_count = RM3100_CYCLE_COUNT_DEFAULT;
48+
}
49+
4250
for (size_t i = 0; i < num_channels; i++) {
4351
edata->header.channels |= rm3100_encode_channel(channels[i].chan_type);
4452
}
@@ -105,19 +113,30 @@ static int rm3100_decoder_get_frame_count(const uint8_t *buffer,
105113
return -1;
106114
}
107115

108-
static int rm3100_convert_raw_to_q31(uint32_t raw_reading, q31_t *out, int8_t *shift)
116+
static int rm3100_convert_raw_to_q31(uint16_t cycle_count, uint32_t raw_reading,
117+
q31_t *out, int8_t *shift)
109118
{
110119
int64_t value;
120+
uint8_t divider;
111121

112122
raw_reading = sys_be24_to_cpu(raw_reading);
113123
value = sign_extend(raw_reading, 23);
114124

115125
/** Convert to Gauss, assuming 1 LSB = 75 uT, given default Cycle-Counting (200).
116126
* We can represent the largest sample (2^23 LSB) in Gauss with 11 bits.
117127
*/
118-
*shift = 11;
128+
if (cycle_count == RM3100_CYCLE_COUNT_DEFAULT) {
129+
*shift = 11;
130+
divider = 75;
131+
} else {
132+
/** Otherwise, it's 1 LSB = 38 uT at Cycle-counting for 600 Hz ODR (100):
133+
* 12-bits max value.
134+
*/
135+
*shift = 12;
136+
divider = 38;
137+
}
119138

120-
int64_t micro_tesla_scaled = ((int64_t)value << (31 - *shift)) / 75;
139+
int64_t micro_tesla_scaled = ((int64_t)value << (31 - *shift)) / divider;
121140
int64_t gauss_scaled = (int64_t)micro_tesla_scaled / 100;
122141

123142
*out = gauss_scaled;
@@ -166,7 +185,8 @@ static int rm3100_decoder_decode(const uint8_t *buffer,
166185
raw_reading = edata->magn.z;
167186
}
168187

169-
rm3100_convert_raw_to_q31(raw_reading, &out->readings->value, &out->shift);
188+
rm3100_convert_raw_to_q31(
189+
edata->header.cycle_count, raw_reading, &out->readings->value, &out->shift);
170190

171191
*fit = 1;
172192
return 1;
@@ -182,9 +202,12 @@ static int rm3100_decoder_decode(const uint8_t *buffer,
182202
out->header.base_timestamp_ns = edata->header.timestamp;
183203
out->header.reading_count = 1;
184204

185-
rm3100_convert_raw_to_q31(edata->magn.x, &out->readings[0].x, &out->shift);
186-
rm3100_convert_raw_to_q31(edata->magn.y, &out->readings[0].y, &out->shift);
187-
rm3100_convert_raw_to_q31(edata->magn.z, &out->readings[0].z, &out->shift);
205+
rm3100_convert_raw_to_q31(
206+
edata->header.cycle_count, edata->magn.x, &out->readings[0].x, &out->shift);
207+
rm3100_convert_raw_to_q31(
208+
edata->header.cycle_count, edata->magn.y, &out->readings[0].y, &out->shift);
209+
rm3100_convert_raw_to_q31(
210+
edata->header.cycle_count, edata->magn.z, &out->readings[0].z, &out->shift);
188211

189212
*fit = 1;
190213
return 1;

drivers/sensor/pni/rm3100/rm3100_reg.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@
1010

1111
/* RM3100 register addresses */
1212
#define RM3100_REG_CMM 0x01 /* Continuous measurement mode */
13+
#define RM3100_REG_CCX_MSB 0x04 /* Cycle Count X LSB */
14+
#define RM3100_REG_CCX_LSB 0x05 /* Cycle Count X MSB */
15+
#define RM3100_REG_CCY_MSB 0x06 /* Cycle Count Y LSB */
16+
#define RM3100_REG_CCY_LSB 0x07 /* Cycle Count Y MSB */
17+
#define RM3100_REG_CCZ_MSB 0x08 /* Cycle Count Z LSB */
18+
#define RM3100_REG_CCZ_LSB 0x09 /* Cycle Count Z MSB */
19+
#define RM3100_REG_TMRC 0x0B /* Continuous Mode Update Rate */
1320
#define RM3100_REG_MX 0x24 /* Measurement results X (3 bytes) */
1421
#define RM3100_REG_MY 0x27 /* Measurement results Y (3 bytes) */
1522
#define RM3100_REG_MZ 0x2A /* Measurement results Z (3 bytes) */
@@ -21,4 +28,8 @@
2128

2229
#define RM3100_CMM_ALL_AXIS 0x71
2330

31+
#define RM3100_CYCLE_COUNT_DEFAULT 0x00C8 /* Default Cycle Count value */
32+
#define RM3100_CYCLE_COUNT_HIGH_ODR 0x0064 /* Cycle count value required for 600 Hz ODR */
33+
34+
2435
#endif /* ZEPHYR_DRIVERS_SENSOR_PNI_RM3100_REG_H_ */

dts/bindings/sensor/pni,rm3100.yaml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,43 @@ description: |
77
88
The RM3100 can use either I2C or SPI as a communication bus.
99
This driver currently supports I2C only.
10+
When setting the odr property in a .dts or .dtsi file you may include rm3100.h
11+
and use the macros defined there.
12+
13+
Example:
14+
#include <zephyr/dt-bindings/sensor/rm3100.h>
15+
16+
&i2c0 {
17+
rm3100@20 {
18+
compatible = "pni,rm3100";
19+
reg = <0x20>;
20+
odr = <RM3100_DT_ODR_600>;
21+
};
22+
};
1023
1124
compatible: "pni,rm3100"
1225

1326
include: [sensor-device.yaml, i2c-device.yaml]
27+
28+
properties:
29+
odr:
30+
type: int
31+
default: 0x96
32+
description: |
33+
The output data rate (ODR) of the sensor in Hz.
34+
Default is power-on setting.
35+
enum:
36+
- 0x92 # RM33100_DT_ODR_600
37+
- 0x93 # RM33100_DT_ODR_300
38+
- 0x94 # RM33100_DT_ODR_150
39+
- 0x95 # RM33100_DT_ODR_75
40+
- 0x96 # RM33100_DT_ODR_37_5
41+
- 0x97 # RM33100_DT_ODR_18
42+
- 0x98 # RM33100_DT_ODR_9
43+
- 0x99 # RM33100_DT_ODR_4_5
44+
- 0x9A # RM33100_DT_ODR_2_3
45+
- 0x9B # RM33100_DT_ODR_1_2
46+
- 0x9C # RM33100_DT_ODR_0_6
47+
- 0x9D # RM33100_DT_ODR_0_3
48+
- 0x9E # RM33100_DT_ODR_0_015
49+
- 0x9F # RM33100_DT_ODR_0_0075
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright (c) 2024 Intel Corporation
3+
* Copyright (c) 2025 Croxel Inc.
4+
* Copyright (c) 2025 CogniPilot Foundation
5+
*
6+
* SPDX-License-Identifier: Apache-2.0
7+
*/
8+
#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_PNI_RM3100_H_
9+
#define ZEPHYR_INCLUDE_DT_BINDINGS_PNI_RM3100_H_
10+
11+
/**
12+
* @defgroup RM3100 PNI DT Options
13+
* @ingroup sensor_interface
14+
* @{
15+
*/
16+
17+
/**
18+
* @defgroup RM3100_ODR Output data rate options
19+
* @{
20+
*/
21+
#define RM3100_DT_ODR_600 0x92
22+
#define RM3100_DT_ODR_300 0x93
23+
#define RM3100_DT_ODR_150 0x94
24+
#define RM3100_DT_ODR_75 0x95
25+
#define RM3100_DT_ODR_37_5 0x96
26+
#define RM3100_DT_ODR_18 0x97
27+
#define RM3100_DT_ODR_9 0x98
28+
#define RM3100_DT_ODR_4_5 0x99
29+
#define RM3100_DT_ODR_2_3 0x9A
30+
#define RM3100_DT_ODR_1_2 0x9B
31+
#define RM3100_DT_ODR_0_6 0x9C
32+
#define RM3100_DT_ODR_0_3 0x9D
33+
#define RM3100_DT_ODR_0_015 0x9E
34+
#define RM3100_DT_ODR_0_0075 0x9F
35+
/** @} */
36+
37+
/** @} */
38+
39+
#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_PNI_RM3100_H_ */

0 commit comments

Comments
 (0)