From 7cbbe955bb52283274270d24e0ea92f8c5008dda Mon Sep 17 00:00:00 2001 From: doryan Date: Thu, 22 May 2025 21:51:13 +0400 Subject: [PATCH] feat(buf): add ringbuffer structure --- src/structures/mod.rs | 1 + src/structures/ring_buffer.rs | 148 ++++++++++++++++++++++++++++++++++ 2 files changed, 149 insertions(+) create mode 100644 src/structures/mod.rs create mode 100644 src/structures/ring_buffer.rs diff --git a/src/structures/mod.rs b/src/structures/mod.rs new file mode 100644 index 0000000..5fcb102 --- /dev/null +++ b/src/structures/mod.rs @@ -0,0 +1 @@ +pub mod ring_buffer; diff --git a/src/structures/ring_buffer.rs b/src/structures/ring_buffer.rs new file mode 100644 index 0000000..4b04404 --- /dev/null +++ b/src/structures/ring_buffer.rs @@ -0,0 +1,148 @@ +// Thanks to Low Byte Productions, I like this channel. +// Youtube: https://www.youtube.com/watch?v=uIJnATS9j_0 + +use arduino_hal::port::PinOps; +use static_pins::StaticPinOps; + +use crate::{HalfDuplexSerial, SoftSerialReader, SoftSerialWriter}; + +#[derive(Debug, Clone, Copy)] +pub struct RingBuffer { + buf: [u8; N], + mask: usize, + head: usize, + tail: usize, +} + +impl RingBuffer { + #[inline] + pub const fn new() -> Self { + if N.is_power_of_two() { + RingBuffer { + buf: [0; N], + mask: N - 1, + head: 0, + tail: 0, + } + } else { + panic!("Buffer capacity isn't power of two"); + } + } + + #[inline(always)] + pub fn get_buffer(&self) -> &[u8] { + &self.buf + } + + #[inline(always)] + pub fn is_empty(&self) -> bool { + self.head == self.tail + } + + #[inline(always)] + pub fn is_full(&self) -> bool { + (self.head + 1) & self.mask == self.tail + } + + #[inline(always)] + pub fn capacity(&self) -> usize { + N + } + + #[inline(always)] + pub fn len(&self) -> usize { + self.head.overflowing_sub(self.tail).0 & self.mask + } + + #[inline(always)] + pub fn clear(&mut self) { + self.buf = [0; N]; + self.head = 0; + self.tail = 0; + } + + #[inline(always)] + pub fn push(&mut self, value: u8) -> Option<()> { + let (head, tail) = (self.head, self.tail); + let next_head = (head + 1) & self.mask; + + if next_head == tail { + return None; + } + + self.buf[head] = value; + self.head = next_head; + + Some(()) + } + + #[inline(always)] + pub fn pop(&mut self) -> Option { + let (head, mut tail) = (self.head, self.tail); + + if head == tail { + return None; + } + + let value = self.buf[tail]; + tail = (tail + 1) & self.mask; + self.tail = tail; + + Some(value) + } +} + +impl Iterator for RingBuffer { + type Item = u8; + + fn next(&mut self) -> Option { + self.pop() + } +} + +impl SoftSerialWriter> for HalfDuplexSerial

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

(data); + } + + fn write_bytes(&self, transmit_data: &mut RingBuffer) { + self.sync_transmitter(); + >>::write_byte(self, N as u8); + + for _ in 0..N { + let byte = transmit_data.pop().unwrap_or(0); + self.sync_transmitter(); + >>::write_byte(self, byte); + } + } +} + +impl SoftSerialReader> for HalfDuplexSerial

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

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