 Hello and welcome to this introduction to microphones. In this video I'm going to cover the details of the PDM to PCM conversion library for STM32 offered by STM microelectronics. The PDM to PCM software library includes all the steps required for PDM to PCM conversion as we saw in the previous video. Those steps are low pass filtering, decimation, high pass filter and gain control. The library runs on Cortex M0, M0+, M3, M4 and M7 based STM32. Please note that the library may not be needed if you are adopting an STM32 with PDM to PCM conversion capability in hardware such as the DFSDM peripheral available on some STM32. Let's start from a quick introduction on how audio data is organized when dealing with more than a single channel. Standard PCM buffer contains interleaved channels. In the four channels example you see, the first four values represent the first sample of each one of the four channels. The second four values are the second sample of each channel and so on. PDM format on the other hand doesn't define a standard. For the sake of using our library, PDM data must be arranged in bytes and those bytes are interleaved for each channel. So in the four channels example you are seeing, the first four bytes represent the first eight PDM bits of each one of the four microphones. The second four bytes represent the second eight bits of each of the four microphones and so on. This information will be useful later on when we dive deeper into the PDM to PCM library. The PDM to PCM library execution can be divided into three phases. Initialization will set all the fundamental parameters which will be fixed for the whole life cycle of the library. Those parameters are set in the initial phase and cannot be changed until a new initialization is performed. Configuration is about setting all those parameters that can be changed later on at runtime. For example, the game setting is one of those configuration parameters. It's set at the beginning with its initial value, but it can be modified at runtime if the user wants to change the volume setting without the necessity to reinitialize the whole library. Conversion is the actual call to the filtering and decimation function. Usually, it's triggered periodically by the data acquisition process. As soon as we have enough data to be processed, we call the processing function. Let's have a look at how those operations are done in the code. Initialization is performed by means of a data structure keeping all the information needed for the correct run of the library. The same structure contains also a portion of memory used for keeping the internal filter state. One of those endlers is needed for each microphone to be converted. Let's go deeper into the parameters themselves. BitOrder and Endianness describe the bit and bytes order in the acquired PDM data. Depending on the peripheral used for the acquisition, PDM data may be arranged differently in the PDM buffer. Instead of forcing the user to rearrange the data externally, the library can handle several scenarios internally. High pass top parameter is used to tune the cutoff frequency of the high pass filter. Further information about the format of this value can be found in the reference manual. In pointer channels and out pointer channels define the number of channels which are present in the input PDM buffer and the number of channels in the output PCM buffer. At each function call, while reading the PDM data, a number of bytes equal to in pointer channels will be skipped in order to process the samples belonging to the same microphone. In the same way, a number of samples equal to output pointer channels will be skipped in the PCM buffer in order to write the samples in the correct position as per PCM standards. This example shows the case when in pointer channels and out pointer channels are both equal to four. Those two parameters are not necessarily equal. If you are acquiring microphones using several peripherals like I2S and SPI as we will see in the following videos you may have PDM data into several different buffers, but when converting them you may want to have all the output data into the same PCM buffer. In this example you will set the in pointer channels equal to two, while the output pointer channels will be equal to four. A different data structure is used to keep the configuration parameters, the ones that can be modified at runtime. A couple of functions are available to set or get the current configuration. The main parameters are the decimation factor, which is the actual decimation factor to be applied to the PDM stream. The output samples number, which is the number of PCM samples to be produced at each call of the processing function. The correct number of input samples must be provided in the PDM buffer to avoid buffer overflows while reading the input data. MIC gain is the gain in decibel to be applied to the microphone signal. A processing function is provided to be called when data to be converted is available. The parameters of this function are a pointer to the first byte of the PDM input, a pointer to the first sample to be written in the output buffer, a handler for the specific microphone. Please note that a handler is required for each microphone conversion and a call to the processing function must be made for each microphone to be converted. Let's go in-depth to see how the whole process works. In the following example, we want to perform PDM to PCM conversion for four microphones. We have an input PDM buffer called PDM buffer with the byte interleaved for the four microphones, as we saw previously. So here is the status of the buffer just before the conversion. We want the output signals to be placed in an array called PCM buffer with the samples interleaved as per the standard. Here's the desired status of the output buffer after the conversion. So let's start from the initialization and configuration of the library. First of all, we have to activate the STM32 CRC peripheral to unlock the library, which can be run only on STM32. Then we will fill the initialization and configuration structure for each microphone. In our case, we will have four microphones, so we will fill all the information for the initialization. Please note that we assign four for both output and input channels, which is consistent with our buffer structure. And then we can call the initialization function. We do the same for the configuration, fill the parameters and call the configuration function. At this point, when the data is available, we can call the conversion function. We are calling the function for each microphone we want to convert, passing the parameters we analyzed previously. So let's unroll this loop and see what happens to the buffers at each call. During the first call, we pass pointers to the first byte of the PDM buffer, the first half-word of the PCM buffer, and the first handler. Since we define the input channel's numbers equal to four, the library will read one PDM byte over four, starting from the first one. In the same way, since the output channels are defined equal to four, the library will write one half-word for each four in the output buffer, starting from the first one. The second call works in the same way, but this time we pass pointers to the second byte of the PDM buffer and the second half-word of the PCM buffer. Also, we point to the proper handler, the one for the second microphone. Bites are read and samples are written as in the figure. During the third and fourth call, the same principle applies. This is the third call and this is the fourth call. At the end of this process, the PDM data coming from our microphones will be converted to PCM and properly placed in the output buffer. You can find more information in these references. Look for the next videos in this series on the ST YouTube channel. Thank you.