lc3_ensemble/sim/device/
display.rs1use std::sync::{Arc, RwLock, RwLockWriteGuard, TryLockError};
2
3use super::{DevWrapper, ExternalDevice, Interrupt, DDR, DSR};
4
5trait DisplayDevice: Send + Sync + 'static {
7 fn ready(&self) -> bool;
9 fn send_output(&mut self, byte: u8) -> bool;
11
12 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#[derive(Default, Clone)]
41pub struct BufferedDisplay {
42 buffer: Arc<RwLock<Vec<u8>>>
43}
44impl BufferedDisplay {
45 pub fn new(buffer: Arc<RwLock<Vec<u8>>>) -> Self {
47 Self { buffer }
48 }
49
50 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}