diff --git a/firmware/Cargo.lock b/firmware/Cargo.lock index 343e2c7..5b80994 100644 --- a/firmware/Cargo.lock +++ b/firmware/Cargo.lock @@ -120,6 +120,7 @@ dependencies = [ "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)", "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)", "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)", diff --git a/firmware/Cargo.toml b/firmware/Cargo.toml index c10efea..e903799 100644 --- a/firmware/Cargo.toml +++ b/firmware/Cargo.toml @@ -13,6 +13,7 @@ cortex-m-rt = "0.6" crc = { version = "1.7", default-features = false } tm4c129x = { version = "0.8", features = ["rt"] } embedded-hal = { version = "0.2", features = ["unproven"] } +nb = "0.1" [dependencies.smoltcp] git = "https://github.com/m-labs/smoltcp" diff --git a/firmware/src/board/mod.rs b/firmware/src/board/mod.rs index 8fb7303..6c57e8e 100644 --- a/firmware/src/board/mod.rs +++ b/firmware/src/board/mod.rs @@ -2,6 +2,7 @@ use cortex_m; use tm4c129x; mod gpio; +mod softspi; const LED1: u8 = 0x10; // PK4 diff --git a/firmware/src/board/softspi.rs b/firmware/src/board/softspi.rs new file mode 100644 index 0000000..8d8e31a --- /dev/null +++ b/firmware/src/board/softspi.rs @@ -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: SCK, + mosi: MOSI, + miso: MISO, + state: State, + input: Option, +} + +#[derive(PartialEq)] +enum State { + Idle, + Transfer { + clock_phase: bool, + mask: u8, + output: u8, + input: u8, + }, +} + +impl SoftSpi { + 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 FullDuplex for SoftSpi { + type Error = (); + + fn read(&mut self) -> Result> { + 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> { + match self.state { + State::Idle => { + self.state = State::Transfer { + clock_phase: false, + mask: 0x80, + output, + input: 0, + }; + Ok(()) + } + _ => Err(WouldBlock) + } + } +} diff --git a/firmware/src/main.rs b/firmware/src/main.rs index 39c5b02..986756c 100644 --- a/firmware/src/main.rs +++ b/firmware/src/main.rs @@ -11,6 +11,7 @@ extern crate tm4c129x; extern crate smoltcp; extern crate crc; extern crate embedded_hal; +extern crate nb; use core::cell::{Cell, RefCell}; use core::fmt;