use core::marker::PhantomData;
use core::ptr;
use esp_idf_sys::*;
use crate::gpio::{InputPin, OutputPin};
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct OWAddress(u64);
impl OWAddress {
pub fn address(&self) -> u64 {
self.0
}
pub fn family_code(&self) -> u8 {
(self.0 & u64::from(0xffu8)) as u8
}
}
pub struct DeviceSearch<'a, 'b> {
search: onewire_device_iter_handle_t,
_bus: &'a mut OWDriver<'b>,
}
impl<'a, 'b> DeviceSearch<'a, 'b> {
fn new(bus: &'a mut OWDriver<'b>) -> Result<Self, EspError> {
let mut my_iter: onewire_device_iter_handle_t = ptr::null_mut();
esp!(unsafe { onewire_new_device_iter(bus.handle(), &mut my_iter) })?;
Ok(Self {
search: my_iter,
_bus: bus,
})
}
fn next_device(&mut self) -> Result<OWAddress, EspError> {
let mut next_onewire_device = onewire_device_t::default();
esp!(unsafe { onewire_device_iter_get_next(self.search, &mut next_onewire_device) })?;
Ok(OWAddress(next_onewire_device.address))
}
}
impl<'a, 'b> Iterator for DeviceSearch<'a, 'b> {
type Item = Result<OWAddress, EspError>;
fn next(&mut self) -> Option<Self::Item> {
match self.next_device() {
Ok(addr) => Some(Ok(addr)),
Err(err) if err.code() == ESP_ERR_NOT_FOUND => None,
Err(err) => Some(Err(err)),
}
}
}
impl<'a, 'b> Drop for DeviceSearch<'a, 'b> {
fn drop(&mut self) {
esp!(unsafe { onewire_del_device_iter(self.search) }).unwrap();
}
}
#[derive(Debug)]
pub struct OWDriver<'a> {
handle: onewire_bus_handle_t,
_p: PhantomData<&'a mut ()>,
}
impl<'a> OWDriver<'a> {
pub fn new(pin: impl InputPin + OutputPin + 'a) -> Result<Self, EspError> {
let pin = pin.pin() as _;
let bus_config = onewire_bus_config_t {
bus_gpio_num: pin,
flags: Default::default(),
};
let rmt_config = onewire_bus_rmt_config_t { max_rx_bytes: 10 };
let mut handle: onewire_bus_handle_t = ptr::null_mut();
esp!(unsafe { onewire_new_bus_rmt(&bus_config, &rmt_config, &mut handle) })?;
Ok(Self {
handle,
_p: PhantomData,
})
}
pub fn handle(&self) -> onewire_bus_handle_t {
self.handle
}
pub fn read(&self, buf: &mut [u8]) -> Result<(), EspError> {
esp!(unsafe {
onewire_bus_read_bytes(self.handle(), buf.as_mut_ptr() as *mut _, buf.len())
})?;
Ok(())
}
pub fn write(&self, data: &[u8]) -> Result<(), EspError> {
esp!(unsafe { onewire_bus_write_bytes(self.handle(), data.as_ptr(), data.len() as u8) })?;
Ok(())
}
pub fn reset(&self) -> Result<(), EspError> {
esp!(unsafe { onewire_bus_reset(self.handle()) })
}
pub fn search(&mut self) -> Result<DeviceSearch<'_, 'a>, EspError> {
DeviceSearch::new(self)
}
}
impl<'d> Drop for OWDriver<'d> {
fn drop(&mut self) {
esp!(unsafe { onewire_bus_del(self.handle()) }).unwrap();
}
}
unsafe impl<'d> Send for OWDriver<'d> {}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
#[repr(u8)]
pub enum OWCommand {
Search = 0xF0, MatchRom = 0x55, SkipRom = 0xCC, ReadRom = 0x33, SearchAlarm = 0xEC, ReadPowerSupply = 0xB4,
}