21
21
#include " I2S.h"
22
22
#include " freertos/semphr.h"
23
23
24
- // #define _USE_SYS_VIEW 1
25
- #ifdef _USE_SYS_VIEW
26
- #include " esp_sysview_trace.h" // debug
27
- // #include "esp_heap_trace.h" // debug
28
- #include " esp_log.h" // debug
29
- #endif // _USE_SYS_VIEW
24
+ #define _I2S_EVENT_QUEUE_LENGTH 100
25
+
26
+ #define _I2S_DMA_BUFFER_SIZE 512 // BUFFER SIZE must be between 8 and 1024
27
+ #define _I2S_DMA_BUFFER_COUNT 8 // BUFFER count must be between 2 and 128
30
28
31
- #define _I2S_EVENT_QUEUE_LENGTH 10
32
- #define _I2S_DMA_BUFFER_SIZE 512
33
- #define _I2S_DMA_BUFFER_COUNT 8
34
29
#define I2S_INTERFACES_COUNT SOC_I2S_NUM
35
30
36
31
#ifndef I2S_DEVICE
53
48
#define PIN_I2S_SD 26
54
49
#endif
55
50
51
+
56
52
#ifndef PIN_I2S_SD_IN
57
53
#define PIN_I2S_SD_IN 35 // 35 can be only input pin
58
54
#endif
59
55
60
-
61
56
#ifndef PIN_I2S_SD_OUT
62
57
#define PIN_I2S_SD_OUT 26
63
58
#endif
@@ -75,6 +70,15 @@ I2SClass::I2SClass(uint8_t deviceIndex, uint8_t clockGenerator, uint8_t sdPin, u
75
70
_sampleRate(0 ),
76
71
_mode(I2S_PHILIPS_MODE),
77
72
73
+ _buffer_byte_size(0 ),
74
+ _output_buffer_pointer(0 ),
75
+ _input_buffer_pointer(0 ),
76
+ _read_available(0 ),
77
+ _in_buf_semaphore(NULL ),
78
+ _out_buf_semaphore(NULL ),
79
+ _inputBuffer(NULL ),
80
+ _outputBuffer(NULL ),
81
+
78
82
_initialized(false ),
79
83
_callbackTaskHandle(NULL ),
80
84
_i2sEventQueue(NULL ),
@@ -98,6 +102,15 @@ I2SClass::I2SClass(uint8_t deviceIndex, uint8_t clockGenerator, uint8_t inSdPin,
98
102
_sampleRate(0 ),
99
103
_mode(I2S_PHILIPS_MODE),
100
104
105
+ _buffer_byte_size(0 ),
106
+ _output_buffer_pointer(0 ),
107
+ _input_buffer_pointer(0 ),
108
+ _read_available(0 ),
109
+ _in_buf_semaphore(NULL ),
110
+ _out_buf_semaphore(NULL ),
111
+ _inputBuffer(NULL ),
112
+ _outputBuffer(NULL ),
113
+
101
114
_initialized(false ),
102
115
_callbackTaskHandle(NULL ),
103
116
_i2sEventQueue(NULL ),
@@ -110,7 +123,7 @@ I2SClass::I2SClass(uint8_t deviceIndex, uint8_t clockGenerator, uint8_t inSdPin,
110
123
111
124
void I2SClass::createCallbackTask ()
112
125
{
113
- int stack_size = 3000 ;
126
+ int stack_size = 10000 ;
114
127
if (_callbackTaskHandle == NULL ){
115
128
if (_task_kill_cmd_semaphore_handle == NULL ){
116
129
_task_kill_cmd_semaphore_handle = xSemaphoreCreateBinary ();
@@ -189,16 +202,13 @@ int I2SClass::begin(int mode, long sampleRate, int bitsPerSample, bool driveCloc
189
202
pin_config.bck_io_num = _sckPin;
190
203
pin_config.ws_io_num = _fsPin;
191
204
192
- Serial.println (" I2SClass::begin foo" ); // debug
193
205
if (_mode == I2S_ADC_DAC){
194
- Serial.println (" I2SClass::begin foo adc" ); // debug
195
206
if (_bitsPerSample != 16 ){ // ADC/DAC can only work in 16-bit sample mode
196
207
Serial.println (" ERROR I2SClass::begin invalid bps for ADC/DAC" ); // debug
197
208
return 0 ; // ERR
198
209
}
199
210
i2s_mode = (esp_i2s::i2s_mode_t )(i2s_mode | esp_i2s::I2S_MODE_DAC_BUILT_IN | esp_i2s::I2S_MODE_ADC_BUILT_IN);
200
211
}else { // End of ADC/DAC mode; start of Normal mode
201
- Serial.println (" I2SClass::begin foo normal" ); // debug
202
212
if (_bitsPerSample != 16 && /* _bitsPerSample != 24 && */ _bitsPerSample != 32 ){
203
213
Serial.println (" I2S.begin(): invalid bits per second for normal mode" );
204
214
// ESP does support 24 bps, however for the compatibility
@@ -220,22 +230,39 @@ int I2SClass::begin(int mode, long sampleRate, int bitsPerSample, bool driveCloc
220
230
}
221
231
222
232
} // Normal mode
223
- Serial.println (" I2SClass::begin bar" ); // debug
224
233
esp_i2s::i2s_config_t i2s_config = {
225
234
.mode = i2s_mode,
226
235
.sample_rate = _sampleRate,
227
236
.bits_per_sample = (esp_i2s::i2s_bits_per_sample_t )_bitsPerSample,
228
237
.channel_format = esp_i2s::I2S_CHANNEL_FMT_RIGHT_LEFT,
229
- .communication_format = (esp_i2s::i2s_comm_format_t )(esp_i2s::I2S_COMM_FORMAT_STAND_I2S | esp_i2s::I2S_COMM_FORMAT_STAND_PCM_SHORT), // 0x01 | 0x04
238
+ .communication_format = (esp_i2s::i2s_comm_format_t )(esp_i2s::I2S_COMM_FORMAT_STAND_I2S | esp_i2s::I2S_COMM_FORMAT_STAND_PCM_SHORT), // 0x01 | 0x04 // default
230
239
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL2,
231
240
.dma_buf_count = _I2S_DMA_BUFFER_COUNT,
232
241
.dma_buf_len = _I2S_DMA_BUFFER_SIZE
233
242
};
234
243
244
+
245
+ _buffer_byte_size = _I2S_DMA_BUFFER_SIZE * (_bitsPerSample / 8 );
246
+ _inputBuffer = malloc (_buffer_byte_size);
247
+ _outputBuffer = malloc (_buffer_byte_size);
248
+ _output_buffer_pointer = 0 ;
249
+ _input_buffer_pointer = 0 ;
250
+ if (_inputBuffer == NULL || _outputBuffer == NULL ){
251
+ return 0 ; // ERR
252
+ }
253
+ _in_buf_semaphore = xSemaphoreCreateMutex ();
254
+ _out_buf_semaphore = xSemaphoreCreateMutex ();
255
+ // _in_buf_semaphore = xSemaphoreCreateBinary();
256
+ // _out_buf_semaphore = xSemaphoreCreateBinary();
257
+
258
+ if (_in_buf_semaphore == NULL || _out_buf_semaphore == NULL ){
259
+ return 0 ; // ERR
260
+ }
261
+ // xSemaphoreGive(_in_buf_semaphore);
262
+ // xSemaphoreGive(_out_buf_semaphore);
263
+
235
264
if (ESP_OK != esp_i2s::i2s_driver_install ((esp_i2s::i2s_port_t ) _deviceIndex, &i2s_config, _I2S_EVENT_QUEUE_LENGTH, &_i2sEventQueue)){ // Install and start i2s driver
236
265
Serial.println (" ERROR I2SClass::begin error installing i2s driver" ); // debug
237
- Serial.flush ();
238
- delay (100 );
239
266
return 0 ; // ERR
240
267
}
241
268
@@ -253,7 +280,6 @@ int I2SClass::begin(int mode, long sampleRate, int bitsPerSample, bool driveCloc
253
280
esp_i2s::adc1_config_channel_atten (adc_channel, esp_i2s::ADC_ATTEN_DB_11);
254
281
esp_i2s::i2s_adc_enable ((esp_i2s::i2s_port_t ) _deviceIndex);
255
282
}else { // End of ADC/DAC mode; start of Normal mode
256
- Serial.println (" I2SClass::begin calling set" ); // debug
257
283
if (ESP_OK != esp_i2s::i2s_set_pin ((esp_i2s::i2s_port_t ) _deviceIndex, &pin_config)) {
258
284
Serial.println (" i2s_set_pin err" );
259
285
end ();
@@ -262,6 +288,7 @@ int I2SClass::begin(int mode, long sampleRate, int bitsPerSample, bool driveCloc
262
288
}
263
289
createCallbackTask ();
264
290
_initialized = true ;
291
+
265
292
return 1 ; // OK
266
293
}
267
294
@@ -302,7 +329,6 @@ int I2SClass::setAllPins(int sckPin, int fsPin, int inSdPin, int outSdPin){
302
329
.data_in_num = _inSdPin
303
330
};
304
331
if (ESP_OK != esp_i2s::i2s_set_pin ((esp_i2s::i2s_port_t ) _deviceIndex, &pin_config)){
305
- Serial.printf (" setFullDuplex() set pins error\n " ); // debug
306
332
return 0 ; // ERR
307
333
}
308
334
}
@@ -329,10 +355,8 @@ int I2SClass::setHalfDuplex(uint8_t inSdPin, uint8_t outSdPin){
329
355
.data_in_num = _inSdPin
330
356
};
331
357
if (ESP_OK != esp_i2s::i2s_set_pin ((esp_i2s::i2s_port_t ) _deviceIndex, &pin_config)){
332
- Serial.printf (" setFullDuplex() set pins error\n " ); // debug
333
358
return 0 ; // ERR
334
359
}
335
- Serial.printf (" setFullDuplex(inSdPin=%d, outSdPin=%d) OK\n " , inSdPin, outSdPin); // debug
336
360
}
337
361
return 1 ; // OK
338
362
}
@@ -349,10 +373,8 @@ int I2SClass::setSimplex(uint8_t sdPin){
349
373
.data_in_num = _sdPin
350
374
};
351
375
if (ESP_OK != esp_i2s::i2s_set_pin ((esp_i2s::i2s_port_t ) _deviceIndex, &pin_config)){
352
- Serial.printf (" setHalfDuplex: err setting pin %d\n " , sdPin); // debug
353
376
return 0 ; // ERR
354
377
}
355
- Serial.printf (" setHalfDuplex(sdPin=%d) OK\n " , sdPin); // debug
356
378
}
357
379
return 1 ; // OK
358
380
}
@@ -374,6 +396,18 @@ void I2SClass::end()
374
396
}
375
397
_onTransmit = NULL ;
376
398
_onReceive = NULL ;
399
+ free (_inputBuffer);
400
+ free (_outputBuffer);
401
+ _inputBuffer = NULL ;
402
+ _outputBuffer = NULL ;
403
+ _buffer_byte_size = 0 ;
404
+ _output_buffer_pointer = 0 ;
405
+ _input_buffer_pointer = 0 ;
406
+ vSemaphoreDelete (_in_buf_semaphore);
407
+ vSemaphoreDelete (_out_buf_semaphore);
408
+ _in_buf_semaphore = NULL ;
409
+ _out_buf_semaphore = NULL ;
410
+
377
411
}else {
378
412
// TODO log_e with error - destroy task from inside not permitted
379
413
}
@@ -382,9 +416,7 @@ void I2SClass::end()
382
416
// available to read
383
417
int I2SClass::available ()
384
418
{
385
- // There is no actual way to tell in ESP
386
- return _I2S_DMA_BUFFER_SIZE;
387
- // uxQueueSpacesAvailable();
419
+ return _read_available;
388
420
}
389
421
390
422
union i2s_sample_t {
@@ -419,21 +451,22 @@ int I2SClass::read(void* buffer, size_t size)
419
451
return 0 ; // There was an error switching to receiver
420
452
}
421
453
}
422
- int read ;
423
- #ifdef _USE_SYS_VIEW
424
- SEGGER_SYSVIEW_Print (" i2s_read start" );
425
- #endif // _USE_SYS_VIEW
426
- esp_i2s::i2s_read ((esp_i2s::i2s_port_t ) _deviceIndex, buffer, size, (size_t *) &read , 0 );
427
- #ifdef _USE_SYS_VIEW
428
- SEGGER_SYSVIEW_Print (" i2s_read stop" );
429
- #endif // _USE_SYS_VIEW
430
-
454
+ // int read;
455
+ // esp_i2s::i2s_read((esp_i2s::i2s_port_t) _deviceIndex, buffer, size, (size_t*) &read, 0);
456
+ size_t cpy_size = size <= _read_available ? size : _read_available;
457
+ // if(_in_buf_semaphore != NULL && xSemaphoreTake(_in_buf_semaphore, portMAX_DELAY) == pdTRUE){
458
+ if (_in_buf_semaphore != NULL && xSemaphoreTake (_in_buf_semaphore, 10 ) == pdTRUE){
459
+ memcpy (buffer, _inputBuffer, cpy_size);
460
+ xSemaphoreGive (_in_buf_semaphore);
461
+ _input_buffer_pointer = (_input_buffer_pointer + cpy_size) > _buffer_byte_size ? _buffer_byte_size : _input_buffer_pointer + cpy_size;
462
+ _read_available -= cpy_size;
463
+ }
431
464
if (_mode == I2S_ADC_DAC){
432
- for (int i = 0 ; i < read / 2 ; ++i){
465
+ for (int i = 0 ; i < cpy_size / 2 ; ++i){
433
466
((uint16_t *)buffer)[i] = ((uint16_t *)buffer)[i] & 0x0FFF ;
434
467
}
435
468
}
436
- return read ;
469
+ return cpy_size ;
437
470
}
438
471
439
472
/*
@@ -450,20 +483,20 @@ size_t I2SClass::write(int32_t sample)
450
483
451
484
size_t I2SClass::write (const void *buffer, size_t size)
452
485
{
453
- // Serial.printf("I2SClass::write(): _state = %d\n",_state);
454
486
if (_state != I2S_STATE_TRANSMITTER && _state != I2S_STATE_DUPLEX) {
455
487
if (!enableTransmitter ()){
456
488
return 0 ; // There was an error switching to transmitter
457
489
}
458
490
}
459
491
size_t bytes_written;
460
- #ifdef _USE_SYS_VIEW
461
- SEGGER_SYSVIEW_Print (" i2s_write start" );
462
- #endif // _USE_SYS_VIEW
463
- esp_i2s::i2s_write ((esp_i2s::i2s_port_t ) _deviceIndex, buffer, size, &bytes_written, 0 );
464
- #ifdef _USE_SYS_VIEW
465
- SEGGER_SYSVIEW_Print (" i2s_write stop" );
466
- #endif // _USE_SYS_VIEW
492
+ // esp_i2s::i2s_write((esp_i2s::i2s_port_t) _deviceIndex, buffer, size, &bytes_written, 0);
493
+ size_t cpy_size = size <= _buffer_byte_size - _output_buffer_pointer ? size : _buffer_byte_size - _output_buffer_pointer;
494
+ if (_out_buf_semaphore != NULL && xSemaphoreTake (_out_buf_semaphore, portMAX_DELAY) == pdTRUE){
495
+ memcpy ((void *)((uint )_outputBuffer+_output_buffer_pointer), buffer, cpy_size);
496
+ xSemaphoreGive (_out_buf_semaphore);
497
+ }else {
498
+ }
499
+ _output_buffer_pointer = (_output_buffer_pointer + cpy_size) > _buffer_byte_size ? _output_buffer_pointer : _output_buffer_pointer + cpy_size;
467
500
return bytes_written;
468
501
}
469
502
@@ -491,9 +524,7 @@ size_t I2SClass::write(const uint8_t *buffer, size_t size)
491
524
492
525
int I2SClass::availableForWrite ()
493
526
{
494
- // There is no actual way to tell in ESP
495
- return _I2S_DMA_BUFFER_SIZE;
496
- // uxQueueSpacesAvailable();
527
+ return _buffer_byte_size - _output_buffer_pointer;
497
528
}
498
529
499
530
void I2SClass::onTransmit (void (*function)(void ))
@@ -513,9 +544,7 @@ void I2SClass::setBufferSize(int bufferSize)
513
544
514
545
int I2SClass::enableTransmitter ()
515
546
{
516
- Serial.printf (" I2SClass::enableTransmitter(): _state = %d\n " ,_state);
517
547
if (_state != I2S_STATE_TRANSMITTER && _state != I2S_STATE_DUPLEX){
518
- Serial.printf (" I2SClass::enableTransmitter(): change data out pin to %d\n " ,_sdPin);
519
548
esp_i2s::i2s_pin_config_t pin_config = {
520
549
.bck_io_num = _sckPin,
521
550
.ws_io_num = _fsPin,
@@ -561,48 +590,57 @@ void I2SClass::onTransferComplete()
561
590
xQueueAddToSet (_task_kill_cmd_semaphore_handle, xQueueSet);
562
591
563
592
while (true ){
564
- // Serial.printf("I2S:onTransferComplete: loop start\n");
565
593
xActivatedMember = xQueueSelectFromSet (xQueueSet, portMAX_DELAY);
566
594
if (xActivatedMember == _task_kill_cmd_semaphore_handle){
567
- Serial.printf (" I2S:onTransferComplete: received kill command, breaking from loop\n " );
568
595
xSemaphoreTake (_task_kill_cmd_semaphore_handle, 0 );
569
596
break ; // from the infinite loop
570
597
}else if (xActivatedMember == _i2sEventQueue){
571
- // Serial.printf("I2S:onTransferComplete: received Q\n");
572
598
xQueueReceive (_i2sEventQueue, &i2s_event, 0 );
573
- if ((i2s_event == esp_i2s::I2S_EVENT_TX_DONE) && (_state == I2S_STATE_DUPLEX || _state == I2S_STATE_TRANSMITTER)){
599
+ // if((i2s_event == esp_i2s::I2S_EVENT_TX_DONE) && (_state == I2S_STATE_DUPLEX || _state == I2S_STATE_TRANSMITTER)){
600
+ if (i2s_event == esp_i2s::I2S_EVENT_TX_DONE){
601
+ size_t bytes_written;
602
+ if (_out_buf_semaphore != NULL && xSemaphoreTake (_out_buf_semaphore, portMAX_DELAY) == pdTRUE){
603
+ esp_i2s::i2s_write ((esp_i2s::i2s_port_t ) _deviceIndex, _outputBuffer, _output_buffer_pointer, &bytes_written, 0 );
604
+ _output_buffer_pointer = 0 ;
605
+ if (xSemaphoreGive (_out_buf_semaphore) != pdTRUE){
606
+ // We would not expect this call to fail because we must have
607
+ // obtained the semaphore to get here.
608
+ }
609
+ }
574
610
if (_onTransmit){
575
- // Serial.printf("I2S:onTransferComplete: calling _onTransmit\n");
576
- #ifdef _USE_SYS_VIEW
577
- SEGGER_SYSVIEW_Print (" _onTransmit start" );
578
- #endif // _USE_SYS_VIEW
579
611
_onTransmit ();
580
- # ifdef _USE_SYS_VIEW
581
- SEGGER_SYSVIEW_Print ( " _onTransmit stop " );
582
- # endif // _USE_SYS_VIEW
583
- }
584
- } else if (i2s_event == esp_i2s::I2S_EVENT_RX_DONE && (_state == I2S_STATE_RECEIVER || _state == I2S_STATE_DUPLEX) ){
585
- if (_onReceive) {
586
- // Serial.printf("I2S:onTransferComplete: calling _onReceive\n") ;
587
- # ifdef _USE_SYS_VIEW
588
- SEGGER_SYSVIEW_Print ( " _onReceive start " );
589
- # endif // _USE_SYS_VIEW
590
- _onReceive ();
591
- # ifdef _USE_SYS_VIEW
592
- SEGGER_SYSVIEW_Print ( " _onReceive stop " );
593
- # endif // _USE_SYS_VIEW
594
- }
612
+ } // user callback
613
+ // }else if(i2s_event == esp_i2s::I2S_EVENT_RX_DONE && (_state == I2S_STATE_RECEIVER || _state == I2S_STATE_DUPLEX)){
614
+ } else if (i2s_event == esp_i2s::I2S_EVENT_RX_DONE){
615
+ // if(_in_buf_semaphore != NULL && xSemaphoreTake(_in_buf_semaphore, portMAX_DELAY == pdTRUE)){
616
+ if (_in_buf_semaphore != NULL && xSemaphoreTake (_in_buf_semaphore, 10 ) == pdTRUE ){
617
+ esp_i2s::i2s_read ((esp_i2s:: i2s_port_t ) _deviceIndex, _inputBuffer, _buffer_byte_size, ( size_t *) &_read_available, 0 );
618
+ _input_buffer_pointer = 0 ;
619
+ if ( xSemaphoreGive (_in_buf_semaphore) != pdTRUE){ // CRASHING HERE on first call
620
+ // We would not expect this call to fail because we must have
621
+ // obtained the semaphore to get here.
622
+ }
623
+ if (_onReceive) {
624
+ _onReceive ( );
625
+ } // user callback
626
+ } // semaphore
595
627
} // if event TX or RX
596
628
}
597
629
}
598
- Serial.printf (" xxxxxxx I2S:onTransferComplete: out of loop - kill my self xxxxxxx\n " );
599
630
_callbackTaskHandle = NULL ; // prevent secondary termination to non-existing task
600
631
vTaskDelete (NULL );
601
632
}
602
633
603
634
void I2SClass::onDmaTransferComplete (void *)
604
635
{
636
+
637
+ #ifdef _USE_SYS_VIEW
638
+ SEGGER_SYSVIEW_Print (" onTransferComplete start" );
639
+ #endif // _USE_SYS_VIEW
605
640
I2S.onTransferComplete ();
641
+ #ifdef _USE_SYS_VIEW
642
+ SEGGER_SYSVIEW_Print (" onTransferComplete stop" );
643
+ #endif // _USE_SYS_VIEW
606
644
}
607
645
608
646
#if I2S_INTERFACES_COUNT > 0
0 commit comments