Page 1 of 1

PDM microphones: big/little endian

Posted: Tue Jun 19, 2018 4:58 pm
by Piocky
Hi everyone,

I'm currently working on a project which uses two of those PDM mics: https://www.invensense.com/wp-content/u ... NMP621.pdf. For now, i'm saving some audio samples in flash memory, and then download them on my laptop, before opening the .pcm files on Audacity.

I followed the code given here: https://github.com/espressif/esp-idf/issues/1758 to do this, but the weird thing is that in my case, i've got better results (good audio level, no needs to amplify) with big endian than little endian as parameter in Audacity. It should be the opposite if i understood well. Also, i shouldn't be able to hear something with the wrong parameter, but here it's only about the level, which i don't get..
I'm trying then to playback audio using the following code:

Code: Select all

#define SAMPLE_RATE    44100
#define BITS_PS        16
#define BUF_COUNT      2
#define BUF_LENGTH     1000

/*
 * In PDM mode the clock is generated on WS line. Fwsclk = 64*(sample frequency)
 * Here sample frequency is 8KHz, hence WS clk frequency will  be 64*8k = 512KHz
 * Each sector of flash is 4096 bytes
 */

int16_t samples_data[SPI_FLASH_SEC_SIZE / 2] = {0};   //Since each sample is 2 bytes
size_t bytes_read;

void app_main()
{

	i2c_master_init();
	while (!tas5754m_init());
	i2s_tas_init();

    i2s_config_t i2s_config = {
        .mode = I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_PDM,    //master, RX, PDM
        .sample_rate = SAMPLE_RATE,
        .bits_per_sample = BITS_PS,                                    
        .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
        .communication_format = I2S_COMM_FORMAT_PCM, 			//pcm data format
        .dma_buf_count = BUF_COUNT,                   
        .dma_buf_len = BUF_LENGTH,                  
        .use_apll = 0,                               //apll disabled
        .intr_alloc_flags = ESP_INTR_FLAG_LEVEL3     //interrupt level 3
    };

    i2s_pin_config_t pin_config = {
        .ws_io_num = GPIO_NUM_18,
        .data_in_num = GPIO_NUM_19,
    };
    i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
    i2s_set_pin(I2S_NUM_0, &pin_config);

    vTaskDelay(1000/portTICK_PERIOD_MS);
/*
 * Steps to follow:
 * 1. erase each sector
 * 2. read data from PDM mics
 * 3. write to flash
 */
    for (uint32_t base_addr = 0x300000; base_addr < 0x400000; base_addr += SPI_FLASH_SEC_SIZE) {
        
        printf("erasing sector %x\n", base_addr / SPI_FLASH_SEC_SIZE);
        spi_flash_erase_sector(base_addr / SPI_FLASH_SEC_SIZE);
    }

    printf("Start speaking\n");
    for (uint32_t base_addr = 0x300000; base_addr < 0x400000; base_addr += SPI_FLASH_SEC_SIZE) {

    	i2s_read(I2S_NUM_0, samples_data, SPI_FLASH_SEC_SIZE, &bytes_read , portMAX_DELAY);
		spi_flash_write(base_addr, samples_data, sizeof(samples_data));
    }
    printf("Done writing data to flash\n");

    vTaskDelay(1000/portTICK_PERIOD_MS);
    for (uint32_t base_addr = 0x300000; base_addr < 0x400000; base_addr += SPI_FLASH_SEC_SIZE) {

		spi_flash_read(base_addr, samples_data, sizeof(samples_data));
		i2s_write(I2S_NUM_1, samples_data, sizeof(samples_data), &bytes_read , portMAX_DELAY);
	}
    printf("Done\n");
}
But again, the sound level is very very low. I tried to change pretty much every parameters (channel and communication format), nothing change (my output works well with bluetooth example, so i don't think that's my issue).

So my question is: is there a way to change the parameter of my I2S_NUM_0 to save data in the little endian way? If yes i didn't find where yet. If no, i would accept any suggestions!