Precise measurement/adjustment of SAI1_CLK_ROOT.

hatchjaw

Member
(First, if this isn't the appropriate category in which to post, please feel free to relocate this thread!)

I've posted previously about my networked/distributed audio experiments, and I'm looking again at synchronising audio across a network of Teensy 4.1s as best I can.

I know I can start and stop PLL4 while Teensy is running, and adjust the rate of the SAI1 clock. What I would like, is a way to derive a high-resolution clock from the audio subsystem.

Imagine for a moment that my Teensy is receiving a really accurate 1 PPS signal*. I would like to measure, the number of cycles of the SAI1 clock between two pulses. I know that, ideally, in one second, that clock should cycle 11,289,600 (44100 * 256) times per second; if I detect more cycles than that, then I should adjust PLL4 to generate a lower frequency; fewer cycles, higher frequency. The aim is to condition SAI1 to run at the rate indicated by the 1 PPS source.

My suspicion is there's no equivalent to the cycle count register (ARM_DWT_CYCCNT, 0xE0001004) for PLL4. I tried duplicating and modifying AudioOutputI2S and counting calls to MyOutputI2S::isr(), but that's only called twice per buffer, when DMA requests one half or the other of it, so, at AUDIO_BLOCK_SAMPLES=32, resolution is only ~2.756 kHz. Can anyone suggest a more accurate/higher-resolution approach? Is such a thing possible?

Any advice or suggestions very gratefully received.

* In practice I want to attempt a software PTP implementation, which jitter on the network may render completely unfeasible. In any case, I have to at least give it a try.
 
You might want to look at Dan Drown's Teensy NTP Server. I'm not sure if by "network" you mean Ethernet network, but Dan's project shows how to derive an accurate timestamp using a 1 PPS signal from a GPS module. The basic idea is to use input capture on the 1 PPS and keep track of a "correction factor" to go from timer clock pulses to an accurate time. He uses the 1588 capabilities of the T4 Ethernet peripheral, so I think that might give you some ideas.
 
Hello, and thanks for the reply! I looked up teensy-ntp (and the thread in which Dan introduces that project); I'm certain that I'll be able to learn a lot from it, particularly the PID implementation (to date I've just been using a buffer-fill-level/delay-locked-loop algorithm for low-accuracy sync).

I've been working with unmanaged switches with the aim of keeping things low-cost/accessible, and had ruled out hardware PTP, so (to my discredit) I didn't realise that the iMX RT1060 provides IEEE 1588 support. I guess an unmanaged switch wouldn't remove physical layer timestamp information (it just wouldn't be able to add any of its own); seems to be corroborated by this blog post.

I'm wondering whether anyone can help me better understand the ENET Adjustable Timer Control Register and Timer Value Register (ENET_ATCR/ENET_ATVR). Are these related to/derived from PLL6? Does the ATCR (or ENET_TCCRn) actually adjust the clock from which 1588 timestamps are derived?

Since the thing I'm interested in is synchronising audio between Teensies, how could I use incoming timestamp info in the ENET part of the system to set the SAI1 clock? I guess they, and PLL1, are all derived from the 24 MHz crystal oscillator, so if I were to compare ARM_DWT_CYCCNT (internally consistent) with ENET_ATVR (conditioned to be consistent with external clock) I could calculate a ratio by which to adjust SAI1...

There's a good chance that the above is nonsense, so if anyone can point me in the right direction I'd be really grateful.
 
Back
Top