lis2mdl_rs/register/main.rs
1use super::super::{
2 BusOperation, DelayNs, Error, Lis2mdl, RegisterOperation, SensorOperation, bisync,
3 register::OnState,
4};
5
6use bitfield_struct::bitfield;
7use derive_more::TryFrom;
8
9use st_mem_bank_macro::{named_register, register};
10
11#[repr(u8)]
12#[derive(Clone, Copy, PartialEq)]
13pub enum Reg {
14 OffsetXRegL = 0x45,
15 OffsetXRegH = 0x46,
16 OffsetYRegL = 0x47,
17 OffsetYRegH = 0x48,
18 OffsetZRegL = 0x49,
19 OffsetZRegH = 0x4A,
20 WhoAmI = 0x4F,
21 CfgRegA = 0x60,
22 CfgRegB = 0x61,
23 CfgRegC = 0x62,
24 IntCrtlReg = 0x63,
25 IntSourceReg = 0x64,
26 IntThsLReg = 0x65,
27 IntThsHReg = 0x66,
28 StatusReg = 0x67,
29 OutxLReg = 0x68,
30 OutxHReg = 0x69,
31 OutyLReg = 0x6A,
32 OutyHReg = 0x6B,
33 OutzLReg = 0x6C,
34 OutzHReg = 0x6D,
35 TempOutLReg = 0x6E,
36 TempOutHReg = 0x6F,
37}
38
39/// Offset XYZ (0x45 - 0x4A)
40///
41/// Magnetic user offset for hard-iron to compensate environmental
42/// effects.
43/// 1LSB = 1.5mg
44#[named_register(address = Reg::OffsetXRegL, access_type = "Lis2mdl<B, T, OnState>")]
45#[derive(Default, Debug)]
46pub struct OffsetXYZ {
47 pub x: i16,
48 pub y: i16,
49 pub z: i16,
50}
51
52/// WHO_AM_I (0x4F)
53///
54/// The identification register is used to identify the device
55#[register(address = Reg::WhoAmI, access_type = "Lis2mdl<B, T, OnState>")]
56#[cfg_attr(feature = "bit_order_msb", bitfield(u8, order = Msb))]
57#[cfg_attr(not(feature = "bit_order_msb"), bitfield(u8, order = Lsb))]
58pub struct WhoAmI {
59 #[bits(8, default = 0b01000000)]
60 pub who_am_i: u8,
61}
62
63/// CFG_REG_A (0x60)
64///
65/// Configuration register A (R/W)
66/// Controls output data rate, power mode, reboot, soft reset, and temperature compensation.
67#[register(address = Reg::CfgRegA, access_type = "Lis2mdl<B, T, OnState>")]
68#[cfg_attr(feature = "bit_order_msb", bitfield(u8, order = Msb))]
69#[cfg_attr(not(feature = "bit_order_msb"), bitfield(u8, order = Lsb))]
70pub struct CfgRegA {
71 /// Mode of operation selection (2 bits)
72 /// 00: Continuous mode (continuous measurement, data-ready signal generated)
73 /// 01: Single measurement mode (performs one measurement, sets DRDY high, then idle)
74 /// 10: Idle mode (I2C and SPI active)
75 /// 11: Idle mode (default)
76 /// Connected enum: Md
77 #[bits(2, default = 0b11)]
78 pub md: u8,
79 /// Output data rate configuration (2 bits)
80 /// 00: 10 Hz (default)
81 /// 01: 20 Hz
82 /// 10: 50 Hz
83 /// 11: 100 Hz
84 /// Connected enum: Odr
85 #[bits(2, default = 0b00)]
86 pub odr: u8,
87 /// Low-power mode enable (1 bit)
88 /// 0: High-resolution mode
89 /// 1: Low-power mode enabled
90 /// Connected enum: Lp
91 #[bits(1, default = 0)]
92 pub lp: u8,
93 /// Soft reset configuration and user registers (1 bit)
94 /// When set, resets configuration and user registers; flash registers keep their values.
95 #[bits(1, default = 0)]
96 pub soft_rst: u8,
97 /// Reboot magnetometer memory content (1 bit)
98 /// When set, reboots magnetometer memory content.
99 #[bits(1, default = 0)]
100 pub reboot: u8,
101 /// Temperature compensation enable (1 bit)
102 /// Must be set to 1 for correct operation.
103 #[bits(1, default = 0)]
104 pub comp_temp_en: u8,
105}
106
107/// CFG_REG_B (0x61)
108///
109/// Configuration register B (R/W)
110/// Controls offset cancellation, interrupt on data off, set pulse frequency, and low-pass filter.
111#[register(address = Reg::CfgRegB, access_type = "Lis2mdl<B, T, OnState>")]
112#[cfg_attr(feature = "bit_order_msb", bitfield(u8, order = Msb))]
113#[cfg_attr(not(feature = "bit_order_msb"), bitfield(u8, order = Lsb))]
114pub struct CfgRegB {
115 /// Digital low-pass filter enable (1 bit)
116 /// 0: Filter disabled (bandwidth = ODR/2)
117 /// 1: Filter enabled (bandwidth = ODR/4)
118 /// Connected enum: Lpf
119 #[bits(1, default = 0)]
120 pub lpf: u8,
121 /// Set pulse frequency selection (2 bits)
122 /// 00: Set pulse released every 64 ODR cycles (default)
123 /// 01: Enables offset cancellation
124 /// 10: Set pulse is released only at power-on after PD condition
125 /// Connected enum: SetRst
126 #[bits(2, default = 0)]
127 pub set_rst: u8,
128 /// Interrupt block checks data after hard-iron correction (1 bit)
129 /// If 1, interrupt recognition checks data after hard-iron correction.
130 /// Connected enum: IntOnDataoff
131 #[bits(1, default = 0)]
132 pub int_on_dataoff: u8,
133 /// Offset cancellation in single measurement mode enable (1 bit)
134 /// 0: Disabled (default)
135 /// 1: Enabled (OFF_CANC bit must be set to 1 when enabling)
136 #[bits(1, default = 0)]
137 pub off_canc_one_shot: u8,
138 /// Reserved bits (3 bits, read-only)
139 #[bits(3, access = RO, default = 0)]
140 pub not_used_01: u8,
141}
142
143/// CFG_REG_C (0x62)
144///
145/// Configuration register C (R/W)
146/// Controls interrupt pin behavior, interface selection, byte order, SPI mode, self-test, and data-ready pin.
147#[register(address = Reg::CfgRegC, access_type = "Lis2mdl<B, T, OnState>")]
148#[cfg_attr(feature = "bit_order_msb", bitfield(u8, order = Msb))]
149#[cfg_attr(not(feature = "bit_order_msb"), bitfield(u8, order = Lsb))]
150pub struct CfgRegC {
151 /// Data-ready signal driven on INT/DRDY pin (push-pull output) (1 bit)
152 #[bits(1, default = 0)]
153 pub drdy_on_pin: u8,
154 /// Self-test enable (1 bit)
155 #[bits(1, default = 0)]
156 pub self_test: u8,
157 /// Enable 4-wire SPI interface (disables interrupt and data-ready signaling) (1 bit)
158 /// Connected enum: Sim
159 #[bits(1, default = 0)]
160 pub four_wire_spi: u8,
161 /// Byte order inversion (low and high bytes of data are swapped) (1 bit)
162 #[bits(1, default = 0)]
163 pub ble: u8,
164 /// Block data update enable (prevents reading incoherent data during update) (1 bit)
165 /// Connected enum: Ble
166 #[bits(1, default = 0)]
167 pub bdu: u8,
168 /// I2C interface disable (1 bit)
169 /// If 1, I2C interface is inhibited; only SPI interface can be used.
170 /// Connected enum: I2cDis
171 #[bits(1, default = 0)]
172 pub i2c_dis: u8,
173 /// Interrupt signal driven on INT/DRDY pin (push-pull output) (1 bit)
174 #[bits(1, default = 0)]
175 pub int_on_pin: u8,
176 /// Reserved bit (1 bit, read-only)
177 #[bits(1, access = RO, default = 0)]
178 pub not_used_02: u8,
179}
180
181/// INT_CRTL_REG (0x63)
182///
183/// Interrupt control register (R/W)
184/// Enables and configures interrupt recognition.
185#[register(address = Reg::IntCrtlReg, access_type = "Lis2mdl<B, T, OnState>")]
186#[cfg_attr(feature = "bit_order_msb", bitfield(u8, order = Msb))]
187#[cfg_attr(not(feature = "bit_order_msb"), bitfield(u8, order = Lsb))]
188pub struct IntCrtlReg {
189 /// Interrupt enable (1 bit)
190 /// Enables generation of interrupt (INT bit in INT_SOURCE_REG).
191 #[bits(1, default = 0b0)]
192 pub ien: u8,
193 /// Interrupt latch enable (1 bit)
194 /// 0: INT bit is pulsed
195 /// 1: INT bit is latched until INT_SOURCE_REG is read
196 #[bits(1, default = 0b0)]
197 pub iel: u8,
198 /// Interrupt polarity (1 bit)
199 /// 0: INT = 0 signals interrupt
200 /// 1: INT = 1 signals interrupt
201 #[bits(1, default = 0b0)]
202 pub iea: u8,
203 /// Reserved bits (2 bits, read-only)
204 #[bits(2, access = RO, default = 0)]
205 pub not_used_01: u8,
206 /// Z-axis interrupt enable (1 bit)
207 #[bits(1, default = 0b1)]
208 pub zien: u8,
209 /// Y-axis interrupt enable (1 bit)
210 #[bits(1, default = 0b1)]
211 pub yien: u8,
212 /// X-axis interrupt enable (1 bit)
213 #[bits(1, default = 0b1)]
214 pub xien: u8,
215}
216
217/// INT_SOURCE_REG (0x64)
218///
219/// Interrupt source register (R)
220/// Indicates interrupt event status and axis threshold crossing.
221#[register(address = Reg::IntSourceReg, access_type = "Lis2mdl<B, T, OnState>")]
222#[cfg_attr(feature = "bit_order_msb", bitfield(u8, order = Msb))]
223#[cfg_attr(not(feature = "bit_order_msb"), bitfield(u8, order = Lsb))]
224pub struct IntSourceReg {
225 /// Interrupt event occurred (1 bit)
226 #[bits(1, access = RO)]
227 pub int: u8,
228 /// Magnetic ROI flag (1 bit)
229 /// Always enabled; reset by reading this register.
230 #[bits(1, access = RO)]
231 pub mroi: u8,
232 /// Negative threshold exceeded on Z-axis (1 bit)
233 #[bits(1, access = RO)]
234 pub n_th_s_z: u8,
235 /// Negative threshold exceeded on Y-axis (1 bit)
236 #[bits(1, access = RO)]
237 pub n_th_s_y: u8,
238 /// Negative threshold exceeded on X-axis (1 bit)
239 #[bits(1, access = RO)]
240 pub n_th_s_x: u8,
241 /// Positive threshold exceeded on Z-axis (1 bit)
242 #[bits(1, access = RO)]
243 pub p_th_s_z: u8,
244 /// Positive threshold exceeded on Y-axis (1 bit)
245 #[bits(1, access = RO)]
246 pub p_th_s_y: u8,
247 /// Positive threshold exceeded on X-axis (1 bit)
248 #[bits(1, access = RO)]
249 pub p_th_s_x: u8,
250}
251
252/// INT_THS_L_REG - INT_THS_H_REG (0x65 - 0x66)
253///
254/// These registers set the threshold value for the output to generate the interrupt (INT bit in INT_SOURCE_REG(64h)).
255/// This threshold is common to all three (axes) output values and is unsigned unipolar. The threshold value is correlated
256/// to the current gain and it is unsigned because the threshold is considered as an absolute value, but crossing the
257/// threshold is detected for both the positive and negative sides.
258#[register(address = Reg::IntThsLReg, access_type = "Lis2mdl<B, T, OnState>")]
259#[cfg_attr(feature = "bit_order_msb", bitfield(u16, order = Msb))]
260#[cfg_attr(not(feature = "bit_order_msb"), bitfield(u16, order = Lsb))]
261pub struct IntThs {
262 #[bits(16)]
263 pub threshold: u16,
264}
265
266/// STATUS_REG (0x67)
267///
268/// Status register (R)
269/// Indicates data availability and overrun status for each axis.
270#[register(address = Reg::StatusReg, access_type = "Lis2mdl<B, T, OnState>")]
271#[cfg_attr(feature = "bit_order_msb", bitfield(u8, order = Msb))]
272#[cfg_attr(not(feature = "bit_order_msb"), bitfield(u8, order = Lsb))]
273pub struct StatusReg {
274 /// X-axis new data available (1 bit)
275 #[bits(1)]
276 pub xda: u8,
277 /// Y-axis new data available (1 bit)
278 #[bits(1)]
279 pub yda: u8,
280 /// Z-axis new data available (1 bit)
281 #[bits(1)]
282 pub zda: u8,
283 /// X-, Y-, and Z-axis new data available (1 bit)
284 #[bits(1)]
285 pub zyxda: u8,
286 /// X-axis data overrun (1 bit)
287 #[bits(1)]
288 pub _xor: u8,
289 /// Y-axis data overrun (1 bit)
290 #[bits(1)]
291 pub yor: u8,
292 /// Z-axis data overrun (1 bit)
293 #[bits(1)]
294 pub zor: u8,
295 /// X-, Y-, and Z-axis data overrun (1 bit)
296 #[bits(1)]
297 pub zyxor: u8,
298}
299
300/// OutXYZ (0x68 - 0x6D)
301///
302/// The output data represents the raw magnetic data only if
303/// relative OFFSET_axis_REG is equal to zero, otherwise hard-iron
304/// calibration is included.
305#[named_register(address = Reg::OutxLReg, access_type = "Lis2mdl<B, T, OnState>")]
306pub struct OutXYZ {
307 pub x: i16,
308 pub y: i16,
309 pub z: i16,
310}
311
312/// TempOut (0x6E - 0x6F)
313///
314/// Temperature register of the sensor
315#[register(address = Reg::TempOutLReg, access_type = "Lis2mdl<B, T, OnState>")]
316#[derive(Default, Debug)]
317pub struct TempOut(pub i16);
318
319/// Mode of operation
320#[repr(u8)]
321#[derive(Clone, Copy, PartialEq, Default, Debug)]
322pub enum Md {
323 /// Continuous mode (continuous measurement, data-ready signal generated)
324 ContinuousMode = 0,
325 /// Single measurement mode (performs one measurement, sets DRDY high, then idle)
326 SingleTrigger = 1,
327 /// Idle mode (I2C and SPI active): bits 10 or 11
328 #[default]
329 PowerDown = 3,
330}
331
332impl TryFrom<u8> for Md {
333 type Error = ();
334
335 fn try_from(value: u8) -> Result<Self, Self::Error> {
336 let md = match value {
337 0 => Md::ContinuousMode,
338 1 => Md::SingleTrigger,
339 _ => Md::PowerDown,
340 };
341
342 Ok(md)
343 }
344}
345
346/// Output data rate configuration for the sensor.
347///
348/// Determines the frequency at which data is updated and made available.
349#[repr(u8)]
350#[derive(Clone, Copy, PartialEq, Default, Debug, TryFrom)]
351#[try_from(repr)]
352pub enum Odr {
353 /// Output data rate at 10 Hz (default)
354 #[default]
355 _10hz = 0,
356 /// Output data rate at 20 Hz
357 _20hz = 1,
358 /// Output data rate at 50 Hz
359 _50hz = 2,
360 /// Output data rate at 100 Hz
361 _100hz = 3,
362}
363
364/// Power mode
365#[repr(u8)]
366#[derive(Clone, Copy, PartialEq, Default, Debug, TryFrom)]
367#[try_from(repr)]
368pub enum PowerMode {
369 /// High-resolution mode
370 #[default]
371 HighResolution = 0,
372 /// Low-power mode enabled
373 LowPower = 1,
374}
375
376/// Digital low pass filter
377#[repr(u8)]
378#[derive(Clone, Copy, PartialEq, Default, Debug, TryFrom)]
379#[try_from(repr)]
380pub enum LowPassFilter {
381 /// Filter disabled (bandwidth = ODR/2)
382 #[default]
383 OdrDiv2 = 0,
384 /// Filter enabled (bandwidth = ODR/4)
385 OdrDiv4 = 1,
386}
387
388#[repr(u8)]
389#[derive(Clone, Copy, PartialEq, Default, Debug, TryFrom)]
390#[try_from(repr)]
391pub enum SetRst {
392 /// Set pulse released every 64 ODR cycles (default)
393 #[default]
394 SetSensOdrDiv63 = 0,
395 /// Enables offset cancellation
396 SensOffCancEveryOdr = 1,
397 /// Set pulse released only at power-on after power-down condition
398 SetSensOnlyAtPowerOn = 2,
399}
400
401#[repr(u8)]
402#[derive(Clone, Copy, PartialEq, Default, Debug, TryFrom)]
403#[try_from(repr)]
404pub enum Ble {
405 /// LSB at low address (default byte order)
406 #[default]
407 LsbAtLowAdd = 0,
408 /// MSB at low address (byte order inverted)
409 MsbAtLowAdd = 1,
410}
411
412#[repr(u8)]
413#[derive(Clone, Copy, PartialEq, Default, TryFrom)]
414#[try_from(repr)]
415pub enum IntOnDataoff {
416 /// Interrupt recognition checks data before hard-iron correction
417 #[default]
418 CheckBefore = 0,
419 /// Interrupt recognition checks data after hard-iron correction
420 CheckAfter = 1,
421}
422
423#[repr(u8)]
424#[derive(Clone, Copy, PartialEq, Default, TryFrom)]
425#[try_from(repr)]
426pub enum Sim {
427 /// SPI 4-wire interface enabled (disables interrupt and data-ready signaling)
428 Spi4Wire = 1,
429 /// SPI 3-wire interface enabled
430 #[default]
431 Spi3Wire = 0,
432}
433
434#[repr(u8)]
435#[derive(Clone, Copy, PartialEq, Default, TryFrom)]
436#[try_from(repr)]
437pub enum I2cSwitch {
438 /// I2C interface enabled (default)
439 #[default]
440 I2cEnable = 0,
441 /// I2C interface disabled; only SPI interface can be used
442 I2cDisable = 1,
443}