From 68c1ff13ebd285d79e5e8adf8469bcaa368d2d3e Mon Sep 17 00:00:00 2001 From: doryan Date: Sun, 1 Jun 2025 18:20:24 +0400 Subject: [PATCH] feat: remove complex type casting --- src/lib.rs | 133 +++++++++++++++++----------------- src/structures/ring_buffer.rs | 35 ++++----- 2 files changed, 82 insertions(+), 86 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 5084585..43e5e85 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -107,99 +107,105 @@ where } } -pub trait SoftSerialWriter +pub trait SoftSerialWriter: SoftSerialByteWriter

where P: PinOps + StaticPinOps, { - fn write_byte(&self, data: u8); fn write_bytes(&self, transmit_data: T); } -pub trait SoftSerialReader +pub trait SoftSerialReader: SoftSerialByteReader

where P: PinOps + StaticPinOps, { - fn read_byte(&self) -> ReadByteResult; fn read_bytes(&self, recieve_data: T); } -#[inline(always)] -pub(crate) fn _priv_read_byte() -> ReadByteResult { - let (mut data, mut reciever_parity_bit) = (0, 0); +pub trait SoftSerialByteWriter

+where + P: PinOps + StaticPinOps, +{ + #[inline(never)] + fn write_byte(&self, transmit_data: u8) { + let (mut data, mut parity_bit) = (transmit_data, 0); - delay_cycles(FIRST_ENTRY_READING); - for _ in 0..8 { - delay_us(FIRST_HALF_SERIAL_DELAY); + for _ in 0..8 { + if data & MSB == 0 { + P::set_high(); + parity_bit ^= 0; + } else { + P::set_low(); + parity_bit ^= 1; + } - data <<= 1; + delay_us(SERIAL_DELAY); - if P::is_low() { - data |= 1; - reciever_parity_bit ^= 1; - } else { - data |= 0; - reciever_parity_bit ^= 0; + data <<= 1; } - delay_cycles(READING_ADJUST); - delay_us(SECOND_HALF_SERIAL_DELAY); - } + // Hamming code and CRC are very weightful and slow, so I use simple parity check - 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 { + if parity_bit == 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); } +pub trait SoftSerialByteReader

+where + P: PinOps + StaticPinOps, +{ + #[inline(never)] + fn read_byte(&self) -> 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); + + 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); + } + + 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) + } +} + +impl SoftSerialByteWriter

for HalfDuplexSerial

{} +impl SoftSerialByteReader

for HalfDuplexSerial

{} + 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.write_byte(*byte); self.sync_transmitter(); } } @@ -209,14 +215,9 @@ 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) = >::read_byte(self) { + if let Ok(data) = self.read_byte() { *byte = data; } self.sync_reciever(); diff --git a/src/structures/ring_buffer.rs b/src/structures/ring_buffer.rs index 4483fe8..b2ee8d0 100644 --- a/src/structures/ring_buffer.rs +++ b/src/structures/ring_buffer.rs @@ -4,7 +4,10 @@ use arduino_hal::port::PinOps; use static_pins::StaticPinOps; -use crate::{HalfDuplexSerial, SoftSerialReader, SoftSerialWriter}; +use crate::{ + HalfDuplexSerial, SoftSerialByteReader, SoftSerialByteWriter, SoftSerialReader, + SoftSerialWriter, +}; #[derive(Debug, Clone, Copy)] pub struct RingBuffer { @@ -14,11 +17,17 @@ pub struct RingBuffer { tail: usize, } +impl Default for RingBuffer { + fn default() -> Self { + Self::new() + } +} + impl RingBuffer { #[inline] pub const fn new() -> Self { if N.is_power_of_two() { - RingBuffer { + Self { buf: [0; N], mask: N - 1, head: 0, @@ -104,21 +113,13 @@ impl SoftSerialWriter> for HalfDuplexSe where P: PinOps + StaticPinOps, { - #[inline(never)] - fn write_byte(&self, data: u8) { - crate::_priv_write_bytes::

(data); - } - #[inline(never)] fn write_bytes(&self, transmit_data: &mut RingBuffer) { - >>::write_byte( - self, - transmit_data.len() as u8, - ); + self.write_byte(transmit_data.len() as u8); for byte in transmit_data { self.sync_transmitter(); - >>::write_byte(self, byte); + self.write_byte(byte); } } } @@ -127,21 +128,15 @@ impl SoftSerialReader> for HalfDuplexSe where P: PinOps + StaticPinOps, { - #[inline(never)] - fn read_byte(&self) -> crate::ReadByteResult { - crate::_priv_read_byte::

() - } - #[inline(never)] fn read_bytes(&self, recieve_data: &mut RingBuffer) { - let byte = >>::read_byte(self); + let byte = self.read_byte(); if let Ok(len) = byte { for _ in 0..len { self.sync_reciever(); - if let Ok(byte) = >>::read_byte(self) - { + if let Ok(byte) = self.read_byte() { recieve_data.push(byte).unwrap_or(()); } }