cancel
Showing results for 
Search instead for 
Did you mean: 

Unexpected behaviors in DMA buffer for I2S MEMS microphone (SPH0645)

tnowroz
Associate II

Board: STM32 Nucleo-F411RE

I am trying to get audio from I2S MEMS microphone (SPH0645). According to datasheet here - 

https://www.knowles.com/docs/default-source/default-document-library/sph0645lm4h-1-datasheet.pdf 

tnowroz_0-1727571409920.png

Basically I am supposed to get a 32-bit, where the first 24-bit is needed, last 8-bits should be ignored.

According to this, I have set the I2S pins as Half Duplex Master, with following settings -

tnowroz_1-1727571542326.png

 

The DMA settings is given below - 

tnowroz_2-1727571569792.png

 

Here as the frame size is 32-bits, I have set data width as 'word'. 

My code is like this (ignoring the init functions) - 

 

 

#define BUFF_SIZE 200
volatile uint32_t i2s_rxData[BUFF_SIZE];
volatile uint32_t i2s_RxSmpl;

int main(void) {
  HAL_I2S_Receive_DMA(&hi2s2, (uint32_t *)i2s_rxData, BUFF_SIZE);

  while (1) {
  }
}

 

 

 

 

Now, my expectation was that each entry on data buffer would be a 32-bit number, but it seems I get 16-bit each entry. In debug mode, this is how the DMA buffer looks like. 

The pattern is, 2 numbers 16-bit numbers, ending with two zeros. I dont know exactly why it behaves like this.

tnowroz_3-1727571640927.png

So, I considered each 4 buffer entry as 1 audio data and did the needed bit shifting - 

 

 

void HAL_I2S_RxCpltCallback(I2S_HandleTypeDef *hi2s){

	HAL_I2S_DMAPause(hi2s);
	uint16_t n1 = 0;
	uint16_t n2 = 0;
	uint32_t decoded = 0;

	for (int i = 0; i < BUFF_SIZE; i = i+4) {
		 decoded = 0;
		 decoded = i2s_rxData[i]; // Take 1st element of every 4th entry
		 decoded = decoded << 16; // Left shift it 
		 decoded |= i2s_rxData[i+1]; // put the next number LSB 16-bit
		 decoded = decoded >> 8; // Get 24 bits on data by shifting 8-bits right
		 aduio_dataBuff[i/4] = decoded; // Append it to Audio buffer
	    }

        // See plot of Audio Buffer at trace timeline @ Debug Mode
	for (int i = 0; i < BUFF_SIZE/4; i++) {
		if (aduio_dataBuff[i] != 0)
			x = aduio_dataBuff[i];
	}


	HAL_I2S_DMAResume(hi2s);

}

 

 

 

This does work, however, I am not getting perfect audio signal after post processing unless I ignore the zeros in processed audio buffer.

 

Processed Audio with zeros ignored - 

tnowroz_4-1727572117439.png

 

Without Zero Ignored - 

tnowroz_5-1727572171290.png

 

This means, clearly there is something I am not doing right.

 

I have tried changing *Data and Data Frame format* on I2S settings and also Data Width from DMA request settings, but I am no sure where it's not going perfect.

 

Can anyone please guide me toward right direction? I just spend quite a bit time on this and want to get this right. Thanks.

1 REPLY 1
Remyhx
Associate III

Late response, but did you try 24-bits data (on a 32 bits frame)?