For experts: when you want to bring VisionShields PDM MIC via USB audio (as USB recording device) to PC - you might experience audio artefacts (audible clicks in audio with a periodic frequency).
This is based on my experience done with my VFR project:
Portenta H7 VFR project
Why?
The clocks of two components in system are independent and they drift away, they are not really identical.
I use SAI4 for PDM MICs (as Ardunio/mbed does). it runs with MCU internal PLL3, approx. 48 KHz.
USB-A (FS, on main/breakout board) uses also a PLL, with 48 MHz. This clock is used for the bit transfer via USB, but does not mean it is the "USB Audio Clock".
There is also a real "USB Audio Clock", for the transfer for samples via USB Audio. But this clock is generated by the external Host PC: the PC requests USB Audio frames. And this clock is independent (free running), not in synch, or even a bit off in relation to the MCU internal clocks or a slightly different frequency as SAI4 would run for the MICs.
Two clock sources: one for MCU internal SAI4 (for the PDM MICs, generated internally by MCU), one on the host PC side, for the USB timing, to request new USB Audio (every 1 KHz).
So, after a while (actually a short period of time), the clocks are drifting, SAI4 for MIC is not "in sync" with the USB timing: the buffers for PDM MIC and USB sent to host PC, "pass each other", one is faster as the other. You overrun a buffer, you miss some data (if PDM MIC is slower) or you have too much data (if PDM MIC is faster).
You get audible clocks, with a constant period, depending on the clock frequency difference. The more the clocks are different in nominal frequency - the faster clicks.
And it was pretty drastic in my case, e.g. the clock frequencies differ by approx. 100 Hz, so, every 10 ms such a click (sounds like distortion and it is due to "corrupted" data content).
How to solve?
It is tricky: in general: the SAI4 (for the PDM MICs) must run with exactly the same (coupled) clock as USB. But not so easy, maybe with external means and using the USB SOF signal. But how to generate an SAI4 clock from it? (it is not an 48 MHz signal).
The PC getting the USB audio is the clock master! How to generate a clock from USB for SAI4?
So, my solution:
- I use two different PLLs, PPL1 for the 48 MHz used for the USB peripheral (but just serial bit clock, not related to PC Audio Clock!)
- SAI4 runs on PLL3 (which is not used really for other devices)
- each PLL, also PLL3, has a "fractional multiplier": this can be used in order to fine tune the generate PLL clock out frequency. Just set proper PLL config values in order to have a range you need for fine tune with "fractional".
I tried to trim PLL3, the "fractional multiplier" to bring both clocks (USB and SAI4) to the same frequency (using a scope on GPIO pins). This has removed all the clicks and artefacts; maybe there is still one after a long time (but know after seconds or minutes). The clocks are still "floating" and drifting away, but now they are "nominal the same" for a long period of time (but no guarantee).
Correct solution:
The correct solution, when we have to deal with two INDEPENDENT clock sources (one for SAI4, internal in MCU, the other for USB where clock is generated by the host PC), which are never "in sync" (not correlated or coupled with each other) -
we need an "Adaptive Clock Recovery".
Luckily, the MCU supports to set the "fractional multiplier" without to stop the PLL. This is cool!
So, we could adjust this value during run time, so that the generated clock is modified, trying to stay at the same frequency as the other clock. Try to let follow one clock the master clock (here PC USB Audio clock): adjust the frequency a tiny bit, up and down.
My intended approach:
I measure the time tick, e.g. via SYSTICK counter (not the 1 ms interrupt, the real fast running counter in MCU), in order to know when SAI4 and USB interrupt has been invoked.
I find the time difference between both, e.g. during the first few iterations to see when SAI4 and USB interrupt are triggered. This timing relation should be kept the same all the time.
Now, I try to keep this difference value as constant, the same all the time: I trim the SAI4 clock via "fractional multiplier" to adjust its clock. So, it should run with the same clock as USB now, after a while, following the USB clock.
Does Arduino use Adaptive Clocks?
I have checked the Arduino/mbed code (repository) and I have not seen that such approach is there. It has code for the PDM MICs, also for USB Audio (as USBPluggable device), potentially you can try to bring the VisionShield PDM MICs via USB to a host PC.
But what about this clock issue?
If Arduino does not do this "clock recovery" or "adaptive clock" - you will hear the artefacts due to "glitches" in buffers (one is faster as the other, not enough samples or too many, and the "audio jumps". generating an audible click artefact).
Conclusion:
The MCU is cool, this fractional PLL trim helps a lot to deal with "asynchronous clock domains".
But if Arduino/mbed would do it right? (potentially not, and no way to bring PCM MICs via USB to a PC).