use crate::util::parse_khz;
use espf::context::ParsedNode;
use espf::diag::EspfError;
use espforge_bindings::components::attrs::Issue;
use espforge_bindings::components::generated_elements::spi as schema;
#[derive(Debug, Clone)]
pub struct SpiPeripheral {
pub id: String,
pub sclk: u8,
pub mosi: u8,
pub miso: Option<u8>,
pub khz: u32,
pub mode: u8,
}
pub fn lower_spi(n: &ParsedNode) -> Result<SpiPeripheral, EspfError> {
if n.id != "spi2" {
return Err(EspfError::at_node(
n,
"invalid spi id",
format!("<spi id=\"{}\">: the id must be spi2", n.id),
));
}
let attrs = schema::Attrs::from_node(n).map_err(|issue| {
let (title, message) = describe(n.id, issue);
EspfError::at_node(n, title, message)
})?;
let mode = attrs.mode.value as u8;
let miso = attrs.miso.map(|miso| miso.value);
let khz = match attrs.frequency {
None => 1000,
Some(f) => parse_khz(f.value, "spi", n.id)
.map_err(|m| EspfError::at_node(n, "invalid spi frequency", m))?,
};
Ok(SpiPeripheral {
id: n.id.to_string(),
sclk: attrs.sclk.value,
mosi: attrs.mosi.value,
miso,
khz,
mode,
})
}
fn describe(id: &str, issue: Issue<'_>) -> (&'static str, String) {
match issue {
Issue::Invalid {
attr: "mode",
value,
} => (
"invalid spi mode",
format!("<spi id=\"{id}\"> mode=\"{value}\" must be 0, 1, 2 or 3"),
),
Issue::Missing { attr } | Issue::Invalid { attr, .. } => (
"invalid spi pin",
format!("<spi id=\"{id}\"> needs a numeric {attr}=\"...\""),
),
}
}