1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
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)
}