esp_hal_rmt_onewire/
lib.rs

1#![no_std]
2#![allow(incomplete_features)]
3#![feature(generic_const_exprs)]
4
5use core::marker::PhantomData;
6use embassy_futures::select::*;
7use esp_hal::{
8    gpio::{
9        interconnect::*, DriveMode, DriveStrength, Flex, InputConfig, Level, OutputConfig, Pin,
10        Pull,
11    },
12    rmt::{
13        Channel, PulseCode, RxChannelAsync, RxChannelConfig, RxChannelCreator, RxChannelInternal,
14        TxChannelAsync, TxChannelConfig, TxChannelCreator, TxChannelInternal,
15    },
16    Async,
17};
18
19pub trait OneWireConfig {
20    type Rx: RxChannelAsync;
21    type Tx: TxChannelAsync;
22    type TxRaw: TxChannelInternal;
23}
24
25#[derive(Default)]
26pub struct OneWireConfigZST<Rx: RxChannelAsync, Tx: TxChannelAsync, TxRaw: TxChannelInternal>(
27    PhantomData<Rx>,
28    PhantomData<Tx>,
29    PhantomData<TxRaw>,
30);
31
32impl<R: RxChannelAsync, T: TxChannelAsync, TR: TxChannelInternal> OneWireConfig
33    for OneWireConfigZST<R, T, TR>
34{
35    type Rx = R;
36    type Tx = T;
37    type TxRaw = TR;
38}
39
40pub struct OneWire<'a, C: OneWireConfig> {
41    rx: C::Rx,
42    tx: C::Tx,
43    input: InputSignal<'a>,
44    txchan: C::TxRaw, // Used for clearing a transmit transaction without driver support.
45}
46
47impl<'a, Rx: RxChannelInternal, Tx: TxChannelInternal>
48    OneWire<'a, OneWireConfigZST<Channel<Async, Rx>, Channel<Async, Tx>, Tx>>
49{
50    pub fn new<
51        Txc: TxChannelCreator<'a, Async, Raw = Tx>,
52        Rxc: RxChannelCreator<'a, Async, Raw = Rx>,
53        P: Pin + 'a,
54        >(
55        txcc: Txc,
56        rxcc: Rxc,
57        pin: P,
58    ) -> Result<Self, Error> {
59        let rx_config = RxChannelConfig::default()
60            .with_clk_divider(80)
61            .with_idle_threshold(1000)
62            .with_filter_threshold(10)
63            .with_carrier_modulation(false);
64        let tx_config = TxChannelConfig::default()
65            .with_clk_divider(80)
66            .with_carrier_modulation(false);
67
68        let mut pin: Flex = Flex::new(pin);
69
70        pin.apply_input_config(&InputConfig::default().with_pull(Pull::Up));
71        pin.apply_output_config(
72            &OutputConfig::default()
73                .with_drive_mode(DriveMode::OpenDrain)
74                .with_drive_strength(DriveStrength::_40mA),
75        );
76        pin.set_input_enable(true);
77        pin.set_output_enable(true);
78        let (input, output) = pin.split();
79
80        let tx = txcc
81            .configure_tx(output.with_output_inverter(true), tx_config)
82            .map_err(Error::SendError)?;
83        let rx = rxcc
84            .configure_rx(input.clone().with_input_inverter(true), rx_config)
85            .map_err(Error::ReceiveError)?;
86
87        Ok(OneWire {
88            rx,
89            tx,
90            input,
91            txchan: Txc::RAW,
92        })
93    }
94}
95
96impl<'a, CFG: OneWireConfig> OneWire<'a, CFG> {
97    pub async fn reset(&mut self) -> Result<bool, Error> {
98        let data = [
99            PulseCode::new(Level::Low, 60, Level::High, 600),
100            PulseCode::new(Level::Low, 600, Level::Low, 0),
101            PulseCode::empty(),
102        ];
103        let mut indata = [PulseCode::empty(); 10];
104
105        let _res = self.send_and_receive(&mut indata, &data).await?;
106
107        Ok(indata[0].length1() > 0
108            && indata[0].length2() > 0
109            && indata[1].length1() > 100
110            && indata[1].length1() < 200)
111    }
112
113    pub async fn send_and_receive(
114        &mut self,
115        indata: &mut [u32],
116        data: &[u32],
117    ) -> Result<(), Error> {
118        let delay = [PulseCode::new(Level::Low, 30000, Level::Low, 0)]; // timeout delay for 30ms using the RMT tx peripheral.
119        if self.input.level() == Level::Low {
120            Err(Error::InputNotHigh)?;
121        }
122        // This relies on select polling in order to set up the rx & tx registers, which is not strictly documented behavior.
123        let res = select(self.rx.receive(indata), async {
124            let r = self.tx.transmit(data).await;
125            let _ = self.tx.transmit(&delay).await;
126            r
127        })
128        .await;
129        // Still need to use the internal interface to cancel the TX-based timeout.
130        self.txchan.stop_tx();
131
132        match res {
133            Either::First(Ok(r)) => Ok(r),
134            Either::First(Err(r)) => Err(Error::ReceiveError(r)),
135            Either::Second(Ok(())) => Err(Error::ReceiveTimedOut),
136            Either::Second(Err(e)) => Err(Error::SendError(e)),
137        }
138    }
139
140    const ZERO_BIT_LEN: u16 = 70;
141    const ONE_BIT_LEN: u16 = 3;
142
143    pub fn encode_bit(bit: bool) -> u32 {
144        if bit {
145            PulseCode::new(
146                Level::High,
147                Self::ONE_BIT_LEN,
148                Level::Low,
149                Self::ZERO_BIT_LEN,
150            )
151        } else {
152            PulseCode::new(
153                Level::High,
154                Self::ZERO_BIT_LEN,
155                Level::Low,
156                Self::ONE_BIT_LEN,
157            )
158        }
159    }
160
161    pub fn decode_bit(code: u32) -> bool {
162        let len = code.length1();
163        if len < 20 {
164            true
165        } else {
166            false
167        }
168    }
169
170    pub async fn exchange_byte(&mut self, byte: u8) -> Result<u8, Error> {
171        let mut data = [PulseCode::empty(); 10];
172        let mut indata = [PulseCode::empty(); 10];
173        for n in 0..8 {
174            data[n] = Self::encode_bit(0 != byte & 1 << n);
175        }
176        let _res = self.send_and_receive(&mut indata, &data).await?;
177        let mut res: u8 = 0;
178        for n in 0..8 {
179            if Self::decode_bit(indata[n]) {
180                res |= 1 << n;
181            }
182        }
183        Ok(res)
184    }
185
186    pub async fn send_byte(&mut self, byte: u8) -> Result<(), Error> {
187        let mut data = [PulseCode::empty(); 10];
188        for n in 0..8 {
189            data[n] = Self::encode_bit(0 != byte & 1 << n);
190        }
191        let _res = self.tx.transmit(&data).await?;
192        Ok(())
193    }
194
195    pub async fn exchange_bits<const N: usize>(
196        &mut self,
197        bits: [bool; N],
198    ) -> Result<[bool; N], Error>
199    where
200        [(); N + 1]:,
201    {
202        let mut data = [PulseCode::empty(); N + 1];
203        let mut indata = [PulseCode::empty(); N + 1];
204        for n in 0..N {
205            data[n] = Self::encode_bit(bits[n]);
206        }
207        let _res = self.send_and_receive(&mut indata, &data).await?;
208        let mut res: [bool; N] = [false; N];
209        for n in 0..N {
210            res[n] = Self::decode_bit(indata[n]);
211        }
212        Ok(res)
213    }
214
215    pub async fn send_u64(&mut self, val: u64) -> Result<(), Error> {
216        for byte in val.to_le_bytes() {
217            self.send_byte(byte).await?;
218        }
219        Ok(())
220    }
221
222    pub async fn send_address(&mut self, val: Address) -> Result<(), Error> {
223        self.send_u64(val.0).await
224    }
225}
226
227#[derive(Debug)]
228pub enum Error {
229    InputNotHigh,
230    ReceiveTimedOut,
231    ReceiveError(esp_hal::rmt::Error),
232    SendError(esp_hal::rmt::Error),
233}
234
235impl From<esp_hal::rmt::Error> for Error {
236    fn from(e: esp_hal::rmt::Error) -> Error {
237        Error::SendError(e)
238    }
239}
240
241#[derive(PartialEq, Eq, Clone, Copy)]
242pub struct Address(pub u64);
243
244impl core::fmt::Debug for Address {
245    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
246        core::write!(f, "{:X?}", self.0.to_le_bytes())
247    }
248}
249
250impl core::fmt::Display for Address {
251    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
252        for k in self.0.to_le_bytes() {
253            core::write!(f, "{:X}", k)?;
254        }
255        Ok(())
256    }
257}
258
259pub struct Search {
260    command: u8,
261    address: u64,
262    #[cfg(feature = "search-masks")]
263    address_mask: u64,
264    last_discrepancy: Option<usize>,
265    complete: bool,
266}
267
268#[derive(Debug)]
269pub enum SearchError {
270    SearchComplete,
271    NoDevicesPresent,
272    BusError(Error),
273}
274
275impl From<Error> for SearchError {
276    fn from(e: Error) -> SearchError {
277        SearchError::BusError(e)
278    }
279}
280
281impl Search {
282    pub fn new() -> Search {
283        Search {
284            command: 0xF0,
285            address: 0,
286            #[cfg(feature = "search-masks")]
287            address_mask: 0,
288            last_discrepancy: None,
289            complete: false,
290        }
291    }
292    pub fn new_alarm() -> Search {
293        Search {
294            command: 0xEC,
295            address: 0,
296            #[cfg(feature = "search-masks")]
297            address_mask: 0,
298            last_discrepancy: None,
299            complete: false,
300        }
301    }
302    #[cfg(feature = "search-masks")]
303    pub fn new_with_mask(fixed_bits: u64, bit_mask: u64) {
304        Search {
305            command: 0xEC,
306            address: fixed_bits,
307            address_mask: bit_mask,
308            last_discrepancy: None,
309            complete: false,
310        }
311    }
312    pub async fn next<'d, CFG: OneWireConfig>(
313        &mut self,
314        ow: &mut OneWire<'d, CFG>,
315    ) -> Result<Address, SearchError> {
316        if self.complete {
317            return Err(SearchError::SearchComplete);
318        }
319        let have_devices = ow.reset().await?;
320        let mut last_zero = None;
321        ow.send_byte(self.command).await?;
322        if have_devices {
323            for id_bit_number in 0..64 {
324                let id_bits = ow.exchange_bits([true, true]).await?;
325                let search_direction = match id_bits {
326                    #[cfg(feature = "search-masks")]
327                    _ if address_mask & (1 << id_bit_number) != 0 => {
328                        address & (1 << id_bit_number) != 0
329                    }
330                    [false, true] => false,
331                    [true, false] => true,
332                    [true, true] => {
333                        return Err(SearchError::NoDevicesPresent);
334                    }
335                    [false, false] => {
336                        if self.last_discrepancy == Some(id_bit_number) {
337                            true
338                        } else if Some(id_bit_number) > self.last_discrepancy {
339                            last_zero = Some(id_bit_number);
340                            false
341                        } else {
342                            self.address & (1 << id_bit_number) != 0
343                        }
344                    }
345                };
346                if search_direction {
347                    self.address |= 1 << id_bit_number;
348                } else {
349                    self.address &= !(1 << id_bit_number);
350                }
351                ow.exchange_bits([search_direction]).await?;
352            }
353            self.last_discrepancy = last_zero;
354            self.complete = last_zero.is_none();
355            Ok(Address(self.address))
356        } else {
357            Err(SearchError::NoDevicesPresent)
358        }
359    }
360}