cancel
Showing results for 
Search instead for 
Did you mean: 

Record audio using DFSDM and send the data over UART

anwvo
Associate II

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.
1 ACCEPTED SOLUTION

Accepted Solutions

>> 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.

If you feel a post has answered your question, please click "Accept as Solution".

View solution in original post

6 REPLIES 6
AScha.3
Principal III

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 ?

If you feel a post has answered your question, please click "Accept as Solution".

> 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"?


>> 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.

If you feel a post has answered your question, please click "Accept as Solution".

You didnt tell, you use a B-L475E-IOT01 board 

Well, that was the first sentence of my post. Anyway.

After some testing, the problem is indeed with the UART speed. Even if:

  • I enable DMA for UART Tx,
  • I use 115,200 bps for the UART transfer,
  • I slow down the audio clock to get 16 kHz sampling,

the UART is still too slow for the audio. I monitored the callbacks using ITM_Send, and it shows that my DFSDM DMA buffer gets full four times during the period it takes for the UART to finish transmitting.

> Yes, so much data - you have to store it ,

Where could I store it? I read that flash is not good for large writes at runtime, it will wear out too quickly.

> 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.

Is this possible with an STM MCU or do I need a specialized module?

Thanks for your help!

>Well, that was the first sentence of my post. Anyway.

Right. Bad eyes...sorry. 🙂

>the UART is still too slow for the audio.

First (always!) calculate : i want read data here->transfer->receive ; is speed possible at all ?

-> so 42kHz x 2ch x 16b = about 1,4Mbit . = your needed minimum transfer speed .

>Where could I store it?

If sd-card or USB stick there, should be possible. (But no easy game.)

> USB audio device >Is this possible with an STM MCU ..

Yes. Your card has (from manual): 

  • USB OTG FS with Micro-AB connector

-> need library/driver for USB audio device , also no easy game. But will work.

If you feel a post has answered your question, please click "Accept as Solution".
anwvo
Associate II

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