Skip to main content

piper_driver/
mode.rs

1//! Driver 模式定义
2//!
3//! 定义 Piper 驱动的工作模式,用于控制 TX 线程行为。
4
5use std::sync::atomic::{AtomicU8, Ordering};
6
7/// Driver 工作模式
8///
9/// # 模式说明
10///
11/// - **Normal**: 正常模式,TX 线程按周期发送控制指令(MIT/Position)
12/// - **Replay**: 回放模式,TX 线程暂停周期性发送,仅发送显式指令
13///
14/// # 设计目的
15///
16/// Replay 模式用于安全地回放预先录制的 CAN 帧,避免双控制流冲突:
17/// - 正常模式:TX 线程每 1ms 发送一次控制指令
18/// - 回放模式:暂停 TX 线程,由回放逻辑控制帧发送时机
19///
20/// # 线程安全
21///
22/// 使用原子操作确保模式切换的线程安全性。
23#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
24#[repr(u8)]
25pub enum DriverMode {
26    /// 正常模式(默认)
27    ///
28    /// TX 线程按周期发送控制指令(MIT/Position 模式)。
29    #[default]
30    Normal = 0,
31
32    /// 回放模式
33    ///
34    /// TX 线程暂停周期性发送,仅发送显式指令。
35    /// 用于安全回放预先录制的 CAN 帧。
36    Replay = 1,
37}
38
39impl DriverMode {
40    /// 从 u8 转换
41    ///
42    /// 如果值无效,返回 Normal 模式。
43    pub fn from_u8(value: u8) -> Self {
44        match value {
45            0 => Self::Normal,
46            1 => Self::Replay,
47            _ => Self::Normal, // 无效值默认为 Normal
48        }
49    }
50
51    /// 转换为 u8
52    pub fn as_u8(self) -> u8 {
53        self as u8
54    }
55
56    /// 是否为回放模式
57    pub fn is_replay(self) -> bool {
58        self == Self::Replay
59    }
60
61    /// 是否为正常模式
62    pub fn is_normal(self) -> bool {
63        self == Self::Normal
64    }
65}
66
67/// Driver 模式(原子版本,用于线程间共享)
68///
69/// # 使用场景
70///
71/// - TX 线程读取模式决定是否发送周期性指令
72/// - 主线程通过 `set_mode()` 切换模式
73///
74/// # 示例
75///
76/// ```rust,no_run
77/// use piper_driver::mode::{AtomicDriverMode, DriverMode};
78/// use std::sync::atomic::Ordering;
79///
80/// let mode = AtomicDriverMode::new(DriverMode::Normal);
81///
82/// // 读取模式
83/// let current = mode.get(Ordering::Relaxed);
84///
85/// // 切换到回放模式
86/// mode.set(DriverMode::Replay, Ordering::Relaxed);
87/// ```
88#[derive(Debug)]
89pub struct AtomicDriverMode {
90    inner: AtomicU8,
91}
92
93impl AtomicDriverMode {
94    /// 创建新的原子模式
95    pub fn new(mode: DriverMode) -> Self {
96        Self {
97            inner: AtomicU8::new(mode.as_u8()),
98        }
99    }
100
101    /// 获取当前模式
102    ///
103    /// # 参数
104    ///
105    /// - `ordering`: 内存序(通常使用 Relaxed 即可)
106    pub fn get(&self, ordering: Ordering) -> DriverMode {
107        DriverMode::from_u8(self.inner.load(ordering))
108    }
109
110    /// 设置模式
111    ///
112    /// # 参数
113    ///
114    /// - `mode`: 新模式
115    /// - `ordering`: 内存序(通常使用 Relaxed 即可)
116    pub fn set(&self, mode: DriverMode, ordering: Ordering) {
117        self.inner.store(mode.as_u8(), ordering);
118    }
119
120    /// 比较并交换(Compare-and-Swap)
121    ///
122    /// # 参数
123    ///
124    /// - `current`: 期望的当前值
125    /// - `new`: 新值
126    /// - `ordering`: 内存序
127    ///
128    /// # 返回
129    ///
130    /// 如果当前值等于 `current`,则设置为 `new` 并返回 true
131    /// 否则返回 false
132    pub fn compare_exchange(
133        &self,
134        current: DriverMode,
135        new: DriverMode,
136        success: Ordering,
137        failure: Ordering,
138    ) -> bool {
139        self.inner
140            .compare_exchange(current.as_u8(), new.as_u8(), success, failure)
141            .is_ok()
142    }
143}
144
145impl Clone for AtomicDriverMode {
146    fn clone(&self) -> Self {
147        Self::new(self.get(Ordering::Relaxed))
148    }
149}
150
151#[cfg(test)]
152mod tests {
153    use super::*;
154
155    #[test]
156    fn test_driver_mode_conversions() {
157        let normal = DriverMode::Normal;
158        let replay = DriverMode::Replay;
159
160        assert_eq!(normal.as_u8(), 0);
161        assert_eq!(replay.as_u8(), 1);
162
163        assert!(normal.is_normal());
164        assert!(!normal.is_replay());
165
166        assert!(replay.is_replay());
167        assert!(!replay.is_normal());
168    }
169
170    #[test]
171    fn test_from_u8() {
172        assert_eq!(DriverMode::from_u8(0), DriverMode::Normal);
173        assert_eq!(DriverMode::from_u8(1), DriverMode::Replay);
174        assert_eq!(DriverMode::from_u8(255), DriverMode::Normal); // 无效值
175    }
176
177    #[test]
178    fn test_atomic_driver_mode() {
179        let mode = AtomicDriverMode::new(DriverMode::Normal);
180
181        assert_eq!(mode.get(Ordering::Relaxed), DriverMode::Normal);
182
183        mode.set(DriverMode::Replay, Ordering::Relaxed);
184        assert_eq!(mode.get(Ordering::Relaxed), DriverMode::Replay);
185
186        // 测试 compare_exchange
187        assert!(mode.compare_exchange(
188            DriverMode::Replay,
189            DriverMode::Normal,
190            Ordering::Relaxed,
191            Ordering::Relaxed
192        ));
193        assert_eq!(mode.get(Ordering::Relaxed), DriverMode::Normal);
194
195        // 失败情况
196        assert!(!mode.compare_exchange(
197            DriverMode::Replay, // 期望值是 Replay,但实际是 Normal
198            DriverMode::Replay,
199            Ordering::Relaxed,
200            Ordering::Relaxed
201        ));
202    }
203
204    #[test]
205    fn test_default() {
206        let mode: DriverMode = Default::default();
207        assert_eq!(mode, DriverMode::Normal);
208    }
209}