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