The purpose of this project is to demonstrate how to use the Stereo MEMS Microphone on SLSTK3701A.
The MCU publishes the received data using the LCD. The received digital data are converted to decibel dimension. Each side has two textboxes where the numbers are the RMS and Peak values. Moreover, there are two scales, represent the previous values visually. The pressing of BUTTON_0 resets the Peak values.
By going through the project, the reader gets information regarding several peripherals, like I2S, TIMER, GPIO, LCD handling and interrupts.
The STK has two MEMS microphones, using these to capture the left- and right-side. The output signal of the microphones is PDM (Pulse Density Modulation) signal. The EFM32GG11 has no PDM processor peripheral, instead the STK has a PDM-to-I2S codec. The output from both microphones is connected to this codec which again is connected to a USART peripheral which supports I2S. The below figure shows the physical connections, see Figure 1.
As every project, it starts with the initialization of the peripherals, clocks and interrupts. Hereupon the whole application is based on a state-machine, has the following states:
Have a look at for each state.
The 1st state is made for synchronization. There are two microphones, but the data arrives on one line (MIC_I2S_DATA). The I2S standard define the LRCLK signal, to indicate the codec which microphone data is needed. On low-level the left-, on high-level the right-side data will be requested from codec. The LRCLK frequency is generated automatically by USART. At the beginning peripheral and codec delay might occur, therefore it can't be sure the first USART_RX interrupt is caused by the left or right-side data. To determine the cause of the interrupt, the level of LRCLK had to be known. The PRS and GPIO Interrupt help to know the state of LRCLK. If the level is low, a GPIO interrupt occurs to sign the left data will come. The PRS is used to connect to the USART_LRCLK and the GPIO.
After the falling edge of LRCLK, the next state is coming.
The purpose of the 2nd state is to collect both side data. For this, the USART generates an interrupt, if its buffer is full. The 16 bits data are stored in a common array for both sides. After 2400 samples (1200/side), the state-machine switches to the next state.
The 3rd state is made for waiting before processing the samples. Due to the high sampling frequency(48kHz) the data gathering takes about 50 ms. The TIMER0 ensures to elapse the defined LCD update time, even if the sample rate or buffer size would be modified.
In the 4th state, the data processing follows. Here the RMS and Peak values are calculated, then a string is made from the float numbers. After all the necessary data and strings are made, the content of the LCD have to be refreshed. The "red arrow" on Figure 2. shows how the process is repeated cyclically.
After the update we must know again which side data will come, because during the processing, the data gathering has been stalled. Similarly to the 1st state, the GPIO interrupt will indicate the active side.
The below figure illustrates the above.
Since the project is attached to this KBA, only the important parts of the software is highlighted.
As the whole project is based on the data via USART, important to avoid data loss. The codec transmits the bits regardless what the MCU does at that time. To be sure none of bits are lost and the frequently generated GPIO_ODD interrupt doesn't influence the USART_RX interrupt, set the priorities.
__NVIC_SetPriority(USART3_RX_IRQn, 0); __NVIC_SetPriority(GPIO_ODD_IRQn, 1); __NVIC_SetPriority(TIMER0_IRQn, 2);
The data sheet of codec specifies that the BCLK has to be at least 64 times greater than the LRCLK. In addition, the typical LRCLK is 48kHz, the related BCLK is 3.072MHz. The codec has 20-bit digital output. The width of frame determines the frequency of LRCLK. For example 32[bit width frame]* 2[side]*48kHz=3.072MHz, therefore it fulfills the requirements.
The above means we should use 32bit width frames. The useful data of frame could be 16 bits, because the LSBs may mean just noise.
def.sync.databits = usartDatabits16; def.sync.autoCsEnable = true; def.sync.baudrate = BCLK_FREQUENCY_3MHz; def.format = usartI2sFormatW32D16;
Since 16 of 20 bits are considered, the appropriate interrupt source would be the "RX buffer is full". By using this, we do not have to deal with the other bits.
Warning: It is not enough to read the RXDOUBLE register to clear the pending RXFULL interrupt flag like in case of RXDATAV, the RXFULL interrupt flag must be cleared by software.
In the USART_RX IRQ low values are ignored to get more visible change on the scales.
For instance, if the data is 1, it means ~-96dB,100 means ~-56dB. These numbers rarely come, but sometimes it happens.
By considering the size of the LCD and the possible sound pressures in a room, suitable spectrum is between -30dB and 0dB.
The demo is tested with
Demo on STK.