1#![no_std]
4#![forbid(unsafe_code)]
5#![cfg_attr(docsrs, feature(doc_cfg))]
6
7#[cfg(all(feature = "hal-0_2", feature = "hal-1_0"))]
8compile_error!(
9 "HAL feature \"hal-0_2\" and feature \"hal-1_0\" cannot be enabled at the same time"
10);
11
12#[cfg(not(any(feature = "hal-0_2", feature = "hal-1_0")))]
13compile_error!("A HAL feature (\"hal-0_2\" or \"hal-1_0\") must be enabled");
14
15#[cfg(feature = "hal-0_2")]
16#[cfg_attr(docsrs, doc(cfg(feature = "hal-0_2")))]
17use hal_0_2::digital::v2::OutputPin;
18
19#[cfg(feature = "hal-1_0")]
20#[cfg_attr(docsrs, doc(cfg(feature = "hal-1_0")))]
21use hal_1_0::digital::OutputPin;
22
23pub trait ChipSelect {
25 fn select(&mut self);
27
28 fn deselect(&mut self);
30}
31
32pub trait ChipSelectGuarded: ChipSelect {
34 type Guard<'a>
36 where
37 Self: 'a;
38
39 fn select_guard(&mut self) -> Self::Guard<'_>;
41}
42
43pub trait ActiveLow {}
45
46pub trait ActiveHigh {}
48
49pub struct ChipSelectActiveLow<Pin>(Pin);
51
52pub struct ChipSelectActiveHigh<Pin>(Pin);
54
55impl<Pin> ChipSelectActiveLow<Pin>
56where
57 Pin: OutputPin,
58{
59 pub const fn new(pin: Pin) -> Self {
61 Self(pin)
62 }
63
64 pub fn select(&mut self) {
66 <Pin as OutputPin>::set_low(&mut self.0).ok();
67 }
68
69 pub fn deselect(&mut self) {
71 <Pin as OutputPin>::set_high(&mut self.0).ok();
72 }
73
74 #[must_use]
76 pub fn into_inner(self) -> Pin {
77 self.0
78 }
79
80 #[must_use]
82 pub fn select_guard(&mut self) -> DeselectOnDrop<Self> {
83 self.select();
84 DeselectOnDrop::from(self)
85 }
86}
87
88impl<Pin> ChipSelectActiveHigh<Pin>
89where
90 Pin: OutputPin,
91{
92 pub const fn new(pin: Pin) -> Self {
94 Self(pin)
95 }
96
97 pub fn select(&mut self) {
99 <Pin as OutputPin>::set_high(&mut self.0).ok();
100 }
101
102 pub fn deselect(&mut self) {
104 <Pin as OutputPin>::set_low(&mut self.0).ok();
105 }
106
107 #[must_use]
109 pub fn into_inner(self) -> Pin {
110 self.0
111 }
112
113 #[must_use]
115 pub fn select_guard(&mut self) -> DeselectOnDrop<Self> {
116 self.select();
117 DeselectOnDrop::from(self)
118 }
119}
120
121impl<Pin> From<Pin> for ChipSelectActiveLow<Pin>
122where
123 Pin: OutputPin,
124{
125 fn from(value: Pin) -> Self {
126 Self::new(value)
127 }
128}
129
130impl<Pin> From<Pin> for ChipSelectActiveHigh<Pin>
131where
132 Pin: OutputPin,
133{
134 fn from(value: Pin) -> Self {
135 Self::new(value)
136 }
137}
138
139impl<Pin> ActiveLow for ChipSelectActiveLow<Pin> where Pin: OutputPin {}
140
141impl<Pin> ActiveHigh for ChipSelectActiveHigh<Pin> where Pin: OutputPin {}
142
143impl<Pin> ChipSelect for ChipSelectActiveLow<Pin>
144where
145 Pin: OutputPin,
146{
147 fn select(&mut self) {
148 self.select()
149 }
150
151 fn deselect(&mut self) {
152 self.deselect()
153 }
154}
155
156impl<Pin> ChipSelectGuarded for ChipSelectActiveLow<Pin>
157where
158 Pin: OutputPin,
159{
160 type Guard<'a> = DeselectOnDrop<'a, Self> where Pin: 'a;
161
162 fn select_guard(&mut self) -> DeselectOnDrop<Self> {
164 self.select_guard()
165 }
166}
167
168impl<Pin> ChipSelect for ChipSelectActiveHigh<Pin>
169where
170 Pin: OutputPin,
171{
172 fn select(&mut self) {
173 self.select()
174 }
175
176 fn deselect(&mut self) {
177 self.deselect()
178 }
179}
180
181impl<Pin> ChipSelectGuarded for ChipSelectActiveHigh<Pin>
182where
183 Pin: OutputPin,
184{
185 type Guard<'a> = DeselectOnDrop<'a, Self> where Pin: 'a;
186
187 fn select_guard(&mut self) -> Self::Guard<'_> {
189 self.select_guard()
190 }
191}
192
193pub struct DeselectOnDrop<'a, T>(&'a mut T)
195where
196 T: ChipSelect;
197
198impl<'a, T> From<&'a mut T> for DeselectOnDrop<'a, T>
199where
200 T: ChipSelect,
201{
202 fn from(value: &'a mut T) -> Self {
203 Self(value)
204 }
205}
206
207impl<'a, T> Drop for DeselectOnDrop<'a, T>
208where
209 T: ChipSelect,
210{
211 fn drop(&mut self) {
212 self.0.deselect()
213 }
214}