use std::fs::read_to_string;
use std::string::{String, ToString};
pub use serde::{Deserialize, de::DeserializeOwned};
pub use structopt::StructOpt;
pub use simplelog::{TermLogger, LevelFilter};
pub use embedded_hal::digital::v2::{InputPin, OutputPin};
pub use linux_embedded_hal::{spidev, Spidev, Pin as Pindev, Delay};
pub use linux_embedded_hal::sysfs_gpio::Direction;
use crate::wrapper::Wrapper;
#[derive(Debug, StructOpt, Deserialize)]
pub struct DeviceConfig {
#[structopt(short = "d", long = "spi-dev", default_value = "/dev/spidev0.0")]
spi: String,
#[structopt(short = "b", long = "spi-baud", default_value = "1000000", env = "SX127X_BAUD")]
baud: u32,
#[structopt(long = "cs-pin", default_value = "16")]
chip_select: u64,
#[structopt(long = "reset-pin")]
reset: Option<u64>,
#[structopt(long = "busy-pin")]
busy: Option<u64>,
#[structopt(long = "ready-pin")]
ready: Option<u64>,
}
impl DeviceConfig {
pub fn load(&self) -> Wrapper<Spidev, std::io::Error, Pindev, Pindev, (), Delay> {
let spi = load_spi(&self.spi, self.baud, spidev::SPI_MODE_0);
let mut cs = load_pin(self.chip_select, Direction::Out);
cs.set_high().unwrap();
let mut w = Wrapper::new(spi, cs, Delay{});
if let Some(v) = self.busy {
w.with_busy(load_pin(v, Direction::In));
}
if let Some(v) = self.ready {
w.with_ready(load_pin(v, Direction::In));
}
if let Some(v) = self.reset {
w.with_reset(load_pin(v, Direction::Out));
}
w
}
}
#[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(spidev::SPI_MODE_0 | spidev::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{}
}