1#![no_std]
2
3#![deny(
8 missing_docs,
9 missing_debug_implementations,
10 missing_copy_implementations,
11 trivial_casts,
12 unstable_features,
13 unused_import_braces,
14 unused_qualifications,
15 )]
17#![allow(
18 dead_code,
19 clippy::uninit_assumed_init,
20 clippy::too_many_arguments,
21 clippy::upper_case_acronyms
22)]
23
24extern crate cast;
25extern crate embedded_hal as ehal;
26extern crate generic_array;
27extern crate nb;
28extern crate safe_transmute;
29
30use core::mem::MaybeUninit;
31
32use ehal::blocking::i2c::WriteRead;
33use generic_array::typenum::consts::*;
34use generic_array::{ArrayLength, GenericArray};
35
36const EM7180_ADDRESS: u8 = 0x28;
38
39#[derive(Debug, Copy, Clone)]
41pub struct USFS<I2C> {
42 com: I2C,
43 address: u8,
44 int_pin: u8,
45 pass_thru: bool,
46}
47
48#[derive(Debug, Copy, Clone)]
50pub enum Error<E> {
51 InvalidDevice(u8),
53 BusError(E),
55 Timeout,
57}
58
59impl<E> From<E> for Error<E> {
60 fn from(error: E) -> Self {
61 Error::BusError(error)
62 }
63}
64
65impl<I2C, E> USFS<I2C>
66where
67 I2C: WriteRead<Error = E>,
68{
69 pub fn default(i2c: I2C) -> Result<USFS<I2C>, Error<E>>
71 where
72 I2C: WriteRead<Error = E>,
73 {
74 USFS::new(i2c, EM7180_ADDRESS, 8, false)
75 }
76
77 pub fn new(i2c: I2C, address: u8, int_pin: u8, pass_thru: bool) -> Result<USFS<I2C>, Error<E>>
79 where
80 I2C: WriteRead<Error = E>,
81 {
82 let mut chip = USFS {
83 com: i2c,
84 address,
85 int_pin,
86 pass_thru,
87 };
88
89 let wai = chip.get_product_id()?;
90
91 if wai == 0x80 {
92 let acc_bw: u8 = 0x03;
111 let gyro_bw: u8 = 0x03;
112 let qrt_div: u8 = 0x01;
113 let mag_rt: u8 = 0x64;
114 let acc_rt: u8 = 0x14;
115 let gyro_rt: u8 = 0x14;
116 let baro_rt: u8 = 0x32;
117 let acc_fs: u16 = 0x08;
118 let gyro_fs: u16 = 0x7D0;
119 let mag_fs: u16 = 0x3E8;
120
121 chip.load_fw_from_eeprom()?;
122 chip.init_hardware(
123 acc_bw, gyro_bw, acc_fs, gyro_fs, mag_fs, qrt_div, mag_rt, acc_rt, gyro_rt, baro_rt,
124 )?;
125 Ok(chip)
126 } else {
127 Err(Error::InvalidDevice(wai))
128 }
129 }
130
131 fn read_byte(&mut self, reg: u8) -> Result<u8, E> {
132 let mut data: [u8; 1] = [0];
133 self.com.write_read(self.address, &[reg], &mut data)?;
134 Ok(data[0])
135 }
136
137 fn read_registers<N>(&mut self, reg: Register) -> Result<GenericArray<u8, N>, E>
138 where
139 N: ArrayLength<u8>,
140 {
141 let mut buffer: GenericArray<u8, N> =
142 unsafe { MaybeUninit::<GenericArray<u8, N>>::uninit().assume_init() };
143
144 {
145 let buffer: &mut [u8] = &mut buffer;
146 const I2C_AUTO_INCREMENT: u8 = 0;
147 self.com
148 .write_read(self.address, &[(reg as u8) | I2C_AUTO_INCREMENT], buffer)?;
149 }
150
151 Ok(buffer)
152 }
153
154 fn read_4bytes(&mut self, reg: Register) -> Result<[u8; 4], E> {
155 let buffer: GenericArray<u8, U4> = self.read_registers(reg)?;
156 let mut ret: [u8; 4] = Default::default();
157 ret.copy_from_slice(buffer.as_slice());
158
159 Ok(ret)
160 }
161
162 fn read_6bytes(&mut self, reg: Register) -> Result<[u8; 6], E> {
163 let buffer: GenericArray<u8, U6> = self.read_registers(reg)?;
164 let mut ret: [u8; 6] = Default::default();
165 ret.copy_from_slice(buffer.as_slice());
166
167 Ok(ret)
168 }
169
170 fn read_16bytes(&mut self, reg: Register) -> Result<[u8; 16], E> {
171 let buffer: GenericArray<u8, U16> = self.read_registers(reg)?;
172 let mut ret: [u8; 16] = Default::default();
173 ret.copy_from_slice(buffer.as_slice());
174
175 Ok(ret)
176 }
177
178 fn read_register(&mut self, reg: Register) -> Result<u8, E> {
179 let mut data: [u8; 1] = [0];
180 self.com.write_read(self.address, &[reg as u8], &mut data)?;
181 Ok(data[0])
182 }
183
184 fn write_register(&mut self, reg: Register, byte: u8) -> Result<(), E> {
185 let mut buffer = [0];
186 self.com
187 .write_read(self.address, &[reg as u8, byte], &mut buffer)
188 }
189
190 fn em7180_set_integer_param(&mut self, param: u8, param_val: u32) -> Result<(), E> {
191 let bytes_0 = (param_val & (0xFF)) as u8;
192 let bytes_1 = ((param_val >> 8) & (0xFF)) as u8;
193 let bytes_2 = ((param_val >> 16) & (0xFF)) as u8;
194 let bytes_3 = ((param_val >> 24) & (0xFF)) as u8;
195 let param = param | 0x80; self.write_register(Register::EM7180_LoadParamByte0, bytes_0)?; self.write_register(Register::EM7180_LoadParamByte1, bytes_1)?;
199 self.write_register(Register::EM7180_LoadParamByte2, bytes_2)?;
200 self.write_register(Register::EM7180_LoadParamByte3, bytes_3)?; self.write_register(Register::EM7180_ParamRequest, param)?;
202 self.write_register(Register::EM7180_AlgorithmControl, 0x80)?; let mut stat = self.read_register(Register::EM7180_ParamAcknowledge)?; while stat != param {
206 stat = self.read_register(Register::EM7180_ParamAcknowledge)?;
207 }
208
209 self.write_register(Register::EM7180_ParamRequest, 0x00)?; self.write_register(Register::EM7180_AlgorithmControl, 0x00)?; Ok(())
213 }
214
215 fn em7180_set_mag_acc_fs(&mut self, mag_fs: u16, acc_fs: u16) -> Result<(), E> {
216 let bytes_0 = (mag_fs & (0xFF)) as u8;
217 let bytes_1 = ((mag_fs >> 8) & (0xFF)) as u8;
218 let bytes_2 = (acc_fs & (0xFF)) as u8;
219 let bytes_3 = ((acc_fs >> 8) & (0xFF)) as u8;
220
221 self.write_register(Register::EM7180_LoadParamByte0, bytes_0)?; self.write_register(Register::EM7180_LoadParamByte1, bytes_1)?; self.write_register(Register::EM7180_LoadParamByte2, bytes_2)?; self.write_register(Register::EM7180_LoadParamByte3, bytes_3)?; self.write_register(Register::EM7180_ParamRequest, 0xCA)?; self.write_register(Register::EM7180_AlgorithmControl, 0x80)?; let mut stat = self.read_register(Register::EM7180_ParamAcknowledge)?; while stat != 0xCA {
230 stat = self.read_register(Register::EM7180_ParamAcknowledge)?;
231 }
232
233 self.write_register(Register::EM7180_ParamRequest, 0x00)?; self.write_register(Register::EM7180_AlgorithmControl, 0x00)?; Ok(())
237 }
238
239 fn em7180_set_gyro_fs(&mut self, gyro_fs: u16) -> Result<(), E> {
240 let bytes_0 = (gyro_fs & (0xFF)) as u8;
241 let bytes_1 = ((gyro_fs >> 8) & (0xFF)) as u8;
242 let bytes_2 = 0x00;
243 let bytes_3 = 0x00;
244
245 self.write_register(Register::EM7180_LoadParamByte0, bytes_0)?; self.write_register(Register::EM7180_LoadParamByte1, bytes_1)?; self.write_register(Register::EM7180_LoadParamByte2, bytes_2)?; self.write_register(Register::EM7180_LoadParamByte3, bytes_3)?; self.write_register(Register::EM7180_ParamRequest, 0xCB)?; self.write_register(Register::EM7180_AlgorithmControl, 0x80)?; let mut stat = self.read_register(Register::EM7180_ParamAcknowledge)?; while stat != 0xCB {
254 stat = self.read_register(Register::EM7180_ParamAcknowledge)?;
255 }
256
257 self.write_register(Register::EM7180_ParamRequest, 0x00)?; self.write_register(Register::EM7180_AlgorithmControl, 0x00)?; Ok(())
261 }
262
263 fn load_fw_from_eeprom(&mut self) -> Result<(), E> {
264 let mut stat = self.read_register(Register::EM7180_SentralStatus)? & 0x01;
265
266 let mut count = 0;
267 while stat != 0 {
268 self.write_register(Register::EM7180_ResetRequest, 0x01)?;
269 count += 1;
270 stat = self.read_register(Register::EM7180_SentralStatus)? & 0x01;
271 if count > 10 {
272 break;
273 };
274 }
275
276 Ok(())
277 }
278
279 fn init_hardware(
280 &mut self,
281 acc_bw: u8,
282 gyro_bw: u8,
283 acc_fs: u16,
284 gyro_fs: u16,
285 mag_fs: u16,
286 qrt_div: u8,
287 mag_rt: u8,
288 acc_rt: u8,
289 gyro_rt: u8,
290 baro_rt: u8,
291 ) -> Result<(), Error<E>> {
292 self.write_register(Register::EM7180_HostControl, 0x00)?; self.write_register(Register::EM7180_PassThruControl, 0x00)?; self.write_register(Register::EM7180_HostControl, 0x01)?; self.write_register(Register::EM7180_HostControl, 0x00)?; self.write_register(Register::EM7180_ACC_LPF_BW, acc_bw)?; self.write_register(Register::EM7180_GYRO_LPF_BW, gyro_bw)?; self.write_register(Register::EM7180_QRateDivisor, qrt_div)?; self.write_register(Register::EM7180_MagRate, mag_rt)?; self.write_register(Register::EM7180_AccelRate, acc_rt)?; self.write_register(Register::EM7180_GyroRate, gyro_rt)?; self.write_register(Register::EM7180_BaroRate, 0x80 | baro_rt)?; self.write_register(Register::EM7180_AlgorithmControl, 0x00)?; self.write_register(Register::EM7180_EnableEvents, 0x07)?;
313 self.write_register(Register::EM7180_HostControl, 0x01)?; self.write_register(Register::EM7180_ParamRequest, 0x4A)?; self.write_register(Register::EM7180_AlgorithmControl, 0x80)?; let mut param_xfer = self.read_register(Register::EM7180_ParamAcknowledge)?;
323 while param_xfer != 0x4A {
324 param_xfer = self.read_register(Register::EM7180_ParamAcknowledge)?;
325 }
326
327 self.write_register(Register::EM7180_ParamRequest, 0x4B)?; let mut param_xfer = self.read_register(Register::EM7180_ParamAcknowledge)?;
329 while param_xfer != 0x4B {
330 param_xfer = self.read_register(Register::EM7180_ParamAcknowledge)?;
331 }
332
333 self.write_register(Register::EM7180_ParamRequest, 0x00)?; self.write_register(Register::EM7180_AlgorithmControl, 0x00)?; self.em7180_set_integer_param(0x49, 0x00)?;
338
339 self.em7180_set_mag_acc_fs(mag_fs, acc_fs)?; self.em7180_set_gyro_fs(gyro_fs)?; self.write_register(Register::EM7180_ParamRequest, 0x4A)?; self.write_register(Register::EM7180_AlgorithmControl, 0x80)?; let mut param_xfer = self.read_register(Register::EM7180_ParamAcknowledge)?;
347 while param_xfer != 0x4A {
348 param_xfer = self.read_register(Register::EM7180_ParamAcknowledge)?;
349 }
350
351 self.write_register(Register::EM7180_ParamRequest, 0x4B)?; let mut param_xfer = self.read_register(Register::EM7180_ParamAcknowledge)?;
353 while param_xfer != 0x4B {
354 param_xfer = self.read_register(Register::EM7180_ParamAcknowledge)?;
355 }
356
357 self.write_register(Register::EM7180_ParamRequest, 0x00)?; self.write_register(Register::EM7180_AlgorithmControl, 0x00)?; Ok(())
361 }
362
363 pub fn get_product_id(&mut self) -> Result<u8, E> {
365 self.read_register(Register::EM7180_ProductID)
366 }
367
368 pub fn get_rom_version(&mut self) -> Result<[u8; 2], E> {
370 let rom_version1 = self.read_register(Register::EM7180_ROMVersion1)?;
371 let rom_version2 = self.read_register(Register::EM7180_ROMVersion2)?;
372 Ok([rom_version1, rom_version2])
373 }
374
375 pub fn get_sentral_status(&mut self) -> Result<u8, E> {
377 self.read_register(Register::EM7180_SentralStatus)
378 }
379
380 pub fn check_run_status(&mut self) -> Result<u8, E> {
382 self.read_register(Register::EM7180_RunStatus)
383 }
384
385 pub fn check_status(&mut self) -> Result<u8, E> {
395 self.read_register(Register::EM7180_EventStatus)
396 }
397
398 pub fn check_errors(&mut self) -> Result<u8, E> {
411 self.read_register(Register::EM7180_Error)
412 }
413
414 pub fn check_sensor_status(&mut self) -> Result<u8, E> {
424 self.read_register(Register::EM7180_SensorStatus)
425 }
426
427 pub fn check_feature_flags(&mut self) -> Result<u8, E> {
436 self.read_register(Register::EM7180_FeatureFlags)
437 }
438
439 pub fn get_actual_magnetometer_rate(&mut self) -> Result<u8, E> {
441 self.read_register(Register::EM7180_ActualMagRate)
442 }
443
444 pub fn get_actual_accel_rate(&mut self) -> Result<u8, E> {
446 Ok(self.read_register(Register::EM7180_ActualAccelRate)? * 10)
447 }
448
449 pub fn get_actual_gyroscope_rate(&mut self) -> Result<u8, E> {
451 Ok(self.read_register(Register::EM7180_ActualGyroRate)? * 10)
452 }
453
454 pub fn read_sentral_accel_data(&mut self) -> Result<[i16; 3], E> {
459 let raw_data = self.read_6bytes(Register::EM7180_AX)?;
460
461 let ax = (raw_data[1] as i16) << 8 | raw_data[0] as i16;
462 let ay = (raw_data[3] as i16) << 8 | raw_data[2] as i16;
463 let az = (raw_data[5] as i16) << 8 | raw_data[4] as i16;
464
465 Ok([ax, ay, az])
466 }
467
468 pub fn read_sentral_gyro_data(&mut self) -> Result<[i16; 3], E> {
473 let raw_data = self.read_6bytes(Register::EM7180_GX)?;
474
475 let ax = (raw_data[1] as i16) << 8 | raw_data[0] as i16;
476 let ay = (raw_data[3] as i16) << 8 | raw_data[2] as i16;
477 let az = (raw_data[5] as i16) << 8 | raw_data[4] as i16;
478
479 Ok([ax, ay, az])
480 }
481
482 pub fn read_sentral_mag_data(&mut self) -> Result<[i16; 3], E> {
487 let raw_data = self.read_6bytes(Register::EM7180_MX)?;
488
489 let ax = (raw_data[1] as i16) << 8 | raw_data[0] as i16;
490 let ay = (raw_data[3] as i16) << 8 | raw_data[2] as i16;
491 let az = (raw_data[5] as i16) << 8 | raw_data[4] as i16;
492
493 Ok([ax, ay, az])
494 }
495
496 pub fn read_sentral_quat_qata(&mut self) -> Result<[f32; 4], E> {
502 let raw_data_qx = self.read_4bytes(Register::EM7180_QX)?;
503 let qx = reg_to_float(&raw_data_qx);
504
505 let raw_data_qy = self.read_4bytes(Register::EM7180_QY)?;
506 let qy = reg_to_float(&raw_data_qy);
507
508 let raw_data_qz = self.read_4bytes(Register::EM7180_QZ)?;
509 let qz = reg_to_float(&raw_data_qz);
510
511 let raw_data_qw = self.read_4bytes(Register::EM7180_QW)?;
512 let qw = reg_to_float(&raw_data_qw);
513
514 Ok([qx, qy, qz, qw])
515 }
516
517 pub fn read_sentral_baro_data(&mut self) -> Result<i16, E> {
519 let raw_data = self.read_6bytes(Register::EM7180_Baro)?; Ok((raw_data[1] as i16) << 8 | raw_data[0] as i16) }
522
523 pub fn read_sentral_temp_data(&mut self) -> Result<i16, E> {
525 let raw_data = self.read_6bytes(Register::EM7180_Temp)?; Ok((raw_data[1] as i16) << 8 | raw_data[0] as i16) }
528}
529
530#[derive(Debug, Copy, Clone)]
531#[allow(non_camel_case_types)]
532enum Register {
533 EM7180_EventStatus = 0x35,
534 EM7180_Error = 0x50,
535 EM7180_ProductID = 0x90,
536 EM7180_HostControl = 0x34,
537 EM7180_PassThruControl = 0xA0,
538 EM7180_ACC_LPF_BW = 0x5B,
539 EM7180_GYRO_LPF_BW = 0x5C,
540 EM7180_QRateDivisor = 0x32,
541 EM7180_MagRate = 0x55,
542 EM7180_AccelRate = 0x56,
543 EM7180_GyroRate = 0x57,
544 EM7180_BaroRate = 0x58,
545 EM7180_AlgorithmControl = 0x54,
546 EM7180_EnableEvents = 0x33,
547 EM7180_SensorStatus = 0x36,
548 EM7180_ActualMagRate = 0x45,
549 EM7180_ActualAccelRate = 0x46,
550 EM7180_ActualGyroRate = 0x47,
551 EM7180_ParamRequest = 0x64,
552 EM7180_ParamAcknowledge = 0x3A,
553 EM7180_ROMVersion1 = 0x70,
554 EM7180_ROMVersion2 = 0x71,
555 EM7180_LoadParamByte0 = 0x60,
556 EM7180_LoadParamByte1 = 0x61,
557 EM7180_LoadParamByte2 = 0x62,
558 EM7180_LoadParamByte3 = 0x63,
559 EM7180_SavedParamByte0 = 0x3B,
560 EM7180_SavedParamByte1 = 0x3C,
561 EM7180_SavedParamByte2 = 0x3D,
562 EM7180_SavedParamByte3 = 0x3E,
563 EM7180_FeatureFlags = 0x39,
564 EM7180_SentralStatus = 0x37,
565 EM7180_ResetRequest = 0x9B,
566 EM7180_RunStatus = 0x92,
567 EM7180_QX = 0x00, EM7180_QY = 0x04, EM7180_QZ = 0x08, EM7180_QW = 0x0C, EM7180_AX = 0x1A, EM7180_GX = 0x22, EM7180_MX = 0x12, EM7180_Baro = 0x2A, EM7180_Temp = 0x2E, }
577
578fn reg_to_float(buf: &[u8]) -> f32 {
580 unsafe { safe_transmute::guarded_transmute::<f32>(buf).unwrap() }
581}
582
583pub fn raw_temperature_to_celsius(raw_temperature: i16) -> f64 {
585 raw_temperature as f64 * 0.01f64
586}
587
588pub fn raw_temperature_to_fahrenheit(raw_temperature: i16) -> f64 {
590 9.0f64 * raw_temperature_to_celsius(raw_temperature) / 5.0f64 + 32.0f64
591}
592
593pub fn raw_pressure_to_mbar(raw_pressure: i16) -> f64 {
595 raw_pressure as f64 * 0.01f64 + 1013.25f64
596}
597
598pub fn raw_pressure_to_feet(_raw_pressure: i16) -> f64 {
600 0.0
604}