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}