tinkerforge/bindings/
io4_v2_bricklet.rs

1/* ***********************************************************
2 * This file was automatically generated on 2024-02-27.      *
3 *                                                           *
4 * Rust Bindings Version 2.0.21                              *
5 *                                                           *
6 * If you have a bugfix for this file and want to commit it, *
7 * please fix the bug in the generator. You can find a link  *
8 * to the generators git repository on tinkerforge.com       *
9 *************************************************************/
10
11//! 4-channel digital input/output.
12//!
13//! See also the documentation [here](https://www.tinkerforge.com/en/doc/Software/Bricklets/IO4V2_Bricklet_Rust.html).
14use crate::{
15    byte_converter::*, converting_callback_receiver::ConvertingCallbackReceiver, converting_receiver::ConvertingReceiver, device::*,
16    ip_connection::GetRequestSender,
17};
18pub enum Io4V2BrickletFunction {
19    SetValue,
20    GetValue,
21    SetSelectedValue,
22    SetConfiguration,
23    GetConfiguration,
24    SetInputValueCallbackConfiguration,
25    GetInputValueCallbackConfiguration,
26    SetAllInputValueCallbackConfiguration,
27    GetAllInputValueCallbackConfiguration,
28    SetMonoflop,
29    GetMonoflop,
30    GetEdgeCount,
31    SetEdgeCountConfiguration,
32    GetEdgeCountConfiguration,
33    SetPwmConfiguration,
34    GetPwmConfiguration,
35    GetSpitfpErrorCount,
36    SetBootloaderMode,
37    GetBootloaderMode,
38    SetWriteFirmwarePointer,
39    WriteFirmware,
40    SetStatusLedConfig,
41    GetStatusLedConfig,
42    GetChipTemperature,
43    Reset,
44    WriteUid,
45    ReadUid,
46    GetIdentity,
47    CallbackInputValue,
48    CallbackAllInputValue,
49    CallbackMonoflopDone,
50}
51impl From<Io4V2BrickletFunction> for u8 {
52    fn from(fun: Io4V2BrickletFunction) -> Self {
53        match fun {
54            Io4V2BrickletFunction::SetValue => 1,
55            Io4V2BrickletFunction::GetValue => 2,
56            Io4V2BrickletFunction::SetSelectedValue => 3,
57            Io4V2BrickletFunction::SetConfiguration => 4,
58            Io4V2BrickletFunction::GetConfiguration => 5,
59            Io4V2BrickletFunction::SetInputValueCallbackConfiguration => 6,
60            Io4V2BrickletFunction::GetInputValueCallbackConfiguration => 7,
61            Io4V2BrickletFunction::SetAllInputValueCallbackConfiguration => 8,
62            Io4V2BrickletFunction::GetAllInputValueCallbackConfiguration => 9,
63            Io4V2BrickletFunction::SetMonoflop => 10,
64            Io4V2BrickletFunction::GetMonoflop => 11,
65            Io4V2BrickletFunction::GetEdgeCount => 12,
66            Io4V2BrickletFunction::SetEdgeCountConfiguration => 13,
67            Io4V2BrickletFunction::GetEdgeCountConfiguration => 14,
68            Io4V2BrickletFunction::SetPwmConfiguration => 15,
69            Io4V2BrickletFunction::GetPwmConfiguration => 16,
70            Io4V2BrickletFunction::GetSpitfpErrorCount => 234,
71            Io4V2BrickletFunction::SetBootloaderMode => 235,
72            Io4V2BrickletFunction::GetBootloaderMode => 236,
73            Io4V2BrickletFunction::SetWriteFirmwarePointer => 237,
74            Io4V2BrickletFunction::WriteFirmware => 238,
75            Io4V2BrickletFunction::SetStatusLedConfig => 239,
76            Io4V2BrickletFunction::GetStatusLedConfig => 240,
77            Io4V2BrickletFunction::GetChipTemperature => 242,
78            Io4V2BrickletFunction::Reset => 243,
79            Io4V2BrickletFunction::WriteUid => 248,
80            Io4V2BrickletFunction::ReadUid => 249,
81            Io4V2BrickletFunction::GetIdentity => 255,
82            Io4V2BrickletFunction::CallbackInputValue => 17,
83            Io4V2BrickletFunction::CallbackAllInputValue => 18,
84            Io4V2BrickletFunction::CallbackMonoflopDone => 19,
85        }
86    }
87}
88pub const IO4_V2_BRICKLET_DIRECTION_IN: char = 'i';
89pub const IO4_V2_BRICKLET_DIRECTION_OUT: char = 'o';
90pub const IO4_V2_BRICKLET_EDGE_TYPE_RISING: u8 = 0;
91pub const IO4_V2_BRICKLET_EDGE_TYPE_FALLING: u8 = 1;
92pub const IO4_V2_BRICKLET_EDGE_TYPE_BOTH: u8 = 2;
93pub const IO4_V2_BRICKLET_BOOTLOADER_MODE_BOOTLOADER: u8 = 0;
94pub const IO4_V2_BRICKLET_BOOTLOADER_MODE_FIRMWARE: u8 = 1;
95pub const IO4_V2_BRICKLET_BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT: u8 = 2;
96pub const IO4_V2_BRICKLET_BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT: u8 = 3;
97pub const IO4_V2_BRICKLET_BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT: u8 = 4;
98pub const IO4_V2_BRICKLET_BOOTLOADER_STATUS_OK: u8 = 0;
99pub const IO4_V2_BRICKLET_BOOTLOADER_STATUS_INVALID_MODE: u8 = 1;
100pub const IO4_V2_BRICKLET_BOOTLOADER_STATUS_NO_CHANGE: u8 = 2;
101pub const IO4_V2_BRICKLET_BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT: u8 = 3;
102pub const IO4_V2_BRICKLET_BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT: u8 = 4;
103pub const IO4_V2_BRICKLET_BOOTLOADER_STATUS_CRC_MISMATCH: u8 = 5;
104pub const IO4_V2_BRICKLET_STATUS_LED_CONFIG_OFF: u8 = 0;
105pub const IO4_V2_BRICKLET_STATUS_LED_CONFIG_ON: u8 = 1;
106pub const IO4_V2_BRICKLET_STATUS_LED_CONFIG_SHOW_HEARTBEAT: u8 = 2;
107pub const IO4_V2_BRICKLET_STATUS_LED_CONFIG_SHOW_STATUS: u8 = 3;
108
109#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
110pub struct Configuration {
111    pub direction: char,
112    pub value: bool,
113}
114impl FromByteSlice for Configuration {
115    fn bytes_expected() -> usize { 2 }
116    fn from_le_byte_slice(bytes: &[u8]) -> Configuration {
117        Configuration { direction: <char>::from_le_byte_slice(&bytes[0..1]), value: <bool>::from_le_byte_slice(&bytes[1..2]) }
118    }
119}
120
121#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
122pub struct InputValueCallbackConfiguration {
123    pub period: u32,
124    pub value_has_to_change: bool,
125}
126impl FromByteSlice for InputValueCallbackConfiguration {
127    fn bytes_expected() -> usize { 5 }
128    fn from_le_byte_slice(bytes: &[u8]) -> InputValueCallbackConfiguration {
129        InputValueCallbackConfiguration {
130            period: <u32>::from_le_byte_slice(&bytes[0..4]),
131            value_has_to_change: <bool>::from_le_byte_slice(&bytes[4..5]),
132        }
133    }
134}
135
136#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
137pub struct AllInputValueCallbackConfiguration {
138    pub period: u32,
139    pub value_has_to_change: bool,
140}
141impl FromByteSlice for AllInputValueCallbackConfiguration {
142    fn bytes_expected() -> usize { 5 }
143    fn from_le_byte_slice(bytes: &[u8]) -> AllInputValueCallbackConfiguration {
144        AllInputValueCallbackConfiguration {
145            period: <u32>::from_le_byte_slice(&bytes[0..4]),
146            value_has_to_change: <bool>::from_le_byte_slice(&bytes[4..5]),
147        }
148    }
149}
150
151#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
152pub struct Monoflop {
153    pub value: bool,
154    pub time: u32,
155    pub time_remaining: u32,
156}
157impl FromByteSlice for Monoflop {
158    fn bytes_expected() -> usize { 9 }
159    fn from_le_byte_slice(bytes: &[u8]) -> Monoflop {
160        Monoflop {
161            value: <bool>::from_le_byte_slice(&bytes[0..1]),
162            time: <u32>::from_le_byte_slice(&bytes[1..5]),
163            time_remaining: <u32>::from_le_byte_slice(&bytes[5..9]),
164        }
165    }
166}
167
168#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
169pub struct EdgeCountConfiguration {
170    pub edge_type: u8,
171    pub debounce: u8,
172}
173impl FromByteSlice for EdgeCountConfiguration {
174    fn bytes_expected() -> usize { 2 }
175    fn from_le_byte_slice(bytes: &[u8]) -> EdgeCountConfiguration {
176        EdgeCountConfiguration { edge_type: <u8>::from_le_byte_slice(&bytes[0..1]), debounce: <u8>::from_le_byte_slice(&bytes[1..2]) }
177    }
178}
179
180#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
181pub struct PwmConfiguration {
182    pub frequency: u32,
183    pub duty_cycle: u16,
184}
185impl FromByteSlice for PwmConfiguration {
186    fn bytes_expected() -> usize { 6 }
187    fn from_le_byte_slice(bytes: &[u8]) -> PwmConfiguration {
188        PwmConfiguration { frequency: <u32>::from_le_byte_slice(&bytes[0..4]), duty_cycle: <u16>::from_le_byte_slice(&bytes[4..6]) }
189    }
190}
191
192#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
193pub struct InputValueEvent {
194    pub channel: u8,
195    pub changed: bool,
196    pub value: bool,
197}
198impl FromByteSlice for InputValueEvent {
199    fn bytes_expected() -> usize { 3 }
200    fn from_le_byte_slice(bytes: &[u8]) -> InputValueEvent {
201        InputValueEvent {
202            channel: <u8>::from_le_byte_slice(&bytes[0..1]),
203            changed: <bool>::from_le_byte_slice(&bytes[1..2]),
204            value: <bool>::from_le_byte_slice(&bytes[2..3]),
205        }
206    }
207}
208
209#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
210pub struct AllInputValueEvent {
211    pub changed: [bool; 4],
212    pub value: [bool; 4],
213}
214impl FromByteSlice for AllInputValueEvent {
215    fn bytes_expected() -> usize { 2 }
216    fn from_le_byte_slice(bytes: &[u8]) -> AllInputValueEvent {
217        AllInputValueEvent { changed: <[bool; 4]>::from_le_byte_slice(&bytes[0..1]), value: <[bool; 4]>::from_le_byte_slice(&bytes[1..2]) }
218    }
219}
220
221#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
222pub struct MonoflopDoneEvent {
223    pub channel: u8,
224    pub value: bool,
225}
226impl FromByteSlice for MonoflopDoneEvent {
227    fn bytes_expected() -> usize { 2 }
228    fn from_le_byte_slice(bytes: &[u8]) -> MonoflopDoneEvent {
229        MonoflopDoneEvent { channel: <u8>::from_le_byte_slice(&bytes[0..1]), value: <bool>::from_le_byte_slice(&bytes[1..2]) }
230    }
231}
232
233#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
234pub struct SpitfpErrorCount {
235    pub error_count_ack_checksum: u32,
236    pub error_count_message_checksum: u32,
237    pub error_count_frame: u32,
238    pub error_count_overflow: u32,
239}
240impl FromByteSlice for SpitfpErrorCount {
241    fn bytes_expected() -> usize { 16 }
242    fn from_le_byte_slice(bytes: &[u8]) -> SpitfpErrorCount {
243        SpitfpErrorCount {
244            error_count_ack_checksum: <u32>::from_le_byte_slice(&bytes[0..4]),
245            error_count_message_checksum: <u32>::from_le_byte_slice(&bytes[4..8]),
246            error_count_frame: <u32>::from_le_byte_slice(&bytes[8..12]),
247            error_count_overflow: <u32>::from_le_byte_slice(&bytes[12..16]),
248        }
249    }
250}
251
252#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
253pub struct Identity {
254    pub uid: String,
255    pub connected_uid: String,
256    pub position: char,
257    pub hardware_version: [u8; 3],
258    pub firmware_version: [u8; 3],
259    pub device_identifier: u16,
260}
261impl FromByteSlice for Identity {
262    fn bytes_expected() -> usize { 25 }
263    fn from_le_byte_slice(bytes: &[u8]) -> Identity {
264        Identity {
265            uid: <String>::from_le_byte_slice(&bytes[0..8]),
266            connected_uid: <String>::from_le_byte_slice(&bytes[8..16]),
267            position: <char>::from_le_byte_slice(&bytes[16..17]),
268            hardware_version: <[u8; 3]>::from_le_byte_slice(&bytes[17..20]),
269            firmware_version: <[u8; 3]>::from_le_byte_slice(&bytes[20..23]),
270            device_identifier: <u16>::from_le_byte_slice(&bytes[23..25]),
271        }
272    }
273}
274
275/// 4-channel digital input/output
276#[derive(Clone)]
277pub struct Io4V2Bricklet {
278    device: Device,
279}
280impl Io4V2Bricklet {
281    pub const DEVICE_IDENTIFIER: u16 = 2111;
282    pub const DEVICE_DISPLAY_NAME: &'static str = "IO-4 Bricklet 2.0";
283    /// Creates an object with the unique device ID `uid`. This object can then be used after the IP Connection `ip_connection` is connected.
284    pub fn new<T: GetRequestSender>(uid: &str, req_sender: T) -> Io4V2Bricklet {
285        let mut result = Io4V2Bricklet { device: Device::new([2, 0, 0], uid, req_sender, 0) };
286        result.device.response_expected[u8::from(Io4V2BrickletFunction::SetValue) as usize] = ResponseExpectedFlag::False;
287        result.device.response_expected[u8::from(Io4V2BrickletFunction::GetValue) as usize] = ResponseExpectedFlag::AlwaysTrue;
288        result.device.response_expected[u8::from(Io4V2BrickletFunction::SetSelectedValue) as usize] = ResponseExpectedFlag::False;
289        result.device.response_expected[u8::from(Io4V2BrickletFunction::SetConfiguration) as usize] = ResponseExpectedFlag::False;
290        result.device.response_expected[u8::from(Io4V2BrickletFunction::GetConfiguration) as usize] = ResponseExpectedFlag::AlwaysTrue;
291        result.device.response_expected[u8::from(Io4V2BrickletFunction::SetInputValueCallbackConfiguration) as usize] =
292            ResponseExpectedFlag::True;
293        result.device.response_expected[u8::from(Io4V2BrickletFunction::GetInputValueCallbackConfiguration) as usize] =
294            ResponseExpectedFlag::AlwaysTrue;
295        result.device.response_expected[u8::from(Io4V2BrickletFunction::SetAllInputValueCallbackConfiguration) as usize] =
296            ResponseExpectedFlag::True;
297        result.device.response_expected[u8::from(Io4V2BrickletFunction::GetAllInputValueCallbackConfiguration) as usize] =
298            ResponseExpectedFlag::AlwaysTrue;
299        result.device.response_expected[u8::from(Io4V2BrickletFunction::SetMonoflop) as usize] = ResponseExpectedFlag::False;
300        result.device.response_expected[u8::from(Io4V2BrickletFunction::GetMonoflop) as usize] = ResponseExpectedFlag::AlwaysTrue;
301        result.device.response_expected[u8::from(Io4V2BrickletFunction::GetEdgeCount) as usize] = ResponseExpectedFlag::AlwaysTrue;
302        result.device.response_expected[u8::from(Io4V2BrickletFunction::SetEdgeCountConfiguration) as usize] = ResponseExpectedFlag::False;
303        result.device.response_expected[u8::from(Io4V2BrickletFunction::GetEdgeCountConfiguration) as usize] =
304            ResponseExpectedFlag::AlwaysTrue;
305        result.device.response_expected[u8::from(Io4V2BrickletFunction::SetPwmConfiguration) as usize] = ResponseExpectedFlag::False;
306        result.device.response_expected[u8::from(Io4V2BrickletFunction::GetPwmConfiguration) as usize] = ResponseExpectedFlag::AlwaysTrue;
307        result.device.response_expected[u8::from(Io4V2BrickletFunction::GetSpitfpErrorCount) as usize] = ResponseExpectedFlag::AlwaysTrue;
308        result.device.response_expected[u8::from(Io4V2BrickletFunction::SetBootloaderMode) as usize] = ResponseExpectedFlag::AlwaysTrue;
309        result.device.response_expected[u8::from(Io4V2BrickletFunction::GetBootloaderMode) as usize] = ResponseExpectedFlag::AlwaysTrue;
310        result.device.response_expected[u8::from(Io4V2BrickletFunction::SetWriteFirmwarePointer) as usize] = ResponseExpectedFlag::False;
311        result.device.response_expected[u8::from(Io4V2BrickletFunction::WriteFirmware) as usize] = ResponseExpectedFlag::AlwaysTrue;
312        result.device.response_expected[u8::from(Io4V2BrickletFunction::SetStatusLedConfig) as usize] = ResponseExpectedFlag::False;
313        result.device.response_expected[u8::from(Io4V2BrickletFunction::GetStatusLedConfig) as usize] = ResponseExpectedFlag::AlwaysTrue;
314        result.device.response_expected[u8::from(Io4V2BrickletFunction::GetChipTemperature) as usize] = ResponseExpectedFlag::AlwaysTrue;
315        result.device.response_expected[u8::from(Io4V2BrickletFunction::Reset) as usize] = ResponseExpectedFlag::False;
316        result.device.response_expected[u8::from(Io4V2BrickletFunction::WriteUid) as usize] = ResponseExpectedFlag::False;
317        result.device.response_expected[u8::from(Io4V2BrickletFunction::ReadUid) as usize] = ResponseExpectedFlag::AlwaysTrue;
318        result.device.response_expected[u8::from(Io4V2BrickletFunction::GetIdentity) as usize] = ResponseExpectedFlag::AlwaysTrue;
319        result
320    }
321
322    /// Returns the response expected flag for the function specified by the function ID parameter.
323    /// It is true if the function is expected to send a response, false otherwise.
324    ///
325    /// For getter functions this is enabled by default and cannot be disabled, because those
326    /// functions will always send a response. For callback configuration functions it is enabled
327    /// by default too, but can be disabled by [`set_response_expected`](crate::io4_v2_bricklet::Io4V2Bricklet::set_response_expected).
328    /// For setter functions it is disabled by default and can be enabled.
329    ///
330    /// Enabling the response expected flag for a setter function allows to detect timeouts
331    /// and other error conditions calls of this setter as well. The device will then send a response
332    /// for this purpose. If this flag is disabled for a setter function then no response is sent
333    /// and errors are silently ignored, because they cannot be detected.
334    ///
335    /// See [`set_response_expected`](crate::io4_v2_bricklet::Io4V2Bricklet::set_response_expected) for the list of function ID constants available for this function.
336    pub fn get_response_expected(&mut self, fun: Io4V2BrickletFunction) -> Result<bool, GetResponseExpectedError> {
337        self.device.get_response_expected(u8::from(fun))
338    }
339
340    /// Changes the response expected flag of the function specified by the function ID parameter.
341    /// This flag can only be changed for setter (default value: false) and callback configuration
342    /// functions (default value: true). For getter functions it is always enabled.
343    ///
344    /// Enabling the response expected flag for a setter function allows to detect timeouts and
345    /// other error conditions calls of this setter as well. The device will then send a response
346    /// for this purpose. If this flag is disabled for a setter function then no response is sent
347    /// and errors are silently ignored, because they cannot be detected.
348    pub fn set_response_expected(&mut self, fun: Io4V2BrickletFunction, response_expected: bool) -> Result<(), SetResponseExpectedError> {
349        self.device.set_response_expected(u8::from(fun), response_expected)
350    }
351
352    /// Changes the response expected flag for all setter and callback configuration functions of this device at once.
353    pub fn set_response_expected_all(&mut self, response_expected: bool) { self.device.set_response_expected_all(response_expected) }
354
355    /// Returns the version of the API definition (major, minor, revision) implemented by this API bindings.
356    /// This is neither the release version of this API bindings nor does it tell you anything about the represented Brick or Bricklet.
357    pub fn get_api_version(&self) -> [u8; 3] { self.device.api_version }
358
359    /// This receiver is triggered periodically according to the configuration set by
360    /// [`set_input_value_callback_configuration`].
361    ///
362    /// The parameters are the channel, a value-changed indicator and the actual value
363    /// for the channel. The `changed` parameter is true if the value has changed since
364    /// the last receiver.
365    ///
366    /// [`set_input_value_callback_configuration`]: #method.set_input_value_callback_configuration
367    pub fn get_input_value_callback_receiver(&self) -> ConvertingCallbackReceiver<InputValueEvent> {
368        self.device.get_callback_receiver(u8::from(Io4V2BrickletFunction::CallbackInputValue))
369    }
370
371    /// This receiver is triggered periodically according to the configuration set by
372    /// [`set_all_input_value_callback_configuration`].
373    ///
374    /// The parameters are the same as [`get_value`]. Additional the
375    /// `changed` parameter is true if the value has changed since
376    /// the last receiver.
377    pub fn get_all_input_value_callback_receiver(&self) -> ConvertingCallbackReceiver<AllInputValueEvent> {
378        self.device.get_callback_receiver(u8::from(Io4V2BrickletFunction::CallbackAllInputValue))
379    }
380
381    /// This receiver is triggered whenever a monoflop timer reaches 0. The
382    /// parameters contain the channel and the current value of the channel
383    /// (the value after the monoflop).
384    pub fn get_monoflop_done_callback_receiver(&self) -> ConvertingCallbackReceiver<MonoflopDoneEvent> {
385        self.device.get_callback_receiver(u8::from(Io4V2BrickletFunction::CallbackMonoflopDone))
386    }
387
388    /// Sets the output value of all four channels. A value of *true* or *false* outputs
389    /// logic 1 or logic 0 respectively on the corresponding channel.
390    ///
391    /// Use [`set_selected_value`] to change only one output channel state.
392    ///
393    /// For example: (True, True, False, False) will turn the channels 0-1 high and the
394    /// channels 2-3 low.
395    ///
396    /// All running monoflop timers and PWMs will be aborted if this function is called.
397    ///
398    /// # Note
399    ///  This function does nothing for channels that are configured as input. Pull-up
400    ///  resistors can be switched on with [`set_configuration`].
401    pub fn set_value(&self, value: [bool; 4]) -> ConvertingReceiver<()> {
402        let mut payload = vec![0; 1];
403        payload[0..1].copy_from_slice(&<[bool; 4]>::to_le_byte_vec(value));
404
405        self.device.set(u8::from(Io4V2BrickletFunction::SetValue), payload)
406    }
407
408    /// Returns the logic levels that are currently measured on the channels.
409    /// This function works if the channel is configured as input as well as if it is
410    /// configured as output.
411    pub fn get_value(&self) -> ConvertingReceiver<[bool; 4]> {
412        let payload = vec![0; 0];
413
414        self.device.get(u8::from(Io4V2BrickletFunction::GetValue), payload)
415    }
416
417    /// Sets the output value of a specific channel without affecting the other channels.
418    ///
419    /// A running monoflop timer or PWM for the specific channel will be aborted if this
420    /// function is called.
421    ///
422    /// # Note
423    ///  This function does nothing for channels that are configured as input. Pull-up
424    ///  resistors can be switched on with [`set_configuration`].
425    pub fn set_selected_value(&self, channel: u8, value: bool) -> ConvertingReceiver<()> {
426        let mut payload = vec![0; 2];
427        payload[0..1].copy_from_slice(&<u8>::to_le_byte_vec(channel));
428        payload[1..2].copy_from_slice(&<bool>::to_le_byte_vec(value));
429
430        self.device.set(u8::from(Io4V2BrickletFunction::SetSelectedValue), payload)
431    }
432
433    /// Configures the value and direction of a specific channel. Possible directions
434    /// are 'i' and 'o' for input and output.
435    ///
436    /// If the direction is configured as output, the value is either high or low
437    /// (set as *true* or *false*).
438    ///
439    /// If the direction is configured as input, the value is either pull-up or
440    /// default (set as *true* or *false*).
441    ///
442    /// For example:
443    ///
444    /// * (0, 'i', true) will set channel 0 as input pull-up.
445    /// * (1, 'i', false) will set channel 1 as input default (floating if nothing is connected).
446    /// * (2, 'o', true) will set channel 2 as output high.
447    /// * (3, 'o', false) will set channel 3 as output low.
448    ///
449    /// A running monoflop timer or PWM for the specific channel will be aborted if this
450    /// function is called.
451    ///
452    /// Associated constants:
453    /// * IO4_V2_BRICKLET_DIRECTION_IN
454    ///	* IO4_V2_BRICKLET_DIRECTION_OUT
455    pub fn set_configuration(&self, channel: u8, direction: char, value: bool) -> ConvertingReceiver<()> {
456        let mut payload = vec![0; 3];
457        payload[0..1].copy_from_slice(&<u8>::to_le_byte_vec(channel));
458        payload[1..2].copy_from_slice(&<char>::to_le_byte_vec(direction));
459        payload[2..3].copy_from_slice(&<bool>::to_le_byte_vec(value));
460
461        self.device.set(u8::from(Io4V2BrickletFunction::SetConfiguration), payload)
462    }
463
464    /// Returns the channel configuration as set by [`set_configuration`].
465    ///
466    /// Associated constants:
467    /// * IO4_V2_BRICKLET_DIRECTION_IN
468    ///	* IO4_V2_BRICKLET_DIRECTION_OUT
469    pub fn get_configuration(&self, channel: u8) -> ConvertingReceiver<Configuration> {
470        let mut payload = vec![0; 1];
471        payload[0..1].copy_from_slice(&<u8>::to_le_byte_vec(channel));
472
473        self.device.get(u8::from(Io4V2BrickletFunction::GetConfiguration), payload)
474    }
475
476    /// This receiver can be configured per channel.
477    ///
478    /// The period is the period with which the [`get_input_value_callback_receiver`]
479    /// receiver is triggered periodically. A value of 0 turns the receiver off.
480    ///
481    /// If the `value has to change`-parameter is set to true, the receiver is only
482    /// triggered after the value has changed. If the value didn't change within the
483    /// period, the receiver is triggered immediately on change.
484    ///
485    /// If it is set to false, the receiver is continuously triggered with the period,
486    /// independent of the value.
487    pub fn set_input_value_callback_configuration(&self, channel: u8, period: u32, value_has_to_change: bool) -> ConvertingReceiver<()> {
488        let mut payload = vec![0; 6];
489        payload[0..1].copy_from_slice(&<u8>::to_le_byte_vec(channel));
490        payload[1..5].copy_from_slice(&<u32>::to_le_byte_vec(period));
491        payload[5..6].copy_from_slice(&<bool>::to_le_byte_vec(value_has_to_change));
492
493        self.device.set(u8::from(Io4V2BrickletFunction::SetInputValueCallbackConfiguration), payload)
494    }
495
496    /// Returns the receiver configuration for the given channel as set by
497    /// [`set_input_value_callback_configuration`].
498    pub fn get_input_value_callback_configuration(&self, channel: u8) -> ConvertingReceiver<InputValueCallbackConfiguration> {
499        let mut payload = vec![0; 1];
500        payload[0..1].copy_from_slice(&<u8>::to_le_byte_vec(channel));
501
502        self.device.get(u8::from(Io4V2BrickletFunction::GetInputValueCallbackConfiguration), payload)
503    }
504
505    /// The period is the period with which the [`get_all_input_value_callback_receiver`]
506    /// receiver is triggered periodically. A value of 0 turns the receiver off.
507    ///
508    /// If the `value has to change`-parameter is set to true, the receiver is only
509    /// triggered after the value has changed. If the value didn't change within the
510    /// period, the receiver is triggered immediately on change.
511    ///
512    /// If it is set to false, the receiver is continuously triggered with the period,
513    /// independent of the value.
514    pub fn set_all_input_value_callback_configuration(&self, period: u32, value_has_to_change: bool) -> ConvertingReceiver<()> {
515        let mut payload = vec![0; 5];
516        payload[0..4].copy_from_slice(&<u32>::to_le_byte_vec(period));
517        payload[4..5].copy_from_slice(&<bool>::to_le_byte_vec(value_has_to_change));
518
519        self.device.set(u8::from(Io4V2BrickletFunction::SetAllInputValueCallbackConfiguration), payload)
520    }
521
522    /// Returns the receiver configuration as set by
523    /// [`set_all_input_value_callback_configuration`].
524    pub fn get_all_input_value_callback_configuration(&self) -> ConvertingReceiver<AllInputValueCallbackConfiguration> {
525        let payload = vec![0; 0];
526
527        self.device.get(u8::from(Io4V2BrickletFunction::GetAllInputValueCallbackConfiguration), payload)
528    }
529
530    /// The first parameter is the desired state of the channel (*true* means output *high*
531    /// and *false* means output *low*). The second parameter indicates the time that
532    /// the channel should hold the state.
533    ///
534    /// If this function is called with the parameters (true, 1500):
535    /// The channel will turn on and in 1.5s it will turn off again.
536    ///
537    /// A PWM for the selected channel will be aborted if this function is called.
538    ///
539    /// A monoflop can be used as a failsafe mechanism. For example: Lets assume you
540    /// have a RS485 bus and a IO-4 Bricklet 2.0 is connected to one of the slave
541    /// stacks. You can now call this function every second, with a time parameter
542    /// of two seconds. The channel will be *high* all the time. If now the RS485
543    /// connection is lost, the channel will turn *low* in at most two seconds.
544    pub fn set_monoflop(&self, channel: u8, value: bool, time: u32) -> ConvertingReceiver<()> {
545        let mut payload = vec![0; 6];
546        payload[0..1].copy_from_slice(&<u8>::to_le_byte_vec(channel));
547        payload[1..2].copy_from_slice(&<bool>::to_le_byte_vec(value));
548        payload[2..6].copy_from_slice(&<u32>::to_le_byte_vec(time));
549
550        self.device.set(u8::from(Io4V2BrickletFunction::SetMonoflop), payload)
551    }
552
553    /// Returns (for the given channel) the current value and the time as set by
554    /// [`set_monoflop`] as well as the remaining time until the value flips.
555    ///
556    /// If the timer is not running currently, the remaining time will be returned
557    /// as 0.
558    pub fn get_monoflop(&self, channel: u8) -> ConvertingReceiver<Monoflop> {
559        let mut payload = vec![0; 1];
560        payload[0..1].copy_from_slice(&<u8>::to_le_byte_vec(channel));
561
562        self.device.get(u8::from(Io4V2BrickletFunction::GetMonoflop), payload)
563    }
564
565    /// Returns the current value of the edge counter for the selected channel. You can
566    /// configure the edges that are counted with [`set_edge_count_configuration`].
567    ///
568    /// If you set the reset counter to *true*, the count is set back to 0
569    /// directly after it is read.
570    ///
571    /// # Note
572    ///  Calling this function is only allowed for channels configured as input.
573    pub fn get_edge_count(&self, channel: u8, reset_counter: bool) -> ConvertingReceiver<u32> {
574        let mut payload = vec![0; 2];
575        payload[0..1].copy_from_slice(&<u8>::to_le_byte_vec(channel));
576        payload[1..2].copy_from_slice(&<bool>::to_le_byte_vec(reset_counter));
577
578        self.device.get(u8::from(Io4V2BrickletFunction::GetEdgeCount), payload)
579    }
580
581    /// Configures the edge counter for a specific channel.
582    ///
583    /// The edge type parameter configures if rising edges, falling edges or
584    /// both are counted if the channel is configured for input. Possible edge types are:
585    ///
586    /// * 0 = rising
587    /// * 1 = falling
588    /// * 2 = both
589    ///
590    /// Configuring an edge counter resets its value to 0.
591    ///
592    /// If you don't know what any of this means, just leave it at default. The
593    /// default configuration is very likely OK for you.
594    ///
595    /// # Note
596    ///  Calling this function is only allowed for channels configured as input.
597    ///
598    /// Associated constants:
599    /// * IO4_V2_BRICKLET_EDGE_TYPE_RISING
600    ///	* IO4_V2_BRICKLET_EDGE_TYPE_FALLING
601    ///	* IO4_V2_BRICKLET_EDGE_TYPE_BOTH
602    pub fn set_edge_count_configuration(&self, channel: u8, edge_type: u8, debounce: u8) -> ConvertingReceiver<()> {
603        let mut payload = vec![0; 3];
604        payload[0..1].copy_from_slice(&<u8>::to_le_byte_vec(channel));
605        payload[1..2].copy_from_slice(&<u8>::to_le_byte_vec(edge_type));
606        payload[2..3].copy_from_slice(&<u8>::to_le_byte_vec(debounce));
607
608        self.device.set(u8::from(Io4V2BrickletFunction::SetEdgeCountConfiguration), payload)
609    }
610
611    /// Returns the edge type and debounce time for the selected channel as set by
612    /// [`set_edge_count_configuration`].
613    ///
614    /// # Note
615    ///  Calling this function is only allowed for channels configured as input.
616    ///
617    /// Associated constants:
618    /// * IO4_V2_BRICKLET_EDGE_TYPE_RISING
619    ///	* IO4_V2_BRICKLET_EDGE_TYPE_FALLING
620    ///	* IO4_V2_BRICKLET_EDGE_TYPE_BOTH
621    pub fn get_edge_count_configuration(&self, channel: u8) -> ConvertingReceiver<EdgeCountConfiguration> {
622        let mut payload = vec![0; 1];
623        payload[0..1].copy_from_slice(&<u8>::to_le_byte_vec(channel));
624
625        self.device.get(u8::from(Io4V2BrickletFunction::GetEdgeCountConfiguration), payload)
626    }
627
628    /// Activates a PWM for the given channel.
629    ///
630    /// You need to set the channel to output before you call this function, otherwise it will
631    /// report an invalid parameter error. To turn the PWM off again, you can set the frequency to 0 or any other
632    /// function that changes a value of the channel (e.g. [`set_selected_value`]).
633    ///
634    /// A running monoflop timer for the given channel will be aborted if this function
635    /// is called.
636    pub fn set_pwm_configuration(&self, channel: u8, frequency: u32, duty_cycle: u16) -> ConvertingReceiver<()> {
637        let mut payload = vec![0; 7];
638        payload[0..1].copy_from_slice(&<u8>::to_le_byte_vec(channel));
639        payload[1..5].copy_from_slice(&<u32>::to_le_byte_vec(frequency));
640        payload[5..7].copy_from_slice(&<u16>::to_le_byte_vec(duty_cycle));
641
642        self.device.set(u8::from(Io4V2BrickletFunction::SetPwmConfiguration), payload)
643    }
644
645    /// Returns the PWM configuration as set by [`set_pwm_configuration`].
646    pub fn get_pwm_configuration(&self, channel: u8) -> ConvertingReceiver<PwmConfiguration> {
647        let mut payload = vec![0; 1];
648        payload[0..1].copy_from_slice(&<u8>::to_le_byte_vec(channel));
649
650        self.device.get(u8::from(Io4V2BrickletFunction::GetPwmConfiguration), payload)
651    }
652
653    /// Returns the error count for the communication between Brick and Bricklet.
654    ///
655    /// The errors are divided into
656    ///
657    /// * ACK checksum errors,
658    /// * message checksum errors,
659    /// * framing errors and
660    /// * overflow errors.
661    ///
662    /// The errors counts are for errors that occur on the Bricklet side. All
663    /// Bricks have a similar function that returns the errors on the Brick side.
664    pub fn get_spitfp_error_count(&self) -> ConvertingReceiver<SpitfpErrorCount> {
665        let payload = vec![0; 0];
666
667        self.device.get(u8::from(Io4V2BrickletFunction::GetSpitfpErrorCount), payload)
668    }
669
670    /// Sets the bootloader mode and returns the status after the requested
671    /// mode change was instigated.
672    ///
673    /// You can change from bootloader mode to firmware mode and vice versa. A change
674    /// from bootloader mode to firmware mode will only take place if the entry function,
675    /// device identifier and CRC are present and correct.
676    ///
677    /// This function is used by Brick Viewer during flashing. It should not be
678    /// necessary to call it in a normal user program.
679    ///
680    /// Associated constants:
681    /// * IO4_V2_BRICKLET_BOOTLOADER_MODE_BOOTLOADER
682    ///	* IO4_V2_BRICKLET_BOOTLOADER_MODE_FIRMWARE
683    ///	* IO4_V2_BRICKLET_BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT
684    ///	* IO4_V2_BRICKLET_BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT
685    ///	* IO4_V2_BRICKLET_BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT
686    ///	* IO4_V2_BRICKLET_BOOTLOADER_STATUS_OK
687    ///	* IO4_V2_BRICKLET_BOOTLOADER_STATUS_INVALID_MODE
688    ///	* IO4_V2_BRICKLET_BOOTLOADER_STATUS_NO_CHANGE
689    ///	* IO4_V2_BRICKLET_BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT
690    ///	* IO4_V2_BRICKLET_BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT
691    ///	* IO4_V2_BRICKLET_BOOTLOADER_STATUS_CRC_MISMATCH
692    pub fn set_bootloader_mode(&self, mode: u8) -> ConvertingReceiver<u8> {
693        let mut payload = vec![0; 1];
694        payload[0..1].copy_from_slice(&<u8>::to_le_byte_vec(mode));
695
696        self.device.get(u8::from(Io4V2BrickletFunction::SetBootloaderMode), payload)
697    }
698
699    /// Returns the current bootloader mode, see [`set_bootloader_mode`].
700    ///
701    /// Associated constants:
702    /// * IO4_V2_BRICKLET_BOOTLOADER_MODE_BOOTLOADER
703    ///	* IO4_V2_BRICKLET_BOOTLOADER_MODE_FIRMWARE
704    ///	* IO4_V2_BRICKLET_BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT
705    ///	* IO4_V2_BRICKLET_BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT
706    ///	* IO4_V2_BRICKLET_BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT
707    pub fn get_bootloader_mode(&self) -> ConvertingReceiver<u8> {
708        let payload = vec![0; 0];
709
710        self.device.get(u8::from(Io4V2BrickletFunction::GetBootloaderMode), payload)
711    }
712
713    /// Sets the firmware pointer for [`write_firmware`]. The pointer has
714    /// to be increased by chunks of size 64. The data is written to flash
715    /// every 4 chunks (which equals to one page of size 256).
716    ///
717    /// This function is used by Brick Viewer during flashing. It should not be
718    /// necessary to call it in a normal user program.
719    pub fn set_write_firmware_pointer(&self, pointer: u32) -> ConvertingReceiver<()> {
720        let mut payload = vec![0; 4];
721        payload[0..4].copy_from_slice(&<u32>::to_le_byte_vec(pointer));
722
723        self.device.set(u8::from(Io4V2BrickletFunction::SetWriteFirmwarePointer), payload)
724    }
725
726    /// Writes 64 Bytes of firmware at the position as written by
727    /// [`set_write_firmware_pointer`] before. The firmware is written
728    /// to flash every 4 chunks.
729    ///
730    /// You can only write firmware in bootloader mode.
731    ///
732    /// This function is used by Brick Viewer during flashing. It should not be
733    /// necessary to call it in a normal user program.
734    pub fn write_firmware(&self, data: [u8; 64]) -> ConvertingReceiver<u8> {
735        let mut payload = vec![0; 64];
736        payload[0..64].copy_from_slice(&<[u8; 64]>::to_le_byte_vec(data));
737
738        self.device.get(u8::from(Io4V2BrickletFunction::WriteFirmware), payload)
739    }
740
741    /// Sets the status LED configuration. By default the LED shows
742    /// communication traffic between Brick and Bricklet, it flickers once
743    /// for every 10 received data packets.
744    ///
745    /// You can also turn the LED permanently on/off or show a heartbeat.
746    ///
747    /// If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
748    ///
749    /// Associated constants:
750    /// * IO4_V2_BRICKLET_STATUS_LED_CONFIG_OFF
751    ///	* IO4_V2_BRICKLET_STATUS_LED_CONFIG_ON
752    ///	* IO4_V2_BRICKLET_STATUS_LED_CONFIG_SHOW_HEARTBEAT
753    ///	* IO4_V2_BRICKLET_STATUS_LED_CONFIG_SHOW_STATUS
754    pub fn set_status_led_config(&self, config: u8) -> ConvertingReceiver<()> {
755        let mut payload = vec![0; 1];
756        payload[0..1].copy_from_slice(&<u8>::to_le_byte_vec(config));
757
758        self.device.set(u8::from(Io4V2BrickletFunction::SetStatusLedConfig), payload)
759    }
760
761    /// Returns the configuration as set by [`set_status_led_config`]
762    ///
763    /// Associated constants:
764    /// * IO4_V2_BRICKLET_STATUS_LED_CONFIG_OFF
765    ///	* IO4_V2_BRICKLET_STATUS_LED_CONFIG_ON
766    ///	* IO4_V2_BRICKLET_STATUS_LED_CONFIG_SHOW_HEARTBEAT
767    ///	* IO4_V2_BRICKLET_STATUS_LED_CONFIG_SHOW_STATUS
768    pub fn get_status_led_config(&self) -> ConvertingReceiver<u8> {
769        let payload = vec![0; 0];
770
771        self.device.get(u8::from(Io4V2BrickletFunction::GetStatusLedConfig), payload)
772    }
773
774    /// Returns the temperature as measured inside the microcontroller. The
775    /// value returned is not the ambient temperature!
776    ///
777    /// The temperature is only proportional to the real temperature and it has bad
778    /// accuracy. Practically it is only useful as an indicator for
779    /// temperature changes.
780    pub fn get_chip_temperature(&self) -> ConvertingReceiver<i16> {
781        let payload = vec![0; 0];
782
783        self.device.get(u8::from(Io4V2BrickletFunction::GetChipTemperature), payload)
784    }
785
786    /// Calling this function will reset the Bricklet. All configurations
787    /// will be lost.
788    ///
789    /// After a reset you have to create new device objects,
790    /// calling functions on the existing ones will result in
791    /// undefined behavior!
792    pub fn reset(&self) -> ConvertingReceiver<()> {
793        let payload = vec![0; 0];
794
795        self.device.set(u8::from(Io4V2BrickletFunction::Reset), payload)
796    }
797
798    /// Writes a new UID into flash. If you want to set a new UID
799    /// you have to decode the Base58 encoded UID string into an
800    /// integer first.
801    ///
802    /// We recommend that you use Brick Viewer to change the UID.
803    pub fn write_uid(&self, uid: u32) -> ConvertingReceiver<()> {
804        let mut payload = vec![0; 4];
805        payload[0..4].copy_from_slice(&<u32>::to_le_byte_vec(uid));
806
807        self.device.set(u8::from(Io4V2BrickletFunction::WriteUid), payload)
808    }
809
810    /// Returns the current UID as an integer. Encode as
811    /// Base58 to get the usual string version.
812    pub fn read_uid(&self) -> ConvertingReceiver<u32> {
813        let payload = vec![0; 0];
814
815        self.device.get(u8::from(Io4V2BrickletFunction::ReadUid), payload)
816    }
817
818    /// Returns the UID, the UID where the Bricklet is connected to,
819    /// the position, the hardware and firmware version as well as the
820    /// device identifier.
821    ///
822    /// The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
823    /// A Bricklet connected to an [Isolator Bricklet](isolator_bricklet) is always at
824    /// position 'z'.
825    ///
826    /// The device identifier numbers can be found [here](device_identifier).
827    /// |device_identifier_constant|
828    pub fn get_identity(&self) -> ConvertingReceiver<Identity> {
829        let payload = vec![0; 0];
830
831        self.device.get(u8::from(Io4V2BrickletFunction::GetIdentity), payload)
832    }
833}