1use embedded_hal::blocking::spi;
2use embedded_hal::digital::v2 as gpiov2;
3
4pub trait Comms {
5 type Error;
6
7 fn set_cs(&self, active: bool) -> Result<(), Self::Error>;
8 fn set_a(&self, active: bool) -> Result<(), Self::Error>;
9 fn set_b(&self, active: bool) -> Result<(), Self::Error>;
10 fn write(&self, data: &[u8]) -> Result<(), Self::Error>;
11 fn transfer<'w>(&self, data: &'w mut [u8]) -> Result<&'w [u8], Self::Error>;
12}
13
14pub struct Parts<'a, SD: 'a>
22where
23 SD: Comms,
24{
25 pub spi: SPI<'a, SD>,
28
29 pub cs: CS<'a, SD>,
36
37 pub pin_a: PinA<'a, SD>,
40
41 pub pin_b: PinB<'a, SD>,
44}
45
46impl<'a, SD: 'a> Parts<'a, SD>
47where
48 SD: Comms,
49{
50 pub(crate) fn new(sd: &'a SD) -> Self {
51 Self {
52 spi: SPI::new(&sd),
53 cs: CS::new(&sd),
54 pin_a: PinA::new(&sd),
55 pin_b: PinB::new(&sd),
56 }
57 }
58}
59
60pub struct SPI<'a, SD: Comms>(&'a SD);
63
64impl<'a, SD: 'a> SPI<'a, SD>
65where
66 SD: Comms,
67{
68 fn new(sd: &'a SD) -> Self {
69 Self(sd)
70 }
71}
72
73impl<'a, SD: 'a, E> spi::Transfer<u8> for SPI<'a, SD>
74where
75 SD: Comms<Error = E>,
76{
77 type Error = E;
78
79 fn transfer<'w>(&mut self, data: &'w mut [u8]) -> Result<&'w [u8], E> {
86 self.0.transfer(data)
87 }
88}
89
90impl<'a, SD: 'a, E> spi::Write<u8> for SPI<'a, SD>
91where
92 SD: Comms<Error = E>,
93{
94 type Error = E;
95
96 fn write(&mut self, data: &[u8]) -> Result<(), E> {
103 self.0.write(data)
104 }
105}
106
107pub struct CS<'a, SD: Comms>(&'a SD);
110
111impl<'a, SD: 'a> CS<'a, SD>
112where
113 SD: Comms,
114{
115 fn new(sd: &'a SD) -> Self {
116 Self(sd)
117 }
118}
119
120impl<'a, SD: 'a, E> gpiov2::OutputPin for CS<'a, SD>
121where
122 SD: Comms<Error = E>,
123{
124 type Error = E;
125
126 fn set_low(&mut self) -> Result<(), E> {
127 self.0.set_cs(false)
128 }
129
130 fn set_high(&mut self) -> Result<(), E> {
131 self.0.set_cs(true)
132 }
133}
134
135pub struct PinA<'a, SD: Comms>(&'a SD);
138
139impl<'a, SD: 'a> PinA<'a, SD>
140where
141 SD: Comms,
142{
143 fn new(sd: &'a SD) -> Self {
144 Self(sd)
145 }
146}
147
148impl<'a, SD: 'a, E> gpiov2::OutputPin for PinA<'a, SD>
149where
150 SD: Comms<Error = E>,
151{
152 type Error = E;
153
154 fn set_low(&mut self) -> Result<(), E> {
155 self.0.set_a(false)
156 }
157
158 fn set_high(&mut self) -> Result<(), E> {
159 self.0.set_a(true)
160 }
161}
162
163pub struct PinB<'a, SD: Comms>(&'a SD);
166
167impl<'a, SD: 'a> PinB<'a, SD>
168where
169 SD: Comms,
170{
171 fn new(sd: &'a SD) -> Self {
172 Self(sd)
173 }
174}
175
176impl<'a, SD: 'a, E> gpiov2::OutputPin for PinB<'a, SD>
177where
178 SD: Comms<Error = E>,
179{
180 type Error = E;
181
182 fn set_low(&mut self) -> Result<(), E> {
183 self.0.set_b(false)
184 }
185
186 fn set_high(&mut self) -> Result<(), E> {
187 self.0.set_b(true)
188 }
189}