arduino-audio-tools
AnalogAudioESP32.h
1 #pragma once
2 
3 #include "AudioConfig.h"
4 #if defined(ESP32) && defined(USE_ANALOG) && ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0 , 0) || defined(DOXYGEN)
5 #include "AudioAnalog/AnalogAudioBase.h"
6 #include "driver/i2s.h"
7 #include "driver/adc.h"
8 #include "soc/dac_channel.h"
9 #include "soc/adc_channel.h"
10 #include "soc/rtc.h"
11 #include "AudioTools/AudioStreams.h"
12 
13 namespace audio_tools {
14 
15 // Output I2S data to built-in DAC, no matter the data format is 16bit or 32 bit, the DAC module will only take the 8bits from MSB
16 // so we convet it to a singed 16 bit value
17 static inline uint16_t convert8DAC(int64_t value, int value_bits_per_sample){
18  uint16_t result = value;
19  if (value_bits_per_sample!=16){
20  // convert to 16 bit value
21  result = (value * NumberConverter::maxValue(16) / NumberConverter::maxValue(value_bits_per_sample));
22  }
23  // uint_t positive range
24  result+= 32768;
25  return result;
26 }
27 
28 
36  public:
38  AnalogDriverESP32() = default;
39 
41  virtual ~AnalogDriverESP32() {
42  end();
43  }
44 
47  TRACEI();
48  cfg.logInfo();
49 
50  if (adc_config.is_auto_center_read){
51  LOGI("auto_center")
52  auto_center.begin(cfg.channels, cfg.bits_per_sample);
53  }
54 
55  if (!is_driver_installed){
56  port_no = (i2s_port_t) cfg.port_no;
57 
58  adc_config = cfg;
59  i2s_config_t i2s_config = {
60  .mode = (i2s_mode_t)cfg.mode_internal,
61  .sample_rate = (eps32_i2s_sample_rate_type)cfg.sample_rate,
62  .bits_per_sample = (i2s_bits_per_sample_t)cfg.bits_per_sample,
63  .channel_format = (cfg.channels == 1 && cfg.rx_tx_mode == RX_MODE) ? I2S_CHANNEL_FMT_ONLY_LEFT :I2S_CHANNEL_FMT_RIGHT_LEFT,
64  .communication_format = (i2s_comm_format_t)0,
65  .intr_alloc_flags = 0,
66  .dma_buf_count = cfg.buffer_count,
67  .dma_buf_len = cfg.buffer_size,
68  .use_apll = cfg.use_apll,
69  .tx_desc_auto_clear = cfg.auto_clear,
70 #if ESP_IDF_VERSION_MAJOR >= 4
71  .fixed_mclk = 0,
72  .mclk_multiple = I2S_MCLK_MULTIPLE_DEFAULT,
73  .bits_per_chan = I2S_BITS_PER_CHAN_DEFAULT,
74 #endif
75  };
76 
77  // setup config
78  if (i2s_driver_install(port_no, &i2s_config, 0, nullptr)!=ESP_OK){
79  LOGE( "%s - %s", __func__, "i2s_driver_install");
80  return false;
81  }
82 
83  // record driver as installed
84  is_driver_installed = true;
85 
86  // clear i2s buffer
87  if (i2s_zero_dma_buffer(port_no)!=ESP_OK) {
88  LOGE( "%s - %s", __func__, "i2s_zero_dma_buffer");
89  return false;
90  }
91 
92  switch (cfg.rx_tx_mode) {
93  case RX_MODE:
94  LOGI("RX_MODE");
95 
96  setupInputPin(cfg.adc_pin);
97 
98  if (i2s_set_adc_mode(adc_unit, adc_channel)!=ESP_OK) {
99  LOGE( "%s - %s", __func__, "i2s_driver_install");
100  return false;
101  }
102 
103  // enable the ADC
104  if (i2s_adc_enable(port_no)!=ESP_OK) {
105  LOGE( "%s - %s", __func__, "i2s_adc_enable");
106  return false;
107  }
108 
109  break;
110 
111  case TX_MODE:
112  LOGI("TX_MODE");
113  if (i2s_set_pin(port_no, nullptr) != ESP_OK) LOGE("i2s_set_pin");
114  if (i2s_set_dac_mode( I2S_DAC_CHANNEL_BOTH_EN) != ESP_OK) LOGE("i2s_set_dac_mode");
115  if (i2s_set_sample_rates(port_no, cfg.sample_rate) != ESP_OK) LOGE("i2s_set_sample_rates");
116  //if (i2s_set_clk(port_no, cfg.sample_rate, cfg.bits_per_sample, I2S_CHANNEL_STEREO)) LOGE("i2s_set_clk");
117 
118  break;
119 
120  default:
121  LOGE( "Unsupported MODE: %d", cfg.rx_tx_mode);
122  return false;
123  break;
124 
125  }
126  } else {
127  i2s_start(port_no);
128  if (adc_config.rx_tx_mode == RX_MODE){
129  i2s_adc_enable(port_no);
130  }
131  }
132  active = true;
133  return true;
134  }
135 
137  void end() override {
138  LOGI(__func__);
139  if (active) {
140  i2s_zero_dma_buffer(port_no);
141  }
142 
143  // close ADC
144  if (adc_config.rx_tx_mode == RX_MODE){
145  i2s_adc_disable(port_no);
146  }
147  if (adc_config.uninstall_driver_on_end){
148  i2s_driver_uninstall(port_no);
149  is_driver_installed = false;
150  } else {
151  i2s_stop(port_no);
152  }
153  active = false;
154  }
155 
156  // /// Overides the sample rate and uses the max value which is around ~13MHz. Call this methd after begin();
157  // void setMaxSampleRate() {
158  // //this is the hack that enables the highest sampling rate possible ~13MHz, have fun
159  // SET_PERI_REG_BITS(I2S_CLKM_CONF_REG(0), I2S_CLKM_DIV_A_V, 1, I2S_CLKM_DIV_A_S);
160  // SET_PERI_REG_BITS(I2S_CLKM_CONF_REG(0), I2S_CLKM_DIV_B_V, 1, I2S_CLKM_DIV_B_S);
161  // SET_PERI_REG_BITS(I2S_CLKM_CONF_REG(0), I2S_CLKM_DIV_NUM_V, 1, I2S_CLKM_DIV_NUM_S);
162  // SET_PERI_REG_BITS(I2S_SAMPLE_RATE_CONF_REG(0), I2S_TX_BCK_DIV_NUM_V, 1, I2S_TX_BCK_DIV_NUM_S);
163  // }
164 
166  size_t write(const uint8_t *src, size_t size_bytes) override {
167  TRACED();
168 
169  size_t result = 0;
170  if (size_bytes>0 && src!=nullptr){
171  switch(adc_config.channels){
172  case 1:
173  result = outputMono(src, size_bytes);
174  break;
175  case 2:
176  result = outputStereo(src, size_bytes);
177  break;
178  default:
179  LOGE("Unsupported number of channels: %d", adc_config.channels);
180  stop();
181  }
182  LOGD("converted write size: %d",result);
183  }
184  return size_bytes;
185  }
186 
187  size_t readBytes(uint8_t *dest, size_t size_bytes) override {
188  TRACED();
189  size_t result = 0;
190  if (i2s_read(port_no, dest, size_bytes, &result, portMAX_DELAY)!=ESP_OK){
191  TRACEE();
192  }
193  // make sure that the center is at 0
194  if (adc_config.is_auto_center_read){
195  auto_center.convert(dest, result);
196  }
197  LOGD( "%s - len: %d -> %d", __func__, size_bytes, result);
198  return result;
199  }
200 
201  virtual int available() override {
202  return active ? adc_config.buffer_size*adc_config.buffer_count : 0;
203  }
204 
205  protected:
206  AnalogConfigESP32 adc_config;
207  ConverterAutoCenter auto_center;
208  i2s_port_t port_no;
209  bool active = false;
210  bool is_driver_installed = false;
211  size_t result=0;
212 
213  // input values
214  adc_unit_t adc_unit;
215  adc1_channel_t adc_channel;
216 
218  void setupInputPin(int gpio){
219  TRACED();
220 
221  switch(gpio){
222  case 32:
223  adc_unit = ADC_UNIT_1;
224  adc_channel = ADC1_GPIO32_CHANNEL;
225  break;
226  case 33:
227  adc_unit = ADC_UNIT_1;
228  adc_channel = ADC1_GPIO33_CHANNEL;
229  break;
230  case 34:
231  adc_unit = ADC_UNIT_1;
232  adc_channel = ADC1_GPIO34_CHANNEL;
233  break;
234  case 35:
235  adc_unit = ADC_UNIT_1;
236  adc_channel = ADC1_GPIO35_CHANNEL;
237  break;
238  case 36:
239  adc_unit = ADC_UNIT_1;
240  adc_channel = ADC1_GPIO36_CHANNEL;
241  break;
242  case 37:
243  adc_unit = ADC_UNIT_1;
244  adc_channel = ADC1_GPIO37_CHANNEL;
245  break;
246  case 38:
247  adc_unit = ADC_UNIT_1;
248  adc_channel = ADC1_GPIO38_CHANNEL;
249  break;
250  case 39:
251  adc_unit = ADC_UNIT_1;
252  adc_channel = ADC1_GPIO39_CHANNEL;
253  break;
254 
255  default:
256  LOGE( "%s - pin GPIO%d is not supported", __func__,gpio);
257  }
258  }
259 
260  // The internal DAC only supports 8 bit values - so we need to convert the data
261  size_t outputStereo(const void *src, size_t size_bytes) {
262  TRACED();
263  size_t output_size = 0;
264  size_t result;
265  uint16_t *dst = (uint16_t *)src;
266  switch(adc_config.bits_per_sample){
267  case 16: {
268  int16_t *data=(int16_t *)src;
269  output_size = size_bytes;
270  for (int j=0;j<size_bytes/2;j++){
271  dst[j] = convert8DAC(data[j], adc_config.bits_per_sample);
272  }
273  } break;
274  case 24: {
275  int24_t *data=(int24_t *)src;
276  output_size = (size_bytes/3) * 2;
277  for (int j=0;j<size_bytes/3;j++){
278  dst[j] = (uint32_t)convert8DAC(data[j], adc_config.bits_per_sample);
279  }
280  } break;
281  case 32: {
282  int32_t *data=(int32_t *)src;
283  output_size = (size_bytes/4) * 2;
284  for (int j=0;j<size_bytes/4;j++){
285  dst[j] = convert8DAC(data[j], adc_config.bits_per_sample);
286  }
287  } break;
288  }
289 
290  if (output_size>0){
291  if (i2s_write(port_no, src, output_size, &result, portMAX_DELAY)!=ESP_OK){
292  LOGE("%s: %d", LOG_METHOD, output_size);
293  }
294  }
295 
296  LOGD("i2s_write %d -> %d bytes", size_bytes, result);
297  return result;
298 
299  }
300 
301  // I2S requires stereo so we convert mono to stereo
302  size_t outputMono(const void *src, size_t size_bytes) {
303  TRACED();
304  size_t output_size = 0;
305  uint16_t out[2];
306  size_t resultTotal = 0;
307  switch(adc_config.bits_per_sample){
308  case 16: {
309  int16_t *data=(int16_t *)src;
310  for (int j=0;j<size_bytes/2;j++){
311  out[0] = convert8DAC(data[j], adc_config.bits_per_sample);
312  out[1] = out[0];
313  if (i2s_write(port_no, out, 4, &result, portMAX_DELAY)!=ESP_OK){
314  LOGE("%s: %d", LOG_METHOD, output_size);
315  }
316  resultTotal += result;
317  }
318  }break;
319  case 24: {
320  int24_t *data=(int24_t*)src;
321  for (int j=0;j<size_bytes/3;j++){
322  out[0] = convert8DAC(data[j], adc_config.bits_per_sample);
323  out[1] = out[0];
324  if (i2s_write(port_no, out, 4, &result, portMAX_DELAY)!=ESP_OK){
325  LOGE("%s: %d", LOG_METHOD, output_size);
326  }
327  resultTotal += result;
328  }
329  } break;
330  case 32: {
331  int32_t *data=(int32_t *)src;
332  for (int j=0;j<size_bytes/4;j++){
333  out[0] = convert8DAC(data[j], adc_config.bits_per_sample);
334  out[1] = out[0];
335  if (i2s_write(port_no, out, 4, &result, portMAX_DELAY)!=ESP_OK){
336  LOGE("%s: %d", LOG_METHOD, output_size);
337  }
338  resultTotal += result;
339  }
340  } break;
341  }
342 
343  LOGD("i2s_write %d -> %d bytes", size_bytes, resultTotal);
344  return resultTotal;
345  }
346 };
348 using AnalogDriver = AnalogDriverESP32;
349 
350 } // namespace
351 
352 #endif
ESP32 specific configuration for i2s input via adc. The default input pin is GPIO34....
Definition: AnalogConfigESP32.h:21
Definition: AnalogAudioBase.h:13
Please use AnalogAudioStream: A very fast ADC and DAC using the ESP32 I2S interface.
Definition: AnalogAudioESP32.h:35
void setupInputPin(int gpio)
Defines the current ADC pin. The following GPIO pins are supported: GPIO32-GPIO39.
Definition: AnalogAudioESP32.h:218
bool begin(AnalogConfigESP32 cfg)
starts the DAC
Definition: AnalogAudioESP32.h:46
size_t write(const uint8_t *src, size_t size_bytes) override
writes the data to the I2S interface
Definition: AnalogAudioESP32.h:166
AnalogDriverESP32()=default
Default constructor.
void end() override
stops the I2S and unistalls the driver
Definition: AnalogAudioESP32.h:137
virtual ~AnalogDriverESP32()
Destructor.
Definition: AnalogAudioESP32.h:41
static int64_t maxValue(int value_bits_per_sample)
provides the biggest number for the indicated number of bits
Definition: AudioTypes.h:330
void stop()
Public generic methods.
Definition: AudioRuntime.h:12
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition: AnalogAudio.h:10
AnalogDriverArduino AnalogDriver
AnalogAudioStream.
Definition: AnalogAudioArduino.h:258
sample_rate_t sample_rate
Sample Rate: e.g 44100.
Definition: AudioTypes.h:53
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition: AudioTypes.h:55
uint8_t bits_per_sample
Number of bits per sample (int16_t = 16 bits)
Definition: AudioTypes.h:57