pudding_pac/
fifo.rs

1use core::ptr;
2
3pub struct Fifo {
4    buf_size: u32,
5    tx_ptr: u32,
6    rx_ptr: u32,
7    buf: [u8; 1],
8}
9
10impl Fifo {
11    pub fn reset(&mut self, size: isize) {
12        let buf_size = (size - 4 * 3) as u32;
13        unsafe {
14            ptr::write_volatile(&mut self.buf_size, 0);
15            ptr::write_volatile(&mut self.tx_ptr, 0);
16            ptr::write_volatile(&mut self.rx_ptr, 0);
17            ptr::write_volatile(&mut self.buf_size, buf_size);
18        }
19    }
20
21    pub fn send_char(&mut self, c: u8) -> bool {
22        unsafe {
23            let rx_ptr = ptr::read_volatile(&self.rx_ptr);
24            let tx_ptr = ptr::read_volatile(&self.tx_ptr as *const u32);
25            let buf = &mut self.buf[0] as *mut u8;
26            let next_ptr = if tx_ptr + 1 < self.buf_size {
27                tx_ptr + 1
28            } else {
29                0
30            };
31            if next_ptr != rx_ptr {
32                ptr::write_volatile(buf.offset(tx_ptr as isize), c);
33                ptr::write_volatile(&mut self.tx_ptr, next_ptr);
34                true
35            } else {
36                false
37            }
38        }
39    }
40
41    pub fn recv_char(&mut self) -> Option<u8> {
42        unsafe {
43            let tx_ptr = ptr::read_volatile(&self.tx_ptr as *const u32);
44            let rx_ptr = ptr::read_volatile(&self.rx_ptr as *const u32);
45            let buf = &self.buf[0] as *const u8;
46            if tx_ptr != rx_ptr {
47                let c = ptr::read_volatile(buf.offset(rx_ptr as isize));
48                let next_ptr = if rx_ptr + 1 < self.buf_size {
49                    rx_ptr + 1
50                } else {
51                    0
52                };
53                ptr::write_volatile(&mut self.rx_ptr as *mut u32, next_ptr);
54                Some(c)
55            } else {
56                None
57            }
58        }
59    }
60}
61
62#[cfg(test)]
63mod tests {
64    use super::*;
65
66    #[test]
67    fn fifo_test() {
68        let mut mem: [u8; 256] = [0; 256];
69        let ptr = &mut mem as *mut u8;
70        unsafe {
71            let fifo = &mut *(ptr as *mut Fifo);
72            fifo.buf_size = 3;
73            fifo.tx_ptr = 0;
74            fifo.rx_ptr = 0;
75            assert_eq!(fifo.recv_char(), None);
76            assert_eq!(fifo.send_char('a' as u8), true);
77            assert_eq!(fifo.send_char('b' as u8), true);
78            assert_eq!(fifo.send_char('c' as u8), false);
79            assert_eq!(fifo.recv_char().unwrap(), 'a' as u8);
80            assert_eq!(fifo.send_char('c' as u8), true);
81            assert_eq!(fifo.send_char('d' as u8), false);
82            assert_eq!(fifo.recv_char().unwrap(), 'b' as u8);
83            assert_eq!(fifo.recv_char().unwrap(), 'c' as u8);
84            assert_eq!(fifo.recv_char(), None);
85        }
86    }
87}