spectrusty_peripherals/joystick/
sinclair.rs1use core::fmt::Debug;
10use core::marker::PhantomData;
11use super::{JoystickDevice, Directions, JoystickInterface};
12const UNUSED_MASK: u8 = 0b1110_0000;
13
14#[derive(Clone, Copy, Debug)]
18pub struct SinclairJoystickDevice<S> {
19 data: u8,
20 directions: Directions,
21 _side: PhantomData<S>
22}
23
24pub trait SinclairJoyKeyMap: Debug {
25 const FIRE_MASK: u8;
26 const UP_MASK: u8;
27 const DOWN_MASK: u8;
28 const RIGHT_MASK: u8;
29 const LEFT_MASK: u8;
30}
31
32#[derive(Clone, Copy, Default, Debug)]
34pub struct SinclairJoyLeftMap;
35impl SinclairJoyKeyMap for SinclairJoyLeftMap {
36 const FIRE_MASK: u8 = 0b0001_0000;
39 const UP_MASK: u8 = 0b0000_1000;
40 const DOWN_MASK: u8 = 0b0000_0100;
41 const RIGHT_MASK: u8 = 0b0000_0010;
42 const LEFT_MASK: u8 = 0b0000_0001;
43}
44
45#[derive(Clone, Copy, Default, Debug)]
47pub struct SinclairJoyRightMap;
48impl SinclairJoyKeyMap for SinclairJoyRightMap {
49 const FIRE_MASK: u8 = 0b0000_0001;
52 const UP_MASK: u8 = 0b0000_0010;
53 const DOWN_MASK: u8 = 0b0000_0100;
54 const RIGHT_MASK: u8 = 0b0000_1000;
55 const LEFT_MASK: u8 = 0b0001_0000;
56}
57
58impl<S> Default for SinclairJoystickDevice<S> {
59 fn default() -> Self {
60 SinclairJoystickDevice {
61 data: !0,
62 directions: Directions::empty(),
63 _side: PhantomData
64 }
65 }
66}
67
68impl<S: Debug> JoystickDevice for SinclairJoystickDevice<S> {
69 #[inline]
70 fn port_read(&self, _port: u16) -> u8 {
71 self.data
72 }
73}
74
75impl<S> JoystickInterface for SinclairJoystickDevice<S>
76 where S: SinclairJoyKeyMap
77{
78 fn fire(&mut self, _btn: u8, pressed: bool) {
79 if pressed {
80 self.data &= !S::FIRE_MASK;
81 }
82 else {
83 self.data |= S::FIRE_MASK;
84 }
85 }
86
87 fn get_fire(&self, _btn: u8) -> bool {
88 self.data & S::FIRE_MASK == 0
89 }
90
91 fn set_directions(&mut self, dir: Directions) {
92 self.directions = dir;
93 self.data = (self.data & (S::FIRE_MASK|UNUSED_MASK)) |
94 if dir.intersects(Directions::UP) { 0 } else { S::UP_MASK } |
95 if dir.intersects(Directions::RIGHT) { 0 } else { S::RIGHT_MASK } |
96 if dir.intersects(Directions::DOWN) { 0 } else { S::DOWN_MASK } |
97 if dir.intersects(Directions::LEFT) { 0 } else { S::LEFT_MASK };
98 }
99
100 fn get_directions(&self) -> Directions {
101 self.directions
102 }
103}