chore: move calibrate to config

This commit is contained in:
Naxdy 2024-03-29 16:07:44 +01:00
parent 7878c283e6
commit 5408d37560
Signed by: Naxdy
GPG key ID: CC15075846BCE91B
3 changed files with 154 additions and 152 deletions

View file

@ -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<const N: usize>(
&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<const N: usize>(
&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<const N: usize, const M: usize>(
&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<const N: usize>(
&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<const N: usize>(
&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<const N: usize, const M: usize>(
&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;
}
}

View file

@ -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<const N: usize>(
&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<const N: usize>(
&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<const N: usize, const M: usize>(
&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<const N: usize>(
&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<const N: usize>(
&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<const N: usize, const M: usize>(
&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;
}
}

View file

@ -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,