sdmmc-core 0.5.0

SD/MMC core data structures and algorithms
Documentation
use crate::result::{Error, Result};
use crate::{lib_bitfield, response};

lib_bitfield! {
    /// Response sent by every command except `SEND_STATUS` in SPI mode.
    pub R1(u8): u8 {
        raw_msb: 7;
        /// Invalid command argument.
        pub parameter_error: 6;
        /// A misaligned address that does not match block length detected.
        pub address_error: 5;
        /// An erase sequence error occurred.
        pub erase_error: 4;
        /// A communication CRC check failed.
        pub crc_error: 3;
        /// An illegal command code detected.
        pub illegal_command: 2;
        /// An erase sequence was cleared by a command received out of erase sequence.
        pub erase_reset: 1;
        /// Card is in idle state and running intializing process.
        pub idle: 0;
    }
}

response! {
    R1 {
        response_mode: Spi,
    }
}

impl R1 {
    /// Represents the default value of the [R1].
    pub const DEFAULT: u8 = 0;

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

    /// Gets the most-significant bit (MSB) of [R1].
    pub const fn msb(&self) -> bool {
        self.raw_msb()
    }

    /// Attempts to convert a [`u8`] into a [R1].
    pub const fn try_from_bits(val: u8) -> Result<Self> {
        match Self(val) {
            r if r.msb() => Err(Error::invalid_field_variant("r1", val as usize)),
            r => Ok(r),
        }
    }
}

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

impl TryFrom<u8> for R1 {
    type Error = Error;

    fn try_from(val: u8) -> Result<Self> {
        Self::try_from_bits(val)
    }
}

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

    #[test]
    fn test_fields() {
        let mut r1 = R1::new();

        test_field!(r1, idle: 0);
        test_field!(r1, erase_reset: 1);
        test_field!(r1, illegal_command: 2);
        test_field!(r1, crc_error: 3);
        test_field!(r1, erase_error: 4);
        test_field!(r1, address_error: 5);
        test_field!(r1, parameter_error: 6);

        assert!(!r1.msb());

        (0..=u8::MAX).for_each(|v| match v {
            v if R1(v).msb() => assert_eq!(
                R1::try_from(v),
                Err(Error::invalid_field_variant("r1", v as usize))
            ),
            _ => assert_eq!(R1::try_from(v), Ok(R1(v))),
        });
    }
}