Skip to main content
Explorer
February 19, 2024
Solved

Record audio using DFSDM and send the data over UART

  • February 19, 2024
  • 2 replies
  • 3152 views

I have a B-L475E-IOT01A2 board. I'm trying to use the onboard microphones to record audio, using the DFSDM peripheral, and then send the data over UART to my PC to play it back. The thing is, the data I get is basically just static.

Here is how I configured the DFSDM peripheral in CubeMX, based on the "DFSDM_AudioRecord" example for the eval boards

  • Source for output clock is audio clock. SAI1 is clocked at 13.714286 MHz, the divider is set at 5 to get 2.74 MHz.
  • Channel 1 and 2:
    • SPI with falling (resp. rising) edge, internal SPI clock
    • Offset = 0, right bit shift = 0x02
    • Analog watchdog (I think is unused): FastSinc, oversampling = 10
  • Filter 0 and 1:
    • Regular channel selection 1 (resp. 2)
    • Continuous mode, software trigger, fast mode and DMA mode enabled
    • No injected channels
    • Sinc 3 filter
    • Filter oversampling : 64 to get 42.85 kHz. Integrator oversampling: 1 (bypass).
  • DMA channels set for both filters, peripheral to memory, high priority, circular mode, increment memory address automatically, data width = word.
  • DMA channels and filter interrupts enabled.

Now, for the code:

 

 

#define DFSDM_RECORDING_SIZE 2048

static bool left_dma_half_complete = false;
static bool left_dma_full_complete = false;
static bool right_dma_half_complete = false;
static bool right_dma_full_complete = false;

static int32_t left_rec_buf[DFSDM_RECORDING_SIZE];
static int32_t right_rec_buf[DFSDM_RECORDING_SIZE];
static int16_t output_buf[DFSDM_RECORDING_SIZE * 2];

static HAL_StatusTypeDef status;

// ...
// in main():

 if (HAL_DFSDM_FilterRegularStart_DMA(&hdfsdm1_filter0, left_rec_buf,
 DFSDM_RECORDING_SIZE) != HAL_OK) {
 Error_Handler();
 }
 if (HAL_DFSDM_FilterRegularStart_DMA(&hdfsdm1_filter1, right_rec_buf,
 DFSDM_RECORDING_SIZE) != HAL_OK) {
 Error_Handler();
 }
 while (1) {
 if (left_dma_half_complete && right_dma_half_complete) {
 for (int i = 0; i < DFSDM_RECORDING_SIZE; i++) {
 output_buf[i * 2] = clamp(left_rec_buf[i] / 256, -32768, 32767);
 output_buf[i * 2 + 1] = clamp(right_rec_buf[i] / 256, -32768, 32767);
 }
 status = HAL_UART_Transmit(&huart1, (uint8_t *)output_buf,
 DFSDM_RECORDING_SIZE * 4, 1000);
 if (status != HAL_OK) {
 Error_Handler();
 }
 left_dma_half_complete = false;
 right_dma_half_complete = false;
 }
 if (left_dma_full_complete && right_dma_full_complete) {
 for (int i = 0; i < DFSDM_RECORDING_SIZE; i++) {
 output_buf[i * 2] = clamp(left_rec_buf[i] / 256, -32768, 32767);
 output_buf[i * 2 + 1] = clamp(right_rec_buf[i] / 256, -32768, 32767);
 }
 status = HAL_UART_Transmit(&huart1, (uint8_t *)output_buf,
 DFSDM_RECORDING_SIZE * 4, 1000);
 if (status != HAL_OK) {
 Error_Handler();
 }
 left_dma_full_complete = false;
 right_dma_full_complete = false;
 }
 }

 

 

 

 And the callbacks:

 

 

 

void HAL_DFSDM_FilterRegConvHalfCpltCallback(
 DFSDM_Filter_HandleTypeDef *hdfsdm_filter) {
 if (hdfsdm_filter == &hdfsdm1_filter0) {
 left_dma_half_complete = true;
 } else if (hdfsdm_filter == &hdfsdm1_filter1) {
 right_dma_half_complete = true;
 }
}

void HAL_DFSDM_FilterRegConvCpltCallback(
 DFSDM_Filter_HandleTypeDef *hdfsdm_filter) {
 if (hdfsdm_filter == &hdfsdm1_filter0) {
 left_dma_full_complete = true;
 } else if (hdfsdm_filter == &hdfsdm1_filter1) {
 right_dma_full_complete = true;
 }
}

 

 

 

