@@ -449,8 +449,12 @@ dual_i2s!(pac::SPI3, pac::I2S3EXT, DualI2s3, i2s3, i2s_apb1_clk);
449449mod dma {
450450 use super :: * ;
451451 use crate :: dma:: traits:: { DMASet , PeriAddress } ;
452+ use crate :: pac:: spi1:: RegisterBlock ;
453+ use core:: marker:: PhantomData ;
452454 use core:: ops:: Deref ;
453- use stm32_i2s_v12x:: driver:: I2sDriver ;
455+ use stm32_i2s_v12x:: driver:: { I2sCore , I2sDriver } ;
456+ use stm32_i2s_v12x:: transfer:: { Ext , Main } ;
457+ use stm32_i2s_v12x:: DualI2sPeripheral ;
454458
455459 /// I2S DMA reads from and writes to the data register
456460 unsafe impl < SPI : Instance , MS , TR , STD > PeriAddress for I2sDriver < I2s < SPI > , MS , TR , STD >
@@ -474,4 +478,68 @@ mod dma {
474478 SPI : DMASet < STREAM , CHANNEL , DIR > ,
475479 {
476480 }
481+
482+ pub trait DualI2sDmaTargetExt < I , PART , MS , DIR , STD > {
483+ fn dma_target ( & self ) -> DualI2sDmaTarget < I , PART , MS , DIR , STD > ;
484+ }
485+ impl < I , PART , MS , DIR , STD > DualI2sDmaTargetExt < I , PART , MS , DIR , STD >
486+ for I2sCore < I , PART , MS , DIR , STD >
487+ {
488+ fn dma_target ( & self ) -> DualI2sDmaTarget < I , PART , MS , DIR , STD > {
489+ DualI2sDmaTarget {
490+ _dual_i2s_peripheral : PhantomData ,
491+ _part : PhantomData ,
492+ _ms : PhantomData ,
493+ _dir : PhantomData ,
494+ _std : PhantomData ,
495+ }
496+ }
497+ }
498+
499+ /// - `I`: The [DualI2sPeripheral] controlled by the I2sCore.
500+ /// - `PART`: `Main` or `Ext`. The part of [DualI2sPeripheral] controlled by I2sCore.
501+ /// - `MS`: `Master` or `Slave`. The role of the I2sCore. Only a `Main` I2sCore can be Master.
502+ /// - `DIR` : `Transmit` or `Receive`. Communication direction.
503+ /// - `STD`: I2S standard, eg `Philips`
504+ pub struct DualI2sDmaTarget < I , PART , MS , DIR , STD > {
505+ _dual_i2s_peripheral : PhantomData < I > ,
506+ _part : PhantomData < PART > ,
507+ _ms : PhantomData < MS > ,
508+ _dir : PhantomData < DIR > ,
509+ _std : PhantomData < STD > ,
510+ }
511+
512+ macro_rules! dual_dma {
513+ ( $ext: ty, $reg: ident) => {
514+ /// I2S DMA reads from and writes to the data register
515+ unsafe impl <SPIext : DualInstance , MS , TR , STD > PeriAddress
516+ for DualI2sDmaTarget <DualI2s <SPIext >, $ext, MS , TR , STD >
517+ where
518+ DualI2s <SPIext >: DualI2sPeripheral ,
519+ {
520+ /// SPI_DR is only 16 bits. Multiple transfers are needed for a 24-bit or 32-bit sample,
521+ /// as explained in the reference manual.
522+ type MemSize = u16 ;
523+
524+ fn address( & self ) -> u32 {
525+ let reg = unsafe { & * ( DualI2s :: $reg as * const RegisterBlock ) } ;
526+ ( & reg. dr) as * const _ as u32
527+ }
528+ }
529+ } ;
530+ }
531+
532+ dual_dma ! ( Main , MAIN_REGISTERS ) ;
533+ dual_dma ! ( Ext , EXT_REGISTERS ) ;
534+
535+ /// DMA is available for I2S based on the underlying implementations for SPI
536+ unsafe impl < SPIext : DualInstance , PART , MS , TR , STD , STREAM , const CHANNEL : u8 , DIR >
537+ DMASet < STREAM , CHANNEL , DIR > for DualI2sDmaTarget < DualI2s < SPIext > , PART , MS , TR , STD >
538+ where
539+ SPIext : DMASet < STREAM , CHANNEL , DIR > ,
540+ {
541+ }
477542}
543+
544+ #[ cfg( feature = "stm32_i2s_v12x" ) ]
545+ pub use dma:: { DualI2sDmaTarget , DualI2sDmaTargetExt } ;
0 commit comments