pros_simulator/host/
controllers.rs

1use std::mem;
2
3use pros_simulator_interface::{ControllerState, DigitalControllerState};
4use pros_sys::{
5    misc::E_CONTROLLER_DIGITAL_R1, EINVAL, E_CONTROLLER_ANALOG_LEFT_X, E_CONTROLLER_ANALOG_LEFT_Y,
6    E_CONTROLLER_ANALOG_RIGHT_X, E_CONTROLLER_ANALOG_RIGHT_Y, E_CONTROLLER_DIGITAL_A,
7    E_CONTROLLER_DIGITAL_B, E_CONTROLLER_DIGITAL_DOWN, E_CONTROLLER_DIGITAL_L1,
8    E_CONTROLLER_DIGITAL_L2, E_CONTROLLER_DIGITAL_LEFT, E_CONTROLLER_DIGITAL_R2,
9    E_CONTROLLER_DIGITAL_RIGHT, E_CONTROLLER_DIGITAL_UP, E_CONTROLLER_DIGITAL_X,
10    E_CONTROLLER_DIGITAL_Y, E_CONTROLLER_MASTER, E_CONTROLLER_PARTNER,
11};
12struct Controller {
13    state: ControllerState,
14    new_presses: DigitalControllerState,
15}
16
17impl From<ControllerState> for Controller {
18    fn from(state: ControllerState) -> Self {
19        Self {
20            new_presses: state.digital.clone(),
21            state,
22        }
23    }
24}
25
26impl Controller {
27    /// Update controller state and set new press values to true if either it is currently true or it has changed to true.
28    pub fn update(&mut self, state: ControllerState) {
29        self.new_presses = DigitalControllerState {
30            l1: (state.digital.l1 && !self.state.digital.l1) || self.new_presses.l1,
31            l2: (state.digital.l2 && !self.state.digital.l2) || self.new_presses.l2,
32            r1: (state.digital.r1 && !self.state.digital.r1) || self.new_presses.r1,
33            r2: (state.digital.r2 && !self.state.digital.r2) || self.new_presses.r2,
34            up: (state.digital.up && !self.state.digital.up) || self.new_presses.up,
35            down: (state.digital.down && !self.state.digital.down) || self.new_presses.down,
36            left: (state.digital.left && !self.state.digital.left) || self.new_presses.left,
37            right: (state.digital.right && !self.state.digital.right) || self.new_presses.right,
38            x: (state.digital.x && !self.state.digital.x) || self.new_presses.x,
39            b: (state.digital.b && !self.state.digital.b) || self.new_presses.b,
40            y: (state.digital.y && !self.state.digital.y) || self.new_presses.y,
41            a: (state.digital.a && !self.state.digital.a) || self.new_presses.a,
42        };
43        self.state = state;
44    }
45}
46
47/// Stores state of VEX V5 master and partner controllers.
48pub struct Controllers {
49    master: Option<Controller>,
50    partner: Option<Controller>,
51}
52
53impl Controllers {
54    pub fn new(master: Option<ControllerState>, partner: Option<ControllerState>) -> Self {
55        Self {
56            master: master.map(|v| v.into()),
57            partner: partner.map(|v| v.into()),
58        }
59    }
60
61    /// Update state of both controllers and set new press values.
62    pub fn update(
63        &mut self,
64        new_master: Option<ControllerState>,
65        new_partner: Option<ControllerState>,
66    ) {
67        if let Some(new_master) = new_master {
68            if let Some(master) = &mut self.master {
69                master.update(new_master);
70            } else {
71                self.master = Some(new_master.into());
72            }
73        }
74        if let Some(new_partner) = new_partner {
75            if let Some(partner) = &mut self.partner {
76                partner.update(new_partner);
77            } else {
78                self.partner = Some(new_partner.into());
79            }
80        }
81    }
82
83    pub fn is_connected(&self, controller_id: u32) -> Result<bool, i32> {
84        match controller_id {
85            E_CONTROLLER_MASTER => Ok(self.master.is_some()),
86            E_CONTROLLER_PARTNER => Ok(self.partner.is_some()),
87            _ => Err(EINVAL),
88        }
89    }
90
91    /// Get the state of a controller by ID. Fails with EINVAL if the controller ID is invalid.
92    fn get_controller_state(&self, controller_id: u32) -> Result<Option<&Controller>, i32> {
93        match controller_id {
94            E_CONTROLLER_MASTER => Ok(self.master.as_ref()),
95            E_CONTROLLER_PARTNER => Ok(self.partner.as_ref()),
96            _ => Err(EINVAL),
97        }
98    }
99
100    /// Get the state of a controller by ID. Fails with EINVAL if the controller ID is invalid.
101    fn get_controller_state_mut(
102        &mut self,
103        controller_id: u32,
104    ) -> Result<Option<&mut Controller>, i32> {
105        match controller_id {
106            E_CONTROLLER_MASTER => Ok(self.master.as_mut()),
107            E_CONTROLLER_PARTNER => Ok(self.partner.as_mut()),
108            _ => Err(EINVAL),
109        }
110    }
111
112    /// Returns the current state of a specific analog channel (joystick) on a specific controller.
113    ///
114    /// This function retrieves the current state of a given analog channel (joystick) on a specific controller.
115    /// The state is represented as a integer value in the range [-127, 127] where -127 is full down or left,
116    /// and 127 is full up or right.
117    ///
118    /// # Arguments
119    ///
120    /// * `controller_id` - A u32 that holds the ID of the controller.
121    /// * `channel` - A u32 that represents the axis whose state is to be retrieved.
122    ///
123    /// # Returns
124    ///
125    /// * `Ok(i32)` - If the controller and button exist, returns the state of the axis.
126    /// * `Err(i32)` - If the controller or button does not exist, returns an error with the code `EINVAL`.
127    ///
128    /// # Example
129    ///
130    /// ```
131    /// if controllers.get_analog(pros_sys::E_CONTROLLER_MASTER, pros_sys::E_CONTROLLER_ANALOG_LEFT_X)? > 0 {
132    ///     println!("Left joystick is pushed right")
133    /// }
134    /// ```
135    pub fn get_analog(&self, controller_id: u32, channel: u32) -> Result<i32, i32> {
136        let controller = self.get_controller_state(controller_id)?;
137        if let Some(Controller { state, .. }) = controller {
138            match channel {
139                E_CONTROLLER_ANALOG_LEFT_X => Ok(state.analog.left_x),
140                E_CONTROLLER_ANALOG_LEFT_Y => Ok(state.analog.left_y),
141                E_CONTROLLER_ANALOG_RIGHT_X => Ok(state.analog.right_x),
142                E_CONTROLLER_ANALOG_RIGHT_Y => Ok(state.analog.right_y),
143                _ => Err(EINVAL),
144            }
145        } else {
146            Ok(0)
147        }
148        .map(|v| v as i32)
149    }
150
151    /// Returns the current state of a specific button on a specific controller.
152    ///
153    /// This function retrieves the current state of a given button on a specific controller.
154    /// The state is represented as a boolean value, where `true` indicates that the button is currently pressed,
155    /// and `false` indicates that it is not.
156    ///
157    /// # Arguments
158    ///
159    /// * `controller_id` - A u32 that holds the ID of the controller.
160    /// * `button` - A u32 that represents the button whose state is to be retrieved.
161    ///
162    /// # Returns
163    ///
164    /// * `Ok(bool)` - If the controller and button exist, returns a boolean indicating whether the button is currently pressed.
165    /// * `Err(i32)` - If the controller or button does not exist, returns an error with the code `EINVAL`.
166    ///
167    /// # Example
168    ///
169    /// ```
170    /// if controllers.get_digital(pros_sys::E_CONTROLLER_MASTER, pros_sys::E_CONTROLLER_DIGITAL_X)? {
171    ///     println!("Button X pressed")
172    /// }
173    /// ```
174    pub fn get_digital(&self, controller_id: u32, button: u32) -> Result<bool, i32> {
175        let controller = self.get_controller_state(controller_id)?;
176        if let Some(Controller { state, .. }) = controller {
177            match button {
178                E_CONTROLLER_DIGITAL_L1 => Ok(state.digital.l1),
179                E_CONTROLLER_DIGITAL_L2 => Ok(state.digital.l2),
180                E_CONTROLLER_DIGITAL_R1 => Ok(state.digital.r1),
181                E_CONTROLLER_DIGITAL_R2 => Ok(state.digital.r2),
182                E_CONTROLLER_DIGITAL_UP => Ok(state.digital.up),
183                E_CONTROLLER_DIGITAL_DOWN => Ok(state.digital.down),
184                E_CONTROLLER_DIGITAL_LEFT => Ok(state.digital.left),
185                E_CONTROLLER_DIGITAL_RIGHT => Ok(state.digital.right),
186                E_CONTROLLER_DIGITAL_X => Ok(state.digital.x),
187                E_CONTROLLER_DIGITAL_B => Ok(state.digital.b),
188                E_CONTROLLER_DIGITAL_Y => Ok(state.digital.y),
189                E_CONTROLLER_DIGITAL_A => Ok(state.digital.a),
190                _ => Err(EINVAL),
191            }
192        } else {
193            Ok(false)
194        }
195    }
196
197    /// Returns whether a new press event occurred for a specific button on a specific controller.
198    ///
199    /// This function checks if a new press event has occurred for a given button on a specific controller.
200    /// If a new press event has occurred, it returns `true` and resets the state to `false`.
201    /// If no new press event has occurred, it returns `false`.
202    /// If the controller or button does not exist, it returns an error.
203    ///
204    /// State is shared between tasks so to get notified on every change it's best to always call this from
205    /// the same task.
206    ///
207    /// # Arguments
208    ///
209    /// * `controller_id` - A u32 that holds the ID of the controller.
210    /// * `button` - A u32 that represents the button to check for a new press event.
211    ///
212    /// # Returns
213    ///
214    /// * `Ok(bool)` - If the controller and button exist, returns whether a new press event has occurred.
215    /// * `Err(i32)` - If the controller or button does not exist, returns an error.
216    ///
217    /// # Example
218    ///
219    /// ```ignore
220    /// if controllers.get_digital_new_press(pros_sys::E_CONTROLLER_MASTER, pros_sys::E_CONTROLLER_DIGITAL_X)? {
221    ///     println!("Button X has been pressed since last call");
222    /// }
223    /// ```
224    pub fn get_digital_new_press(&mut self, controller_id: u32, button: u32) -> Result<bool, i32> {
225        let mut controller = self.get_controller_state_mut(controller_id)?;
226        if let Some(Controller { new_presses, .. }) = &mut controller {
227            let field = match button {
228                E_CONTROLLER_DIGITAL_L1 => Ok(&mut new_presses.l1),
229                E_CONTROLLER_DIGITAL_L2 => Ok(&mut new_presses.l2),
230                E_CONTROLLER_DIGITAL_R1 => Ok(&mut new_presses.r1),
231                E_CONTROLLER_DIGITAL_R2 => Ok(&mut new_presses.r2),
232                E_CONTROLLER_DIGITAL_UP => Ok(&mut new_presses.up),
233                E_CONTROLLER_DIGITAL_DOWN => Ok(&mut new_presses.down),
234                E_CONTROLLER_DIGITAL_LEFT => Ok(&mut new_presses.left),
235                E_CONTROLLER_DIGITAL_RIGHT => Ok(&mut new_presses.right),
236                E_CONTROLLER_DIGITAL_X => Ok(&mut new_presses.x),
237                E_CONTROLLER_DIGITAL_B => Ok(&mut new_presses.b),
238                E_CONTROLLER_DIGITAL_Y => Ok(&mut new_presses.y),
239                E_CONTROLLER_DIGITAL_A => Ok(&mut new_presses.a),
240                _ => Err(EINVAL),
241            }?;
242
243            Ok(mem::replace(field, false))
244        } else {
245            Ok(false)
246        }
247    }
248}