sdmmc-core 0.5.0

SD/MMC core data structures and algorithms
Documentation
//! R2 response for SD mode.

use crate::register::{Cid, Csd};
use crate::response::Start;
use crate::result::{Error, Result};
use crate::{lib_bitfield, response};

mod register;

pub use register::Register;

lib_bitfield! {
    /// Represents the `R2` response in SD mode.
    ///
    /// Contains the `CID` or `CSD` register, including internal CRC7.
    pub R2(MSB0 [u8; 17]): u128 {
        raw_start: 135, 128;
        raw_register: 127, 0;
    }
}

response! {
    R2 {
        response_mode: Sd,
    }
}

impl R2 {
    /// Represents the byte length of the [R2] response in SD mode.
    pub const LEN: usize = 17;
    /// Represents the default byte value of the [R2].
    pub const DEFAULT: [u8; Self::LEN] = [0x3f, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0x13];

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

    /// Attempts to get the [Start] field for the [R2].
    pub const fn start(&self) -> Result<Start> {
        Start::try_from_bits(self.raw_start() as u8)
    }

    /// Attempts to get the [Register] field for the [R2].
    pub const fn register(&self) -> Result<Register> {
        Register::try_from_bytes(&self.raw_register().to_be_bytes())
    }

    /// Sets the [Register] field for the [R2].
    pub fn set_register(&mut self, val: Register) {
        self.set_raw_register(u128::from_be_bytes(val.bytes()));
    }

    /// Attempts to convert a byte slice into a [R2].
    pub const fn try_from_bytes(val: &[u8]) -> Result<Self> {
        match val.len() {
            len if len < Self::LEN => Err(Error::invalid_length(len, Self::LEN)),
            _ => {
                let r = Self([
                    val[0], val[1], val[2], val[3], val[4], val[5], val[6], val[7], val[8], val[9],
                    val[10], val[11], val[12], val[13], val[14], val[15], val[16],
                ]);

                match (r.start(), r.register()) {
                    (Ok(_), Ok(_)) => Ok(r),
                    (Err(_err), _) => Err(Error::invalid_field_variant(
                        "r2::start",
                        r.raw_start() as usize,
                    )),
                    (_, Err(err)) => Err(err),
                }
            }
        }
    }
}

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

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

    #[test]
    fn test_valid() {
        let mut r2 = R2::new();
        let start = Start::from_bits(0x3f);
        let register = Register::new();
        let cid = Cid::new();
        let csd = Csd::new();
        let r2_bytes = R2::DEFAULT;
        let raw_crc = r2_bytes[16];

        assert_eq!(
            r2.register().and_then(|r| r.cid().map(|c| c.crc().bits())),
            Ok(raw_crc)
        );
        assert_eq!(R2::try_from_bytes(r2_bytes.as_ref()), Ok(r2));
        assert_eq!(r2.bytes(), r2_bytes);

        assert_eq!(r2.start(), Ok(start));

        assert_eq!(r2.register(), Ok(register));

        assert_eq!(r2.register().unwrap().cid(), Ok(&cid));

        r2.set_register(csd.into());
        assert_eq!(r2.register().unwrap().csd(), Ok(&csd));
    }
}