chip_8/
keypad.rs

1//! Keys and keypad
2
3use crate::errors::Chip8Error;
4use core::convert::TryFrom;
5use core::ops::{Index, IndexMut};
6
7/// Possible state for each key
8#[derive(Clone, Copy, Debug, PartialEq, Eq)]
9pub enum KeyState {
10    /// Key not pressed
11    NotPressed = 0,
12    /// Key pressed
13    Pressed = 1,
14}
15
16impl Default for KeyState {
17    #[must_use]
18    fn default() -> Self {
19        Self::NotPressed
20    }
21}
22
23/// Individual key on the [`Keypad`]
24#[repr(u8)]
25#[derive(Clone, Copy, Debug, PartialEq, Eq)]
26pub enum Key {
27    /// Key `0`
28    Key0 = 0x0,
29    /// Key `1`
30    Key1 = 0x1,
31    /// Key `2`
32    Key2 = 0x2,
33    /// Key `3`
34    Key3 = 0x3,
35    /// Key `4`
36    Key4 = 0x4,
37    /// Key `5`
38    Key5 = 0x5,
39    /// Key `6`
40    Key6 = 0x6,
41    /// Key `7`
42    Key7 = 0x7,
43    /// Key `8`
44    Key8 = 0x8,
45    /// Key `9`
46    Key9 = 0x9,
47    /// Key `A`
48    KeyA = 0xA,
49    /// Key `B`
50    KeyB = 0xB,
51    /// Key `C`
52    KeyC = 0xC,
53    /// Key `D`
54    KeyD = 0xD,
55    /// Key `E`
56    KeyE = 0xE,
57    /// Key `F`
58    KeyF = 0xF,
59}
60
61impl TryFrom<u8> for Key {
62    type Error = Chip8Error;
63
64    fn try_from(value: u8) -> Result<Self, Self::Error> {
65        match value {
66            0x0 => Ok(Self::Key0),
67            0x1 => Ok(Self::Key1),
68            0x2 => Ok(Self::Key2),
69            0x3 => Ok(Self::Key3),
70            0x4 => Ok(Self::Key4),
71            0x5 => Ok(Self::Key5),
72            0x6 => Ok(Self::Key6),
73            0x7 => Ok(Self::Key7),
74            0x8 => Ok(Self::Key8),
75            0x9 => Ok(Self::Key9),
76            0xA => Ok(Self::KeyA),
77            0xB => Ok(Self::KeyB),
78            0xC => Ok(Self::KeyC),
79            0xD => Ok(Self::KeyD),
80            0xE => Ok(Self::KeyE),
81            0xF => Ok(Self::KeyF),
82
83            _ => Err(Chip8Error::InvalidKey(value)),
84        }
85    }
86}
87
88/// 16-key hexadecimal keypad
89///
90/// # Key layout
91// table without thead requires html
92/// <table>
93///     <tr>
94///         <td>1
95///         <td>2
96///         <td>3
97///         <td>C
98///     <tr>
99///         <td>4
100///         <td>5
101///         <td>6
102///         <td>D
103///     <tr>
104///         <td>7
105///         <td>8
106///         <td>9
107///         <td>E
108///     <tr>
109///         <td>A
110///         <td>0
111///         <td>B
112///         <td>F
113/// </table>
114#[derive(Clone, Copy, Debug, PartialEq, Eq)]
115pub struct Keypad {
116    state: [KeyState; 16],
117}
118
119impl Keypad {
120    /// Creates a new instance with default state for each key
121    #[must_use]
122    pub fn new() -> Self {
123        Self {
124            state: [KeyState::default(); 16],
125        }
126    }
127}
128
129impl Index<Key> for Keypad {
130    type Output = KeyState;
131
132    #[must_use]
133    fn index(&self, index: Key) -> &Self::Output {
134        &self.state[index as usize]
135    }
136}
137
138impl IndexMut<Key> for Keypad {
139    #[must_use]
140    fn index_mut(&mut self, index: Key) -> &mut Self::Output {
141        &mut self.state[index as usize]
142    }
143}
144
145impl Default for Keypad {
146    #[must_use]
147    fn default() -> Self {
148        Self::new()
149    }
150}
151
152#[cfg(test)]
153mod tests {
154    use super::*;
155
156    #[test]
157    fn keypad_default() {
158        use super::{Key::*, KeyState::*};
159
160        let keypad = Keypad::default();
161
162        assert_eq!(keypad[Key0], NotPressed);
163        assert_eq!(keypad[Key1], NotPressed);
164        assert_eq!(keypad[Key2], NotPressed);
165        assert_eq!(keypad[Key3], NotPressed);
166        assert_eq!(keypad[Key4], NotPressed);
167        assert_eq!(keypad[Key5], NotPressed);
168        assert_eq!(keypad[Key6], NotPressed);
169        assert_eq!(keypad[Key7], NotPressed);
170        assert_eq!(keypad[Key8], NotPressed);
171        assert_eq!(keypad[Key9], NotPressed);
172        assert_eq!(keypad[KeyA], NotPressed);
173        assert_eq!(keypad[KeyB], NotPressed);
174        assert_eq!(keypad[KeyC], NotPressed);
175        assert_eq!(keypad[KeyD], NotPressed);
176        assert_eq!(keypad[KeyE], NotPressed);
177        assert_eq!(keypad[KeyF], NotPressed);
178    }
179}