11/*
2- * Copyright (c) 2009-2011, Fabian Greif
3- * Copyright (c) 2010, Martin Rosekeit
4- * Copyright (c) 2011-2017, Niklas Hauser
5- * Copyright (c) 2012, Georgi Grinshpun
6- * Copyright (c) 2013, Kevin Läufer
7- * Copyright (c) 2014, Sascha Schade
82 * Copyright (C) 2021, Marton Ledneczki
3+ * Copyright (C) 2021, Raphael Lehmann
94 *
105 * This file is part of the modm project.
116 *
@@ -36,16 +31,26 @@ namespace platform
3631 *
3732 * TODO: say something about the nature of implementation
3833 *
39- * @author Marton Ledneczki
34+ * @tparam DmaChannelTX DMA channel for sending
35+ *
36+ * @author Marton Ledneczki, Raphael Lehmann
4037 * @ingroup modm_platform_i2s modm_platform_i2s_{{id}}
4138 */
39+ template <class DmaChannelTx>
4240class I2sMaster{{ id }} : public modm::I2sMaster
4341{
42+ struct Dma {
43+ using TxChannel = typename DmaChannelTx::template RequestMapping<
44+ Peripheral::Spi{{ id }}, DmaBase::Signal::Tx>::Channel;
45+ static constexpr DmaBase::Request TxRequest = DmaChannelTx::template RequestMapping<
46+ Peripheral::Spi{{ id }}, DmaBase::Signal::Tx>::Request;
47+ };
48+
4449public:
4550 using Hal = I2sHal{{ id }};
4651
4752
48- template< template<Peripheral _> class... Signals >
53+ template< class... Signals >
4954 static void
5055 connect()
5156 {
@@ -65,7 +70,7 @@ public:
6570
6671 template< class SystemClock, frequency_t samplerate, percent_t tolerance=pct(0.019) >
6772 static inline void
68- initialize()
73+ initialize(DmaBase::Priority dmaPriority = DmaBase::Priority::High )
6974 {
7075 constexpr float prescaler = static_cast<float>(SystemClock::I2sPll) / (samplerate*16*2*8);
7176 constexpr uint8_t i2s_div = static_cast<uint8_t>(prescaler/2);
@@ -77,9 +82,68 @@ public:
7782 "I2S{{ id }}: Exceeding specified tolerance, when determining prescelar.");
7883 Hal::initialize(odd_factor ? Hal::OddFactor::Enabled : Hal::OddFactor::Disabled,
7984 i2s_div);
85+
86+ Dma::TxChannel::configure(
87+ DmaBase::DataTransferDirection::MemoryToPeripheral, DmaBase::MemoryDataSize::Bit16,
88+ DmaBase::PeripheralDataSize::Bit16, DmaBase::MemoryIncrementMode::Increment,
89+ DmaBase::PeripheralIncrementMode::Fixed, dmaPriority,
90+ DmaBase::CircularMode::Disabled, DmaBase::DoubleBufferMode::Enabled);
91+ Dma::TxChannel::setPeripheralAddress(SPI{{ id }}_BASE + 0x0c);
92+ Dma::TxChannel::setTransferErrorIrqHandler(handleDmaTransferError);
93+ Dma::TxChannel::enableInterruptVector();
94+ Dma::TxChannel::enableInterrupt(DmaBase::InterruptEnable::TransferError |
95+ DmaBase::InterruptEnable::TransferComplete);
96+ Dma::TxChannel::template setPeripheralRequest<Dma::TxRequest>();
97+ }
98+
99+ static inline void
100+ setTxBufferAddresses(uintptr_t first_address, uintptr_t second_address, std::size_t length)
101+ {
102+ Dma::TxChannel::setMemoryAddress(first_address);
103+ Dma::TxChannel::setMemoryAddress2(second_address);
104+ Dma::TxChannel::setDataLength(length);
105+ }
106+
107+ static inline void
108+ setTxBufferAddress1(uintptr_t first_address)
109+ {
110+ Dma::TxChannel::setMemoryAddress(first_address);
111+ }
112+
113+ static inline void
114+ setTxBufferAddress2( uintptr_t second_address)
115+ {
116+ Dma::TxChannel::setMemoryAddress2(second_address);
117+ }
118+
119+ static inline bool
120+ isBuffer1Active()
121+ {
122+ return Dma::TxChannel::isPrimaryBufferActive();
123+ }
124+
125+ static inline void
126+ start()
127+ {
128+ Dma::TxChannel::start();
129+ }
130+
131+ static inline void
132+ stop()
133+ {
134+ Dma::TxChannel::stop();
80135 }
81136
82137 // end documentation inherited
138+
139+ private:
140+ static void handleDmaTransferError()
141+ {
142+ Dma::TxChannel::stop();
143+ dmaError = true;
144+ }
145+
146+ static inline bool dmaError { false };
83147};
84148
85149} // namespace platform
0 commit comments