1use crate::{
55 constants::{
56 frs_status_to_str, q_to_f32, CHANNEL_COMMAND, CHANNEL_EXECUTABLE, CHANNEL_HUB_CONTROL,
57 CHANNEL_SENSOR_REPORTS, CMD_RESP_ADVERTISEMENT, CMD_RESP_ERROR_LIST,
58 EXECUTABLE_DEVICE_CMD_RESET, EXECUTABLE_DEVICE_RESP_RESET_COMPLETE, FRS_STATUS_NO_DATA,
59 FRS_STATUS_WRITE_COMPLETE, FRS_STATUS_WRITE_FAILED, FRS_STATUS_WRITE_READY, NUM_CHANNELS,
60 PACKET_RECV_BUF_LEN, PACKET_SEND_BUF_LEN, Q_POINTS, Q_POINTS2,
61 SENSOR_REPORTID_ACCELEROMETER, SENSOR_REPORTID_GRAVITY, SENSOR_REPORTID_GYROSCOPE,
62 SENSOR_REPORTID_GYROSCOPE_UNCALIB, SENSOR_REPORTID_LINEAR_ACCEL,
63 SENSOR_REPORTID_MAGNETIC_FIELD, SENSOR_REPORTID_ROTATION_VECTOR,
64 SENSOR_REPORTID_ROTATION_VECTOR_GAME, SENSOR_REPORTID_ROTATION_VECTOR_GEOMAGNETIC,
65 SH2_INIT_SYSTEM, SH2_STARTUP_INIT_UNSOLICITED, SHUB_COMMAND_RESP, SHUB_FRS_WRITE_RESP,
66 SHUB_GET_FEATURE_RESP, SHUB_PROD_ID_REQ, SHUB_PROD_ID_RESP, SHUB_REPORT_SET_FEATURE_CMD,
67 },
68 frs::{
69 build_frs_write_data, build_frs_write_request, quaternion_to_frs_words,
70 FRS_TYPE_SENSOR_ORIENTATION,
71 },
72 interface::{
73 delay::delay_ms,
74 gpio::{GpiodIn, GpiodOut},
75 spi::SpiControlLines,
76 spidev::SpiDevice,
77 SensorInterface, SpiInterface, PACKET_HEADER_LENGTH,
78 },
79};
80use log::{debug, trace, warn};
81
82use core::ops::Shr;
83use std::{
84 collections::HashMap,
85 fmt::Debug,
86 io::{self, Error, ErrorKind},
87 time::{Instant, SystemTime},
88};
89
90type ReportCallbackMap<'a, SI> = HashMap<String, Box<dyn Fn(&BNO08x<'a, SI>) + 'a>>;
92
93#[derive(Debug)]
98pub enum DriverError<E> {
99 CommError(E),
101 InvalidChipId(u8),
103 InvalidFWVersion(u8),
105 NoDataAvailable,
107}
108
109impl<E: std::fmt::Debug> From<DriverError<E>> for io::Error {
110 fn from(err: DriverError<E>) -> Self {
111 match err {
112 DriverError::CommError(e) => io::Error::other(format!("Communication error: {:?}", e)),
113 DriverError::InvalidChipId(id) => {
114 io::Error::new(ErrorKind::InvalidData, format!("Invalid chip ID: {}", id))
115 }
116 DriverError::InvalidFWVersion(ver) => io::Error::new(
117 ErrorKind::InvalidData,
118 format!("Invalid firmware version: {}", ver),
119 ),
120 DriverError::NoDataAvailable => {
121 io::Error::new(ErrorKind::TimedOut, "No sensor data available")
122 }
123 }
124 }
125}
126
127pub struct BNO08x<'a, SI> {
169 pub(crate) sensor_interface: SI,
170 sequence_numbers: [u8; NUM_CHANNELS],
172 packet_send_buf: [u8; PACKET_SEND_BUF_LEN],
174 packet_recv_buf: [u8; PACKET_RECV_BUF_LEN],
176
177 last_packet_len_received: usize,
178 device_reset: bool,
180 prod_id_verified: bool,
182
183 init_received: bool,
184
185 advert_received: bool,
187
188 frs_write_status: u8,
190
191 error_list_received: bool,
193 last_error_received: u8,
194
195 last_chan_received: u8,
196 last_exec_chan_rid: u8,
197 last_command_chan_rid: u8,
198
199 accelerometer: [f32; 3],
201
202 rotation_quaternion: [f32; 4],
204 rotation_acc: f32,
206
207 geomag_rotation_quaternion: [f32; 4],
209 geomag_rotation_acc: f32,
211
212 game_rotation_quaternion: [f32; 4],
214
215 linear_accel: [f32; 3],
217
218 gravity: [f32; 3],
220
221 gyro: [f32; 3],
223
224 uncalib_gyro: [f32; 3],
226
227 mag_field: [f32; 3],
229
230 report_enabled: [bool; 16],
232
233 report_update_time: [u128; 16],
235
236 report_update_callbacks: [ReportCallbackMap<'a, SI>; 16],
238}
239
240impl<SI> BNO08x<'_, SI> {
241 pub fn new_with_interface(sensor_interface: SI) -> Self {
243 Self {
244 sensor_interface,
245 sequence_numbers: [0; NUM_CHANNELS],
246 packet_send_buf: [0; PACKET_SEND_BUF_LEN],
247 packet_recv_buf: [0; PACKET_RECV_BUF_LEN],
248 last_packet_len_received: 0,
249 device_reset: false,
250 prod_id_verified: false,
251 frs_write_status: FRS_STATUS_NO_DATA,
252 init_received: false,
253 advert_received: false,
254 error_list_received: false,
255 last_error_received: 0,
256 last_chan_received: 0,
257 last_exec_chan_rid: 0,
258 last_command_chan_rid: 0,
259 accelerometer: [0.0; 3],
260 rotation_quaternion: [0.0; 4],
261 rotation_acc: 0.0,
262 game_rotation_quaternion: [0.0; 4],
263 geomag_rotation_quaternion: [0.0; 4],
264 geomag_rotation_acc: 0.0,
265 linear_accel: [0.0; 3],
266 gravity: [0.0; 3],
267 gyro: [0.0; 3],
268 uncalib_gyro: [0.0; 3],
269 mag_field: [0.0; 3],
270 report_enabled: [false; 16],
271 report_update_time: [0; 16],
272 report_update_callbacks: std::array::from_fn(|_| HashMap::new()),
273 }
274 }
275
276 pub fn free(self) -> SI {
278 self.sensor_interface
279 }
280}
281
282fn find_gpio_by_symbol(symbol: &str) -> io::Result<Option<(String, u32)>> {
296 let gpio_chips = gpiod::Chip::list_devices()?;
297
298 for entry in gpio_chips {
299 let chip = gpiod::Chip::new(&entry)?;
300 for i in 0..chip.num_lines() {
301 let line_info = chip.line_info(i)?;
302 trace!("--- {} ---", line_info.name);
303 if line_info.name == symbol {
304 return Ok(Some((entry.display().to_string(), i)));
305 }
306 }
307 }
308 Ok(None)
309}
310
311impl<'a> BNO08x<'a, SpiInterface<SpiDevice, GpiodIn, GpiodOut>> {
312 pub fn new_spi(
322 spidevice: &str,
323 hintn_gpiochip: &str,
324 hintn_pin: u32,
325 reset_gpiochip: &str,
326 reset_pin: u32,
327 ) -> io::Result<BNO08x<'a, SpiInterface<SpiDevice, GpiodIn, GpiodOut>>> {
328 let hintn: GpiodIn;
329 let reset: GpiodOut;
330 if hintn_gpiochip == reset_gpiochip {
331 let chip = gpiod::Chip::new(hintn_gpiochip)?;
332 hintn = GpiodIn::new(&chip, hintn_pin)?;
333 reset = GpiodOut::new(&chip, reset_pin)?;
334 } else {
335 let chip0 = gpiod::Chip::new(hintn_gpiochip)?;
336 hintn = GpiodIn::new(&chip0, hintn_pin)?;
337 let chip1 = gpiod::Chip::new(reset_gpiochip)?;
338 reset = GpiodOut::new(&chip1, reset_pin)?;
339 }
340
341 let spidev = SpiDevice::new(spidevice)?;
342 let ctrl_lines: SpiControlLines<SpiDevice, GpiodIn, GpiodOut> =
343 SpiControlLines::<SpiDevice, GpiodIn, GpiodOut> {
344 spi: spidev,
345 hintn,
346 reset,
347 };
348
349 let spi_int: SpiInterface<SpiDevice, GpiodIn, GpiodOut> = SpiInterface::new(ctrl_lines);
350 let imu_driver: BNO08x<SpiInterface<SpiDevice, GpiodIn, GpiodOut>> =
351 BNO08x::new_with_interface(spi_int);
352
353 Ok(imu_driver)
354 }
355
356 pub fn new_spi_from_symbol(
366 spidevice: &str,
367 hintn_pin: &str,
368 reset_pin: &str,
369 ) -> io::Result<BNO08x<'a, SpiInterface<SpiDevice, GpiodIn, GpiodOut>>> {
370 let (hintn_gpio_chip, hintn_num) = find_gpio_by_symbol(hintn_pin)?.ok_or_else(|| {
371 Error::new(
372 ErrorKind::AddrNotAvailable,
373 format!("Did not find hintn pin \"{}\"", hintn_pin),
374 )
375 })?;
376
377 let (reset_gpio_chip, reset_num) = find_gpio_by_symbol(reset_pin)?.ok_or_else(|| {
378 Error::new(
379 ErrorKind::AddrNotAvailable,
380 format!("Did not find reset pin \"{}\"", reset_pin),
381 )
382 })?;
383
384 Self::new_spi(
385 spidevice,
386 hintn_gpio_chip.as_str(),
387 hintn_num,
388 reset_gpio_chip.as_str(),
389 reset_num,
390 )
391 }
392}
393
394impl<'a, SI, SE> BNO08x<'a, SI>
395where
396 SI: SensorInterface<SensorError = SE>,
397 SE: core::fmt::Debug,
398{
399 pub fn eat_all_messages(&mut self) {
404 loop {
405 let msg_count = self.eat_one_message();
406 if msg_count == 0 {
407 break;
408 }
409 delay_ms(1);
410 }
411 }
412
413 pub fn handle_messages(&mut self, timeout_ms: usize, max_count: u32) -> u32 {
441 let mut total_handled: u32 = 0;
442 let mut i: u32 = 0;
443 while i < max_count {
444 let handled_count = self.handle_one_message(timeout_ms);
445 if handled_count == 0 || total_handled > max_count {
446 break;
447 } else {
448 total_handled += handled_count;
449 delay_ms(1);
450 }
451 i += 1
452 }
453 total_handled
454 }
455
456 pub fn handle_all_messages(&mut self, timeout_ms: usize) -> u32 {
488 let mut total_handled: u32 = 0;
489 loop {
490 let handled_count = self.handle_one_message(timeout_ms);
491 if handled_count == 0 {
492 break;
493 } else {
494 total_handled += handled_count;
495 delay_ms(1);
496 }
497 }
498 total_handled
499 }
500
501 pub fn handle_one_message(&mut self, max_ms: usize) -> u32 {
503 let mut msg_count = 0;
504
505 let res = self.receive_packet_with_timeout(max_ms);
506 if let Ok(received_len) = res {
507 if received_len > 0 {
508 msg_count += 1;
509 if let Err(e) = self.handle_received_packet(received_len) {
510 warn!("{:?}", e)
511 }
512 }
513 } else {
514 trace!("handle1 err {:?}", res);
515 }
516
517 msg_count
518 }
519
520 pub fn eat_one_message(&mut self) -> usize {
522 let res = self.receive_packet_with_timeout(150);
523 if let Ok(received_len) = res {
524 received_len
525 } else {
526 trace!("e1 err {:?}", res);
527 0
528 }
529 }
530
531 fn handle_advertise_response(&mut self, received_len: usize) {
532 let payload_len = received_len - PACKET_HEADER_LENGTH;
533 let payload = &self.packet_recv_buf[PACKET_HEADER_LENGTH..received_len];
534 let mut cursor: usize = 1; while cursor < payload_len {
537 let _tag: u8 = payload[cursor];
538 cursor += 1;
539 let len: u8 = payload[cursor];
540 cursor += 1;
541 cursor += len as usize;
542 }
543
544 self.advert_received = true;
545 }
546
547 fn read_u8_at_cursor(msg: &[u8], cursor: &mut usize) -> u8 {
548 let val = msg[*cursor];
549 *cursor += 1;
550 val
551 }
552
553 fn read_i16_at_cursor(msg: &[u8], cursor: &mut usize) -> i16 {
554 let val = (msg[*cursor] as i16) | ((msg[*cursor + 1] as i16) << 8);
555 *cursor += 2;
556 val
557 }
558
559 fn try_read_i16_at_cursor(msg: &[u8], cursor: &mut usize) -> Option<i16> {
560 let remaining = msg.len() - *cursor;
561 if remaining >= 2 {
562 let val = (msg[*cursor] as i16) | ((msg[*cursor + 1] as i16) << 8);
563 *cursor += 2;
564 Some(val)
565 } else {
566 None
567 }
568 }
569
570 fn handle_one_input_report(
572 outer_cursor: usize,
573 msg: &[u8],
574 ) -> (usize, u8, i16, i16, i16, i16, i16) {
575 let mut cursor = outer_cursor;
576
577 let feature_report_id = Self::read_u8_at_cursor(msg, &mut cursor);
578 let _rep_seq_num = Self::read_u8_at_cursor(msg, &mut cursor);
579 let _rep_status = Self::read_u8_at_cursor(msg, &mut cursor);
580 let _delay = Self::read_u8_at_cursor(msg, &mut cursor);
581
582 let data1: i16 = Self::read_i16_at_cursor(msg, &mut cursor);
583 let data2: i16 = Self::read_i16_at_cursor(msg, &mut cursor);
584 let data3: i16 = Self::read_i16_at_cursor(msg, &mut cursor);
585 let data4: i16 = Self::try_read_i16_at_cursor(msg, &mut cursor).unwrap_or(0);
586 let data5: i16 = Self::try_read_i16_at_cursor(msg, &mut cursor).unwrap_or(0);
587
588 (cursor, feature_report_id, data1, data2, data3, data4, data5)
589 }
590
591 fn handle_sensor_report_update(&mut self, report_id: u8, timestamp: u128) {
592 self.report_update_time[report_id as usize] = timestamp;
593 for (_, val) in self.report_update_callbacks[report_id as usize].iter() {
594 val(self);
595 }
596 }
597
598 fn handle_sensor_reports(&mut self, received_len: usize) {
600 let mut outer_cursor: usize = PACKET_HEADER_LENGTH + 5; if received_len < outer_cursor {
602 return;
603 }
604
605 let payload_len = received_len - outer_cursor;
606 if payload_len < 10 {
607 trace!(
608 "bad report: {:?}",
609 &self.packet_recv_buf[..PACKET_HEADER_LENGTH]
610 );
611 return;
612 }
613
614 while outer_cursor < payload_len {
615 let (inner_cursor, report_id, data1, data2, data3, data4, data5) =
616 Self::handle_one_input_report(outer_cursor, &self.packet_recv_buf[..received_len]);
617 outer_cursor = inner_cursor;
618
619 let timestamp = SystemTime::now()
620 .duration_since(SystemTime::UNIX_EPOCH)
621 .map(|d| d.as_nanos())
622 .unwrap_or(0);
623
624 match report_id {
625 SENSOR_REPORTID_ACCELEROMETER => {
626 self.update_accelerometer(data1, data2, data3);
627 self.handle_sensor_report_update(report_id, timestamp)
628 }
629 SENSOR_REPORTID_ROTATION_VECTOR => {
630 self.update_rotation_quaternion(data1, data2, data3, data4, data5);
631 self.handle_sensor_report_update(report_id, timestamp)
632 }
633 SENSOR_REPORTID_ROTATION_VECTOR_GAME => {
634 self.update_rotation_quaternion_game(data1, data2, data3, data4);
635 self.handle_sensor_report_update(report_id, timestamp)
636 }
637 SENSOR_REPORTID_ROTATION_VECTOR_GEOMAGNETIC => {
638 self.update_rotation_quaternion_geomag(data1, data2, data3, data4, data5);
639 self.handle_sensor_report_update(report_id, timestamp)
640 }
641 SENSOR_REPORTID_LINEAR_ACCEL => {
642 self.update_linear_accel(data1, data2, data3);
643 self.handle_sensor_report_update(report_id, timestamp)
644 }
645 SENSOR_REPORTID_GRAVITY => {
646 self.update_gravity(data1, data2, data3);
647 self.handle_sensor_report_update(report_id, timestamp)
648 }
649 SENSOR_REPORTID_GYROSCOPE => {
650 self.update_gyro_calib(data1, data2, data3);
651 self.handle_sensor_report_update(report_id, timestamp)
652 }
653 SENSOR_REPORTID_GYROSCOPE_UNCALIB => {
654 self.update_gyro_uncalib(data1, data2, data3);
655 self.handle_sensor_report_update(report_id, timestamp)
656 }
657 SENSOR_REPORTID_MAGNETIC_FIELD => {
658 self.update_magnetic_field_calib(data1, data2, data3);
659 self.handle_sensor_report_update(report_id, timestamp)
660 }
661 _ => {}
662 }
663 }
664 }
665
666 fn update_accelerometer(&mut self, x: i16, y: i16, z: i16) {
667 let q = Q_POINTS[SENSOR_REPORTID_ACCELEROMETER as usize];
668 self.accelerometer = [q_to_f32(x, q), q_to_f32(y, q), q_to_f32(z, q)];
669 }
670
671 fn update_rotation_quaternion(&mut self, q_i: i16, q_j: i16, q_k: i16, q_r: i16, q_a: i16) {
672 let q = Q_POINTS[SENSOR_REPORTID_ROTATION_VECTOR as usize];
673 let q2 = Q_POINTS2[SENSOR_REPORTID_ROTATION_VECTOR as usize];
674 self.rotation_quaternion = [
675 q_to_f32(q_i, q),
676 q_to_f32(q_j, q),
677 q_to_f32(q_k, q),
678 q_to_f32(q_r, q),
679 ];
680 self.rotation_acc = q_to_f32(q_a, q2);
681 }
682
683 fn update_rotation_quaternion_geomag(
684 &mut self,
685 q_i: i16,
686 q_j: i16,
687 q_k: i16,
688 q_r: i16,
689 q_a: i16,
690 ) {
691 let q = Q_POINTS[SENSOR_REPORTID_ROTATION_VECTOR_GEOMAGNETIC as usize];
692 let q2 = Q_POINTS2[SENSOR_REPORTID_ROTATION_VECTOR_GEOMAGNETIC as usize];
693 self.geomag_rotation_quaternion = [
694 q_to_f32(q_i, q),
695 q_to_f32(q_j, q),
696 q_to_f32(q_k, q),
697 q_to_f32(q_r, q),
698 ];
699 self.geomag_rotation_acc = q_to_f32(q_a, q2);
700 }
701
702 fn update_rotation_quaternion_game(&mut self, q_i: i16, q_j: i16, q_k: i16, q_r: i16) {
703 let q = Q_POINTS[SENSOR_REPORTID_ROTATION_VECTOR_GAME as usize];
704 self.game_rotation_quaternion = [
705 q_to_f32(q_i, q),
706 q_to_f32(q_j, q),
707 q_to_f32(q_k, q),
708 q_to_f32(q_r, q),
709 ];
710 }
711
712 fn update_linear_accel(&mut self, x: i16, y: i16, z: i16) {
713 let q = Q_POINTS[SENSOR_REPORTID_LINEAR_ACCEL as usize];
714 self.linear_accel = [q_to_f32(x, q), q_to_f32(y, q), q_to_f32(z, q)];
715 }
716
717 fn update_gravity(&mut self, x: i16, y: i16, z: i16) {
718 let q = Q_POINTS[SENSOR_REPORTID_GRAVITY as usize];
719 self.gravity = [q_to_f32(x, q), q_to_f32(y, q), q_to_f32(z, q)];
720 }
721
722 fn update_gyro_calib(&mut self, x: i16, y: i16, z: i16) {
723 let q = Q_POINTS[SENSOR_REPORTID_GYROSCOPE as usize];
724 self.gyro = [q_to_f32(x, q), q_to_f32(y, q), q_to_f32(z, q)];
725 }
726
727 fn update_gyro_uncalib(&mut self, x: i16, y: i16, z: i16) {
728 let q = Q_POINTS[SENSOR_REPORTID_GYROSCOPE_UNCALIB as usize];
729 self.uncalib_gyro = [q_to_f32(x, q), q_to_f32(y, q), q_to_f32(z, q)];
730 }
731
732 fn update_magnetic_field_calib(&mut self, x: i16, y: i16, z: i16) {
733 let q = Q_POINTS[SENSOR_REPORTID_MAGNETIC_FIELD as usize];
734 self.mag_field = [q_to_f32(x, q), q_to_f32(y, q), q_to_f32(z, q)];
735 }
736
737 fn handle_cmd_resp_error_list(&mut self, received_len: usize) {
739 let payload_len = received_len - PACKET_HEADER_LENGTH;
740 let payload = &self.packet_recv_buf[PACKET_HEADER_LENGTH..received_len];
741
742 self.error_list_received = true;
743 for err in payload.iter().take(payload_len).skip(1) {
744 let err: u8 = *err;
745 self.last_error_received = err;
746 match err {
747 0 => {}
748 1 => {
749 warn!("Hub application attempted to exceed maximum read cargo length: Error code {}", err);
750 }
751 2 => {
752 warn!(
753 "Host write was too short (need at least a 4-byte header): Error code {}",
754 err
755 );
756 }
757 3 => {
758 warn!("Host wrote a header with length greater than maximum write cargo length: Error code {}", err);
759 }
760 4 => {
761 warn!("Host wrote a header with length less than or equal to header length: Error code {}", err);
762 }
763 5 => {
764 warn!("Host wrote beginning of fragmented cargo, fragmentation not supported: Error code {}", err);
765 }
766 6 => {
767 warn!("Host wrote continuation of fragmented cargo, fragmentation not supported: Error code {}", err);
768 }
769 7 => {
770 warn!(
771 "Unrecognized command on control channel: Error code {}",
772 err
773 );
774 }
775 8 => {
776 warn!(
777 "Unrecognized parameter to get-advertisement command: Error code {}",
778 err
779 );
780 }
781 9 => {
782 warn!("Host wrote to unrecognized channel: Error code {}", err);
783 }
784 10 => {
785 warn!("Advertisement request received while Advertisement Response was pending: Error code {}", err);
786 }
787 11 => {
788 warn!("Host performed a write operation before the hub had finished sending its advertisement response: Error code {}", err);
789 }
790 12 => {
791 warn!("Error list too long to send, truncated: Error code {}", err);
792 }
793 _ => {
794 debug!("Unknown error code {}", err);
795 }
796 }
797 }
798 }
799
800 pub fn handle_received_packet(&mut self, received_len: usize) -> Result<(), Box<dyn Debug>> {
802 let mut rec_len = received_len;
803 if rec_len > PACKET_RECV_BUF_LEN {
804 warn!(
805 "Packet length of {} exceeded the buffer length of {}",
806 received_len, PACKET_RECV_BUF_LEN
807 );
808 rec_len = PACKET_RECV_BUF_LEN;
809 } else if rec_len < PACKET_HEADER_LENGTH {
810 return Err(Box::new(format!(
811 "Packet length of {} was ignored. Shorter than header length of {}",
812 received_len, PACKET_HEADER_LENGTH
813 )));
814 }
815 let msg = &self.packet_recv_buf[..rec_len];
816 let chan_num = msg[2];
817 let report_id: u8 = if rec_len > PACKET_HEADER_LENGTH {
818 msg[4]
819 } else {
820 0
821 };
822 self.last_chan_received = chan_num;
823 match chan_num {
824 CHANNEL_COMMAND => match report_id {
825 CMD_RESP_ADVERTISEMENT => {
826 self.handle_advertise_response(rec_len);
827 }
828 CMD_RESP_ERROR_LIST => {
829 self.handle_cmd_resp_error_list(rec_len);
830 }
831 _ => {
832 self.last_command_chan_rid = report_id;
833 return Err(Box::new(format!("unknown cmd: {}", report_id)));
834 }
835 },
836 CHANNEL_EXECUTABLE => match report_id {
837 EXECUTABLE_DEVICE_RESP_RESET_COMPLETE => {
838 self.device_reset = true;
839 trace!("resp_reset {}", 1);
840 }
841 _ => {
842 self.last_exec_chan_rid = report_id;
843 return Err(Box::new(format!("unknown exe: {}", report_id)));
844 }
845 },
846 CHANNEL_HUB_CONTROL => match report_id {
847 SHUB_COMMAND_RESP => {
848 let cmd_resp = msg[6];
849 if cmd_resp == SH2_STARTUP_INIT_UNSOLICITED || cmd_resp == SH2_INIT_SYSTEM {
850 self.init_received = true;
851 }
852 trace!("CMD_RESP: 0x{:X}", cmd_resp);
853 }
854 SHUB_PROD_ID_RESP => {
855 {
856 let _sw_vers_major = msg[4 + 2];
857 let _sw_vers_minor = msg[4 + 3];
858 trace!("PID_RESP {}.{}", _sw_vers_major, _sw_vers_major);
859 }
860 self.prod_id_verified = true;
861 }
862 SHUB_GET_FEATURE_RESP => {
863 trace!("feat resp: {}", msg[5]);
864 self.report_enabled[msg[5] as usize] = true;
865 }
866 SHUB_FRS_WRITE_RESP => {
867 trace!("write resp: {}", frs_status_to_str(msg[5]));
868 self.frs_write_status = msg[5];
869 }
870 _ => {
871 trace!(
872 "unh hbc: 0x{:X} {:x?}",
873 report_id,
874 &msg[..PACKET_HEADER_LENGTH]
875 );
876 return Err(Box::new(format!(
877 "unknown hbc: 0x{:X} {:x?}",
878 report_id,
879 &msg[..PACKET_HEADER_LENGTH]
880 )));
881 }
882 },
883 CHANNEL_SENSOR_REPORTS => {
884 self.handle_sensor_reports(rec_len);
885 }
886 _ => {
887 self.last_chan_received = chan_num;
888 trace!("unh chan 0x{:X}", chan_num);
889 return Err(Box::new(format!("unknown chan 0x{:X}", chan_num)));
890 }
891 }
892 Ok(())
893 }
894
895 pub fn init(&mut self) -> Result<(), DriverError<SE>> {
919 trace!("driver init");
920
921 delay_ms(1);
924 self.sensor_interface
925 .setup()
926 .map_err(DriverError::CommError)?;
927
928 if self.sensor_interface.requires_soft_reset() {
929 delay_ms(1);
930 self.soft_reset()?;
931 delay_ms(250);
932 self.eat_all_messages();
933 delay_ms(250);
934 self.eat_all_messages();
935 } else {
936 delay_ms(250);
939 trace!("Eating advertisement response");
940 self.handle_one_message(20);
941 trace!("Eating reset response");
942 delay_ms(250);
943 self.handle_one_message(20);
944 }
945 self.verify_product_id()?;
946 delay_ms(100);
947 Ok(())
948 }
949
950 pub fn enable_rotation_vector(
957 &mut self,
958 millis_between_reports: u16,
959 ) -> Result<bool, DriverError<SE>> {
960 self.enable_report(SENSOR_REPORTID_ROTATION_VECTOR, millis_between_reports)
961 }
962
963 pub fn enable_linear_accel(
967 &mut self,
968 millis_between_reports: u16,
969 ) -> Result<bool, DriverError<SE>> {
970 self.enable_report(SENSOR_REPORTID_LINEAR_ACCEL, millis_between_reports)
971 }
972
973 pub fn enable_gyro(&mut self, millis_between_reports: u16) -> Result<bool, DriverError<SE>> {
977 self.enable_report(SENSOR_REPORTID_GYROSCOPE, millis_between_reports)
978 }
979
980 pub fn enable_gravity(&mut self, millis_between_reports: u16) -> Result<bool, DriverError<SE>> {
984 self.enable_report(SENSOR_REPORTID_GRAVITY, millis_between_reports)
985 }
986
987 pub fn report_update_time(&self, report_id: u8) -> u128 {
989 if report_id as usize <= self.report_enabled.len() {
990 return self.report_update_time[report_id as usize];
991 }
992 0
993 }
994
995 pub fn is_report_enabled(&self, report_id: u8) -> bool {
997 if report_id as usize <= self.report_enabled.len() {
998 return self.report_enabled[report_id as usize];
999 }
1000 false
1001 }
1002
1003 pub fn add_sensor_report_callback(
1005 &mut self,
1006 report_id: u8,
1007 key: String,
1008 func: impl Fn(&Self) + 'a,
1009 ) {
1010 self.report_update_callbacks[report_id as usize]
1011 .entry(key)
1012 .or_insert_with(|| Box::new(func));
1013 }
1014
1015 pub fn remove_sensor_report_callback(&mut self, report_id: u8, key: String) {
1017 self.report_update_callbacks[report_id as usize].remove(&key);
1018 }
1019
1020 pub fn enable_report(
1024 &mut self,
1025 report_id: u8,
1026 millis_between_reports: u16,
1027 ) -> Result<bool, DriverError<SE>> {
1028 trace!("enable_report 0x{:X}", report_id);
1029
1030 let micros_between_reports: u32 = (millis_between_reports as u32) * 1000;
1031 let cmd_body: [u8; 17] = [
1032 SHUB_REPORT_SET_FEATURE_CMD,
1033 report_id,
1034 0, 0, 0, (micros_between_reports & 0xFFu32) as u8, (micros_between_reports.shr(8) & 0xFFu32) as u8,
1039 (micros_between_reports.shr(16) & 0xFFu32) as u8,
1040 (micros_between_reports.shr(24) & 0xFFu32) as u8, 0, 0,
1043 0,
1044 0, 0, 0,
1047 0,
1048 0, ];
1050 self.send_packet(CHANNEL_HUB_CONTROL, &cmd_body)?;
1051
1052 let start = Instant::now();
1053 while !self.report_enabled[report_id as usize] && start.elapsed().as_millis() < 2000 {
1054 if let Ok(received_len) = self.receive_packet_with_timeout(250) {
1055 if received_len > 0 {
1056 if let Err(e) = self.handle_received_packet(received_len) {
1057 warn!("{:?}", e)
1058 }
1059 }
1060 }
1061 }
1062 delay_ms(200);
1063 trace!(
1064 "Report {:x} is enabled: {}",
1065 report_id,
1066 self.report_enabled[report_id as usize]
1067 );
1068 if !self.report_enabled[report_id as usize] {
1069 return Ok(false);
1070 }
1071 Ok(true)
1072 }
1073
1074 fn wait_for_frs_response(&mut self, timeout_ms: u128) -> bool {
1081 let start = Instant::now();
1082 while self.frs_write_status == FRS_STATUS_NO_DATA
1083 && start.elapsed().as_millis() < timeout_ms
1084 {
1085 if let Ok(received_len) = self.receive_packet_with_timeout(250) {
1086 if received_len > 0 {
1087 if let Err(e) = self.handle_received_packet(received_len) {
1088 warn!("{:?}", e)
1089 }
1090 }
1091 }
1092 }
1093 self.frs_write_status != FRS_STATUS_NO_DATA
1094 }
1095
1096 fn wait_for_frs_completion(&mut self, timeout_ms: u128) -> bool {
1103 let start = Instant::now();
1104 while self.frs_write_status != FRS_STATUS_WRITE_FAILED
1105 && self.frs_write_status != FRS_STATUS_WRITE_COMPLETE
1106 && start.elapsed().as_millis() < timeout_ms
1107 {
1108 if let Ok(received_len) = self.receive_packet_with_timeout(250) {
1109 if received_len > 0 {
1110 if let Err(e) = self.handle_received_packet(received_len) {
1111 warn!("{:?}", e)
1112 }
1113 }
1114 }
1115 }
1116 self.frs_write_status == FRS_STATUS_WRITE_COMPLETE
1117 }
1118
1119 fn send_frs_data_chunk(
1124 &mut self,
1125 offset: u16,
1126 word1: [u8; 4],
1127 word2: [u8; 4],
1128 timeout_ms: u128,
1129 ) -> Result<(), DriverError<SE>> {
1130 let cmd_body_data = build_frs_write_data(offset, word1, word2);
1131 let _ = self.send_packet(CHANNEL_HUB_CONTROL, cmd_body_data.as_ref())?;
1132
1133 self.frs_write_status = FRS_STATUS_NO_DATA;
1134 self.wait_for_frs_response(timeout_ms);
1135 delay_ms(150);
1136 Ok(())
1137 }
1138
1139 pub fn set_sensor_orientation(
1144 &mut self,
1145 qi: f32,
1146 qj: f32,
1147 qk: f32,
1148 qr: f32,
1149 timeout: u128,
1150 ) -> Result<bool, DriverError<SE>> {
1151 let length: u16 = 4;
1153 let cmd_body_req = build_frs_write_request(length, FRS_TYPE_SENSOR_ORIENTATION);
1154 let _ = self.send_packet(CHANNEL_HUB_CONTROL, cmd_body_req.as_ref())?;
1155
1156 self.frs_write_status = FRS_STATUS_NO_DATA;
1158 self.wait_for_frs_response(timeout);
1159
1160 if self.frs_write_status != FRS_STATUS_WRITE_READY {
1161 trace!("FRS Write not ready");
1162 return Ok(false);
1163 }
1164 trace!("FRS Write ready");
1165 delay_ms(150);
1166
1167 let (q30_qi, q30_qj, q30_qk, q30_qr) = quaternion_to_frs_words(qi, qj, qk, qr);
1169
1170 self.send_frs_data_chunk(0, q30_qi, q30_qj, 800)?;
1171 self.send_frs_data_chunk(2, q30_qk, q30_qr, 800)?;
1172
1173 self.frs_write_status = FRS_STATUS_NO_DATA;
1175 let success = self.wait_for_frs_completion(800);
1176 delay_ms(100);
1177
1178 Ok(success)
1179 }
1180
1181 fn prep_send_packet(&mut self, channel: u8, body_data: &[u8]) -> usize {
1183 let body_len = body_data.len();
1184
1185 let packet_length = body_len + PACKET_HEADER_LENGTH;
1186 let packet_header = [
1187 (packet_length & 0xFF) as u8, packet_length.shr(8) as u8, channel,
1190 self.sequence_numbers[channel as usize],
1191 ];
1192 self.sequence_numbers[channel as usize] += 1;
1193
1194 self.packet_send_buf[..PACKET_HEADER_LENGTH].copy_from_slice(packet_header.as_ref());
1195 self.packet_send_buf[PACKET_HEADER_LENGTH..packet_length].copy_from_slice(body_data);
1196
1197 packet_length
1198 }
1199
1200 fn send_packet(&mut self, channel: u8, body_data: &[u8]) -> Result<usize, DriverError<SE>> {
1202 let packet_length = self.prep_send_packet(channel, body_data);
1203
1204 let rc = self
1205 .sensor_interface
1206 .send_and_receive_packet(
1207 &self.packet_send_buf[..packet_length],
1208 &mut self.packet_recv_buf,
1209 )
1210 .map_err(DriverError::CommError)?;
1211 if rc > 0 {
1212 if let Err(e) = self.handle_received_packet(rc) {
1213 warn!("{:?}", e)
1214 }
1215 }
1216 Ok(packet_length)
1217 }
1218
1219 pub(crate) fn receive_packet_with_timeout(
1221 &mut self,
1222 max_ms: usize,
1223 ) -> Result<usize, DriverError<SE>> {
1224 self.packet_recv_buf[0] = 0;
1225 self.packet_recv_buf[1] = 0;
1226 let packet_len = self
1227 .sensor_interface
1228 .read_with_timeout(&mut self.packet_recv_buf, max_ms)
1229 .map_err(DriverError::CommError)?;
1230
1231 self.last_packet_len_received = packet_len;
1232
1233 Ok(packet_len)
1234 }
1235
1236 fn verify_product_id(&mut self) -> Result<(), DriverError<SE>> {
1238 trace!("request PID...");
1239 let cmd_body: [u8; 2] = [
1240 SHUB_PROD_ID_REQ, 0, ];
1243
1244 if self.sensor_interface.requires_soft_reset() {
1247 self.send_packet(CHANNEL_HUB_CONTROL, cmd_body.as_ref())?;
1248 } else {
1249 let response_size =
1250 self.send_and_receive_packet(CHANNEL_HUB_CONTROL, cmd_body.as_ref())?;
1251 if response_size > 0 {
1252 if let Err(e) = self.handle_received_packet(response_size) {
1253 warn!("{:?}", e)
1254 }
1255 }
1256 }
1257
1258 while !self.prod_id_verified {
1260 trace!("read PID");
1261 let msg_count = self.handle_one_message(150);
1262 if msg_count < 1 {
1263 break;
1264 }
1265 }
1266
1267 if !self.prod_id_verified {
1268 return Err(DriverError::InvalidChipId(0));
1269 }
1270 Ok(())
1271 }
1272
1273 pub fn accelerometer(&self) -> Result<[f32; 3], DriverError<SE>> {
1275 Ok(self.accelerometer)
1276 }
1277
1278 pub fn rotation_quaternion(&self) -> Result<[f32; 4], DriverError<SE>> {
1280 Ok(self.rotation_quaternion)
1281 }
1282
1283 pub fn rotation_acc(&self) -> f32 {
1285 self.rotation_acc
1286 }
1287
1288 pub fn game_rotation_quaternion(&self) -> Result<[f32; 4], DriverError<SE>> {
1290 Ok(self.game_rotation_quaternion)
1291 }
1292
1293 pub fn geomag_rotation_quaternion(&self) -> Result<[f32; 4], DriverError<SE>> {
1295 Ok(self.geomag_rotation_quaternion)
1296 }
1297
1298 pub fn geomag_rotation_acc(&self) -> f32 {
1300 self.geomag_rotation_acc
1301 }
1302
1303 pub fn linear_accel(&self) -> Result<[f32; 3], DriverError<SE>> {
1305 Ok(self.linear_accel)
1306 }
1307
1308 pub fn gravity(&self) -> Result<[f32; 3], DriverError<SE>> {
1310 Ok(self.gravity)
1311 }
1312
1313 pub fn gyro(&self) -> Result<[f32; 3], DriverError<SE>> {
1315 Ok(self.gyro)
1316 }
1317
1318 pub fn gyro_uncalib(&self) -> Result<[f32; 3], DriverError<SE>> {
1320 Ok(self.uncalib_gyro)
1321 }
1322
1323 pub fn mag_field(&self) -> Result<[f32; 3], DriverError<SE>> {
1325 Ok(self.mag_field)
1326 }
1327
1328 pub fn soft_reset(&mut self) -> Result<(), DriverError<SE>> {
1333 trace!("soft_reset");
1334 let data: [u8; 1] = [EXECUTABLE_DEVICE_CMD_RESET];
1335 let received_len = self.send_and_receive_packet(CHANNEL_EXECUTABLE, data.as_ref())?;
1336 if received_len > 0 {
1337 if let Err(e) = self.handle_received_packet(received_len) {
1338 warn!("{:?}", e)
1339 }
1340 }
1341 Ok(())
1342 }
1343
1344 fn send_and_receive_packet(
1346 &mut self,
1347 channel: u8,
1348 body_data: &[u8],
1349 ) -> Result<usize, DriverError<SE>> {
1350 let send_packet_length = self.prep_send_packet(channel, body_data);
1351
1352 let recv_packet_length = self
1353 .sensor_interface
1354 .send_and_receive_packet(
1355 self.packet_send_buf[..send_packet_length].as_ref(),
1356 &mut self.packet_recv_buf,
1357 )
1358 .map_err(DriverError::CommError)?;
1359
1360 Ok(recv_packet_length)
1361 }
1362}
1363
1364#[cfg(test)]
1365mod tests {
1366 use super::*;
1367 use crate::interface::SensorInterface;
1368
1369 struct MockSensorInterface {
1371 setup_called: bool,
1372 soft_reset_required: bool,
1373 }
1374
1375 impl MockSensorInterface {
1376 fn new() -> Self {
1377 Self {
1378 setup_called: false,
1379 soft_reset_required: false,
1380 }
1381 }
1382 }
1383
1384 #[derive(Debug)]
1385 struct MockError;
1386
1387 impl SensorInterface for MockSensorInterface {
1388 type SensorError = MockError;
1389
1390 fn setup(&mut self) -> Result<(), Self::SensorError> {
1391 self.setup_called = true;
1392 Ok(())
1393 }
1394
1395 fn write_packet(&mut self, _packet: &[u8]) -> Result<(), Self::SensorError> {
1396 Ok(())
1397 }
1398
1399 fn read_packet(&mut self, _recv_buf: &mut [u8]) -> Result<usize, Self::SensorError> {
1400 Ok(0)
1401 }
1402
1403 fn read_with_timeout(
1404 &mut self,
1405 _recv_buf: &mut [u8],
1406 _max_ms: usize,
1407 ) -> Result<usize, Self::SensorError> {
1408 Ok(0)
1409 }
1410
1411 fn send_and_receive_packet(
1412 &mut self,
1413 _send_buf: &[u8],
1414 _recv_buf: &mut [u8],
1415 ) -> Result<usize, Self::SensorError> {
1416 Ok(0)
1417 }
1418
1419 fn requires_soft_reset(&self) -> bool {
1420 self.soft_reset_required
1421 }
1422 }
1423
1424 #[test]
1429 fn test_driver_error_comm_error_to_io_error() {
1430 let err: DriverError<&str> = DriverError::CommError("test error");
1431 let io_err: io::Error = err.into();
1432 assert!(io_err.to_string().contains("Communication error"));
1433 assert!(io_err.to_string().contains("test error"));
1434 }
1435
1436 #[test]
1437 fn test_driver_error_invalid_chip_id_to_io_error() {
1438 let err: DriverError<&str> = DriverError::InvalidChipId(0x42);
1439 let io_err: io::Error = err.into();
1440 assert_eq!(io_err.kind(), ErrorKind::InvalidData);
1441 assert!(io_err.to_string().contains("Invalid chip ID"));
1442 assert!(io_err.to_string().contains("66")); }
1444
1445 #[test]
1446 fn test_driver_error_invalid_fw_version_to_io_error() {
1447 let err: DriverError<&str> = DriverError::InvalidFWVersion(0x10);
1448 let io_err: io::Error = err.into();
1449 assert_eq!(io_err.kind(), ErrorKind::InvalidData);
1450 assert!(io_err.to_string().contains("Invalid firmware version"));
1451 }
1452
1453 #[test]
1454 fn test_driver_error_no_data_available_to_io_error() {
1455 let err: DriverError<&str> = DriverError::NoDataAvailable;
1456 let io_err: io::Error = err.into();
1457 assert_eq!(io_err.kind(), ErrorKind::TimedOut);
1458 assert!(io_err.to_string().contains("No sensor data available"));
1459 }
1460
1461 #[test]
1466 fn test_read_u8_at_cursor() {
1467 let data = [0x12, 0x34, 0x56, 0x78];
1468 let mut cursor = 0;
1469
1470 assert_eq!(
1471 BNO08x::<MockSensorInterface>::read_u8_at_cursor(&data, &mut cursor),
1472 0x12
1473 );
1474 assert_eq!(cursor, 1);
1475
1476 assert_eq!(
1477 BNO08x::<MockSensorInterface>::read_u8_at_cursor(&data, &mut cursor),
1478 0x34
1479 );
1480 assert_eq!(cursor, 2);
1481
1482 assert_eq!(
1483 BNO08x::<MockSensorInterface>::read_u8_at_cursor(&data, &mut cursor),
1484 0x56
1485 );
1486 assert_eq!(cursor, 3);
1487
1488 assert_eq!(
1489 BNO08x::<MockSensorInterface>::read_u8_at_cursor(&data, &mut cursor),
1490 0x78
1491 );
1492 assert_eq!(cursor, 4);
1493 }
1494
1495 #[test]
1496 fn test_read_i16_at_cursor_positive() {
1497 let data = [0x02, 0x01, 0x00, 0x00];
1499 let mut cursor = 0;
1500
1501 let value = BNO08x::<MockSensorInterface>::read_i16_at_cursor(&data, &mut cursor);
1502 assert_eq!(value, 0x0102);
1503 assert_eq!(cursor, 2);
1504 }
1505
1506 #[test]
1507 fn test_read_i16_at_cursor_negative() {
1508 let data = [0xFF, 0xFF, 0x00, 0x00];
1510 let mut cursor = 0;
1511
1512 let value = BNO08x::<MockSensorInterface>::read_i16_at_cursor(&data, &mut cursor);
1513 assert_eq!(value, -1);
1514 assert_eq!(cursor, 2);
1515 }
1516
1517 #[test]
1518 fn test_read_i16_at_cursor_max_positive() {
1519 let data = [0xFF, 0x7F, 0x00, 0x00];
1521 let mut cursor = 0;
1522
1523 let value = BNO08x::<MockSensorInterface>::read_i16_at_cursor(&data, &mut cursor);
1524 assert_eq!(value, i16::MAX);
1525 }
1526
1527 #[test]
1528 fn test_read_i16_at_cursor_min_negative() {
1529 let data = [0x00, 0x80, 0x00, 0x00];
1531 let mut cursor = 0;
1532
1533 let value = BNO08x::<MockSensorInterface>::read_i16_at_cursor(&data, &mut cursor);
1534 assert_eq!(value, i16::MIN);
1535 }
1536
1537 #[test]
1538 fn test_try_read_i16_at_cursor_success() {
1539 let data = [0x34, 0x12, 0x78, 0x56];
1540 let mut cursor = 0;
1541
1542 let result = BNO08x::<MockSensorInterface>::try_read_i16_at_cursor(&data, &mut cursor);
1543 assert_eq!(result, Some(0x1234));
1544 assert_eq!(cursor, 2);
1545
1546 let result = BNO08x::<MockSensorInterface>::try_read_i16_at_cursor(&data, &mut cursor);
1547 assert_eq!(result, Some(0x5678));
1548 assert_eq!(cursor, 4);
1549 }
1550
1551 #[test]
1552 fn test_try_read_i16_at_cursor_insufficient_data() {
1553 let data = [0x12];
1554 let mut cursor = 0;
1555
1556 let result = BNO08x::<MockSensorInterface>::try_read_i16_at_cursor(&data, &mut cursor);
1557 assert_eq!(result, None);
1558 assert_eq!(cursor, 0); }
1560
1561 #[test]
1562 fn test_try_read_i16_at_cursor_exactly_at_end() {
1563 let data = [0x12, 0x34];
1564 let mut cursor = 2;
1565
1566 let result = BNO08x::<MockSensorInterface>::try_read_i16_at_cursor(&data, &mut cursor);
1567 assert_eq!(result, None);
1568 }
1569
1570 #[test]
1571 fn test_try_read_i16_at_cursor_one_byte_remaining() {
1572 let data = [0x12, 0x34, 0x56];
1573 let mut cursor = 2;
1574
1575 let result = BNO08x::<MockSensorInterface>::try_read_i16_at_cursor(&data, &mut cursor);
1576 assert_eq!(result, None);
1577 }
1578
1579 #[test]
1584 fn test_handle_one_input_report_full_data() {
1585 #[rustfmt::skip]
1588 let msg: [u8; 14] = [
1589 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, ];
1599
1600 let (cursor, report_id, d1, d2, d3, d4, d5) =
1601 BNO08x::<MockSensorInterface>::handle_one_input_report(0, &msg);
1602
1603 assert_eq!(report_id, SENSOR_REPORTID_ACCELEROMETER);
1604 assert_eq!(d1, 256);
1605 assert_eq!(d2, 512);
1606 assert_eq!(d3, 1024);
1607 assert_eq!(d4, 2048);
1608 assert_eq!(d5, 4096);
1609 assert_eq!(cursor, 14);
1610 }
1611
1612 #[test]
1613 fn test_handle_one_input_report_partial_data() {
1614 let msg: [u8; 10] = [
1616 0x01, 0x01, 0x02, 0x03, 0x10, 0x00, 0x20, 0x00, 0x30, 0x00, ];
1624
1625 let (cursor, report_id, d1, d2, d3, d4, d5) =
1626 BNO08x::<MockSensorInterface>::handle_one_input_report(0, &msg);
1627
1628 assert_eq!(report_id, SENSOR_REPORTID_ACCELEROMETER);
1629 assert_eq!(d1, 16);
1630 assert_eq!(d2, 32);
1631 assert_eq!(d3, 48);
1632 assert_eq!(d4, 0); assert_eq!(d5, 0); assert_eq!(cursor, 10);
1635 }
1636
1637 #[test]
1638 fn test_handle_one_input_report_with_offset() {
1639 #[rustfmt::skip]
1641 let msg: [u8; 16] = [
1642 0xFF, 0xFF, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, ];
1653
1654 let (cursor, report_id, d1, d2, d3, d4, d5) =
1655 BNO08x::<MockSensorInterface>::handle_one_input_report(2, &msg);
1656
1657 assert_eq!(report_id, SENSOR_REPORTID_ROTATION_VECTOR);
1658 assert_eq!(d1, 1);
1659 assert_eq!(d2, 2);
1660 assert_eq!(d3, 3);
1661 assert_eq!(d4, 4);
1662 assert_eq!(d5, 5);
1663 assert_eq!(cursor, 16); }
1665
1666 #[test]
1671 fn test_new_with_interface() {
1672 let mock = MockSensorInterface::new();
1673 let driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
1674
1675 assert!(!driver.device_reset);
1677 assert!(!driver.prod_id_verified);
1678 assert!(!driver.init_received);
1679 assert!(!driver.advert_received);
1680 assert!(!driver.error_list_received);
1681 assert_eq!(driver.last_packet_len_received, 0);
1682 assert_eq!(driver.sequence_numbers, [0; NUM_CHANNELS]);
1683 assert_eq!(driver.accelerometer, [0.0; 3]);
1684 assert_eq!(driver.rotation_quaternion, [0.0; 4]);
1685 assert_eq!(driver.gyro, [0.0; 3]);
1686 }
1687
1688 #[test]
1689 fn test_free_returns_interface() {
1690 let mock = MockSensorInterface::new();
1691 let driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
1692 let _interface = driver.free();
1693 }
1695
1696 #[test]
1701 fn test_accelerometer_accessor() {
1702 let mock = MockSensorInterface::new();
1703 let driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
1704
1705 let accel = driver.accelerometer().unwrap();
1706 assert_eq!(accel, [0.0, 0.0, 0.0]);
1707 }
1708
1709 #[test]
1710 fn test_rotation_quaternion_accessor() {
1711 let mock = MockSensorInterface::new();
1712 let driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
1713
1714 let quat = driver.rotation_quaternion().unwrap();
1715 assert_eq!(quat, [0.0, 0.0, 0.0, 0.0]);
1716 }
1717
1718 #[test]
1719 fn test_rotation_acc_accessor() {
1720 let mock = MockSensorInterface::new();
1721 let driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
1722
1723 assert_eq!(driver.rotation_acc(), 0.0);
1724 }
1725
1726 #[test]
1727 fn test_game_rotation_quaternion_accessor() {
1728 let mock = MockSensorInterface::new();
1729 let driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
1730
1731 let quat = driver.game_rotation_quaternion().unwrap();
1732 assert_eq!(quat, [0.0, 0.0, 0.0, 0.0]);
1733 }
1734
1735 #[test]
1736 fn test_geomag_rotation_quaternion_accessor() {
1737 let mock = MockSensorInterface::new();
1738 let driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
1739
1740 let quat = driver.geomag_rotation_quaternion().unwrap();
1741 assert_eq!(quat, [0.0, 0.0, 0.0, 0.0]);
1742 }
1743
1744 #[test]
1745 fn test_geomag_rotation_acc_accessor() {
1746 let mock = MockSensorInterface::new();
1747 let driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
1748
1749 assert_eq!(driver.geomag_rotation_acc(), 0.0);
1750 }
1751
1752 #[test]
1753 fn test_linear_accel_accessor() {
1754 let mock = MockSensorInterface::new();
1755 let driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
1756
1757 let accel = driver.linear_accel().unwrap();
1758 assert_eq!(accel, [0.0, 0.0, 0.0]);
1759 }
1760
1761 #[test]
1762 fn test_gravity_accessor() {
1763 let mock = MockSensorInterface::new();
1764 let driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
1765
1766 let gravity = driver.gravity().unwrap();
1767 assert_eq!(gravity, [0.0, 0.0, 0.0]);
1768 }
1769
1770 #[test]
1771 fn test_gyro_accessor() {
1772 let mock = MockSensorInterface::new();
1773 let driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
1774
1775 let gyro = driver.gyro().unwrap();
1776 assert_eq!(gyro, [0.0, 0.0, 0.0]);
1777 }
1778
1779 #[test]
1780 fn test_gyro_uncalib_accessor() {
1781 let mock = MockSensorInterface::new();
1782 let driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
1783
1784 let gyro = driver.gyro_uncalib().unwrap();
1785 assert_eq!(gyro, [0.0, 0.0, 0.0]);
1786 }
1787
1788 #[test]
1789 fn test_mag_field_accessor() {
1790 let mock = MockSensorInterface::new();
1791 let driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
1792
1793 let mag = driver.mag_field().unwrap();
1794 assert_eq!(mag, [0.0, 0.0, 0.0]);
1795 }
1796
1797 #[test]
1802 fn test_is_report_enabled_default() {
1803 let mock = MockSensorInterface::new();
1804 let driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
1805
1806 for i in 0..16 {
1808 assert!(!driver.is_report_enabled(i));
1809 }
1810 }
1811
1812 #[test]
1813 fn test_is_report_enabled_out_of_bounds() {
1814 let mock = MockSensorInterface::new();
1815 let driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
1816
1817 assert!(!driver.is_report_enabled(255));
1819 }
1820
1821 #[test]
1822 fn test_report_update_time_default() {
1823 let mock = MockSensorInterface::new();
1824 let driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
1825
1826 for i in 0..16 {
1828 assert_eq!(driver.report_update_time(i), 0);
1829 }
1830 }
1831
1832 #[test]
1833 fn test_report_update_time_out_of_bounds() {
1834 let mock = MockSensorInterface::new();
1835 let driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
1836
1837 assert_eq!(driver.report_update_time(255), 0);
1839 }
1840
1841 #[test]
1846 fn test_prep_send_packet_basic() {
1847 let mock = MockSensorInterface::new();
1848 let mut driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
1849
1850 let body = [0x01, 0x02, 0x03];
1851 let packet_len = driver.prep_send_packet(CHANNEL_HUB_CONTROL, &body);
1852
1853 assert_eq!(packet_len, 7);
1855
1856 assert_eq!(driver.packet_send_buf[0], 7); assert_eq!(driver.packet_send_buf[1], 0); assert_eq!(driver.packet_send_buf[2], CHANNEL_HUB_CONTROL);
1860 assert_eq!(driver.packet_send_buf[3], 0); assert_eq!(driver.packet_send_buf[4], 0x01);
1864 assert_eq!(driver.packet_send_buf[5], 0x02);
1865 assert_eq!(driver.packet_send_buf[6], 0x03);
1866 }
1867
1868 #[test]
1869 fn test_prep_send_packet_sequence_increments() {
1870 let mock = MockSensorInterface::new();
1871 let mut driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
1872
1873 let body = [0x01];
1874
1875 driver.prep_send_packet(CHANNEL_HUB_CONTROL, &body);
1877 assert_eq!(driver.sequence_numbers[CHANNEL_HUB_CONTROL as usize], 1);
1878
1879 driver.prep_send_packet(CHANNEL_HUB_CONTROL, &body);
1881 assert_eq!(driver.sequence_numbers[CHANNEL_HUB_CONTROL as usize], 2);
1882
1883 driver.prep_send_packet(CHANNEL_HUB_CONTROL, &body);
1885 assert_eq!(driver.sequence_numbers[CHANNEL_HUB_CONTROL as usize], 3);
1886 }
1887
1888 #[test]
1889 fn test_prep_send_packet_different_channels() {
1890 let mock = MockSensorInterface::new();
1891 let mut driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
1892
1893 let body = [0x01];
1894
1895 driver.prep_send_packet(CHANNEL_COMMAND, &body);
1897 driver.prep_send_packet(CHANNEL_HUB_CONTROL, &body);
1898 driver.prep_send_packet(CHANNEL_EXECUTABLE, &body);
1899
1900 assert_eq!(driver.sequence_numbers[CHANNEL_COMMAND as usize], 1);
1902 assert_eq!(driver.sequence_numbers[CHANNEL_HUB_CONTROL as usize], 1);
1903 assert_eq!(driver.sequence_numbers[CHANNEL_EXECUTABLE as usize], 1);
1904 }
1905
1906 #[test]
1907 fn test_prep_send_packet_large_body() {
1908 let mock = MockSensorInterface::new();
1909 let mut driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
1910
1911 let body = [0xAB; 100];
1913 let packet_len = driver.prep_send_packet(CHANNEL_HUB_CONTROL, &body);
1914
1915 assert_eq!(packet_len, 104); assert_eq!(driver.packet_send_buf[0], 104); assert_eq!(driver.packet_send_buf[1], 0); for i in 0..100 {
1921 assert_eq!(driver.packet_send_buf[4 + i], 0xAB);
1922 }
1923 }
1924
1925 #[test]
1930 fn test_update_accelerometer() {
1931 let mock = MockSensorInterface::new();
1932 let mut driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
1933
1934 driver.update_accelerometer(256, 512, -256);
1936
1937 let accel = driver.accelerometer().unwrap();
1938 assert!((accel[0] - 1.0).abs() < 0.01);
1939 assert!((accel[1] - 2.0).abs() < 0.01);
1940 assert!((accel[2] + 1.0).abs() < 0.01);
1941 }
1942
1943 #[test]
1944 fn test_update_rotation_quaternion() {
1945 let mock = MockSensorInterface::new();
1946 let mut driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
1947
1948 driver.update_rotation_quaternion(0, 0, 0, 16384, 0);
1951
1952 let quat = driver.rotation_quaternion().unwrap();
1953 assert!(quat[0].abs() < 0.001);
1954 assert!(quat[1].abs() < 0.001);
1955 assert!(quat[2].abs() < 0.001);
1956 assert!((quat[3] - 1.0).abs() < 0.001);
1957 }
1958
1959 #[test]
1960 fn test_update_rotation_quaternion_with_accuracy() {
1961 let mock = MockSensorInterface::new();
1962 let mut driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
1963
1964 driver.update_rotation_quaternion(0, 0, 0, 16384, 2048);
1966
1967 assert!((driver.rotation_acc() - 0.5).abs() < 0.01);
1968 }
1969
1970 #[test]
1971 fn test_update_rotation_quaternion_game() {
1972 let mock = MockSensorInterface::new();
1973 let mut driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
1974
1975 driver.update_rotation_quaternion_game(8192, 0, 0, 8192);
1977
1978 let quat = driver.game_rotation_quaternion().unwrap();
1979 assert!((quat[0] - 0.5).abs() < 0.001);
1980 assert!(quat[1].abs() < 0.001);
1981 assert!(quat[2].abs() < 0.001);
1982 assert!((quat[3] - 0.5).abs() < 0.001);
1983 }
1984
1985 #[test]
1986 fn test_update_rotation_quaternion_geomag() {
1987 let mock = MockSensorInterface::new();
1988 let mut driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
1989
1990 driver.update_rotation_quaternion_geomag(0, 0, 0, 16384, 4096);
1991
1992 let quat = driver.geomag_rotation_quaternion().unwrap();
1993 assert!((quat[3] - 1.0).abs() < 0.001);
1994 assert!((driver.geomag_rotation_acc() - 1.0).abs() < 0.01);
1995 }
1996
1997 #[test]
1998 fn test_update_linear_accel() {
1999 let mock = MockSensorInterface::new();
2000 let mut driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
2001
2002 driver.update_linear_accel(128, 256, 512);
2004
2005 let accel = driver.linear_accel().unwrap();
2006 assert!((accel[0] - 0.5).abs() < 0.01);
2007 assert!((accel[1] - 1.0).abs() < 0.01);
2008 assert!((accel[2] - 2.0).abs() < 0.01);
2009 }
2010
2011 #[test]
2012 fn test_update_gravity() {
2013 let mock = MockSensorInterface::new();
2014 let mut driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
2015
2016 driver.update_gravity(0, 0, 2509);
2018
2019 let gravity = driver.gravity().unwrap();
2020 assert!(gravity[0].abs() < 0.01);
2021 assert!(gravity[1].abs() < 0.01);
2022 assert!((gravity[2] - 9.8).abs() < 0.1);
2023 }
2024
2025 #[test]
2026 fn test_update_gyro_calib() {
2027 let mock = MockSensorInterface::new();
2028 let mut driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
2029
2030 driver.update_gyro_calib(512, -512, 256);
2032
2033 let gyro = driver.gyro().unwrap();
2034 assert!((gyro[0] - 1.0).abs() < 0.01);
2035 assert!((gyro[1] + 1.0).abs() < 0.01);
2036 assert!((gyro[2] - 0.5).abs() < 0.01);
2037 }
2038
2039 #[test]
2040 fn test_update_gyro_uncalib() {
2041 let mock = MockSensorInterface::new();
2042 let mut driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
2043
2044 driver.update_gyro_uncalib(256, 512, 768);
2046
2047 let gyro = driver.gyro_uncalib().unwrap();
2048 assert!((gyro[0] - 0.5).abs() < 0.01);
2049 assert!((gyro[1] - 1.0).abs() < 0.01);
2050 assert!((gyro[2] - 1.5).abs() < 0.01);
2051 }
2052
2053 #[test]
2054 fn test_update_magnetic_field_calib() {
2055 let mock = MockSensorInterface::new();
2056 let mut driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
2057
2058 driver.update_magnetic_field_calib(160, 320, 480);
2060
2061 let mag = driver.mag_field().unwrap();
2062 assert!((mag[0] - 10.0).abs() < 0.1);
2063 assert!((mag[1] - 20.0).abs() < 0.1);
2064 assert!((mag[2] - 30.0).abs() < 0.1);
2065 }
2066
2067 #[test]
2072 fn test_handle_received_packet_too_short() {
2073 let mock = MockSensorInterface::new();
2074 let mut driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
2075
2076 let result = driver.handle_received_packet(2);
2078 assert!(result.is_err());
2079 }
2080
2081 #[test]
2082 fn test_handle_received_packet_clamped_to_buffer_size() {
2083 let mock = MockSensorInterface::new();
2084 let mut driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
2085
2086 driver.packet_recv_buf[0] = 8;
2089 driver.packet_recv_buf[1] = 0;
2090 driver.packet_recv_buf[2] = CHANNEL_HUB_CONTROL;
2091 driver.packet_recv_buf[3] = 0;
2092 driver.packet_recv_buf[4] = SHUB_PROD_ID_RESP;
2093 driver.packet_recv_buf[5] = 0;
2094 driver.packet_recv_buf[6] = 1;
2095 driver.packet_recv_buf[7] = 0;
2096
2097 let result = driver.handle_received_packet(PACKET_RECV_BUF_LEN + 100);
2100 assert!(result.is_ok());
2102 }
2103
2104 #[test]
2105 fn test_handle_received_packet_executable_channel_reset() {
2106 let mock = MockSensorInterface::new();
2107 let mut driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
2108
2109 driver.packet_recv_buf[0] = 5; driver.packet_recv_buf[1] = 0; driver.packet_recv_buf[2] = CHANNEL_EXECUTABLE; driver.packet_recv_buf[3] = 0; driver.packet_recv_buf[4] = EXECUTABLE_DEVICE_RESP_RESET_COMPLETE;
2116
2117 assert!(!driver.device_reset);
2118 let result = driver.handle_received_packet(5);
2119 assert!(result.is_ok());
2120 assert!(driver.device_reset);
2121 }
2122
2123 #[test]
2124 fn test_handle_received_packet_unknown_executable_report() {
2125 let mock = MockSensorInterface::new();
2126 let mut driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
2127
2128 driver.packet_recv_buf[0] = 5;
2129 driver.packet_recv_buf[1] = 0;
2130 driver.packet_recv_buf[2] = CHANNEL_EXECUTABLE;
2131 driver.packet_recv_buf[3] = 0;
2132 driver.packet_recv_buf[4] = 0xFF; let result = driver.handle_received_packet(5);
2135 assert!(result.is_err());
2136 assert_eq!(driver.last_exec_chan_rid, 0xFF);
2137 }
2138
2139 #[test]
2140 fn test_handle_received_packet_unknown_channel() {
2141 let mock = MockSensorInterface::new();
2142 let mut driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
2143
2144 driver.packet_recv_buf[0] = 5;
2145 driver.packet_recv_buf[1] = 0;
2146 driver.packet_recv_buf[2] = 0xFE; driver.packet_recv_buf[3] = 0;
2148 driver.packet_recv_buf[4] = 0x01;
2149
2150 let result = driver.handle_received_packet(5);
2151 assert!(result.is_err());
2152 assert_eq!(driver.last_chan_received, 0xFE);
2153 }
2154
2155 #[test]
2156 fn test_handle_received_packet_hub_control_init() {
2157 let mock = MockSensorInterface::new();
2158 let mut driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
2159
2160 driver.packet_recv_buf[0] = 8;
2162 driver.packet_recv_buf[1] = 0;
2163 driver.packet_recv_buf[2] = CHANNEL_HUB_CONTROL;
2164 driver.packet_recv_buf[3] = 0;
2165 driver.packet_recv_buf[4] = SHUB_COMMAND_RESP;
2166 driver.packet_recv_buf[5] = 0;
2167 driver.packet_recv_buf[6] = SH2_INIT_SYSTEM;
2168
2169 assert!(!driver.init_received);
2170 let result = driver.handle_received_packet(8);
2171 assert!(result.is_ok());
2172 assert!(driver.init_received);
2173 }
2174
2175 #[test]
2176 fn test_handle_received_packet_hub_control_prod_id() {
2177 let mock = MockSensorInterface::new();
2178 let mut driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
2179
2180 driver.packet_recv_buf[0] = 10;
2182 driver.packet_recv_buf[1] = 0;
2183 driver.packet_recv_buf[2] = CHANNEL_HUB_CONTROL;
2184 driver.packet_recv_buf[3] = 0;
2185 driver.packet_recv_buf[4] = SHUB_PROD_ID_RESP;
2186 driver.packet_recv_buf[5] = 0; driver.packet_recv_buf[6] = 3; driver.packet_recv_buf[7] = 5; assert!(!driver.prod_id_verified);
2191 let result = driver.handle_received_packet(10);
2192 assert!(result.is_ok());
2193 assert!(driver.prod_id_verified);
2194 }
2195
2196 #[test]
2197 fn test_handle_received_packet_hub_control_feature_resp() {
2198 let mock = MockSensorInterface::new();
2199 let mut driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
2200
2201 driver.packet_recv_buf[0] = 8;
2203 driver.packet_recv_buf[1] = 0;
2204 driver.packet_recv_buf[2] = CHANNEL_HUB_CONTROL;
2205 driver.packet_recv_buf[3] = 0;
2206 driver.packet_recv_buf[4] = SHUB_GET_FEATURE_RESP;
2207 driver.packet_recv_buf[5] = SENSOR_REPORTID_ACCELEROMETER;
2208
2209 assert!(!driver.report_enabled[SENSOR_REPORTID_ACCELEROMETER as usize]);
2210 let result = driver.handle_received_packet(8);
2211 assert!(result.is_ok());
2212 assert!(driver.report_enabled[SENSOR_REPORTID_ACCELEROMETER as usize]);
2213 }
2214
2215 #[test]
2216 fn test_handle_received_packet_hub_control_frs_write_resp() {
2217 let mock = MockSensorInterface::new();
2218 let mut driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
2219
2220 driver.packet_recv_buf[0] = 8;
2221 driver.packet_recv_buf[1] = 0;
2222 driver.packet_recv_buf[2] = CHANNEL_HUB_CONTROL;
2223 driver.packet_recv_buf[3] = 0;
2224 driver.packet_recv_buf[4] = SHUB_FRS_WRITE_RESP;
2225 driver.packet_recv_buf[5] = FRS_STATUS_WRITE_READY;
2226
2227 let result = driver.handle_received_packet(8);
2228 assert!(result.is_ok());
2229 assert_eq!(driver.frs_write_status, FRS_STATUS_WRITE_READY);
2230 }
2231
2232 #[test]
2233 fn test_handle_received_packet_hub_control_unknown() {
2234 let mock = MockSensorInterface::new();
2235 let mut driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
2236
2237 driver.packet_recv_buf[0] = 8;
2238 driver.packet_recv_buf[1] = 0;
2239 driver.packet_recv_buf[2] = CHANNEL_HUB_CONTROL;
2240 driver.packet_recv_buf[3] = 0;
2241 driver.packet_recv_buf[4] = 0xFE; let result = driver.handle_received_packet(8);
2244 assert!(result.is_err());
2245 }
2246
2247 #[test]
2248 fn test_handle_received_packet_command_channel_unknown() {
2249 let mock = MockSensorInterface::new();
2250 let mut driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
2251
2252 driver.packet_recv_buf[0] = 8;
2253 driver.packet_recv_buf[1] = 0;
2254 driver.packet_recv_buf[2] = CHANNEL_COMMAND;
2255 driver.packet_recv_buf[3] = 0;
2256 driver.packet_recv_buf[4] = 0xFE; let result = driver.handle_received_packet(8);
2259 assert!(result.is_err());
2260 assert_eq!(driver.last_command_chan_rid, 0xFE);
2261 }
2262
2263 #[test]
2268 fn test_handle_cmd_resp_error_list_empty() {
2269 let mock = MockSensorInterface::new();
2270 let mut driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
2271
2272 driver.packet_recv_buf[0] = 6;
2273 driver.packet_recv_buf[1] = 0;
2274 driver.packet_recv_buf[2] = CHANNEL_COMMAND;
2275 driver.packet_recv_buf[3] = 0;
2276 driver.packet_recv_buf[4] = CMD_RESP_ERROR_LIST;
2277 driver.packet_recv_buf[5] = 0; let result = driver.handle_received_packet(6);
2280 assert!(result.is_ok());
2281 assert!(driver.error_list_received);
2282 }
2283
2284 #[test]
2285 fn test_handle_cmd_resp_error_list_various_errors() {
2286 let mock = MockSensorInterface::new();
2287 let mut driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
2288
2289 driver.packet_recv_buf[0] = 18;
2291 driver.packet_recv_buf[1] = 0;
2292 driver.packet_recv_buf[2] = CHANNEL_COMMAND;
2293 driver.packet_recv_buf[3] = 0;
2294 driver.packet_recv_buf[4] = CMD_RESP_ERROR_LIST;
2295 for i in 0..13 {
2297 driver.packet_recv_buf[5 + i] = i as u8;
2298 }
2299 driver.packet_recv_buf[18] = 0xFF; let result = driver.handle_received_packet(18);
2302 assert!(result.is_ok());
2303 assert!(driver.error_list_received);
2304 }
2305
2306 #[test]
2311 fn test_handle_sensor_reports_accelerometer() {
2312 let mock = MockSensorInterface::new();
2313 let mut driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
2314
2315 driver.packet_recv_buf[0] = 19; driver.packet_recv_buf[1] = 0;
2319 driver.packet_recv_buf[2] = CHANNEL_SENSOR_REPORTS;
2320 driver.packet_recv_buf[3] = 0;
2321 driver.packet_recv_buf[4] = 0xFB; driver.packet_recv_buf[5] = 0;
2324 driver.packet_recv_buf[6] = 0;
2325 driver.packet_recv_buf[7] = 0;
2326 driver.packet_recv_buf[8] = 0;
2327 driver.packet_recv_buf[9] = SENSOR_REPORTID_ACCELEROMETER;
2329 driver.packet_recv_buf[10] = 0; driver.packet_recv_buf[11] = 0; driver.packet_recv_buf[12] = 0; driver.packet_recv_buf[13] = 0x00;
2334 driver.packet_recv_buf[14] = 0x01;
2335 driver.packet_recv_buf[15] = 0x00;
2337 driver.packet_recv_buf[16] = 0x02;
2338 driver.packet_recv_buf[17] = 0x00;
2340 driver.packet_recv_buf[18] = 0xFF;
2341
2342 let result = driver.handle_received_packet(19);
2343 assert!(result.is_ok());
2344
2345 let accel = driver.accelerometer().unwrap();
2346 assert!((accel[0] - 1.0).abs() < 0.1);
2347 assert!((accel[1] - 2.0).abs() < 0.1);
2348 }
2349
2350 #[test]
2351 fn test_handle_sensor_reports_rotation_vector() {
2352 let mock = MockSensorInterface::new();
2353 let mut driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
2354
2355 driver.packet_recv_buf[0] = 23; driver.packet_recv_buf[1] = 0;
2358 driver.packet_recv_buf[2] = CHANNEL_SENSOR_REPORTS;
2359 driver.packet_recv_buf[3] = 0;
2360 driver.packet_recv_buf[4] = 0xFB;
2362 driver.packet_recv_buf[5..9].copy_from_slice(&[0, 0, 0, 0]);
2363 driver.packet_recv_buf[9] = SENSOR_REPORTID_ROTATION_VECTOR;
2365 driver.packet_recv_buf[10] = 0;
2366 driver.packet_recv_buf[11] = 0;
2367 driver.packet_recv_buf[12] = 0;
2368 driver.packet_recv_buf[13..15].copy_from_slice(&0i16.to_le_bytes()); driver.packet_recv_buf[15..17].copy_from_slice(&0i16.to_le_bytes()); driver.packet_recv_buf[17..19].copy_from_slice(&0i16.to_le_bytes()); driver.packet_recv_buf[19..21].copy_from_slice(&16384i16.to_le_bytes()); driver.packet_recv_buf[21..23].copy_from_slice(&0i16.to_le_bytes()); let result = driver.handle_received_packet(23);
2377 assert!(result.is_ok());
2378
2379 let quat = driver.rotation_quaternion().unwrap();
2380 assert!((quat[3] - 1.0).abs() < 0.01);
2381 }
2382
2383 #[test]
2384 fn test_handle_sensor_reports_game_rotation() {
2385 let mock = MockSensorInterface::new();
2386 let mut driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
2387
2388 driver.packet_recv_buf[0] = 21;
2389 driver.packet_recv_buf[1] = 0;
2390 driver.packet_recv_buf[2] = CHANNEL_SENSOR_REPORTS;
2391 driver.packet_recv_buf[3] = 0;
2392 driver.packet_recv_buf[4] = 0xFB;
2393 driver.packet_recv_buf[5..9].copy_from_slice(&[0, 0, 0, 0]);
2394 driver.packet_recv_buf[9] = SENSOR_REPORTID_ROTATION_VECTOR_GAME;
2395 driver.packet_recv_buf[10..13].copy_from_slice(&[0, 0, 0]);
2396 driver.packet_recv_buf[13..15].copy_from_slice(&0i16.to_le_bytes());
2398 driver.packet_recv_buf[15..17].copy_from_slice(&0i16.to_le_bytes());
2399 driver.packet_recv_buf[17..19].copy_from_slice(&6270i16.to_le_bytes()); driver.packet_recv_buf[19..21].copy_from_slice(&15137i16.to_le_bytes()); let result = driver.handle_received_packet(21);
2403 assert!(result.is_ok());
2404 }
2405
2406 #[test]
2407 fn test_handle_sensor_reports_geomag_rotation() {
2408 let mock = MockSensorInterface::new();
2409 let mut driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
2410
2411 driver.packet_recv_buf[0] = 23;
2412 driver.packet_recv_buf[1] = 0;
2413 driver.packet_recv_buf[2] = CHANNEL_SENSOR_REPORTS;
2414 driver.packet_recv_buf[3] = 0;
2415 driver.packet_recv_buf[4] = 0xFB;
2416 driver.packet_recv_buf[5..9].copy_from_slice(&[0, 0, 0, 0]);
2417 driver.packet_recv_buf[9] = SENSOR_REPORTID_ROTATION_VECTOR_GEOMAGNETIC;
2418 driver.packet_recv_buf[10..13].copy_from_slice(&[0, 0, 0]);
2419 driver.packet_recv_buf[13..15].copy_from_slice(&0i16.to_le_bytes());
2420 driver.packet_recv_buf[15..17].copy_from_slice(&0i16.to_le_bytes());
2421 driver.packet_recv_buf[17..19].copy_from_slice(&0i16.to_le_bytes());
2422 driver.packet_recv_buf[19..21].copy_from_slice(&16384i16.to_le_bytes());
2423 driver.packet_recv_buf[21..23].copy_from_slice(&4096i16.to_le_bytes()); let result = driver.handle_received_packet(23);
2426 assert!(result.is_ok());
2427 }
2428
2429 #[test]
2430 fn test_handle_sensor_reports_linear_accel() {
2431 let mock = MockSensorInterface::new();
2432 let mut driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
2433
2434 driver.packet_recv_buf[0] = 19;
2435 driver.packet_recv_buf[1] = 0;
2436 driver.packet_recv_buf[2] = CHANNEL_SENSOR_REPORTS;
2437 driver.packet_recv_buf[3] = 0;
2438 driver.packet_recv_buf[4] = 0xFB;
2439 driver.packet_recv_buf[5..9].copy_from_slice(&[0, 0, 0, 0]);
2440 driver.packet_recv_buf[9] = SENSOR_REPORTID_LINEAR_ACCEL;
2441 driver.packet_recv_buf[10..13].copy_from_slice(&[0, 0, 0]);
2442 driver.packet_recv_buf[13..15].copy_from_slice(&256i16.to_le_bytes());
2443 driver.packet_recv_buf[15..17].copy_from_slice(&512i16.to_le_bytes());
2444 driver.packet_recv_buf[17..19].copy_from_slice(&768i16.to_le_bytes());
2445
2446 let result = driver.handle_received_packet(19);
2447 assert!(result.is_ok());
2448
2449 let accel = driver.linear_accel().unwrap();
2450 assert!((accel[0] - 1.0).abs() < 0.1);
2451 assert!((accel[1] - 2.0).abs() < 0.1);
2452 assert!((accel[2] - 3.0).abs() < 0.1);
2453 }
2454
2455 #[test]
2456 fn test_handle_sensor_reports_gravity() {
2457 let mock = MockSensorInterface::new();
2458 let mut driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
2459
2460 driver.packet_recv_buf[0] = 19;
2461 driver.packet_recv_buf[1] = 0;
2462 driver.packet_recv_buf[2] = CHANNEL_SENSOR_REPORTS;
2463 driver.packet_recv_buf[3] = 0;
2464 driver.packet_recv_buf[4] = 0xFB;
2465 driver.packet_recv_buf[5..9].copy_from_slice(&[0, 0, 0, 0]);
2466 driver.packet_recv_buf[9] = SENSOR_REPORTID_GRAVITY;
2467 driver.packet_recv_buf[10..13].copy_from_slice(&[0, 0, 0]);
2468 driver.packet_recv_buf[13..15].copy_from_slice(&0i16.to_le_bytes());
2469 driver.packet_recv_buf[15..17].copy_from_slice(&0i16.to_le_bytes());
2470 driver.packet_recv_buf[17..19].copy_from_slice(&2509i16.to_le_bytes()); let result = driver.handle_received_packet(19);
2473 assert!(result.is_ok());
2474
2475 let gravity = driver.gravity().unwrap();
2476 assert!((gravity[2] - 9.8).abs() < 0.1);
2477 }
2478
2479 #[test]
2480 fn test_handle_sensor_reports_gyro() {
2481 let mock = MockSensorInterface::new();
2482 let mut driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
2483
2484 driver.packet_recv_buf[0] = 19;
2485 driver.packet_recv_buf[1] = 0;
2486 driver.packet_recv_buf[2] = CHANNEL_SENSOR_REPORTS;
2487 driver.packet_recv_buf[3] = 0;
2488 driver.packet_recv_buf[4] = 0xFB;
2489 driver.packet_recv_buf[5..9].copy_from_slice(&[0, 0, 0, 0]);
2490 driver.packet_recv_buf[9] = SENSOR_REPORTID_GYROSCOPE;
2491 driver.packet_recv_buf[10..13].copy_from_slice(&[0, 0, 0]);
2492 driver.packet_recv_buf[13..15].copy_from_slice(&512i16.to_le_bytes());
2494 driver.packet_recv_buf[15..17].copy_from_slice(&(-512i16).to_le_bytes());
2495 driver.packet_recv_buf[17..19].copy_from_slice(&256i16.to_le_bytes());
2496
2497 let result = driver.handle_received_packet(19);
2498 assert!(result.is_ok());
2499
2500 let gyro = driver.gyro().unwrap();
2501 assert!((gyro[0] - 1.0).abs() < 0.1);
2502 assert!((gyro[1] + 1.0).abs() < 0.1);
2503 assert!((gyro[2] - 0.5).abs() < 0.1);
2504 }
2505
2506 #[test]
2507 fn test_handle_sensor_reports_gyro_uncalib() {
2508 let mock = MockSensorInterface::new();
2509 let mut driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
2510
2511 driver.packet_recv_buf[0] = 19;
2512 driver.packet_recv_buf[1] = 0;
2513 driver.packet_recv_buf[2] = CHANNEL_SENSOR_REPORTS;
2514 driver.packet_recv_buf[3] = 0;
2515 driver.packet_recv_buf[4] = 0xFB;
2516 driver.packet_recv_buf[5..9].copy_from_slice(&[0, 0, 0, 0]);
2517 driver.packet_recv_buf[9] = SENSOR_REPORTID_GYROSCOPE_UNCALIB;
2518 driver.packet_recv_buf[10..13].copy_from_slice(&[0, 0, 0]);
2519 driver.packet_recv_buf[13..15].copy_from_slice(&256i16.to_le_bytes());
2520 driver.packet_recv_buf[15..17].copy_from_slice(&512i16.to_le_bytes());
2521 driver.packet_recv_buf[17..19].copy_from_slice(&768i16.to_le_bytes());
2522
2523 let result = driver.handle_received_packet(19);
2524 assert!(result.is_ok());
2525 }
2526
2527 #[test]
2528 fn test_handle_sensor_reports_magnetometer() {
2529 let mock = MockSensorInterface::new();
2530 let mut driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
2531
2532 driver.packet_recv_buf[0] = 19;
2533 driver.packet_recv_buf[1] = 0;
2534 driver.packet_recv_buf[2] = CHANNEL_SENSOR_REPORTS;
2535 driver.packet_recv_buf[3] = 0;
2536 driver.packet_recv_buf[4] = 0xFB;
2537 driver.packet_recv_buf[5..9].copy_from_slice(&[0, 0, 0, 0]);
2538 driver.packet_recv_buf[9] = SENSOR_REPORTID_MAGNETIC_FIELD;
2539 driver.packet_recv_buf[10..13].copy_from_slice(&[0, 0, 0]);
2540 driver.packet_recv_buf[13..15].copy_from_slice(&160i16.to_le_bytes()); driver.packet_recv_buf[15..17].copy_from_slice(&320i16.to_le_bytes()); driver.packet_recv_buf[17..19].copy_from_slice(&480i16.to_le_bytes()); let result = driver.handle_received_packet(19);
2546 assert!(result.is_ok());
2547
2548 let mag = driver.mag_field().unwrap();
2549 assert!((mag[0] - 10.0).abs() < 0.5);
2550 assert!((mag[1] - 20.0).abs() < 0.5);
2551 assert!((mag[2] - 30.0).abs() < 0.5);
2552 }
2553
2554 #[test]
2555 fn test_handle_sensor_reports_unknown_report_id() {
2556 let mock = MockSensorInterface::new();
2557 let mut driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
2558
2559 driver.packet_recv_buf[0] = 19;
2560 driver.packet_recv_buf[1] = 0;
2561 driver.packet_recv_buf[2] = CHANNEL_SENSOR_REPORTS;
2562 driver.packet_recv_buf[3] = 0;
2563 driver.packet_recv_buf[4] = 0xFB;
2564 driver.packet_recv_buf[5..9].copy_from_slice(&[0, 0, 0, 0]);
2565 driver.packet_recv_buf[9] = 0xFE; driver.packet_recv_buf[10..19].copy_from_slice(&[0; 9]);
2567
2568 let result = driver.handle_received_packet(19);
2570 assert!(result.is_ok());
2571 }
2572
2573 #[test]
2578 fn test_handle_advertise_response() {
2579 let mock = MockSensorInterface::new();
2580 let mut driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
2581
2582 driver.packet_recv_buf[0] = 10;
2584 driver.packet_recv_buf[1] = 0;
2585 driver.packet_recv_buf[2] = CHANNEL_COMMAND;
2586 driver.packet_recv_buf[3] = 0;
2587 driver.packet_recv_buf[4] = CMD_RESP_ADVERTISEMENT;
2588 driver.packet_recv_buf[5] = 0x00;
2590 driver.packet_recv_buf[6] = 0xFF; assert!(!driver.advert_received);
2593 let result = driver.handle_received_packet(10);
2594 assert!(result.is_ok());
2595 assert!(driver.advert_received);
2596 }
2597
2598 #[test]
2603 fn test_add_sensor_report_callback() {
2604 let mock = MockSensorInterface::new();
2605 let mut driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
2606
2607 let called = std::rc::Rc::new(std::cell::Cell::new(false));
2608 let called_clone = called.clone();
2609
2610 driver.add_sensor_report_callback(
2611 SENSOR_REPORTID_ACCELEROMETER,
2612 "test".to_string(),
2613 move |_driver| {
2614 called_clone.set(true);
2615 },
2616 );
2617
2618 assert!(!driver.report_update_callbacks[SENSOR_REPORTID_ACCELEROMETER as usize].is_empty());
2620 }
2621
2622 #[test]
2623 fn test_remove_sensor_report_callback() {
2624 let mock = MockSensorInterface::new();
2625 let mut driver: BNO08x<MockSensorInterface> = BNO08x::new_with_interface(mock);
2626
2627 driver.add_sensor_report_callback(
2628 SENSOR_REPORTID_ACCELEROMETER,
2629 "test".to_string(),
2630 |_| {},
2631 );
2632
2633 assert!(!driver.report_update_callbacks[SENSOR_REPORTID_ACCELEROMETER as usize].is_empty());
2634
2635 driver.remove_sensor_report_callback(SENSOR_REPORTID_ACCELEROMETER, "test".to_string());
2636
2637 assert!(driver.report_update_callbacks[SENSOR_REPORTID_ACCELEROMETER as usize].is_empty());
2638 }
2639}