use crate::hardware::mct8316a::Mct8316AVDriver;
use crate::hardware::mct8316a::closed_loop::{ClosedLoop1, ClosedLoop2, ClosedLoop3, ClosedLoop4};
use crate::hardware::mct8316a::constant_power::ConstantPower;
use crate::hardware::mct8316a::constant_speed::ConstantSpeed;
use crate::hardware::mct8316a::device_config::DeviceConfig;
use crate::hardware::mct8316a::driver::Mct8316AVData;
use crate::hardware::mct8316a::fault_config::{FaultConfig1, FaultConfig2};
use crate::hardware::mct8316a::gate_driver_config::{GateDriverConfig1, GateDriverConfig2};
use crate::hardware::mct8316a::isd_config::IsdConfig;
use crate::hardware::mct8316a::motor_startup::{MotorStartup1, MotorStartup2};
use crate::hardware::mct8316a::phase_profile::{
    ThreePhase150DegreeProfile, TwoPhase150DegreeProfile,
};
use crate::hardware::mct8316a::pin_config::{PinConfig1, PinConfig2};
use crate::hardware::mct8316a::trap_config::{TrapConfig1, TrapConfig2};
use anyhow::Result;
use embedded_hal::i2c::I2c;
use log::trace;
use std::any::type_name;
use std::fmt::{Debug, Formatter};
use std::thread::sleep;
use std::time::Duration;

pub struct Mct8316AVEeprom<'a, I2C>
where
    I2C: I2c + Send + Sync,
    I2C::Error: Send,
    I2C::Error: Sync,
    I2C::Error: 'static,
{
    driver: &'a mut Mct8316AVDriver<I2C>,
    modified: bool,
}

impl<I2C> Debug for Mct8316AVEeprom<'_, I2C>
where
    I2C: I2c + Send + Sync,
    I2C::Error: Send,
    I2C::Error: Sync,
    I2C::Error: 'static,
{
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(
            f,
            "Mct8316AVEeprom<I2C={}> {{ driver: {:?}, modified: {} }}",
            type_name::<I2C>(),
            self.driver,
            self.modified
        )
    }
}

