1use crate::gpio::*;
2use crate::rcc::*;
3use crate::stm32::{SPI1, SPI2};
4use crate::time::Hertz;
5use core::ptr;
6pub use hal::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3};
7
8#[derive(Debug)]
10pub enum Error {
11    Overrun,
13    ModeFault,
15    Crc,
17}
18
19pub struct NoSck;
21pub struct NoMiso;
23pub struct NoMosi;
25
26pub trait Pins<SPI> {
27    fn setup(&self);
28    fn release(self) -> Self;
29}
30
31pub trait PinSck<SPI> {
32    fn setup(&self);
33    fn release(self) -> Self;
34}
35
36pub trait PinMiso<SPI> {
37    fn setup(&self);
38    fn release(self) -> Self;
39}
40
41pub trait PinMosi<SPI> {
42    fn setup(&self);
43    fn release(self) -> Self;
44}
45
46impl<SPI, SCK, MISO, MOSI> Pins<SPI> for (SCK, MISO, MOSI)
47where
48    SCK: PinSck<SPI>,
49    MISO: PinMiso<SPI>,
50    MOSI: PinMosi<SPI>,
51{
52    fn setup(&self) {
53        self.0.setup();
54        self.1.setup();
55        self.2.setup();
56    }
57
58    fn release(self) -> Self {
59        (self.0.release(), self.1.release(), self.2.release())
60    }
61}
62
63#[derive(Debug)]
64pub struct Spi<SPI, PINS> {
65    spi: SPI,
66    pins: PINS,
67}
68
69pub trait SpiExt: Sized {
70    fn spi<PINS>(self, pins: PINS, mode: Mode, freq: Hertz, rcc: &mut Rcc) -> Spi<Self, PINS>
71    where
72        PINS: Pins<Self>;
73}
74
75macro_rules! spi {
76    ($SPIX:ident, $spiX:ident,
77        sck: [ $(($SCK:ty, $SCK_AF:expr),)+ ],
78        miso: [ $(($MISO:ty, $MISO_AF:expr),)+ ],
79        mosi: [ $(($MOSI:ty, $MOSI_AF:expr),)+ ],
80    ) => {
81        impl PinSck<$SPIX> for NoSck {
82            fn setup(&self) {}
83
84            fn release(self) -> Self {
85                self
86            }
87        }
88
89        impl PinMiso<$SPIX> for NoMiso {
90            fn setup(&self) {}
91
92            fn release(self) -> Self {
93                self
94            }
95        }
96
97        impl PinMosi<$SPIX> for NoMosi {
98            fn setup(&self) {}
99
100            fn release(self) -> Self {
101                self
102            }
103        }
104
105        $(
106            impl PinSck<$SPIX> for $SCK {
107                fn setup(&self) {
108                    self.set_alt_mode($SCK_AF);
109                }
110
111                fn release(self) -> Self {
112                    self.into_analog()
113                }
114            }
115        )*
116        $(
117            impl PinMiso<$SPIX> for $MISO {
118                fn setup(&self) {
119                    self.set_alt_mode($MISO_AF);
120                }
121
122                fn release(self) -> Self {
123                    self.into_analog()
124                }
125            }
126        )*
127        $(
128            impl PinMosi<$SPIX> for $MOSI {
129                fn setup(&self) {
130                    self.set_alt_mode($MOSI_AF);
131                }
132
133                fn release(self) -> Self {
134                    self.into_analog()
135                }
136            }
137        )*
138
139        impl<PINS: Pins<$SPIX>> Spi<$SPIX, PINS> {
140            pub fn $spiX(
141                spi: $SPIX,
142                pins: PINS,
143                mode: Mode,
144                speed: Hertz,
145                rcc: &mut Rcc
146            ) -> Self {
147                $SPIX::enable(rcc);
148                $SPIX::reset(rcc);
149
150                spi.cr2.write(|w| w.ssoe().clear_bit());
152
153                let br = match rcc.clocks.apb_clk / speed {
154                    0 => unreachable!(),
155                    1..=2 => 0b000,
156                    3..=5 => 0b001,
157                    6..=11 => 0b010,
158                    12..=23 => 0b011,
159                    24..=47 => 0b100,
160                    48..=95 => 0b101,
161                    96..=191 => 0b110,
162                    _ => 0b111,
163                };
164
165                spi.cr2.write(|w| unsafe {
166                    w.frxth().set_bit().ds().bits(0b111).ssoe().clear_bit()
167                });
168
169                pins.setup();
171
172                spi.cr1.write(|w| unsafe {
173                    w.cpha()
174                        .bit(mode.phase == Phase::CaptureOnSecondTransition)
175                        .cpol()
176                        .bit(mode.polarity == Polarity::IdleHigh)
177                        .mstr()
178                        .set_bit()
179                        .br()
180                        .bits(br)
181                        .lsbfirst()
182                        .clear_bit()
183                        .ssm()
184                        .set_bit()
185                        .ssi()
186                        .set_bit()
187                        .rxonly()
188                        .clear_bit()
189                        .dff()
190                        .clear_bit()
191                        .bidimode()
192                        .clear_bit()
193                        .ssi()
194                        .set_bit()
195                        .spe()
196                        .set_bit()
197                });
198
199                Spi { spi, pins }
200            }
201
202            pub fn data_size(&mut self, nr_bits: u8) {
203                self.spi.cr2.modify(|_, w| unsafe {
204                    w.ds().bits(nr_bits-1)
205                });
206            }
207
208            pub fn half_duplex_enable(&mut self, enable: bool) {
209                self.spi.cr1.modify(|_, w|
210                    w.bidimode().bit(enable)
211                );
212            }
213
214            pub fn half_duplex_output_enable(&mut self, enable: bool) {
215                self.spi.cr1.modify(|_, w|
216                    w.bidioe().bit(enable)
217                );
218            }
219
220            pub fn release(self) -> ($SPIX, PINS) {
221                (self.spi, self.pins.release())
222            }
223        }
224
225        impl SpiExt for $SPIX {
226            fn spi<PINS>(self, pins: PINS, mode: Mode, freq: Hertz, rcc: &mut Rcc) -> Spi<$SPIX, PINS>
227            where
228                PINS: Pins<$SPIX>,
229            {
230                Spi::$spiX(self, pins, mode, freq, rcc)
231            }
232        }
233
234        impl<PINS> hal::spi::FullDuplex<u8> for Spi<$SPIX, PINS> {
235            type Error = Error;
236
237            fn read(&mut self) -> nb::Result<u8, Error> {
238                let sr = self.spi.sr.read();
239
240                Err(if sr.ovr().bit_is_set() {
241                    nb::Error::Other(Error::Overrun)
242                } else if sr.modf().bit_is_set() {
243                    nb::Error::Other(Error::ModeFault)
244                } else if sr.crcerr().bit_is_set() {
245                    nb::Error::Other(Error::Crc)
246                } else if sr.rxne().bit_is_set() {
247                    return Ok(unsafe {
250                        ptr::read_volatile(&self.spi.dr as *const _ as *const u8)
251                    });
252                } else {
253                    nb::Error::WouldBlock
254                })
255            }
256
257            fn send(&mut self, byte: u8) -> nb::Result<(), Error> {
258                let sr = self.spi.sr.read();
259
260                Err(if sr.ovr().bit_is_set() {
261                    nb::Error::Other(Error::Overrun)
262                } else if sr.modf().bit_is_set() {
263                    nb::Error::Other(Error::ModeFault)
264                } else if sr.crcerr().bit_is_set() {
265                    nb::Error::Other(Error::Crc)
266                } else if sr.txe().bit_is_set() {
267                    unsafe { ptr::write_volatile(&self.spi.dr as *const _ as *mut u8, byte) }
269                    return Ok(());
270                } else {
271                    nb::Error::WouldBlock
272                })
273            }
274        }
275
276        impl<PINS> ::hal::blocking::spi::transfer::Default<u8> for Spi<$SPIX, PINS> {}
277
278        impl<PINS> ::hal::blocking::spi::write::Default<u8> for Spi<$SPIX, PINS> {}
279    }
280}
281
282spi!(
283    SPI1,
284    spi1,
285    sck: [
286        (PA1<DefaultMode>, AltFunction::AF0),
287        (PA5<DefaultMode>, AltFunction::AF0),
288        (PB3<DefaultMode>, AltFunction::AF0),
289        (PD8<DefaultMode>, AltFunction::AF1),
290    ],
291    miso: [
292        (PA6<DefaultMode>, AltFunction::AF0),
293        (PA11<DefaultMode>, AltFunction::AF0),
294        (PB4<DefaultMode>, AltFunction::AF0),
295        (PD5<DefaultMode>, AltFunction::AF1),
296    ],
297    mosi: [
298        (PA2<DefaultMode>, AltFunction::AF0),
299        (PA7<DefaultMode>, AltFunction::AF0),
300        (PA12<DefaultMode>, AltFunction::AF0),
301        (PB5<DefaultMode>, AltFunction::AF0),
302        (PD6<DefaultMode>, AltFunction::AF1),
303    ],
304);
305
306spi!(
307    SPI2,
308    spi2,
309    sck: [
310        (PA0<DefaultMode>, AltFunction::AF0),
311        (PB8<DefaultMode>, AltFunction::AF1),
312        (PB10<DefaultMode>, AltFunction::AF5),
313        (PB13<DefaultMode>, AltFunction::AF0),
314        (PD1<DefaultMode>, AltFunction::AF1),
315    ],
316    miso: [
317        (PA3<DefaultMode>, AltFunction::AF0),
318        (PA9<DefaultMode>, AltFunction::AF4),
319        (PB2<DefaultMode>, AltFunction::AF1),
320        (PB6<DefaultMode>, AltFunction::AF4),
321        (PB14<DefaultMode>, AltFunction::AF0),
322        (PC2<DefaultMode>, AltFunction::AF1),
323        (PD3<DefaultMode>, AltFunction::AF1),
324    ],
325    mosi: [
326        (PA4<DefaultMode>, AltFunction::AF1),
327        (PA10<DefaultMode>, AltFunction::AF0),
328        (PB7<DefaultMode>, AltFunction::AF1),
329        (PB11<DefaultMode>, AltFunction::AF0),
330        (PB15<DefaultMode>, AltFunction::AF0),
331        (PC3<DefaultMode>, AltFunction::AF1),
332        (PD4<DefaultMode>, AltFunction::AF1),
333    ],
334);