Skip to content

Commit 23d2a68

Browse files
committed
Make transfer outgoing blocks consistent with common SPI practice
Merge branch 'multi_bus_interface' of https://github.com/tstellanova/bno080 into multi_bus_interface Signed-off-by: Todd Stellanova <tstellanova@users.noreply.github.com>
2 parents 61b6b9a + 432b6ff commit 23d2a68

File tree

6 files changed

+625
-1040
lines changed

6 files changed

+625
-1040
lines changed

src/interface/i2c.rs

Lines changed: 104 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11

2-
// use embedded_hal::{
3-
// blocking::delay::{DelayUs, DelayMs},
4-
// };
5-
6-
use super::{SensorInterface, PACKET_HEADER_LENGTH};
2+
use super::{SensorInterface, SensorCommon, PACKET_HEADER_LENGTH};
3+
use crate::Error;
4+
use embedded_hal::blocking::delay::DelayMs;
75

86
/// the i2c address normally used by BNO080
97
pub const DEFAULT_ADDRESS: u8 = 0x4A;
@@ -24,6 +22,9 @@ pub struct I2cInterface<I2C> {
2422
address: u8,
2523
/// buffer for receiving segments of packets from the sensor hub
2624
seg_recv_buf: [u8; SEG_RECV_BUF_LEN],
25+
26+
/// number of packets received
27+
received_packet_count: usize,
2728
}
2829

