use bit_field::BitField;
use crate::analog::VoltageReference;
use crate::settings::{ClockOutputSetting, GpSettings};
#[derive(Debug, Clone, Copy)]
pub struct InterruptSettingsChanges {
clear_interrupt_flag: bool,
interrupt_on_positive_edge: Option<bool>,
interrupt_on_negative_edge: Option<bool>,
}
impl InterruptSettingsChanges {
pub fn clear_flag(clear: bool) -> Self {
Self {
clear_interrupt_flag: clear,
interrupt_on_positive_edge: None,
interrupt_on_negative_edge: None,
}
}
pub fn interrupt_on_positive_edge(&mut self, v: bool) -> &mut Self {
self.interrupt_on_positive_edge = Some(v);
self
}
pub fn interrupt_on_negative_edge(&mut self, v: bool) -> &mut Self {
self.interrupt_on_negative_edge = Some(v);
self
}
}
#[derive(Debug, Default, Clone, Copy)]
pub struct SramSettingsChanges {
clock_output: Option<ClockOutputSetting>,
dac_reference: Option<VoltageReference>,
dac_value: Option<u8>,
adc_reference: Option<VoltageReference>,
interrupt_settings: Option<InterruptSettingsChanges>,
gp_settings: Option<GpSettings>,
}
impl SramSettingsChanges {
pub fn new() -> Self {
Self::default()
}
pub fn with_clock_output(&mut self, clock: ClockOutputSetting) -> &mut Self {
self.clock_output = Some(clock);
self
}
pub fn with_dac_reference(&mut self, vref: VoltageReference) -> &mut Self {
self.dac_reference = Some(vref);
self
}
pub fn with_dac_value(&mut self, value: u8) -> &mut Self {
self.dac_value = Some(value & 31);
self
}
pub fn with_adc_reference(&mut self, vref: VoltageReference) -> &mut Self {
self.adc_reference = Some(vref);
self
}
pub fn with_interrupt_settings(
&mut self,
interrupt_settings: InterruptSettingsChanges,
) -> &mut Self {
self.interrupt_settings = Some(interrupt_settings);
self
}
pub fn with_gp_modes(
&mut self,
gp_settings: GpSettings,
dac_reference: Option<VoltageReference>,
adc_reference: Option<VoltageReference>,
) -> &mut Self {
self.gp_settings = Some(gp_settings);
if dac_reference.is_some() {
self.dac_reference = dac_reference;
}
if adc_reference.is_some() {
self.adc_reference = adc_reference;
}
self
}
pub(crate) fn apply_to_sram_buffer(&self, buf: &mut [u8; 64]) {
if let Some(clock) = self.clock_output {
buf[2].set_bit(7, true);
buf[2].set_bits(0..=4, clock.into());
}
if let Some(dac_vref) = self.dac_reference {
let (vrm_vdd, vrm_level) = dac_vref.into();
buf[3].set_bit(7, true);
buf[3].set_bits(1..=2, vrm_level);
buf[3].set_bit(0, vrm_vdd);
}
if let Some(value) = self.dac_value {
buf[4].set_bit(7, true);
buf[4].set_bits(0..=4, value);
}
if let Some(adc_vref) = self.adc_reference {
let (vrm_vdd, vrm_level) = adc_vref.into();
buf[5].set_bit(7, true);
buf[5].set_bits(1..=2, vrm_level);
buf[5].set_bit(0, vrm_vdd);
}
if let Some(ref interrupts) = self.interrupt_settings {
buf[6].set_bit(7, true);
if let Some(trigger) = interrupts.interrupt_on_positive_edge {
buf[6].set_bit(4, true);
buf[6].set_bit(3, trigger);
}
if let Some(trigger) = interrupts.interrupt_on_negative_edge {
buf[6].set_bit(2, true);
buf[6].set_bit(1, trigger);
}
buf[6].set_bit(0, interrupts.clear_interrupt_flag);
}
if let Some(ref gp_settings) = self.gp_settings {
buf[7].set_bit(7, true);
buf[8].set_bit(4, gp_settings.gp0_value.into());
buf[8].set_bit(3, gp_settings.gp0_direction.into());
buf[8].set_bits(0..=2, gp_settings.gp0_mode.into());
buf[9].set_bit(4, gp_settings.gp1_value.into());
buf[9].set_bit(3, gp_settings.gp1_direction.into());
buf[9].set_bits(0..=2, gp_settings.gp1_mode.into());
buf[10].set_bit(4, gp_settings.gp2_value.into());
buf[10].set_bit(3, gp_settings.gp2_direction.into());
buf[10].set_bits(0..=2, gp_settings.gp2_mode.into());
buf[11].set_bit(4, gp_settings.gp3_value.into());
buf[11].set_bit(3, gp_settings.gp3_direction.into());
buf[11].set_bits(0..=2, gp_settings.gp3_mode.into());
}
}
}