lc3_ensemble/sim/device/
display.rs

1use std::sync::{Arc, RwLock, RwLockWriteGuard, TryLockError};
2
3use super::{DevWrapper, ExternalDevice, Interrupt, DDR, DSR};
4
5/// Scaffolding required to implement [`ExternalDevice`] for display devices.
6trait DisplayDevice: Send + Sync + 'static {
7    /// Whether the display is ready to take output.
8    fn ready(&self) -> bool;
9    /// Sends output, returns whether the output was successfully accepted.
10    fn send_output(&mut self, byte: u8) -> bool;
11
12    /// Clears all of the current output.
13    fn clear_output(&mut self);
14}
15impl<D: DisplayDevice> ExternalDevice for DevWrapper<D, dyn DisplayDevice> {
16    fn io_read(&mut self, addr: u16, _effectful: bool) -> Option<u16> {
17        match addr {
18            DSR => Some(u16::from(self.ready()) << 15),
19            _   => None
20        }
21    }
22
23    fn io_write(&mut self, addr: u16, data: u16) -> bool {
24        match addr {
25            DDR => self.send_output(data as u8),
26            _ => false
27        }
28    }
29
30    fn io_reset(&mut self) {
31        self.clear_output();
32    }
33
34    fn poll_interrupt(&mut self) -> Option<Interrupt> {
35        None
36    }
37}
38
39/// A display that delegates its output to a buffer.
40#[derive(Default, Clone)]
41pub struct BufferedDisplay {
42    buffer: Arc<RwLock<Vec<u8>>>
43}
44impl BufferedDisplay {
45    /// Creates a new display, wrapping it around a given buffer.
46    pub fn new(buffer: Arc<RwLock<Vec<u8>>>) -> Self {
47        Self { buffer }
48    }
49
50    /// Gets a reference to the internal buffer of this display.
51    pub fn get_buffer(&self) -> &Arc<RwLock<Vec<u8>>> {
52        &self.buffer
53    }
54
55    fn try_output(&self) -> Option<RwLockWriteGuard<'_, Vec<u8>>> {
56        match self.buffer.try_write() {
57            Ok(g) => Some(g),
58            Err(TryLockError::Poisoned(e)) => Some(e.into_inner()),
59            Err(TryLockError::WouldBlock) => None,
60        }
61    }
62}
63impl DisplayDevice for BufferedDisplay {
64    fn ready(&self) -> bool {
65        self.try_output().is_some()
66    }
67
68    fn send_output(&mut self, byte: u8) -> bool {
69        match self.try_output() {
70            Some(mut d) => {
71                d.push(byte);
72                true
73            },
74            None => false,
75        }
76    }
77    
78    fn clear_output(&mut self) {
79        if let Some(mut out) = self.try_output() {
80            out.clear();
81        }
82    }
83}
84impl ExternalDevice for BufferedDisplay {
85    fn io_read(&mut self, addr: u16, effectful: bool) -> Option<u16> {
86        DevWrapper::wrap(self).io_read(addr, effectful)
87    }
88
89    fn io_write(&mut self, addr: u16, data: u16) -> bool {
90        DevWrapper::wrap(self).io_write(addr, data)
91    }
92
93    fn io_reset(&mut self) {
94        DevWrapper::wrap(self).io_reset();
95    }
96
97    fn poll_interrupt(&mut self) -> Option<Interrupt> {
98        DevWrapper::wrap(self).poll_interrupt()
99    }
100    
101    fn _to_sim_device(self, _: super::internals::ToSimDeviceToken) -> super::internals::SimDevice
102        where Self: Sized
103    {
104        super::internals::SimDevice::Display(self)
105    }
106}