1use core::{convert::Infallible, marker::PhantomData, ops::Deref};
30
31use embedded_hal::spi::{self, Phase, Polarity};
32use embedded_hal_0_2::{blocking::spi as blocking_spi02, spi as spi02};
34use embedded_hal_nb::spi::FullDuplex;
35use fugit::{HertzU32, RateExtU32};
36
37use crate::{
38 dma::{EndlessReadTarget, EndlessWriteTarget, ReadTarget, WriteTarget},
39 pac::{self, dma::ch::ch_ctrl_trig::TREQ_SEL_A, RESETS},
40 resets::SubsystemReset,
41 typelevel::Sealed,
42};
43
44mod pins;
45pub use pins::*;
46
47impl From<spi::Mode> for FrameFormat {
48 fn from(f: spi::Mode) -> Self {
49 Self::MotorolaSpi(f)
50 }
51}
52
53impl From<&spi::Mode> for FrameFormat {
54 fn from(f: &spi::Mode) -> Self {
55 Self::MotorolaSpi(*f)
56 }
57}
58
59#[derive(Clone, Copy, PartialEq, Eq)]
61pub enum FrameFormat {
62 MotorolaSpi(spi::Mode),
64 TexasInstrumentsSynchronousSerial,
66 NationalSemiconductorMicrowire,
68}
69
70impl From<&embedded_hal_0_2::spi::Mode> for FrameFormat {
71 fn from(f: &embedded_hal_0_2::spi::Mode) -> Self {
72 let embedded_hal_0_2::spi::Mode { polarity, phase } = f;
73 match (polarity, phase) {
74 (spi02::Polarity::IdleLow, spi02::Phase::CaptureOnFirstTransition) => {
75 FrameFormat::MotorolaSpi(spi::MODE_0)
76 }
77 (spi02::Polarity::IdleLow, spi02::Phase::CaptureOnSecondTransition) => {
78 FrameFormat::MotorolaSpi(spi::MODE_1)
79 }
80 (spi02::Polarity::IdleHigh, spi02::Phase::CaptureOnFirstTransition) => {
81 FrameFormat::MotorolaSpi(spi::MODE_2)
82 }
83 (spi02::Polarity::IdleHigh, spi02::Phase::CaptureOnSecondTransition) => {
84 FrameFormat::MotorolaSpi(spi::MODE_3)
85 }
86 }
87 }
88}
89
90impl From<embedded_hal_0_2::spi::Mode> for FrameFormat {
91 fn from(f: embedded_hal_0_2::spi::Mode) -> Self {
92 From::from(&f)
93 }
94}
95
96pub trait State: Sealed {}
98
99pub struct Disabled {
101 __private: (),
102}
103
104pub struct Enabled {
106 __private: (),
107}
108
109impl State for Disabled {}
110impl Sealed for Disabled {}
111impl State for Enabled {}
112impl Sealed for Enabled {}
113
114pub trait SpiDevice: Deref<Target = pac::spi0::RegisterBlock> + SubsystemReset + Sealed {
116 const ID: usize;
118
119 fn tx_dreq() -> u8;
121 fn rx_dreq() -> u8;
123}
124
125impl Sealed for pac::SPI0 {}
126impl SpiDevice for pac::SPI0 {
127 const ID: usize = 0;
128 fn tx_dreq() -> u8 {
129 TREQ_SEL_A::SPI0_TX.into()
130 }
131 fn rx_dreq() -> u8 {
132 TREQ_SEL_A::SPI0_RX.into()
133 }
134}
135impl Sealed for pac::SPI1 {}
136impl SpiDevice for pac::SPI1 {
137 const ID: usize = 1;
138 fn tx_dreq() -> u8 {
139 TREQ_SEL_A::SPI1_TX.into()
140 }
141 fn rx_dreq() -> u8 {
142 TREQ_SEL_A::SPI1_RX.into()
143 }
144}
145
146pub trait DataSize: Sealed {}
148
149impl DataSize for u8 {}
150impl DataSize for u16 {}
151impl Sealed for u8 {}
152impl Sealed for u16 {}
153
154pub struct Spi<S: State, D: SpiDevice, P: ValidSpiPinout<D>, const DS: u8 = 8u8> {
180 device: D,
181 pins: P,
182 state: PhantomData<S>,
183}
184
185impl<S: State, D: SpiDevice, P: ValidSpiPinout<D>, const DS: u8> Spi<S, D, P, DS> {
186 fn transition<To: State>(self, _: To) -> Spi<To, D, P, DS> {
187 Spi {
188 device: self.device,
189 pins: self.pins,
190 state: PhantomData,
191 }
192 }
193
194 pub fn free(self) -> (D, P) {
196 (self.device, self.pins)
197 }
198
199 pub fn set_baudrate<F: Into<HertzU32>, B: Into<HertzU32>>(
207 &mut self,
208 peri_frequency: F,
209 baudrate: B,
210 ) -> HertzU32 {
211 let freq_in = peri_frequency.into().to_Hz();
212 let baudrate = baudrate.into().to_Hz();
213 let mut prescale: u8 = u8::MAX;
214 let mut postdiv: u8 = 0;
215
216 for prescale_option in (2u32..=254).step_by(2) {
219 if freq_in < ((prescale_option + 2) * 256).saturating_mul(baudrate) {
223 prescale = prescale_option as u8;
224 break;
225 }
226 }
227
228 debug_assert_ne!(prescale, u8::MAX);
230
231 for postdiv_option in (1..=255u8).rev() {
234 if freq_in / (prescale as u32 * postdiv_option as u32) > baudrate {
235 postdiv = postdiv_option;
236 break;
237 }
238 }
239
240 self.device
241 .sspcpsr()
242 .write(|w| unsafe { w.cpsdvsr().bits(prescale) });
243 self.device
244 .sspcr0()
245 .modify(|_, w| unsafe { w.scr().bits(postdiv) });
246
247 (freq_in / (prescale as u32 * (1 + postdiv as u32))).Hz()
249 }
250
251 pub fn set_format(&mut self, frame_format: FrameFormat) {
253 self.device.sspcr0().modify(|_, w| unsafe {
254 w.dss().bits(DS - 1).frf().bits(match &frame_format {
255 FrameFormat::MotorolaSpi(_) => 0x00,
256 FrameFormat::TexasInstrumentsSynchronousSerial => 0x01,
257 FrameFormat::NationalSemiconductorMicrowire => 0x10,
258 });
259
260 if let FrameFormat::MotorolaSpi(ref mode) = frame_format {
265 w.spo()
266 .bit(mode.polarity == Polarity::IdleHigh)
267 .sph()
268 .bit(mode.phase == Phase::CaptureOnSecondTransition);
269 }
270 w
271 });
272 }
273}
274
275impl<D: SpiDevice, P: ValidSpiPinout<D>, const DS: u8> Spi<Disabled, D, P, DS> {
276 pub fn new(device: D, pins: P) -> Spi<Disabled, D, P, DS> {
284 Spi {
285 device,
286 pins,
287 state: PhantomData,
288 }
289 }
290
291 fn set_slave(&mut self, slave: bool) {
293 if slave {
294 self.device.sspcr1().modify(|_, w| w.ms().set_bit());
295 } else {
296 self.device.sspcr1().modify(|_, w| w.ms().clear_bit());
297 }
298 }
299
300 fn init_spi<F: Into<HertzU32>, B: Into<HertzU32>>(
301 mut self,
302 resets: &mut RESETS,
303 peri_frequency: F,
304 baudrate: B,
305 frame_format: FrameFormat,
306 slave: bool,
307 ) -> Spi<Enabled, D, P, DS> {
308 self.device.reset_bring_down(resets);
309 self.device.reset_bring_up(resets);
310
311 self.set_baudrate(peri_frequency, baudrate);
312 self.set_format(frame_format);
313 self.set_slave(slave);
314 self.device
316 .sspdmacr()
317 .modify(|_, w| w.txdmae().set_bit().rxdmae().set_bit());
318
319 self.device.sspcr1().modify(|_, w| w.sse().set_bit());
321
322 self.transition(Enabled { __private: () })
323 }
324
325 pub fn init<F: Into<HertzU32>, B: Into<HertzU32>, M: Into<FrameFormat>>(
327 self,
328 resets: &mut RESETS,
329 peri_frequency: F,
330 baudrate: B,
331 frame_format: M,
332 ) -> Spi<Enabled, D, P, DS> {
333 self.init_spi(resets, peri_frequency, baudrate, frame_format.into(), false)
334 }
335
336 pub fn init_slave<M: Into<FrameFormat>>(
338 self,
339 resets: &mut RESETS,
340 frame_format: M,
341 ) -> Spi<Enabled, D, P, DS> {
342 self.init_spi(
346 resets,
347 1000u32.Hz(),
348 1000u32.Hz(),
349 frame_format.into(),
350 true,
351 )
352 }
353}
354
355impl<D: SpiDevice, P: ValidSpiPinout<D>, const DS: u8> Spi<Enabled, D, P, DS> {
356 fn is_writable(&self) -> bool {
357 self.device.sspsr().read().tnf().bit_is_set()
358 }
359 fn is_readable(&self) -> bool {
360 self.device.sspsr().read().rne().bit_is_set()
361 }
362
363 pub fn is_busy(&self) -> bool {
365 self.device.sspsr().read().bsy().bit_is_set()
366 }
367
368 pub fn disable(self) -> Spi<Disabled, D, P, DS> {
371 self.device.sspcr1().modify(|_, w| w.sse().clear_bit());
372
373 self.transition(Disabled { __private: () })
374 }
375}
376
377macro_rules! impl_write {
378 ($type:ident, [$($nr:expr),+]) => {
379
380 $(
381 impl<D: SpiDevice, P: ValidSpiPinout<D>> spi02::FullDuplex<$type> for Spi<Enabled, D, P, $nr> {
382 type Error = Infallible;
383
384 fn read(&mut self) -> Result<$type, nb::Error<Infallible>> {
385 if !self.is_readable() {
386 return Err(nb::Error::WouldBlock);
387 }
388
389 Ok(self.device.sspdr().read().data().bits() as $type)
390 }
391 fn send(&mut self, word: $type) -> Result<(), nb::Error<Infallible>> {
392 if !self.is_writable() {
396 return Err(nb::Error::WouldBlock);
397 }
398
399 self.device
400 .sspdr()
401 .write(|w| unsafe { w.data().bits(word as u16) });
402 Ok(())
403 }
404 }
405
406 impl<D: SpiDevice, P: ValidSpiPinout<D>> blocking_spi02::write::Default<$type> for Spi<Enabled, D, P, $nr> {}
407 impl<D: SpiDevice, P: ValidSpiPinout<D>> blocking_spi02::transfer::Default<$type> for Spi<Enabled, D, P, $nr> {}
408 impl<D: SpiDevice, P: ValidSpiPinout<D>> blocking_spi02::write_iter::Default<$type> for Spi<Enabled, D, P, $nr> {}
409
410 impl<D: SpiDevice, P: ValidSpiPinout<D>> spi::ErrorType for Spi<Enabled, D, P, $nr> {
411 type Error = Infallible;
412 }
413
414 impl<D: SpiDevice, P: ValidSpiPinout<D>> spi::SpiBus<$type> for Spi<Enabled, D, P, $nr> {
415 fn read(&mut self, words: &mut [$type]) -> Result<(), Self::Error> {
416 for word in words.iter_mut() {
417 while !self.is_writable() {}
419 self.device
420 .sspdr()
421 .write(|w| unsafe { w.data().bits(0) });
422
423 while !self.is_readable() {}
425 *word = self.device.sspdr().read().data().bits() as $type;
426 }
427 Ok(())
428 }
429
430 fn write(&mut self, words: &[$type]) -> Result<(), Self::Error> {
431 for word in words.iter() {
432 while !self.is_writable() {}
434 self.device
435 .sspdr()
436 .write(|w| unsafe { w.data().bits(*word as u16) });
437
438 while !self.is_readable() {}
440 let _ = self.device.sspdr().read().data().bits();
441 }
442 Ok(())
443 }
444
445 fn transfer(&mut self, read: &mut [$type], write: &[$type]) -> Result<(), Self::Error>{
446 let len = read.len().max(write.len());
447 for i in 0..len {
448 let wb = write.get(i).copied().unwrap_or(0);
450 while !self.is_writable() {}
451 self.device
452 .sspdr()
453 .write(|w| unsafe { w.data().bits(wb as u16) });
454
455 while !self.is_readable() {}
457 let rb = self.device.sspdr().read().data().bits() as $type;
458 if let Some(r) = read.get_mut(i) {
459 *r = rb;
460 }
461 }
462
463 Ok(())
464 }
465
466 fn transfer_in_place(&mut self, words: &mut [$type]) -> Result<(), Self::Error>{
467 for word in words.iter_mut() {
468 while !self.is_writable() {}
470 self.device
471 .sspdr()
472 .write(|w| unsafe { w.data().bits(*word as u16) });
473
474 while !self.is_readable() {}
476 *word = self.device.sspdr().read().data().bits() as $type;
477 }
478
479 Ok(())
480 }
481
482 fn flush(&mut self) -> Result<(), Self::Error> {
483 while self.is_busy() {}
484 Ok(())
485 }
486 }
487
488 impl<D: SpiDevice, P: ValidSpiPinout<D>> FullDuplex<$type> for Spi<Enabled, D, P, $nr> {
489 fn read(&mut self) -> Result<$type, nb::Error<Infallible>> {
490 if !self.is_readable() {
491 return Err(nb::Error::WouldBlock);
492 }
493
494 Ok(self.device.sspdr().read().data().bits() as $type)
495 }
496 fn write(&mut self, word: $type) -> Result<(), nb::Error<Infallible>> {
497 if !self.is_writable() {
501 return Err(nb::Error::WouldBlock);
502 }
503
504 self.device
505 .sspdr()
506 .write(|w| unsafe { w.data().bits(word as u16) });
507 Ok(())
508 }
509 }
510
511 unsafe impl<D: SpiDevice, P: ValidSpiPinout<D>> ReadTarget for Spi<Enabled, D, P, $nr> {
514 type ReceivedWord = $type;
515
516 fn rx_treq() -> Option<u8> {
517 Some(D::rx_dreq())
518 }
519
520 fn rx_address_count(&self) -> (u32, u32) {
521 (
522 self.device.sspdr().as_ptr() as u32,
523 u32::MAX,
524 )
525 }
526
527 fn rx_increment(&self) -> bool {
528 false
529 }
530 }
531
532 impl<D: SpiDevice, P: ValidSpiPinout<D>> EndlessReadTarget for Spi<Enabled, D, P, $nr> {}
533
534 unsafe impl<D: SpiDevice, P: ValidSpiPinout<D>> WriteTarget for Spi<Enabled, D, P, $nr> {
537 type TransmittedWord = $type;
538
539 fn tx_treq() -> Option<u8> {
540 Some(D::tx_dreq())
541 }
542
543 fn tx_address_count(&mut self) -> (u32, u32) {
544 (
545 self.device.sspdr().as_ptr() as u32,
546 u32::MAX,
547 )
548 }
549
550 fn tx_increment(&self) -> bool {
551 false
552 }
553 }
554
555 impl<D: SpiDevice, P: ValidSpiPinout<D>> EndlessWriteTarget for Spi<Enabled, D, P, $nr> {}
556 )+
557
558 };
559}
560
561impl_write!(u8, [4, 5, 6, 7, 8]);
562impl_write!(u16, [9, 10, 11, 12, 13, 14, 15, 16]);