// We intentionally pass by value in here
#[allow(clippy::needless_pass_by_value)]
impl<'a, I2C> Mct8316AVEeprom<'a, I2C>
where
    I2C: I2c + Send + Sync,
    I2C::Error: Send,
    I2C::Error: Sync,
    I2C::Error: 'static,
{
    pub fn load(driver: &'a mut Mct8316AVDriver<I2C>) -> Result<Self> {
        trace!(
            "Mct8316AVEeprom<I2C={}>::load(driver: {driver:?})",
            type_name::<I2C>()
        );

        driver.write(0x00_00E6, Mct8316AVData::Four(0x4000_0000))?;
        // Wait 100ms for the EEPROM operation to complete
        sleep(Duration::from_millis(100));

        Ok(Self {
            driver,
            modified: false,
        })
    }

    pub fn set_isd_config(self, isd_config: IsdConfig) -> Result<Self> {
        trace!("Mct8316AVEeprom::set_isd_config(self: {self:?}, isd_config: {isd_config:?})");

        let expected_value = if isd_config.enable_isd {
            0x4000_0000
        } else {
            0
        } | if isd_config.enable_brake {
            0x2000_0000
        } else {
            0
        } | if isd_config.enable_high_impedance {
            0x1000_0000
        } else {
            0
        } | if isd_config.enable_reverse_drive {
            0x0800_0000
        } else {
            0
        } | if isd_config.enable_resynchronization {
            0x0400_0000
        } else {
            0
        } | if isd_config.enable_stationary_brake {
            0x0200_0000
        } else {
            0
        } | (((isd_config.stationary_detect_threshold as u32) & 0x7) << 22)
            | ((isd_config.brake_mode as u32) & 0x1) << 21
            | ((isd_config.brake_config as u32) & 0x1) << 20
            | ((isd_config.brake_current_threshold as u32) & 0x7) << 17
            | ((isd_config.brake_time as u32) & 0xF) << 13
            | ((isd_config.high_impedence_time as u32) & 0xF) << 9
            | ((isd_config.startup_break_time as u32) & 0x7) << 6
            | ((isd_config.resync_minimum_threshold as u32) & 0x7) << 3;

        self.assert_register(0x80, Mct8316AVData::Four(expected_value))
    }

    #[allow(clippy::identity_op)]
    pub fn set_motor_startup1(self, motor_startup1: MotorStartup1) -> Result<Self> {
        trace!(
            "Mct8316AVEeprom::set_motor_startup1(self: {self:?}, motor_startup1: {motor_startup1:?})"
        );

        let expected_value = ((motor_startup1.motor_startup_method as u32) & 0x3) << 29
            | ((motor_startup1.align_ramp_rate as u32) & 0xF) << 25
            | ((motor_startup1.align_time as u32) & 0xF) << 21
            | ((motor_startup1.align_current_threshold as u32) & 0xF) << 17
            | ((motor_startup1.ipd_clock_frequency as u32) & 0x7) << 14
            | ((motor_startup1.ipd_current_threshold as u32) & 0xF) << 10
            | ((motor_startup1.ipd_release_mode as u32) & 0x3) << 8
            | ((motor_startup1.ipd_advance_angle as u32) & 0x3) << 6
            | ((motor_startup1.ipd_repeat as u32) & 0x3) << 4
            | ((motor_startup1.slow_first_cycle_frequency as u32) & 0xF) << 0;

        self.assert_register(0x82, Mct8316AVData::Four(expected_value))
    }

    pub fn set_motor_startup2(self, motor_startup2: MotorStartup2) -> Result<Self> {
        trace!(
            "Mct8316AVEeprom::set_motor_startup2(self: {self:?}, motor_startup2: {motor_startup2:?})"
        );

        let expected_value = ((motor_startup2.open_loop_current_limit_mode as u32) & 0x1) << 30
            | ((motor_startup2.open_loop_duty_cycle as u32) & 0x7) << 27
            | ((motor_startup2.open_loop_current_limit as u32) & 0xF) << 23
            | ((motor_startup2.open_loop_acceleration1 as u32) & 0x1F) << 18
            | ((motor_startup2.open_loop_acceleration2 as u32) & 0x1F) << 13
            | ((motor_startup2.open_closed_handoff_threshold as u32) & 0x1F) << 8
            | if motor_startup2.auto_handoff_enable {
                1u32 << 7
            } else {
                0u32
            }
            | ((motor_startup2.first_cycle_frequency_select as u32) & 0x1) << 6
            | ((motor_startup2.minimum_duty_cycle as u32) & 0xF) << 2;

        self.assert_register(0x84, Mct8316AVData::Four(expected_value))
    }

    // The casts in here are save due to clamps
    #[allow(clippy::cast_possible_truncation)]
    #[allow(clippy::cast_sign_loss)]
    pub fn set_closed_loop1(self, closed_loop1: ClosedLoop1) -> Result<Self> {
        trace!("Mct8316AVEeprom::set_closed_loop1(self: {self:?}, closed_loop1: {closed_loop1:?})");

        let lead_angle = (closed_loop1.lead_angle / 0.12f32)
            .round()
            .clamp(0.0f32, f32::from(u8::MAX)) as u8;

        let expected_value = ((closed_loop1.commutation_mode as u32) & 0x2) << 29
            | ((closed_loop1.closed_loop_acceleration_rate as u32) & 0x1F) << 24
            | ((closed_loop1.closed_loop_deceleration_mode as u32) & 0x1) << 23
            | ((closed_loop1.closed_loop_deceleration_rate as u32) & 0x1F) << 18
            | ((closed_loop1.pwm_frequency as u32) & 0x1F) << 13
            | ((closed_loop1.pwm_modulation as u32) & 0x3) << 11
            | ((closed_loop1.pwm_mode as u32) & 0x1) << 10
            | ((closed_loop1.lead_angle_polarity as u32) & 0x1) << 9
            | u32::from(lead_angle) << 1;

        self.assert_register(0x86, Mct8316AVData::Four(expected_value))
    }

    pub fn set_closed_loop2(self, closed_loop2: ClosedLoop2) -> Result<Self> {
        trace!("Mct8316AVEeprom::set_closed_loop2(self: {self:?}, closed_loop2: {closed_loop2:?})");

        let expected_value = ((closed_loop2.speed_feedback_mode as u32) & 0x2) << 29
            | ((closed_loop2.speed_feedback_division as u32) & 0xF) << 25
            | ((closed_loop2.speed_feedback_config as u32) & 0x1) << 24
            | ((closed_loop2.bemf_threshold as u32) & 0x7) << 21
            | ((closed_loop2.motor_stop_mode as u32) & 0x7) << 18
            | ((closed_loop2.motor_stop_brake_time as u32) & 0xF) << 14
            | ((closed_loop2.active_low_high_brake_threshold as u32) & 0x7) << 11
            | ((closed_loop2.brake_pin_threshold as u32) & 0x7) << 8
            | if closed_loop2.avs_enable {
                1u32 << 7
            } else {
                0u32
            }
            | ((closed_loop2.cycle_current_limit as u32) & 0xF) << 3;

        self.assert_register(0x88, Mct8316AVData::Four(expected_value))
    }

    pub fn set_closed_loop3(self, closed_loop3: ClosedLoop3) -> Result<Self> {
        trace!("Mct8316AVEeprom::set_closed_loop3(self: {self:?}, closed_loop3: {closed_loop3:?})");

        let expected_value = ((closed_loop3.degauss_samples as u32) & 0x2) << 29
            | ((closed_loop3.degauss_upper_bound as u32) & 0x3) << 27
            | ((closed_loop3.degauss_lower_bound as u32) & 0x3) << 25
            | ((closed_loop3.integration_cycle_low_threshold as u32) & 0x3) << 23
            | ((closed_loop3.integration_cycle_high_threshold as u32) & 0x3) << 21
            | ((closed_loop3.integration_duty_cycle_low_threshold as u32) & 0x3) << 19
            | ((closed_loop3.integration_duty_cycle_high_threshold as u32) & 0x3) << 17
            | ((closed_loop3.bemf_threshold2 as u32) & 0x3F) << 11
            | ((closed_loop3.bemf_threshold1 as u32) & 0x3F) << 5
            | ((closed_loop3.commutation_method as u32) & 0x1) << 4
            | ((closed_loop3.degauss_window as u32) & 0x7) << 1
            | u32::from(closed_loop3.degauss_enable);

        self.assert_register(0x8A, Mct8316AVData::Four(expected_value))
    }

    #[allow(clippy::identity_op)]
    pub fn set_closed_loop4(self, closed_loop4: ClosedLoop4) -> Result<Self> {
        trace!("Mct8316AVEeprom::set_closed_loop4(self: {self:?}, closed_loop4: {closed_loop4:?})");

        let expected_value = if closed_loop4.wcomp_blanking_enable {
            1u32 << 19
        } else {
            0u32
        } | ((closed_loop4.fast_deceleration_duty_window as u32) & 0x7) << 16
            | ((closed_loop4.fast_deceleration_duty_threshold as u32) & 0x7) << 13
            | ((closed_loop4.dynamic_brake_current_lower_threshold as u32) & 0x7) << 9
            | if closed_loop4.dynamic_braking_current_enable {
                1u32 << 8
            } else {
                0u32
            }
            | if closed_loop4.fast_deceleration_enable {
                1u32 << 7
            } else {
                0u32
            }
            | ((closed_loop4.fast_deceleration_current_threshold as u32) & 0xF) << 3
            | ((closed_loop4.fast_brake_delta as u32) & 0x7) << 0;

        self.assert_register(0x8C, Mct8316AVData::Four(expected_value))
    }

    // The casts in here are save due to clamps
    #[allow(clippy::cast_possible_truncation)]
    #[allow(clippy::cast_sign_loss)]
    // These names come from the ICD
    #[allow(clippy::similar_names)]
    pub fn set_constant_speed(self, constant_speed: ConstantSpeed) -> Result<Self> {
        trace!(
            "Mct8316AVEeprom::set_constant_speed(self: {self:?}, constant_speed: {constant_speed:?})"
        );

        let speed_power_kp = (constant_speed.speed_power_kp * 10000f64)
            .round()
            .clamp(0.0f64, f64::from(0x3FF)) as u32;
        let speed_power_ki = (constant_speed.speed_power_ki * 1_000_000_f64)
            .round()
            .clamp(0.0f64, f64::from(0xFFF)) as u32;

        let expected_value = speed_power_kp << 20
            | speed_power_ki << 8
            | ((constant_speed.speed_power_upper_limit as u32) & 0x7) << 5
            | ((constant_speed.speed_power_lower_limit as u32) & 0x7) << 2
            | ((constant_speed.mode as u32) & 0x3) << 9;

        self.assert_register(0x8E, Mct8316AVData::Four(expected_value))
    }

    // The casts in here are save due to clamps
    #[allow(clippy::cast_possible_truncation)]
    #[allow(clippy::cast_sign_loss)]
    // To follow a pattern for the ICD
    #[allow(clippy::identity_op)]
    pub fn set_constant_power(self, constant_power: ConstantPower) -> Result<Self> {
        trace!(
            "Mct8316AVEeprom::set_constant_power(self: {self:?}, constant_power: {constant_power:?})"
        );

        let max_speed = (constant_power.max_speed * 16f64)
            .round()
            .clamp(0.0f64, f64::from(0xFFFF)) as u32;
        let max_power = (constant_power.max_power * 4f64)
            .round()
            .clamp(0.0f64, f64::from(0x3FF)) as u32;

        let expected_value = max_speed << 15
            | if constant_power.dead_time_compensation_enable {
                1u32 << 14
            } else {
                0u32
            }
            | max_power << 4
            | ((constant_power.power_hysteresis as u32) & 0x3) << 2
            | ((constant_power.mode as u32) & 0x3) << 0;

        self.assert_register(0x90, Mct8316AVData::Four(expected_value))
    }

    pub fn set_two_phase_profile(self, profile: TwoPhase150DegreeProfile) -> Result<Self> {
        trace!("Mct8316AVEeprom::set_two_phase_profile(self: {self:?}, profile: {profile:?})");

        let expected_value = ((profile.steps[0] as u32) & 0x7) << 28
            | ((profile.steps[1] as u32) & 0x7) << 25
            | ((profile.steps[2] as u32) & 0x7) << 22
            | ((profile.steps[3] as u32) & 0x7) << 19
            | ((profile.steps[4] as u32) & 0x7) << 16
            | ((profile.steps[5] as u32) & 0x7) << 13
            | ((profile.steps[6] as u32) & 0x7) << 10
            | ((profile.steps[7] as u32) & 0x7) << 7;

        self.assert_register(0x96, Mct8316AVData::Four(expected_value))
    }

    pub fn set_three_phase_profile(self, profile: ThreePhase150DegreeProfile) -> Result<Self> {
        trace!("Mct8316AVEeprom::set_three_phase_profile(self: {self:?}, profile: {profile:?})");

        let expected_value = ((profile.steps[0] as u32) & 0x7) << 28
            | ((profile.steps[1] as u32) & 0x7) << 25
            | ((profile.steps[2] as u32) & 0x7) << 22
            | ((profile.steps[3] as u32) & 0x7) << 19
            | ((profile.steps[4] as u32) & 0x7) << 16
            | ((profile.steps[5] as u32) & 0x7) << 13
            | ((profile.steps[6] as u32) & 0x7) << 10
            | ((profile.steps[7] as u32) & 0x7) << 7
            | ((profile.lead_angle as u32) & 0x3) << 5;

        self.assert_register(0x98, Mct8316AVData::Four(expected_value))
    }

    #[allow(clippy::identity_op)]
    pub fn set_trap_config1(self, trap_config1: TrapConfig1) -> Result<Self> {
        trace!("Mct8316AVEeprom::set_trap_config1(self: {self:?}, trap_config1: {trap_config1:?})");

        let expected_value = ((trap_config1.open_loop_handoff_cycles as u32) & 0x3) << 22
            | ((trap_config1.avs_negative_current_limit as u32) & 0x7) << 16
            | ((trap_config1.avs_limit_hysteresis as u32) & 0x1) << 15
            | ((trap_config1.isd_bemf_threshold as u32) & 0x1F) << 10
            | ((trap_config1.isd_cycle_threshold as u32) & 0x7) << 7
            | ((trap_config1.open_loop_zc_detection_threshold as u32) & 0x7) << 2
            | ((trap_config1.fast_startup_div_factor as u32) & 0x3) << 0;

        self.assert_register(0x9A, Mct8316AVData::Four(expected_value))
    }

    pub fn set_trap_config2(self, trap_config2: TrapConfig2) -> Result<Self> {
        trace!("Mct8316AVEeprom::set_trap_config2(self: {self:?}, trap_config2: {trap_config2:?})");

        let expected_value = (u32::from(trap_config2.blanking_time_microseconds) & 0xF) << 27
            | (u32::from(trap_config2.comparator_deglitch_time_microseconds) & 0x7) << 24
            | ((trap_config2.align_duty_cycle as u32) & 0x7) << 18;

        self.assert_register(0x9C, Mct8316AVData::Four(expected_value))
    }

    #[allow(clippy::identity_op)]
    pub fn set_fault_config1(self, fault_config1: FaultConfig1) -> Result<Self> {
        trace!(
            "Mct8316AVEeprom::set_fault_config1(self: {self:?}, fault_config1: {fault_config1:?})"
        );

        let expected_value = ((fault_config1.no_motor_detect_deglitch_time as u32) & 0x7) << 27
            | ((fault_config1.cycle_by_cycle_current_limit as u32) & 0xF) << 23
            | ((fault_config1.lock_detection_current_limit as u32) & 0xF) << 19
            | ((fault_config1.lock_detection_current_limit_mode as u32) & 0xF) << 15
            | ((fault_config1.lock_detection_current_limit_deglitch_time as u32) & 0xF) << 11
            | (u32::from(fault_config1.cycle_by_cycle_pwm_limit) & 0x7) << 8
            | ((fault_config1.motor_lock_mode as u32) & 0xF) << 3
            | ((fault_config1.lock_retry_time as u32) & 0x7) << 0;

        self.assert_register(0x92, Mct8316AVData::Four(expected_value))
    }

    #[allow(clippy::identity_op)]
    pub fn set_fault_config2(self, fault_config2: FaultConfig2) -> Result<Self> {
        trace!(
            "Mct8316AVEeprom::set_fault_config2(self: {self:?}, fault_config2: {fault_config2:?})"
        );

        let expected_value = if fault_config2.lock_abnormal_speed_enable {
            1u32 << 30
        } else {
            0u32
        } | if fault_config2.lock_loss_of_sync_enable {
            1u32 << 29
        } else {
            0u32
        } | if fault_config2.lock_no_motor_enable {
            1u32 << 28
        } else {
            0u32
        } | ((fault_config2.abnormal_speed_lock_threshold as u32) & 0xF) << 24
            | ((fault_config2.loss_sync_times as u32) & 0x7) << 21
            | ((fault_config2.no_motor_threshold as u32) & 0x7) << 18
            | ((fault_config2.max_motor_voltage_mode as u32) & 0x1) << 17
            | ((fault_config2.max_motor_voltage as u32) & 0x7) << 14
            | ((fault_config2.min_motor_voltage_mode as u32) & 0x1) << 13
            | ((fault_config2.min_motor_voltage as u32) & 0x7) << 10
            | ((fault_config2.automatic_retries as u32) & 0x7) << 7
            | ((fault_config2.lock_min_speed as u32) & 0x7) << 4
            | ((fault_config2.abnormal_speed_lock as u32) & 0x3) << 2
            | ((fault_config2.zero_duty_threshold as u32) & 0x3) << 0;

        self.assert_register(0x94, Mct8316AVData::Four(expected_value))
    }

    pub fn set_pin_config1(self, pin_config1: PinConfig1) -> Result<Self> {
        trace!("Mct8316AVEeprom::set_pin_config1(self: {self:?}, pin_config1: {pin_config1:?})");

        let expected_value = (u32::from(pin_config1.dacout1_address) & 0xFFF) << 19
            | (u32::from(pin_config1.dacout2_address) & 0xFFF) << 7
            | ((pin_config1.brake_input_config as u32) & 0x3) << 5
            | ((pin_config1.direction_input_config as u32) & 0x3) << 3
            | ((pin_config1.speed_input_config as u32) & 0x3) << 1;

        self.assert_register(0xA4, Mct8316AVData::Four(expected_value))
    }

    pub fn set_pin_config2(self, pin_config2: PinConfig2) -> Result<Self> {
        trace!("Mct8316AVEeprom::set_pin_config2(self: {self:?}, pin_config2: {pin_config2:?})");

        let expected_value = ((pin_config2.pin36config as u32) & 0x3) << 29
            | ((pin_config2.pin37_38config as u32) & 0x1) << 27
            | ((pin_config2.sleep_time as u32) & 0x3) << 18
            | if pin_config2.enable_external_watchdog {
                1u32 << 17
            } else {
                0u32
            }
            | ((pin_config2.external_watchdog_source as u32) & 0x1) << 16
            | ((pin_config2.external_watchdog_fault_mode as u32) & 0x1) << 15
            | ((pin_config2.external_watchdog_frequency as u32) & 0x3) << 13;

        self.assert_register(0xA6, Mct8316AVData::Four(expected_value))
    }

    pub fn set_device_config(self, device_config: DeviceConfig) -> Result<Self> {
        trace!(
            "Mct8316AVEeprom::set_device_config(self: {self:?}, device_config: {device_config:?})"
        );

        let expected_value = (u32::from(device_config.max_frequency) & 0x7FFF) << 16
            | if device_config.stl_enable {
                1u32 << 15
            } else {
                0u32
            }
            | if device_config.ssm_enable {
                1u32 << 14
            } else {
                0u32
            }
            | ((device_config.device_mode as u32) & 0x1) << 11
            | ((device_config.pwm_range_select as u32) & 0x1) << 10
            | ((device_config.clock_source as u32) & 0x3) << 8
            | if device_config.external_clock_enable {
                1u32 << 6
            } else {
                0u32
            }
            | ((device_config.external_clock_frequency as u32) & 0x7) << 3;

        self.assert_register(0xA8, Mct8316AVData::Four(expected_value))
    }

    #[allow(clippy::identity_op)]
    pub fn set_gate_driver_config1(self, gate_driver_config1: GateDriverConfig1) -> Result<Self> {
        trace!(
            "Mct8316AVEeprom::set_gate_driver_config1(self: {self:?}, gate_driver_config1: {gate_driver_config1:?})"
        );

        let expected_value = ((gate_driver_config1.slew_rate as u32) & 0x3) << 26
            | ((gate_driver_config1.overvoltage_protection_level as u32) & 0x1) << 19
            | if gate_driver_config1.overvoltage_protection_enable {
                1u32 << 18
            } else {
                0u32
            }
            | if gate_driver_config1.overtemperature_warning_enable {
                1u32 << 16
            } else {
                0u32
            }
            | ((gate_driver_config1.overcurrent_protection_deglitch_time as u32) & 0x3) << 12
            | ((gate_driver_config1.overcurrent_protection_retry_time as u32) & 0x1) << 11
            | ((gate_driver_config1.overcurrent_protection_level as u32) & 0x1) << 10
            | ((gate_driver_config1.overcurrent_fault_mode as u32) & 0x3) << 8
            | ((gate_driver_config1.low_demag_comparator_threshold as u32) & 0x1) << 5
            | ((gate_driver_config1.high_demag_comparator_threshold as u32) & 0x1) << 4
            | if gate_driver_config1.synchronous_rectification_enable {
                1u32 << 3
            } else {
                0u32
            }
            | if gate_driver_config1.asynchronous_rectification_enable {
                1u32 << 2
            } else {
                0u32
            }
            | ((gate_driver_config1.current_sense_amplifier as u32) & 0x3) << 0;

        self.assert_register(0xAC, Mct8316AVData::Four(expected_value))
    }

    pub fn set_gate_driver_config2(self, gate_driver_config2: GateDriverConfig2) -> Result<Self> {
        trace!(
            "Mct8316AVEeprom::set_gate_driver_config2(self: {self:?}, gate_driver_config2: {gate_driver_config2:?})"
        );

        let expected_value = if gate_driver_config2.driver_delay_compensation_enable {
            1u32 << 30
        } else {
            0u32
        } | ((gate_driver_config2.target_delay as u32) & 0xF) << 26
            | ((gate_driver_config2.buck_slew_rate as u32) & 0x1) << 25
            | if gate_driver_config2.buck_power_sequencing_disable {
                1u32 << 24
            } else {
                0u32
            }
            | ((gate_driver_config2.buck_current_limit as u32) & 0x1) << 23
            | ((gate_driver_config2.buck_voltage_selection as u32) & 0x3) << 21
            | if gate_driver_config2.buck_disable {
                1u32 << 20
            } else {
                0u32
            };

        self.assert_register(0xAE, Mct8316AVData::Four(expected_value))
    }

    fn assert_register(self, address: u32, value: Mct8316AVData) -> Result<Self> {
        trace!(
            "Mct8316AVEeprom::assert_register(self: {self:?}, address: {address:06x}, value: {value})"
        );

        let mut read_value = value;

        self.driver.read(address, &mut read_value)?;

        if let Mct8316AVData::Four(value) = &mut read_value {
            *value &= !0x8000_0000u32;
        }

        if read_value == value {
            Ok(self)
        } else {
            self.driver.write(address, value)?;

            Ok(Self {
                modified: true,
                ..self
            })
        }
    }

    pub fn commit(self) -> Result<()> {
        trace!("Mct8316AVEeprom::commit(self: {self:?})");
        if self.modified {
            self.driver
                .write(0x00_00E6, Mct8316AVData::Four(0x8000_0000))?;
            // Wait for EEPROM operation to complete
            sleep(Duration::from_millis(100));
        }
        Ok(())
    }
}
