-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Sample driver implementation/draft for rust-embedded/embedded-hal#54
Quick refactor to fit the model described in rust-embedded/embedded-hal#54 (comment) Optional parasite mode for the OpenDrain implementation got dropped.
- Loading branch information
1 parent
e44cdf2
commit 9bdc2da
Showing
9 changed files
with
400 additions
and
342 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
|
||
use super::ADDRESS_BYTES; | ||
|
||
use core::fmt::Display; | ||
use core::fmt::Formatter; | ||
|
||
#[derive(Debug, Clone, PartialOrd, PartialEq)] | ||
pub struct Device { | ||
pub address: [u8; ADDRESS_BYTES as usize] | ||
} | ||
|
||
impl Device { | ||
pub fn family_code(&self) -> u8 { | ||
self.address[0] | ||
} | ||
} | ||
|
||
|
||
impl Display for Device { | ||
fn fmt(&self, f: &mut Formatter) -> ::core::fmt::Result { | ||
write!(f, "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}", | ||
self.address[0], | ||
self.address[1], | ||
self.address[2], | ||
self.address[3], | ||
self.address[4], | ||
self.address[5], | ||
self.address[6], | ||
self.address[7], | ||
) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
extern crate embedded_hal as hal; | ||
|
||
use self::hal::digital::OutputPin; | ||
use self::hal::digital::InputPin; | ||
use self::hal::blocking::delay::DelayUs; | ||
|
||
|
||
use Error; | ||
use Driver; | ||
use BitDriver; | ||
|
||
|
||
pub trait OpenDrainOutput: OutputPin + InputPin {} | ||
impl<P: OutputPin + InputPin> OpenDrainOutput for P {} | ||
|
||
pub struct BlockingOpenDrainByteDriver<'a> { | ||
pin: &'a mut OpenDrainOutput, | ||
delay: &'a mut DelayUs<u16>, | ||
} | ||
|
||
impl<'a> BlockingOpenDrainByteDriver<'a> { | ||
pub fn new(pin: &'a mut OpenDrainOutput, delay: &'a mut DelayUs<u16>) -> BlockingOpenDrainByteDriver<'a> { | ||
BlockingOpenDrainByteDriver { | ||
pin, | ||
delay, | ||
} | ||
} | ||
|
||
fn set_input(&mut self) { | ||
// nothing to do | ||
self.pin.set_high() | ||
} | ||
|
||
fn set_output(&mut self) { | ||
// nothing to do | ||
} | ||
|
||
fn write_low(&mut self) { | ||
self.pin.set_low() | ||
} | ||
|
||
fn write_high(&mut self) { | ||
self.pin.set_high() | ||
} | ||
|
||
fn read(&self) -> bool { | ||
self.pin.is_high() | ||
} | ||
|
||
fn ensure_wire_high(&mut self) -> Result<(), Error> { | ||
for _ in 0..125 { | ||
if self.read_bit()? { | ||
return Ok(()); | ||
} | ||
self.delay.delay_us(2); | ||
} | ||
Err(Error::WireNotHigh) | ||
} | ||
} | ||
|
||
|
||
|
||
impl<'a> Driver for BlockingOpenDrainByteDriver<'a> { | ||
fn reset(&mut self) -> Result<bool, Error> { | ||
// let mut cli = DisableInterrupts::new(); | ||
self.set_input(); | ||
// drop(cli); | ||
|
||
self.ensure_wire_high()?; | ||
// cli = DisableInterrupts::new(); | ||
self.write_low(); | ||
self.set_output(); | ||
|
||
// drop(cli); | ||
self.delay.delay_us(480); | ||
// cli = DisableInterrupts::new(); | ||
self.set_input(); | ||
|
||
let mut val = false; | ||
for _ in 0..7 { | ||
self.delay.delay_us(10); | ||
val |= !self.read_bit()?; | ||
} | ||
// drop(cli); | ||
self.delay.delay_us(410); | ||
Ok(val) | ||
} | ||
} | ||
|
||
impl<'a> BitDriver for BlockingOpenDrainByteDriver<'a> { | ||
fn read_bit(&mut self) -> Result<bool, Error> { | ||
// let cli = DisableInterrupts::new(); | ||
self.set_output(); | ||
self.write_low(); | ||
self.delay.delay_us(3); | ||
self.set_input(); | ||
self.delay.delay_us(2); // was 10 | ||
let val = self.read(); | ||
// drop(cli); | ||
self.delay.delay_us(61); // was 53 | ||
Ok(val) | ||
} | ||
|
||
fn write_bit(&mut self, high: bool) -> Result<(), Error> { | ||
// let cli = DisableInterrupts::new(); | ||
self.write_low(); | ||
self.set_output(); | ||
self.delay.delay_us(if high {10} else {65}); | ||
self.write_high(); | ||
// drop(cli); | ||
self.delay.delay_us(if high {55} else {5}); | ||
Ok(()) | ||
} | ||
} |
Empty file.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
|
||
#[cfg(feature = "embedded-opendrain")] mod embedded_opendrain; | ||
#[cfg(feature = "embedded-opendrain")] pub use self::embedded_opendrain::*; | ||
|
||
#[cfg(feature = "embedded-spi")] mod embedded_spi; | ||
#[cfg(feature = "embedded-spi")] pub use self::embedded_spi::*; | ||
|
||
#[cfg(feature = "linux-gpio")] mod embedded_spi; | ||
#[cfg(feature = "linux-gpio")] pub use self::embedded_spi::*; | ||
|
||
|
||
use super::Error; | ||
|
||
pub trait Driver { | ||
/// Performs a reset and listens for a presence pulse | ||
/// Returns Err(WireNotHigh) if the wire seems to be shortened, | ||
/// Ok(true) if presence pulse has been received and Ok(false) | ||
/// if no other device was detected but the wire seems to be ok | ||
fn reset(&mut self) -> Result<bool, Error>; | ||
} | ||
|
||
pub trait BitDriver: Driver { | ||
fn read_bit(&mut self) -> Result<bool, Error>; | ||
|
||
fn write_bit(&mut self, data: bool) -> Result<(), Error>; | ||
} | ||
|
||
pub trait ByteDriver: Driver { | ||
fn read_byte(&mut self) -> Result<u8, Error>; | ||
|
||
fn read_bytes(&mut self, data: &mut [u8]) -> Result<(), Error> { | ||
for byte in data.iter_mut() { | ||
*byte = self.read_byte()?; | ||
} | ||
Ok(()) | ||
} | ||
|
||
fn write_byte(&mut self, data: u8) -> Result<(), Error>; | ||
|
||
fn write_bytes(&mut self, data: &[u8]) -> Result<(), Error> { | ||
for byte in data { | ||
self.write_byte(*byte)?; | ||
} | ||
Ok(()) | ||
} | ||
} | ||
|
||
impl<T: BitDriver> ByteDriver for T { | ||
fn read_byte(&mut self) -> Result<u8, Error> { | ||
fn to_bit(state: bool) -> u8 { | ||
if state { | ||
0x01 | ||
} else { | ||
0x00 | ||
} | ||
} | ||
Ok( | ||
to_bit(self.read_bit()?) << 7 | ||
| to_bit(self.read_bit()?) << 6 | ||
| to_bit(self.read_bit()?) << 5 | ||
| to_bit(self.read_bit()?) << 4 | ||
| to_bit(self.read_bit()?) << 3 | ||
| to_bit(self.read_bit()?) << 2 | ||
| to_bit(self.read_bit()?) << 1 | ||
| to_bit(self.read_bit()?) | ||
) | ||
} | ||
|
||
fn write_byte(&mut self, data: u8) -> Result<(), Error> { | ||
fn is_bit_set(byte: u8, n: u8) -> bool { | ||
let flag = 0x01 << n; | ||
byte & flag == flag | ||
} | ||
self.write_bit(is_bit_set(data, 7))?; | ||
self.write_bit(is_bit_set(data, 6))?; | ||
self.write_bit(is_bit_set(data, 5))?; | ||
self.write_bit(is_bit_set(data, 4))?; | ||
self.write_bit(is_bit_set(data, 3))?; | ||
self.write_bit(is_bit_set(data, 2))?; | ||
self.write_bit(is_bit_set(data, 1))?; | ||
self.write_bit(is_bit_set(data, 0))?; | ||
Ok(()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.