use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, signal::Signal};
use tinyrand::{RandRange, StdRand};
use imu_sensors::{AccFullScale, AccUnits, GyroFullScale, GyroUnits, ImuMock, MockImuBus};
use vqm::Vector3f32;
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct ImuData {
pub acc: Vector3f32,
pub gyro_rps: Vector3f32,
pub delta_t: f32,
}
impl ImuData {
pub const fn new() -> Self {
Self {
acc: Vector3f32 { x: 0.0, y: 0.0, z: 0.0 },
gyro_rps: Vector3f32 { x: 0.0, y: 0.0, z: 0.0 },
delta_t: 0.1,
}
}
}
impl Default for ImuData {
fn default() -> Self {
Self::new()
}
}
pub static IMU_SIGNAL: Signal<CriticalSectionRawMutex, ImuData> = Signal::new();
pub struct ImuContext {
pub imu: ImuMock<MockImuBus>,
}
impl ImuContext {
pub fn new() -> Self {
Self { imu: ImuMock::new(MockImuBus::new(), imu_sensors::ImuAxesOrder::XPOS_YPOS_ZPOS) }
}
}
#[embassy_executor::task]
pub async fn imu_task(ctx: &'static mut ImuContext) {
let delta_t_us = 1000;
let delta_t = 0.001_f32;
let mut ticker = embassy_time::Ticker::every(embassy_time::Duration::from_micros(delta_t_us));
let mut loop_count: u32 = 0;
let mut rand = StdRand::default();
let mut x_base: i32 = 0;
_ = ctx.imu.init(8000, GyroFullScale::Max, GyroUnits::Rps, AccFullScale::Max, AccUnits::G).await;
log::info!(" IMU: task started");
loop {
ticker.next().await;
let acc_rnd = Vector3f32 { x: 1.0, y: 0.5, z: 0.25 };
ctx.imu.set_acc(acc_rnd).await;
x_base += rand.next_range(0..5_u32).cast_signed() - 2;
let gyro_x = x_base + rand.next_range(0..5_u32).cast_signed() - 2;
let gyro_y = rand.next_range(0..11_u32).cast_signed() - 5;
let gyro_z = rand.next_range(0..11_u32).cast_signed() - 5;
#[allow(clippy::cast_precision_loss)]
let gyro_dps_rnd = Vector3f32 { x: gyro_x as f32, y: gyro_y as f32, z: gyro_z as f32 };
ctx.imu.set_gyro(gyro_dps_rnd).await;
let imu_data = ImuData { acc: acc_rnd, gyro_rps: gyro_dps_rnd.to_radians(), delta_t };
IMU_SIGNAL.signal(imu_data);
if loop_count.is_multiple_of(100) {
log::info!(" IMU: loop {loop_count}");
}
loop_count = loop_count.wrapping_add(1);
embassy_time::Timer::after(embassy_time::Duration::from_millis(1)).await;
}
}