1use alloc::collections::VecDeque;
4use core::{convert::TryInto, fmt, time::Duration};
5use slice_copy::copy;
6
7use crate::{
8 bindings,
9 error::{get_errno, Error},
10 io::eprintln,
11 rtos::{delay_until, queue, time_since_start, DataSource, SendQueue, Task},
12 select,
13};
14
15const SCREEN_SUCCESS_DELAY: Duration = Duration::from_millis(50);
16const SCREEN_FAILURE_DELAY: Duration = Duration::from_millis(5);
17
18pub struct Controller {
20 id: bindings::controller_id_e_t,
21 pub left_stick: AnalogStick,
23 pub right_stick: AnalogStick,
25 pub l1: Button,
27 pub l2: Button,
29 pub r1: Button,
31 pub r2: Button,
33 pub up: Button,
35 pub down: Button,
37 pub left: Button,
39 pub right: Button,
41 pub x: Button,
43 pub y: Button,
45 pub a: Button,
47 pub b: Button,
49 pub screen: Screen,
51}
52
53impl Controller {
54 pub unsafe fn new(id: ControllerId) -> Self {
62 let id: bindings::controller_id_e_t = id.into();
63 Controller {
64 id,
65 left_stick: AnalogStick {
66 id,
67 x_channel: bindings::controller_analog_e_t_E_CONTROLLER_ANALOG_LEFT_X,
68 y_channel: bindings::controller_analog_e_t_E_CONTROLLER_ANALOG_LEFT_Y,
69 },
70 right_stick: AnalogStick {
71 id,
72 x_channel: bindings::controller_analog_e_t_E_CONTROLLER_ANALOG_RIGHT_X,
73 y_channel: bindings::controller_analog_e_t_E_CONTROLLER_ANALOG_RIGHT_Y,
74 },
75 l1: Button {
76 id,
77 button: bindings::controller_digital_e_t_E_CONTROLLER_DIGITAL_L1,
78 },
79 l2: Button {
80 id,
81 button: bindings::controller_digital_e_t_E_CONTROLLER_DIGITAL_L2,
82 },
83 r1: Button {
84 id,
85 button: bindings::controller_digital_e_t_E_CONTROLLER_DIGITAL_R1,
86 },
87 r2: Button {
88 id,
89 button: bindings::controller_digital_e_t_E_CONTROLLER_DIGITAL_R2,
90 },
91 up: Button {
92 id,
93 button: bindings::controller_digital_e_t_E_CONTROLLER_DIGITAL_UP,
94 },
95 down: Button {
96 id,
97 button: bindings::controller_digital_e_t_E_CONTROLLER_DIGITAL_DOWN,
98 },
99 right: Button {
100 id,
101 button: bindings::controller_digital_e_t_E_CONTROLLER_DIGITAL_RIGHT,
102 },
103 left: Button {
104 id,
105 button: bindings::controller_digital_e_t_E_CONTROLLER_DIGITAL_LEFT,
106 },
107 x: Button {
108 id,
109 button: bindings::controller_digital_e_t_E_CONTROLLER_DIGITAL_X,
110 },
111 y: Button {
112 id,
113 button: bindings::controller_digital_e_t_E_CONTROLLER_DIGITAL_Y,
114 },
115 b: Button {
116 id,
117 button: bindings::controller_digital_e_t_E_CONTROLLER_DIGITAL_B,
118 },
119 a: Button {
120 id,
121 button: bindings::controller_digital_e_t_E_CONTROLLER_DIGITAL_A,
122 },
123 screen: Screen { id, queue: None },
124 }
125 }
126
127 pub fn is_connected(&self) -> Result<bool, ControllerError> {
129 match unsafe { bindings::controller_is_connected(self.id) } {
130 0 => Ok(false),
131 1 => Ok(true),
132 _ => Err(ControllerError::from_errno()),
133 }
134 }
135
136 pub fn get_battery_level(&self) -> Result<i32, ControllerError> {
138 match unsafe { bindings::controller_get_battery_level(self.id) } {
139 bindings::PROS_ERR_ => Err(ControllerError::from_errno()),
140 x => Ok(x),
141 }
142 }
143
144 pub fn get_battery_capacity(&self) -> Result<i32, ControllerError> {
146 match unsafe { bindings::controller_get_battery_capacity(self.id) } {
147 bindings::PROS_ERR_ => Err(ControllerError::from_errno()),
148 x => Ok(x),
149 }
150 }
151}
152
153impl fmt::Debug for Controller {
154 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
155 f.debug_struct("Controller").field("id", &self.id).finish()
156 }
157}
158
159impl DataSource for Controller {
160 type Data = ControllerData;
161
162 type Error = ControllerError;
163
164 fn read(&self) -> Result<Self::Data, Self::Error> {
165 Ok(ControllerData {
166 left_x: self.left_stick.get_x()?,
167 left_y: self.left_stick.get_y()?,
168 right_x: self.right_stick.get_x()?,
169 right_y: self.right_stick.get_y()?,
170 l1: self.l1.is_pressed()?,
171 l2: self.l2.is_pressed()?,
172 r1: self.r1.is_pressed()?,
173 r2: self.r2.is_pressed()?,
174 up: self.up.is_pressed()?,
175 down: self.down.is_pressed()?,
176 left: self.left.is_pressed()?,
177 right: self.right.is_pressed()?,
178 x: self.x.is_pressed()?,
179 y: self.y.is_pressed()?,
180 a: self.a.is_pressed()?,
181 b: self.b.is_pressed()?,
182 battery_level: self.get_battery_level()?,
183 battery_capacity: self.get_battery_capacity()?,
184 })
185 }
186}
187
188#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
189pub struct ControllerData {
191 pub left_x: i8,
193 pub left_y: i8,
195 pub right_x: i8,
197 pub right_y: i8,
199 pub l1: bool,
201 pub l2: bool,
203 pub r1: bool,
205 pub r2: bool,
207 pub up: bool,
209 pub down: bool,
211 pub left: bool,
213 pub right: bool,
215 pub x: bool,
217 pub y: bool,
219 pub a: bool,
221 pub b: bool,
223 pub battery_level: i32,
225 pub battery_capacity: i32,
227}
228
229pub struct AnalogStick {
231 id: bindings::controller_id_e_t,
232 x_channel: bindings::controller_analog_e_t,
233 y_channel: bindings::controller_analog_e_t,
234}
235
236impl AnalogStick {
237 pub fn get_x(&self) -> Result<i8, ControllerError> {
241 self.get_channel(self.x_channel)
242 }
243
244 pub fn get_y(&self) -> Result<i8, ControllerError> {
248 self.get_channel(self.y_channel)
249 }
250
251 fn get_channel(&self, channel: bindings::controller_analog_e_t) -> Result<i8, ControllerError> {
252 match unsafe { bindings::controller_get_analog(self.id, channel) } {
253 bindings::PROS_ERR_ => Err(ControllerError::from_errno()),
254 x => match x.try_into() {
255 Ok(converted_x) => Ok(converted_x),
256 Err(_) => {
257 panic!(
258 "bindings::controller_get_analog returned unexpected value: {}",
259 x
260 )
261 }
262 },
263 }
264 }
265}
266
267pub struct Button {
269 id: bindings::controller_id_e_t,
270 button: bindings::controller_digital_e_t,
271}
272
273impl Button {
274 pub fn is_pressed(&self) -> Result<bool, ControllerError> {
277 match unsafe { bindings::controller_get_digital(self.id, self.button) } {
278 0 => Ok(false),
279 1 => Ok(true),
280 _ => Err(ControllerError::from_errno()),
281 }
282 }
283}
284
285pub struct Screen {
287 id: bindings::controller_id_e_t,
288 queue: Option<SendQueue<ScreenCommand>>,
289}
290
291impl Screen {
292 pub fn clear(&mut self) {
294 self.command(ScreenCommand::Clear);
295 }
296
297 pub fn clear_line(&mut self, line: u8) {
300 if line > 2 {
301 return;
302 }
303 self.command(ScreenCommand::ClearLine(line));
304 }
305
306 pub fn print(&mut self, line: u8, column: u8, str: &str) {
309 if line > 2 || column > 18 {
310 return;
311 }
312 let mut chars: [libc::c_char; 19] = Default::default();
313 copy(&mut chars, str.as_bytes());
314 self.command(ScreenCommand::Print {
315 chars,
316 line,
317 column,
318 length: str.as_bytes().len() as u8,
319 });
320 }
321
322 pub fn rumble(&mut self, rumble_pattern: &str) {
327 let mut pattern: [libc::c_char; 8] = Default::default();
328 let mut i = 0;
329 for c in rumble_pattern.chars() {
330 match c {
331 '.' | '-' | '_' => {
332 pattern[i] = c as libc::c_char;
333 i += 1;
334 }
335 _ => {}
336 }
337 if i >= pattern.len() {
338 break;
339 }
340 }
341 self.command(ScreenCommand::Rumble(pattern));
342 }
343
344 fn command(&mut self, cmd: ScreenCommand) {
345 self.queue().send(cmd);
346 }
347
348 fn queue(&mut self) -> &mut SendQueue<ScreenCommand> {
349 self.queue.get_or_insert_with(|| {
350 let name = match self.id {
351 bindings::controller_id_e_t_E_CONTROLLER_MASTER => "controller-screen-master",
352 bindings::controller_id_e_t_E_CONTROLLER_PARTNER => "controller-screen-partner",
353 _ => "",
354 };
355 let id = self.id;
356 let (send, recv) = queue(VecDeque::<ScreenCommand>::new());
357 Task::spawn_ext(
358 name,
359 bindings::TASK_PRIORITY_MAX,
360 bindings::TASK_STACK_DEPTH_DEFAULT as u16,
361 move || {
362 let mut delay_target = None;
363 let mut offset = 0usize;
364 let mut clear = false;
365 let mut buffer = [ScreenRow::default(); 3];
366 let mut rumble: Option<[libc::c_char; 9]> = None;
367 'main: loop {
368 let command: Option<ScreenCommand> = select! {
369 cmd = recv.select() => Some(cmd),
370 _ = delay_until(t); Some(t) = delay_target => None,
371 };
372 if let Some(cmd) = command {
373 match cmd {
374 ScreenCommand::Clear => {
375 offset = 0;
376 clear = true;
377 buffer = Default::default();
378 }
379 ScreenCommand::ClearLine(line) => {
380 let row = &mut buffer[line as usize];
381 *row = ScreenRow::default();
382 row.needs_clear = true;
383 }
384 ScreenCommand::Print {
385 chars,
386 line,
387 column,
388 length,
389 } => {
390 let row = &mut buffer[line as usize];
391 copy(
392 &mut row.chars[column as usize..],
393 &chars[..length as usize],
394 );
395 row.dirty = true;
396 }
397 ScreenCommand::Rumble(pattern) => {
398 let mut buf: [libc::c_char; 9] = Default::default();
399 copy(&mut buf, &pattern);
400 rumble = Some(buf);
401 }
402 ScreenCommand::Stop => break,
403 }
404 }
405 if let Some(pattern) = rumble {
406 match unsafe { bindings::controller_rumble(id, pattern.as_ptr()) } {
407 1 => {
408 delay_target = Some(time_since_start() + SCREEN_SUCCESS_DELAY);
409 rumble = None;
410 }
411 _ => {
412 delay_target = Some(time_since_start() + SCREEN_FAILURE_DELAY);
413 Self::print_error()
414 }
415 }
416 } else if clear {
417 match unsafe { bindings::controller_clear(id) } {
418 1 => {
419 delay_target = Some(time_since_start() + SCREEN_SUCCESS_DELAY);
420 clear = false;
421 }
422 _ => {
423 delay_target = Some(time_since_start() + SCREEN_FAILURE_DELAY);
424 Self::print_error()
425 }
426 }
427 } else {
428 for i in 0..3 {
429 let index = (offset + i) % buffer.len();
430 let row = &mut buffer[index];
431 if row.needs_clear {
432 match unsafe {
433 bindings::controller_clear_line(id, index as u8)
434 } {
435 1 => {
436 delay_target =
437 Some(time_since_start() + SCREEN_SUCCESS_DELAY);
438 row.needs_clear = false;
439 }
440 _ => {
441 delay_target =
442 Some(time_since_start() + SCREEN_FAILURE_DELAY);
443 Self::print_error()
444 }
445 }
446 } else if row.dirty {
447 match unsafe {
448 bindings::controller_set_text(
449 id,
450 index as u8,
451 0,
452 row.chars.as_ptr(),
453 )
454 } {
455 1 => {
456 delay_target =
457 Some(time_since_start() + SCREEN_SUCCESS_DELAY);
458 row.dirty = false;
459 }
460 _ => {
461 delay_target =
462 Some(time_since_start() + SCREEN_FAILURE_DELAY);
463 Self::print_error()
464 }
465 }
466 } else {
467 continue;
468 }
469 offset = i + 1;
470 continue 'main;
471 }
472 delay_target = None;
474 }
475 }
476 },
477 )
478 .unwrap();
479 send
480 })
481 }
482
483 fn print_error() {
484 if get_errno() != libc::EAGAIN {
485 eprintln!("{:?}", ControllerError::from_errno());
486 }
487 }
488}
489
490impl Drop for Screen {
491 fn drop(&mut self) {
492 if self.queue.is_some() {
493 self.command(ScreenCommand::Stop);
494 }
495 }
496}
497
498#[derive(Copy, Clone)]
499struct ScreenRow {
500 chars: [libc::c_char; 20],
501 dirty: bool,
502 needs_clear: bool,
503}
504
505impl Default for ScreenRow {
506 fn default() -> Self {
507 let mut chars = [0x20; 20];
509 chars[19] = 0;
510 Self {
511 chars,
512 dirty: Default::default(),
513 needs_clear: Default::default(),
514 }
515 }
516}
517
518#[derive(Debug)]
519enum ScreenCommand {
520 Clear,
521 ClearLine(u8),
522 Print {
523 chars: [libc::c_char; 19],
524 line: u8,
525 column: u8,
526 length: u8,
527 },
528 Rumble([libc::c_char; 8]),
529 Stop,
530}
531
532pub enum ControllerId {
534 Master,
536 Partner,
538}
539
540impl From<ControllerId> for bindings::controller_id_e_t {
541 fn from(id: ControllerId) -> Self {
542 match id {
543 ControllerId::Master => bindings::controller_id_e_t_E_CONTROLLER_MASTER,
544 ControllerId::Partner => bindings::controller_id_e_t_E_CONTROLLER_PARTNER,
545 }
546 }
547}
548
549#[derive(Debug)]
551pub enum ControllerError {
552 InvalidController,
554 ControllerBusy,
556 Unknown(i32),
558}
559
560impl ControllerError {
561 fn from_errno() -> Self {
562 match { get_errno() } {
563 libc::EINVAL => Self::InvalidController,
564 libc::EACCES => Self::ControllerBusy,
565 x => Self::Unknown(x),
566 }
567 }
568}
569
570impl From<ControllerError> for Error {
571 fn from(err: ControllerError) -> Self {
572 match err {
573 ControllerError::InvalidController => Error::Custom("invalid controller id".into()),
574 ControllerError::ControllerBusy => Error::Custom("controller is busy".into()),
575 ControllerError::Unknown(n) => Error::System(n),
576 }
577 }
578}