Skip to main content

neoradio2/
types.rs

1use crate::ffi;
2use std::time::Duration;
3
4macro_rules! int_enum {
5    ($(#[$m:meta])* $name:ident { $($(#[$vm:meta])* $variant:ident = $val:expr),* $(,)? }) => {
6        $(#[$m])*
7        #[derive(Debug, Clone, Copy, PartialEq, Eq)]
8        pub enum $name { $($(#[$vm])* $variant = $val),* }
9        impl $name {
10            /// Convert from the C integer value.
11            pub fn from_raw(v: i32) -> Option<Self> {
12                match v { $($val => Some($name::$variant),)* _ => None }
13            }
14            /// The C integer value.
15            pub fn as_raw(self) -> i32 { match self { $($name::$variant => $val),* } }
16        }
17    };
18}
19
20int_enum!(
21    /// neoRAD-IO2 device type.
22    DeviceType {
23        /// Thermocouple module.
24        Tc = 0,
25        /// Digital I/O module.
26        Dio = 1,
27        /// Power relay module.
28        PwrRly = 2,
29        /// Analog input module.
30        Ain = 3,
31        /// Analog output module.
32        Aout = 4,
33        /// CAN hub module.
34        CanHub = 5,
35        /// Badge module.
36        Badge = 6,
37        /// Host (non-module) device.
38        Host = 0xFF
39    }
40);
41int_enum!(
42    /// Sensor read calibration mode.
43    CalType {
44        /// Apply stored calibration.
45        Enabled = 0,
46        /// Return raw, uncalibrated data.
47        NoCal = 1,
48        /// Return raw data with enhanced (extended-range) scaling.
49        NoCalEnhanced = 2
50    }
51);
52int_enum!(
53    /// LED toggle mode.
54    LedMode {
55        /// Turn the LED(s) off.
56        Off = 0,
57        /// Turn the LED(s) on.
58        On = 1,
59        /// Blink the LED(s) once.
60        BlinkOnce = 2,
61        /// Blink the LED(s) for a given duration in milliseconds.
62        BlinkDurationMs = 3
63    }
64);
65int_enum!(
66    /// Status query type (see `Device::status`).
67    StatusType {
68        /// Chain identification status.
69        Chain = 0,
70        /// Application firmware start status.
71        AppStart = 1,
72        /// PCB serial number read status.
73        Pcbsn = 2,
74        /// Sensor read status.
75        SensorRead = 3,
76        /// Sensor write status.
77        SensorWrite = 4,
78        /// Settings read status.
79        SettingsRead = 5,
80        /// Settings write status.
81        SettingsWrite = 6,
82        /// Calibration write status.
83        Calibration = 7,
84        /// Calibration points write status.
85        CalibrationPoints = 8,
86        /// Calibration stored status.
87        CalibrationStored = 9,
88        /// Calibration info status.
89        CalibrationInfo = 10,
90        /// LED toggle status.
91        LedToggle = 11,
92    }
93);
94int_enum!(
95    /// Command status returned by `Device::status`.
96    CommandStatus {
97        /// The command has not yet finished.
98        InProgress = 0,
99        /// The command completed successfully.
100        Finished = 1,
101        /// The command failed.
102        Error = 2
103    }
104);
105
106/// Set process-global blocking mode. In blocking mode, calls wait up to
107/// `timeout` for completion; in non-blocking mode they return immediately.
108pub fn set_blocking(blocking: bool, timeout: Duration) {
109    let ms = timeout.as_millis().min(i64::MAX as u128) as std::os::raw::c_longlong;
110    unsafe { ffi::neoradio2_set_blocking(if blocking { 1 } else { 0 }, ms) };
111}
112
113/// Whether the API is in blocking mode.
114pub fn is_blocking() -> bool {
115    unsafe { ffi::neoradio2_is_blocking() != 0 }
116}
117
118#[cfg(test)]
119mod tests {
120    use super::*;
121    #[test]
122    fn device_type_round_trip() {
123        for (v, t) in [
124            (0, DeviceType::Tc),
125            (3, DeviceType::Ain),
126            (6, DeviceType::Badge),
127        ] {
128            assert_eq!(DeviceType::from_raw(v), Some(t));
129            assert_eq!(t.as_raw(), v);
130        }
131        assert_eq!(DeviceType::from_raw(42), None);
132        // Host uses a non-sequential C value (0xFF); verify accessors and the
133        // native discriminant cast all agree.
134        assert_eq!(DeviceType::from_raw(0xFF), Some(DeviceType::Host));
135        assert_eq!(DeviceType::Host.as_raw(), 0xFF);
136        assert_eq!(DeviceType::Host as i32, 0xFF);
137    }
138    #[test]
139    fn blocking_round_trips() {
140        set_blocking(true, std::time::Duration::from_millis(500));
141        assert!(is_blocking());
142        set_blocking(false, std::time::Duration::from_millis(500));
143        assert!(!is_blocking());
144    }
145    #[test]
146    fn caltype_values() {
147        assert_eq!(CalType::Enabled.as_raw(), 0);
148        assert_eq!(CalType::NoCal.as_raw(), 1);
149    }
150}