Skip to content

Instantly share code, notes, and snippets.

@schreibfaul1
Created May 6, 2021 21:26
Show Gist options
  • Save schreibfaul1/e6fe8774302c5873cce1305631c452b7 to your computer and use it in GitHub Desktop.
Save schreibfaul1/e6fe8774302c5873cce1305631c452b7 to your computer and use it in GitHub Desktop.
ESP32_ I2S_Microphone
// external HW
// 24-bit I2S Interface INMP441 Omnidirectional Microphone
// I2S PCM5102A DAC Decoder
#include "Arduino.h"
#include "driver/i2s.h"
#define TX_I2S_DOUT 25 // connect with external DAC
#define TX_I2S_BCLK 27
#define TX_I2S_LRC 26
#define RX_I2S_DIN 33 // connect with I2S microphone
#define RX_I2S_BCLK 12
#define RX_I2S_LRC 14
const i2s_port_t I2S_PORT_RX = I2S_NUM_1;
const i2s_port_t I2S_PORT_TX = I2S_NUM_0;
const uint32_t sample_rate = 44100;
const uint16_t buf_len = 512;
char buf[buf_len];
size_t bytes_written = 0;
void init_i2s() {
/* TX: I2S_NUM_0 */
i2s_config_t i2s_config_tx = {
.mode = (i2s_mode_t) (I2S_MODE_MASTER | I2S_MODE_TX),
.sample_rate = sample_rate,
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, // 2-channels
.communication_format = (i2s_comm_format_t) I2S_COMM_FORMAT_I2S_MSB,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, // Interrupt level 1
.dma_buf_count = 16, // number of buffers, 128 max.
.dma_buf_len = 256, // size of each buffer
.use_apll = false,
.tx_desc_auto_clear = true, // new in V1.0.1
.fixed_mclk = I2S_PIN_NO_CHANGE,
};
i2s_pin_config_t pin_config_tx = {
.bck_io_num = TX_I2S_BCLK,
.ws_io_num = TX_I2S_LRC,
.data_out_num = TX_I2S_DOUT,
.data_in_num = I2S_PIN_NO_CHANGE
};
i2s_driver_install(I2S_PORT_TX, &i2s_config_tx, 0, NULL);
i2s_set_pin(I2S_PORT_TX, &pin_config_tx);
/* RX: I2S_NUM_1 */
i2s_config_t i2s_config_rx = {
.mode = (i2s_mode_t) (I2S_MODE_MASTER | I2S_MODE_RX), // Only TX
.sample_rate = sample_rate,
.bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT, // Only 8-bit DAC support
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, // 2-channels
.communication_format = (i2s_comm_format_t) I2S_COMM_FORMAT_I2S_MSB,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, // Interrupt level 1
.dma_buf_count = 16, // number of buffers, 128 max.
.dma_buf_len = 256, // size of each buffer
.use_apll = false,
.tx_desc_auto_clear = true, // new in V1.0.1
.fixed_mclk = I2S_PIN_NO_CHANGE,
};
i2s_pin_config_t pin_config_rx = {
.bck_io_num = RX_I2S_BCLK,
.ws_io_num = RX_I2S_LRC,
.data_out_num = I2S_PIN_NO_CHANGE,
.data_in_num = RX_I2S_DIN
};
i2s_driver_install(I2S_PORT_RX, &i2s_config_rx, 0, NULL);
i2s_set_pin(I2S_PORT_RX, &pin_config_rx);
}
void setup(){
init_i2s();
}
void loop(){
// char *buf_ptr_read = buf + 4; // connect L/R with ground
char *buf_ptr_read = buf; // connect L/R with VDD
char *buf_ptr_write = buf;
// read whole block of samples
size_t bytes_read = 0;
while(bytes_read == 0) {
i2s_read(I2S_PORT_RX, buf, buf_len, &bytes_read, portMAX_DELAY);
}
uint32_t samples_read = bytes_read / 2 / (I2S_BITS_PER_SAMPLE_32BIT / 8);
// convert 2x 32 bit stereo -> 1 x 16 bit mono
for(int i = 0; i < samples_read; i++) {
// left channel
int32_t sample = (buf_ptr_read[3] << 24) + (buf_ptr_read[2] << 16) + (buf_ptr_read[1] << 8) + buf_ptr_read[4];
sample = sample >> 14; // gain
buf_ptr_write[0] = sample & 0x00FF;
buf_ptr_write[1] = (sample >>8) & 0x00FF;
// right channel
buf_ptr_write[2] = buf_ptr_write[0]; // mid
buf_ptr_write[3] = buf_ptr_write[1]; // high
buf_ptr_write += 2 * (I2S_BITS_PER_SAMPLE_16BIT / 8);
buf_ptr_read += 2 * (I2S_BITS_PER_SAMPLE_32BIT / 8);
}
// local echo
size_t bytes_written2;
bytes_written = samples_read * 2 * (I2S_BITS_PER_SAMPLE_16BIT / 8);
i2s_write(I2S_PORT_TX, buf, bytes_written, &bytes_written2, portMAX_DELAY);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment