feat(calibration): implement notch adjustment
All checks were successful
Publish nightly release / build (push) Successful in 1m13s
All checks were successful
Publish nightly release / build (push) Successful in 1m13s
This commit is contained in:
parent
d5dbaaaa49
commit
84d531e80a
4 changed files with 113 additions and 42 deletions
|
@ -5,6 +5,7 @@
|
||||||
use core::{cmp::min, f32::consts::PI};
|
use core::{cmp::min, f32::consts::PI};
|
||||||
|
|
||||||
use defmt::{debug, error, info, warn, Format};
|
use defmt::{debug, error, info, warn, Format};
|
||||||
|
use embassy_futures::yield_now;
|
||||||
use embassy_rp::{
|
use embassy_rp::{
|
||||||
flash::{Async, Flash, ERASE_SIZE},
|
flash::{Async, Flash, ERASE_SIZE},
|
||||||
peripherals::FLASH,
|
peripherals::FLASH,
|
||||||
|
@ -12,7 +13,7 @@ use embassy_rp::{
|
||||||
use packed_struct::{derive::PackedStruct, PackedStruct};
|
use packed_struct::{derive::PackedStruct, PackedStruct};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
helpers::{PackedFloat, ToPackedFloatArray, XyValuePair},
|
helpers::{PackedFloat, ToPackedFloatArray, ToRegularArray, XyValuePair},
|
||||||
input::{
|
input::{
|
||||||
read_ext_adc, Stick, StickAxis, StickState, FLOAT_ORIGIN, SPI_ACS_SHARED, SPI_CCS_SHARED,
|
read_ext_adc, Stick, StickAxis, StickState, FLOAT_ORIGIN, SPI_ACS_SHARED, SPI_CCS_SHARED,
|
||||||
SPI_SHARED,
|
SPI_SHARED,
|
||||||
|
@ -38,6 +39,9 @@ use crate::{gcc_hid::GcReport, input::CHANNEL_GCC_STATE};
|
||||||
/// Initial status is assumed to be false.
|
/// Initial status is assumed to be false.
|
||||||
pub static SIGNAL_IS_CALIBRATING: Signal<ThreadModeRawMutex, bool> = Signal::new();
|
pub static SIGNAL_IS_CALIBRATING: Signal<ThreadModeRawMutex, bool> = Signal::new();
|
||||||
|
|
||||||
|
/// Config change signalled to the stick task.
|
||||||
|
pub static SIGNAL_CONFIG_CHANGE: Signal<ThreadModeRawMutex, ControllerConfig> = Signal::new();
|
||||||
|
|
||||||
/// Signal used to override the stick state in order to display desired stick positions during calibration.
|
/// Signal used to override the stick state in order to display desired stick positions during calibration.
|
||||||
pub static SIGNAL_OVERRIDE_STICK_STATE: Signal<
|
pub static SIGNAL_OVERRIDE_STICK_STATE: Signal<
|
||||||
CriticalSectionRawMutex,
|
CriticalSectionRawMutex,
|
||||||
|
@ -74,7 +78,7 @@ const BUTTON_POLL_INTERVAL_MILLIS: u64 = 20;
|
||||||
|
|
||||||
/// This needs to be incremented for ANY change to ControllerConfig
|
/// This needs to be incremented for ANY change to ControllerConfig
|
||||||
/// else we risk loading uninitialized memory.
|
/// else we risk loading uninitialized memory.
|
||||||
pub const CONTROLLER_CONFIG_REVISION: u8 = 2;
|
pub const CONTROLLER_CONFIG_REVISION: u8 = 1;
|
||||||
|
|
||||||
pub const DEFAULT_NOTCH_STATUS: [NotchStatus; NO_OF_NOTCHES] = [
|
pub const DEFAULT_NOTCH_STATUS: [NotchStatus; NO_OF_NOTCHES] = [
|
||||||
NotchStatus::Cardinal,
|
NotchStatus::Cardinal,
|
||||||
|
@ -458,30 +462,32 @@ impl<'a> StickCalibrationProcess<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn adjust_notch(&mut self, notch_adjustment_type: NotchAdjustmentType) -> Option<(f32, f32)> {
|
fn adjust_notch(&mut self, notch_adjustment_type: NotchAdjustmentType) {
|
||||||
|
let stick_config = match self.which_stick {
|
||||||
|
Stick::ControlStick => &mut self.gcc_config.astick_config,
|
||||||
|
Stick::CStick => &mut self.gcc_config.cstick_config,
|
||||||
|
};
|
||||||
|
|
||||||
let notch_idx =
|
let notch_idx =
|
||||||
NOTCH_ADJUSTMENT_ORDER[self.calibration_step as usize - NO_OF_CALIBRATION_POINTS];
|
NOTCH_ADJUSTMENT_ORDER[self.calibration_step as usize - NO_OF_CALIBRATION_POINTS];
|
||||||
|
|
||||||
if self.applied_calibration.cleaned_calibration.notch_status[notch_idx]
|
if self.applied_calibration.cleaned_calibration.notch_status[notch_idx]
|
||||||
== NotchStatus::TertInactive
|
== NotchStatus::TertInactive
|
||||||
{
|
{}
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
// assumes a tick rate of 1ms
|
// assumes a tick rate of 1ms
|
||||||
match notch_adjustment_type {
|
match notch_adjustment_type {
|
||||||
NotchAdjustmentType::Clockwise => {
|
NotchAdjustmentType::Clockwise => {
|
||||||
self.applied_calibration.notch_angles[notch_idx] -= 0.000075;
|
stick_config.angles[notch_idx] -= 0.0075;
|
||||||
}
|
}
|
||||||
NotchAdjustmentType::CounterClockwise => {
|
NotchAdjustmentType::CounterClockwise => {
|
||||||
self.applied_calibration.notch_angles[notch_idx] += 0.000075;
|
stick_config.angles[notch_idx] += 0.0075;
|
||||||
}
|
}
|
||||||
NotchAdjustmentType::Reset => {
|
NotchAdjustmentType::Reset => {
|
||||||
self.applied_calibration.notch_angles[notch_idx] = DEFAULT_ANGLES[notch_idx];
|
stick_config.angles[notch_idx] =
|
||||||
}
|
PackedFloat(self.applied_calibration.measured_notch_angles[notch_idx]);
|
||||||
NotchAdjustmentType::None => {
|
|
||||||
return None;
|
|
||||||
}
|
}
|
||||||
|
NotchAdjustmentType::None => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
match notch_adjustment_type {
|
match notch_adjustment_type {
|
||||||
|
@ -492,7 +498,7 @@ impl<'a> StickCalibrationProcess<'a> {
|
||||||
CleanedCalibrationPoints::from_temp_calibration_points(
|
CleanedCalibrationPoints::from_temp_calibration_points(
|
||||||
&self.cal_points.map(|e| e.x),
|
&self.cal_points.map(|e| e.x),
|
||||||
&self.cal_points.map(|e| e.y),
|
&self.cal_points.map(|e| e.y),
|
||||||
&self.applied_calibration.notch_angles,
|
&self.applied_calibration.measured_notch_angles,
|
||||||
);
|
);
|
||||||
|
|
||||||
let linearized_calibration =
|
let linearized_calibration =
|
||||||
|
@ -512,15 +518,18 @@ impl<'a> StickCalibrationProcess<'a> {
|
||||||
notch_calibration.affine_coeffs;
|
notch_calibration.affine_coeffs;
|
||||||
self.applied_calibration.stick_params.boundary_angles =
|
self.applied_calibration.stick_params.boundary_angles =
|
||||||
notch_calibration.boundary_angles;
|
notch_calibration.boundary_angles;
|
||||||
}
|
|
||||||
NotchAdjustmentType::None => return None,
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(
|
stick_config.angles = *legalize_notches(
|
||||||
match calc_stick_values(self.applied_calibration.measured_notch_angles[notch_idx]) {
|
self.calibration_step as usize,
|
||||||
(x, y) => (x + FLOAT_ORIGIN, y + FLOAT_ORIGIN),
|
&self.applied_calibration.measured_notch_angles,
|
||||||
},
|
&stick_config.angles.to_regular_array(),
|
||||||
)
|
)
|
||||||
|
.to_packed_float_array();
|
||||||
|
|
||||||
|
SIGNAL_CONFIG_CHANGE.signal(self.gcc_config.clone());
|
||||||
|
}
|
||||||
|
NotchAdjustmentType::None => {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn calibration_advance(&mut self) -> bool {
|
async fn calibration_advance(&mut self) -> bool {
|
||||||
|
@ -593,7 +602,7 @@ impl<'a> StickCalibrationProcess<'a> {
|
||||||
stick_config.angles = *legalize_notches(
|
stick_config.angles = *legalize_notches(
|
||||||
self.calibration_step as usize,
|
self.calibration_step as usize,
|
||||||
&self.applied_calibration.measured_notch_angles,
|
&self.applied_calibration.measured_notch_angles,
|
||||||
&stick_config.angles.map(|e| *e),
|
&stick_config.angles.to_regular_array(),
|
||||||
)
|
)
|
||||||
.to_packed_float_array();
|
.to_packed_float_array();
|
||||||
|
|
||||||
|
@ -610,6 +619,8 @@ impl<'a> StickCalibrationProcess<'a> {
|
||||||
stick_config.cal_points_x = self.cal_points.map(|p| p.x.into());
|
stick_config.cal_points_x = self.cal_points.map(|p| p.x.into());
|
||||||
stick_config.cal_points_y = self.cal_points.map(|p| p.y.into());
|
stick_config.cal_points_y = self.cal_points.map(|p| p.y.into());
|
||||||
|
|
||||||
|
SIGNAL_CONFIG_CHANGE.signal(self.gcc_config.clone());
|
||||||
|
|
||||||
info!("Finished calibrating stick {}", self.which_stick);
|
info!("Finished calibrating stick {}", self.which_stick);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -687,7 +698,7 @@ impl<'a> StickCalibrationProcess<'a> {
|
||||||
AwaitableButtons::Y,
|
AwaitableButtons::Y,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
let override_result = match btn_result {
|
match btn_result {
|
||||||
Some(btn) => match btn {
|
Some(btn) => match btn {
|
||||||
AwaitableButtons::A => {
|
AwaitableButtons::A => {
|
||||||
debug!("Btn A release pressed");
|
debug!("Btn A release pressed");
|
||||||
|
@ -705,18 +716,8 @@ impl<'a> StickCalibrationProcess<'a> {
|
||||||
None => self.adjust_notch(NotchAdjustmentType::None),
|
None => self.adjust_notch(NotchAdjustmentType::None),
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some((x, y)) = override_result {
|
|
||||||
SIGNAL_OVERRIDE_STICK_STATE.signal(Some(OverrideStickState {
|
|
||||||
x: x as u8,
|
|
||||||
y: y as u8,
|
|
||||||
which_stick: match self.which_stick {
|
|
||||||
Stick::ControlStick => Stick::CStick,
|
|
||||||
Stick::CStick => Stick::ControlStick,
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
ticker.next().await;
|
ticker.next().await;
|
||||||
|
yield_now().await;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -360,7 +360,13 @@ pub async fn usb_transfer_task(
|
||||||
trace!("Report Written: {:08b}", report);
|
trace!("Report Written: {:08b}", report);
|
||||||
let currtime = Instant::now();
|
let currtime = Instant::now();
|
||||||
let polltime = currtime.duration_since(lasttime);
|
let polltime = currtime.duration_since(lasttime);
|
||||||
trace!("Report written in {}us", polltime.as_micros());
|
let micros = polltime.as_micros();
|
||||||
|
debug!("Report written in {}us", micros);
|
||||||
|
// If we're sending reports too fast, reset the ticker.
|
||||||
|
// This might happen right after plug-in, or after suspend.
|
||||||
|
if micros < 8150 {
|
||||||
|
ticker.reset();
|
||||||
|
}
|
||||||
lasttime = currtime;
|
lasttime = currtime;
|
||||||
}
|
}
|
||||||
Err(e) => warn!("Failed to send report: {:?}", e),
|
Err(e) => warn!("Failed to send report: {:?}", e),
|
||||||
|
|
|
@ -1,11 +1,67 @@
|
||||||
use core::ops::Deref;
|
use core::ops::{Add, AddAssign, Deref, Sub, SubAssign};
|
||||||
use defmt::Format;
|
use defmt::Format;
|
||||||
use packed_struct::PackedStruct;
|
use packed_struct::PackedStruct;
|
||||||
|
|
||||||
/// wrapper type because packed_struct doesn't implement float
|
/// wrapper type because packed_struct doesn't implement float
|
||||||
/// packing by default
|
/// packing by default
|
||||||
#[derive(Debug, Format, Clone, Default, Copy)]
|
#[derive(Debug, Format, Clone, Default, Copy)]
|
||||||
pub struct PackedFloat(f32);
|
pub struct PackedFloat(pub f32);
|
||||||
|
|
||||||
|
impl Add for PackedFloat {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn add(self, rhs: Self) -> Self::Output {
|
||||||
|
Self(self.0 + rhs.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Add<f32> for PackedFloat {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn add(self, rhs: f32) -> Self::Output {
|
||||||
|
Self(self.0 + rhs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Sub for PackedFloat {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn sub(self, rhs: Self) -> Self::Output {
|
||||||
|
Self(self.0 - rhs.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Sub<f32> for PackedFloat {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn sub(self, rhs: f32) -> Self::Output {
|
||||||
|
Self(self.0 - rhs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SubAssign for PackedFloat {
|
||||||
|
fn sub_assign(&mut self, rhs: Self) {
|
||||||
|
self.0 -= rhs.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SubAssign<f32> for PackedFloat {
|
||||||
|
fn sub_assign(&mut self, rhs: f32) {
|
||||||
|
self.0 -= rhs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AddAssign for PackedFloat {
|
||||||
|
fn add_assign(&mut self, rhs: Self) {
|
||||||
|
self.0 += rhs.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AddAssign<f32> for PackedFloat {
|
||||||
|
fn add_assign(&mut self, rhs: f32) {
|
||||||
|
self.0 += rhs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait ToRegularArray<const T: usize> {
|
pub trait ToRegularArray<const T: usize> {
|
||||||
fn to_regular_array(&self) -> &[f32; T];
|
fn to_regular_array(&self) -> &[f32; T];
|
||||||
|
|
18
src/input.rs
18
src/input.rs
|
@ -21,8 +21,8 @@ use libm::{fmaxf, fminf};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
config::{
|
config::{
|
||||||
ControllerConfig, OverrideGcReportInstruction, OverrideStickState, SIGNAL_IS_CALIBRATING,
|
ControllerConfig, OverrideGcReportInstruction, OverrideStickState, SIGNAL_CONFIG_CHANGE,
|
||||||
SIGNAL_OVERRIDE_GCC_STATE, SIGNAL_OVERRIDE_STICK_STATE,
|
SIGNAL_IS_CALIBRATING, SIGNAL_OVERRIDE_GCC_STATE, SIGNAL_OVERRIDE_STICK_STATE,
|
||||||
},
|
},
|
||||||
filter::{run_waveshaping, FilterGains, KalmanState, WaveshapingValues, FILTER_GAINS},
|
filter::{run_waveshaping, FilterGains, KalmanState, WaveshapingValues, FILTER_GAINS},
|
||||||
gcc_hid::GcReport,
|
gcc_hid::GcReport,
|
||||||
|
@ -506,9 +506,10 @@ pub async fn update_stick_states_task(
|
||||||
*SPI_ACS_SHARED.lock().await = Some(spi_acs);
|
*SPI_ACS_SHARED.lock().await = Some(spi_acs);
|
||||||
*SPI_CCS_SHARED.lock().await = Some(spi_ccs);
|
*SPI_CCS_SHARED.lock().await = Some(spi_ccs);
|
||||||
|
|
||||||
let controlstick_params = StickParams::from_stick_config(&controller_config.astick_config);
|
let mut controller_config = controller_config;
|
||||||
let cstick_params = StickParams::from_stick_config(&controller_config.cstick_config);
|
let mut controlstick_params = StickParams::from_stick_config(&controller_config.astick_config);
|
||||||
let filter_gains = FILTER_GAINS.get_normalized_gains(&controller_config);
|
let mut cstick_params = StickParams::from_stick_config(&controller_config.cstick_config);
|
||||||
|
let mut filter_gains = FILTER_GAINS.get_normalized_gains(&controller_config);
|
||||||
|
|
||||||
info!("Controlstick params: {:?}", controlstick_params);
|
info!("Controlstick params: {:?}", controlstick_params);
|
||||||
|
|
||||||
|
@ -572,6 +573,13 @@ pub async fn update_stick_states_task(
|
||||||
yield_now().await;
|
yield_now().await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(new_config) = SIGNAL_CONFIG_CHANGE.try_take() {
|
||||||
|
controller_config = new_config;
|
||||||
|
controlstick_params = StickParams::from_stick_config(&controller_config.astick_config);
|
||||||
|
cstick_params = StickParams::from_stick_config(&controller_config.cstick_config);
|
||||||
|
filter_gains = FILTER_GAINS.get_normalized_gains(&controller_config);
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
{
|
{
|
||||||
// give other tasks a chance to do something
|
// give other tasks a chance to do something
|
||||||
|
|
Loading…
Reference in a new issue