embedded_drivers/onewire/
mod.rs1use embedded_hal::blocking::delay::DelayUs;
4use embedded_hal::digital::v2::{InputPin, OutputPin};
5
6pub use self::ds18b20::DS18B20;
7
8pub mod ds18b20;
9
10const ADDRESS_BYTES: u8 = 8;
11const ADDRESS_BITS: u8 = ADDRESS_BYTES * 8;
12
13pub const ROM_CMD_SEARCH_ROM: u8 = 0xf0;
14pub const ROM_CMD_READ_ROM: u8 = 0x33;
15pub const ROM_CMD_MATCH_ROM: u8 = 0x55;
16pub const ROM_CMD_SKIP_ROM: u8 = 0xcc;
17pub const ROM_CMD_ALARM_SEARCH: u8 = 0xec;
18
19pub trait OneWirePinExt {
21 fn to_input(&mut self) -> &mut dyn InputPin<Error = core::convert::Infallible>;
22 fn to_output(&mut self) -> &mut dyn OutputPin<Error = core::convert::Infallible>;
23}
24
25#[derive(Debug)]
26pub enum Error {
27 WireNotLow,
28 WireNotHigh,
29 CrcMismatch(u8, u8),
30 FamilyCodeMismatch(u8, u8),
31 Debug(Option<u8>),
32 PortError,
33}
34
35#[derive(Clone, PartialOrd, PartialEq)]
36pub struct Device {
37 pub address: [u8; 8],
38}
39
40impl Device {
41 pub fn family_code(&self) -> u8 {
42 self.address[0]
43 }
44
45 pub fn is_crc_ok(&self) -> bool {
46 ensure_crc(&self.address[..])
47 }
48}
49
50impl ::core::fmt::Debug for Device {
51 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
52 write!(
53 f,
54 "{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}",
55 self.address[0],
56 self.address[6],
57 self.address[5],
58 self.address[4],
59 self.address[3],
60 self.address[2],
61 self.address[1],
62 )
64 }
65}
66
67impl core::str::FromStr for Device {
68 type Err = core::num::ParseIntError;
69
70 fn from_str(s: &str) -> Result<Self, Self::Err> {
71 if s.len() < 23 {
72 let _ = u8::from_str_radix("", 16)?; }
74 Ok(Device {
75 address: [
76 u8::from_str_radix(&s[0..2], 16)?,
77 u8::from_str_radix(&s[3..5], 16)?,
78 u8::from_str_radix(&s[6..8], 16)?,
79 u8::from_str_radix(&s[9..11], 16)?,
80 u8::from_str_radix(&s[12..14], 16)?,
81 u8::from_str_radix(&s[15..17], 16)?,
82 u8::from_str_radix(&s[18..20], 16)?,
83 u8::from_str_radix(&s[21..23], 16)?,
84 ],
85 })
86 }
87}
88
89impl core::ops::Deref for Device {
90 type Target = [u8];
91
92 fn deref(&self) -> &[u8] {
93 &self.address[..]
94 }
95}
96
97#[derive(Debug, Clone, Copy, PartialEq)]
98enum SearchState {
99 Initialized,
100 DeviceFound,
101 End,
102}
103
104pub struct DeviceSearch<'a, P: OneWirePinExt, D: DelayUs<u16>> {
105 address: [u8; 8],
106 discrepancies: [u8; 8],
107 state: SearchState,
108 port: &'a mut OneWire<P>,
109 delay: &'a mut D,
110}
111
112impl<'a, P: OneWirePinExt, D: DelayUs<u16>> DeviceSearch<'a, P, D> {
113 fn is_bit_set(array: &[u8], bit: u8) -> bool {
114 if bit / 8 >= array.len() as u8 {
115 return false;
116 }
117 let index = bit / 8;
118 let offset = bit % 8;
119 array[index as usize] & (0x01 << offset) != 0x00
120 }
121
122 fn is_bit_set_in_address(&self, bit: u8) -> bool {
123 Self::is_bit_set(&self.address, bit)
124 }
125
126 fn set_bit_in_address(&mut self, bit: u8) {
127 Self::set_bit(&mut self.address, bit);
128 }
129
130 fn reset_bit_in_address(&mut self, bit: u8) {
131 Self::reset_bit(&mut self.address, bit);
132 }
133
134 fn write_bit_in_address(&mut self, bit: u8, value: bool) {
135 if value {
136 self.set_bit_in_address(bit);
137 } else {
138 self.reset_bit_in_address(bit);
139 }
140 }
141
142 fn is_bit_set_in_discrepancies(&self, bit: u8) -> bool {
143 Self::is_bit_set(&self.discrepancies, bit)
144 }
145
146 fn set_bit_in_discrepancy(&mut self, bit: u8) {
147 Self::set_bit(&mut self.discrepancies, bit);
148 }
149
150 fn reset_bit_in_discrepancy(&mut self, bit: u8) {
151 Self::reset_bit(&mut self.discrepancies, bit);
152 }
153
154 fn last_discrepancy(&self) -> Option<u8> {
155 let mut result = None;
156 for i in 0..ADDRESS_BITS {
157 if self.is_bit_set_in_discrepancies(i) {
158 result = Some(i);
159 }
160 }
161 result
162 }
163
164 fn set_bit(array: &mut [u8], bit: u8) {
165 if bit / 8 >= array.len() as u8 {
166 return;
167 }
168 let index = bit / 8;
169 let offset = bit % 8;
170 array[index as usize] |= 0x01 << offset
171 }
172
173 fn reset_bit(array: &mut [u8], bit: u8) {
174 if bit / 8 >= array.len() as u8 {
175 return;
176 }
177 let index = bit / 8;
178 let offset = bit % 8;
179 array[index as usize] &= !(0x01 << offset)
180 }
181}
182
183impl<'a, P: OneWirePinExt, D: DelayUs<u16>> core::iter::Iterator for DeviceSearch<'a, P, D> {
184 type Item = Device;
185
186 fn next(&mut self) -> Option<Self::Item> {
187 if self.state == SearchState::End {
188 return None;
189 }
190
191 let mut discrepancy_found = false;
192 let last_discrepancy = self.last_discrepancy();
193
194 if !self.port.reset(self.delay).is_ok() {
195 return None;
196 }
197
198 self.port.write_byte(self.delay, ROM_CMD_SEARCH_ROM).ok()?;
199
200 if let Some(last_discrepancy) = last_discrepancy {
201 for i in 0..last_discrepancy {
203 let bit0 = self.port.read_bit(self.delay).ok()?;
204 let bit1 = self.port.read_bit(self.delay).ok()?;
205
206 if bit0 && bit1 {
207 return None;
209 } else {
210 let bit = self.is_bit_set_in_address(i);
211 self.port.write_bit(self.delay, bit).ok()?;
214 }
215 }
216 } else {
217 if self.state == SearchState::DeviceFound {
219 self.state = SearchState::End;
220 return None;
221 }
222 }
223
224 for i in last_discrepancy.unwrap_or(0)..ADDRESS_BITS {
225 let bit0 = self.port.read_bit(self.delay).ok()?; let bit1 = self.port.read_bit(self.delay).ok()?; if last_discrepancy.eq(&Some(i)) {
229 self.reset_bit_in_discrepancy(i);
231 self.set_bit_in_address(i);
232 self.port.write_bit(self.delay, true).ok()?;
233 } else {
234 if bit0 && bit1 {
235 return None;
237 }
238
239 if !bit0 && !bit1 {
240 discrepancy_found |= true;
243 self.set_bit_in_discrepancy(i);
244 self.reset_bit_in_address(i);
245 self.port.write_bit(self.delay, false).ok();
246 } else {
247 self.write_bit_in_address(i, bit0);
249 self.port.write_bit(self.delay, bit0).ok();
250 }
251 }
252 }
253
254 if !discrepancy_found && self.last_discrepancy().is_none() {
255 self.state = SearchState::End;
256 } else {
257 self.state = SearchState::DeviceFound;
258 }
259 Some(Device { address: self.address })
260 }
261}
262
263pub struct OneWire<P: OneWirePinExt> {
264 pin: P,
265}
266
267impl<P: OneWirePinExt> OneWire<P> {
268 pub fn new(mut pin: P) -> Self {
269 pin.to_output().set_high().unwrap();
270 OneWire { pin }
271 }
272
273 pub fn reset(&mut self, delay: &mut impl DelayUs<u16>) -> Result<(), Error> {
274 self.pin.to_output().set_high().unwrap();
276 self.pin.to_output().set_low().unwrap();
277
278 delay.delay_us(480);
279 let pin = self.pin.to_input();
281
282 let mut val = false;
284 for _ in 0..24 {
285 if pin.is_low().unwrap() {
286 val |= true;
287 }
288 delay.delay_us(10);
289 }
290 if !val {
291 return Err(Error::WireNotLow);
292 }
293 val = false;
294 for _ in 0..24 {
295 if pin.is_high().unwrap() {
296 val |= true;
297 }
298 delay.delay_us(10);
299 }
300 if !val {
301 return Err(Error::WireNotHigh);
302 }
303
304 Ok(())
305 }
306
307 pub fn read_rom(&mut self, delay: &mut impl DelayUs<u16>) -> Result<Device, Error> {
311 self.reset(delay)?;
312 self.write_byte(delay, ROM_CMD_READ_ROM)?;
313 let mut rom = [0u8; 8];
314 self.read_bytes(delay, &mut rom)?;
315 Ok(Device { address: rom })
316 }
317
318 pub fn search_device<'a, D: DelayUs<u16>>(&'a mut self, delay: &'a mut D) -> DeviceSearch<'a, P, D> {
320 DeviceSearch {
321 address: [0u8; 8],
322 discrepancies: [0u8; 8],
323 state: SearchState::Initialized,
324 port: self,
325 delay,
326 }
327 }
328
329 pub fn pullup(&mut self) {
331 self.pin.to_output().set_high().unwrap();
332 }
333
334 pub fn write_bytes(&mut self, delay: &mut impl DelayUs<u16>, bytes: &[u8]) -> Result<(), Error> {
335 for b in bytes {
336 self.write_byte(delay, *b)?;
337 }
338 Ok(())
339 }
340
341 pub fn write_byte(&mut self, delay: &mut impl DelayUs<u16>, mut byte: u8) -> Result<(), Error> {
342 for _ in 0..8 {
343 self.write_bit(delay, (byte & 0x01) == 0x01)?;
344 byte >>= 1;
345 }
346 Ok(())
347 }
348
349 pub fn read_bytes(&mut self, delay: &mut impl DelayUs<u16>, dst: &mut [u8]) -> Result<(), Error> {
350 for d in dst {
351 *d = self.read_byte(delay)?;
352 }
353 Ok(())
354 }
355
356 pub fn read_bit(&mut self, delay: &mut impl DelayUs<u16>) -> Result<bool, Error> {
357 self.pin.to_output().set_low().unwrap();
358 delay.delay_us(3);
359 let pin = self.pin.to_input();
360 delay.delay_us(2);
361 let val = pin.is_high().unwrap();
362 delay.delay_us(61);
363 Ok(val)
364 }
365
366 pub fn read_byte(&mut self, delay: &mut impl DelayUs<u16>) -> Result<u8, Error> {
367 let mut byte = 0_u8;
368 for _ in 0..8 {
369 byte >>= 1;
370 if self.read_bit(delay)? {
371 byte |= 0x80;
372 }
373 }
374 Ok(byte)
375 }
376
377 fn write_bit(&mut self, delay: &mut impl DelayUs<u16>, high: bool) -> Result<(), Error> {
378 let pin = self.pin.to_output();
380 pin.set_low().unwrap();
381 delay.delay_us(if high { 10 } else { 65 });
382 pin.set_high().unwrap();
383 delay.delay_us(if high { 55 } else { 5 });
384 Ok(())
385 }
386}
387
388pub struct OneWireDevice<'a, P: OneWirePinExt> {
390 wire: &'a mut OneWire<P>,
391 dev: Option<Device>,
392}
393
394impl<P: OneWirePinExt> OneWireDevice<'_, P> {
395 fn select_device<D: DelayUs<u16>>(&mut self, delay: &mut D) -> Result<(), Error> {
396 if let Some(ref dev) = self.dev {
397 self.wire.reset(delay)?;
398 self.wire.write_byte(delay, ROM_CMD_MATCH_ROM)?; self.wire.write_bytes(delay, dev)?;
400 Ok(())
401 } else {
402 self.wire.reset(delay)?;
403 self.wire.write_byte(delay, ROM_CMD_SKIP_ROM)?;
404 Ok(())
405 }
406 }
407
408 pub fn release(self) {}
409}
410
411pub fn ensure_crc(data: &[u8]) -> bool {
412 compute_partial_crc8(0, data) == 0
413}
414
415fn compute_partial_crc8(crc: u8, data: &[u8]) -> u8 {
416 let mut crc = crc;
417 for byte in data.iter() {
418 let mut byte = *byte;
419 for _ in 0..8 {
420 let mix = (crc ^ byte) & 0x01;
421 crc >>= 1;
422 if mix != 0x00 {
423 crc ^= 0x8C;
424 }
425 byte >>= 1;
426 }
427 }
428 crc
429}