Skip to content

Commit d7eb3f3

Browse files
committed
[BACKUP] Work in progress on overlaying buffer (crashing)
1 parent 12d926f commit d7eb3f3

File tree

2 files changed

+122
-75
lines changed

2 files changed

+122
-75
lines changed

Diff for: libraries/I2S/src/I2S.cpp

+113-75
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,11 @@
2121
#include "I2S.h"
2222
#include "freertos/semphr.h"
2323

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
3028

31-
#define _I2S_EVENT_QUEUE_LENGTH 10
32-
#define _I2S_DMA_BUFFER_SIZE 512
33-
#define _I2S_DMA_BUFFER_COUNT 8
3429
#define I2S_INTERFACES_COUNT SOC_I2S_NUM
3530

3631
#ifndef I2S_DEVICE
@@ -53,11 +48,11 @@
5348
#define PIN_I2S_SD 26
5449
#endif
5550

51+
5652
#ifndef PIN_I2S_SD_IN
5753
#define PIN_I2S_SD_IN 35 // 35 can be only input pin
5854
#endif
5955

60-
6156
#ifndef PIN_I2S_SD_OUT
6257
#define PIN_I2S_SD_OUT 26
6358
#endif
@@ -75,6 +70,15 @@ I2SClass::I2SClass(uint8_t deviceIndex, uint8_t clockGenerator, uint8_t sdPin, u
7570
_sampleRate(0),
7671
_mode(I2S_PHILIPS_MODE),
7772

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+
7882
_initialized(false),
7983
_callbackTaskHandle(NULL),
8084
_i2sEventQueue(NULL),
@@ -98,6 +102,15 @@ I2SClass::I2SClass(uint8_t deviceIndex, uint8_t clockGenerator, uint8_t inSdPin,
98102
_sampleRate(0),
99103
_mode(I2S_PHILIPS_MODE),
100104

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+
101114
_initialized(false),
102115
_callbackTaskHandle(NULL),
103116
_i2sEventQueue(NULL),
@@ -110,7 +123,7 @@ I2SClass::I2SClass(uint8_t deviceIndex, uint8_t clockGenerator, uint8_t inSdPin,
110123

111124
void I2SClass::createCallbackTask()
112125
{
113-
int stack_size = 3000;
126+
int stack_size = 10000;
114127
if(_callbackTaskHandle == NULL){
115128
if(_task_kill_cmd_semaphore_handle == NULL){
116129
_task_kill_cmd_semaphore_handle = xSemaphoreCreateBinary();
@@ -189,16 +202,13 @@ int I2SClass::begin(int mode, long sampleRate, int bitsPerSample, bool driveCloc
189202
pin_config.bck_io_num = _sckPin;
190203
pin_config.ws_io_num = _fsPin;
191204

192-
Serial.println("I2SClass::begin foo"); // debug
193205
if(_mode == I2S_ADC_DAC){
194-
Serial.println("I2SClass::begin foo adc"); // debug
195206
if(_bitsPerSample != 16){ // ADC/DAC can only work in 16-bit sample mode
196207
Serial.println("ERROR I2SClass::begin invalid bps for ADC/DAC"); // debug
197208
return 0; // ERR
198209
}
199210
i2s_mode = (esp_i2s::i2s_mode_t)(i2s_mode | esp_i2s::I2S_MODE_DAC_BUILT_IN | esp_i2s::I2S_MODE_ADC_BUILT_IN);
200211
}else{ // End of ADC/DAC mode; start of Normal mode
201-
Serial.println("I2SClass::begin foo normal"); // debug
202212
if(_bitsPerSample != 16 && /*_bitsPerSample != 24 && */ _bitsPerSample != 32){
203213
Serial.println("I2S.begin(): invalid bits per second for normal mode");
204214
// ESP does support 24 bps, however for the compatibility
@@ -220,22 +230,39 @@ int I2SClass::begin(int mode, long sampleRate, int bitsPerSample, bool driveCloc
220230
}
221231

222232
} // Normal mode
223-
Serial.println("I2SClass::begin bar"); // debug
224233
esp_i2s::i2s_config_t i2s_config = {
225234
.mode = i2s_mode,
226235
.sample_rate = _sampleRate,
227236
.bits_per_sample = (esp_i2s::i2s_bits_per_sample_t)_bitsPerSample,
228237
.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
230239
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL2,
231240
.dma_buf_count = _I2S_DMA_BUFFER_COUNT,
232241
.dma_buf_len = _I2S_DMA_BUFFER_SIZE
233242
};
234243

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+
235264
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
236265
Serial.println("ERROR I2SClass::begin error installing i2s driver"); // debug
237-
Serial.flush();
238-
delay(100);
239266
return 0; // ERR
240267
}
241268

@@ -253,7 +280,6 @@ int I2SClass::begin(int mode, long sampleRate, int bitsPerSample, bool driveCloc
253280
esp_i2s::adc1_config_channel_atten(adc_channel, esp_i2s::ADC_ATTEN_DB_11);
254281
esp_i2s::i2s_adc_enable((esp_i2s::i2s_port_t) _deviceIndex);
255282
}else{ // End of ADC/DAC mode; start of Normal mode
256-
Serial.println("I2SClass::begin calling set"); // debug
257283
if (ESP_OK != esp_i2s::i2s_set_pin((esp_i2s::i2s_port_t) _deviceIndex, &pin_config)) {
258284
Serial.println("i2s_set_pin err");
259285
end();
@@ -262,6 +288,7 @@ int I2SClass::begin(int mode, long sampleRate, int bitsPerSample, bool driveCloc
262288
}
263289
createCallbackTask();
264290
_initialized = true;
291+
265292
return 1; // OK
266293
}
267294

@@ -302,7 +329,6 @@ int I2SClass::setAllPins(int sckPin, int fsPin, int inSdPin, int outSdPin){
302329
.data_in_num = _inSdPin
303330
};
304331
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
306332
return 0; // ERR
307333
}
308334
}
@@ -329,10 +355,8 @@ int I2SClass::setHalfDuplex(uint8_t inSdPin, uint8_t outSdPin){
329355
.data_in_num = _inSdPin
330356
};
331357
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
333358
return 0; // ERR
334359
}
335-
Serial.printf("setFullDuplex(inSdPin=%d, outSdPin=%d) OK\n", inSdPin, outSdPin); // debug
336360
}
337361
return 1; // OK
338362
}
@@ -349,10 +373,8 @@ int I2SClass::setSimplex(uint8_t sdPin){
349373
.data_in_num = _sdPin
350374
};
351375
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
353376
return 0; // ERR
354377
}
355-
Serial.printf("setHalfDuplex(sdPin=%d) OK\n", sdPin); // debug
356378
}
357379
return 1; // OK
358380
}
@@ -374,6 +396,18 @@ void I2SClass::end()
374396
}
375397
_onTransmit = NULL;
376398
_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+
377411
}else{
378412
// TODO log_e with error - destroy task from inside not permitted
379413
}
@@ -382,9 +416,7 @@ void I2SClass::end()
382416
// available to read
383417
int I2SClass::available()
384418
{
385-
// There is no actual way to tell in ESP
386-
return _I2S_DMA_BUFFER_SIZE;
387-
//uxQueueSpacesAvailable();
419+
return _read_available;
388420
}
389421

