Can low jitter be achieved with STM32 microcontroller

Status
This old topic is closed. If you want to reopen this topic, contact a moderator using the "Report Post" button.
Hello,

I have worked on the project this week week-end to progress in my proof of concept:
- I have implemented the DSP framework for 2 ways speakers (3 cascades of buffers, scaling factors),
- I implemented realistic filters related to my speakers (LXmini),
- I played music using the Stm32F4 discovery=>amp analog input=> Speakers.

It works ! (and I have no glitches)...

Then I spent part of saturday and sunday to implement a new Stm32 code to make sure that the DSP results are exactly the expected ones.

Stm32F4 reads a measurement signal from a file on a USB key , applies my DSP treatment and then writes the resulting PCM to the USB key.
Then I import, analyse the results and compare to my reference setup:
=> perfect match !

I have used the excel sheet available on miniDSP website to determine the biquad coefficients.

The code is there https://github.com/jmf13/USB_Async_DAC/tree/CleanerCode

So this DSP part is working well :) Next step if to finalize the async USB part, and last move to the Stm32F7 with SPDIF.

JMF
 
Definition of the filters for 2 way speakers. This is the extrct of the code to adapt for a specif speaker. All the rest should be standard. Not difficult ti use:

Code:
/* ----------------------------------------------------------------------
** definition of all the parameters for the filters and digital signal 
** processing to be performed.
**
** The function process the input buffer with the below sequence:
** - convert the buffer from q15 to float
** - scale the input by SCALE_INPUT value
** - apply Filter1
** - on the result of Filter1, apply Filter2 and fill a new buffer,
**    scale by SCALE_OUTPUT1_3 value, and invert if requested by INVERT_OUTPUT1_3
**    convert from float to q15
** - on the result of Filter1, apply Filter3 and fill a new buffer,
**     scale by SCALE_OUTPUT2_4 value, and invert if requested by INVERT_OUTPUT2_4
**    convert from float to q15
**
** Filter1, Filter 2 and Filter3 are Biquad cascades defined by:
** - NUMSTAGES_FILTERx
** - CoeffTableFilterx
** Biquad filters format is b0, b1, b2, a1, a2
**
** The digital processing is the same for the Left and Right channels
** This part is the only part to modify for the specific application
** ------------------------------------------------------------------- */

#define SCALE_INPUT        1    //scaling factor applied to input buffer

#define NUMSTAGES_FILTER1    2    //number of biquads in this filter
float32_t coeffTableFilter1[5*NUMSTAGES_FILTER1] = {
        x.003791623405750, -1.916261673869340, X.966920997039797, X.916261673869340, X.970712620445551,  
        x.052140969066160, 0.931305193641266, X.899631210773041, X.931305193641266, X.951772179839199     
};



#define SCALE_OUTPUT1_3_dB        0    //scaling factor applied to output buffer 1 and 3 in dB
#define INVERT_OUTPUT1_3     false

#define NUMSTAGES_FILTER2    4    //number of biquads in this filter
float32_t coeffTableFilter2[5*NUMSTAGES_FILTER2] = {
        X.001921697757295, X.003843395514590, X.001921697757295, X.824651307057290, x.832338098086468,     
        X.003858302013990, X.993727804265180, X.989912205497575, X.993727804265180, x.993770507511564,    
        X.925455940386243, X.431501433736160, X.897376826164088, x.431501433736160, x.822832766550331,    
        X.884138082603731, X.204926343048180, X.776971533616450, x.204926343048180, x.661109616220181
};


#define SCALE_OUTPUT2_4_dB        X.X    //scaling factor applied to output buffers 2 and 4 in dB
#define INVERT_OUTPUT2_4         true

#define NUMSTAGES_FILTER3    6    //number of biquads in this filter
float32_t coeffTableFilter3[5*NUMSTAGES_FILTER3] = {
  .....
};

/* ----------------------------------------------------------------------
** End of definition of all the parameters for the filters and digital signal 
** processing to be performed.
** ------------------------------------------------------------------- */

Note: I replaced in the code some coefficients numbers by X as the filter in under IP restrictions.
 
As of SPDIF, are you going to implement some kind of ASRC? The STM32 itself cannot recover masterclock from SPDIF data. And with ASRC async USB audio is not necessary at all...

