1use anyhow::{Result, bail};
6use serde::{Deserialize, Serialize};
7use serialport::Parity;
8use thiserror::Error;
9
10#[derive(Clone, Copy, Debug, PartialEq)]
12pub enum UartStopBits {
13 Stop1,
14 Stop1_5,
15 Stop2,
16}
17
18#[derive(Clone, Debug)]
20pub struct UartBitbangConfig {
21 pub data_bits: u8, pub stop_bits: UartStopBits, pub break_char_cycles: u8,
26 pub parity: Parity,
27}
28
29impl UartBitbangConfig {
30 pub fn new(
31 data_bits: u8,
32 stop_bits: UartStopBits,
33 break_char_cycles: u8,
34 parity: Parity,
35 ) -> Result<UartBitbangConfig> {
36 if !(5..=8).contains(&data_bits) {
37 bail!("UART bitbanging only supports between 5 and 8 bit data.");
38 }
39 if stop_bits == UartStopBits::Stop1_5 {
40 bail!("UART bitbanging only supports 1 or 2 stop bits.");
41 }
42 Ok(Self {
43 data_bits,
44 stop_bits,
45 break_char_cycles,
46 parity,
47 })
48 }
49
50 fn stop_bit_time(&self) -> u8 {
52 match self.stop_bits {
53 UartStopBits::Stop1 => 1,
54 _ => 2,
55 }
56 }
57
58 pub fn bit_time_per_frame(&self) -> u32 {
60 let start_bit = 1;
61 let parity_bits = (self.parity != Parity::None) as u8;
62 let stop_bits = self.stop_bit_time();
63 (start_bit + self.data_bits + parity_bits + stop_bits).into()
64 }
65
66 pub fn break_bit_time(&self) -> u32 {
68 self.bit_time_per_frame() * self.break_char_cycles as u32
69 }
70}
71
72#[inline]
75pub fn compute_parity(data: u8, parity_bit: Option<bool>) -> bool {
76 let data_parity = !data.count_ones().is_multiple_of(2);
77 if let Some(bit) = parity_bit {
78 data_parity ^ bit
79 } else {
80 data_parity
81 }
82}
83
84#[derive(Debug, PartialEq)]
85pub enum UartTransfer {
86 Byte {
88 data: u8,
89 },
90 Broken {
91 data: u8,
92 parity: Option<bool>,
93 error: UartTransferDecodeError,
94 },
95 Break,
96}
97
98pub struct UartBitbangEncoder {
101 pub config: UartBitbangConfig,
102}
103
104impl UartBitbangEncoder {
105 pub fn new(config: UartBitbangConfig) -> Self {
106 Self { config }
107 }
108
109 pub fn encode_break(&self, samples: &mut Vec<u8>) {
112 let break_bits = self.config.break_bit_time() as usize;
113 let stop_bits = self.config.stop_bit_time() as usize;
114 samples.extend(std::iter::repeat_n(0x00, break_bits));
115 samples.extend(std::iter::repeat_n(0x01, stop_bits));
116 }
117
118 pub fn encode_character(&self, data: u8, samples: &mut Vec<u8>) {
122 samples.reserve(self.config.bit_time_per_frame() as usize);
123 samples.push(0x00);
125 for bit_index in 0..self.config.data_bits {
127 let bit = (data >> bit_index) & 0x01;
128 samples.push(bit);
129 }
130 let parity = compute_parity(data, None);
132 match self.config.parity {
133 Parity::Even => samples.push(parity as u8),
134 Parity::Odd => samples.push(!parity as u8),
135 Parity::None => (),
136 }
137 for _ in 0..self.config.stop_bit_time() {
139 samples.push(0x01);
140 }
141 }
142
143 pub fn encode_characters(&self, chars: &[u8], samples: &mut Vec<u8>) {
146 for char in chars {
147 self.encode_character(*char, samples);
148 }
149 }
150
151 pub fn encode_transfer(&self, transfer: &UartTransfer, samples: &mut Vec<u8>) -> Result<()> {
154 match *transfer {
155 UartTransfer::Broken { .. } => bail!("Cannot encode a broken UART transfer"),
156 UartTransfer::Break => self.encode_break(samples),
157 UartTransfer::Byte { data } => self.encode_character(data, samples),
158 }
159 Ok(())
160 }
161
162 pub fn encode_transfers(
165 &self,
166 transfers: &[UartTransfer],
167 samples: &mut Vec<u8>,
168 ) -> Result<()> {
169 for transfer in transfers {
170 self.encode_transfer(transfer, samples)?;
171 }
172 Ok(())
173 }
174}
175
176#[derive(Error, Debug, PartialEq, Serialize, Deserialize)]
177pub enum UartTransferDecodeError {
178 #[error("Computed parity does not match expected parity")]
179 ParityMismatch,
180 #[error("Stop was not held high for the full stop time")]
181 InvalidStop,
182 #[error(
183 "RX held low too long for a valid transmission, but not long enough for a break condition"
184 )]
185 InvalidBreak,
186}
187
188#[derive(Debug, PartialEq)]
190enum DecodingState {
191 Idle,
192 Data {
193 data: u8, bits: u8, },
196 Parity {
197 data: u8, },
199 Stop {
200 data: u8, parity: Option<bool>, stop_data: u8, stop_bits: u8, },
205 Break {
206 bits: u32, },
208}
209
210pub struct UartBitbangDecoder {
213 pub config: UartBitbangConfig,
214 state: DecodingState,
215}
216
217impl UartBitbangDecoder {
218 pub fn new(config: UartBitbangConfig) -> Self {
219 Self {
220 config,
221 state: DecodingState::Idle,
222 }
223 }
224
225 fn get_decoded_break(&mut self) -> Result<UartTransfer> {
227 let DecodingState::Break { bits } = self.state else {
228 bail!("`get_decoded_break` called before decoding a break");
229 };
230 if bits < self.config.break_bit_time() {
231 let parity = if self.config.parity != Parity::None {
232 Some(false)
233 } else {
234 None
235 };
236 Ok(UartTransfer::Broken {
237 data: 0x00,
238 parity,
239 error: UartTransferDecodeError::InvalidBreak,
240 })
241 } else {
242 Ok(UartTransfer::Break)
243 }
244 }
245
246 fn get_decoded_character(&mut self) -> Result<UartTransfer> {
248 let DecodingState::Stop {
250 data,
251 parity,
252 stop_data,
253 stop_bits,
254 } = self.state
255 else {
256 bail!("`get_decoded_character` called before the end of a transmission");
257 };
258 if stop_bits != self.config.stop_bit_time() {
259 bail!("`get_decoded_character` called before reading all stop bits");
260 }
261 if stop_data.count_ones() as u8 != stop_bits {
262 return Ok(UartTransfer::Broken {
263 data,
264 parity,
265 error: UartTransferDecodeError::InvalidStop,
266 });
267 }
268
269 if self.config.parity != Parity::None {
271 let decoded_parity = compute_parity(data, parity);
272 let expected_parity = self.config.parity != Parity::Even;
273 if expected_parity != decoded_parity {
274 return Ok(UartTransfer::Broken {
275 data,
276 parity,
277 error: UartTransferDecodeError::ParityMismatch,
278 });
279 }
280 }
281
282 Ok(UartTransfer::Byte { data })
283 }
284
285 pub fn decode_sample(&mut self, sample: u8) -> Result<Option<UartTransfer>> {
289 let rx = sample & 0x1;
290 match self.state {
291 DecodingState::Idle => {
292 if rx == 0 {
293 self.state = DecodingState::Data {
294 data: 0x00,
295 bits: 0,
296 };
297 }
298 }
299 DecodingState::Data { mut data, mut bits } => {
300 data |= rx << bits;
301 bits += 1;
302 self.state = if bits >= self.config.data_bits {
303 if self.config.parity == Parity::None {
304 DecodingState::Stop {
305 data,
306 parity: None,
307 stop_data: 0x00,
308 stop_bits: 0,
309 }
310 } else {
311 DecodingState::Parity { data }
312 }
313 } else {
314 DecodingState::Data { data, bits }
315 }
316 }
317 DecodingState::Parity { data } => {
318 self.state = DecodingState::Stop {
319 data,
320 parity: Some(rx != 0),
321 stop_data: 0x00,
322 stop_bits: 0,
323 };
324 }
325 DecodingState::Stop {
326 data,
327 parity,
328 mut stop_data,
329 mut stop_bits,
330 } => {
331 stop_data |= rx << stop_bits;
332 stop_bits += 1;
333 self.state = DecodingState::Stop {
334 data,
335 parity,
336 stop_data,
337 stop_bits,
338 };
339 if stop_bits >= self.config.stop_bit_time() {
340 if data != 0x00 || parity == Some(true) || stop_data != 0x00 {
341 let decoded = self.get_decoded_character()?;
342 self.state = DecodingState::Idle;
343 return Ok(Some(decoded));
344 }
345 self.state = DecodingState::Break {
346 bits: self.config.bit_time_per_frame(),
347 }
348 }
349 }
350 DecodingState::Break { bits } => {
351 if rx != 0 {
352 let decoded = self.get_decoded_break()?;
353 self.state = DecodingState::Idle;
354 return Ok(Some(decoded));
355 }
356 self.state = DecodingState::Break { bits: bits + 1 };
357 }
358 }
359 Ok(None)
360 }
361
362 pub fn decode_samples(&mut self, samples: &Vec<u8>) -> Result<Vec<UartTransfer>> {
366 let mut transfers = vec![];
367 for sample in samples {
368 if let Some(transfer) = self.decode_sample(*sample)? {
369 transfers.push(transfer);
370 }
371 }
372 Ok(transfers)
373 }
374
375 pub fn is_idle(&self) -> bool {
377 self.state == DecodingState::Idle
378 }
379
380 pub fn reset(&mut self) {
382 self.state = DecodingState::Idle;
383 }
384}
385
386#[cfg(test)]
387mod test {
388 use super::*;
389
390 fn compare_decoded_result(received: &[UartTransfer], expected: &[u8]) -> Result<()> {
391 assert_eq!(received.len(), expected.len());
392 for (transfer, expected) in received.iter().zip(expected.iter()) {
393 match transfer {
394 UartTransfer::Byte { data } => {
395 assert_eq!(data, expected);
396 }
397 _ => bail!("Only expected to decode bytes"),
398 }
399 }
400 Ok(())
401 }
402
403 fn uart_encode_decode(config: UartBitbangConfig, message: Option<&[u8]>) -> Result<()> {
404 let encoder = UartBitbangEncoder::new(config.clone());
405 let mut decoder = UartBitbangDecoder::new(config);
406 let msg = message.unwrap_or(b"Hello, this is a simple UART test message.");
407 let mut samples = Vec::new();
408 encoder.encode_characters(msg, &mut samples);
409 assert!(!samples.is_empty());
410 let decoded = decoder
411 .decode_samples(&samples)
412 .expect("Should have decoded the bitbanged message");
413 assert!(decoder.is_idle());
414 compare_decoded_result(&decoded, msg)
415 }
416
417 #[test]
418 fn smoke() -> Result<()> {
419 let config = UartBitbangConfig::new(8, UartStopBits::Stop2, 1, Parity::None)?;
421 uart_encode_decode(config.clone(), None)?;
422 uart_encode_decode(config.clone(), Some(b"abc def ghi jkl"))?;
423 uart_encode_decode(config.clone(), Some(b"12345"))?;
424
425 let encoder = UartBitbangEncoder::new(config);
427 let bytes = [0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF];
428 let mut samples = Vec::new();
429 encoder.encode_characters(&bytes, &mut samples);
430 let expected = [
431 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0,
432 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1,
433 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1,
434 1,
435 ];
436 assert_eq!(samples, expected);
437 Ok(())
438 }
439
440 #[test]
441 fn data_bits() -> Result<()> {
442 assert!(UartBitbangConfig::new(4, UartStopBits::Stop2, 1, Parity::None).is_err());
444 assert!(UartBitbangConfig::new(9, UartStopBits::Stop2, 1, Parity::None).is_err());
445 let test_msg = b"data_bits TEST STRING";
447 for data_bits in 5..=8 {
448 let data_mask = ((0x1u16 << data_bits) - 1) as u8;
449 let msg = test_msg.iter().map(|b| b & data_mask).collect::<Vec<_>>();
450 uart_encode_decode(
451 UartBitbangConfig::new(data_bits, UartStopBits::Stop2, 1, Parity::None)?,
452 Some(&msg),
453 )?;
454 }
455 Ok(())
456 }
457
458 #[test]
459 fn stop_bits() -> Result<()> {
460 assert!(UartBitbangConfig::new(8, UartStopBits::Stop1_5, 1, Parity::None).is_err());
462 for stop_bits in [UartStopBits::Stop1, UartStopBits::Stop2] {
464 uart_encode_decode(
465 UartBitbangConfig::new(8, stop_bits, 1, Parity::None)?,
466 Some(b"hello from the `stop_bits()` test!"),
467 )?;
468 }
469 let mut samples = Vec::new();
471 UartBitbangEncoder::new(UartBitbangConfig::new(
472 8,
473 UartStopBits::Stop1,
474 1,
475 Parity::None,
476 )?)
477 .encode_character(0xA5, &mut samples);
478 assert_eq!(&samples, &[0, 1, 0, 1, 0, 0, 1, 0, 1, 1]);
479 samples.clear();
480 UartBitbangEncoder::new(UartBitbangConfig::new(
481 8,
482 UartStopBits::Stop2,
483 1,
484 Parity::None,
485 )?)
486 .encode_character(0xA5, &mut samples);
487 assert_eq!(&samples, &[0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1]);
488 assert_eq!(
490 UartBitbangDecoder::new(UartBitbangConfig::new(
491 8,
492 UartStopBits::Stop2,
493 1,
494 Parity::None
495 )?)
496 .decode_samples(&vec![0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0])?,
497 vec![UartTransfer::Broken {
498 data: 0xA5,
499 parity: None,
500 error: UartTransferDecodeError::InvalidStop,
501 }]
502 );
503 Ok(())
504 }
505
506 #[test]
507 fn parity_bits() -> Result<()> {
508 let tests = [
509 (Parity::None, vec![0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1]),
510 (Parity::Odd, vec![0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1]),
511 (Parity::Even, vec![0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1]),
512 ];
513 for (parity, expected) in tests {
514 uart_encode_decode(
516 UartBitbangConfig::new(8, UartStopBits::Stop2, 1, parity)?,
517 Some(b"this string is used for testing parity"),
518 )?;
519 let config = UartBitbangConfig::new(8, UartStopBits::Stop2, 1, parity)?;
521 let mut samples = Vec::new();
522 UartBitbangEncoder::new(config.clone()).encode_character(0xA5, &mut samples);
523 assert_eq!(&samples, &expected);
524 if parity == Parity::None {
526 continue;
527 }
528 let mut decoder = UartBitbangDecoder::new(config.clone());
529 let mut invalid_samples = expected.clone();
530 invalid_samples[9] = !invalid_samples[9] & 0x01;
532 assert_eq!(
533 decoder.decode_samples(&invalid_samples)?,
534 vec![UartTransfer::Broken {
535 data: 0xA5,
536 parity: Some(invalid_samples[9] != 0),
537 error: UartTransferDecodeError::ParityMismatch,
538 }]
539 );
540 decoder.reset();
541 for data_bit in 0..8 {
543 invalid_samples = expected.clone();
544 invalid_samples[1 + data_bit] = !expected[1 + data_bit] & 0x01;
545 assert_eq!(
546 decoder.decode_samples(&invalid_samples)?,
547 vec![UartTransfer::Broken {
548 data: 0xA5 ^ (0x1 << data_bit),
549 parity: Some(expected[9] != 0),
550 error: UartTransferDecodeError::ParityMismatch,
551 }]
552 );
553 decoder.reset();
554 }
555 }
556 Ok(())
557 }
558
559 #[test]
560 fn breaks() -> Result<()> {
561 let break_transfer = [
563 UartTransfer::Byte { data: 0x12 },
564 UartTransfer::Byte { data: 0x34 },
565 UartTransfer::Break,
566 UartTransfer::Byte { data: 0x56 },
567 UartTransfer::Byte { data: 0x78 },
568 ];
569 for break_cycles in 1..=5 {
570 let config =
571 UartBitbangConfig::new(8, UartStopBits::Stop2, break_cycles, Parity::None)?;
572 let encoder = UartBitbangEncoder::new(config.clone());
573 let mut decoder = UartBitbangDecoder::new(config.clone());
574 let mut samples = Vec::new();
575 encoder.encode_transfers(&break_transfer, &mut samples)?;
576 assert!(
577 samples.len() > (config.bit_time_per_frame() as usize) * (break_cycles as usize)
578 );
579 let decoded = decoder
580 .decode_samples(&samples)
581 .expect("Should have decoded the bitbanged transmission");
582 assert!(decoder.is_idle());
583 assert_eq!(&break_transfer, &decoded[..]);
584 }
585 assert_eq!(
587 UartBitbangDecoder::new(UartBitbangConfig::new(
588 8,
589 UartStopBits::Stop2,
590 2,
591 Parity::None
592 )?)
593 .decode_samples(&vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1])?,
594 vec![UartTransfer::Broken {
595 data: 0x00,
596 parity: None,
597 error: UartTransferDecodeError::InvalidBreak,
598 }]
599 );
600 Ok(())
601 }
602
603 #[test]
604 fn partial_transfers() -> Result<()> {
605 let mut decoder = UartBitbangDecoder::new(UartBitbangConfig::new(
608 8,
609 UartStopBits::Stop2,
610 1,
611 Parity::None,
612 )?);
613 assert!(decoder.is_idle());
614 for sample in [0, 1, 0, 1, 0, 0, 1, 0, 1, 1] {
615 assert!(decoder.decode_samples(&vec![sample])?.is_empty());
616 assert!(!decoder.is_idle());
617 }
618 assert_eq!(
619 decoder.decode_samples(&vec![1])?,
620 vec![UartTransfer::Byte { data: 0xA5 }]
621 );
622 assert!(decoder.is_idle());
623 Ok(())
624 }
625}