1#![no_std]
2pub mod crc;
17pub mod ds18b20;
18pub mod rom_code;
19pub mod search_rom;
20pub mod wirelock;
21
22use crc::crc8_maxim;
23use embedded_hal::{
24 self,
25 delay::DelayNs,
26 digital::{InputPin, OutputPin},
27};
28use rom_code::RomCode;
29use search_rom::OneWireRomIter;
30
31pub struct OneWire<'a, P: InputPin + OutputPin> {
36 pin: &'a mut P,
37}
38
39impl<'a, P: InputPin + OutputPin> OneWire<'a, P> {
40 pub fn new(pin: &'a mut P) -> Self {
42 Self { pin }
43 }
44
45 pub fn initialize_bus(&mut self, delay: &mut impl DelayNs) -> Result<bool, P::Error> {
51 self.pin.set_high()?;
52 delay.delay_us(2);
53 while self.pin.is_low()? {
54 delay.delay_us(2);
55 }
56
57 self.pin.set_low()?;
58 delay.delay_us(480);
59 self.pin.set_high()?;
60
61 delay.delay_us(67);
64 let is_present = self.pin.is_low()?;
65
66 delay.delay_us(480 - 67);
68 Ok(is_present)
69 }
70
71 pub fn write_bit(&mut self, bit: bool, delay: &mut impl DelayNs) -> Result<(), P::Error> {
75 match bit {
76 true => {
77 self.pin.set_low()?;
78 delay.delay_us(10);
79 self.pin.set_high()?;
80 delay.delay_us(50);
81 }
82 false => {
83 self.pin.set_low()?;
84 delay.delay_us(65);
85 self.pin.set_high()?;
86 }
87 }
88
89 delay.delay_us(5);
91
92 Ok(())
93 }
94
95 pub fn read_bit(&mut self, delay: &mut impl DelayNs) -> Result<bool, P::Error> {
99 self.pin.set_low()?;
101 delay.delay_us(3);
102 self.pin.set_high()?;
103 delay.delay_us(10);
104
105 let bit = self.pin.is_high()?;
108
109 delay.delay_us(53);
111
112 Ok(bit)
113 }
114
115 pub fn write_byte(&mut self, byte: u8, delay: &mut impl DelayNs) -> Result<(), P::Error> {
120 let mut byte = byte;
121 for _ in 0..8 {
123 let bit = byte & 1 == 1; byte >>= 1;
125 self.write_bit(bit, delay)?;
126 }
127 Ok(())
128 }
129
130 pub fn read_byte(&mut self, delay: &mut impl DelayNs) -> Result<u8, P::Error> {
135 let mut byte = 0u8;
136 for _ in 0..8 {
139 byte >>= 1;
140
141 let bit = self.read_bit(delay)?;
142
143 if bit {
145 byte |= 0b10000000;
146 };
147 }
148 Ok(byte)
149 }
150
151 pub fn read_rom(
156 &mut self,
157 delay: &mut impl DelayNs,
158 ) -> Result<RomCode, OneWireError<P::Error>> {
159 if !self.initialize_bus(delay)? {
160 return Err(OneWireError::NoDevicePresent());
161 }
162
163 let read_rom_command = 0x33u8;
164 self.write_byte(read_rom_command, delay)?;
165
166 let mut bytes = [0; 8];
168 for byte in &mut bytes {
169 *byte = self.read_byte(delay)?;
170 }
171 let crc = crc8_maxim(&bytes[0..7]);
172 if crc != bytes[7] {
173 Err(OneWireError::CrCMismatch {
174 crc_received: bytes[7],
175 crc_calculated: crc,
176 })
177 } else {
178 Ok(RomCode { bytes })
179 }
180 }
181
182 pub fn match_rom(
184 &mut self,
185 rom_code: RomCode,
186 delay: &mut impl DelayNs,
187 ) -> Result<(), OneWireError<P::Error>> {
188 if !self.initialize_bus(delay)? {
189 return Err(OneWireError::NoDevicePresent());
190 }
191
192 let match_rom_command = 0x55u8;
193 self.write_byte(match_rom_command, delay)?;
194
195 for byte in rom_code.bytes {
197 self.write_byte(byte, delay)?;
198 }
199 Ok(())
200 }
201
202 pub fn skip_rom(&mut self, delay: &mut impl DelayNs) -> Result<(), OneWireError<P::Error>> {
204 if !self.initialize_bus(delay)? {
205 return Err(OneWireError::NoDevicePresent());
206 }
207
208 let match_rom_command = 0xCCu8;
209 self.write_byte(match_rom_command, delay)?;
210 Ok(())
211 }
212
213 pub fn search_rom_iter<'b, D: DelayNs>(
215 &'b mut self,
216 delay: &'b mut D,
217 ) -> OneWireRomIter<'a, 'b, P, D, false> {
218 OneWireRomIter::from_wire(self, delay)
219 }
220
221 pub fn alarm_search_iter<'b, D: DelayNs>(
223 &'b mut self,
224 delay: &'b mut D,
225 ) -> OneWireRomIter<'a, 'b, P, D, true> {
226 OneWireRomIter::alarm_from_wire(self, delay)
227 }
228}
229
230#[derive(Debug, thiserror::Error)]
231pub enum FamilyCodeError {
232 #[error("Expected to find family code {expected:X}, but found family code {received:X}.")]
233 MismatchedFamilyCode { expected: u8, received: u8 },
234}
235
236#[derive(Debug, thiserror::Error)]
237pub enum OneWireError<PinErr> {
238 #[error("An error occourred on the OneWire pin.")]
239 PinError(#[from] PinErr),
240 #[error(
241 "CRC={crc_received:X} of the data does not match the calculated CRC={crc_calculated:X}"
242 )]
243 CrCMismatch {
244 crc_received: u8,
245 crc_calculated: u8,
246 },
247 #[error("No device responded to the Reset pulse with a Presence pulse.")]
248 NoDevicePresent(),
249}