1
1
/*
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
8
2
* Copyright (C) 2021, Marton Ledneczki
3
+ * Copyright (C) 2021, Raphael Lehmann
9
4
*
10
5
* This file is part of the modm project.
11
6
*
@@ -36,16 +31,26 @@ namespace platform
36
31
*
37
32
* TODO: say something about the nature of implementation
38
33
*
39
- * @author Marton Ledneczki
34
+ * @tparam DmaChannelTX DMA channel for sending
35
+ *
36
+ * @author Marton Ledneczki, Raphael Lehmann
40
37
* @ingroup modm_platform_i2s modm_platform_i2s_{{id}}
41
38
*/
39
+ template <class DmaChannelTx>
42
40
class I2sMaster{{ id }} : public modm::I2sMaster
43
41
{
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
+
44
49
public:
45
50
using Hal = I2sHal{{ id }};
46
51
47
52
48
- template< template<Peripheral _> class... Signals >
53
+ template< class... Signals >
49
54
static void
50
55
connect()
51
56
{
@@ -65,7 +70,7 @@ public:
65
70
66
71
template< class SystemClock, frequency_t samplerate, percent_t tolerance=pct(0.019) >
67
72
static inline void
68
- initialize()
73
+ initialize(DmaBase::Priority dmaPriority = DmaBase::Priority::High )
69
74
{
70
75
constexpr float prescaler = static_cast<float>(SystemClock::I2sPll) / (samplerate*16*2*8);
71
76
constexpr uint8_t i2s_div = static_cast<uint8_t>(prescaler/2);
@@ -77,9 +82,68 @@ public:
77
82
"I2S{{ id }}: Exceeding specified tolerance, when determining prescelar.");
78
83
Hal::initialize(odd_factor ? Hal::OddFactor::Enabled : Hal::OddFactor::Disabled,
79
84
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();
80
135
}
81
136
82
137
// 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 };
83
147
};
84
148
85
149
} // namespace platform
0 commit comments