diff --git a/src/calibrate.rs b/src/calibrate.rs deleted file mode 100644 index 0decbca..0000000 --- a/src/calibrate.rs +++ /dev/null @@ -1,150 +0,0 @@ -use defmt::Format; -use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, pubsub::Subscriber}; -use embassy_time::Timer; - -use crate::{gcc_hid::GcReport, input::CHANNEL_GCC_STATE}; - -const CALIBRATION_ENTRY_COMBO: [AwaitableButtons; 4] = [ - AwaitableButtons::Start, - AwaitableButtons::A, - AwaitableButtons::X, - AwaitableButtons::Y, -]; - -/// This doesn't need to be super fast, since it's only used -/// in calibration mode. -const BUTTON_POLL_INTERVAL_MILLIS: u64 = 20; - -#[derive(Clone, Copy, Debug, Format)] -enum AwaitableButtons { - A, - B, - X, - Y, - Up, - Down, - Left, - Right, - Start, - L, - R, -} - -trait WaitForButtonPress { - /// Wait for a single button press. - async fn wait_for_button_press(&mut self, button_to_wait_for: &AwaitableButtons); - - /// Wait for multiple buttons to be pressed simultaneously. - async fn wait_for_simultaneous_button_presses( - &mut self, - buttons_to_wait_for: &[AwaitableButtons; N], - ); - - /// Wait for a single button press of specified buttons, and return the button that was pressed. - async fn wait_and_filter_button_press( - &mut self, - buttons_to_wait_for: &[AwaitableButtons; N], - ) -> AwaitableButtons; - - /// Wait for multiple possible button combinations to be pressed simultaneously, and return the index of the combination that was pressed. - async fn wait_and_filter_simultaneous_button_presses( - &mut self, - buttons_to_wait_for: &[[AwaitableButtons; N]; M], - ) -> usize; -} - -impl<'a, const I: usize, const J: usize, const K: usize> WaitForButtonPress - for Subscriber<'a, CriticalSectionRawMutex, GcReport, I, J, K> -{ - async fn wait_for_button_press(&mut self, button_to_wait_for: &AwaitableButtons) { - loop { - if match self.next_message_pure().await { - report => is_awaitable_button_pressed(&report, button_to_wait_for), - } { - break; - } - Timer::after_millis(BUTTON_POLL_INTERVAL_MILLIS).await; - } - } - - async fn wait_for_simultaneous_button_presses( - &mut self, - buttons_to_wait_for: &[AwaitableButtons; N], - ) { - loop { - if match self.next_message_pure().await { - report => buttons_to_wait_for - .iter() - .all(|button| is_awaitable_button_pressed(&report, button)), - } { - break; - } - Timer::after_millis(BUTTON_POLL_INTERVAL_MILLIS).await; - } - } - - async fn wait_and_filter_button_press( - &mut self, - buttons_to_wait_for: &[AwaitableButtons; N], - ) -> AwaitableButtons { - loop { - match self.next_message_pure().await { - report => { - for button in buttons_to_wait_for { - if is_awaitable_button_pressed(&report, button) { - return *button; - } - } - } - } - Timer::after_millis(BUTTON_POLL_INTERVAL_MILLIS).await; - } - } - - async fn wait_and_filter_simultaneous_button_presses( - &mut self, - buttons_to_wait_for: &[[AwaitableButtons; N]; M], - ) -> usize { - loop { - match self.next_message_pure().await { - report => { - for (i, buttons) in buttons_to_wait_for.iter().enumerate() { - if buttons - .iter() - .all(|button| is_awaitable_button_pressed(&report, button)) - { - return i; - } - } - } - } - Timer::after_millis(BUTTON_POLL_INTERVAL_MILLIS).await; - } - } -} - -fn is_awaitable_button_pressed(report: &GcReport, button_to_wait_for: &AwaitableButtons) -> bool { - match button_to_wait_for { - AwaitableButtons::A => report.buttons_1.button_a, - AwaitableButtons::B => report.buttons_1.button_b, - AwaitableButtons::X => report.buttons_1.button_x, - AwaitableButtons::Y => report.buttons_1.button_y, - AwaitableButtons::Up => report.buttons_1.dpad_up, - AwaitableButtons::Down => report.buttons_1.dpad_down, - AwaitableButtons::Left => report.buttons_1.dpad_left, - AwaitableButtons::Right => report.buttons_1.dpad_right, - AwaitableButtons::Start => report.buttons_2.button_start, - AwaitableButtons::L => report.buttons_2.button_l, - AwaitableButtons::R => report.buttons_2.button_r, - } -} - -pub async fn calibration_loop() { - let mut gcc_subscriber = CHANNEL_GCC_STATE.subscriber().unwrap(); - - loop { - gcc_subscriber - .wait_for_simultaneous_button_presses(&CALIBRATION_ENTRY_COMBO) - .await; - } -} diff --git a/src/config.rs b/src/config.rs index da95f57..8c917de 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,5 +1,6 @@ /** * Storage for controller configuration, including helper functions & types, as well as sane defaults. + * Also includes necessary logic for configuring the controller & calibrating the sticks. */ use core::f32::consts::PI; @@ -16,6 +17,22 @@ use crate::{ ADDR_OFFSET, FLASH_SIZE, }; +use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, pubsub::Subscriber}; +use embassy_time::Timer; + +use crate::{gcc_hid::GcReport, input::CHANNEL_GCC_STATE}; + +const CONFIG_MODE_ENTRY_COMBO: [AwaitableButtons; 4] = [ + AwaitableButtons::Start, + AwaitableButtons::A, + AwaitableButtons::X, + AwaitableButtons::Y, +]; + +/// This doesn't need to be super fast, since it's only used +/// in config mode. +const BUTTON_POLL_INTERVAL_MILLIS: u64 = 20; + /// This needs to be incremented for ANY change to ControllerConfig /// else we risk loading uninitialized memory. pub const CONTROLLER_CONFIG_REVISION: u8 = 2; @@ -98,6 +115,21 @@ const DEFAULT_ANGLES: [f32; NO_OF_NOTCHES] = [ PI * 15. / 8., ]; +#[derive(Clone, Copy, Debug, Format)] +enum AwaitableButtons { + A, + B, + X, + Y, + Up, + Down, + Left, + Right, + Start, + L, + R, +} + #[derive(Debug, Clone, Format, PackedStruct)] #[packed_struct(endian = "msb")] pub struct StickConfig { @@ -199,3 +231,123 @@ impl ControllerConfig { Ok(()) } } + +trait WaitForButtonPress { + /// Wait for a single button press. + async fn wait_for_button_press(&mut self, button_to_wait_for: &AwaitableButtons); + + /// Wait for multiple buttons to be pressed simultaneously. + async fn wait_for_simultaneous_button_presses( + &mut self, + buttons_to_wait_for: &[AwaitableButtons; N], + ); + + /// Wait for a single button press of specified buttons, and return the button that was pressed. + async fn wait_and_filter_button_press( + &mut self, + buttons_to_wait_for: &[AwaitableButtons; N], + ) -> AwaitableButtons; + + /// Wait for multiple possible button combinations to be pressed simultaneously, and return the index of the combination that was pressed. + async fn wait_and_filter_simultaneous_button_presses( + &mut self, + buttons_to_wait_for: &[[AwaitableButtons; N]; M], + ) -> usize; +} + +impl<'a, const I: usize, const J: usize, const K: usize> WaitForButtonPress + for Subscriber<'a, CriticalSectionRawMutex, GcReport, I, J, K> +{ + async fn wait_for_button_press(&mut self, button_to_wait_for: &AwaitableButtons) { + loop { + if match self.next_message_pure().await { + report => is_awaitable_button_pressed(&report, button_to_wait_for), + } { + break; + } + Timer::after_millis(BUTTON_POLL_INTERVAL_MILLIS).await; + } + } + + async fn wait_for_simultaneous_button_presses( + &mut self, + buttons_to_wait_for: &[AwaitableButtons; N], + ) { + loop { + if match self.next_message_pure().await { + report => buttons_to_wait_for + .iter() + .all(|button| is_awaitable_button_pressed(&report, button)), + } { + break; + } + Timer::after_millis(BUTTON_POLL_INTERVAL_MILLIS).await; + } + } + + async fn wait_and_filter_button_press( + &mut self, + buttons_to_wait_for: &[AwaitableButtons; N], + ) -> AwaitableButtons { + loop { + match self.next_message_pure().await { + report => { + for button in buttons_to_wait_for { + if is_awaitable_button_pressed(&report, button) { + return *button; + } + } + } + } + Timer::after_millis(BUTTON_POLL_INTERVAL_MILLIS).await; + } + } + + async fn wait_and_filter_simultaneous_button_presses( + &mut self, + buttons_to_wait_for: &[[AwaitableButtons; N]; M], + ) -> usize { + loop { + match self.next_message_pure().await { + report => { + for (i, buttons) in buttons_to_wait_for.iter().enumerate() { + if buttons + .iter() + .all(|button| is_awaitable_button_pressed(&report, button)) + { + return i; + } + } + } + } + Timer::after_millis(BUTTON_POLL_INTERVAL_MILLIS).await; + } + } +} + +fn is_awaitable_button_pressed(report: &GcReport, button_to_wait_for: &AwaitableButtons) -> bool { + match button_to_wait_for { + AwaitableButtons::A => report.buttons_1.button_a, + AwaitableButtons::B => report.buttons_1.button_b, + AwaitableButtons::X => report.buttons_1.button_x, + AwaitableButtons::Y => report.buttons_1.button_y, + AwaitableButtons::Up => report.buttons_1.dpad_up, + AwaitableButtons::Down => report.buttons_1.dpad_down, + AwaitableButtons::Left => report.buttons_1.dpad_left, + AwaitableButtons::Right => report.buttons_1.dpad_right, + AwaitableButtons::Start => report.buttons_2.button_start, + AwaitableButtons::L => report.buttons_2.button_l, + AwaitableButtons::R => report.buttons_2.button_r, + } +} + +#[embassy_executor::task] +pub async fn config_task() { + let mut gcc_subscriber = CHANNEL_GCC_STATE.subscriber().unwrap(); + + loop { + gcc_subscriber + .wait_for_simultaneous_button_presses(&CONFIG_MODE_ENTRY_COMBO) + .await; + } +} diff --git a/src/main.rs b/src/main.rs index e49a382..4974835 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,7 +4,6 @@ #![no_std] #![no_main] -mod calibrate; mod config; mod filter; mod gcc_hid; @@ -12,7 +11,7 @@ mod helpers; mod input; mod stick; -use calibrate::calibration_loop; +use config::config_task; use config::ControllerConfig; use defmt::{debug, info}; use embassy_executor::Executor; @@ -119,6 +118,7 @@ fn main() -> ! { // pwm_brake.set_counter(255); executor0.run(|spawner| { + spawner.spawn(config_task()).unwrap(); spawner .spawn(update_stick_states_task( spi,