@@ -8,8 +8,12 @@ I2SClass::I2SClass(SERCOM *p_sercom, uint8_t uc_index, uint8_t uc_pinSD, uint8_t
88 _uc_index(uc_index),
99 _uc_sd(uc_pinSD),
1010 _uc_sck(uc_pinSCK),
11- _uc_fs(uc_pinFS)
11+ _uc_fs(uc_pinFS),
12+
13+ _i_head(0 ),
14+ _i_tail(0 )
1215{
16+ memset (_aui_buffer, 0 , sizeof (_aui_buffer));
1317}
1418
1519int I2SClass::begin (int mode, long sampleRate, int bitsPerSample, int driveClock)
@@ -31,6 +35,7 @@ int I2SClass::begin(int mode, long sampleRate, int bitsPerSample, int driveClock
3135 case 16 :
3236 case 24 :
3337 case 32 :
38+ _i_bits_per_sample = bitsPerSample;
3439 break ;
3540
3641 default :
@@ -158,6 +163,15 @@ int I2SClass::begin(int mode, long sampleRate, int bitsPerSample, int driveClock
158163 _i2s->CTRLA .bit .SEREN1 = 1 ;
159164 }
160165
166+ NVIC_EnableIRQ (I2S_IRQn);
167+ NVIC_SetPriority (I2S_IRQn, (1 << __NVIC_PRIO_BITS) - 1 ); /* set Priority */
168+
169+ if (_uc_index == 0 ) {
170+ _i2s->INTENSET .bit .TXRDY0 = 1 ;
171+ } else {
172+ _i2s->INTENSET .bit .TXRDY1 = 1 ;
173+ }
174+
161175 return 0 ;
162176}
163177
@@ -187,17 +201,38 @@ void I2SClass::flush()
187201
188202size_t I2SClass::write (uint8_t data)
189203{
190- return write ((int )data);
204+ return write ((int32_t )data);
191205}
192206
193207size_t I2SClass::write (const uint8_t *buffer, size_t size)
194208{
195- return 0 ;
209+ size_t written = 0 ;
210+ int bytesPerSample = (_i_bits_per_sample) / 8 ;
211+
212+ size = (size / bytesPerSample) * bytesPerSample;
213+
214+ while (size) {
215+ int32_t data;
216+
217+ memcpy (&data, buffer + written, bytesPerSample);
218+ written += bytesPerSample;
219+ size -= bytesPerSample;
220+
221+ if (write (data) == 0 ) {
222+ break ;
223+ }
224+ }
225+
226+ return written;
196227}
197228
198229size_t I2SClass::availableForWrite ()
199230{
200- return 0 ;
231+ if (_i_head >= _i_tail) {
232+ return I2S_BUFFER_SIZE - 1 - _i_head + _i_tail;
233+ } else {
234+ return _i_tail - _i_head - 1 ;
235+ }
201236}
202237
203238int I2SClass::read (int8_t data[], int size)
@@ -207,28 +242,51 @@ int I2SClass::read(int8_t data[], int size)
207242
208243int I2SClass::write (short data)
209244{
210- return write ((int )data);
245+ return write ((int32_t )data);
211246}
212247
213248int I2SClass::write (int data)
214249{
215- if (_uc_index == 0 ) {
216- while (!_i2s->INTFLAG .bit .TXRDY0 );
217- while (_i2s->SYNCBUSY .bit .DATA0 );
218- } else {
219- while (!_i2s->INTFLAG .bit .TXRDY1 );
220- while (_i2s->SYNCBUSY .bit .DATA1 );
250+ return write ((int32_t )data);
251+ }
252+
253+ int I2SClass::write (int32_t data)
254+ {
255+ int i = ((uint32_t )(_i_head + 1 ) % I2S_BUFFER_SIZE);
256+
257+ if (i == _i_tail) {
258+ return 0 ;
221259 }
222260
223- _i2s->DATA [_uc_index].bit .DATA = data;
261+ _aui_buffer[i] = data;
262+ _i_head = i;
263+
264+ return 1 ;
265+ }
266+
267+ void I2SClass::onService () {
224268
225269 if (_uc_index == 0 ) {
226- _i2s->INTFLAG .bit .TXRDY0 = 1 ;
227- } else {
228- _i2s->INTFLAG .bit .TXRDY1 = 1 ;
270+ if (_i2s->INTFLAG .bit .TXRDY0 ) {
271+ int32_t data = 0 ;
272+
273+ if (_i_head != _i_tail) {
274+ data = _aui_buffer[_i_tail];
275+ _i_tail = ((uint32_t )(_i_tail + 1 ) % I2S_BUFFER_SIZE);
276+ }
277+
278+ while (_i2s->SYNCBUSY .bit .DATA0 );
279+ _i2s->DATA [_uc_index].bit .DATA = data;
280+
281+ _i2s->INTFLAG .bit .TXRDY0 = 1 ;
282+ }
229283 }
284+ }
230285
231- return 1 ;
286+ extern " C" {
287+ void I2S_Handler () {
288+ I2S.onService ();
289+ }
232290}
233291
234292/*
0 commit comments