stm32f1_hal/common/dma/
circular_buffer_rx.rs1use super::*;
2#[cfg(not(feature = "std"))]
3use crate::common::os::*;
4
5pub struct DmaCircularBufferRx<T: Sized, CH> {
7 ch: CH,
8 buf: CircularBuffer<T>,
9}
10
11impl<T, CH> DmaCircularBufferRx<T, CH>
12where
13 T: Sized + Copy,
14 CH: DmaChannel,
15{
16 pub fn new(mut ch: CH, peripheral_addr: usize, buf_size: usize) -> Self {
17 let buf = CircularBuffer::<T>::new(buf_size);
18 ch.stop();
19 ch.set_memory_buf_for_peripheral(buf.as_slice());
20 ch.set_peripheral_address::<T>(peripheral_addr, false, false, true);
21 ch.start();
22 Self { ch, buf }
23 }
24
25 #[inline]
26 pub fn pop_slice(&mut self, max: usize) -> Option<&[T]> {
27 self.buf.pop_slice(self.ch.get_unprocessed_len(), max)
28 }
29}
30
31pub struct CircularBuffer<T> {
32 recv_buf: Vec<T>,
33 read_idx: usize,
34}
35
36impl<T: Sized + Copy> CircularBuffer<T> {
37 fn new(buf_size: usize) -> Self {
38 let mut recv_buf = Vec::<T>::with_capacity(buf_size);
39 #[allow(clippy::uninit_vec)]
40 unsafe {
41 recv_buf.set_len(buf_size)
42 }
43
44 Self {
45 recv_buf,
46 read_idx: 0,
47 }
48 }
49
50 fn pop_slice(&mut self, unprocessed_len: usize, max: usize) -> Option<&[T]> {
51 let dma_recv_idx = if unprocessed_len == 0 {
52 0
53 } else {
54 self.recv_buf.len() - unprocessed_len
55 };
56
57 if self.read_idx == dma_recv_idx {
58 return None;
59 }
60
61 let ret;
62 if dma_recv_idx < self.read_idx {
63 if max > self.recv_buf.len() - self.read_idx {
64 ret = Some(&self.recv_buf[self.read_idx..]);
65 self.read_idx = 0;
66 } else {
67 let end = self.read_idx + max;
68 ret = Some(&self.recv_buf[self.read_idx..end]);
69 self.read_idx = end;
70 }
71 } else if max > dma_recv_idx - self.read_idx {
72 ret = Some(&self.recv_buf[self.read_idx..dma_recv_idx]);
73 self.read_idx = dma_recv_idx;
74 } else {
75 let end = self.read_idx + max;
76 ret = Some(&self.recv_buf[self.read_idx..end]);
77 self.read_idx = end;
78 }
79 ret
80 }
81
82 fn as_slice(&self) -> &[T] {
83 self.recv_buf.as_slice()
84 }
85}
86
87#[cfg(test)]
88mod tests {
89 use super::*;
90
91 #[test]
92 fn circular_buffer() {
93 let buf_size = 13;
94 let mut buf = CircularBuffer::new(buf_size);
95 assert_eq!(buf.recv_buf.len(), buf_size);
96
97 for i in 0..buf_size {
98 buf.recv_buf[i] = i as u8;
99 }
100
101 assert_eq!(
102 buf.pop_slice(5, usize::MAX),
103 Some([0u8, 1, 2, 3, 4, 5, 6, 7].as_slice())
104 );
105 assert_eq!(buf.pop_slice(5, usize::MAX), None);
106 assert_eq!(
108 buf.pop_slice(0, usize::MAX),
109 Some([8u8, 9, 10, 11, 12].as_slice())
110 );
111 assert_eq!(buf.pop_slice(0, usize::MAX), None);
112 assert_eq!(buf.pop_slice(buf_size, usize::MAX), None);
113 assert_eq!(buf.pop_slice(5, 5), Some([0u8, 1, 2, 3, 4].as_slice()));
115 assert_eq!(buf.pop_slice(5, 5), Some([5u8, 6, 7].as_slice()));
116 assert_eq!(buf.pop_slice(5, 5), None);
117 assert_eq!(
118 buf.pop_slice(0, usize::MAX),
119 Some([8u8, 9, 10, 11, 12].as_slice())
120 );
121 assert_eq!(
123 buf.pop_slice(5, usize::MAX),
124 Some([0u8, 1, 2, 3, 4, 5, 6, 7].as_slice())
125 );
126 assert_eq!(
127 buf.pop_slice(10, usize::MAX),
128 Some([8u8, 9, 10, 11, 12].as_slice())
129 );
130 assert_eq!(buf.pop_slice(10, usize::MAX), Some([0u8, 1, 2].as_slice()));
131 assert_eq!(buf.pop_slice(10, usize::MAX), None);
132 }
133}