1#![no_std]
3use bitfield::bitfield;
4use embedded_hal::i2c::{ErrorType, I2c};
5
6pub mod address {
7 pub const PRIMARY: u8 = 0x1D;
8 pub const SECONDARY: u8 = 0x53;
9}
10
11const ID_VAL: u8 = 0b11100101;
12const EARTH_GRAVITY: f32 = 9.80665;
13const LSB_SCALE_FACTOR_FULL_RES: f32 = 0.0039;
14
15#[derive(Debug)]
16pub enum Error<E> {
17 IdMismatch,
18 BusError(E),
19}
20
21impl<E> From<E> for Error<E> {
22 fn from(error: E) -> Self {
23 Error::BusError(error)
24 }
25}
26
27pub struct Driver<Bus> {
28 bus: Bus,
29 addr: u8,
30}
31
32impl<Bus> Driver<Bus>
33where
34 Bus: I2c + ErrorType,
35{
36 pub fn new(bus: Bus, addr: Option<u8>) -> Result<Driver<Bus>, Error<Bus::Error>> {
40 let addr = addr.unwrap_or(address::PRIMARY);
41 let mut driver = Driver { bus, addr };
42 driver.get_id()?;
43 driver.power_on()?;
44
45 Ok(driver)
46 }
47
48 fn get_id(&mut self) -> Result<u8, Error<Bus::Error>> {
49 let tx_buf = [registers::DEVID; 1];
50 let mut rx_buf = [0u8; 1];
51 self.bus.write_read(self.addr, &tx_buf, &mut rx_buf)?;
52 if rx_buf[0] != ID_VAL {
53 return Err(Error::IdMismatch);
54 }
55
56 Ok(rx_buf[0])
57 }
58
59 fn power_on(&mut self) -> Result<(), Error<Bus::Error>> {
60 let tx_buf = [registers::POWER_CTL, 0x08];
61 self.bus.write(self.addr, &tx_buf)?;
62
63 Ok(())
64 }
65
66 pub fn set_tap_detection_ints(
67 &mut self,
68 single_tap: Option<InterruptMapPin>,
69 double_tap: Option<InterruptMapPin>,
70 axes: u8,
71 duration: u8,
72 latent: u8,
73 window: u8,
74 threshold: u8,
75 ) -> Result<(), Error<Bus::Error>> {
76 let tx_buf = [registers::INT_ENABLE, 0u8];
78 self.bus.write(self.addr, &tx_buf)?;
79
80 let tx_buf = [registers::TAP_AXES, axes];
82 self.bus.write(self.addr, &tx_buf)?;
83
84 let tx_buf = [registers::DUR, duration];
85 self.bus.write(self.addr, &tx_buf)?;
86
87 let tx_buf = [registers::LATENT, latent];
88 self.bus.write(self.addr, &tx_buf)?;
89
90 let tx_buf = [registers::WINDOW, window];
91 self.bus.write(self.addr, &tx_buf)?;
92
93 let tx_buf = [registers::THRESH_TAP, threshold];
94 self.bus.write(self.addr, &tx_buf)?;
95
96 let mut int_map = InterruptsFlags(0);
98 int_map.set_single_tap(single_tap.unwrap_or(InterruptMapPin::INT1).as_bool());
99 int_map.set_double_tap(double_tap.unwrap_or(InterruptMapPin::INT1).as_bool());
100 let tx_buf = [registers::INT_MAP, int_map.0];
101 self.bus.write(self.addr, &tx_buf)?;
102
103 let mut int_config = InterruptsFlags(0);
105 int_config.set_single_tap(single_tap.is_some());
106 int_config.set_double_tap(double_tap.is_some());
107 let tx_buf = [registers::INT_ENABLE, int_config.0];
108 self.bus.write(self.addr, &tx_buf)?;
109
110 Ok(())
111 }
112
113 pub fn set_tap_detection_ints_defaults(
115 &mut self,
116 single_tap: Option<InterruptMapPin>,
117 double_tap: Option<InterruptMapPin>,
118 ) -> Result<(), Error<Bus::Error>> {
119 let axes = 0x03; let duration = 0x10; let latent = 0x50; let window = 0xFF; let threshold = 0x20; self.set_tap_detection_ints(
125 single_tap, double_tap, axes, duration, latent, window, threshold,
126 )
127 }
128
129 pub fn clear_ints(&mut self) -> Result<InterruptsFlags, Error<Bus::Error>> {
130 let tx_buf = [registers::INT_SOURCE; 1];
131 let mut rx_buf = [0u8; 1];
132 self.bus.write_read(self.addr, &tx_buf, &mut rx_buf)?;
133
134 Ok(InterruptsFlags(rx_buf[0]))
135 }
136
137 pub fn get_accel_raw(&mut self) -> Result<(i16, i16, i16), Error<Bus::Error>> {
138 let tx_buf = [registers::DATAX0; 1];
139 let mut rx_buf = [0u8; 6]; self.bus.write_read(self.addr, &tx_buf, &mut rx_buf)?;
141 let datax: i16 = ((rx_buf[1] as i16) << 8) | rx_buf[0] as i16;
142 let datay: i16 = ((rx_buf[3] as i16) << 8) | rx_buf[2] as i16;
143 let dataz: i16 = ((rx_buf[5] as i16) << 8) | rx_buf[4] as i16;
144
145 Ok((datax, datay, dataz))
146 }
147
148 pub fn set_range(&mut self, range: GRange) -> Result<(), Error<Bus::Error>> {
149 let mut rx_buf = [0u8; 1];
150 self.bus.read(self.addr, &mut rx_buf)?;
151
152 let mut format = rx_buf[0] & 0xF0;
154 format |= range as u8;
155
156 format |= 0x08;
158
159 self.bus
160 .write(self.addr, &[registers::DATA_FORMAT, format])?;
161
162 Ok(())
163 }
164
165 pub fn set_datarate(&mut self, rate: OutputDataRate) -> Result<(), Error<Bus::Error>> {
166 let tx_buf = [registers::BW_RATE, rate as u8];
167 self.bus.write(self.addr, &tx_buf)?;
168
169 Ok(())
170 }
171
172 pub fn get_accel(&mut self) -> Result<(f32, f32, f32), Error<Bus::Error>> {
173 let accel = self.get_accel_raw()?;
174 let accel_g: (f32, f32, f32) = (
175 (accel.0 as f32) * EARTH_GRAVITY * LSB_SCALE_FACTOR_FULL_RES,
176 (accel.1 as f32) * EARTH_GRAVITY * LSB_SCALE_FACTOR_FULL_RES,
177 (accel.2 as f32) * EARTH_GRAVITY * LSB_SCALE_FACTOR_FULL_RES,
178 );
179
180 Ok(accel_g)
181 }
182}
183
184#[allow(dead_code)]
185mod registers {
186 pub const DEVID: u8 = 0x00; pub const THRESH_TAP: u8 = 0x1D; pub const OFSX: u8 = 0x1E; pub const OFSY: u8 = 0x1F; pub const OFSZ: u8 = 0x20; pub const DUR: u8 = 0x21; pub const LATENT: u8 = 0x22; pub const WINDOW: u8 = 0x23; pub const THRESH_ACT: u8 = 0x24; pub const THRESH_INACT: u8 = 0x25; pub const TIME_INACT: u8 = 0x26; pub const ACT_INACT_CTL: u8 = 0x27; pub const THRESH_FF: u8 = 0x28; pub const TIME_FF: u8 = 0x29; pub const TAP_AXES: u8 = 0x2A; pub const ACT_TAP_STATUS: u8 = 0x2B; pub const BW_RATE: u8 = 0x2C; pub const POWER_CTL: u8 = 0x2D; pub const INT_ENABLE: u8 = 0x2E; pub const INT_MAP: u8 = 0x2F; pub const INT_SOURCE: u8 = 0x30; pub const DATA_FORMAT: u8 = 0x31; pub const DATAX0: u8 = 0x32; pub const DATAX1: u8 = 0x33; pub const DATAY0: u8 = 0x34; pub const DATAY1: u8 = 0x35; pub const DATAZ0: u8 = 0x36; pub const DATAZ1: u8 = 0x37; pub const FIFO_CTL: u8 = 0x38; pub const FIFO_STATUS: u8 = 0x39; }
217
218#[repr(u8)]
219#[derive(Clone, Copy)]
220pub enum GRange {
221 Two = 0, Four = 1, Eight = 2, Sixteen = 3, }
226
227#[repr(u8)]
228#[derive(Clone, Copy)]
229pub enum OutputDataRate {
230 Hz0_10 = 0,
231 Hz0_20 = 1,
232 Hz0_39 = 2,
233 Hz0_78 = 3,
234 Hz1_56 = 4,
235 Hz3_13 = 5,
236 Hz6_25 = 6,
237 Hz12_5 = 7,
238 Hz25 = 8,
239 Hz50 = 9,
240 Hz100 = 10,
241 Hz200 = 11,
242 Hz400 = 12,
243 Hz800 = 13,
244 Hz1600 = 14,
245 Hz3200 = 15,
246}
247
248bitfield! {
249 pub struct InterruptsFlags(u8);
250 impl Debug;
251 pub data_ready, set_data_ready: 7;
252 pub single_tap, set_single_tap: 6;
253 pub double_tap, set_double_tap: 5;
254 pub activity, set_activity: 4;
255 pub inactivity, set_inactivity: 3;
256 pub free_fall, set_free_fall: 2;
257 pub watermark, set_watermark: 1;
258 pub overrun, set_overrun: 0;
259}
260
261#[repr(u8)]
262#[derive(Clone, Copy)]
263pub enum InterruptMapPin {
264 INT1 = 0,
265 INT2 = 1,
266}
267
268impl InterruptMapPin {
269 pub fn as_bool(self) -> bool {
270 match self {
271 InterruptMapPin::INT1 => false,
272 InterruptMapPin::INT2 => true,
273 }
274 }
275}