-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 97ed511
Showing
7 changed files
with
251 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
/target | ||
**/*.rs.bk | ||
Cargo.lock |
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,12 @@ | ||
[package] | ||
name = "bitbang-hal" | ||
version = "0.1.0" | ||
authors = ["Paul Sajna <sajattack@gmail.com>"] | ||
edition = "2018" | ||
|
||
[dependencies] | ||
nb = "~0.1" | ||
|
||
[dependencies.embedded-hal] | ||
version = "~0.2" | ||
features = ["unproven"] |
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,6 @@ | ||
#![no_std] | ||
|
||
pub mod i2c; | ||
pub mod spi; | ||
pub mod serial; | ||
pub mod time; |
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,162 @@ | ||
use embedded_hal::spi::FullDuplex; | ||
use embedded_hal::spi::Mode; | ||
use embedded_hal::spi::Phase::*; | ||
use embedded_hal::spi::Polarity::*; | ||
use embedded_hal::digital::{InputPin, OutputPin}; | ||
use embedded_hal::blocking::delay::DelayUs; | ||
use crate::time::Hertz; | ||
use nb; | ||
|
||
#[derive(Debug)] | ||
pub enum Error { | ||
Unimplemented, | ||
} | ||
|
||
pub struct SPI<Miso, Mosi, Sck, Delay> | ||
where | ||
Miso: InputPin, | ||
Mosi: OutputPin, | ||
Sck: OutputPin, | ||
Delay: DelayUs<u32> | ||
{ | ||
mode: Mode, | ||
miso: Miso, | ||
mosi: Mosi, | ||
sck: Sck, | ||
delay: Delay, | ||
half_delay_us: u32, | ||
} | ||
|
||
impl <Miso, Mosi, Sck, Delay> SPI<Miso, Mosi, Sck, Delay> | ||
where | ||
Miso: InputPin, | ||
Mosi: OutputPin, | ||
Sck: OutputPin, | ||
Delay: DelayUs<u32> | ||
{ | ||
pub fn new<F: Into<Hertz>>( | ||
freq: F, | ||
mode: Mode, | ||
miso: Miso, | ||
mosi: Mosi, | ||
sck: Sck, | ||
delay: Delay, | ||
) -> Self { | ||
let hertz = freq.into().0; | ||
let mut half_delay_us = 500_000 / hertz; | ||
// round up the delay (lower the baudrate) | ||
if 500_000 % hertz != 0 { | ||
half_delay_us += 1; | ||
} | ||
SPI { | ||
mode: mode, | ||
miso: miso, | ||
mosi: mosi, | ||
sck: sck, | ||
delay: delay, | ||
half_delay_us: half_delay_us | ||
} | ||
} | ||
} | ||
|
||
impl<Miso, Mosi, Sck, Delay> FullDuplex<u8> for SPI<Miso, Mosi, Sck, Delay> | ||
where | ||
Miso: InputPin, | ||
Mosi: OutputPin, | ||
Sck: OutputPin, | ||
Delay: DelayUs<u32> | ||
{ | ||
type Error = Error; | ||
|
||
fn read(&mut self) -> nb::Result<u8, Error> { | ||
self.mosi.set_low(); | ||
let mut data_in: u8 = 0; | ||
for _bit in 0..8 { | ||
if self.mode.phase == CaptureOnFirstTransition { | ||
if self.mode.polarity == IdleLow { | ||
self.delay.delay_us(self.half_delay_us); | ||
self.sck.set_high(); | ||
if self.miso.is_high() { | ||
data_in = (data_in << 1) | 1 | ||
} else { | ||
data_in = data_in << 1 | ||
} | ||
self.delay.delay_us(self.half_delay_us); | ||
self.sck.set_low(); | ||
} else { | ||
self.delay.delay_us(self.half_delay_us); | ||
self.sck.set_low(); | ||
if self.miso.is_high() { | ||
data_in = (data_in << 1) | 1 | ||
} else { | ||
data_in = data_in << 1 | ||
} | ||
self.delay.delay_us(self.half_delay_us); | ||
self.sck.set_high(); | ||
} | ||
} else { | ||
if self.mode.polarity == IdleLow { | ||
self.sck.set_high(); | ||
self.delay.delay_us(self.half_delay_us); | ||
if self.miso.is_high() { | ||
data_in = (data_in << 1) | 1 | ||
} else { | ||
data_in = data_in << 1 | ||
} | ||
self.sck.set_low(); | ||
self.delay.delay_us(self.half_delay_us); | ||
} else { | ||
self.sck.set_low(); | ||
self.delay.delay_us(self.half_delay_us); | ||
if self.miso.is_high() { | ||
data_in = (data_in << 1) | 1 | ||
} else { | ||
data_in = data_in << 1 | ||
} | ||
self.sck.set_high(); | ||
self.delay.delay_us(self.half_delay_us); | ||
} | ||
} | ||
} | ||
Ok(data_in) | ||
} | ||
|
||
fn send(&mut self, byte: u8) -> nb::Result<(), Self::Error> { | ||
let mut data_out = byte; | ||
for _bit in 0..8 { | ||
let out_bit = (data_out >> 7) & 1; | ||
if out_bit == 1 { | ||
self.mosi.set_high(); | ||
} else { | ||
self.mosi.set_low(); | ||
} | ||
if self.mode.phase == CaptureOnFirstTransition { | ||
if self.mode.polarity == IdleLow { | ||
self.delay.delay_us(self.half_delay_us); | ||
self.sck.set_high(); | ||
self.delay.delay_us(self.half_delay_us); | ||
self.sck.set_low(); | ||
} else { | ||
self.delay.delay_us(self.half_delay_us); | ||
self.sck.set_low(); | ||
self.delay.delay_us(self.half_delay_us); | ||
self.sck.set_high(); | ||
} | ||
} else { | ||
if self.mode.polarity == IdleLow { | ||
self.sck.set_high(); | ||
self.delay.delay_us(self.half_delay_us); | ||
self.sck.set_low(); | ||
self.delay.delay_us(self.half_delay_us); | ||
} else { | ||
self.sck.set_low(); | ||
self.delay.delay_us(self.half_delay_us); | ||
self.sck.set_high(); | ||
self.delay.delay_us(self.half_delay_us); | ||
} | ||
} | ||
data_out <<= 1; | ||
} | ||
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
//! Time units | ||
/// Bits per second | ||
#[derive(Clone, Copy, PartialEq, Eq, Debug)] | ||
pub struct Bps(pub u32); | ||
|
||
/// Hertz | ||
#[derive(Clone, Copy, PartialEq, Eq, Debug)] | ||
pub struct Hertz(pub u32); | ||
|
||
/// KiloHertz | ||
#[derive(Clone, Copy, PartialEq, Eq, Debug)] | ||
pub struct KiloHertz(pub u32); | ||
|
||
/// MegaHertz | ||
#[derive(Clone, Copy, PartialEq, Eq, Debug)] | ||
pub struct MegaHertz(pub u32); | ||
|
||
/// Extension trait that adds convenience methods to the `u32` type | ||
pub trait U32Ext { | ||
/// Wrap in `Bps` | ||
fn bps(self) -> Bps; | ||
|
||
/// Wrap in `Hertz` | ||
fn hz(self) -> Hertz; | ||
|
||
/// Wrap in `KiloHertz` | ||
fn khz(self) -> KiloHertz; | ||
|
||
/// Wrap in `MegaHertz` | ||
fn mhz(self) -> MegaHertz; | ||
} | ||
|
||
impl U32Ext for u32 { | ||
fn bps(self) -> Bps { | ||
Bps(self) | ||
} | ||
|
||
fn hz(self) -> Hertz { | ||
Hertz(self) | ||
} | ||
|
||
fn khz(self) -> KiloHertz { | ||
KiloHertz(self) | ||
} | ||
|
||
fn mhz(self) -> MegaHertz { | ||
MegaHertz(self) | ||
} | ||
} | ||
|
||
impl Into<Hertz> for KiloHertz { | ||
fn into(self) -> Hertz { | ||
Hertz(self.0 * 1_000) | ||
} | ||
} | ||
|
||
impl Into<Hertz> for MegaHertz { | ||
fn into(self) -> Hertz { | ||
Hertz(self.0 * 1_000_000) | ||
} | ||
} | ||
|
||
impl Into<KiloHertz> for MegaHertz { | ||
fn into(self) -> KiloHertz { | ||
KiloHertz(self.0 * 1_000) | ||
} | ||
} |