use crate::calibration::Calibration;
use cgmath::*;
use input::WhichController;
use joycon_sys::*;
#[derive(Debug, Copy, Clone)]
pub struct IMU {
pub gyro: Vector3<f64>,
pub accel: Vector3<f64>,
}
impl IMU {
pub const SAMPLE_DURATION: f64 = imu::IMU_SAMPLE_DURATION;
pub const SAMPLE_PER_SECOND: u32 = imu::IMU_SAMPLES_PER_SECOND;
}
pub struct Handler {
device_type: WhichController,
calib_gyro: Calibration,
gyro_sens: imu::GyroSens,
accel_sens: imu::AccSens,
factory_calibration: spi::SensorCalibration,
user_calibration: spi::UserSensorCalibration,
calib_nb: u32,
}
impl Handler {
pub fn new(
device_type: WhichController,
gyro_sens: imu::GyroSens,
accel_sens: imu::AccSens,
) -> Self {
Handler {
device_type,
calib_gyro: Calibration::with_capacity(200),
gyro_sens,
accel_sens,
factory_calibration: spi::SensorCalibration::default(),
user_calibration: spi::UserSensorCalibration::default(),
calib_nb: 0,
}
}
pub fn set_factory(&mut self, calib: spi::SensorCalibration) {
self.factory_calibration = calib;
}
pub fn set_user(&mut self, calib: spi::UserSensorCalibration) {
self.user_calibration = calib;
}
fn acc_calib(&self) -> Vector3<f64> {
self.user_calibration
.acc_offset()
.unwrap_or_else(|| self.factory_calibration.acc_offset())
}
fn gyro_calib(&self) -> Vector3<f64> {
self.user_calibration
.gyro_offset()
.unwrap_or_else(|| self.factory_calibration.gyro_offset())
}
pub fn handle_frames(&mut self, frames: &[imu::Frame]) -> [IMU; 3] {
let gyro_offset = self.gyro_calib();
let acc_offset = self.acc_calib();
let mut out = [IMU {
gyro: Vector3::zero(),
accel: Vector3::zero(),
}; 3];
for (frame, out) in frames.iter().rev().zip(out.iter_mut()) {
let raw_rotation = frame.rotation_dps(gyro_offset, self.gyro_sens);
let raw_acc = frame.accel_g(acc_offset, self.accel_sens);
if self.calib_nb > 0 {
self.calib_gyro.push(raw_rotation);
self.calib_nb -= 1;
}
*out = IMU {
gyro: raw_rotation - self.calib_gyro.get_average(),
accel: raw_acc,
};
match self.device_type {
WhichController::LeftJoyCon | WhichController::ProController => {
out.gyro.y = -out.gyro.y;
out.gyro.z = -out.gyro.z;
out.accel.x = -out.accel.x;
}
WhichController::RightJoyCon => {
out.accel = -out.accel;
}
}
}
out
}
pub fn reset_calibration(&mut self) {
self.calib_gyro.reset();
self.calib_nb = 0;
}
}