thermostat/src/ad5680.rs

59 lines
1.4 KiB
Rust
Raw Normal View History

2020-03-13 04:27:03 +08:00
use stm32f4xx_hal::{
hal::{
blocking::spi::Transfer,
digital::v2::OutputPin,
},
2020-03-13 04:27:03 +08:00
time::MegaHertz,
spi,
};
2020-05-29 02:45:42 +08:00
use crate::timer::sleep;
2020-03-13 04:27:03 +08:00
2020-05-14 05:19:09 +08:00
/// SPI Mode 1
2020-03-13 04:27:03 +08:00
pub const SPI_MODE: spi::Mode = spi::Mode {
2020-05-14 05:19:09 +08:00
polarity: spi::Polarity::IdleLow,
phase: spi::Phase::CaptureOnSecondTransition,
2020-03-13 04:27:03 +08:00
};
/// 30 MHz
pub const SPI_CLOCK: MegaHertz = MegaHertz(30);
2020-05-14 05:19:20 +08:00
pub const MAX_VALUE: u32 = 0x3FFFF;
2020-03-20 01:34:57 +08:00
2020-03-13 04:27:03 +08:00
/// [AD5680](https://www.analog.com/media/en/technical-documentation/data-sheets/AD5680.pdf) DAC
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 {
2020-05-16 07:18:14 +08:00
let _ = sync.set_low();
2020-03-13 04:27:03 +08:00
Dac {
spi,
sync,
}
}
2020-05-29 02:45:42 +08:00
fn write(&mut self, buf: &mut [u8]) -> Result<(), SPI::Error> {
2020-05-16 07:18:14 +08:00
// pulse sync to start a new transfer. leave sync idle low
// afterwards to save power as recommended per datasheet.
2020-03-13 04:27:03 +08:00
let _ = self.sync.set_high();
2020-05-29 02:45:42 +08:00
// must be high for >= 33 ns
sleep(1);
2020-05-16 07:18:14 +08:00
let _ = self.sync.set_low();
2020-05-29 02:45:42 +08:00
self.spi.transfer(buf)?;
2020-05-16 07:18:14 +08:00
Ok(())
2020-03-13 04:27:03 +08:00
}
2020-09-17 04:05:31 +08:00
pub fn set(&mut self, value: u32) -> Result<u32, SPI::Error> {
2020-09-07 01:06:31 +08:00
let value = value.min(MAX_VALUE);
2020-05-29 02:45:42 +08:00
let mut buf = [
2020-03-13 04:27:03 +08:00
(value >> 14) as u8,
(value >> 6) as u8,
(value << 2) as u8,
];
2020-09-17 04:05:31 +08:00
self.write(&mut buf)?;
Ok(value)
2020-03-13 04:27:03 +08:00
}
}