1#![deny(missing_docs)]
14#![deny(warnings)]
15#![no_std]
16
17
18
19use embedded_hal::blocking::spi::{Transfer, Write};
20use embedded_hal::digital::v2::OutputPin;
21use embedded_hal::spi::{Mode};
22
23pub const MODE: Mode = embedded_hal::spi::MODE_3;
25
26
27pub struct I3G4250D<SPI, CS> {
29 spi: SPI,
30 cs: CS,
31}
32
33impl<SPI, CS, E> I3G4250D<SPI, CS>
34where
35 SPI: Transfer<u8, Error = E> + Write<u8, Error = E>,
36 CS: OutputPin,
37{
38 pub fn new(spi: SPI, cs: CS) -> Result<Self, E> {
40 let mut i3g4259d = I3G4250D { spi, cs };
41
42 i3g4259d.write_register(Register::CTRL_REG1, 0b00_00_1_111)?;
44
45 Ok(i3g4259d)
46 }
47
48 pub fn all(&mut self) -> Result<Measurements, E> {
50 let mut bytes = [0u8; 9];
51 self.read_many(Register::OUT_TEMP, &mut bytes)?;
52
53 Ok(Measurements {
54 gyro: I16x3 {
55 x: (bytes[3] as u16 + ((bytes[4] as u16) << 8)) as i16,
56 y: (bytes[5] as u16 + ((bytes[6] as u16) << 8)) as i16,
57 z: (bytes[7] as u16 + ((bytes[8] as u16) << 8)) as i16,
58 },
59 temp: bytes[1] as i8,
60 })
61 }
62
63 pub fn gyro(&mut self) -> Result<I16x3, E> {
65 let mut bytes = [0u8; 7];
66 self.read_many(Register::OUT_X_L, &mut bytes)?;
67
68 Ok(I16x3 {
69 x: (bytes[1] as u16 + ((bytes[2] as u16) << 8)) as i16,
70 y: (bytes[3] as u16 + ((bytes[4] as u16) << 8)) as i16,
71 z: (bytes[5] as u16 + ((bytes[6] as u16) << 8)) as i16,
72 })
73 }
74
75 pub fn temp(&mut self) -> Result<i8, E> {
77 Ok(self.read_register(Register::OUT_TEMP)? as i8)
78 }
79
80 pub fn who_am_i(&mut self) -> Result<u8, E> {
82 self.read_register(Register::WHO_AM_I)
83 }
84
85 pub fn status(&mut self) -> Result<Status, E> {
87 let sts = self.read_register(Register::STATUS_REG)?;
88 Ok(Status::from_u8(sts))
89 }
90
91 pub fn odr(&mut self) -> Result<Odr, E> {
93 let reg1 = self.read_register(Register::CTRL_REG1)?;
95 Ok(Odr::from_u8(reg1))
96 }
97
98 pub fn set_odr(&mut self, odr: Odr) -> Result<&mut Self, E> {
100 self.change_config(Register::CTRL_REG1, odr)
101 }
102
103 pub fn bandwidth(&mut self) -> Result<Bandwidth, E> {
105 let reg1 = self.read_register(Register::CTRL_REG1)?;
106 Ok(Bandwidth::from_u8(reg1))
107 }
108
109 pub fn set_bandwidth(&mut self, bw: Bandwidth) -> Result<&mut Self, E> {
113 self.change_config(Register::CTRL_REG1, bw)
114 }
115
116 pub fn scale(&mut self) -> Result<Scale, E> {
120 let scl = self.read_register(Register::CTRL_REG4)?;
121 Ok(Scale::from_u8(scl))
122 }
123
124 pub fn set_scale(&mut self, scale: Scale) -> Result<&mut Self, E> {
129 self.change_config(Register::CTRL_REG4, scale)
130 }
131
132 fn read_register(&mut self, reg: Register) -> Result<u8, E> {
133 let _ = self.cs.set_low();
134
135 let mut buffer = [reg.addr() | SINGLE | READ, 0];
136 self.spi.transfer(&mut buffer)?;
137
138 let _ = self.cs.set_high();
139
140 Ok(buffer[1])
141 }
142
143 fn read_many(&mut self,
146 start_reg: Register,
147 buffer: &mut [u8])
148 -> Result<(), E> {
149 let _ = self.cs.set_low();
150 buffer[0] = start_reg.addr() | MULTI | READ ;
151 self.spi.transfer(buffer)?;
152 let _ = self.cs.set_high();
153
154 Ok(())
155 }
156
157
158 fn write_register(&mut self, reg: Register, byte: u8) -> Result<(), E> {
159 let _ = self.cs.set_low();
160
161 let buffer = [reg.addr() | SINGLE | WRITE, byte];
162 self.spi.write(&buffer)?;
163
164 let _ = self.cs.set_high();
165
166 Ok(())
167 }
168
169 fn change_config<B: BitValue>(&mut self, reg: Register, bits: B) -> Result<&mut Self, E> {
176 let mask = B::mask() << B::shift();
178 let bits = (bits.value() << B::shift()) & mask;
180 let current = self.read_register(reg)?;
182 let masked = current & !mask;
184 let new_reg = masked | bits;
186 self.write_register(reg, new_reg)?;
187 Ok(self)
188 }
189}
190
191trait BitValue {
193 fn width() -> u8;
195 fn mask() -> u8 {
197 (1 << Self::width()) - 1
198 }
199 fn shift() -> u8;
201 fn value(&self) -> u8;
206}
207
208#[allow(dead_code)]
209#[allow(non_camel_case_types)]
210#[derive(Clone, Copy)]
211enum Register {
212 WHO_AM_I = 0x0F,
213 CTRL_REG1 = 0x20,
214 CTRL_REG2 = 0x21,
215 CTRL_REG3 = 0x22,
216 CTRL_REG4 = 0x23,
217 CTRL_REG5 = 0x24,
218 REFERENCE = 0x25,
219 OUT_TEMP = 0x26,
220 STATUS_REG = 0x27,
221 OUT_X_L = 0x28,
222 OUT_X_H = 0x29,
223 OUT_Y_L = 0x2A,
224 OUT_Y_H = 0x2B,
225 OUT_Z_L = 0x2C,
226 OUT_Z_H = 0x2D,
227 FIFO_CTRL_REG = 0x2E,
228 FIFO_SRC_REG = 0x2F,
229 INT1_CFG = 0x30,
230 INT1_SRC = 0x31,
231 INT1_TSH_XH = 0x32,
232 INT1_TSH_XL = 0x33,
233 INT1_TSH_YH = 0x34,
234 INT1_TSH_YL = 0x35,
235 INT1_TSH_ZH = 0x36,
236 INT1_TSH_ZL = 0x37,
237 INT1_DURATION = 0x38,
238}
239
240
241
242#[derive(Debug, Clone, Copy)]
244pub enum Odr {
245 Hz100 = 0x00,
247 Hz200 = 0x01,
249 Hz400 = 0x02,
251 Hz800 = 0x03,
253}
254
255impl BitValue for Odr {
256 fn width() -> u8 {
257 2
258 }
259 fn shift() -> u8 {
260 6
261 }
262 fn value(&self) -> u8 {
263 *self as u8
264 }
265}
266
267impl Odr {
268 fn from_u8(from: u8) -> Self {
269 match (from >> Odr::shift()) & Odr::mask() {
271 x if x == Odr::Hz100 as u8 => Odr::Hz100,
272 x if x == Odr::Hz200 as u8 => Odr::Hz200,
273 x if x == Odr::Hz400 as u8 => Odr::Hz400,
274 x if x == Odr::Hz800 as u8 => Odr::Hz800,
275 _ => unreachable!(),
276 }
277 }
278}
279
280#[derive(Debug, Clone, Copy)]
282pub enum Scale {
283 Dps245 = 0x00,
285 Dps500 = 0x01,
287 Dps2000 = 0x03,
289}
290
291impl BitValue for Scale {
292 fn width() -> u8 {
293 2
294 }
295 fn shift() -> u8 {
296 4
297 }
298 fn value(&self) -> u8 {
299 *self as u8
300 }
301}
302
303impl Scale {
304 fn from_u8(from: u8) -> Self {
305 match (from >> Scale::shift()) & Scale::mask() {
308 x if x == Scale::Dps245 as u8 => Scale::Dps245,
309 x if x == Scale::Dps500 as u8 => Scale::Dps500,
310 x if x == Scale::Dps2000 as u8 => Scale::Dps2000,
311 0x02 => Scale::Dps2000,
313 _ => unreachable!(),
314 }
315 }
316}
317
318#[derive(Debug, Clone, Copy)]
324pub enum Bandwidth {
325 Low = 0x00,
327 Medium = 0x01,
329 High = 0x02,
331 Maximum = 0x03,
333}
334
335impl BitValue for Bandwidth {
336 fn width() -> u8 {
337 2
338 }
339 fn shift() -> u8 {
340 4
341 }
342 fn value(&self) -> u8 {
343 *self as u8
344 }
345}
346
347impl Bandwidth {
348 fn from_u8(from: u8) -> Self {
349 match (from >> Bandwidth::shift()) & Bandwidth::mask() {
351 x if x == Bandwidth::Low as u8 => Bandwidth::Low,
352 x if x == Bandwidth::Medium as u8 => Bandwidth::Medium,
353 x if x == Bandwidth::High as u8 => Bandwidth::High,
354 x if x == Bandwidth::Maximum as u8 => Bandwidth::Maximum,
355 _ => unreachable!(),
356 }
357 }
358}
359
360const READ: u8 = 1 << 7;
361const WRITE: u8 = 0 << 7;
362const MULTI: u8 = 1 << 6;
363const SINGLE: u8 = 0 << 6;
364
365impl Register {
366 fn addr(self) -> u8 {
367 self as u8
368 }
369}
370
371impl Scale {
372 pub fn degrees(&self, val: i16) -> f32 {
374 match *self {
375 Scale::Dps245 => val as f32 * 0.00875,
376 Scale::Dps500 => val as f32 * 0.0175,
377 Scale::Dps2000 => val as f32 * 0.07,
378 }
379 }
380
381 pub fn radians(&self, val: i16) -> f32 {
383 self.degrees(val) * (core::f32::consts::PI / 180.0)
386 }
387}
388
389#[derive(Debug)]
391pub struct I16x3 {
392 pub x: i16,
394 pub y: i16,
396 pub z: i16,
398}
399
400#[derive(Debug)]
402pub struct Measurements {
403 pub gyro: I16x3,
405 pub temp: i8,
407}
408
409#[derive(Debug, Clone, Copy)]
411pub struct Status {
412 pub overrun: bool,
415 pub z_overrun: bool,
417 pub y_overrun: bool,
419 pub x_overrun: bool,
421 pub new_data: bool,
423 pub z_new: bool,
425 pub y_new: bool,
427 pub x_new: bool,
429}
430
431impl Status {
432 fn from_u8(from: u8) -> Self {
433 Status {
434 overrun: (from & 1 << 7) != 0,
435 z_overrun: (from & 1 << 6) != 0,
436 y_overrun: (from & 1 << 5) != 0,
437 x_overrun: (from & 1 << 4) != 0,
438 new_data: (from & 1 << 3) != 0,
439 z_new: (from & 1 << 2) != 0,
440 y_new: (from & 1 << 1) != 0,
441 x_new: (from & 1 << 0) != 0,
442 }
443 }
444}