1use crate::hw::{spi::CsControl, SpiBus};
12use core::f32::consts::PI;
13use stm32f7xx_hal::spi;
14
15const WHO_AM_I_VALUE: u8 = 0x70;
17
18const G: f32 = 9.80665;
20
21mod reg {
22 pub const WHO_AM_I: u8 = 0x0F;
23 pub const CTRL1: u8 = 0x10;
24 pub const CTRL2: u8 = 0x11;
25 pub const CTRL3: u8 = 0x12;
26 pub const CTRL6: u8 = 0x15;
27 pub const CTRL8: u8 = 0x17;
28 pub const OUTX_L_G: u8 = 0x22;
29}
30
31const SPI_READ: u8 = 0x80;
33
34#[derive(Debug)]
35pub enum Error {
36 Spi(spi::Error),
37 InvalidDevice,
38}
39
40impl From<spi::Error> for Error {
41 fn from(e: spi::Error) -> Self {
42 Error::Spi(e)
43 }
44}
45
46#[derive(Debug, Clone, Copy, Default)]
48pub struct ImuSample {
49 pub ax: f32,
51 pub ay: f32,
52 pub az: f32,
53 pub gx: f32,
55 pub gy: f32,
56 pub gz: f32,
57}
58
59pub struct Lsm6dsv16x {
62 accel_scale: f32,
63 gyro_scale: f32,
64}
65
66impl Lsm6dsv16x {
67 pub fn new<I, PINS, CS>(spi: &mut SpiBus<I, PINS>, cs: &mut CS) -> Result<Self, Error>
70 where
71 I: spi::Instance,
72 PINS: spi::Pins<I>,
73 CS: CsControl,
74 {
75 let mut dev = Self {
76 accel_scale: (2.0 * G) / 32768.0, gyro_scale: (2000.0 * PI / 180.0) / 32768.0, };
79
80 if dev.read_reg(spi, cs, reg::WHO_AM_I)? != WHO_AM_I_VALUE {
81 return Err(Error::InvalidDevice);
82 }
83
84 dev.write_reg(spi, cs, reg::CTRL3, 0x45)?;
86 for _ in 0..1000 {
88 let v = dev.read_reg(spi, cs, reg::CTRL3)?;
89 if (v & 0x01) == 0 {
90 break;
91 }
92 }
93 dev.write_reg(spi, cs, reg::CTRL3, 0x44)?;
95
96 dev.write_reg(spi, cs, reg::CTRL8, 0x00)?;
98 dev.write_reg(spi, cs, reg::CTRL6, 0x04)?;
100
101 dev.write_reg(spi, cs, reg::CTRL1, 0x06)?;
103 dev.write_reg(spi, cs, reg::CTRL2, 0x06)?;
105
106 Ok(dev)
107 }
108
109 pub fn read_sample<I, PINS, CS>(
112 &mut self,
113 spi: &mut SpiBus<I, PINS>,
114 cs: &mut CS,
115 ) -> Result<ImuSample, Error>
116 where
117 I: spi::Instance,
118 PINS: spi::Pins<I>,
119 CS: CsControl,
120 {
121 let mut buf = [0u8; 13];
122 buf[0] = reg::OUTX_L_G | SPI_READ;
123
124 cs.select();
125 let res = spi.transfer_in_place(&mut buf);
126 cs.deselect();
127 res?;
128
129 let gx_raw = i16::from_le_bytes([buf[1], buf[2]]);
130 let gy_raw = i16::from_le_bytes([buf[3], buf[4]]);
131 let gz_raw = i16::from_le_bytes([buf[5], buf[6]]);
132 let ax_raw = i16::from_le_bytes([buf[7], buf[8]]);
133 let ay_raw = i16::from_le_bytes([buf[9], buf[10]]);
134 let az_raw = i16::from_le_bytes([buf[11], buf[12]]);
135
136 Ok(ImuSample {
137 ax: ax_raw as f32 * self.accel_scale,
138 ay: ay_raw as f32 * self.accel_scale,
139 az: az_raw as f32 * self.accel_scale,
140 gx: gx_raw as f32 * self.gyro_scale,
141 gy: gy_raw as f32 * self.gyro_scale,
142 gz: gz_raw as f32 * self.gyro_scale,
143 })
144 }
145
146 fn read_reg<I, PINS, CS>(
147 &mut self,
148 spi: &mut SpiBus<I, PINS>,
149 cs: &mut CS,
150 addr: u8,
151 ) -> Result<u8, Error>
152 where
153 I: spi::Instance,
154 PINS: spi::Pins<I>,
155 CS: CsControl,
156 {
157 let mut buf = [addr | SPI_READ, 0];
158 cs.select();
159 let res = spi.transfer_in_place(&mut buf);
160 cs.deselect();
161 res?;
162 Ok(buf[1])
163 }
164
165 fn write_reg<I, PINS, CS>(
166 &mut self,
167 spi: &mut SpiBus<I, PINS>,
168 cs: &mut CS,
169 addr: u8,
170 value: u8,
171 ) -> Result<(), Error>
172 where
173 I: spi::Instance,
174 PINS: spi::Pins<I>,
175 CS: CsControl,
176 {
177 let mut buf = [addr & 0x7F, value];
178 cs.select();
179 let res = spi.transfer_in_place(&mut buf);
180 cs.deselect();
181 res?;
182 Ok(())
183 }
184}