1use crate::pac::{SPI1, SPI2};
4use core::{cmp::max, slice};
5use embedded_hal::spi::{ErrorKind, ErrorType, SpiBus};
6pub use embedded_hal::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3};
7
8pub type Error = ErrorKind;
10
11pub enum Proto {
12 Spi(Mode),
13 AudioI2s(AudioFrameFormat),
14}
15
16#[derive(Copy, Clone, Debug, PartialEq)]
18pub enum AudioFrameFormat {
19 F32S16,
21 F64S16,
23 F64S24,
25 F64S32,
27}
28
29impl AudioFrameFormat {
30 fn mode16(self) -> bool {
31 match self {
32 AudioFrameFormat::F32S16 => false,
33 AudioFrameFormat::F64S16 => true,
34 AudioFrameFormat::F64S24 => true,
35 AudioFrameFormat::F64S32 => false,
36 }
37 }
38
39 fn mode32(self) -> bool {
40 match self {
41 AudioFrameFormat::F32S16 => false,
42 AudioFrameFormat::F64S16 => false,
43 AudioFrameFormat::F64S24 => true,
44 AudioFrameFormat::F64S32 => true,
45 }
46 }
47}
48
49pub struct Spi<SPI> {
50 spi: SPI,
51}
52
53macro_rules! spi {
54 ($Id:ident, $Spi:ident) => {
55 impl Spi<$Spi> {
56 pub fn $Id(spi: $Spi, proto: Proto, clock_div: u32) -> Self {
63 spi.con1.write(|w| unsafe { w.bits(0) }); let brg1 = clock_div / 2;
65 let brg = if brg1 > 0 { brg1 - 1 } else { brg1 };
66 spi.brg.write(|w| unsafe { w.bits(brg) });
67 match proto {
68 Proto::Spi(mode) => {
69 let ckp = match mode.polarity {
70 Polarity::IdleLow => false,
71 Polarity::IdleHigh => true,
72 };
73 let cke = match mode.phase {
74 Phase::CaptureOnFirstTransition => true,
75 Phase::CaptureOnSecondTransition => false,
76 };
77 spi.con2.write(|w| unsafe { w.bits(0) });
78 spi.con1.write(|w| {
79 w.enhbuf()
80 .bit(true)
81 .cke()
82 .bit(cke)
83 .ckp()
84 .bit(ckp)
85 .msten()
86 .bit(true)
87 });
88 spi.con1set.write(|w| w.on().bit(true));
89 }
90 Proto::AudioI2s(frame_format) => {
91 spi.con2.write(|w| unsafe {
92 w.ignrov()
93 .bit(true)
94 .igntur()
95 .bit(true)
96 .auden()
97 .bit(true)
98 .audmod()
99 .bits(0b00) });
101 spi.con1.write(|w| unsafe {
102 w.mclksel()
103 .bit(true) .enhbuf()
105 .bit(true)
106 .mode32()
107 .bit(frame_format.mode32())
108 .mode16()
109 .bit(frame_format.mode16())
110 .ckp()
111 .bit(true)
112 .stxisel()
113 .bits(0b11) .srxisel()
115 .bits(0b01) .msten()
117 .bit(true)
118 .on()
119 .bit(true)
120 });
121 }
122 }
123 Spi { spi }
124 }
125
126 pub fn free(self) -> $Spi {
127 self.spi.con1.write(|w| w.on().bit(false)); self.spi
129 }
130 }
131
132 impl embedded_hal_0_2::spi::FullDuplex<u8> for Spi<$Spi> {
133 type Error = Error;
134
135 fn read(&mut self) -> nb::Result<u8, Error> {
136 if self.spi.stat.read().spirbe().bit() {
137 Err(nb::Error::WouldBlock)
138 } else if self.spi.stat.read().spirov().bit() {
139 self.spi.statclr.write(|w| w.spirov().bit(true));
140 Err(nb::Error::Other(Error::Overrun))
141 } else {
142 let byte = self.spi.buf.read().bits() as u8;
143 Ok(byte)
144 }
145 }
146
147 fn send(&mut self, byte: u8) -> nb::Result<(), Error> {
148 if self.spi.stat.read().spitbf().bit() {
149 Err(nb::Error::WouldBlock)
150 } else {
151 self.spi.buf.write(|w| unsafe { w.bits(byte as u32) });
152 Ok(())
153 }
154 }
155 }
156
157 impl embedded_hal_0_2::blocking::spi::transfer::Default<u8> for Spi<$Spi> {}
158 impl embedded_hal_0_2::blocking::spi::write::Default<u8> for Spi<$Spi> {}
159
160 impl ErrorType for Spi<$Spi> {
161 type Error = Error;
162 }
163
164 impl SpiBus<u8> for Spi<$Spi> {
165 fn read(&mut self, bytes: &mut [u8]) -> Result<(), Self::Error> {
166 self.transfer(bytes, &[])
167 }
168
169 fn write(&mut self, bytes: &[u8]) -> Result<(), Self::Error> {
170 self.transfer(&mut [], bytes)
171 }
172
173 fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> {
174 let xfer_len = max(read.len(), write.len());
175 let mut rd_ndx = 0;
176 let mut wr_ndx = 0;
177 while rd_ndx < xfer_len || wr_ndx < xfer_len {
179 if wr_ndx < xfer_len && !self.spi.stat.read().spitbf().bit() {
181 let byte = if wr_ndx < write.len() {
182 write[wr_ndx]
183 } else {
184 0x00
185 };
186 self.spi.buf.write(|w| unsafe { w.bits(byte as u32) });
187 wr_ndx += 1;
188 }
189 if rd_ndx < xfer_len && !self.spi.stat.read().spirbe().bit() {
191 let byte = self.spi.buf.read().bits() as u8;
192 if rd_ndx < read.len() {
193 read[rd_ndx] = byte;
194 }
195 rd_ndx += 1;
196 }
197 }
198 Ok(())
199 }
200
201 fn transfer_in_place(&mut self, bytes: &mut [u8]) -> Result<(), Self::Error> {
202 let ptr = bytes.as_mut_ptr();
203 let len = bytes.len();
204 let read = unsafe { slice::from_raw_parts_mut(ptr, len) };
207 let write = unsafe { slice::from_raw_parts(ptr, len) };
208 self.transfer(read, write)
209 }
210
211 fn flush(&mut self) -> Result<(), Self::Error> {
212 Ok(())
213 }
214 }
215 };
216}
217
218spi!(spi1, SPI1);
219spi!(spi2, SPI2);