From ca54784e643efa3fbf86541d02b44c0b7761a3c8 Mon Sep 17 00:00:00 2001 From: doryan Date: Sun, 10 Aug 2025 20:57:28 +0400 Subject: [PATCH] feat(encode): add CRC calculation --- src/lib.rs | 51 +++++++++++++++++++-------------------------------- 1 file changed, 19 insertions(+), 32 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 43e5e85..1c7d8b9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -28,8 +28,12 @@ const SECOND_HALF_SERIAL_DELAY: u32 = SERIAL_DELAY - FIRST_HALF_SERIAL_DELAY; const READING_ADJUST: u32 = 16; const FIRST_ENTRY_READING: u32 = 30; -const LSB: u8 = 0x01; -const MSB: u8 = 0x80; +const MSB: u16 = 0x0200; + +#[inline(always)] +fn crc_calculate(value: u8) -> u8 { + ((value >> 6) | (value >> 4) | (value >> 2) | value) & 0x0F +} pub enum PollError { NotFound, @@ -53,7 +57,7 @@ where pub fn poll(&self) -> PollResult { P::into_output(); - delay_cycles(1); + delay_cycles(4); P::into_pull_up_input(); delay_us(SERIAL_DELAY); @@ -127,31 +131,19 @@ where { #[inline(never)] fn write_byte(&self, transmit_data: u8) { - let (mut data, mut parity_bit) = (transmit_data, 0); + let mut data = ((transmit_data as u16) << 4) | (crc_calculate(transmit_data) as u16); - for _ in 0..8 { + for _ in 0..(u8::BITS + 4) { 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); } } @@ -161,35 +153,30 @@ where { #[inline(never)] fn read_byte(&self) -> ReadByteResult { - let (mut data, mut reciever_parity_bit) = (0, 0); + let mut packet = 0u16; delay_cycles(FIRST_ENTRY_READING); - for _ in 0..8 { + for _ in 0..(u8::BITS + 4) { delay_us(FIRST_HALF_SERIAL_DELAY); - data <<= 1; + packet <<= 1; if P::is_low() { - data |= 1; - reciever_parity_bit ^= 1; + packet |= 1; } else { - data |= 0; - reciever_parity_bit ^= 0; + packet |= 0; } delay_cycles(READING_ADJUST); delay_us(SECOND_HALF_SERIAL_DELAY); } - delay_us(FIRST_HALF_SERIAL_DELAY); + let received_crc = (packet & 0x000F) as u8; + let data = packet.overflowing_shr(4).0 as u8; + let calculated_crc = crc_calculate(data); - 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)); + if received_crc != calculated_crc { + return Err((received_crc, calculated_crc)); } Ok(data)