My receiver program on the PC can get data properly: I checked by sending dummy data and verifying that the data is the same as what the UART sent.
When I run the above code for about five seconds, I received about 32 kB of data. That's way too small for 42 kHz sampling rate WAV data... If I try to import that in Audacity (Signed 16 bit PCM data, big endian, stereo mode) the audio is only a few milliseconds long.
Now, I may completely misunderstand how DFSDM rate works. If instead I take 42 kHz to mean 42 bits per seconds (rather than int32 per seconds) then the audio length is reasonable, about five seconds. But then it's only static.
What's going wrong? Am I using the DFSDM peripheral correctly?
Note that I cannot independently test that the microphones are working - apparently they're sensitive to ESD... But since there aren't any working full examples for B-L475E-IOT boards anywhere, I cannot compare my solution to a reference point.
    This topic has been closed for replies.
    Best answer by AScha.3

    >> Basically i dont see, what you do with the data in real time, that you generate: 42,8KHz x 2 ch x 16b = 13,7 Mbit data rate .

    I don't understand this sentence. Can you rephrase?

    I made complex sentence - just to say : sooo much data - where do you store it ?

    But i calculate wrong (decimal point...) , i edit. its 1,37Mbit --- and thats possible on usb or on uart .

    +

    > At > 1,4 Mbit ?

    I guess that's where my issue comes from. I didn't think about that. My test is indeed at a very low speed. Do you have any suggestions on how to get the data fast enough to the PC?

    Yes, so much data - you have to store it , or make USB audio device (= sound card) , to send over USB audio; here i see the best way to get 48kHz (this is the standard speed) 16b stereo to a pc.

    On uart : what speed you set ? You need 2 Mbit (minimum) and send with DMA; blocking/polling probably too slow.

    +

    > can you show the circuit,

    > what and how you make the data stream for input ?

    You didnt tell, you use a B-L475E-IOT01 board .  No its clear to me : onboard dig. mics -> DFSDM ... ok.

    +

    So first decide, how to do with that data in real time - sending to pc could work on USB or UART .

    Then test with a small and fixed data block, with no real data, but something like a sawtooth pattern, thats easy to see : good or not.

    2 replies

    Super User
    February 19, 2024

    Basically i dont see, what you do with the data in real time, that you generate: 42,8KHz x 2 ch x 16b = 13,7 1,37 Mbit data rate .

    >My receiver program on the PC can get data properly

    At > 14 Mbit ?? how you do this magic speed on UART ?  You proved with a test ?

    +

    Can you show the circuit, what and how you make the data stream for input ?

    anwvoAuthor
    Explorer
    February 19, 2024

    > Basically i dont see, what you do with the data in real time, that you generate: 42,8KHz x 2 ch x 16b = 13,7 Mbit data rate .

    I don't understand this sentence. Can you rephrase?

    At > 14 Mbit ?? how you do this magic speed on UART ?

    I guess that's where my issue comes from. I didn't think about that. My test is indeed at a very low speed. Do you have any suggestions on how to get the data fast enough to the PC?

    can you show the circuit,

    There is no "circuit", the board is just connected to my PC via USB and the integrated ST-Link. As I said, it's a B-L475E-IOT01, so I guess the circuit you might want is the one in the datasheet: https://www.st.com/resource/en/data_brief/b-l475e-iot01a.pdf

    what and how you make the data stream for input ?

    I don't understand your question - what do you mean by "make the data stream for input"?


    AScha.3Answer
    Super User
    February 19, 2024

    >> Basically i dont see, what you do with the data in real time, that you generate: 42,8KHz x 2 ch x 16b = 13,7 Mbit data rate .

    I don't understand this sentence. Can you rephrase?

    I made complex sentence - just to say : sooo much data - where do you store it ?

    But i calculate wrong (decimal point...) , i edit. its 1,37Mbit --- and thats possible on usb or on uart .

    +

    > At > 1,4 Mbit ?

    I guess that's where my issue comes from. I didn't think about that. My test is indeed at a very low speed. Do you have any suggestions on how to get the data fast enough to the PC?

    Yes, so much data - you have to store it , or make USB audio device (= sound card) , to send over USB audio; here i see the best way to get 48kHz (this is the standard speed) 16b stereo to a pc.

    On uart : what speed you set ? You need 2 Mbit (minimum) and send with DMA; blocking/polling probably too slow.

    +

    > can you show the circuit,

    > what and how you make the data stream for input ?

    You didnt tell, you use a B-L475E-IOT01 board .  No its clear to me : onboard dig. mics -> DFSDM ... ok.

    +

    So first decide, how to do with that data in real time - sending to pc could work on USB or UART .

    Then test with a small and fixed data block, with no real data, but something like a sawtooth pattern, thats easy to see : good or not.

    anwvoAuthor
    Explorer
    February 19, 2024

    I was able to get real sound data by increasing the UART transfer rate way up (1843200 bps). Thanks!