@@ -47,11 +47,13 @@ I2SClass::I2SClass(uint8_t deviceIndex, uint8_t clockGenerator, uint8_t sdPin, u
4747
4848int I2SClass::begin (int mode, long sampleRate, int bitsPerSample)
4949{
50+ // master mode (driving clock and frame select pins - output)
5051 return begin (mode, sampleRate, bitsPerSample, true );
5152}
5253
5354int I2SClass::begin (int mode, int bitsPerSample)
5455{
56+ // slave mode (not driving clock and frame select pin - input)
5557 return begin (mode, 0 , bitsPerSample, false );
5658}
5759
@@ -68,6 +70,7 @@ int I2SClass::begin(int mode, long sampleRate, int bitsPerSample, bool driveCloc
6870 break ;
6971
7072 default :
73+ // invalid mode
7174 return 1 ;
7275 }
7376
@@ -79,14 +82,17 @@ int I2SClass::begin(int mode, long sampleRate, int bitsPerSample, bool driveCloc
7982 break ;
8083
8184 default :
85+ // invalid bits per sample
8286 return 1 ;
8387 }
8488
89+ // try to allocate a DMA channel
8590 DMA.begin ();
8691
8792 _dmaChannel = DMA.allocateChannel ();
8893
8994 if (_dmaChannel < 0 ) {
95+ // no DMA channel available
9096 return 1 ;
9197 }
9298
@@ -101,15 +107,18 @@ int I2SClass::begin(int mode, long sampleRate, int bitsPerSample, bool driveCloc
101107 _beginCount++;
102108
103109 if (driveClock) {
110+ // set up clock
104111 enableClock (sampleRate * 2 * bitsPerSample);
105112
106113 i2sd.setSerialClockSelectMasterClockDiv (_deviceIndex);
107114 i2sd.setFrameSyncSelectSerialClockDiv (_deviceIndex);
108115 } else {
116+ // use input signal from SCK and FS pins
109117 i2sd.setSerialClockSelectPin (_deviceIndex);
110118 i2sd.setFrameSyncSelectPin (_deviceIndex);
111119 }
112120
121+ // disable device before continuing
113122 i2sd.disable ();
114123
115124 if (mode == I2S_PHILIPS_MODE) {
@@ -119,6 +128,7 @@ int I2SClass::begin(int mode, long sampleRate, int bitsPerSample, bool driveCloc
119128 }
120129 i2sd.setNumberOfSlots (_deviceIndex, 1 );
121130 i2sd.setSlotSize (_deviceIndex, bitsPerSample);
131+ i2sd.setDataSize (_deviceIndex, bitsPerSample);
122132
123133 pinPeripheral (_sckPin, PIO_COM);
124134 pinPeripheral (_fsPin, PIO_COM);
@@ -133,6 +143,7 @@ int I2SClass::begin(int mode, long sampleRate, int bitsPerSample, bool driveCloc
133143
134144 pinPeripheral (_sdPin, PIO_COM);
135145
146+ // done configure enable
136147 i2sd.enable ();
137148
138149 _doubleBuffer.reset ();
@@ -152,6 +163,7 @@ void I2SClass::end()
152163 i2sd.disableSerializer (_deviceIndex);
153164 i2sd.disableClockUnit (_deviceIndex);
154165
166+ // set the pins back to input mode
155167 pinMode (_sdPin, INPUT);
156168 pinMode (_fsPin, INPUT);
157169 pinMode (_sckPin, INPUT);
@@ -183,10 +195,12 @@ int I2SClass::available()
183195 avail = _doubleBuffer.available ();
184196
185197 if (_dmaTransferInProgress == false && _doubleBuffer.available () == 0 ) {
198+ // no DMA transfer in progress, start a receive process
186199 _dmaTransferInProgress = true ;
187200
188201 DMA.transfer (_dmaChannel, i2sd.data (_deviceIndex), _doubleBuffer.data (), _doubleBuffer.availableForWrite ());
189202
203+ // switch to the next buffer for user output (will be empty)
190204 _doubleBuffer.swap ();
191205 }
192206
@@ -198,24 +212,37 @@ int I2SClass::available()
198212 return avail;
199213}
200214
215+ union i2s_sample_t {
216+ uint8_t b8;
217+ int16_t b16;
218+ int32_t b32;
219+ };
220+
201221int I2SClass::read ()
202222{
203- int sample = 0 ;
223+ i2s_sample_t sample;
224+
225+ sample.b32 = 0 ;
204226
205227 read (&sample, _bitsPerSample / 8 );
206228
207- if (_bitsPerSample == 16 && (sample & 0x8000 )) {
208- // sign extend value
209- sample |= 0xffff0000 ;
229+ if (_bitsPerSample == 32 ) {
230+ return sample.b32 ;
231+ } else if (_bitsPerSample == 16 ) {
232+ return sample.b16 ;
233+ } else if (_bitsPerSample == 8 ) {
234+ return sample.b8 ;
235+ } else {
236+ return 0 ;
210237 }
211-
212- return sample;
213238}
214239
215240int I2SClass::peek ()
216241{
217242 uint8_t enableInterrupts = ((__get_PRIMASK () & 0x1 ) == 0 );
218- int sample = 0 ;
243+ i2s_sample_t sample;
244+
245+ sample.b32 = 0 ;
219246
220247 // disable interrupts,
221248 __disable_irq ();
@@ -227,16 +254,20 @@ int I2SClass::peek()
227254 __enable_irq ();
228255 }
229256
230- if (_bitsPerSample == 16 && (sample & 0x8000 )) {
231- // sign extend value
232- sample |= 0xffff0000 ;
257+ if (_bitsPerSample == 32 ) {
258+ return sample.b32 ;
259+ } else if (_bitsPerSample == 16 ) {
260+ return sample.b16 ;
261+ } else if (_bitsPerSample == 8 ) {
262+ return sample.b8 ;
263+ } else {
264+ return 0 ;
233265 }
234-
235- return sample;
236266}
237267
238268void I2SClass::flush ()
239269{
270+ // do nothing, writes are DMA triggered
240271}
241272
242273size_t I2SClass::write (uint8_t data)
@@ -285,10 +316,12 @@ int I2SClass::read(void* buffer, size_t size)
285316 int read = _doubleBuffer.read (buffer, size);
286317
287318 if (_dmaTransferInProgress == false && _doubleBuffer.available () == 0 ) {
319+ // no DMA transfer in progress, start a receive process
288320 _dmaTransferInProgress = true ;
289321
290322 DMA.transfer (_dmaChannel, i2sd.data (_deviceIndex), _doubleBuffer.data (), _doubleBuffer.availableForWrite ());
291323
324+ // switch to the next buffer for user output (will be empty)
292325 _doubleBuffer.swap ();
293326 }
294327
@@ -311,6 +344,7 @@ size_t I2SClass::write(int32_t sample)
311344 enableTransmitter ();
312345 }
313346
347+ // this is a blocking write
314348 while (!i2sd.txReady (_deviceIndex));
315349
316350 i2sd.writeData (_deviceIndex, sample);
@@ -335,10 +369,12 @@ size_t I2SClass::write(const void *buffer, size_t size)
335369 written = _doubleBuffer.write (buffer, size);
336370
337371 if (_dmaTransferInProgress == false && _doubleBuffer.available ()) {
372+ // no DMA transfer in progress, start a transmit process
338373 _dmaTransferInProgress = true ;
339374
340375 DMA.transfer (_dmaChannel, _doubleBuffer.data (), i2sd.data (_deviceIndex), _doubleBuffer.available ());
341376
377+ // switch to the next buffer for input
342378 _doubleBuffer.swap ();
343379 }
344380
@@ -362,16 +398,19 @@ void I2SClass::onReceive(void(*function)(void))
362398
363399void I2SClass::enableClock (int divider)
364400{
401+ // configure the clock divider
365402 while (GCLK->STATUS .bit .SYNCBUSY );
366403 GCLK->GENDIV .bit .ID = _clockGenerator;
367404 GCLK->GENDIV .bit .DIV = SystemCoreClock / divider;
368405
406+ // use the DFLL as the source
369407 while (GCLK->STATUS .bit .SYNCBUSY );
370408 GCLK->GENCTRL .bit .ID = _clockGenerator;
371409 GCLK->GENCTRL .bit .SRC = GCLK_GENCTRL_SRC_DFLL48M_Val;
372410 GCLK->GENCTRL .bit .IDC = 1 ;
373411 GCLK->GENCTRL .bit .GENEN = 1 ;
374412
413+ // enable
375414 while (GCLK->STATUS .bit .SYNCBUSY );
376415 GCLK->CLKCTRL .bit .ID = i2sd.glckId (_deviceIndex);
377416 GCLK->CLKCTRL .bit .GEN = _clockGenerator;
@@ -427,26 +466,39 @@ void I2SClass::enableReceiver()
427466void I2SClass::onTransferComplete (void )
428467{
429468 if (_state == I2S_STATE_TRANSMITTER) {
469+ // transmit complete
470+
430471 if (_doubleBuffer.available ()) {
472+ // output is available to transfer, start the DMA process for the current buffer
473+
431474 DMA.transfer (_dmaChannel, _doubleBuffer.data (), i2sd.data (_deviceIndex), _doubleBuffer.available ());
432475
476+ // swap to the next user buffer for input
433477 _doubleBuffer.swap ();
434478 } else {
479+ // no user data buffered to send
435480 _dmaTransferInProgress = false ;
436481 }
437482
483+ // call the users transmit callback if provided
438484 if (_onTransmit) {
439485 _onTransmit ();
440486 }
441487 } else {
488+ // receive complete
489+
442490 if (_doubleBuffer.available () == 0 ) {
491+ // the user has read all the current input, start the DMA process to fill it again
443492 DMA.transfer (_dmaChannel, i2sd.data (_deviceIndex), _doubleBuffer.data (), _doubleBuffer.availableForWrite ());
444493
494+ // swap to the next buffer that has previously been filled, so that the user can read it
445495 _doubleBuffer.swap (_doubleBuffer.availableForWrite ());
446496 } else {
497+ // user has not read current data, no free buffer to transfer into
447498 _dmaTransferInProgress = false ;
448499 }
449500
501+ // call the users receveive callback if provided
450502 if (_onReceive) {
451503 _onReceive ();
452504 }
0 commit comments