1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
use crate::{
interface::{I2cInterface, ReadData, SpiInterface, WriteData},
BitFlags as BF, Config, Error, Lsm303agr, Register, Status, UnscaledMeasurement,
};
impl<I2C> Lsm303agr<I2cInterface<I2C>> {
pub fn new_with_i2c(i2c: I2C) -> Self {
Lsm303agr {
iface: I2cInterface { i2c },
ctrl_reg1_a: Config { bits: 0x7 },
ctrl_reg4_a: Config { bits: 0 },
accel_odr: None,
}
}
pub fn destroy(self) -> I2C {
self.iface.i2c
}
}
impl<SPI, CSXL, CSMAG> Lsm303agr<SpiInterface<SPI, CSXL, CSMAG>> {
pub fn new_with_spi(spi: SPI, chip_select_accel: CSXL, chip_select_mag: CSMAG) -> Self {
Lsm303agr {
iface: SpiInterface {
spi,
cs_xl: chip_select_accel,
cs_mag: chip_select_mag,
},
ctrl_reg1_a: Config { bits: 0x7 },
ctrl_reg4_a: Config { bits: 0 },
accel_odr: None,
}
}
pub fn destroy(self) -> (SPI, CSXL, CSMAG) {
(self.iface.spi, self.iface.cs_xl, self.iface.cs_mag)
}
}
impl<DI, CommE, PinE> Lsm303agr<DI>
where
DI: ReadData<Error = Error<CommE, PinE>> + WriteData<Error = Error<CommE, PinE>>,
{
pub fn init(&mut self) -> Result<(), Error<CommE, PinE>> {
let reg4 = self.ctrl_reg4_a.with_high(BF::BDU);
self.iface
.write_accel_register(Register::CTRL_REG4_A, reg4.bits)?;
self.ctrl_reg4_a = reg4;
Ok(())
}
pub fn accel_status(&mut self) -> Result<Status, Error<CommE, PinE>> {
self.iface
.read_accel_register(Register::STATUS_REG_A)
.map(convert_status)
}
pub fn accel_data(&mut self) -> Result<UnscaledMeasurement, Error<CommE, PinE>> {
let data = self
.iface
.read_accel_3_double_registers(Register::OUT_X_L_A)?;
let lp_enabled = self.ctrl_reg1_a.is_high(BF::LP_EN);
let hr_enabled = self.ctrl_reg4_a.is_high(BF::HR);
let resolution_factor = if hr_enabled {
1 << 4
} else if lp_enabled {
1 << 8
} else {
1 << 6
};
let x = (data.0 as i16) / resolution_factor;
let y = (data.1 as i16) / resolution_factor;
let z = (data.2 as i16) / resolution_factor;
Ok(UnscaledMeasurement { x, y, z })
}
pub fn mag_status(&mut self) -> Result<Status, Error<CommE, PinE>> {
self.iface
.read_mag_register(Register::STATUS_REG_M)
.map(convert_status)
}
pub fn accelerometer_id(&mut self) -> Result<u8, Error<CommE, PinE>> {
self.iface.read_accel_register(Register::WHO_AM_I_A)
}
pub fn magnetometer_id(&mut self) -> Result<u8, Error<CommE, PinE>> {
self.iface.read_mag_register(Register::WHO_AM_I_M)
}
}
fn convert_status(st: u8) -> Status {
Status {
xyz_overrun: (st & BF::XYZOR) != 0,
z_overrun: (st & BF::ZOR) != 0,
y_overrun: (st & BF::YOR) != 0,
x_overrun: (st & BF::XOR) != 0,
xyz_new_data: (st & BF::XYZDR) != 0,
z_new_data: (st & BF::ZDR) != 0,
y_new_data: (st & BF::YDR) != 0,
x_new_data: (st & BF::XDR) != 0,
}
}