kirdy/src/thermostat/ad5680.rs

47 lines
1.3 KiB
Rust

use crate::device::sys_timer::sleep;
use fugit::MegahertzU32;
use stm32f4xx_hal::{
hal::{blocking::spi::Transfer, digital::v2::OutputPin},
spi,
};
/// SPI Mode 1
pub const SPI_MODE: spi::Mode = spi::Mode {
polarity: spi::Polarity::IdleLow,
phase: spi::Phase::CaptureOnSecondTransition,
};
pub const SPI_CLOCK_MHZ: MegahertzU32 = MegahertzU32::from_raw(30);
pub const MAX_VALUE: u32 = 0x3FFFF;
pub struct Dac<SPI: Transfer<u8>, S: OutputPin> {
spi: SPI,
sync: S,
}
impl<SPI: Transfer<u8>, S: OutputPin> Dac<SPI, S> {
pub fn new(spi: SPI, mut sync: S) -> Self {
let _ = sync.set_low();
Dac { spi, sync }
}
fn write(&mut self, buf: &mut [u8]) -> Result<(), SPI::Error> {
// pulse sync to start a new transfer. leave sync idle low
// afterwards to save power as recommended per datasheet.
let _ = self.sync.set_high();
// must be high for >= 33 ns
sleep(1);
let _ = self.sync.set_low();
self.spi.transfer(buf)?;
Ok(())
}
pub fn set(&mut self, value: u32) -> Result<u32, SPI::Error> {
let value = value.min(MAX_VALUE);
let mut buf = [(value >> 14) as u8, (value >> 6) as u8, (value << 2) as u8];
self.write(&mut buf)?;
Ok(value)
}
}