2930
impl<I2C, CommE> I2cInterface<I2C>
@@ -36,42 +37,22 @@ impl<I2C, CommE> I2cInterface<I2C>
3637
i2c_port: i2c,
3738
address: addr,
3839
seg_recv_buf: [0; SEG_RECV_BUF_LEN],
40+
received_packet_count: 0,
3941
}
4042
}
41-
}
42-
43-
44-
#[derive(Debug)]
45-
pub enum I2cCommError<E> {
46-
/// I2C bus error
47-
I2c(E),
48-
}
49-
50-
impl<I2C, CommE> SensorInterface for I2cInterface<I2C>
51-
where
52-
I2C: embedded_hal::blocking::i2c::Write<Error = CommE> +
53-
embedded_hal::blocking::i2c::Read<Error = CommE>
54-
{
55-
type SensorError = I2cCommError<CommE>;
5643

57-
fn send_packet(&mut self, packet: &[u8]) -> Result<(), Self::SensorError> {
58-
self.i2c_port.write(self.address,
59-
&packet).map_err(Self::SensorError::I2c)?;
60-
Ok(())
61-
}
62-
63-
fn read_packet_header(&mut self, recv_buf: &mut [u8]) -> Result<(), Self::SensorError> {
64-
recv_buf[0] = 0;
65-
recv_buf[1] = 0;
66-
self.i2c_port.read(self.address, &mut recv_buf[..PACKET_HEADER_LENGTH]).map_err(Self::SensorError::I2c)?;
44+
fn read_packet_header(&mut self) -> Result<(), Error<CommE, ()>> {
45+
self.seg_recv_buf[0] = 0;
46+
self.seg_recv_buf[1] = 0;
47+
self.i2c_port.read(self.address, &mut self.seg_recv_buf[..PACKET_HEADER_LENGTH]).map_err(Error::Comm)?;
6748
Ok(())
6849
}
6950

7051
/// Read the remainder of the packet after the packet header, if any
7152
fn read_sized_packet(&mut self,
7253
total_packet_len: usize,
7354
packet_recv_buf: &mut [u8]
74-
) -> Result<usize, Self::SensorError> {
55+
) -> Result<usize, Error<CommE, ()>> {
7556
//iprintln!("sized: {}", total_packet_len).unwrap();
7657
let mut remaining_body_len: usize = total_packet_len - PACKET_HEADER_LENGTH;
7758
let mut already_read_len: usize = 0;
@@ -83,7 +64,7 @@ impl<I2C, CommE> SensorInterface for I2cInterface<I2C>
8364
if total_packet_len > 0 {
8465
self.i2c_port
8566
.read(self.address, &mut packet_recv_buf[..total_packet_len])
86-
.map_err(Self::SensorError::I2c)?;
67+
.map_err(Error::Comm)?;
8768
//let packet_declared_len = Self::parse_packet_header(&self.packet_recv_buf[..PACKET_HEADER_LENGTH]);
8869
already_read_len = total_packet_len;
8970
}
@@ -97,7 +78,7 @@ impl<I2C, CommE> SensorInterface for I2cInterface<I2C>
9778

9879
self.seg_recv_buf[0] = 0;
9980
self.seg_recv_buf[1] = 0;
100-
self.i2c_port.read(self.address, &mut self.seg_recv_buf[..segment_read_len]).map_err(Self::SensorError::I2c)?;
81+
self.i2c_port.read(self.address, &mut self.seg_recv_buf[..segment_read_len]).map_err(Error::Comm)?;
10182
//let packet_declared_len = Self::parse_packet_header(&self.seg_recv_buf[..PACKET_HEADER_LENGTH]);
10283

10384
//if we've never read any segments, transcribe the first packet header;
@@ -116,6 +97,96 @@ impl<I2C, CommE> SensorInterface for I2cInterface<I2C>
11697

11798
Ok(already_read_len)
11899
}
100+
}
101+
102+
103+
impl<I2C, CommE> SensorInterface for I2cInterface<I2C>
104+
where
105+
I2C: embedded_hal::blocking::i2c::Write<Error = CommE> +
106+
embedded_hal::blocking::i2c::Read<Error = CommE>
107+
{
108+
type SensorError = Error<CommE, ()>;
109+
110+
fn setup(&mut self, _delay_source: &mut impl DelayMs<u8>) -> Result<(), Self::SensorError> {
111+
Ok(())
112+
}
113+
114+
fn wait_for_data_available(&mut self, _max_ms: u8, _delay_source: &mut impl DelayMs<u8>) -> bool {
115+
let rc = self.read_packet_header();
116+
if rc.is_err() {
117+
return false;
118+
}
119+
let packet_len = SensorCommon::parse_packet_header(&self.seg_recv_buf[..PACKET_HEADER_LENGTH]);
120+
packet_len > 0
121+
}
122+
123+
fn send_packet(&mut self, packet: &[u8]) -> Result<(), Self::SensorError> {
124+
self.i2c_port.write(self.address,
125+
&packet).map_err(Error::Comm)?;
126+
Ok(())
127+
}
128+
129+
/// Read one packet into the receive buffer
130+
fn read_packet(&mut self, recv_buf: &mut [u8]) -> Result<usize, Self::SensorError> {
131+
self.read_packet_header()?;
132+
let packet_len = SensorCommon::parse_packet_header(&self.seg_recv_buf[..PACKET_HEADER_LENGTH]);
133+
134+
let received_len =
135+
if packet_len > PACKET_HEADER_LENGTH {
136+
self.read_sized_packet(packet_len, recv_buf)?
137+
}
138+
else {
139+
packet_len
140+
};
141+
142+
if packet_len > 0 {
143+
self.received_packet_count += 1;
144+
}
145+
146+
Ok(received_len)
147+
}
148+
149+
150+
151+
}
152+
153+
#[cfg(test)]
154+
mod tests {
155+
use crate::interface::mock_i2c_port::FakeI2cPort;
156+
use crate::interface::I2cInterface;
157+
use crate::interface::i2c::DEFAULT_ADDRESS;
158+
use crate::wrapper::BNO080;
159+
160+
#[test]
161+
fn test_multi_segment_receive_packet() {
162+
let mut mock_i2c_port = FakeI2cPort::new();
163+
164+
let packet = ADVERTISING_PACKET_FULL;
165+
mock_i2c_port.add_available_packet(&packet);
166+
167+
let mut shub = BNO080::new_with_interface(
168+
I2cInterface::new(mock_i2c_port, DEFAULT_ADDRESS));
169+
let rc = shub.receive_packet();
170+
171+
assert!(rc.is_ok());
172+
let next_packet_size = rc.unwrap_or(0);
173+
assert_eq!(next_packet_size, packet.len(), "wrong length");
174+
}
175+
119176

177+
// Actual advertising packet received from sensor:
178+
pub const ADVERTISING_PACKET_FULL: [u8; 276] = [
179+
0x14, 0x81, 0x00, 0x01,
180+
0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x80, 0x06, 0x31, 0x2e, 0x30, 0x2e, 0x30, 0x00, 0x02, 0x02, 0x00, 0x01, 0x03, 0x02, 0xff, 0x7f, 0x04, 0x02, 0x00, 0x01, 0x05,
181+
0x02, 0xff, 0x7f, 0x08, 0x05, 0x53, 0x48, 0x54, 0x50, 0x00, 0x06, 0x01, 0x00, 0x09, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x00, 0x01, 0x04, 0x01, 0x00, 0x00,
182+
0x00, 0x08, 0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x06, 0x01, 0x01, 0x09, 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x00, 0x01, 0x04,
183+
0x02, 0x00, 0x00, 0x00, 0x08, 0x0a, 0x73, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x68, 0x75, 0x62, 0x00, 0x06, 0x01, 0x02, 0x09, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
184+
0x00, 0x06, 0x01, 0x03, 0x09, 0x0c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x4e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x00, 0x07, 0x01, 0x04, 0x09, 0x0a, 0x69, 0x6e, 0x70, 0x75, 0x74,
185+
0x57, 0x61, 0x6b, 0x65, 0x00, 0x06, 0x01, 0x05, 0x09, 0x0c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x47, 0x79, 0x72, 0x6f, 0x52, 0x76, 0x00, 0x80, 0x06, 0x31, 0x2e, 0x31, 0x2e,
186+
0x30, 0x00, 0x81, 0x64, 0xf8, 0x10, 0xf5, 0x04, 0xf3, 0x10, 0xf1, 0x10, 0xfb, 0x05, 0xfa, 0x05, 0xfc, 0x11, 0xef, 0x02, 0x01, 0x0a, 0x02, 0x0a, 0x03, 0x0a, 0x04, 0x0a,
187+
0x05, 0x0e, 0x06, 0x0a, 0x07, 0x10, 0x08, 0x0c, 0x09, 0x0e, 0x0a, 0x08, 0x0b, 0x08, 0x0c, 0x06, 0x0d, 0x06, 0x0e, 0x06, 0x0f, 0x10, 0x10, 0x05, 0x11, 0x0c, 0x12, 0x06,
188+
0x13, 0x06, 0x14, 0x10, 0x15, 0x10, 0x16, 0x10, 0x17, 0x00, 0x18, 0x08, 0x19, 0x06, 0x1a, 0x00, 0x1b, 0x00, 0x1c, 0x06, 0x1d, 0x00, 0x1e, 0x10, 0x1f, 0x00, 0x20, 0x00,
189+
0x21, 0x00, 0x22, 0x00, 0x23, 0x00, 0x24, 0x00, 0x25, 0x00, 0x26, 0x00, 0x27, 0x00, 0x28, 0x0e, 0x29, 0x0c, 0x2a, 0x0e
190+
];
120191
}
121192

src/interface/mock_i2c_port.rs

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
2+
3+
extern crate std;
4+
5+
6+
use super::PACKET_HEADER_LENGTH;
7+
8+
use embedded_hal::blocking::{
9+
delay::DelayMs,
10+
i2c::{Read, WriteRead, Write}
11+
};
12+
use core::ops::Shr;
13+
use std::collections::VecDeque;
14+
15+
struct FakeDelay {}
16+
17+
impl DelayMs<u8> for FakeDelay {
18+
fn delay_ms(&mut self, _ms: u8) {
19+
// no-op
20+
}
21+
}
22+
23+
const MAX_FAKE_PACKET_SIZE: usize = 512;
24+
25+
//divides up packets into segments
26+
pub struct FakePacket {
27+
pub addr: u8,
28+
pub len: usize,
29+
pub buf: [u8; MAX_FAKE_PACKET_SIZE],
30+
}
31+
32+
impl FakePacket {
33+
pub fn new_from_slice(slice: &[u8]) -> Self {
34+
let src_len = slice.len();
35+
let mut inst = Self {
36+
addr: 0,
37+
len: src_len,
38+
buf: [0; MAX_FAKE_PACKET_SIZE],
39+
};
40+
inst.buf[..src_len].copy_from_slice(&slice);
41+
inst
42+
}
43+
}
44+
45+
pub struct FakeI2cPort {
46+
pub available_packets: VecDeque<FakePacket>,
47+
pub sent_packets: VecDeque<FakePacket>,
48+
}
49+
50+
impl FakeI2cPort {
51+
pub fn new() -> Self {
52+
FakeI2cPort {
53+
available_packets: VecDeque::with_capacity(3),
54+
sent_packets: VecDeque::with_capacity(3),
55+
}
56+
}
57+
58+
/// Enqueue a packet to be received later
59+
pub fn add_available_packet(&mut self, bytes: &[u8]) {
60+
let pack = FakePacket::new_from_slice(bytes);
61+
self.available_packets.push_back(pack);
62+
}
63+
64+
}
65+
66+
impl Read for FakeI2cPort {
67+
type Error = ();
68+
69+
fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
70+
let next_pack = self.available_packets.pop_front().unwrap_or(
71+
FakePacket {
72+
addr: addr,
73+
len: 0,
74+
buf: [0; MAX_FAKE_PACKET_SIZE],
75+
}
76+
);
77+
78+
let src_len = next_pack.len;
79+
if src_len == 0 {
80+
return Ok(())
81+
}
82+
83+
let dest_len = buffer.len();
84+
85+
if src_len > dest_len {
86+
//only read as much as the reader has room for,
87+
//then push the remainder back onto the queue as a remainder packet
88+
let read_len = dest_len;
89+
buffer[..read_len].copy_from_slice(&next_pack.buf[..read_len]);
90+
let remainder_len = src_len - read_len;
91+
let mut remainder_packet = FakePacket {
92+
addr: addr,
93+
len: remainder_len + 4,
94+
buf: [0; MAX_FAKE_PACKET_SIZE],
95+
};
96+
remainder_packet.buf[PACKET_HEADER_LENGTH..PACKET_HEADER_LENGTH+remainder_len]
97+
.copy_from_slice(&next_pack.buf[read_len..read_len+remainder_len]);
98+
remainder_packet.buf[0] = ((remainder_len+4) & 0xFF) as u8;
99+
remainder_packet.buf[1] = ((((remainder_len+4) & 0xFF00) as u16).shr(8) as u8) | 0x80; //set continuation flag
100+
self.available_packets.push_front(remainder_packet);
101+
}
102+
else if src_len == dest_len {
103+
let read_len = src_len;
104+
buffer[..read_len].copy_from_slice(&next_pack.buf[..read_len]);
105+
}
106+
else { // src_len < dest_len
107+
panic!("src_len {} dest_len {}", src_len, dest_len);
108+
}
109+
110+
Ok(())
111+
}
112+
}
113+
114+
impl Write for FakeI2cPort {
115+
type Error = ();
116+
117+
fn write(&mut self, _addr: u8, _bytes: &[u8]) -> Result<(), Self::Error> {
118+
let sent_pack = FakePacket::new_from_slice(_bytes);
119+
self.sent_packets.push_back(sent_pack);
120+
Ok(())
121+
}
122+
}
123+
124+
impl WriteRead for FakeI2cPort {
125+
type Error = ();
126+
127+
fn write_read(&mut self, address: u8, send_buf: &[u8], recv_buf: &mut [u8]) -> Result<(), Self::Error> {
128+
self.write(address, send_buf)?;
129+
self.read(address, recv_buf)?;
130+
Ok(())
131+
}
132+
}
133+
134+

0 commit comments

Comments
 (0)