sdmmc-core 0.5.0

SD/MMC core data structures and algorithms
Documentation
use crate::result::Result;

use super::{ExtCsd, ExtCsdIndex};

/// Represents the `INI_TIMEOUT_EMU` field of the [ExtCsd] register.
///
/// Indicates the maximum timeout (in milliseconds) during first power up after disabling 512B emulation mode.
#[repr(C)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct InitializationTimeoutEmulation(u8);

impl InitializationTimeoutEmulation {
    /// Represents the default byte value of the [InitializationTimeoutEmulation].
    pub const DEFAULT: u8 = 0;
    /// Represents the timeout multiplier (in milliseconds).
    pub const MULTIPLIER: u8 = 100;

    /// Creates a new [InitializationTimeoutEmulation].
    pub const fn new() -> Self {
        Self(Self::DEFAULT)
    }

    /// Gets the total calculated timeout (in milliseconds).
    ///
    /// # Note
    ///
    /// The timeout is calculated as: `INI_TIMEOUT_EMU * 100ms`.
    #[inline]
    pub const fn timeout(&self) -> u16 {
        (self.0 as u16) * (Self::MULTIPLIER as u16)
    }

    /// Converts an inner representation into a [InitializationTimeoutEmulation].
    pub const fn from_inner(val: u8) -> Self {
        Self(val)
    }

    /// Converts the [InitializationTimeoutEmulation] into an inner representation.
    pub const fn into_inner(self) -> u8 {
        self.0
    }
}

impl Default for InitializationTimeoutEmulation {
    fn default() -> Self {
        Self::new()
    }
}

impl ExtCsd {
    /// Gets the `INI_TIMEOUT_EMU` field of the [ExtCsd] register.
    pub const fn ini_timeout_emu(&self) -> InitializationTimeoutEmulation {
        InitializationTimeoutEmulation::from_inner(self.0[ExtCsdIndex::IniTimeoutEmu.into_inner()])
    }

    /// Sets the `INI_TIMEOUT_EMU` field of the [ExtCsd] register.
    pub fn set_ini_timeout_emu(&mut self, val: InitializationTimeoutEmulation) {
        self.0[ExtCsdIndex::IniTimeoutEmu.into_inner()] = val.into_inner();
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_ini_timeout_emu() {
        let mut ext_csd = ExtCsd::new();

        assert_eq!(
            ext_csd.ini_timeout_emu(),
            InitializationTimeoutEmulation::new()
        );

        (0..=u8::MAX)
            .map(InitializationTimeoutEmulation::from_inner)
            .for_each(|timeout| {
                ext_csd.set_ini_timeout_emu(timeout);
                assert_eq!(ext_csd.ini_timeout_emu(), timeout);
            });
    }
}