@@ -8,8 +8,12 @@ I2SClass::I2SClass(SERCOM *p_sercom, uint8_t uc_index, uint8_t uc_pinSD, uint8_t
8
8
_uc_index(uc_index),
9
9
_uc_sd(uc_pinSD),
10
10
_uc_sck(uc_pinSCK),
11
- _uc_fs(uc_pinFS)
11
+ _uc_fs(uc_pinFS),
12
+
13
+ _i_head(0 ),
14
+ _i_tail(0 )
12
15
{
16
+ memset (_aui_buffer, 0 , sizeof (_aui_buffer));
13
17
}
14
18
15
19
int 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
31
35
case 16 :
32
36
case 24 :
33
37
case 32 :
38
+ _i_bits_per_sample = bitsPerSample;
34
39
break ;
35
40
36
41
default :
@@ -158,6 +163,15 @@ int I2SClass::begin(int mode, long sampleRate, int bitsPerSample, int driveClock
158
163
_i2s->CTRLA .bit .SEREN1 = 1 ;
159
164
}
160
165
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
+
161
175
return 0 ;
162
176
}
163
177
@@ -187,17 +201,38 @@ void I2SClass::flush()
187
201
188
202
size_t I2SClass::write (uint8_t data)
189
203
{
190
- return write ((int )data);
204
+ return write ((int32_t )data);
191
205
}
192
206
193
207
size_t I2SClass::write (const uint8_t *buffer, size_t size)
194
208
{
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;
196
227
}
197
228
198
229
size_t I2SClass::availableForWrite ()
199
230
{
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
+ }
201
236
}
202
237
203
238
int I2SClass::read (int8_t data[], int size)
@@ -207,28 +242,51 @@ int I2SClass::read(int8_t data[], int size)
207
242
208
243
int I2SClass::write (short data)
209
244
{
210
- return write ((int )data);
245
+ return write ((int32_t )data);
211
246
}
212
247
213
248
int I2SClass::write (int data)
214
249
{
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 ;
221
259
}
222
260
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 () {
224
268
225
269
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
+ }
229
283
}
284
+ }
230
285
231
- return 1 ;
286
+ extern " C" {
287
+ void I2S_Handler () {
288
+ I2S.onService ();
289
+ }
232
290
}
233
291
234
292
/*
0 commit comments