390422
union i2s_sample_t {
@@ -419,21 +451,22 @@ int I2SClass::read(void* buffer, size_t size)
419451
return 0; // There was an error switching to receiver
420452
}
421453
}
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+
}
431464
if(_mode == I2S_ADC_DAC){
432-
for(int i = 0; i < read / 2; ++i){
465+
for(int i = 0; i < cpy_size / 2; ++i){
433466
((uint16_t*)buffer)[i] = ((uint16_t*)buffer)[i] & 0x0FFF;
434467
}
435468
}
436-
return read;
469+
return cpy_size;
437470
}
438471

439472
/*
@@ -450,20 +483,20 @@ size_t I2SClass::write(int32_t sample)
450483

451484
size_t I2SClass::write(const void *buffer, size_t size)
452485
{
453-
//Serial.printf("I2SClass::write(): _state = %d\n",_state);
454486
if (_state != I2S_STATE_TRANSMITTER && _state != I2S_STATE_DUPLEX) {
455487
if(!enableTransmitter()){
456488
return 0; // There was an error switching to transmitter
457489
}
458490
}
459491
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;
467500
return bytes_written;
468501
}
469502

@@ -491,9 +524,7 @@ size_t I2SClass::write(const uint8_t *buffer, size_t size)
491524

492525
int I2SClass::availableForWrite()
493526
{
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;
497528
}
498529

499530
void I2SClass::onTransmit(void(*function)(void))
@@ -513,9 +544,7 @@ void I2SClass::setBufferSize(int bufferSize)
513544

514545
int I2SClass::enableTransmitter()
515546
{
516-
Serial.printf("I2SClass::enableTransmitter(): _state = %d\n",_state);
517547
if (_state != I2S_STATE_TRANSMITTER && _state != I2S_STATE_DUPLEX){
518-
Serial.printf("I2SClass::enableTransmitter(): change data out pin to %d\n",_sdPin);
519548
esp_i2s::i2s_pin_config_t pin_config = {
520549
.bck_io_num = _sckPin,
521550
.ws_io_num = _fsPin,
@@ -561,48 +590,57 @@ void I2SClass::onTransferComplete()
561590
xQueueAddToSet(_task_kill_cmd_semaphore_handle, xQueueSet);
562591

563592
while(true){
564-
//Serial.printf("I2S:onTransferComplete: loop start\n");
565593
xActivatedMember = xQueueSelectFromSet(xQueueSet, portMAX_DELAY);
566594
if(xActivatedMember == _task_kill_cmd_semaphore_handle){
567-
Serial.printf("I2S:onTransferComplete: received kill command, breaking from loop\n");
568595
xSemaphoreTake(_task_kill_cmd_semaphore_handle, 0);
569596
break; // from the infinite loop
570597
}else if(xActivatedMember == _i2sEventQueue){
571-
//Serial.printf("I2S:onTransferComplete: received Q\n");
572598
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+
}
574610
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
579611
_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
595627
} // if event TX or RX
596628
}
597629
}
598-
Serial.printf("xxxxxxx I2S:onTransferComplete: out of loop - kill my self xxxxxxx\n");
599630
_callbackTaskHandle = NULL; // prevent secondary termination to non-existing task
600631
vTaskDelete(NULL);
601632
}
602633

603634
void I2SClass::onDmaTransferComplete(void*)
604635
{
636+
637+
#ifdef _USE_SYS_VIEW
638+
SEGGER_SYSVIEW_Print("onTransferComplete start");
639+
#endif // _USE_SYS_VIEW
605640
I2S.onTransferComplete();
641+
#ifdef _USE_SYS_VIEW
642+
SEGGER_SYSVIEW_Print("onTransferComplete stop");
643+
#endif // _USE_SYS_VIEW
606644
}
607645

608646
#if I2S_INTERFACES_COUNT > 0

Diff for: libraries/I2S/src/I2S.h

+9
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,15 @@ class I2SClass : public Stream
107107
long _sampleRate;
108108
int _mode;
109109

110+
uint16_t _buffer_byte_size;
111+
uint16_t _output_buffer_pointer;
112+
uint16_t _input_buffer_pointer;
113+
uint16_t _read_available;
114+
SemaphoreHandle_t _in_buf_semaphore;
115+
SemaphoreHandle_t _out_buf_semaphore;
116+
void *_inputBuffer;
117+
void *_outputBuffer;
118+
110119
bool _initialized;
111120
TaskHandle_t _callbackTaskHandle;
112121
QueueHandle_t _i2sEventQueue;

0 commit comments

Comments
 (0)