Skip to content

Commit c7d011e

Browse files
committed
Added C3 PDM support
1 parent 7a9fd45 commit c7d011e

File tree

3 files changed

+48
-12
lines changed

3 files changed

+48
-12
lines changed

libraries/I2S/examples/SimpleTone/.skip.esp32c3

Whitespace-only changes.

libraries/I2S/src/I2S.cpp

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ int I2SClass::_installDriver(){
117117
log_e("(I2S#%d) This chip does not support ADC / DAC mode", _deviceIndex);
118118
return 0; // ERR
119119
#endif
120+
// TODO left/right justified mode is actually stereo, but ignoring the other channel input// left/righ
120121
}else if(_mode == I2S_PHILIPS_MODE ||
121122
_mode == I2S_RIGHT_JUSTIFIED_MODE ||
122123
_mode == I2S_LEFT_JUSTIFIED_MODE){ // End of ADC/DAC mode; start of Normal Philips mode
@@ -128,8 +129,11 @@ int I2SClass::_installDriver(){
128129
log_w("(I2S#%d) Original Arduino library does not support 24 bits per sample.\nKeep that in mind if you should switch back to Arduino", _deviceIndex);
129130
}
130131
}else if(_mode == PDM_STEREO_MODE || _mode == PDM_MONO_MODE){ // end of Normal Philips mode; start of PDM mode
131-
#if (SOC_I2S_SUPPORTS_PDM_TX && SOC_I2S_SUPPORTS_PDM_RX)
132+
#if (SOC_I2S_SUPPORTS_PDM_TX || SOC_I2S_SUPPORTS_PDM_RX)
132133
i2s_mode = (esp_i2s::i2s_mode_t)(i2s_mode | esp_i2s::I2S_MODE_PDM);
134+
#ifndef SOC_I2S_SUPPORTS_PDM_RX
135+
i2s_mode = (esp_i2s::i2s_mode_t)(i2s_mode & ~esp_i2s::I2S_MODE_RX); // remove PRM RX which is not supported on ESP32-C3
136+
#endif
133137
#else
134138
log_e("(I2S#%d) This chip does not support PDM", _deviceIndex);
135139
return 0; // ERR
@@ -254,13 +258,13 @@ int I2SClass::begin(int mode, int sampleRate, int bitsPerSample, bool driveClock
254258

255259
// There is work in progress on this library.
256260
if(_bitsPerSample == 16 && _sampleRate > 16000 && driveClock){
257-
log_w("(I2S#%d) This sample rate is not officially supported - audio might be noisy.\nTry using sample rate below or equal to 16000", _deviceIndex);
261+
log_w("(I2S#%d) The sample rate value %d is not officially supported - audio might be noisy.\nTry using sample rate below or equal to 16000", _deviceIndex, _sampleRate);
258262
}
259263
if(_bitsPerSample != 16){
260264
log_w("(I2S#%d) This bit-per-sample is not officially supported - audio quality might suffer.\nTry using 16bps, with sample rate below or equal 16000", _deviceIndex);
261265
}
262266
if(_mode != I2S_PHILIPS_MODE){
263-
log_w("(I2S#%d) This mode is not officially supported - audio quality might suffer.\nAt the moment the only supported mode is I2S_PHILIPS_MODE", _deviceIndex);
267+
log_w("(I2S#%d) The mode %s is not officially supported - audio quality might suffer.\nAt the moment the only supported mode is I2S_PHILIPS_MODE", _deviceIndex, i2s_mode_text[_mode]);
264268
}
265269

266270
if (_state != I2S_STATE_IDLE && _state != I2S_STATE_DUPLEX) {
@@ -276,14 +280,24 @@ int I2SClass::begin(int mode, int sampleRate, int bitsPerSample, bool driveClock
276280

277281
#if (SOC_I2S_SUPPORTS_ADC && SOC_I2S_SUPPORTS_DAC)
278282
case ADC_DAC_MODE:
283+
#else
284+
log_e("(I2S#%d) ERROR: ADC/DAC is not supported on this SoC. Change mode or SoC", _deviceIndex);
285+
_give_if_top_call();
286+
return 0; // ERR
279287
#endif
280288

289+
#if defined(SOC_I2S_SUPPORTS_PDM_TX) || defined(SOC_I2S_SUPPORTS_PDM_RX)
281290
case PDM_STEREO_MODE:
282291
case PDM_MONO_MODE:
283292
break;
293+
#else
294+
log_e("(I2S#%d) ERROR: PDM is not supported on this SoC. Change mode or SoC", _deviceIndex);
295+
_give_if_top_call();
296+
return 0; // ERR
297+
#endif
284298

285299
default: // invalid mode
286-
log_e("(I2S#%d) ERROR: unknown mode", _deviceIndex);
300+
log_e("(I2S#%d) ERROR: unknown or unsupported mode", _deviceIndex);
287301
_give_if_top_call();
288302
return 0; // ERR
289303
}
@@ -295,6 +309,7 @@ int I2SClass::begin(int mode, int sampleRate, int bitsPerSample, bool driveClock
295309
}
296310

297311
_buffer_byte_size = _i2s_dma_buffer_size * (_bitsPerSample / 8) * _I2S_DMA_BUFFER_COUNT * 2;
312+
log_d("(I2S#%d) Creating internal buffers. Requested size = %dB\n", _deviceIndex, _buffer_byte_size);
298313
_input_ring_buffer = xRingbufferCreate(_buffer_byte_size, RINGBUF_TYPE_BYTEBUF);
299314
_output_ring_buffer = xRingbufferCreate(_buffer_byte_size, RINGBUF_TYPE_BYTEBUF);
300315
if(_input_ring_buffer == NULL || _output_ring_buffer == NULL){
@@ -361,7 +376,6 @@ int I2SClass::setSckPin(int sckPin){
361376
_take_if_not_holding();
362377
_setSckPin(sckPin);
363378
int ret = _applyPinSetting();
364-
_applyPinSetting();
365379
_give_if_top_call();
366380
return ret;
367381
}
@@ -454,15 +468,17 @@ int I2SClass::setAllPins(int sckPin, int fsPin, int sdPin, int outSdPin, int inS
454468
int I2SClass::setDuplex(){
455469
_take_if_not_holding();
456470
_state = I2S_STATE_DUPLEX;
471+
int ret = _applyPinSetting();
457472
_give_if_top_call();
458-
return 1;
473+
return ret;
459474
}
460475

461476
int I2SClass::setSimplex(){
462477
_take_if_not_holding();
463478
_state = I2S_STATE_IDLE;
479+
int ret = _applyPinSetting();
464480
_give_if_top_call();
465-
return 1;
481+
return ret;
466482
}
467483

468484
int I2SClass::isDuplex(){
@@ -707,6 +723,8 @@ size_t I2SClass::write_blocking(const void *buffer, size_t size){
707723
// non-blocking version of write
708724
// In case there is not enough space in buffer to write requested size
709725
// this function will try to flush the buffer and write requested data with 0 time-out
726+
// The function will return number of successfully written bytes. It is users responsibility
727+
// to take care of the remaining data.
710728
size_t I2SClass::write_nonblocking(const void *buffer, size_t size){
711729
_take_if_not_holding();
712730
if(_initialized){
@@ -759,8 +777,8 @@ int I2SClass::peek(){
759777
_give_if_top_call();
760778
return ret;
761779
}
762-
763-
// TODO flush everything instead of one buffer
780+
// Requests data from ring buffer and writes data to I2S module
781+
// note: it is NOT necessary to call the flush after writes. Buffer is flushed automatically after receiveing enough data.
764782
void I2SClass::flush(){
765783
_take_if_not_holding();
766784
if(_initialized){
@@ -804,6 +822,11 @@ void I2SClass::onReceive(void(*function)(void)){
804822
_give_if_top_call();
805823
}
806824

825+
826+
// Change buffer size. The unit is in frames.
827+
// Byte value can be calculated as follows:
828+
// ByteSize = (bits_per_sample / 8) * number_of_channels * bufferSize
829+
// Calling this function will automatically restart the driver, which could cause audio output gap.
807830
int I2SClass::setBufferSize(int bufferSize){
808831
_take_if_not_holding();
809832
int ret = 0;
@@ -997,7 +1020,11 @@ void I2SClass::_post_read_data_fix(void *input, size_t *size){
9971020
((uint16_t*)input)[dst_ptr++] = tmp;
9981021
}
9991022
break;
1000-
default: ; // Do nothing
1023+
case 24:
1024+
// TODO check if need fix and if so, implement it
1025+
break;
1026+
default: ;
1027+
// Do nothing
10011028
} // switch
10021029
}
10031030

libraries/I2S/src/I2S.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,13 +118,22 @@ namespace esp_i2s {
118118

119119
typedef enum {
120120
I2S_PHILIPS_MODE, // Most common I2S mode, FS signal spans across whole channel period
121-
I2S_RIGHT_JUSTIFIED_MODE, // TODO check oscilloscope what it does
122-
I2S_LEFT_JUSTIFIED_MODE, // TODO check oscilloscope what it does
121+
I2S_RIGHT_JUSTIFIED_MODE, // Right channel data are copied to both channels
122+
I2S_LEFT_JUSTIFIED_MODE, // Left channel data are copied to both channels
123123
ADC_DAC_MODE, // Receive and transmit raw analog signal
124124
PDM_STEREO_MODE, // Pulse Density Modulation - stereo / 2 channels
125125
PDM_MONO_MODE // Pulse Density Modulation - mono / 1 channel
126126
} i2s_mode_t;
127127

128+
const char i2s_mode_text[][32] = {
129+
"I2S_PHILIPS_MODE",
130+
"I2S_RIGHT_JUSTIFIED_MODE",
131+
"I2S_LEFT_JUSTIFIED_MODE",
132+
"ADC_DAC_MODE",
133+
"PDM_STEREO_MODE",
134+
"PDM_MONO_MODE"
135+
};
136+
128137
class I2SClass : public Stream
129138
{
130139
public:

0 commit comments

Comments
 (0)