From b72be2fc3b34a1b695594199ba711d13bac58900 Mon Sep 17 00:00:00 2001 From: doryan Date: Thu, 22 May 2025 21:52:03 +0400 Subject: [PATCH] feat(buf): implement SoftSerial traits for HalfDuplexSerial with RingBuffer --- src/lib.rs | 154 +++++++++++++++++++++++++++++------------------------ 1 file changed, 84 insertions(+), 70 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index ff78c0f..da8e285 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,6 +14,8 @@ use avr_device::asm::delay_cycles; use static_pins::StaticPinOps; +mod structures; + pub type PollResult = Result<(), PollError>; pub type ReadByteResult = Result; pub type CorruptedData = (u8, u8); @@ -107,100 +109,112 @@ pub trait SoftSerialWriter where P: PinOps + StaticPinOps, { - #[inline(never)] - fn write_byte(&self, data: u8) { - let (mut data, mut parity_bit) = (data, 0); - - for _ in 0..8 { - if data & MSB == 0 { - P::set_high(); - parity_bit ^= 0; - } else { - P::set_low(); - parity_bit ^= 1; - } - - delay_us(SERIAL_DELAY); - - data <<= 1; - } - - // Hamming code and CRC are very weightful and slow, so I use simple parity check - - if parity_bit == 0 { - P::set_high(); - } else { - P::set_low(); - } - - delay_us(SERIAL_DELAY); - } - + fn write_byte(&self, data: u8); fn write_bytes(&self, transmit_data: T); } -impl

SoftSerialWriter for HalfDuplexSerial

-where - P: PinOps + StaticPinOps, -{ - fn write_bytes(&self, transmit_data: &[u8]) { - for byte in transmit_data { - self.write_byte(*byte); - self.sync_transmitter(); - } - } -} - pub trait SoftSerialReader where P: PinOps + StaticPinOps, { - #[inline(never)] - fn read_byte(&self) -> ReadByteResult { - let (mut data, mut reciever_parity_bit) = (0, 0); + fn read_byte(&self) -> ReadByteResult; + fn read_bytes(&self, recieve_data: T); +} - delay_cycles(FIRST_ENTRY_READING); - for _ in 0..8 { - delay_us(FIRST_HALF_SERIAL_DELAY); - - data <<= 1; - - if P::is_low() { - data |= 1; - reciever_parity_bit ^= 1; - } else { - data |= 0; - reciever_parity_bit ^= 0; - } - - delay_cycles(READING_ADJUST); - delay_us(SECOND_HALF_SERIAL_DELAY); - } +#[inline(always)] +pub(crate) fn _priv_read_byte() -> ReadByteResult { + let (mut data, mut reciever_parity_bit) = (0, 0); + delay_cycles(FIRST_ENTRY_READING); + for _ in 0..8 { delay_us(FIRST_HALF_SERIAL_DELAY); - let transmitter_parity_bit = (P::read() >> P::PIN_NUM) & LSB; + data <<= 1; + + if P::is_low() { + data |= 1; + reciever_parity_bit ^= 1; + } else { + data |= 0; + reciever_parity_bit ^= 0; + } delay_cycles(READING_ADJUST); delay_us(SECOND_HALF_SERIAL_DELAY); - - if reciever_parity_bit == transmitter_parity_bit { - return Err((data, reciever_parity_bit)); - } - - Ok(data) } - fn read_bytes(&self, recieve_data: T); + delay_us(FIRST_HALF_SERIAL_DELAY); + + let transmitter_parity_bit = (P::read() >> P::PIN_NUM) & LSB; + + delay_cycles(READING_ADJUST); + delay_us(SECOND_HALF_SERIAL_DELAY); + + if reciever_parity_bit == transmitter_parity_bit { + return Err((data, reciever_parity_bit)); + } + + Ok(data) +} + +#[inline(always)] +pub(crate) fn _priv_write_bytes(data: u8) { + let (mut data, mut parity_bit) = (data, 0); + + for _ in 0..8 { + if data & MSB == 0 { + P::set_high(); + parity_bit ^= 0; + } else { + P::set_low(); + parity_bit ^= 1; + } + + delay_us(SERIAL_DELAY); + + data <<= 1; + } + + // Hamming code and CRC are very weightful and slow, so I use simple parity check + + if parity_bit == 0 { + P::set_high(); + } else { + P::set_low(); + } + + delay_us(SERIAL_DELAY); +} + +impl

SoftSerialWriter for HalfDuplexSerial

+where + P: PinOps + StaticPinOps, +{ + #[inline(never)] + fn write_byte(&self, data: u8) { + _priv_write_bytes::

(data); + } + + fn write_bytes(&self, transmit_data: &[u8]) { + for byte in transmit_data { + >::write_byte(self, *byte); + self.sync_transmitter(); + } + } } impl

SoftSerialReader for HalfDuplexSerial

where P: PinOps + StaticPinOps, { + #[inline(never)] + fn read_byte(&self) -> ReadByteResult { + _priv_read_byte::

() + } + fn read_bytes(&self, recieve_data: &mut [u8]) { for byte in recieve_data { - if let Ok(data) = self.read_byte() { + if let Ok(data) = >::read_byte(self) { *byte = data; } self.sync_reciever();