actuator: make arming sequences owner-local

This commit is contained in:
Onur Özkan committed 2026-08-09 13:56:45 +03:00
1 parent f200e88ef0
commit c44286bdcf
3 files changed
+59 -83

No files matched your search

+26 -37
View File
@@ -1,7 +1,6 @@
//! Conventional PWM framing and arming policy.
use crate::ArmingDuration;
use core::sync::atomic::{AtomicBool, AtomicU16, Ordering};
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Config {
@@ -104,60 +103,50 @@ pub enum FrameValue {
}
pub struct ArmSequence {
armed_idle: AtomicU16,
minimum_frames: AtomicU16,
remaining: AtomicU16,
armed: AtomicBool,
armed_idle: PulseWidth,
minimum_frames: u16,
remaining: u16,
armed: bool,
}
impl ArmSequence {
pub const fn new(armed_idle: PulseWidth, minimum_frames: u16) -> Self {
Self {
armed_idle: AtomicU16::new(armed_idle.microseconds()),
minimum_frames: AtomicU16::new(minimum_frames),
remaining: AtomicU16::new(0),
armed: AtomicBool::new(false),
armed_idle,
minimum_frames,
remaining: 0,
armed: false,
}
}
pub fn arm(&self) {
self.remaining.store(
self.minimum_frames.load(Ordering::Acquire),
Ordering::Release,
);
self.armed.store(true, Ordering::Release);
/// Starts the fixed configured minimum-frame sequence. The driver which
/// owns this state must acquire external safety authorization before
/// calling this method and before every subsequent non-minimum commit.
pub fn arm(&mut self) {
self.remaining = self.minimum_frames;
self.armed = true;
}
pub fn configure_minimum_frames(&self, minimum_frames: u16) {
self.minimum_frames.store(minimum_frames, Ordering::Release);
/// Stops the sequence; the physical output owner must drive its explicit
/// minimum pulse independently of this local state transition.
pub fn disarm(&mut self) {
self.armed = false;
self.remaining = 0;
}
pub fn configure_armed_idle(&self, armed_idle: PulseWidth) {
self.armed_idle
.store(armed_idle.microseconds(), Ordering::Release);
pub const fn is_armed(&self) -> bool {
self.armed
}
pub fn disarm(&self) {
self.armed.store(false, Ordering::Release);
self.remaining.store(0, Ordering::Release);
}
pub fn is_armed(&self) -> bool {
self.armed.load(Ordering::Acquire)
}
pub fn next_frame(&self) -> Option<FrameValue> {
pub fn next_frame(&mut self) -> Option<FrameValue> {
if !self.is_armed() {
return None;
}
if self.remaining.load(Ordering::Acquire) != 0 {
self.remaining.fetch_sub(1, Ordering::AcqRel);
if self.remaining != 0 {
self.remaining -= 1;
return Some(FrameValue::Minimum);
}
match PulseWidth::new(self.armed_idle.load(Ordering::Acquire)) {
Some(pulse) => Some(FrameValue::ArmedIdle(pulse)),
None => unreachable!(),
}
Some(FrameValue::ArmedIdle(self.armed_idle))
}
}
@@ -176,7 +165,7 @@ mod tests {
#[test]
fn sequence_holds_minimum_before_armed_idle() {
let pulse = PulseWidth::new(1_100).unwrap();
let sequence = ArmSequence::new(pulse, 2);
let mut sequence = ArmSequence::new(pulse, 2);
sequence.arm();
assert_eq!(sequence.next_frame(), Some(FrameValue::Minimum));
assert_eq!(sequence.next_frame(), Some(FrameValue::Minimum));