forked from M-Labs/ionpak-thermostat
implement softspi
This commit is contained in:
parent
2fcae2cdee
commit
4bf52b093e
1
firmware/Cargo.lock
generated
1
firmware/Cargo.lock
generated
@ -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)",
|
||||
|
@ -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"
|
||||
|
@ -2,6 +2,7 @@ use cortex_m;
|
||||
use tm4c129x;
|
||||
|
||||
mod gpio;
|
||||
mod softspi;
|
||||
|
||||
|
||||
const LED1: u8 = 0x10; // PK4
|
||||
|
104
firmware/src/board/softspi.rs
Normal file
104
firmware/src/board/softspi.rs
Normal file
@ -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 crc;
|
||||
extern crate embedded_hal;
|
||||
extern crate nb;
|
||||
|
||||
use core::cell::{Cell, RefCell};
|
||||
use core::fmt;
|
||||
|
Loading…
Reference in New Issue
Block a user