spectrusty_peripherals/mouse/
kempston.rs1#[cfg(feature = "snapshot")]
10use serde::{Serialize, Deserialize};
11
12use super::{MouseInterface, MouseDevice, MouseMovement, MouseButtons};
13const RIGHT_BTN_MASK: u8 = 0b0000_0001;
19const LEFT_BTN_MASK: u8 = 0b0000_0010;
20const MIDDLE_BTN_MASK: u8 = 0b0000_0100; const UNUSED_BTN_MASK: u8 = !(MIDDLE_BTN_MASK|LEFT_BTN_MASK|RIGHT_BTN_MASK);
22
23const PORT_BTN_MASK: u16 = 0b0000_0001_0000_0000;
24const PORT_BTN_BITS: u16 = 0b0000_0000_0000_0000;
25const PORT_POS_MASK: u16 = 0b0000_0101_0000_0000;
26const PORT_X_BITS: u16 = 0b0000_0001_0000_0000;
27const PORT_Y_BITS: u16 = 0b0000_0101_0000_0000;
28
29#[derive(Clone, Copy, Debug)]
42#[cfg_attr(feature = "snapshot", derive(Serialize, Deserialize))]
43#[cfg_attr(feature = "snapshot", serde(rename_all = "camelCase"))]
44pub struct KempstonMouseDevice {
45 #[cfg_attr(feature = "snapshot", serde(skip, default = "u8::max_value"))]
46 data_btn: u8,
47 data_x: u8,
48 data_y: u8,
49 #[cfg_attr(feature = "snapshot", serde(skip))]
50 buttons: MouseButtons,
51}
52
53impl Default for KempstonMouseDevice {
54 fn default() -> Self {
55 KempstonMouseDevice {
56 data_btn: !0,
57 data_x: !0,
58 data_y: !0,
59 buttons: Default::default(),
60 }
61 }
62}
63
64impl MouseDevice for KempstonMouseDevice {
65 #[inline]
66 fn port_read(&self, port: u16) -> u8 {
67 if port & PORT_BTN_MASK == PORT_BTN_BITS {
68 self.data_btn
69 }
70 else {
71 match port & PORT_POS_MASK {
72 PORT_X_BITS => self.data_x,
73 PORT_Y_BITS => self.data_y,
74 _ => unsafe { core::hint::unreachable_unchecked() }
75 }
76 }
77 }
78}
79
80impl MouseInterface for KempstonMouseDevice {
81 #[inline]
82 fn set_buttons(&mut self, buttons: MouseButtons) {
83 self.buttons = buttons;
84 self.data_btn = (self.data_btn & UNUSED_BTN_MASK) |
85 if buttons.intersects(MouseButtons::RIGHT) { 0 } else { RIGHT_BTN_MASK } |
86 if buttons.intersects(MouseButtons::LEFT) { 0 } else { LEFT_BTN_MASK } |
87 if buttons.intersects(MouseButtons::MIDDLE) { 0 } else { MIDDLE_BTN_MASK };
88 }
89 #[inline]
90 fn get_buttons(&self) -> MouseButtons {
91 self.buttons
92 }
93 #[inline]
94 fn move_mouse(&mut self, movement: MouseMovement) {
95 self.data_x = clamped_move(self.data_x, movement.horizontal);
96 self.data_y = clamped_move(self.data_y, -movement.vertical);
97 }
98}
99
100#[inline(always)]
101fn clamped_move(prev: u8, mut delta: i16) -> u8 {
102 delta >>= 1;
103 if delta < i8::min_value().into() {
104 delta = i8::min_value().into();
105 }
106 else if delta > i8::max_value().into() {
107 delta = i8::max_value().into();
108 }
109 prev.wrapping_add(delta as u8)
110}