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}