Can low jitter be achieved with STM32 microcontroller

Good news for the UAC2 driver coming in windows. And Thanks for the explanation on the small limitation on the feedback value from TIM2. Can this cause a very slow "second order" drift in buffer levels that cause problem if not corrected, or is it something which is "self correcting"?

I have to look at the code you uploaded. One other thing I think you made was an external clock module, to provide the needed frequencies for the application. Schematics and implementation would be interesting here also.

Last, I'm still very curious about how you change the USB slew rate and that the affect could be.

Best regards,

JMF
 
Code is here.
Your project is not affected by this bug.
I continue to develop this branch because it needs only minor changes to satisfy me (and, hope, not only me)
File usb_bsp.c

#ifdef USE_USB_OTG_FS

RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOA , ENABLE);

/* Configure SOF VBUS ID DM DP Pins */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 |
GPIO_Pin_9 |
GPIO_Pin_11 |
GPIO_Pin_12;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz; // <-------- was 50!!!
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitStructure);
 
int16_t Audio_output_buffer[AUDIO_OUTPUT_BUFF_SIZE * 2]; // This represents two buffers in ping pong arrangement stereo samples int16_t Audio_buffer_L[AUDIO_OUTPUT_BUFF_SIZE/2]; //one ping pong buffer, Left channel int16_t Audio_buffer_R[AUDIO_OUTPUT_BUFF_SIZE/2]; //one ping pong buffer, Right channel int16_t Audio_input_ring_buffer[AUDIO_INPUT_BUFF_SIZE]; // We want to work between 1/3 and 2/3 buffer, pulling AUDIO_OUTPUT_BUFF_SIZE at a time

.....



for(i=0; i<AUDIO_OUTPUT_BUFF_SIZE/2; i++){ Audio_output_buffer[AUDIO_OUTPUT_BUFF_SIZE*buffer+2*i]= Audio_buffer_L; /*Left Channel*/ Audio_output_buffer[AUDIO_OUTPUT_BUFF_SIZE*buffer+2*i + 1]= Audio_buffer_R; /*Right Channel*/ }

not tested, but i think this should be faster:
int16_t *pout=Audio_output_buffer;
int16_t *pin_l=Audio_buffer_L;
int16_t *pin_r=Audio_buffer_R;

for(i=AUDIO_OUTPUT_BUFF_SIZE/2; i>0 ; i--) {
*pout++=*pin_l++;
*pout++=*pin_r++;
}

maybe another way could be to use 32bits output pointer to reduce memory access... But I don't know well the architecture of the STM32.
something like that (again not tested):

int32_t *pout=Audio_output_buffer;
int16_t *pin_l=Audio_buffer_L;
int16_t *pin_r=Audio_buffer_R;


for(i=AUDIO_OUTPUT_BUFF_SIZE/2; i>0 ; i--) {
*pout++=((*pin_l++)<<16)) | (*pin_r++) ;
}


If speed is increased, it means it is better to use 32 bits pointers to reduce memory acces.
This can be done as well with sample input pointers.

in this case, main loop should be something like that (need debugging)

int32_t *pout=Audio_output_buffer;
int32_t *pin_l=Audio_buffer_L;
int32_t *pin_r=Audio_buffer_R;


// need to fill the first datas if size is not multiple of 4 (see the loop below)

....

for(i=AUDIO_OUTPUT_BUFF_SIZE/4; i>0 ; i--) {
int32 l=*pin_l++;
int32 r=*pin_l++;
int32 a=(l<<16) | (r&65535) ;
*pout++=a;
a=(l&(~65535)) | (r>>16) ;
*pout++=a ;
}

Sorry I expected to have time to work on it, but I am very busy.. :(
Please tell if it helps or if you need debugging tips with eclipse.

regards,
 
Regarding the file:
stm32f4xx_hal_i2s.c

and the doc:

(#) There is two mode of transfer:
(++) Blocking mode : The communication is performed in the polling mode.
The status of all data processing is returned by the same function
after finishing transfer.
(++) No-Blocking mode : The communication is performed using Interrupts
or DMA. These functions return the status of the transfer startup.
The end of the data processing will be indicated through the
dedicated I2S IRQ when using Interrupt mode or the DMA IRQ when
using DMA mode.

There are 2 transfert modes (in non blocking mode):
DMA and interrupts
Interupts may be the best choice.
If yes, It should be possible to rewrite a little bit the interrupt handler to work with 2 output buffers instead 1. And use less CPU to mix left and right channel.

But again please excuse me, it is 2 minutes reading so....
 
Please explain your idea in this code. Do you want to split (multiplexed) stereo signal from host into two separate buffers? And then process them? Or just swap two channels between?

my goal was just to provide a faster routine.

I agree with you (see my previous post) we can speed up the process with a little improvement of the source code architecture.
 
No interest? Or what? Is there anybody who have tried? I can modify the firmware to run with internal PLLI2S on bare STM32F4-DISCOVERY, you'll need to place only single wire between PC7 and PA15. Only several minor changes are needed (change two #defines - MCLK_OUTPUT_DISABLED replace with MCLK_OUTPUT_ENABLED and remove MCLK_FREQUENCY )
MCLK from plli2s is inaccurate and a little bit lesser than required (orange LED blinks, showing that host sends frame of reduced size)
 
Last edited:
Hi Romanetz,

I recognize that I'm interested in your code, but have only a limited time per week allocated to this project, and low knowledge stm32. All this makes me progress very slowly and not being so responsive.

I have choices to make between learning things like Git, learning Stm32, learning from other's code, having my code progress.

It seems to me that people here are often interested in turnkey solutions that directly answer to their needs. I hope to be able to develop a sort of semi turnkey solution for USB (16bits, 48 kHz) => DSP => multichannel I2S or SPDIF. This is my target.

Last, we are not helped by the fact that there is no common IDE. So there are significant entrance fees to import code that is not in the exact structure you are working with (at least for beginners).

I have no clock for generation of 12.288 signal. I would be very happy to learn about how to build one with standard components and prototyping board (without having to make a dedicated PCB).

I understand that the main benefit of your code is using the TIM2 timer to calculate the feedback. Do you confirm? Are there some other parts of the code you think are good to have a look at?

I looked at your code yesterday, and I understand that you don't use Hal libs and stm32cube. Do you confirm?
 
To share, this is my proposed roadmap for my project:
  • Finalize my proof of concept, by implementing realistic filters for my pair of 2 ways speakers, and be able to drive on speaker by the discovery board DAC.
  • Check the consistency of the DSP calculations with my reference design using Charlie Laub tools and libs
  • Clean the code and finalize a USB API for Audio, with reinjecting things in the usb_audio part (management of the audio state machine and input circular buffer)
  • Port the code to Nucleo Stm32F7 for ISAI / Spdif / multichannel
JMF
 
Until feedback endpoint won't be sent right under any circumstances... I've tested your binary. It does not.

My bad... this has to be corrected. Did you identified some pattern ? Do you have the issue in nominal operation streaming music, or when changing something like plugging/unplugging, starting, stopping?

Do you think that it is more related to:
- the EP send mechanism and parity issues?
- the state machine that drives the USB communication/music streaming?

Thank you for pointing the thing out.

JMF