6969//!
7070//! - Only TDM Philips standard is supported.
7171
72+ use core:: {
73+ mem:: ManuallyDrop ,
74+ ops:: { Deref , DerefMut } ,
75+ } ;
76+
7277use enumset:: { EnumSet , EnumSetType } ;
7378use private:: * ;
7479
@@ -86,13 +91,12 @@ use crate::{
8691 DmaError ,
8792 DmaTransferRx ,
8893 DmaTransferRxCircular ,
89- DmaTransferTx ,
90- DmaTransferTxCircular ,
94+ DmaTxBuffer ,
9195 PeripheralRxChannel ,
9296 PeripheralTxChannel ,
93- ReadBuffer ,
9497 WriteBuffer ,
95- dma_private:: { DmaSupport , DmaSupportRx , DmaSupportTx } ,
98+ asynch:: DmaTxDoneChFuture ,
99+ dma_private:: { DmaSupport , DmaSupportRx } ,
96100 } ,
97101 gpio:: { OutputConfig , interconnect:: PeripheralOutput } ,
98102 i2s:: AnyI2s ,
@@ -416,6 +420,39 @@ where
416420 }
417421}
418422
423+ impl < ' d , Dm > I2sTx < ' d , Dm >
424+ where
425+ Dm : DriverMode ,
426+ {
427+ /// Starts a DMA transfer to write data to the I2S transmitter.
428+ pub fn write < TXBUF : DmaTxBuffer > (
429+ mut self ,
430+ mut buf : TXBUF ,
431+ ) -> Result < I2sWriteDmaTransfer < ' d , Dm , TXBUF > , Error > {
432+ // Reset TX unit and TX FIFO
433+ self . i2s . reset_tx ( ) ;
434+
435+ // Enable corresponding interrupts if needed
436+
437+ // configure DMA outlink
438+ unsafe {
439+ self . tx_channel
440+ . prepare_transfer ( self . i2s . dma_peripheral ( ) , & mut buf)
441+ . and_then ( |_| self . tx_channel . start_transfer ( ) ) ?;
442+ }
443+
444+ // set I2S_TX_STOP_EN if needed
445+
446+ // start: set I2S_TX_START
447+ self . i2s . tx_start ( ) ;
448+
449+ Ok ( I2sWriteDmaTransfer {
450+ i2s_tx : ManuallyDrop :: new ( self ) ,
451+ buffer_view : ManuallyDrop :: new ( buf. into_view ( ) ) ,
452+ } )
453+ }
454+ }
455+
419456/// I2S RX channel
420457pub struct I2sRx < ' d , Dm >
421458where
@@ -556,6 +593,88 @@ where
556593 }
557594}
558595
596+ /// An in-progress async circular DMA write transfer.
597+ pub struct I2sWriteDmaTransfer < ' d , Dm : DriverMode , BUFFER : DmaTxBuffer > {
598+ i2s_tx : ManuallyDrop < I2sTx < ' d , Dm > > ,
599+ buffer_view : ManuallyDrop < BUFFER :: View > ,
600+ }
601+
602+ impl < ' d , Dm : DriverMode , BUFFER : DmaTxBuffer > Deref for I2sWriteDmaTransfer < ' d , Dm , BUFFER > {
603+ type Target = BUFFER :: View ;
604+
605+ fn deref ( & self ) -> & Self :: Target {
606+ & self . buffer_view
607+ }
608+ }
609+
610+ impl < ' d , Dm : DriverMode , BUFFER : DmaTxBuffer > DerefMut for I2sWriteDmaTransfer < ' d , Dm , BUFFER > {
611+ fn deref_mut ( & mut self ) -> & mut Self :: Target {
612+ & mut self . buffer_view
613+ }
614+ }
615+
616+ impl < ' d , Dm : DriverMode , BUFFER : DmaTxBuffer > Drop for I2sWriteDmaTransfer < ' d , Dm , BUFFER > {
617+ fn drop ( & mut self ) {
618+ self . stop_peripheral ( ) ;
619+ // SAFETY: This is Drop, we know that self.i2s_tx and self.buffer_view
620+ // won't be touched again.
621+ unsafe {
622+ ManuallyDrop :: drop ( & mut self . i2s_tx ) ;
623+ ManuallyDrop :: drop ( & mut self . buffer_view ) ;
624+ }
625+ }
626+ }
627+
628+ impl < ' d , Dm : DriverMode , BUFFER : DmaTxBuffer > I2sWriteDmaTransfer < ' d , Dm , BUFFER > {
629+ /// Stops the DMA transfer and returns the I2S transmitter and buffer.
630+ pub fn stop ( mut self ) -> ( I2sTx < ' d , Dm > , BUFFER ) {
631+ self . stop_peripheral ( ) ;
632+ let ( i2s_tx, view) = self . release ( ) ;
633+ ( i2s_tx, BUFFER :: from_view ( view) )
634+ }
635+
636+ /// Checks if the DMA transfer is done.
637+ pub fn is_done ( & self ) -> bool {
638+ self . i2s_tx . tx_channel . is_done ( )
639+ }
640+
641+ /// Stops and restarts the DMA transfer.
642+ pub fn restart ( self ) -> Result < Self , Error > {
643+ let ( i2s, buf) = self . stop ( ) ;
644+ i2s. write ( buf)
645+ }
646+
647+ /// Checks if the DMA transfer has an error.
648+ pub fn has_error ( & self ) -> bool {
649+ self . i2s_tx . tx_channel . has_error ( )
650+ }
651+
652+ fn release ( mut self ) -> ( I2sTx < ' d , Dm > , BUFFER :: View ) {
653+ // SAFETY: Since forget is called on self, we know that self.i2s_tx and
654+ // self.buffer_view won't be touched again.
655+ let result = unsafe {
656+ (
657+ ManuallyDrop :: take ( & mut self . i2s_tx ) ,
658+ ManuallyDrop :: take ( & mut self . buffer_view ) ,
659+ )
660+ } ;
661+ core:: mem:: forget ( self ) ;
662+ result
663+ }
664+
665+ fn stop_peripheral ( & mut self ) {
666+ self . i2s_tx . i2s . tx_stop ( ) ;
667+ }
668+ }
669+
670+ impl < BUFFER : DmaTxBuffer > I2sWriteDmaTransfer < ' _ , Async , BUFFER > {
671+ /// Waits for any DMA process to be made.
672+ pub async fn process ( & mut self ) -> Result < ( ) , Error > {
673+ DmaTxDoneChFuture :: new ( & mut self . i2s_tx . tx_channel ) . await ?;
674+ Ok ( ( ) )
675+ }
676+ }
677+
559678/// A peripheral singleton compatible with the I2S master driver.
560679pub trait Instance : RegisterAccessPrivate + super :: IntoAnyI2s { }
561680impl Instance for crate :: peripherals:: I2S0 < ' _ > { }
@@ -1710,116 +1829,6 @@ pub mod asynch {
17101829 } ,
17111830 } ;
17121831
1713- impl < ' d > I2sTx < ' d , Async > {
1714- /// Continuously write to I2S. Returns [I2sWriteDmaTransferAsync]
1715- pub fn write < TXBUF : DmaTxBuffer > (
1716- mut self ,
1717- mut buf : TXBUF ,
1718- ) -> Result < I2sWriteDmaTransferAsync < ' d , TXBUF > , Error > {
1719- // Reset TX unit and TX FIFO
1720- self . i2s . reset_tx ( ) ;
1721-
1722- // Enable corresponding interrupts if needed
1723-
1724- // configure DMA outlink
1725- unsafe {
1726- self . tx_channel
1727- . prepare_transfer ( self . i2s . dma_peripheral ( ) , & mut buf)
1728- . and_then ( |_| self . tx_channel . start_transfer ( ) ) ?;
1729- }
1730-
1731- // set I2S_TX_STOP_EN if needed
1732-
1733- // start: set I2S_TX_START
1734- self . i2s . tx_start ( ) ;
1735-
1736- Ok ( I2sWriteDmaTransferAsync {
1737- i2s_tx : ManuallyDrop :: new ( self ) ,
1738- buffer_view : ManuallyDrop :: new ( buf. into_view ( ) ) ,
1739- } )
1740- }
1741- }
1742-
1743- /// An in-progress async circular DMA write transfer.
1744- pub struct I2sWriteDmaTransferAsync < ' d , BUFFER : DmaTxBuffer > {
1745- i2s_tx : ManuallyDrop < I2sTx < ' d , Async > > ,
1746- buffer_view : ManuallyDrop < BUFFER :: View > ,
1747- }
1748-
1749- impl < ' d , BUFFER : DmaTxBuffer > Deref for I2sWriteDmaTransferAsync < ' d , BUFFER > {
1750- type Target = BUFFER :: View ;
1751-
1752- fn deref ( & self ) -> & Self :: Target {
1753- & self . buffer_view
1754- }
1755- }
1756-
1757- impl < ' d , BUFFER : DmaTxBuffer > DerefMut for I2sWriteDmaTransferAsync < ' d , BUFFER > {
1758- fn deref_mut ( & mut self ) -> & mut Self :: Target {
1759- & mut self . buffer_view
1760- }
1761- }
1762-
1763- impl < ' d , BUFFER : DmaTxBuffer > Drop for I2sWriteDmaTransferAsync < ' d , BUFFER > {
1764- fn drop ( & mut self ) {
1765- self . stop_peripheral ( ) ;
1766- // SAFETY: This is Drop, we know that self.i2s_tx and self.buffer_view
1767- // won't be touched again.
1768- unsafe {
1769- ManuallyDrop :: drop ( & mut self . i2s_tx ) ;
1770- ManuallyDrop :: drop ( & mut self . buffer_view ) ;
1771- }
1772- }
1773- }
1774-
1775- impl < ' d , BUFFER : DmaTxBuffer > I2sWriteDmaTransferAsync < ' d , BUFFER > {
1776- /// Stops the DMA transfer and returns the I2S transmitter and buffer.
1777- pub fn stop ( mut self ) -> ( I2sTx < ' d , Async > , BUFFER ) {
1778- self . stop_peripheral ( ) ;
1779- let ( i2s_tx, view) = self . release ( ) ;
1780- ( i2s_tx, BUFFER :: from_view ( view) )
1781- }
1782-
1783- /// Checks if the DMA transfer is done.
1784- pub fn is_done ( & self ) -> bool {
1785- self . i2s_tx . tx_channel . is_done ( )
1786- }
1787-
1788- /// Stops and restarts the DMA transfer.
1789- pub fn restart ( self ) -> Result < Self , Error > {
1790- let ( i2s, buf) = self . stop ( ) ;
1791- i2s. write ( buf)
1792- }
1793-
1794- /// Checks if the DMA transfer has an error.
1795- pub fn has_error ( & self ) -> bool {
1796- self . i2s_tx . tx_channel . has_error ( )
1797- }
1798-
1799- /// Waits for any DMA process to be made.
1800- pub async fn process ( & mut self ) -> Result < ( ) , Error > {
1801- DmaTxDoneChFuture :: new ( & mut self . i2s_tx . tx_channel ) . await ?;
1802- Ok ( ( ) )
1803- }
1804-
1805- fn release ( mut self ) -> ( I2sTx < ' d , Async > , BUFFER :: View ) {
1806- // SAFETY: Since forget is called on self, we know that self.i2s_tx and
1807- // self.buffer_view won't be touched again.
1808- let result = unsafe {
1809- (
1810- ManuallyDrop :: take ( & mut self . i2s_tx ) ,
1811- ManuallyDrop :: take ( & mut self . buffer_view ) ,
1812- )
1813- } ;
1814- core:: mem:: forget ( self ) ;
1815- result
1816- }
1817-
1818- fn stop_peripheral ( & mut self ) {
1819- self . i2s_tx . i2s . tx_stop ( ) ;
1820- }
1821- }
1822-
18231832 impl < ' d > I2sRx < ' d , Async > {
18241833 /// One-shot read I2S.
18251834 pub async fn read_dma_async ( & mut self , words : & mut [ u8 ] ) -> Result < ( ) , Error > {
0 commit comments