#![deny(warnings)]
#![no_std]
pub mod asynchronous;
pub mod blocking;
use core::marker::PhantomData;
#[derive(Eq, PartialEq, Copy, Clone, Debug)]
pub enum Channel {
A = 0,
B = 1,
C = 2,
D = 3,
E = 4,
F = 5,
G = 6,
H = 7,
NOMSG = 8,
BROADCAST = 9,
}
impl Channel {
pub fn from_index(index: u8) -> Channel {
match index {
0 => Channel::A,
1 => Channel::B,
2 => Channel::C,
3 => Channel::D,
4 => Channel::E,
5 => Channel::F,
6 => Channel::G,
7 => Channel::H,
_ => panic!("Unsupported index for dac8568 channel select"),
}
}
}
pub enum ControlType {
WriteToInputRegister = 0,
UpdateRegister = 1,
WriteToChannelAndUpdateAllRegisters = 2,
WriteToChannelAndUpdateSingleRegister = 3,
PowerDownComm = 4,
WriteToClearCodeRegister = 5,
WriteToLDACRegister = 6,
SoftwareReset = 7,
}
#[derive(Copy, Clone)]
pub struct Message {
prefix: u8, control: u8, address: u8, data: u16, feature: u8, }
impl Message {
pub fn get_internal_reference_message(internal: bool) -> Message {
Message {
prefix: 0x00,
control: 0x08,
address: 0x00,
data: 0x0000,
feature: if internal { 0x01 } else { 0x00 },
}
}
pub fn get_voltage_message(channel: Channel, value: u16, is_inverted: bool) -> Message {
let output = if is_inverted { u16::MAX - value } else { value };
Message {
prefix: 0,
control: ControlType::WriteToChannelAndUpdateSingleRegister as u8,
address: channel as u8,
data: output,
feature: 0,
}
}
pub fn get_software_reset_message() -> Message {
Message {
prefix: 0b0001,
control: 0b1100,
address: 0x00,
data: 0x00,
feature: 0x00,
}
}
pub fn get_payload_word(&self) -> u32 {
let mut payload: u32 = 0x00;
payload |= (self.prefix as u32) << 28;
payload |= (self.control as u32) << 24;
payload |= (self.address as u32) << 20;
payload |= (self.data as u32) << 4;
payload |= self.feature as u32;
payload
}
pub fn get_payload_bytes(&self) -> [u8; 4] {
self.get_payload_word().to_be_bytes()
}
}
#[derive(Copy, Clone, Debug)]
#[non_exhaustive]
pub enum DacError {
BusWriteError,
}
pub struct Dac<SPI, SYNC, MODE> {
spi: SPI,
sync: SYNC,
is_inverted: bool,
_mode: PhantomData<MODE>,
}
pub mod mode {
pub struct Blocking;
pub struct Async;
}
impl<SPI, SYNC, MODE> Dac<SPI, SYNC, MODE> {
pub fn new(spi: SPI, sync: SYNC) -> Self {
Self {
spi,
sync,
is_inverted: false,
_mode: PhantomData,
}
}
pub fn release(self) -> (SPI, SYNC) {
(self.spi, self.sync)
}
pub fn set_inverted_output(&mut self, state: bool) {
self.is_inverted = state;
}
}
#[cfg(test)]
mod tests {
#[test]
fn inverts_signal() {
let message = super::Message::get_voltage_message(super::Channel::A, 0, false);
assert_eq!(message.data, 0);
let message = super::Message::get_voltage_message(super::Channel::A, 0, true);
assert_eq!(message.data, u16::MAX);
}
}