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 asap ))BuddyCasino wrote:I 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
BuddyCasino wrote: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 @BuddyCasinoBuddyCasino wrote:Here 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;