1use core::marker::PhantomData;
10
11pub use crate::traits::wg::spi::{
12 FullDuplex,
13 Mode,
14 Phase,
15 Polarity,
16};
17use crate::typestates::pin::{
18 flexcomm::{
19 Spi,
21 SpiPins,
22 ChipSelect,
23 },
24 PinId,
25};
26use crate::time::{
27 Hertz,
28};
29
30pub mod prelude {
31 pub use super::SpiMaster;
32 pub use super::Error as SpiError;
33 pub use super::Result as SpiResult;
34}
35
36#[derive(Debug)]
39pub enum Error {
40 Overrun,
42 ModeFault,
44 Crc,
46 #[doc(hidden)]
47 _Extensible,
48}
49
50pub type Result<T> = nb::Result<T, Error>;
51
52pub struct SpiMaster<SCK, MOSI, MISO, CS, SPI, PINS>
54where
55 SCK: PinId,
56 MOSI: PinId,
57 MISO: PinId,
58 CS: PinId,
59 SPI: Spi,
60 PINS: SpiPins<SCK, MOSI, MISO, CS, SPI>,
61{
62 spi: SPI,
63 pins: PINS,
64 _sck: PhantomData<SCK>,
65 _mosi: PhantomData<MOSI>,
66 _miso: PhantomData<MISO>,
67 _cs: PhantomData<CS>,
68 cs: ChipSelect,
69}
70
71impl<SCK, MOSI, MISO, CS, SPI, PINS> SpiMaster<SCK, MOSI, MISO, CS, SPI, PINS>
72where
73 SCK: PinId,
74 MOSI: PinId,
75 MISO: PinId,
76 CS: PinId,
77 SPI: Spi,
78 PINS: SpiPins<SCK, MOSI, MISO, CS, SPI>,
79 {
81 pub fn new<Speed: Into<Hertz>>(spi: SPI, pins: PINS, speed: Speed, mode: Mode) -> Self {
82 let speed: Hertz = speed.into();
83 let speed: u32 = speed.0;
84
85 while spi.stat.read().mstidle().bit_is_clear() { continue; }
86
87 spi.fifocfg.modify(|_, w| w
88 .enabletx().disabled()
89 .enablerx().disabled()
90 );
91 spi.cfg.modify(|_, w| w
92 .enable().disabled()
93 .master().master_mode()
94 .lsbf().standard() .cpha().bit(mode.phase == Phase::CaptureOnSecondTransition)
96 .cpol().bit(mode.polarity == Polarity::IdleHigh)
97 .loop_().disabled()
98 );
99
100 let div: u32 = 12_000_000 / speed - 1;
101 assert!(div <= 0xFFFF);
102 spi.div.modify(|_, w| unsafe { w.divval().bits(div as u16) } );
103
104 spi.fifocfg.modify(|_, w| w
112 .enabletx().enabled()
113 .enablerx().enabled()
114 );
115 spi.cfg.modify(|_, w| w
116 .enable().enabled()
117 );
118 Self {
124 spi,
125 pins,
126 _sck: PhantomData,
127 _mosi: PhantomData,
128 _miso: PhantomData,
129 _cs: PhantomData,
130 cs: PINS::CS,
132 }
133 }
134
135 pub fn release(self) -> (SPI, PINS) {
136 (self.spi, self.pins)
137 }
138
139 fn return_on_error(&self) -> Result<()> {
140 Ok(())
142 }
143
144}
145
146impl<SCK, MOSI, MISO, CS, SPI, PINS> FullDuplex<u8> for SpiMaster<SCK, MOSI, MISO, CS, SPI, PINS>
147where
148 SCK: PinId,
149 MOSI: PinId,
150 MISO: PinId,
151 CS: PinId,
152 SPI: Spi,
153 PINS: SpiPins<SCK, MOSI, MISO, CS, SPI>,
154 {
156 type Error = Error;
157
158 fn read(&mut self) -> Result<u8> {
159 if self.spi.fifostat.read().rxnotempty().bit_is_clear() {
161 let byte = self.spi.fiford.read().rxdata().bits();
164 Ok(byte as u8)
165 } else {
166 Err(nb::Error::WouldBlock)
167 }
168 }
169
170 fn send(&mut self, byte: u8) -> Result<()> {
171
172 self.return_on_error()?;
176 if self.spi.fifostat.read().txempty().bit_is_set() {
177 use ChipSelect::*;
180 match self.cs {
181 Chip0 => {
182 self.spi.fifowr.write(|w| unsafe { w
183 .len().bits(7) .txssel0_n().asserted()
186 .txdata().bits(byte as u16)
188 });
189 },
190 Chip1 => {
191 self.spi.fifowr.write(|w| unsafe { w
192 .len().bits(7) .txssel1_n().asserted()
195 .txdata().bits(byte as u16)
197 });
198 },
199 Chip2 => {
200 self.spi.fifowr.write(|w| unsafe { w
201 .len().bits(7) .txssel2_n().asserted()
204 .txdata().bits(byte as u16)
206 });
207 },
208 Chip3 => {
209 self.spi.fifowr.write(|w| unsafe { w
210 .len().bits(7) .txssel3_n().asserted()
213 .txdata().bits(byte as u16)
215 });
216 },
217 AllChips => {
218 self.spi.fifowr.write(|w| unsafe { w
219 .len().bits(7) .txssel0_n().asserted()
222 .txssel1_n().asserted()
223 .txssel2_n().asserted()
224 .txssel3_n().asserted()
225 .txdata().bits(byte as u16)
227 });
228 },
229 }
230 Ok(())
231 } else {
232 Err(nb::Error::WouldBlock)
233 }
234 }
235}
236
237impl<SCK, MOSI, MISO, CS, SPI, PINS> crate::traits::wg::blocking::spi::transfer::Default<u8>
238for
239 SpiMaster<SCK, MOSI, MISO, CS, SPI, PINS>
240where
241 SCK: PinId,
242 MOSI: PinId,
243 MISO: PinId,
244 CS: PinId,
245 SPI: Spi,
246 PINS: SpiPins<SCK, MOSI, MISO, CS, SPI>,
247{}
248
249impl<SCK, MOSI, MISO, CS, SPI, PINS> crate::traits::wg::blocking::spi::write::Default<u8>
250for
251 SpiMaster<SCK, MOSI, MISO, CS, SPI, PINS>
252where
253 SCK: PinId,
254 MOSI: PinId,
255 MISO: PinId,
256 CS: PinId,
257 SPI: Spi,
258 PINS: SpiPins<SCK, MOSI, MISO, CS, SPI>,
259{}
260
261