use crate::chip::nmea::Position;
use crate::edge::Pulse;
use crate::time::VirtualNanos;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Curve {
pub zero: VirtualNanos,
pub full: VirtualNanos,
}
pub const FULL: u32 = 1000;
impl Curve {
#[must_use]
pub fn command(self, pulse: Pulse) -> u32 {
let span = self.full.0.saturating_sub(self.zero.0).max(1);
let above = pulse.width.0.saturating_sub(self.zero.0).min(span);
u32::try_from(above * u64::from(FULL) / span).expect("at most the whole")
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Actuator {
pub name: &'static str,
pub pulse: Option<Pulse>,
pub command: Option<u32>,
}
impl Actuator {
#[must_use]
pub fn on(name: &'static str, pulse: Option<Pulse>, curve: Curve) -> Self {
Self {
name,
pulse,
command: pulse.map(|pulse| curve.command(pulse)),
}
}
#[must_use]
pub(crate) const fn idle(name: &'static str) -> Self {
Self {
name,
pulse: None,
command: None,
}
}
}
pub trait Actuate {
fn actuators(&self) -> &[Actuator];
}
#[derive(
Debug, Clone, Copy, Default, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize,
)]
pub struct Signals {
pub angular_rate: [i32; 3],
pub specific_force: [i32; 3],
pub magnetic_field: [i32; 3],
pub pressure: u32,
pub temperature: i32,
pub battery_voltage: u32,
pub battery_current: i32,
pub position: Position,
pub velocity: [i32; 3],
}
pub const AT_REST: Signals = Signals {
angular_rate: [0; 3],
specific_force: [0, 0, -1_000_000],
magnetic_field: [22_000, 0, 42_000],
pressure: 101_325,
temperature: 2_000,
battery_voltage: 16_800,
battery_current: 0,
position: Position {
latitude: 398_283_000,
longitude: -985_795_000,
altitude: 500_000,
},
velocity: [0; 3],
};
impl crate::link::Wire for Signals {
fn encode(&self, out: &mut Vec<u8>) {
self.angular_rate.encode(out);
self.specific_force.encode(out);
self.magnetic_field.encode(out);
self.pressure.encode(out);
self.temperature.encode(out);
self.battery_voltage.encode(out);
self.battery_current.encode(out);
self.position.encode(out);
self.velocity.encode(out);
}
fn decode(bytes: &mut &[u8]) -> Result<Self, crate::link::WireError> {
Ok(Self {
angular_rate: crate::link::Wire::decode(bytes)?,
specific_force: crate::link::Wire::decode(bytes)?,
magnetic_field: crate::link::Wire::decode(bytes)?,
pressure: crate::link::Wire::decode(bytes)?,
temperature: crate::link::Wire::decode(bytes)?,
battery_voltage: crate::link::Wire::decode(bytes)?,
battery_current: crate::link::Wire::decode(bytes)?,
position: crate::link::Wire::decode(bytes)?,
velocity: crate::link::Wire::decode(bytes)?,
})
}
}