opentitanlib/test_utils/bitbanging/
i2c.rs1use super::Bit;
6use anyhow::{Context, Result, bail};
7use arrayvec::ArrayVec;
8
9#[derive(Debug, PartialEq)]
10enum Symbol {
11 Start,
12 Stop,
13 Byte { data: u8, nack: bool },
14 Broken(ArrayVec<Bit, 8>),
15}
16
17impl Symbol {
18 pub fn broken(data: u8, bits: usize) -> Result<Self> {
19 if !(1..8).contains(&bits) {
20 bail!("Samples must be between 1 and 7");
21 }
22 let buffer: ArrayVec<Bit, 8> = (0..bits).map(|bit| Bit::from(data << bit)).collect();
23
24 Ok(Self::Broken(buffer))
25 }
26
27 pub fn bitbanging<const SDA: u8, const SCL: u8>(&self, samples: &mut Vec<u8>) {
34 match self {
35 Symbol::Start => samples.extend([
38 0x01 << SDA | 0x00 << SCL,
40 0x01 << SDA | 0x01 << SCL,
41 0x00 << SDA | 0x01 << SCL,
43 0x00 << SDA | 0x01 << SCL,
44 0x00 << SDA | 0x01 << SCL,
46 0x00 << SDA | 0x00 << SCL,
47 ]),
48 Symbol::Stop => samples.extend([
49 0x00 << SDA | 0x00 << SCL,
51 0x00 << SDA | 0x00 << SCL,
52 0x00 << SDA | 0x00 << SCL,
54 0x00 << SDA | 0x01 << SCL,
55 0x01 << SDA | 0x01 << SCL,
57 0x01 << SDA | 0x01 << SCL,
58 ]),
59 Symbol::Byte { data, nack } => Self::bitbanging_byte::<SDA, SCL>(*data, *nack, samples),
60 Symbol::Broken(bits) => Self::bitbanging_bits::<SDA, SCL>(bits, samples),
61 }
62 }
63
64 fn bitbanging_byte<const SDA: u8, const SCL: u8>(byte: u8, nack: bool, samples: &mut Vec<u8>) {
65 let data: u16 = (byte as u16) << 1u16 | nack as u16;
66 samples.extend((0..9u8).rev().flat_map(|bit| {
67 [
68 ((((data >> bit) & 0x01) << SDA) | 0x00 << SCL) as u8,
70 ((((data >> bit) & 0x01) << SDA) | 0x01 << SCL) as u8,
71 ((((data >> bit) & 0x01) << SDA) | 0x01 << SCL) as u8,
73 ((((data >> bit) & 0x01) << SDA) | 0x00 << SCL) as u8,
74 ]
75 }));
76 }
77
78 fn bitbanging_bits<const SDA: u8, const SCL: u8>(bits: &[Bit], samples: &mut Vec<u8>) {
79 samples.extend(bits.iter().rev().flat_map(|bit| {
80 [
81 ((*bit as u8) << SDA) | 0x00 << SCL,
83 ((*bit as u8) << SDA) | 0x01 << SCL,
84 ((*bit as u8) << SDA) | 0x01 << SCL,
86 ((*bit as u8) << SDA) | 0x00 << SCL,
87 ]
88 }));
89 }
90}
91
92pub mod encoder {
93 use super::*;
94
95 #[derive(Debug, PartialEq)]
96 pub enum Transfer<'w> {
97 Start,
98 Stop,
99 Addr { addr: u8, read: bool, nack: bool },
100 Write(&'w [u8]),
101 Read(usize),
102 Broken(ArrayVec<Bit, 8>),
103 }
104
105 impl Transfer<'_> {
106 fn bitbanging<const SDA: u8, const SCL: u8>(
107 &self,
108 is_next_stop: bool,
109 samples: &mut Vec<u8>,
110 ) {
111 match self {
112 Transfer::Start => Symbol::Start.bitbanging::<SDA, SCL>(samples),
113 Transfer::Stop => Symbol::Stop.bitbanging::<SDA, SCL>(samples),
114 Transfer::Addr { addr, read, nack } => Symbol::Byte {
115 data: (addr << 1) | *read as u8,
116 nack: *nack,
117 }
118 .bitbanging::<SDA, SCL>(samples),
119 Transfer::Write(bytes) => {
120 for byte in bytes.iter() {
121 Symbol::Byte {
122 data: *byte,
123 nack: true,
124 }
125 .bitbanging::<SDA, SCL>(samples)
126 }
127 }
128 Transfer::Broken(bits) => {
129 Symbol::Broken(bits.clone()).bitbanging::<SDA, SCL>(samples)
130 }
131 Transfer::Read(len) => {
132 for index in 0..*len {
133 Symbol::Byte {
134 data: 0xff,
135 nack: index >= (len - 1) && is_next_stop,
136 }
137 .bitbanging::<SDA, SCL>(samples)
138 }
139 }
140 }
141 }
142 }
143
144 pub struct Encoder<const SDA: u8, const SCL: u8> {}
145 impl<const SDA: u8, const SCL: u8> Encoder<SDA, SCL> {
146 pub fn run(&self, transfer: &[Transfer]) -> Vec<u8> {
150 let mut samples: Vec<u8> = Vec::new();
151 for window in transfer.windows(2) {
152 window[0]
153 .bitbanging::<SDA, SCL>(window.get(1) == Some(&Transfer::Stop), &mut samples)
154 }
155
156 transfer
158 .iter()
159 .last()
160 .unwrap()
161 .bitbanging::<SDA, SCL>(false, &mut samples);
162 samples
163 }
164 }
165}
166
167pub mod decoder {
168 use super::*;
169 use std::iter::Peekable;
170
171 #[derive(Debug, PartialEq)]
172 pub enum Transfer<'b> {
173 Start,
174 Stop,
175 Addr { addr: u8, read: bool, nack: bool },
176 Bytes { data: &'b [u8], nack: bool },
177 Broken(ArrayVec<Bit, 8>),
178 }
179
180 impl<'a> std::convert::From<Symbol> for Transfer<'a> {
181 fn from(symbol: Symbol) -> Self {
182 match symbol {
183 Symbol::Start => Self::Start,
184 Symbol::Stop => Self::Stop,
185 Symbol::Broken(bits) => Self::Broken(bits),
186 _ => panic!("Can't convert {:?} into Transfer", symbol),
187 }
188 }
189 }
190
191 enum DecodingState {
192 Start,
193 Bytes,
194 }
195
196 #[derive(Clone, Debug)]
197 struct Sample<const SDA: u8, const SCL: u8> {
198 raw: u8,
199 }
200
201 impl<const SDA: u8, const SCL: u8> Sample<SDA, SCL> {
202 fn sda(&self) -> Bit {
203 ((self.raw >> SDA) & 0x01).into()
204 }
205
206 fn scl(&self) -> Bit {
207 ((self.raw >> SCL) & 0x01).into()
208 }
209 }
210 pub struct Decoder<const SDA: u8, const SCL: u8> {
211 pub buffer: [u8; 256],
212 }
213
214 impl<const SDA: u8, const SCL: u8> Decoder<SDA, SCL> {
215 fn sample_on_fall_edge<I>(samples: &mut I) -> Result<Option<Symbol>>
219 where
220 I: Iterator<Item = Sample<SDA, SCL>>,
221 {
222 let mut previous: Option<Sample<SDA, SCL>> = None;
223 for sample in samples.by_ref() {
224 if sample.scl() == Bit::Low {
225 return Ok(None); }
227 if let Some(previous) = previous
229 && previous.sda() != sample.sda()
230 {
231 return Ok(Some(match sample.sda() {
232 Bit::High => Symbol::Stop,
233 Bit::Low => Symbol::Start,
234 }));
235 }
236 previous = Some(sample);
237 }
238 bail!("Ran out of samples and did not find fall edge")
239 }
240
241 fn sample_on_raise_edge<I>(samples: &mut Peekable<I>) -> Option<Sample<SDA, SCL>>
245 where
246 I: Iterator<Item = Sample<SDA, SCL>>,
247 {
248 while samples.next_if(|sample| sample.scl() == Bit::Low).is_some() {}
249 samples.peek().cloned()
250 }
251
252 fn loop_until<I>(samples: &mut I, sda: Bit, scl: Bit) -> Option<Sample<SDA, SCL>>
253 where
254 I: Iterator<Item = Sample<SDA, SCL>>,
255 {
256 samples
257 .by_ref()
258 .find(|sample| sample.sda() == sda && sample.scl() == scl)
259 }
260
261 fn find_start<I>(samples: &mut I) -> Result<Sample<SDA, SCL>>
262 where
263 I: Iterator<Item = Sample<SDA, SCL>>,
264 {
265 'outer: loop {
266 Self::loop_until(samples, Bit::High, Bit::High)
268 .context("Beginning of start bit not found")?;
269
270 for sample in samples.by_ref() {
272 if sample.scl() == Bit::Low {
273 continue 'outer;
274 }
275
276 if sample.sda() == Bit::Low {
277 return Ok(sample);
278 }
279 }
280 bail!("Start bit condition not found")
281 }
282 }
283
284 fn decode_symbol<I>(samples: &mut Peekable<I>) -> Result<Symbol>
285 where
286 I: Iterator<Item = Sample<SDA, SCL>>,
287 {
288 let mut byte = 0u16;
289 for index in 0..9 {
291 let Ok(fall_sample) = Self::sample_on_fall_edge(samples) else {
292 return Symbol::broken(byte as u8, index);
293 };
294
295 if let Some(symbol) = fall_sample {
297 return Ok(symbol);
298 }
299
300 let Some(sample) = Self::sample_on_raise_edge(samples) else {
301 return Symbol::broken(byte as u8, index);
302 };
303 byte <<= 1;
304 byte |= sample.sda() as u16;
305 }
306
307 Ok(Symbol::Byte {
308 data: (byte >> 1) as u8,
309 nack: byte & 0x01 == 1,
310 })
311 }
312
313 pub fn run(&mut self, samples: Vec<u8>) -> Result<Vec<Transfer<'_>>> {
314 let mut samples = samples
315 .into_iter()
316 .map(|raw| Sample::<SDA, SCL> { raw })
317 .peekable();
318 Self::find_start(&mut samples)?;
319 let mut trans = vec![Transfer::Start];
320 let mut state = DecodingState::Start;
321 let mut head_offset = 0usize;
322 let mut buffer = &mut self.buffer[..];
323
324 while let Ok(symbol) = Self::decode_symbol(&mut samples) {
325 state = match state {
326 DecodingState::Start => match symbol {
327 Symbol::Byte { data, nack } => {
328 let read = (data & 1) == 1;
329 trans.push(Transfer::Addr {
330 addr: data >> 1,
331 read,
332 nack,
333 });
334 DecodingState::Bytes
335 }
336 _ => {
337 trans.push(symbol.into());
338 DecodingState::Start
339 }
340 },
341 DecodingState::Bytes => match symbol {
342 Symbol::Byte { data, nack } => {
343 buffer[head_offset] = data;
344 head_offset += 1;
345 assert!(head_offset < buffer.len());
346 if nack {
347 let (filled, empty) = buffer.split_at_mut(head_offset);
348 buffer = empty;
349 head_offset = 0;
350 trans.push(Transfer::Bytes { data: filled, nack });
351 DecodingState::Start
352 } else {
353 DecodingState::Bytes
354 }
355 }
356 Symbol::Start | Symbol::Stop => {
357 if head_offset > 0 {
358 let (filled, empty) = buffer.split_at_mut(head_offset);
359 buffer = empty;
360 head_offset = 0;
361 trans.push(Transfer::Bytes {
362 data: filled,
363 nack: false,
364 });
365 }
366 trans.push(symbol.into());
367 DecodingState::Start
368 }
369 Symbol::Broken(_) => {
370 trans.push(symbol.into());
371 DecodingState::Start
372 }
373 },
374 }
375 }
376 Ok(trans)
377 }
378 }
379}