embedded_onewire/
traits_async.rs

1#![allow(async_fn_in_trait)]
2use crate::{OneWireError, OneWireResult, OneWireStatus};
3
4/// Trait for 1-Wire communication.
5/// This trait defines the basic operations required for 1-Wire communication, such as resetting the bus,
6/// writing and reading bytes, and writing and reading bits.
7pub trait OneWireAsync {
8    /// The status type returned by the reset operation.
9    /// This type must implement the [OneWireStatus] trait.
10    type Status: OneWireStatus;
11    /// The error type returned by the operations of this trait.
12    /// This type is used to indicate errors in the underlying hardware or communication.
13    type BusError;
14
15    /// Resets the 1-Wire bus and returns the status of the bus.
16    ///
17    /// # Returns
18    /// A result containing the status of the bus after the reset operation.
19    ///
20    /// # Errors
21    /// This method returns an error if the reset operation fails.
22    async fn reset(&mut self) -> OneWireResult<Self::Status, Self::BusError>;
23
24    /// Writes a byte to the 1-Wire bus.
25    /// # Arguments
26    /// * `byte` - The byte to write to the bus.
27    ///
28    /// # Errors
29    /// This method returns an error if the write operation fails.
30    async fn write_byte(&mut self, byte: u8) -> OneWireResult<(), Self::BusError>;
31
32    /// Reads a byte from the 1-Wire bus.
33    /// # Returns
34    /// Byte read from the bus.
35    ///
36    /// # Errors
37    /// This method returns an error if the read operation fails.
38    async fn read_byte(&mut self) -> OneWireResult<u8, Self::BusError>;
39
40    /// Reads a byte from the 1-Wire bus, with an option to write a byte before reading.
41    /// # Arguments
42    ///
43    /// * `bit` - The byte to write.
44    ///
45    /// # Errors
46    /// This method returns an error if the read operation fails.
47    async fn write_bit(&mut self, bit: bool) -> OneWireResult<(), Self::BusError>;
48
49    /// Reads a single bit from the 1-Wire bus.
50    /// # Returns
51    /// The bit read from the bus.
52    /// # Errors
53    /// This method returns an error if the read operation fails.
54    async fn read_bit(&mut self) -> OneWireResult<bool, Self::BusError>;
55
56    /// # Note: Not intended for public API use.
57    /// ## This method is internally used to performa [1-wire search ROM sequence](https://www.analog.com/en/resources/app-notes/1wire-search-algorithm.html). A full sequence requires this command to be executed 64 times to identify and address one device.
58    /// ## This method is internally used by the [search algorithm](https://www.analog.com/en/resources/app-notes/1wire-search-algorithm.html).
59    ///
60    /// Generates three time slots: two read time slots and one write time slot at the 1-Wire line. The
61    /// type of write time slot depends on the result of the read time slots and the direction byte. The
62    /// direction byte determines the type of write time slot if both read time slots are 0 (a typical
63    /// case). In this case, a write-one time slot is generated if V = 1 and a write-zero time
64    /// slot if V = 0.
65    /// If the read time slots are 0 and 1, they are followed by a write-zero time slot.
66    /// If the read time slots are 1 and 0, they are followed by a write-one time slot.
67    /// If the read time slots are both 1 (error case), the subsequent write time slot is a write-one.
68    ///
69    ///
70    /// # Arguments
71    /// * `direction` - A boolean indicating the direction of the search. If true, the search is in the forward direction; if false, it is in the backward direction.
72    ///
73    /// # Returns
74    /// A result containing a tuple of two booleans:
75    /// * The first boolean indicates the id bit read from the bus.
76    /// * The second boolean indicates the complement bit read from the bus.
77    ///
78    /// # Errors
79    /// This method returns an error if the triplet read operation is not implemented or if any other error occurs.
80    #[cfg(feature = "triplet-read")]
81    #[cfg_attr(docsrs, doc(cfg(feature = "triplet-read")))]
82    async fn read_triplet(&mut self) -> OneWireResult<(bool, bool, bool), Self::BusError> {
83        Err(OneWireError::Unimplemented)
84    }
85
86    /// Check if the 1-Wire bus is in overdrive mode.
87    /// # Returns
88    /// A result containing a boolean indicating whether the bus is in overdrive mode.
89    async fn get_overdrive_mode(&mut self) -> OneWireResult<bool, Self::BusError>;
90
91    /// Set the 1-Wire bus to overdrive mode.
92    /// # Arguments
93    /// * `enable` - A boolean indicating whether to enable or disable overdrive mode.
94    /// # Returns
95    /// A result indicating the success or failure of the operation.
96    async fn set_overdrive_mode(&mut self, _enable: bool) -> OneWireResult<(), Self::BusError> {
97        Err(OneWireError::Unimplemented)
98    }
99
100    /// Addresses devices on the 1-Wire bus.
101    /// The first [`OneWire::read_byte`], [`OneWire::read_bit`], [`OneWire::write_byte`], [`OneWire::write_bit`] operation should be preceded by this method to address devices on the bus.
102    /// Note: A [`OneWire::read_byte`] or [`OneWire::read_bit`] call will return garbage data if this method is called without specifying a ROM address on a bus with multiple devices.
103    /// # Arguments
104    /// * `rom` - The ROM address of the device to address. Pass [`None`] to skip ROM addressing and address all devices on the bus.
105    ///
106    /// # Returns
107    /// A result indicating the success or failure of the operation.
108    /// If the device is successfully addressed, the method returns `Ok(())`.
109    async fn addrss(&mut self, rom: Option<u64>) -> OneWireResult<(), Self::BusError> {
110        let od = self.get_overdrive_mode().await?;
111        let cmd = if rom.is_some() {
112            if od {
113                crate::consts::ONEWIRE_MATCH_ROM_CMD_OD
114            } else {
115                crate::consts::ONEWIRE_MATCH_ROM_CMD
116            }
117        } else if od {
118            crate::consts::ONEWIRE_SKIP_ROM_CMD_OD
119        } else {
120            crate::consts::ONEWIRE_SKIP_ROM_CMD
121        };
122        self.reset().await?; // Reset the bus before addressing
123        self.write_byte(cmd).await?; // Send the match ROM command
124        if let Some(rom) = rom {
125            for &b in rom.to_le_bytes().iter() {
126                self.write_byte(b).await?; // Write each byte of the ROM address
127            }
128        }
129        Ok(())
130    }
131}