use core::marker::PhantomData;
pub struct Cmd<R: Resp> {
pub cmd: u8,
pub arg: u32,
resp: PhantomData<R>,
}
impl<R: Resp> Cmd<R> {
pub fn response_len(&self) -> ResponseLen {
R::LENGTH
}
}
pub struct Rz;
pub struct R1;
pub struct R2;
pub struct R3;
pub trait Resp {
const LENGTH: ResponseLen = ResponseLen::R48;
}
impl Resp for Rz {
const LENGTH: ResponseLen = ResponseLen::Zero;
}
impl Resp for R2 {
const LENGTH: ResponseLen = ResponseLen::R136;
}
impl Resp for R1 {}
impl Resp for R3 {}
#[derive(Eq, PartialEq, Copy, Clone)]
pub enum ResponseLen {
Zero,
R48,
R136,
}
pub fn cmd<R: Resp>(cmd: u8, arg: u32) -> Cmd<R> {
Cmd {
cmd,
arg,
resp: PhantomData,
}
}
pub fn idle() -> Cmd<Rz> {
cmd(0, 0)
}
pub fn all_send_cid() -> Cmd<R2> {
cmd(2, 0)
}
pub fn select_card(rca: u16) -> Cmd<R1> {
cmd(7, u32::from(rca) << 16)
}
pub fn send_csd(rca: u16) -> Cmd<R2> {
cmd(9, u32::from(rca) << 16)
}
pub fn send_cid(rca: u16) -> Cmd<R2> {
cmd(10, u32::from(rca) << 16)
}
pub fn stop_transmission() -> Cmd<R1> {
cmd(12, 0)
}
pub fn card_status(rca: u16, task_status: bool) -> Cmd<R1> {
let arg = u32::from(rca) << 16 | u32::from(task_status) << 15;
cmd(13, arg)
}
pub fn go_inactive_state(rca: u16) -> Cmd<Rz> {
cmd(15, u32::from(rca) << 16)
}
pub fn set_block_length(blocklen: u32) -> Cmd<R1> {
cmd(16, blocklen)
}
pub fn read_single_block(addr: u32) -> Cmd<R1> {
cmd(17, addr)
}
pub fn read_multiple_blocks(addr: u32) -> Cmd<R1> {
cmd(18, addr)
}
pub fn write_single_block(addr: u32) -> Cmd<R1> {
cmd(24, addr)
}
pub fn write_multiple_blocks(addr: u32) -> Cmd<R1> {
cmd(25, addr)
}
pub fn program_csd() -> Cmd<R1> {
cmd(27, 0)
}
pub fn erase() -> Cmd<R1> {
cmd(38, 0)
}
pub fn app_cmd(rca: u16) -> Cmd<R1> {
cmd(55, u32::from(rca) << 16)
}