Skip to content

Commit cb6da04

Browse files
committed
Pre-release changes
1 parent f45e5ba commit cb6da04

File tree

2 files changed

+148
-107
lines changed

2 files changed

+148
-107
lines changed

libraries/I2S/src/I2S.cpp

+137-102
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
#include "I2S.h"
2222
#include "freertos/semphr.h"
2323

24-
2524
#define _I2S_EVENT_QUEUE_LENGTH 16
2625
#define _I2S_DMA_BUFFER_COUNT 4 // BUFFER COUNT must be between 2 and 128
2726
#define I2S_INTERFACES_COUNT SOC_I2S_NUM
@@ -94,7 +93,7 @@ I2SClass::I2SClass(uint8_t deviceIndex, uint8_t clockGenerator, uint8_t inSdPin,
9493

9594
int I2SClass::createCallbackTask()
9695
{
97-
int stack_size = 15000;
96+
int stack_size = 10000;
9897
if(_callbackTaskHandle == NULL){
9998
if(_task_kill_cmd_semaphore_handle == NULL){
10099
_task_kill_cmd_semaphore_handle = xSemaphoreCreateBinary();
@@ -129,9 +128,7 @@ void I2SClass::destroyCallbackTask()
129128
}
130129
vSemaphoreDelete(_task_kill_cmd_semaphore_handle); // delete semaphore after usage
131130
_task_kill_cmd_semaphore_handle = NULL; // prevent usage of uninitialized (deleted) semaphore
132-
}else{ // callback handle check
133-
log_e("Could not destroy callback");
134-
}
131+
} // callback handle check
135132
}
136133

137134
int I2SClass::_installDriver(){
@@ -187,17 +184,19 @@ int I2SClass::_installDriver(){
187184
.dma_buf_count = _I2S_DMA_BUFFER_COUNT,
188185
.dma_buf_len = _i2s_dma_buffer_size
189186
};
190-
191-
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
192-
log_e("ERROR could not install i2s driver");
193-
return 0; // ERR
194-
}
195-
if(_i2sEventQueue == NULL){
196-
log_e("ERROR i2s driver did not create event queue");
197-
//return 0; // ERR
198-
}else{
199-
log_d("DEBUG MSG i2s event queue exists");
200-
}
187+
// Install and start i2s driver
188+
while(ESP_OK != esp_i2s::i2s_driver_install((esp_i2s::i2s_port_t) _deviceIndex, &i2s_config, _I2S_EVENT_QUEUE_LENGTH, &_i2sEventQueue)){
189+
// double buffer size
190+
log_w("WARNING i2s driver install failed; Trying to increase I2S DMA buffer size from %d to %d\n", _i2s_dma_buffer_size, 2*_i2s_dma_buffer_size);
191+
if(2*_i2s_dma_buffer_size <= 1024){
192+
setBufferSize(2*_i2s_dma_buffer_size);
193+
}else if(_i2s_dma_buffer_size < 1024){
194+
setBufferSize(1024);
195+
}else{
196+
log_e("ERROR i2s driver install failed");
197+
return 0; // ERR
198+
}
199+
} //try installing with increasing size
201200

