1
1
#include < Arduino.h>
2
2
#include < wiring_private.h>
3
3
4
+ #include " utility/DMA.h"
5
+
4
6
#include " I2S.h"
5
7
6
- I2SClass::I2SClass (SERCOM *p_sercom, uint8_t uc_index, uint8_t uc_pinSD, uint8_t uc_pinSCK, uint8_t uc_pinFS) :
7
- _p_sercom(p_sercom),
8
+ I2SClass::I2SClass (uint8_t uc_index, uint8_t uc_clock_generator, uint8_t uc_pinSD, uint8_t uc_pinSCK, uint8_t uc_pinFS) :
8
9
_uc_index(uc_index),
10
+ _uc_clock_generator(uc_clock_generator),
9
11
_uc_sd(uc_pinSD),
10
12
_uc_sck(uc_pinSCK),
11
13
_uc_fs(uc_pinFS),
12
14
13
- _i_head(0 ),
14
- _i_tail(0 )
15
+ _i_dma_channel(-1 ),
16
+ freeBuffers(2 ),
17
+ inIndex(0 ),
18
+
19
+ _onTransmit(NULL )
15
20
{
16
- memset (_aui_buffer, 0 , sizeof (_aui_buffer));
17
21
}
18
22
19
23
int I2SClass::begin (int mode, long sampleRate, int bitsPerSample, int driveClock)
@@ -35,32 +39,39 @@ int I2SClass::begin(int mode, long sampleRate, int bitsPerSample, int driveClock
35
39
case 16 :
36
40
case 24 :
37
41
case 32 :
38
- _i_bits_per_sample = bitsPerSample;
39
42
break ;
40
43
41
44
default :
42
45
Serial.println (" invalid bits per sample" );
43
46
return 1 ;
44
47
}
45
48
49
+ DMA.begin ();
50
+
51
+ _i_dma_channel = DMA.allocateChannel ();
52
+
53
+ if (_i_dma_channel < 0 ) {
54
+ return 1 ;
55
+ }
56
+
46
57
while (_i2s->SYNCBUSY .bit .SWRST );
47
58
_i2s->CTRLA .bit .SWRST = 1 ;
48
59
49
60
PM->APBCMASK .reg |= PM_APBCMASK_I2S;
50
61
51
62
while (GCLK->STATUS .bit .SYNCBUSY );
52
- GCLK->GENDIV .bit .ID = GCLK_CLKCTRL_GEN_GCLK3_Val ;
63
+ GCLK->GENDIV .bit .ID = _uc_clock_generator ;
53
64
GCLK->GENDIV .bit .DIV = SystemCoreClock / (sampleRate * 2 * bitsPerSample);
54
65
55
66
while (GCLK->STATUS .bit .SYNCBUSY );
56
- GCLK->GENCTRL .bit .ID = GCLK_CLKCTRL_GEN_GCLK3_Val ;
67
+ GCLK->GENCTRL .bit .ID = _uc_clock_generator ;
57
68
GCLK->GENCTRL .bit .SRC = GCLK_GENCTRL_SRC_DFLL48M_Val;
58
69
GCLK->GENCTRL .bit .IDC = 1 ;
59
70
GCLK->GENCTRL .bit .GENEN = 1 ;
60
71
61
72
while (GCLK->STATUS .bit .SYNCBUSY );
62
73
GCLK->CLKCTRL .bit .ID = (_uc_index == 0 ) ? I2S_GCLK_ID_0 : I2S_GCLK_ID_1;
63
- GCLK->CLKCTRL .bit .GEN = GCLK_CLKCTRL_GEN_GCLK3_Val ;
74
+ GCLK->CLKCTRL .bit .GEN = _uc_clock_generator ;
64
75
GCLK->CLKCTRL .bit .CLKEN = 1 ;
65
76
66
77
while (GCLK->STATUS .bit .SYNCBUSY );
@@ -163,8 +174,33 @@ int I2SClass::begin(int mode, long sampleRate, int bitsPerSample, int driveClock
163
174
_i2s->CTRLA .bit .SEREN1 = 1 ;
164
175
}
165
176
166
- NVIC_EnableIRQ (I2S_IRQn);
167
- NVIC_SetPriority (I2S_IRQn, (1 << __NVIC_PRIO_BITS) - 1 ); /* set Priority */
177
+ DMA.incSrc (_i_dma_channel);
178
+ DMA.onTransferComplete (_i_dma_channel, I2SClass::onDmaTransferComplete);
179
+ DMA.onTransferError (_i_dma_channel, I2SClass::onDmaTransferError);
180
+
181
+ if (_uc_index == 0 ) {
182
+ DMA.setTriggerSource (_i_dma_channel, I2S_DMAC_ID_TX_0);
183
+ } else {
184
+ DMA.setTriggerSource (_i_dma_channel, I2S_DMAC_ID_TX_1);
185
+ }
186
+
187
+ switch (bitsPerSample) {
188
+ case 32 :
189
+ DMA.setTransferWidth (_i_dma_channel, 32 );
190
+ break ;
191
+
192
+ case 24 :
193
+ DMA.setTransferWidth (_i_dma_channel, 32 );
194
+ break ;
195
+
196
+ case 16 :
197
+ DMA.setTransferWidth (_i_dma_channel, 16 );
198
+ break ;
199
+
200
+ case 8 :
201
+ DMA.setTransferWidth (_i_dma_channel, 8 );
202
+ break ;
203
+ }
168
204
169
205
return 0 ;
170
206
}
@@ -195,99 +231,81 @@ void I2SClass::flush()
195
231
196
232
size_t I2SClass::write (uint8_t data)
197
233
{
198
- return write (( int32_t ) data);
234
+ return write (&data, sizeof ( data) );
199
235
}
200
236
201
237
size_t I2SClass::write (const uint8_t *buffer, size_t size)
202
238
{
203
- size_t written = 0 ;
204
- int bytesPerSample = (_i_bits_per_sample) / 8 ;
239
+ __disable_irq ();
205
240
206
- size = (size / bytesPerSample) * bytesPerSample;
241
+ if (freeBuffers == 0 ) {
242
+ __enable_irq ();
243
+ return 0 ;
244
+ }
245
+
246
+ if (size > I2S_BUFFER_SIZE) {
247
+ size = I2S_BUFFER_SIZE;
248
+ }
207
249
208
- while (size) {
209
- int32_t data ;
250
+ freeBuffers--;
251
+ memcpy (&_auc_buffer[inIndex], buffer, size) ;
210
252
211
- memcpy (&data, buffer + written, bytesPerSample);
212
- written += bytesPerSample ;
213
- size -= bytesPerSample;
253
+ if (freeBuffers == 1 ) {
254
+ DMA. transfer (_i_dma_channel, &_auc_buffer[inIndex], ( void *)&_i2s-> DATA [_uc_index]. reg , size) ;
255
+ }
214
256
215
- if (write (data) == 0 ) {
216
- break ;
217
- }
257
+ if (inIndex == 0 ) {
258
+ inIndex = I2S_BUFFER_SIZE;
259
+ } else {
260
+ inIndex = 0 ;
218
261
}
219
262
220
- return written;
263
+ __enable_irq ();
264
+
265
+ return size;
221
266
}
222
267
223
268
size_t I2SClass::availableForWrite ()
224
269
{
225
- if (_i_head >= _i_tail) {
226
- return I2S_BUFFER_SIZE - 1 - _i_head + _i_tail;
227
- } else {
228
- return _i_tail - _i_head - 1 ;
229
- }
270
+ return (freeBuffers * I2S_BUFFER_SIZE);
230
271
}
231
272
232
- int I2SClass::read ( int8_t data[], int size )
273
+ void I2SClass::onTransmit ( void (*function)( void ) )
233
274
{
234
- return 0 ;
275
+ _onTransmit = function ;
235
276
}
236
277
237
- int I2SClass::write ( short data )
278
+ void I2SClass::onDmaTransferComplete ( )
238
279
{
239
- return write (( int32_t )data );
280
+ I2S. onTransferComplete ( );
240
281
}
241
282
242
- int I2SClass::write ( int data )
283
+ void I2SClass::onDmaTransferError ( )
243
284
{
244
- return write (( int32_t )data );
285
+ I2S. onTransferError ( );
245
286
}
246
287
247
- int I2SClass::write ( int32_t data )
288
+ void I2SClass::onTransferComplete ( void )
248
289
{
249
- int i = ((uint32_t )(_i_head + 1 ) % I2S_BUFFER_SIZE);
250
-
251
- if (i == _i_tail) {
252
- return 0 ;
253
- }
254
-
255
- _aui_buffer[i] = data;
256
- _i_head = i;
290
+ freeBuffers++;
257
291
292
+ int outIndex;
258
293
259
- if (_uc_index == 0 ) {
260
- _i2s-> INTENSET . bit . TXRDY0 = 1 ;
294
+ if (inIndex == 0 ) {
295
+ outIndex = I2S_BUFFER_SIZE ;
261
296
} else {
262
- _i2s-> INTENSET . bit . TXRDY1 = 1 ;
297
+ outIndex = 0 ;
263
298
}
264
299
265
- return 1 ;
266
- }
267
-
268
- void I2SClass::onService () {
300
+ DMA.transfer (_i_dma_channel, &_auc_buffer[outIndex], (void *)&_i2s->DATA [_uc_index].reg , 512 );
269
301
270
- if (_uc_index == 0 ) {
271
- if (_i2s->INTFLAG .bit .TXRDY0 ) {
272
- if (_i_head != _i_tail) {
273
- int32_t data = _aui_buffer[_i_tail];
274
- _i_tail = ((uint32_t )(_i_tail + 1 ) % I2S_BUFFER_SIZE);
275
-
276
- while (_i2s->SYNCBUSY .bit .DATA0 );
277
- _i2s->DATA [_uc_index].bit .DATA = data;
278
- } else {
279
- _i2s->INTENSET .bit .TXRDY0 = 0 ;
280
- }
281
-
282
- _i2s->INTFLAG .bit .TXRDY0 = 1 ;
283
- }
302
+ if (_onTransmit) {
303
+ _onTransmit ();
284
304
}
285
305
}
286
306
287
- extern " C" {
288
- void I2S_Handler () {
289
- I2S.onService ();
290
- }
307
+ void I2SClass::onTransferError (void )
308
+ {
291
309
}
292
310
293
311
/*
@@ -307,4 +325,7 @@ extern "C" {
307
325
+--------+--------------+-----------+-----------------+
308
326
*/
309
327
310
- I2SClass I2S (&sercom2, 0 , 9 , 1 , 0 );
328
+
329
+ // I2SClass I2S(0, GCLK_CLKCTRL_GEN_GCLK3_Val, 9, 1, 0);
330
+
331
+ I2SClass I2S (0 , GCLK_CLKCTRL_GEN_GCLK3_Val, A6, 2 , 3 );
0 commit comments