1#![no_std]
9
10use core::mem;
11use embedded_hal as hal;
12use crate::hal::blocking::i2c::{Write, WriteRead};
13
14use bitflags::bitflags;
15
16#[derive(Debug)]
18pub enum FullScale {
19 Fs4g,
20 Fs8g,
21 Fs12g,
22 Fs16g
23}
24
25#[derive(Debug)]
27pub enum OperatingMode {
28 LowPower,
29 MediumPerformance,
30 HighPerformance,
31 UltraHighPerformance
32}
33
34#[derive(Debug)]
36pub enum MeasurementMode {
37 Idle,
38 SingleMeasurement,
39 Continuous
40}
41
42#[allow(non_camel_case_types)]
44#[derive(Debug)]
45pub enum DataRate {
46 ODR_0_625Hz,
47 ODR_1_25Hz,
48 ODR_2_5Hz,
49 ODR_5Hz,
50 ODR_10Hz,
51 ODR_20Hz,
52 ODR_40Hz,
53 ODR_80Hz,
54 ODR_Fast
56}
57
58#[derive(Debug)]
60pub enum Error {
61 CommunicationError,
63 InvalidValue,
65 IncorrectDeviceIdFound,
67}
68
69fn i2c_error<E>(_: E) -> Error {
70 Error::CommunicationError
71}
72
73#[derive(Debug)]
75pub struct I16xyz {
76 pub x: i16,
78 pub y: i16,
80 pub z: i16,
82}
83
84#[derive(Debug)]
86pub struct I32xyz {
87 pub x: i32,
88 pub y: i32,
89 pub z: i32,
90}
91
92pub enum Address {
93 Addr1E = 0x1E,
94 Addr1C = 0x1C,
95}
96
97const LIS3MDL_DEVICE_ID: u8 = 0x3D;
98
99pub struct Lis3mdl<I2C> {
101 i2c: I2C,
102 address: u8,
103}
104
105impl<I2C, E> Lis3mdl<I2C> where I2C: WriteRead<Error=E> + Write<Error=E>,
106{
107 pub fn new (i2c: I2C, addr: Address) -> Result<Self,Error> {
120 let mut lis3mdl = Lis3mdl {
121 i2c,
122 address: addr as u8,
123 };
124
125 if lis3mdl.who_am_i()? != LIS3MDL_DEVICE_ID {
126 return Err(Error::IncorrectDeviceIdFound)
127 }
128
129 lis3mdl.set_full_scale(FullScale::Fs12g)?;
130 lis3mdl.set_operating_mode(OperatingMode::UltraHighPerformance)?;
131 lis3mdl.set_measurement_mode(MeasurementMode::Continuous)?;
132 lis3mdl.set_temperature_sensor_enable(true)?;
133 lis3mdl.set_data_rate(DataRate::ODR_Fast)?;
134 lis3mdl.set_block_data_update(true)?;
135
136 Ok(lis3mdl)
137 }
138
139 pub fn who_am_i(&mut self) -> Result<u8, Error> {
141 self.read_register(Register::WHO_AM_I).map_err(i2c_error)
142 }
143
144 pub fn get_raw_mag_axes(&mut self) -> Result<I16xyz, Error> {
160
161 let x = self.read_x_raw()?;
162 let y = self.read_y_raw()?;
163 let z = self.read_z_raw()?;
164
165 Ok(I16xyz {
166 x,
167 y,
168 z
169 })
170 }
171
172 pub fn xyz_data_available(&mut self) -> Result<bool, Error> {
174 Ok(self.read_device_status()?.contains(StatusRegisterBits::ZYXDA))
175 }
176
177 pub fn get_mag_axes_mgauss(&mut self) -> Result<I32xyz, Error> {
180 let mag_data = self.get_raw_mag_axes()?;
181
182 let fullscale = FullScaleBits::from_bits(self.read_register(Register::CTRL_REG2)?).unwrap();
183
184 let sensitivity: f64 = match fullscale {
186 FullScaleBits::FS4G => Ok(1000_f64/6842_f64),
187 FullScaleBits::FS8G => Ok(1000_f64/3421_f64),
188 FullScaleBits::FS12G => Ok(1000_f64/2281_f64),
189 FullScaleBits::FS16G => Ok(1000_f64/1711_f64),
190 _ => Err(Error::InvalidValue)
191 }?;
192
193 Ok(I32xyz {
194 x: (mag_data.x as f64 * sensitivity) as i32,
195 y: (mag_data.y as f64 * sensitivity) as i32,
196 z: (mag_data.z as f64 * sensitivity) as i32
197 })
198 }
199
200 pub fn set_full_scale(&mut self, scale: FullScale) -> Result<(),Error> {
205 let fs_mask = !(ControlRegister2Bits::FS1 | ControlRegister2Bits::FS0);
207
208 let fs = match scale {
209 FullScale::Fs4g => FullScaleBits::FS4G,
210 FullScale::Fs8g => FullScaleBits::FS8G,
211 FullScale::Fs12g => FullScaleBits::FS12G,
212 FullScale::Fs16g => FullScaleBits::FS16G,
213 };
214
215 let existing_settings = self.read_control_register_2()? & fs_mask;
217
218 let reg2bits = ControlRegister2Bits::from_bits_truncate(fs.bits());
219
220 self.set_control_register_2(reg2bits | existing_settings)
222 }
223
224 pub fn set_operating_mode(&mut self, mode: OperatingMode) -> Result<(), Error> {
230 let reg1_mask = !(ControlRegister1Bits::OM1 | ControlRegister1Bits::OM0);
232 let reg4_mask = !(ControlRegister4Bits::OMZ1 | ControlRegister4Bits::OMZ0);
233
234 let om = match mode {
235 OperatingMode::LowPower => (ControlRegister1Bits::empty(), ControlRegister4Bits::empty()),
236 OperatingMode::MediumPerformance => (ControlRegister1Bits::OM0, ControlRegister4Bits::OMZ0),
237 OperatingMode::HighPerformance => (ControlRegister1Bits::OM1, ControlRegister4Bits::OMZ1),
238 OperatingMode::UltraHighPerformance => (ControlRegister1Bits::OM1
239 | ControlRegister1Bits::OM0,
240 ControlRegister4Bits::OMZ1
241 | ControlRegister4Bits::OMZ0),
242 };
243
244 let existing_reg_1_settings = self.read_control_register_1()? & reg1_mask;
246 let existing_reg_4_settings = self.read_control_register_4()? & reg4_mask;
247
248 self.set_control_register_1(existing_reg_1_settings | om.0)?;
250 self.set_control_register_4(existing_reg_4_settings | om.1)?;
251 Ok(())
252 }
253
254 pub fn set_measurement_mode(&mut self, mode: MeasurementMode) -> Result<(), Error> {
258 let mm_mask = !(ControlRegister3Bits::MD1 | ControlRegister3Bits::MD0);
260
261 let mm = match mode {
262 MeasurementMode::Idle => ControlRegister3Bits::MD1,
263 MeasurementMode::SingleMeasurement => ControlRegister3Bits::MD0,
264 MeasurementMode::Continuous => ControlRegister3Bits::empty(),
265 };
266
267 let existing_reg_3_settings = self.read_control_register_3()? & mm_mask;
269
270 self.set_control_register_3(existing_reg_3_settings | mm)
272 }
273
274 pub fn set_data_rate(&mut self, rate: DataRate) -> Result<(), Error> {
279 let odr_mask = !(ControlRegister1Bits::DO2 | ControlRegister1Bits::DO1
281 | ControlRegister1Bits::DO0 | ControlRegister1Bits::FAST_ODR);
282
283 let odr = match rate {
284 DataRate::ODR_0_625Hz => ControlRegister1Bits::empty(),
285 DataRate::ODR_1_25Hz => ControlRegister1Bits::DO0,
286 DataRate::ODR_2_5Hz => ControlRegister1Bits::DO1,
287 DataRate::ODR_5Hz => ControlRegister1Bits::DO1 | ControlRegister1Bits::DO0,
288 DataRate::ODR_10Hz => ControlRegister1Bits::DO2,
289 DataRate::ODR_20Hz => ControlRegister1Bits::DO2 | ControlRegister1Bits::DO0,
290 DataRate::ODR_40Hz => ControlRegister1Bits::DO2 | ControlRegister1Bits::DO1,
291 DataRate::ODR_80Hz => ControlRegister1Bits::DO2 | ControlRegister1Bits::DO1
292 | ControlRegister1Bits::DO0,
293 DataRate::ODR_Fast => ControlRegister1Bits::FAST_ODR,
294 };
295
296 let existing_reg_1_settings = self.read_control_register_1()? & odr_mask;
298
299 self.set_control_register_1(existing_reg_1_settings | odr)
301 }
302
303 pub fn set_block_data_update(&mut self, block: bool) -> Result<(), Error> {
308 let bdu_mask = !ControlRegister5Bits::BDU;
309
310 let existing_reg_5_settings = self.read_control_register_5()? & bdu_mask;
311
312 if block {
313 self.set_control_register_5(existing_reg_5_settings | ControlRegister5Bits::BDU)
314 }
315 else {
316 self.set_control_register_5(existing_reg_5_settings)
317 }
318 }
319
320 pub fn set_temperature_sensor_enable(&mut self, enabled: bool) -> Result<(), Error> {
322 let temp_mask = !ControlRegister1Bits::TEMP_EN;
323
324 let existing_reg_1_settings = self.read_control_register_1()? & temp_mask;
325
326 if enabled {
327 self.set_control_register_1(existing_reg_1_settings | ControlRegister1Bits::TEMP_EN)
328 }
329 else {
330 self.set_control_register_1(existing_reg_1_settings)
331 }
332 }
333
334 fn read_x_raw(&mut self) -> Result<i16,Error> {
335 self.read_register_i16(Register::OUT_X_H,Register::OUT_X_L)
336 }
337
338 fn read_y_raw(&mut self) -> Result<i16,Error> {
339 self.read_register_i16(Register::OUT_Y_H,Register::OUT_Y_L)
340 }
341
342 fn read_z_raw(&mut self) -> Result<i16,Error> {
343 self.read_register_i16(Register::OUT_Z_H,Register::OUT_Z_L)
344 }
345
346 fn read_device_status(&mut self) -> Result<StatusRegisterBits, Error> {
347 Ok(StatusRegisterBits::from_bits_truncate(self.read_register(Register::STATUS_REG)?))
348 }
349
350 fn set_control_register_1(&mut self, bits: ControlRegister1Bits) -> Result<(),Error> {
351 Ok(self.write_register(Register::CTRL_REG1, bits.bits())?)
352 }
353
354 fn set_control_register_2(&mut self, bits: ControlRegister2Bits) -> Result<(),Error> {
355 Ok(self.write_register(Register::CTRL_REG2, bits.bits())?)
356 }
357
358 fn set_control_register_3(&mut self, bits: ControlRegister3Bits) -> Result<(),Error> {
359 Ok(self.write_register(Register::CTRL_REG3, bits.bits())?)
360 }
361
362 fn set_control_register_4(&mut self, bits: ControlRegister4Bits) -> Result<(),Error> {
363 Ok(self.write_register(Register::CTRL_REG4, bits.bits())?)
364 }
365
366 fn set_control_register_5(&mut self, bits: ControlRegister5Bits) -> Result<(),Error> {
367 Ok(self.write_register(Register::CTRL_REG5, bits.bits())?)
368 }
369
370 fn read_control_register_1(&mut self) -> Result<ControlRegister1Bits, Error> {
371 Ok(ControlRegister1Bits::from_bits_truncate(self.read_register(Register::CTRL_REG1)?))
372 }
373
374 fn read_control_register_2(&mut self) -> Result<ControlRegister2Bits, Error> {
375 Ok(ControlRegister2Bits::from_bits_truncate(self.read_register(Register::CTRL_REG2)?))
376 }
377
378 fn read_control_register_3(&mut self) -> Result<ControlRegister3Bits, Error> {
379 Ok(ControlRegister3Bits::from_bits_truncate(self.read_register(Register::CTRL_REG3)?))
380 }
381
382 fn read_control_register_4(&mut self) -> Result<ControlRegister4Bits, Error> {
383 Ok(ControlRegister4Bits::from_bits_truncate(self.read_register(Register::CTRL_REG4)?))
384 }
385
386 fn read_control_register_5(&mut self) -> Result<ControlRegister5Bits, Error> {
387 Ok(ControlRegister5Bits::from_bits_truncate(self.read_register(Register::CTRL_REG5)?))
388 }
389
390 fn read_register_i16(&mut self, reg_low: Register, reg_high: Register) -> Result<i16, Error> {
391 let low = self.read_register(reg_low)?;
392 let high = self.read_register(reg_high)?;
393
394 let signed = i16::from_le_bytes([high, low]);
396 Ok(signed)
397 }
398
399 fn read_register(&mut self, reg: Register) -> Result<u8, Error> {
400 let mut buffer: [u8; 1] = unsafe { mem::uninitialized() };
401 self.i2c.write_read(self.address, &[reg.addr()], &mut buffer).map_err(i2c_error)?;
402 Ok(buffer[0])
403 }
404
405 fn write_register(&mut self, reg: Register, byte: u8) -> Result<(), Error> {
406 self.i2c.write(self.address, &[reg.addr(), byte]).map_err(i2c_error)
407 }
408}
409
410#[allow(non_camel_case_types, dead_code)]
411#[derive(Debug, Copy, Clone)]
412enum Register {
413 OFFSET_X_REG_L_M = 0x05,
414 OFFSET_X_REG_H_M = 0x06,
415 OFFSET_Y_REG_L_M = 0x07,
416 OFFSET_Y_REG_H_M = 0x08,
417 OFFSET_Z_REG_L_M = 0x09,
418 OFFSET_Z_REG_H_M = 0x0A,
419
420 WHO_AM_I = 0x0F,
421
422 CTRL_REG1 = 0x20,
423 CTRL_REG2 = 0x21,
424 CTRL_REG3 = 0x22,
425 CTRL_REG4 = 0x23,
426 CTRL_REG5 = 0x24,
427
428 STATUS_REG = 0x27,
429 OUT_X_L = 0x28,
430 OUT_X_H = 0x29,
431 OUT_Y_L = 0x2A,
432 OUT_Y_H = 0x2B,
433 OUT_Z_L = 0x2C,
434 OUT_Z_H = 0x2D,
435 TEMP_OUT_L = 0x2E,
436 TEMP_OUT_H = 0x2F,
437 INT_CFG = 0x30,
438 INT_SRC = 0x31,
439 INT_THS_L = 0x32,
440 INT_THS_H = 0x33
441}
442
443impl Register {
444 fn addr(self) -> u8 {
445 self as u8
446 }
447}
448
449bitflags! {
450#[allow(non_camel_case_types, dead_code)]
451struct ControlRegister1Bits: u8 {
452 const TEMP_EN = 0b1000_0000;
453 const OM1 = 0b0100_0000;
454 const OM0 = 0b0010_0000;
455 const DO2 = 0b0001_0000;
456 const DO1 = 0b0000_1000;
457 const DO0 = 0b0000_0100;
458 const FAST_ODR = 0b0000_0010;
459 const ST = 0b0000_0001;
460}
461}
462
463bitflags! {
464#[allow(non_camel_case_types, dead_code)]
465struct ControlRegister2Bits: u8 {
466 const FS1 = 0b0100_0000;
467 const FS0 = 0b0010_0000;
468 const REBOOT = 0b0000_1000;
469 const SOFT_RST = 0b0000_0100;
470}
471}
472
473bitflags! {
474#[allow(non_camel_case_types, dead_code)]
475struct ControlRegister3Bits: u8 {
476 const LP = 0b0010_0000;
477 const SIM = 0b0000_0100;
478 const MD1 = 0b0000_0010;
479 const MD0 = 0b0000_0001;
480}
481}
482
483bitflags! {
484struct ControlRegister4Bits: u8 {
485 const OMZ1 = 0b0000_1000;
486 const OMZ0 = 0b0000_0100;
487 const BLE = 0b0000_0010;
488 const UHP = 0b0000_1100;
489}
490}
491
492bitflags! {
493struct ControlRegister5Bits: u8 {
494 const FAST_READ = 0b1000_0000;
495 const BDU = 0b0100_0000;
496}
497}
498
499bitflags! {
500struct StatusRegisterBits: u8 {
501 const ZYXOR = 0b1000_0000;
502 const ZOR = 0b0100_0000;
503 const YOR = 0b0010_0000;
504 const XOR = 0b0001_0000;
505 const ZYXDA = 0b0000_1000;
506 const ZDA = 0b0000_0100;
507 const YDA = 0b0000_0010;
508 const XDA = 0b0000_0001;
509}
510}
511
512bitflags! {
513#[allow(non_camel_case_types, dead_code)]
514struct FullScaleBits: u8 {
515 const FS4G = 0b0000_0000;
516 const FS8G = 0b0010_0000;
517 const FS12G = 0b0100_0000;
518 const FS16G = 0b0110_0000;
519}
520}