202201
if(_mode == I2S_ADC_DAC){
203202
esp_i2s::adc_unit_t adc_unit = (esp_i2s::adc_unit_t) 1;
@@ -224,7 +223,7 @@ int I2SClass::_installDriver(){
224223
return 1; // OK
225224
}
226225

227-
int I2SClass::begin(int mode, long sampleRate, int bitsPerSample)
226+
int I2SClass::begin(int mode, int sampleRate, int bitsPerSample)
228227
{
229228
// master mode (driving clock and frame select pins - output)
230229
return begin(mode, sampleRate, bitsPerSample, true);
@@ -233,14 +232,14 @@ int I2SClass::begin(int mode, long sampleRate, int bitsPerSample)
233232
int I2SClass::begin(int mode, int bitsPerSample)
234233
{
235234
log_e("ERROR I2SClass::begin Audio in Slave mode is not implemented for ESP\n\
236-
Note: If it is NOT your intention to initialize in slave mode, you are probably missing <sampleRate> parameter - see the declaration below\
235+
Note: If it is NOT your intention to initialize in slave mode, you are probably missing <sampleRate> parameter - see the declaration below\n\
237236
\tint I2SClass::begin(int mode, long sampleRate, int bitsPerSample)");
238237
return 0; // ERR
239238
// slave mode (not driving clock and frame select pin - input)
240239
//return begin(mode, 0, bitsPerSample, false);
241240
}
242241

243-
int I2SClass::begin(int mode, long sampleRate, int bitsPerSample, bool driveClock)
242+
int I2SClass::begin(int mode, int sampleRate, int bitsPerSample, bool driveClock)
244243
{
245244
if(_initialized){
246245
end();
@@ -279,10 +278,12 @@ int I2SClass::begin(int mode, long sampleRate, int bitsPerSample, bool driveCloc
279278
}
280279

281280
if(!_installDriver()){
281+
_initialized = false;
282282
return 0; // ERR
283283
}
284284

285285
if(!createCallbackTask()){
286+
_initialized = false;
286287
return 0; // ERR
287288
}
288289

@@ -389,21 +390,11 @@ int I2SClass::setAllPins(int sckPin, int fsPin, int inSdPin, int outSdPin){
389390
}
390391

391392
int I2SClass::setDuplex(){
392-
/*
393-
if(_inSdPin < 0 || _outSdPin < 0){
394-
log_e("I2S cannot set Duplex - one or both pins not set\n input pin = %d\toutput pin = %d", _inSdPin, _outSdPin);
395-
return 0; // ERR
396-
}
397-
*/
398393
_state = I2S_STATE_DUPLEX;
399394
return 1;
400395
}
401396

402397
int I2SClass::setSimplex(){
403-
if(_sdPin < 0){
404-
log_e("I2S cannot set Simplex - shared data pin is not set\n data pin = %d", _sdPin);
405-
return 0; // ERR
406-
}
407398
_state = I2S_STATE_IDLE;
408399
return 1;
409400
}
@@ -432,9 +423,15 @@ int I2SClass::getDataOutPin(){
432423
return _outSdPin;
433424
}
434425

435-
int I2SClass::_uninstallDriver(){
436-
// TODO
437-
return 1; // Ok
426+
void I2SClass::_uninstallDriver(){
427+
if(_mode == I2S_ADC_DAC){
428+
esp_i2s::i2s_adc_disable((esp_i2s::i2s_port_t) _deviceIndex);
429+
}
430+
esp_i2s::i2s_driver_uninstall((esp_i2s::i2s_port_t) _deviceIndex);
431+
432+
if(_state != I2S_STATE_DUPLEX){
433+
_state = I2S_STATE_IDLE;
434+
}
438435
}
439436

440437
void I2SClass::end()
@@ -443,15 +440,8 @@ void I2SClass::end()
443440
destroyCallbackTask();
444441

445442
if(_initialized){
446-
447-
if(_mode == I2S_ADC_DAC){
448-
esp_i2s::i2s_adc_disable((esp_i2s::i2s_port_t) _deviceIndex);
449-
}
450-
esp_i2s::i2s_driver_uninstall((esp_i2s::i2s_port_t) _deviceIndex);
443+
_uninstallDriver();
451444
_initialized = false;
452-
if(_state != I2S_STATE_DUPLEX){
453-
_state = I2S_STATE_IDLE;
454-
}
455445
}
456446
_onTransmit = NULL;
457447
_onReceive = NULL;
@@ -538,20 +528,49 @@ size_t I2SClass::write(const uint8_t *buffer, size_t size)
538528
return write((const void*)buffer, size);
539529
}
540530

541-
size_t I2SClass::write(const void *buffer, size_t size)
531+
// blocking version of write
532+
// TODO add timeout
533+
size_t I2SClass::write_blocking(const void *buffer, size_t size)
534+
{
535+
if (_state != I2S_STATE_TRANSMITTER && _state != I2S_STATE_DUPLEX) {
536+
if(!enableTransmitter()){
537+
return 0; // There was an error switching to transmitter
538+
}
539+
}
540+
// TODO add timeout
541+
while(availableForWrite() < size){
542+
yield();
543+
}
544+
if(pdTRUE == xRingbufferSend(_output_ring_buffer, buffer, size, 10)){
545+
return size;
546+
}else{
547+
return 0;
548+
}
549+
}
550+
551+
// non-blocking version of write
552+
size_t I2SClass::write_nonblocking(const void *buffer, size_t size)
542553
{
543554
if (_state != I2S_STATE_TRANSMITTER && _state != I2S_STATE_DUPLEX) {
544555
if(!enableTransmitter()){
545556
return 0; // There was an error switching to transmitter
546557
}
547558
}
559+
if(availableForWrite() < size){
560+
flush();
561+
}
548562
if(pdTRUE == xRingbufferSend(_output_ring_buffer, buffer, size, 10)){
549563
return size;
550564
}else{
551565
return 0;
552566
}
553567
}
554568

569+
size_t I2SClass::write(const void *buffer, size_t size){
570+
//return write_blocking(buffer, size);
571+
return write_nonblocking(buffer, size);
572+
}
573+
555574
int I2SClass::peek()
556575
{
557576
// TODO
@@ -596,10 +615,9 @@ int I2SClass::setBufferSize(int bufferSize)
596615
if(bufferSize >= 8 && bufferSize <= 1024){
597616
_i2s_dma_buffer_size = bufferSize;
598617
if(_initialized){
599-
end();
600-
return begin(_mode, _sampleRate, _bitsPerSample, _driveClock);
618+
_uninstallDriver();
619+
return _installDriver();
601620
}
602-
603621
return 1; // OK
604622
}else{
605623
return 0; // ERR
@@ -628,84 +646,101 @@ int I2SClass::enableReceiver()
628646
return 1; // Ok
629647
}
630648

649+
void I2SClass::_tx_done_routine(uint8_t* prev_item){
650+
static bool prev_item_valid = false;
651+
const size_t single_dma_buf = _i2s_dma_buffer_size*(_bitsPerSample/8);
652+
static size_t item_size = 0;
653+
static size_t prev_item_size = 0;
654+
static void *item = NULL;
655+
static int prev_item_offset = 0;
656+
static size_t bytes_written;
657+
658+
if(prev_item_valid){ // use item from previous round
659+
esp_i2s::i2s_write((esp_i2s::i2s_port_t) _deviceIndex, prev_item+prev_item_offset, prev_item_size, &bytes_written, 0);
660+
if(prev_item_size == bytes_written){
661+
prev_item_valid = false;
662+
} // write size check
663+
prev_item_offset = bytes_written;
664+
prev_item_size -= bytes_written;
665+
} // prev_item_valid
666+
667+
if(_buffer_byte_size - xRingbufferGetCurFreeSize(_output_ring_buffer) >= single_dma_buf){ // fill up the I2S DMA buffer
668+
bytes_written = 0;
669+
item_size = 0;
670+
//if(_buffer_byte_size - xRingbufferGetCurFreeSize(_output_ring_buffer) >= _i2s_dma_buffer_size*(_bitsPerSample/8)){ // don't read from almost empty buffer
671+
item = xRingbufferReceiveUpTo(_output_ring_buffer, &item_size, pdMS_TO_TICKS(1000), single_dma_buf);
672+
if (item != NULL){
673+
esp_i2s::i2s_write((esp_i2s::i2s_port_t) _deviceIndex, item, item_size, &bytes_written, 0);
674+
if(item_size != bytes_written){ // save item that was not written correctly for later
675+
memcpy(prev_item, (void*)&((uint8_t*)item)[bytes_written], item_size-bytes_written);
676+
prev_item_size = item_size - bytes_written;
677+
prev_item_offset = 0;
678+
prev_item_valid = true;
679+
} // save item that was not written correctly for later
680+
vRingbufferReturnItem(_output_ring_buffer, item);
681+
} // Check received item
682+
} // don't read from almost empty buffer
683+
684+
if(_onTransmit){
685+
_onTransmit();
686+
} // user callback
687+
}
688+
689+
void I2SClass::_rx_done_routine(){
690+
static size_t bytes_read;
691+
const size_t single_dma_buf = _i2s_dma_buffer_size*(_bitsPerSample/8);
692+
uint8_t *_inputBuffer = (uint8_t*)malloc(_i2s_dma_buffer_size*4);
693+
694+
size_t avail = xRingbufferGetCurFreeSize(_input_ring_buffer);
695+
esp_i2s::i2s_read((esp_i2s::i2s_port_t) _deviceIndex, _inputBuffer, avail <= single_dma_buf ? avail : single_dma_buf, (size_t*) &bytes_read, 0);
696+
if(pdTRUE != xRingbufferSend(_input_ring_buffer, _inputBuffer, bytes_read, 0)){
697+
log_w("I2S failed to send item from DMA to internal buffer\n");
698+
}else{
699+
if (_onReceive) {
700+
_onReceive();
701+
} // user callback
702+
} // xRingbufferSendComplete
703+
free(_inputBuffer);
704+
}
705+
706+
631707
void I2SClass::onTransferComplete()
632708
{
709+
uint8_t prev_item[_i2s_dma_buffer_size*4];
633710
static QueueSetHandle_t xQueueSet;
634-
const size_t single_dma_buf = _i2s_dma_buffer_size*(_bitsPerSample/8);
635711
QueueSetMemberHandle_t xActivatedMember;
636-
esp_i2s::i2s_event_type_t i2s_event;
637-
size_t item_size = 0;
638-
size_t prev_item_size = 0;
639-
void *item = NULL;
640-
bool prev_item_valid = false;
641-
size_t bytes_written, bytes_read;
642-
int prev_item_offset = 0;
643-
uint8_t prev_item[_i2s_dma_buffer_size*4];
644-
uint8_t _inputBuffer[_i2s_dma_buffer_size*4];
645-
712+
esp_i2s::i2s_event_t i2s_event;
646713
xQueueSet = xQueueCreateSet(sizeof(i2s_event)*_I2S_EVENT_QUEUE_LENGTH + 1);
647714
configASSERT(xQueueSet);
648715
configASSERT(_i2sEventQueue);
649716
xQueueAddToSet(_i2sEventQueue, xQueueSet);
650717
xQueueAddToSet(_task_kill_cmd_semaphore_handle, xQueueSet);
651718

652719
while(true){
653-
xActivatedMember = xQueueSelectFromSet(xQueueSet, portMAX_DELAY);
720+
//xActivatedMember = xQueueSelectFromSet(xQueueSet, portMAX_DELAY); // defaul
721+
xActivatedMember = xQueueSelectFromSet(xQueueSet, 5); // hack
722+
// TODO try just queue receive at the timeout
654723
if(xActivatedMember == _task_kill_cmd_semaphore_handle){
655724
xSemaphoreTake(_task_kill_cmd_semaphore_handle, 0);
656725
break; // from the infinite loop
657-
}else if(xActivatedMember == _i2sEventQueue){
658-
xQueueReceive(_i2sEventQueue, &i2s_event, 0);
659-
if(i2s_event == esp_i2s::I2S_EVENT_TX_DONE){
660-
if(prev_item_valid){ // use item from previous round
661-
esp_i2s::i2s_write((esp_i2s::i2s_port_t) _deviceIndex, prev_item+prev_item_offset, prev_item_size, &bytes_written, 0);
662-
if(prev_item_size == bytes_written){
663-
prev_item_valid = false;
664-
} // write size check
665-
prev_item_offset = bytes_written;
666-
prev_item_size -= bytes_written;
667-
} // prev_item_valid
668-
669-
if(_buffer_byte_size - xRingbufferGetCurFreeSize(_output_ring_buffer) >= single_dma_buf){ // fill up the I2S DMA buffer
670-
671-
bytes_written = 0;
672-
item_size = 0;
673-
item = xRingbufferReceiveUpTo(_output_ring_buffer, &item_size, pdMS_TO_TICKS(1000), single_dma_buf);
674-
if (item != NULL){
675-
esp_i2s::i2s_write((esp_i2s::i2s_port_t) _deviceIndex, item, item_size, &bytes_written, 0);
676-
if(item_size != bytes_written){ // save item that was not written correctly for later
677-
memcpy(prev_item, (void*)&((uint8_t*)item)[bytes_written], item_size-bytes_written);
678-
prev_item_size = item_size - bytes_written;
679-
prev_item_offset = 0;
680-
prev_item_valid = true;
681-
} // save item that was not written correctly for later
682-
vRingbufferReturnItem(_output_ring_buffer, item);
683-
} // Check received item
684-
} // don't read from almost empty buffer
685-
686-
if(_onTransmit){
687-
_onTransmit();
688-
} // user callback
689-
690-
}else if(i2s_event == esp_i2s::I2S_EVENT_RX_DONE){
691-
size_t avail = xRingbufferGetCurFreeSize(_input_ring_buffer);
692-
esp_i2s::i2s_read((esp_i2s::i2s_port_t) _deviceIndex, _inputBuffer, avail <= single_dma_buf ? avail : single_dma_buf, (size_t*) &bytes_read, 0);
693-
if(pdTRUE != xRingbufferSend(_input_ring_buffer, _inputBuffer, bytes_read, 0)){
694-
log_w("I2S failed to send item from DMA to internal buffer\n");
695-
}else{
696-
if (_onReceive) {
697-
_onReceive();
698-
} // user callback
699-
} // xRingbufferSendComplete
700-
} // RX Done
701-
} // Queue set (I2S event or kill command)
726+
//}else if(xActivatedMember == _i2sEventQueue){ // default
727+
}else if(xActivatedMember == _i2sEventQueue || xActivatedMember == NULL){ // hack
728+
if(uxQueueMessagesWaiting(_i2sEventQueue)){
729+
xQueueReceive(_i2sEventQueue, &i2s_event, 0);
730+
if(i2s_event.type == esp_i2s::I2S_EVENT_TX_DONE){
731+
_tx_done_routine(prev_item);
732+
}else if(i2s_event.type == esp_i2s::I2S_EVENT_RX_DONE){
733+
_rx_done_routine();
734+
} // RX Done
735+
} // queue not empty
736+
}else{
737+
}
702738
} // infinite loop
703739
_callbackTaskHandle = NULL; // prevent secondary termination to non-existing task
704740
}
705741

706742
void I2SClass::onDmaTransferComplete(void*)
707743
{
708-
709744
I2S.onTransferComplete();
710745
vTaskDelete(NULL);
711746
}

0 commit comments

Comments
 (0)