@@ -162,6 +162,108 @@ pub struct I2S<'d, T: Instance, Tx, Rx> {
162
162
}
163
163
164
164
impl < ' d , T : Instance , Tx , Rx > I2S < ' d , T , Tx , Rx > {
165
+ /// Note: Full-Duplex modes are not supported at this time
166
+ pub fn new_no_mck (
167
+ peri : impl Peripheral < P = T > + ' d ,
168
+ sd : impl Peripheral < P = impl MosiPin < T > > + ' d ,
169
+ ws : impl Peripheral < P = impl WsPin < T > > + ' d ,
170
+ ck : impl Peripheral < P = impl CkPin < T > > + ' d ,
171
+ txdma : impl Peripheral < P = Tx > + ' d ,
172
+ rxdma : impl Peripheral < P = Rx > + ' d ,
173
+ freq : Hertz ,
174
+ config : Config ,
175
+ ) -> Self {
176
+ into_ref ! ( sd, ws, ck) ;
177
+
178
+ sd. set_as_af ( sd. af_num ( ) , AFType :: OutputPushPull ) ;
179
+ sd. set_speed ( crate :: gpio:: Speed :: VeryHigh ) ;
180
+
181
+ ws. set_as_af ( ws. af_num ( ) , AFType :: OutputPushPull ) ;
182
+ ws. set_speed ( crate :: gpio:: Speed :: VeryHigh ) ;
183
+
184
+ ck. set_as_af ( ck. af_num ( ) , AFType :: OutputPushPull ) ;
185
+ ck. set_speed ( crate :: gpio:: Speed :: VeryHigh ) ;
186
+
187
+ let mut spi_cfg = SpiConfig :: default ( ) ;
188
+ spi_cfg. frequency = freq;
189
+ let spi = Spi :: new_internal ( peri, txdma, rxdma, spi_cfg) ;
190
+
191
+ #[ cfg( all( rcc_f4, not( stm32f410) ) ) ]
192
+ let pclk = Hertz ( 38_400_000 ) ; // unsafe { get_freqs() }.plli2s1_r.unwrap();
193
+
194
+ #[ cfg( stm32f410) ]
195
+ let pclk = T :: frequency ( ) ;
196
+
197
+ let ( odd, div) = compute_baud_rate ( pclk, freq, config. master_clock , config. format ) ;
198
+
199
+ #[ cfg( any( spi_v1, spi_f1) ) ]
200
+ {
201
+ use stm32_metapac:: spi:: vals:: { I2scfg , Odd } ;
202
+
203
+ // 1. Select the I2SDIV[7:0] bits in the SPI_I2SPR register to define the serial clock baud
204
+ // rate to reach the proper audio sample frequency. The ODD bit in the SPI_I2SPR
205
+ // register also has to be defined.
206
+
207
+ T :: REGS . i2spr ( ) . modify ( |w| {
208
+ w. set_i2sdiv ( div) ;
209
+ w. set_odd ( match odd {
210
+ true => Odd :: ODD ,
211
+ false => Odd :: EVEN ,
212
+ } ) ;
213
+
214
+ // No mclk
215
+ w. set_mckoe ( config. master_clock ) ;
216
+ } ) ;
217
+
218
+ // 2. Select the CKPOL bit to define the steady level for the communication clock. Set the
219
+ // MCKOE bit in the SPI_I2SPR register if the master clock MCK needs to be provided to
220
+ // the external DAC/ADC audio component (the I2SDIV and ODD values should be
221
+ // computed depending on the state of the MCK output, for more details refer to
222
+ // Section 28.4.4: Clock generator).
223
+
224
+ // 3. Set the I2SMOD bit in SPI_I2SCFGR to activate the I2S functionalities and choose the
225
+ // I2S standard through the I2SSTD[1:0] and PCMSYNC bits, the data length through the
226
+ // DATLEN[1:0] bits and the number of bits per channel by configuring the CHLEN bit.
227
+ // Select also the I2S master mode and direction (Transmitter or Receiver) through the
228
+ // I2SCFG[1:0] bits in the SPI_I2SCFGR register.
229
+
230
+ // 4. If needed, select all the potential interruption sources and the DMA capabilities by
231
+ // writing the SPI_CR2 register.
232
+
233
+ // 5. The I2SE bit in SPI_I2SCFGR register must be set.
234
+
235
+ T :: REGS . i2scfgr ( ) . modify ( |w| {
236
+ w. set_i2se ( false ) ;
237
+
238
+ w. set_ckpol ( config. clock_polarity . ckpol ( ) ) ;
239
+
240
+ w. set_i2smod ( true ) ;
241
+ w. set_i2sstd ( config. standard . i2sstd ( ) ) ;
242
+ w. set_pcmsync ( config. standard . pcmsync ( ) ) ;
243
+
244
+ w. set_datlen ( config. format . datlen ( ) ) ;
245
+ w. set_chlen ( config. format . chlen ( ) ) ;
246
+
247
+ w. set_i2scfg ( match ( config. mode , config. function ) {
248
+ ( Mode :: Master , Function :: Transmit ) => I2scfg :: MASTERTX ,
249
+ ( Mode :: Master , Function :: Receive ) => I2scfg :: MASTERRX ,
250
+ ( Mode :: Slave , Function :: Transmit ) => I2scfg :: SLAVETX ,
251
+ ( Mode :: Slave , Function :: Receive ) => I2scfg :: SLAVERX ,
252
+ } ) ;
253
+
254
+ w. set_i2se ( true )
255
+ } ) ;
256
+ }
257
+
258
+ Self {
259
+ _peri : spi,
260
+ sd : Some ( sd. map_into ( ) ) ,
261
+ ws : Some ( ws. map_into ( ) ) ,
262
+ ck : Some ( ck. map_into ( ) ) ,
263
+ mck : None ,
264
+ }
265
+ }
266
+
165
267
/// Note: Full-Duplex modes are not supported at this time
166
268
pub fn new (
167
269
peri : impl Peripheral < P = T > + ' d ,
@@ -273,6 +375,20 @@ impl<'d, T: Instance, Tx, Rx> I2S<'d, T, Tx, Rx> {
273
375
self . _peri . write ( data) . await
274
376
}
275
377
378
+ /// Write audio data.
379
+ pub fn writer ( & mut self , data : & [ u16 ] ) -> Result < ( ) , Error > {
380
+ let mut spi = T :: REGS ;
381
+
382
+ // let dr = spi.dr().as_ptr() as *mut W;
383
+
384
+ for sample in data {
385
+ while !spi. sr ( ) . read ( ) . txe ( ) { }
386
+ spi. dr ( ) . write ( |reg| reg. set_dr ( * sample) ) ;
387
+ }
388
+
389
+ Ok ( ( ) )
390
+ }
391
+
276
392
/// Read audio data.
277
393
pub async fn read < W : Word > ( & mut self , data : & mut [ W ] ) -> Result < ( ) , Error >
278
394
where
0 commit comments