forked from M-Labs/ionpak-thermostat
implement softspi
This commit is contained in:
parent
2fcae2cdee
commit
4bf52b093e
|
@ -120,6 +120,7 @@ dependencies = [
|
||||||
"crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"embedded-hal 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"embedded-hal 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libm 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libm 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"nb 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"smoltcp 0.4.0 (git+https://github.com/m-labs/smoltcp?rev=cd893e6)",
|
"smoltcp 0.4.0 (git+https://github.com/m-labs/smoltcp?rev=cd893e6)",
|
||||||
"tm4c129x 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tm4c129x 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
|
|
@ -13,6 +13,7 @@ cortex-m-rt = "0.6"
|
||||||
crc = { version = "1.7", default-features = false }
|
crc = { version = "1.7", default-features = false }
|
||||||
tm4c129x = { version = "0.8", features = ["rt"] }
|
tm4c129x = { version = "0.8", features = ["rt"] }
|
||||||
embedded-hal = { version = "0.2", features = ["unproven"] }
|
embedded-hal = { version = "0.2", features = ["unproven"] }
|
||||||
|
nb = "0.1"
|
||||||
|
|
||||||
[dependencies.smoltcp]
|
[dependencies.smoltcp]
|
||||||
git = "https://github.com/m-labs/smoltcp"
|
git = "https://github.com/m-labs/smoltcp"
|
||||||
|
|
|
@ -2,6 +2,7 @@ use cortex_m;
|
||||||
use tm4c129x;
|
use tm4c129x;
|
||||||
|
|
||||||
mod gpio;
|
mod gpio;
|
||||||
|
mod softspi;
|
||||||
|
|
||||||
|
|
||||||
const LED1: u8 = 0x10; // PK4
|
const LED1: u8 = 0x10; // PK4
|
||||||
|
|
|
@ -0,0 +1,104 @@
|
||||||
|
use embedded_hal::spi::FullDuplex;
|
||||||
|
use embedded_hal::digital::v2::{InputPin, OutputPin};
|
||||||
|
use nb::Error::WouldBlock;
|
||||||
|
|
||||||
|
/// Bit-banged SPI
|
||||||
|
pub struct SoftSpi<SCK, MOSI, MISO> {
|
||||||
|
sck: SCK,
|
||||||
|
mosi: MOSI,
|
||||||
|
miso: MISO,
|
||||||
|
state: State,
|
||||||
|
input: Option<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq)]
|
||||||
|
enum State {
|
||||||
|
Idle,
|
||||||
|
Transfer {
|
||||||
|
clock_phase: bool,
|
||||||
|
mask: u8,
|
||||||
|
output: u8,
|
||||||
|
input: u8,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<SCK: OutputPin, MOSI: OutputPin, MISO: InputPin> SoftSpi<SCK, MOSI, MISO> {
|
||||||
|
pub fn new(mut sck: SCK, mut mosi: MOSI, miso: MISO) -> Self {
|
||||||
|
let _ = sck.set_high();
|
||||||
|
let _ = mosi.set_low();
|
||||||
|
SoftSpi {
|
||||||
|
sck, mosi, miso,
|
||||||
|
state: State::Idle,
|
||||||
|
input: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Call this at twice the data rate
|
||||||
|
pub fn tick(&mut self) {
|
||||||
|
match self.state {
|
||||||
|
State::Idle => {}
|
||||||
|
State::Transfer { clock_phase: false,
|
||||||
|
mask, output, input } => {
|
||||||
|
if output & mask != 0 {
|
||||||
|
let _ = self.mosi.set_high();
|
||||||
|
} else {
|
||||||
|
let _ = self.mosi.set_low();
|
||||||
|
}
|
||||||
|
let _ = self.sck.set_low();
|
||||||
|
|
||||||
|
self.state = State::Transfer {
|
||||||
|
clock_phase: true,
|
||||||
|
mask, output, input,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
State::Transfer { clock_phase: true,
|
||||||
|
mask, output, mut input } => {
|
||||||
|
let _ = self.sck.set_high();
|
||||||
|
if self.miso.is_high().unwrap_or(false) {
|
||||||
|
input |= mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
if mask != 1 {
|
||||||
|
self.state = State::Transfer {
|
||||||
|
clock_phase: false,
|
||||||
|
mask: mask >> 1,
|
||||||
|
output, input,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
self.input = Some(input);
|
||||||
|
self.state = State::Idle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<SCK: OutputPin, MOSI: OutputPin, MISO: InputPin> FullDuplex<u8> for SoftSpi<SCK, MOSI, MISO> {
|
||||||
|
type Error = ();
|
||||||
|
|
||||||
|
fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> {
|
||||||
|
match self.input.take() {
|
||||||
|
Some(input) =>
|
||||||
|
Ok(input),
|
||||||
|
None if self.state == State::Idle =>
|
||||||
|
Err(nb::Error::Other(())),
|
||||||
|
None =>
|
||||||
|
Err(WouldBlock),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn send(&mut self, output: u8) -> Result<(), nb::Error<Self::Error>> {
|
||||||
|
match self.state {
|
||||||
|
State::Idle => {
|
||||||
|
self.state = State::Transfer {
|
||||||
|
clock_phase: false,
|
||||||
|
mask: 0x80,
|
||||||
|
output,
|
||||||
|
input: 0,
|
||||||
|
};
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
_ => Err(WouldBlock)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,6 +11,7 @@ extern crate tm4c129x;
|
||||||
extern crate smoltcp;
|
extern crate smoltcp;
|
||||||
extern crate crc;
|
extern crate crc;
|
||||||
extern crate embedded_hal;
|
extern crate embedded_hal;
|
||||||
|
extern crate nb;
|
||||||
|
|
||||||
use core::cell::{Cell, RefCell};
|
use core::cell::{Cell, RefCell};
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
|
|
Loading…
Reference in New Issue