Skip to main content

cardinal_varvara/
controller.rs

1pub use crate::controller_device::ControllerDevice;
2
3use crate::{Event, EventData};
4use std::{collections::HashSet, mem::offset_of};
5use uxn::{Ports, Uxn};
6use zerocopy::{BigEndian, U16};
7
8/// Helper to map pedal bits to controller key events
9pub fn inject_pedal_keys(controller: &mut Controller, vm: &mut Uxn, prev: u8, pedal: u8) {
10    let pedal_map = [
11        (0, Key::Shift),
12        (1, Key::Ctrl),
13        (2, Key::Alt),
14        (3, Key::Home),
15        (4, Key::Up),
16        (5, Key::Down),
17        (6, Key::Left),
18        (7, Key::Right),
19    ];
20    for (bit, key) in pedal_map.iter() {
21        let was_down = (prev & (1 << bit)) != 0;
22        let is_down = (pedal & (1 << bit)) != 0;
23        if !was_down && is_down {
24            controller.pressed(vm, *key, false);
25        } else if was_down && !is_down {
26            controller.released(vm, *key);
27        }
28    }
29}
30
31#[derive(zerocopy::FromBytes, zerocopy::IntoBytes, zerocopy::Immutable, zerocopy::KnownLayout)]
32#[repr(C)]
33/// Controller port mappings for the Varvara system.
34pub struct ControllerPorts {
35    /// The vector address for controller events.
36    pub vector: U16<BigEndian>,
37    /// The button state.
38    pub button: u8,
39    /// The key code.
40    pub key: u8,
41    /// Padding bytes.
42    pub _pad: [u8; 12],
43}
44
45impl Ports for ControllerPorts {
46    const BASE: u8 = 0x80;
47}
48
49impl ControllerPorts {
50    /// Offset for the key field in the controller port.
51    pub const KEY: u8 = Self::BASE | offset_of!(Self, key) as u8;
52}
53
54#[derive(Default)]
55/// Main controller device for the Varvara system.
56pub struct Controller {
57    /// Keys that are currently held down
58    pub down: HashSet<Key>,
59
60    /// Current button state
61    pub buttons: u8,
62}
63
64/// Key input to the controller device
65#[allow(missing_docs)]
66#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
67pub enum Key {
68    Shift,
69    Ctrl,
70    Alt,
71    Up,
72    Down,
73    Left,
74    Right,
75    Home,
76    End,
77    Char(u8),
78}
79
80impl Controller {
81    /// Builds a new controller with no keys held
82    pub fn new() -> Self {
83        Self::default()
84    }
85
86    /// Sends a single character event
87    pub fn char(&mut self, vm: &mut Uxn, c: u8) -> Event {
88        let p = vm.dev::<ControllerPorts>();
89        let event = Event {
90            vector: p.vector.get(),
91            data: Some(EventData {
92                addr: ControllerPorts::KEY,
93                value: c,
94                clear: true,
95            }),
96        };
97        println!(
98            "[og CONTROLLER][char] char: '{}' (0x{:02x}), vector: 0x{:04x}, addr: 0x{:02x}",
99            c as char,
100            c,
101            event.vector,
102            ControllerPorts::KEY
103        );
104        event
105    }
106
107    /// Send the given key event, returning an event if needed
108    pub fn pressed(&mut self, vm: &mut Uxn, k: Key, repeat: bool) -> Option<Event> {
109        if let Key::Char(k) = k {
110            Some(self.char(vm, k))
111        } else {
112            self.down.insert(k);
113            self.check_buttons(vm, repeat)
114        }
115    }
116
117    /// Indicate that the given key has been released
118    ///
119    /// This may change our button state and return an event
120    pub fn released(&mut self, vm: &mut Uxn, k: Key) -> Option<Event> {
121        if !matches!(k, Key::Char(..)) {
122            self.down.remove(&k);
123            self.check_buttons(vm, false)
124        } else {
125            None
126        }
127    }
128
129    /// Checks the current button states and returns an event if any button state changed.
130    pub fn check_buttons(&mut self, vm: &mut Uxn, repeat: bool) -> Option<Event> {
131        let mut buttons = 0;
132        for (i, k) in [
133            Key::Ctrl,
134            Key::Alt,
135            Key::Shift,
136            Key::Home,
137            Key::Up,
138            Key::Down,
139            Key::Left,
140            Key::Right,
141        ]
142        .iter()
143        .enumerate()
144        {
145            if self.down.contains(k) {
146                buttons |= 1 << i;
147            }
148        }
149
150        // We'll return this event in case we don't have a keypress event;
151        // otherwise, the keypress event will call the vector (at least once)
152        if buttons != self.buttons || repeat {
153            let p = vm.dev_mut::<ControllerPorts>();
154            self.buttons = buttons;
155            p.button = buttons;
156            Some(Event {
157                vector: p.vector.get(),
158                data: None,
159            })
160        } else {
161            None
162        }
163    }
164}