Skip to main content

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}