summaryrefslogtreecommitdiff
path: root/src/devices/system_device.rs
blob: 097c616e44951e74b301b2c2d00d2f5651959f68 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
use crate::*;


pub struct SystemDevice {
    /// Name and version of this system.
    pub name: StringBuffer,
    /// Authors of this system.
    pub authors: StringBuffer,
    /// Mask of all devices permitted to wake from sleep.
    pub wake_mask: u16,
    /// Slot number of device that most recently woke the system.
    pub wake_slot: u8,
    /// True if the system has been put to sleep.
    pub asleep: bool,
    /// Mask of all connected devices.
    pub connected_devices: u16,
    /// Name of the first custom device.
    pub custom1: StringBuffer,
    /// Name of the second custom device.
    pub custom2: StringBuffer,
    /// Name of the third custom device.
    pub custom3: StringBuffer,
    /// Name of the fourth custom device.
    pub custom4: StringBuffer,
}


impl Device for SystemDevice {
    fn read(&mut self, port: u8) -> u8 {
        match port {
            0x0 => 0x00,
            0x1 => 0x00,
            0x2 => self.wake_slot,
            0x3 => 0x00,
            0x4 => self.custom1.read(),
            0x5 => self.custom2.read(),
            0x6 => self.custom3.read(),
            0x7 => self.custom4.read(),
            0x8 => self.name.read(),
            0x9 => self.authors.read(),
            0xA => 0x00,
            0xB => 0x00,
            0xC => 0x00,
            0xD => 0x00,
            0xE => read_h!(self.connected_devices),
            0xF => read_l!(self.connected_devices),
            _ => unreachable!(),
        }
    }

    fn write(&mut self, port: u8, value: u8) -> Option<Signal> {
        match port {
            0x0 => write_h!(self.wake_mask, value),
            0x1 => {
                write_l!(self.wake_mask, value);
                self.asleep = true;
                return Some(Signal::Sleep);
            }
            0x2 =>  (),
            0x3 => match value {
                0 => return Some(Signal::Reset),
                _ => return Some(Signal::Fork),
            }
            0x4 => self.custom1.restart(),
            0x5 => self.custom2.restart(),
            0x6 => self.custom3.restart(),
            0x7 => self.custom4.restart(),
            0x8 => self.name.restart(),
            0x9 => self.authors.restart(),
            0xA => (),
            0xB => (),
            0xC => (),
            0xD => (),
            0xE => (),
            0xF => (),
            _ => unreachable!(),
        };
        return None;
    }

    fn wake(&mut self) -> bool {
        true
    }

    fn reset(&mut self) {
        self.wake_mask = 0;
        self.wake_slot = 0;
        self.custom1.restart();
        self.custom2.restart();
        self.custom3.restart();
        self.custom4.restart();
        self.name.restart();
        self.authors.restart();
    }
}


impl SystemDevice {
    pub fn new(connected_devices: u16) -> Self {
        let pkg_name = env!("CARGO_PKG_NAME");
        let pkg_version = env!("CARGO_PKG_VERSION");
        let pkg_authors = env!("CARGO_PKG_AUTHORS");
        let name = format!("{pkg_name}/{pkg_version}");
        let authors = pkg_authors.replace(':', "\n");

        Self {
            name: StringBuffer::from_str(&name),
            authors: StringBuffer::from_str(&authors),
            wake_mask: 0,
            wake_slot: 0,
            asleep: false,
            connected_devices,
            custom1: StringBuffer::new(),
            custom2: StringBuffer::new(),
            custom3: StringBuffer::new(),
            custom4: StringBuffer::new(),
        }
    }
}