Re: I2S microphone (RX)
Posted: Thu May 25, 2017 4:57 pm
I like things small and digital, so its not for me. I can see the appeal though - good luck!
you are right - perhabs i will try - - hope for the digi tiny ICS boards asapI like things small and digital, so its not for me. I can see the appeal though - good luck!
Already packaged, will send them out tomorrow!hope for the digi tiny ICS boards asap
Already packaged, will send them out tomorrow!hope for the digi tiny ICS boards asap
Code: Select all
#define NUM_CHANNELS 2
#define BIT_SIZE I2S_BITS_PER_SAMPLE_32BIT
...
for (int i = 0; i < samples_read; i ++){
uint16_t val = (rbuf[3] << 8 ) + rbuf[2];
...
rbuf += NUM_CHANNELS * (BIT_SIZE / 8);
Wow.... super thanks @BuddyCasinoHere is a complete example, I verified it works:Code: Select all
/* * app_main.c * * Created on: 30.03.2017 * Author: michaelboeckling */ #include <stdlib.h> #include <stddef.h> #include <inttypes.h> #include <string.h> #include <stdio.h> #include <stdbool.h> #include <sys/time.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/event_groups.h" #include "esp_system.h" #include "esp_log.h" #include "driver/i2s.h" #define TAG "main" static void init_i2s() { const int sample_rate = 44100; /* TX: I2S_NUM_0 */ i2s_config_t i2s_config_tx = { .mode = 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_I2S_MSB, .dma_buf_count = 32, // number of buffers, 128 max. .dma_buf_len = 32 * 2, // size of each buffer .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1 // Interrupt level 1 }; i2s_pin_config_t pin_config_tx = { .bck_io_num = GPIO_NUM_26, .ws_io_num = GPIO_NUM_25, .data_out_num = GPIO_NUM_22, .data_in_num = GPIO_NUM_23 }; i2s_driver_install(I2S_NUM_0, &i2s_config_tx, 0, NULL); i2s_set_pin(I2S_NUM_0, &pin_config_tx); /* RX: I2S_NUM_1 */ i2s_config_t i2s_config_rx = { .mode = 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_I2S_MSB, .dma_buf_count = 32, // number of buffers, 128 max. .dma_buf_len = 32 * 2, // size of each buffer .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1 // Interrupt level 1 }; i2s_pin_config_t pin_config_rx = { .bck_io_num = GPIO_NUM_17, .ws_io_num = GPIO_NUM_18, .data_out_num = I2S_PIN_NO_CHANGE, .data_in_num = GPIO_NUM_5 }; i2s_driver_install(I2S_NUM_1, &i2s_config_rx, 0, NULL); i2s_set_pin(I2S_NUM_1, &pin_config_rx); } void task_megaphone(void *pvParams) { uint16_t buf_len = 1024; char *buf = calloc(buf_len, sizeof(char)); struct timeval tv = {0}; struct timezone *tz = {0}; gettimeofday(&tv, &tz); uint64_t micros = tv.tv_usec + tv.tv_sec * 1000000; uint64_t micros_prev = micros; uint64_t delta = 0; init_i2s(); int cnt = 0; int bytes_written = 0; while(1) { char *buf_ptr_read = buf; char *buf_ptr_write = buf; // read whole block of samples int bytes_read = 0; while(bytes_read == 0) { bytes_read = i2s_read_bytes(I2S_NUM_1, buf, buf_len, 0); } 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++) { // const char samp32[4] = {ptr_l[0], ptr_l[1], ptr_r[0], ptr_r[1]}; // left buf_ptr_write[0] = buf_ptr_read[2]; // mid buf_ptr_write[1] = buf_ptr_read[3]; // high // right 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 bytes_written = samples_read * 2 * (I2S_BITS_PER_SAMPLE_16BIT / 8); i2s_write_bytes(I2S_NUM_0, buf, bytes_written, portMAX_DELAY); cnt += samples_read; if(cnt >= 44100) { gettimeofday(&tv, &tz); micros = tv.tv_usec + tv.tv_sec * 1000000; delta = micros - micros_prev; micros_prev = micros; printf("%d samples in %" PRIu64 " usecs\n", cnt, delta); cnt = 0; } } } /** * entry point */ void app_main() { printf("starting app_main()\n"); xTaskCreatePinnedToCore(&task_megaphone, "task_megaphone", 16384, NULL, 20, NULL, 0); }
Code: Select all
int bytes_read = 0;
while(bytes_read == 0) {
bytes_read = i2s_read_bytes(I2S_NUM_1, buf, sizeof(buf), portMAX_DELAY);
}
uint32_t samples_read = bytes_read / (I2S_BITS_PER_SAMPLE_32BIT / 8);
for (int i = 0; i < samples_read; i++)
{
buf_ptr_write[0] = buf_ptr_read[2]; // mid
buf_ptr_write[1] = buf_ptr_read[3]; // high
}
int bytes_written = samples_read * (I2S_BITS_PER_SAMPLE_32BIT / 8);
i2s_write_bytes(I2S_NUM_0, (const char*)buf, bytes_written, portMAX_DELAY);
I've got some ICS-43434 breakout boards that I bought from here:1. i'd like to try this with a different i2s mems microhone. ( any suggestions, i'm using adafruit's SPH0645 )
Where do you get I2S_COMM_FORMAT_RAW_I2S from? I have the latest IDF and all I have are these:2. any idea's why setting the communication_format to I2S_COMM_FORMAT_RAW_I2S would have this benefit and is there a way to tweak this further ?
Code: Select all
typedef enum {
I2S_COMM_FORMAT_I2S = 0x01, /*!< I2S communication format I2S*/
I2S_COMM_FORMAT_I2S_MSB = 0x02, /*!< I2S format MSB*/
I2S_COMM_FORMAT_I2S_LSB = 0x04, /*!< I2S format LSB*/
I2S_COMM_FORMAT_PCM = 0x08, /*!< I2S communication format PCM*/
I2S_COMM_FORMAT_PCM_SHORT = 0x10, /*!< PCM Short*/
I2S_COMM_FORMAT_PCM_LONG = 0x20, /*!< PCM Long*/
} i2s_comm_format_t;