use std::fs::read_to_string;
use std::string::{String, ToString};
pub use serde::{de::DeserializeOwned, Deserialize};
pub use structopt::StructOpt;
pub use simplelog::{LevelFilter, TermLogger};
pub use embedded_hal::digital::v2::{InputPin, OutputPin};
pub use linux_embedded_hal::sysfs_gpio::{Direction, Error as PinError};
pub use linux_embedded_hal::{spidev, Delay, Pin as Pindev, Spidev, spidev::SpiModeFlags};
use crate::wrapper::Wrapper;
#[derive(Debug, StructOpt, Deserialize)]
pub struct DeviceConfig {
#[structopt(
short = "d",
long = "spi-dev",
default_value = "/dev/spidev0.0",
env = "SPI_DEV"
)]
spi: String,
#[structopt(
short = "b",
long = "spi-baud",
default_value = "1000000",
env = "SPI_BAUD"
)]
baud: u32,
#[structopt(long = "cs-pin", default_value = "16", env = "CS_PIN")]
chip_select: u64,
#[structopt(long = "reset-pin", default_value = "17", env = "RESET_PIN")]
reset: u64,
#[structopt(long = "busy-pin", env = "BUSY_PIN")]
busy: Option<u64>,
#[structopt(long = "ready-pin")]
ready: Option<u64>,
}
impl DeviceConfig {
pub fn load_base(&self) -> Wrapper<Spidev, std::io::Error, Pindev, (), (), Pindev, PinError, Delay> {
let spi = load_spi(&self.spi, self.baud, SpiModeFlags::SPI_MODE_0);
let mut cs = load_pin(self.chip_select, Direction::Out);
cs.set_high().unwrap();
let reset = load_pin(self.reset, Direction::Out);
Wrapper::new(spi, cs, (), (), reset, Delay {})
}
pub fn load_with_busy(
&self,
) -> Wrapper<Spidev, std::io::Error, Pindev, Pindev, (), Pindev, PinError, Delay> {
let spi = load_spi(&self.spi, self.baud, SpiModeFlags::SPI_MODE_0);
let mut cs = load_pin(self.chip_select, Direction::Out);
cs.set_high().unwrap();
let reset = load_pin(self.reset, Direction::Out);
let busy = self.busy.map(|p| load_pin(p, Direction::Out)).unwrap();
Wrapper::new(spi, cs, busy, (), reset, Delay {})
}
pub fn load_with_ready(
&self,
) -> Wrapper<Spidev, std::io::Error, Pindev, (), Pindev, Pindev, PinError, Delay> {
let spi = load_spi(&self.spi, self.baud, SpiModeFlags::SPI_MODE_0);
let mut cs = load_pin(self.chip_select, Direction::Out);
cs.set_high().unwrap();
let reset = load_pin(self.reset, Direction::Out);
let ready = self.ready.map(|p| load_pin(p, Direction::In)).unwrap();
Wrapper::new(spi, cs, (), ready, reset, Delay {})
}
pub fn load_with_busy_ready(
&self,
) -> Wrapper<Spidev, std::io::Error, Pindev, Pindev, Pindev, Pindev, PinError, Delay> {
let spi = load_spi(&self.spi, self.baud, SpiModeFlags::SPI_MODE_0);
let mut cs = load_pin(self.chip_select, Direction::Out);
cs.set_high().unwrap();
let reset = load_pin(self.reset, Direction::Out);
let busy = self.busy.map(|p| load_pin(p, Direction::Out)).unwrap();
let ready = self.ready.map(|p| load_pin(p, Direction::In)).unwrap();
Wrapper::new(spi, cs, busy, ready, reset, Delay {})
}
}
#[derive(Debug, StructOpt)]
pub struct LogConfig {
#[structopt(long = "log-level", default_value = "info")]
level: LevelFilter,
}
pub fn load_spi(path: &str, baud: u32, mode: spidev::SpiModeFlags) -> Spidev {
debug!(
"Conecting to spi: {} at {} baud with mode: {:?}",
path, baud, mode
);
let mut spi = Spidev::open(path).expect("error opening spi device");
let mut config = spidev::SpidevOptions::new();
config.mode(SpiModeFlags::SPI_MODE_0 | SpiModeFlags::SPI_NO_CS);
config.max_speed_hz(baud);
spi.configure(&config)
.expect("error configuring spi device");
spi
}
pub fn load_pin(index: u64, direction: Direction) -> Pindev {
debug!(
"Connecting to pin: {} with direction: {:?}",
index, direction
);
let p = Pindev::new(index);
p.export().expect("error exporting cs pin");
p.set_direction(direction)
.expect("error setting cs pin direction");
p
}
pub fn init_logging(level: LevelFilter) {
TermLogger::init(level, simplelog::Config::default()).unwrap();
}
pub fn load_config<T>(file: &str) -> T
where
T: DeserializeOwned,
{
let d = read_to_string(file).expect("error reading file");
toml::from_str(&d).expect("error parsing toml file")
}
pub fn delay() -> Delay {
Delay {}
}