use uom::si::{electric_potential::volt, f64::ElectricPotential};
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum InputChannel {
Single0 = 0b1000,
Single1 = 0b1001,
Single2 = 0b1010,
Single3 = 0b1011,
Single4 = 0b1100,
Single5 = 0b1101,
Single6 = 0b1110,
Single7 = 0b1111,
Diff01 = 0b0000,
Diff10 = 0b0001,
Diff23 = 0b0010,
Diff32 = 0b0011,
Diff45 = 0b0100,
Diff54 = 0b0101,
Diff67 = 0b0110,
Diff76 = 0b0111,
}
#[maybe_async_cfg::maybe(sync(feature = "sync"), async(feature = "async"))]
pub struct MCP3208<I> {
interface: I,
reference_voltage: ElectricPotential,
}
#[maybe_async_cfg::maybe(
idents(hal(sync = "embedded_hal", async = "embedded_hal_async")),
sync(feature = "sync"),
async(feature = "async")
)]
impl<I> MCP3208<I>
where
I: hal::spi::r#SpiDevice,
{
#[inline]
pub fn new_spi(interface: I, reference_voltage: ElectricPotential) -> Self {
Self {
interface,
reference_voltage,
}
}
}
#[maybe_async_cfg::maybe(
idents(hal(sync = "embedded_hal", async = "embedded_hal_async")),
sync(feature = "sync"),
async(feature = "async")
)]
impl<I: hal::spi::r#SpiDevice> MCP3208<I> {
pub async fn convert_raw(&mut self, channel: InputChannel) -> Result<u16, I::Error> {
let command: u8 = 0b01000000 | (channel as u8) << 2;
let mut data = [command, 0, 0];
self.interface.transfer_in_place(&mut data).await?;
Ok((data[1] as u16) << 4 | (data[2] as u16) >> 4)
}
pub async fn convert(&mut self, channel: InputChannel) -> Result<ElectricPotential, I::Error> {
let raw_value = self.convert_raw(channel).await?;
let v_ref = self.reference_voltage.get::<volt>();
let value = ElectricPotential::new::<volt>(raw_value as f64 * v_ref / 4096.0);
Ok(value)
}
}