11#include < Arduino.h>
22#include < wiring_private.h>
33
4+ #include " utility/DMA.h"
5+
46#include " I2S.h"
57
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) :
89 _uc_index(uc_index),
10+ _uc_clock_generator(uc_clock_generator),
911 _uc_sd(uc_pinSD),
1012 _uc_sck(uc_pinSCK),
1113 _uc_fs(uc_pinFS),
1214
13- _i_head(0 ),
14- _i_tail(0 )
15+ _i_dma_channel(-1 ),
16+ freeBuffers(2 ),
17+ inIndex(0 ),
18+
19+ _onTransmit(NULL )
1520{
16- memset (_aui_buffer, 0 , sizeof (_aui_buffer));
1721}
1822
1923int 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
3539 case 16 :
3640 case 24 :
3741 case 32 :
38- _i_bits_per_sample = bitsPerSample;
3942 break ;
4043
4144 default :
4245 Serial.println (" invalid bits per sample" );
4346 return 1 ;
4447 }
4548
49+ DMA.begin ();
50+
51+ _i_dma_channel = DMA.allocateChannel ();
52+
53+ if (_i_dma_channel < 0 ) {
54+ return 1 ;
55+ }
56+
4657 while (_i2s->SYNCBUSY .bit .SWRST );
4758 _i2s->CTRLA .bit .SWRST = 1 ;
4859
4960 PM->APBCMASK .reg |= PM_APBCMASK_I2S;
5061
5162 while (GCLK->STATUS .bit .SYNCBUSY );
52- GCLK->GENDIV .bit .ID = GCLK_CLKCTRL_GEN_GCLK3_Val ;
63+ GCLK->GENDIV .bit .ID = _uc_clock_generator ;
5364 GCLK->GENDIV .bit .DIV = SystemCoreClock / (sampleRate * 2 * bitsPerSample);
5465
5566 while (GCLK->STATUS .bit .SYNCBUSY );
56- GCLK->GENCTRL .bit .ID = GCLK_CLKCTRL_GEN_GCLK3_Val ;
67+ GCLK->GENCTRL .bit .ID = _uc_clock_generator ;
5768 GCLK->GENCTRL .bit .SRC = GCLK_GENCTRL_SRC_DFLL48M_Val;
5869 GCLK->GENCTRL .bit .IDC = 1 ;
5970 GCLK->GENCTRL .bit .GENEN = 1 ;
6071
6172 while (GCLK->STATUS .bit .SYNCBUSY );
6273 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 ;
6475 GCLK->CLKCTRL .bit .CLKEN = 1 ;
6576
6677 while (GCLK->STATUS .bit .SYNCBUSY );
@@ -163,8 +174,33 @@ int I2SClass::begin(int mode, long sampleRate, int bitsPerSample, int driveClock
163174 _i2s->CTRLA .bit .SEREN1 = 1 ;
164175 }
165176
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+ }
168204
169205 return 0 ;
170206}
@@ -195,99 +231,81 @@ void I2SClass::flush()
195231
196232size_t I2SClass::write (uint8_t data)
197233{
198- return write (( int32_t ) data);
234+ return write (&data, sizeof ( data) );
199235}
200236
201237size_t I2SClass::write (const uint8_t *buffer, size_t size)
202238{
203- size_t written = 0 ;
204- int bytesPerSample = (_i_bits_per_sample) / 8 ;
239+ __disable_irq ();
205240
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+ }
207249
208- while (size) {
209- int32_t data ;
250+ freeBuffers--;
251+ memcpy (&_auc_buffer[inIndex], buffer, size) ;
210252
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+ }
214256
215- if (write (data) == 0 ) {
216- break ;
217- }
257+ if (inIndex == 0 ) {
258+ inIndex = I2S_BUFFER_SIZE;
259+ } else {
260+ inIndex = 0 ;
218261 }
219262
220- return written;
263+ __enable_irq ();
264+
265+ return size;
221266}
222267
223268size_t I2SClass::availableForWrite ()
224269{
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);
230271}
231272
232- int I2SClass::read ( int8_t data[], int size )
273+ void I2SClass::onTransmit ( void (*function)( void ) )
233274{
234- return 0 ;
275+ _onTransmit = function ;
235276}
236277
237- int I2SClass::write ( short data )
278+ void I2SClass::onDmaTransferComplete ( )
238279{
239- return write (( int32_t )data );
280+ I2S. onTransferComplete ( );
240281}
241282
242- int I2SClass::write ( int data )
283+ void I2SClass::onDmaTransferError ( )
243284{
244- return write (( int32_t )data );
285+ I2S. onTransferError ( );
245286}
246287
247- int I2SClass::write ( int32_t data )
288+ void I2SClass::onTransferComplete ( void )
248289{
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++;
257291
292+ int outIndex;
258293
259- if (_uc_index == 0 ) {
260- _i2s-> INTENSET . bit . TXRDY0 = 1 ;
294+ if (inIndex == 0 ) {
295+ outIndex = I2S_BUFFER_SIZE ;
261296 } else {
262- _i2s-> INTENSET . bit . TXRDY1 = 1 ;
297+ outIndex = 0 ;
263298 }
264299
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 );
269301
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 ();
284304 }
285305}
286306
287- extern " C" {
288- void I2S_Handler () {
289- I2S.onService ();
290- }
307+ void I2SClass::onTransferError (void )
308+ {
291309}
292310
293311/*
@@ -307,4 +325,7 @@ extern "C" {
307325+--------+--------------+-----------+-----------------+
308326*/
309327
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