Record audio using DFSDM and send the data over UART
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-02-18 10:10 PM - edited ‎2024-02-18 10:13 PM
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;
}
}
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;
}
}
Solved! Go to Solution.
- Labels:
-
DFSDM
-
DMA
-
STM32L4 Series
-
UART-USART
Accepted Solutions
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-02-19 12:14 AM - edited ‎2024-02-19 12:31 AM
>> 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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-02-18 11:45 PM - edited ‎2024-02-19 12:15 AM
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 ?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-02-18 11:51 PM - edited ‎2024-02-18 11:53 PM
> 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"?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-02-19 12:14 AM - edited ‎2024-02-19 12:31 AM
>> 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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-02-19 4:34 AM - edited ‎2024-02-19 4:37 AM
> 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!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-02-19 5:30 AM
>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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-02-19 6:29 AM - edited ‎2024-02-19 6:30 AM
I was able to get real sound data by increasing the UART transfer rate way up (1843200 bps). Thanks!