Hi Romanetz, Yes, it seems that you are right.

My goal is to use the SPDIF output only, as I'm using Full Digital Amps with SPDIF inputs (FX-Audio D802). I will one amp for each speaker, so two and for my audio set-up.

As for now, I will get the input from Async USB, which looks perfect for my application.

Sure, having some resampling routines for the Stm32 could help to enlarge applications.

One other thing to develop for my audio application, is the delay function, to be able to implement fine delays between channels for time alignment. One example would be the mTap function from Charlie Laub.

JMF
 
Are you going to use USB_OTG_HS with external PHY? I have another board with STM32F4 and airwired USB3300 board, can check this setup. Will you implement controls of DSP part using USB Audio Class vendor-specified controls, to show them in Windows Mixer?


Hello,

I have not the skills to develop the above things. I will reasonably focus on implementing an easier to develop set-up where parameters are hard coded in the code itself. However, if this early work could prove the interest of Stm32 platform and attract more skilled developers'... that would be nice.

Thanks for the link to that other project :) I don't read Russian, but will have a look at the code. Did they published the schematics for the external clock?

JMF
 
No, there wasn't any schematics. Several frequencies are still not implemented, i'm working on it (the way: add list of frequencies in ascending order in Format Type I descriptor, set maximum size of output endpoint of (max_freq*bit_res/8*n_channels/1000) and then either set gpios to switch external generators or play with PLLI2S settings). I'm in doubt if DMA size should be equal to size of single frame of sound. I see that it's not necessary.
AudioControl interface (endpoint 0) requests for setting and getting current value of sampling frequency are already implemented in the code.
 
I did some tests with the ST USBD audio device example (audio standalone) to check the behaviour when stopping and pausing the music on the music player.

Pause is OK: the player (at least foobar) continues to stream zeros (which means silence). The example code and my code work. Resuming works also.

But when we stop playing, the host stops to send frames. My code and the example code generates a strange noise because it continues to try to play without mofifying anymore the buffers.

This is to be corrected. The output should be muted when we arrive to a very low buffer. It should for example resume when we recover to half buffer. The trick is to mix that with the feedback calculation as in this case the low buffer has an explanation...

It is not very clear to me how it is dealt with in sdr_widget.

JMF
 

Hi Romanetz,

I just checked the code you provided. I understand that:

In DataOut you set out_stop to 1 at the end,

In SOF you set out_stop to 0 at the end. Just before you checked if it was already 0 and if it is the case (no Dataout in between), you stop the player.

This is clever, but there is a point that I don't understand: if we don't have data sent by the Host, will there still be a SOF? Or said differently, how can we have 2 consecutive SOF without data in between?

I would be happy to learn.

Best regards,

JM
 
Thank you for the information Romanetz.

It seems that you are pretty active and efficient in Russia with this Stm32 usage, especially as radio amateur. Much more than any other country I have seen looking for information about Async USB :)

Is there from your perspective some explanation to this fact?

Best regards,

JMF
 
SDR is very popular way in amateur radio and SDR software was designed to work with audio cards as a cheap ADC+DAC. It has begun from integrated sound cards but very soon people realized that low level of noises is achievable only with external cards. A progress in technologies has led to next generation of radios with DirectDownConversion and DirectUpConversion implemented in FPGA. So, USB allows to connect FPGA almost directly to the PC. Moreover, amateurs are very attracted by plug-n-play capabilities of USB. Now it's common to associate several interfaces such as HID or CDC and audio in one composite device.
 
Hi,

For information: new M7 core coming (and nucleo board) with 4 SAI (ie 8 "audio lines") at 400MHz
http://www.st.com/en/microcontrolle...l_pron_oct2016&querycriteria=productId=SS1951

Not bad... and this demonstrates the benefit effort of portable code on a general purpose core and active product range...

At the moment; I'm stucked with a stupid bug described here: https://my.st.com/public/STe2ecommu.../cortex_mx_stm32/AllItems.aspx&currentviews=0

Hower, I hope to be able to start working on using the nucleo F7 board, SAI and SPDIF in coming weeks...

JMF
 
Status
This old topic is closed. If you want to reopen this topic, contact a moderator using the "Report Post" button.