peak_can/
io.rs

1//!
2//!
3//!
4//!
5
6/* IO DIGITAL CONFIGURATION trait */
7
8use crate::channel::Channel;
9use crate::error::{CanError, CanOkError};
10use crate::peak_lib;
11use crate::peak_can;
12use std::ffi::c_void;
13
14#[derive(PartialEq, Debug)]
15pub enum IOConfig {
16    In,
17    InOut,
18}
19
20impl TryFrom<u32> for IOConfig {
21    type Error = ();
22
23    fn try_from(value: u32) -> Result<Self, Self::Error> {
24        match value {
25            0 => Ok(IOConfig::In),
26            1 => Ok(IOConfig::InOut),
27            _ => Err(()),
28        }
29    }
30}
31
32impl From<IOConfig> for u32 {
33    fn from(value: IOConfig) -> Self {
34        match value {
35            IOConfig::In => 0,
36            IOConfig::InOut => 1,
37        }
38    }
39}
40
41pub(crate) trait HasDigitalConfiguration {}
42
43pub trait DigitalConfiguration {
44    fn digital_mode(&self, pin: u8) -> Result<IOConfig, CanError>;
45    fn digital_mode_word(&self) -> Result<u32, CanError>;
46}
47
48impl<T: HasDigitalConfiguration + Channel> DigitalConfiguration for T {
49    fn digital_mode(&self, pin: u8) -> Result<IOConfig, CanError> {
50        let mut data = [0u8; 4];
51        let code = unsafe {
52            peak_lib()?.CAN_GetValue(
53                self.channel(),
54                peak_can::PEAK_IO_DIGITAL_CONFIGURATION as u8,
55                data.as_mut_ptr() as *mut c_void,
56                data.len() as u32,
57            )
58        };
59
60        match CanOkError::try_from(code) {
61            Ok(CanOkError::Ok) => {
62                let mode_word = u32::from_le_bytes(data);
63                let pin_enabled = mode_word & (1 << pin);
64
65                if pin_enabled == 0 {
66                    Ok(IOConfig::In)
67                } else {
68                    Ok(IOConfig::InOut)
69                }
70            }
71            Ok(CanOkError::Err(err)) => Err(err),
72            Err(_) => Err(CanError::Unknown),
73        }
74    }
75
76    fn digital_mode_word(&self) -> Result<u32, CanError> {
77        let mut data = [0u8; 4];
78        let code = unsafe {
79            peak_lib()?.CAN_GetValue(
80                self.channel(),
81                peak_can::PEAK_IO_DIGITAL_CONFIGURATION as u8,
82                data.as_mut_ptr() as *mut c_void,
83                data.len() as u32,
84            )
85        };
86
87        match CanOkError::try_from(code) {
88            Ok(CanOkError::Ok) => Ok(u32::from_le_bytes(data)),
89            Ok(CanOkError::Err(err)) => Err(err),
90            Err(_) => Err(CanError::Unknown),
91        }
92    }
93}
94
95pub(crate) trait HasSetDigitalConfiguration {}
96
97pub trait SetDigitalConfiguration {
98    fn set_digital_mode(&self, pin: u8, mode: IOConfig) -> Result<(), CanError>;
99    fn set_digital_mode_word(&self, mode_word: u32) -> Result<(), CanError>;
100}
101
102impl<T: HasSetDigitalConfiguration + Channel> SetDigitalConfiguration for T {
103    fn set_digital_mode(&self, pin: u8, mode: IOConfig) -> Result<(), CanError> {
104        let mut data = [0u8; 4];
105        let code = unsafe {
106            peak_lib()?.CAN_GetValue(
107                self.channel(),
108                peak_can::PEAK_IO_DIGITAL_CONFIGURATION as u8,
109                data.as_mut_ptr() as *mut c_void,
110                data.len() as u32,
111            )
112        };
113
114        let mode_word = match CanOkError::try_from(code) {
115            Ok(CanOkError::Ok) => u32::from_le_bytes(data),
116            Ok(CanOkError::Err(err)) => return Err(err),
117            Err(_) => return Err(CanError::Unknown),
118        };
119
120        let mode_word = match mode {
121            IOConfig::In => mode_word | !(1 << pin),
122            IOConfig::InOut => mode_word | (1 << pin),
123        };
124        let mut data = mode_word.to_le_bytes();
125
126        let code = unsafe {
127            peak_lib()?.CAN_SetValue(
128                self.channel(),
129                peak_can::PEAK_IO_DIGITAL_CONFIGURATION as u8,
130                data.as_mut_ptr() as *mut c_void,
131                data.len() as u32,
132            )
133        };
134
135        return match CanOkError::try_from(code) {
136            Ok(CanOkError::Ok) => Ok(()),
137            Ok(CanOkError::Err(err)) => Err(err),
138            Err(_) => Err(CanError::Unknown),
139        };
140    }
141
142    fn set_digital_mode_word(&self, mode_word: u32) -> Result<(), CanError> {
143        let mut data = mode_word.to_le_bytes();
144        let code = unsafe {
145            peak_lib()?.CAN_SetValue(
146                self.channel(),
147                peak_can::PEAK_IO_DIGITAL_CONFIGURATION as u8,
148                data.as_mut_ptr() as *mut c_void,
149                data.len() as u32,
150            )
151        };
152
153        match CanOkError::try_from(code) {
154            Ok(CanOkError::Ok) => Ok(()),
155            Ok(CanOkError::Err(err)) => Err(err),
156            Err(_) => Err(CanError::Unknown),
157        }
158    }
159}
160
161/* IO DIGITAL VALUE */
162
163#[derive(PartialEq, Debug)]
164pub enum IOValue {
165    Low,
166    High,
167}
168
169impl TryFrom<u32> for IOValue {
170    type Error = ();
171
172    fn try_from(value: u32) -> Result<Self, Self::Error> {
173        match value {
174            0 => Ok(IOValue::Low),
175            1 => Ok(IOValue::High),
176            _ => Err(()),
177        }
178    }
179}
180
181impl From<IOValue> for u32 {
182    fn from(value: IOValue) -> Self {
183        match value {
184            IOValue::Low => 0,
185            IOValue::High => 1,
186        }
187    }
188}
189
190#[allow(unused)]
191pub(crate) trait HasDigitalValue {}
192
193pub trait DigitalValue {
194    fn digital_value(&self, pin: u8) -> Result<IOValue, CanError>;
195    fn digital_value_word(&self) -> Result<u32, CanError>;
196}
197
198impl<T: HasSetDigitalValue + Channel> DigitalValue for T {
199    fn digital_value(&self, pin: u8) -> Result<IOValue, CanError> {
200        let mut data = [0u8; 4];
201        let code = unsafe {
202            peak_lib()?.CAN_GetValue(
203                self.channel(),
204                peak_can::PEAK_IO_DIGITAL_VALUE as u8,
205                data.as_mut_ptr() as *mut c_void,
206                data.len() as u32,
207            )
208        };
209
210        match CanOkError::try_from(code) {
211            Ok(CanOkError::Ok) => {
212                let mode_word = u32::from_le_bytes(data);
213                let pin_enabled = mode_word & (1 << pin);
214
215                if pin_enabled == 0 {
216                    Ok(IOValue::Low)
217                } else {
218                    Ok(IOValue::High)
219                }
220            }
221            Ok(CanOkError::Err(err)) => Err(err),
222            Err(_) => Err(CanError::Unknown),
223        }
224    }
225
226    fn digital_value_word(&self) -> Result<u32, CanError> {
227        let mut data = [0u8; 4];
228        let code = unsafe {
229            peak_lib()?.CAN_GetValue(
230                self.channel(),
231                peak_can::PEAK_IO_DIGITAL_VALUE as u8,
232                data.as_mut_ptr() as *mut c_void,
233                data.len() as u32,
234            )
235        };
236
237        match CanOkError::try_from(code) {
238            Ok(CanOkError::Ok) => Ok(u32::from_le_bytes(data)),
239            Ok(CanOkError::Err(err)) => Err(err),
240            Err(_) => Err(CanError::Unknown),
241        }
242    }
243}
244
245pub(crate) trait HasSetDigitalValue {}
246
247pub trait SetDigitalValue {
248    fn set_digital_value(&self, pin: u8, value: IOValue) -> Result<(), CanError>;
249    fn set_digital_value_word(&self, value_word: u32) -> Result<(), CanError>;
250}
251
252impl<T: HasSetDigitalValue + Channel> SetDigitalValue for T {
253    fn set_digital_value(&self, pin: u8, value: IOValue) -> Result<(), CanError> {
254        let mut data = [0u8; 4];
255        let code = unsafe {
256            peak_lib()?.CAN_GetValue(
257                self.channel(),
258                peak_can::PEAK_IO_DIGITAL_CONFIGURATION as u8,
259                data.as_mut_ptr() as *mut c_void,
260                data.len() as u32,
261            )
262        };
263
264        let mode_word = match CanOkError::try_from(code) {
265            Ok(CanOkError::Ok) => u32::from_le_bytes(data),
266            Ok(CanOkError::Err(err)) => return Err(err),
267            Err(_) => return Err(CanError::Unknown),
268        };
269
270        let mode_word = match value {
271            IOValue::Low => mode_word | !(1 << pin),
272            IOValue::High => mode_word | (1 << pin),
273        };
274        let mut data = mode_word.to_le_bytes();
275
276        let code = unsafe {
277            peak_lib()?.CAN_SetValue(
278                self.channel(),
279                peak_can::PEAK_IO_DIGITAL_VALUE as u8,
280                data.as_mut_ptr() as *mut c_void,
281                data.len() as u32,
282            )
283        };
284
285        return match CanOkError::try_from(code) {
286            Ok(CanOkError::Ok) => Ok(()),
287            Ok(CanOkError::Err(err)) => Err(err),
288            Err(_) => Err(CanError::Unknown),
289        };
290    }
291
292    fn set_digital_value_word(&self, value_word: u32) -> Result<(), CanError> {
293        let mut data = value_word.to_le_bytes();
294        let code = unsafe {
295            peak_lib()?.CAN_SetValue(
296                self.channel(),
297                peak_can::PEAK_IO_DIGITAL_VALUE as u8,
298                data.as_mut_ptr() as *mut c_void,
299                data.len() as u32,
300            )
301        };
302
303        match CanOkError::try_from(code) {
304            Ok(CanOkError::Ok) => Ok(()),
305            Ok(CanOkError::Err(err)) => Err(err),
306            Err(_) => Err(CanError::Unknown),
307        }
308    }
309}
310
311/* IO DIGITAL SET */
312
313pub(crate) trait HasSetDigitalSet {}
314
315pub trait SetDigitalSet {
316    fn digital_set(&self, mask: u32) -> Result<(), CanError>;
317}
318
319impl<T: HasSetDigitalSet + Channel> SetDigitalSet for T {
320    fn digital_set(&self, mask: u32) -> Result<(), CanError> {
321        let mut data = mask.to_le_bytes();
322        let code = unsafe {
323            peak_lib()?.CAN_SetValue(
324                self.channel(),
325                peak_can::PEAK_IO_DIGITAL_SET as u8,
326                data.as_mut_ptr() as *mut c_void,
327                data.len() as u32,
328            )
329        };
330
331        match CanOkError::try_from(code) {
332            Ok(CanOkError::Ok) => Ok(()),
333            Ok(CanOkError::Err(err)) => Err(err),
334            Err(_) => Err(CanError::Unknown),
335        }
336    }
337}
338
339/* IO DIGITAL CLEAR */
340
341pub(crate) trait HasSetDigitalClear {}
342
343pub trait SetDigitalClear {
344    fn digital_clear(&self, mask: u32) -> Result<(), CanError>;
345}
346
347impl<T: HasSetDigitalClear + Channel> SetDigitalClear for T {
348    fn digital_clear(&self, mask: u32) -> Result<(), CanError> {
349        let mut data = mask.to_le_bytes();
350        let code = unsafe {
351            peak_lib()?.CAN_SetValue(
352                self.channel(),
353                peak_can::PEAK_IO_DIGITAL_CLEAR as u8,
354                data.as_mut_ptr() as *mut c_void,
355                data.len() as u32,
356            )
357        };
358
359        match CanOkError::try_from(code) {
360            Ok(CanOkError::Ok) => Ok(()),
361            Ok(CanOkError::Err(err)) => Err(err),
362            Err(_) => Err(CanError::Unknown),
363        }
364    }
365}
366
367/* IO ANALOG VALUE */
368
369pub(crate) trait HasAnalogValue {}
370
371pub trait AnalogValue {
372    fn analog_value(&self) -> Result<u32, CanError>;
373}
374
375impl<T: HasAnalogValue + Channel> AnalogValue for T {
376    fn analog_value(&self) -> Result<u32, CanError> {
377        let mut data = [0u8; 4];
378        let code = unsafe {
379            peak_lib()?.CAN_GetValue(
380                self.channel(),
381                peak_can::PEAK_IO_ANALOG_VALUE as u8,
382                data.as_mut_ptr() as *mut c_void,
383                data.len() as u32,
384            )
385        };
386
387        match CanOkError::try_from(code) {
388            Ok(CanOkError::Ok) => Ok(u32::from_le_bytes(data)),
389            Ok(CanOkError::Err(err)) => Err(err),
390            Err(_) => Err(CanError::Unknown),
391        }
392    }
393}