Hi all,
I think it's time for me to jump in again...
I've been trying to deal with this problem for some time and am having some good luck in solving the problem for my own hardware design. Perhaps there may be some insights here for you in my incomplete solution...
I use an SGTL5000 codec for the heart of my design and clock it from a spare channel of an si5351 clock oscillator. The si5351 generates quadrature clocks for the Tayloe style modulator and demodulator. The third channel is used to generate the nominal 12.288mhz clock for the SGTL5000.
In addition, my hardware allows use of the same codec for the microphone/line input and for receiver speaker/line outputs.
When I designed the hardware, past experience with the two clock problem led me to believe that one way to simplify things would be to keep everything synced to the same 48khz sample rate from a single clock. This design helps to achieve this. This requires some complicated T/R switching however to reconfigure the audio routing as needed for half-duplex operation to turn the input and output channels around to serve both IQ in -> speaker and mic in -> IQ out. It certainly practical to do this, but it REALLY complicates the changeover.
Although I was able to design and build prototype software that takes advantage of this and works well, it turned out that in the real world writing transceiver software is a problem because of the thousands of tiny details it takes to make a useful and usable radio. I've had to abandon the hope of writing my own at this time. Projects like Quisk deal well with these details and Jim has done an outstanding job of juggling them to give a very polished result so I've decided to focus on interfacing my hardware with Quisk.
This meant abandoning (for now) the idea of using the same codec for all 4 endpoints since most standard software assumes separate devices for IQ io and operator audio IO and is not easily modified to handle the needed multiplexing. I'm fine with that for now, especially since the trend is to embed digital IO directly in to the endpoint devices and most systems now have one interface device per endpoint - not to mention the complication from non hardware IO sources like CW oscillators and monitors and external digital programs like WSJT-X!
Unfortunately, this makes the classic "Two Clock Problem" into a much more complicated "N clock" problem! It becomes a game of "Whack-a-Mole" that requires a lot of compromise and messy fixes for mode and TR switching.
The present Quisk fixes this using simple "interpolate/drop" resampling, and it usually seems to do the job of keeping things from overflowing most of the time - at least for the classic 2 input/2 output situation. Interfacing to external program is another question, but I'm avoiding that problem for now as the situation has become fluid again now that "Pulse Audio" is now dead and has become yet another legacy API implemented by emulation in Linux.
Anyway! back to the matter at hand:
I've been testing a hacked in API to read the error correction variable "cr_correction" in the quisk output drivers (sound.c) from the python hardware API and then to use it to trim my codec clock frequency periodically to keep the buffer levels stable and hopefully minimize the need for the existing resampling method.
I temporarily replaced one of the fields in the Config/status communication from the real time thread with the live "cr_correction" value. This allows it to be read (inefficiently) from the 10hz periodic method call in the hardware interface. I initially made no other modifications to the real time thread for these experiments.
I then used code runninng about every 5 seconds to read that value and use it to implement a simple proportional feedback loop to adjust the si5351 channel that clocks the codec. Once it locks up, this keeps things to within 10-15hz and prevents the resampling logic from coming in to play completely.
This works well enough to achieve my original goal of fixing the IQ output artifacts from the splice/drop resampler that were making the output spectrum of the modulator a real mess. It didn't help the receiver however, so I decided to experiment some more...
I'm running a klugy scheme right now to keep separate codec clock values for transmit and receive and swap them as needed during T/R switching. The other channel reverts to "chop/splice" during this period, but it's not in use, so the problem is not audible.
It works nicely, but it takes a long time to settle down - especially because each channel must now recover from an additional error transient during the changeover.
I changed "sound.c" to update the correction value once per second instead of every 10 seconds and that helped a lot, but basically I think I need a much fancier software PLL design to do the correction and am working on that right now.
My intention is to wait until I have a solution I'm happy with and then request that the distribution releases of quisk implement a simple API to allow this to be optionally done from the hardware.py file eliminating any need for recompilation. I believe all that will be needed will be a python API to allow reading the correction values.?
I originally hoped that no method of changing the behavior of the existing resampler would be needed, but it's starting to look like it may at least require an option setting added to adjust the integration time for the error values to make this work.
I think this would be useful to other HW designs as well.
I'll continue to report as I learn more, but the project is proceeding slowly as there's a lot to mull over and I'm not as young as I used to be (!)
Anyway, my advice to Rob is to try to work a finely programmable clock into to your codec design! It is very helpful to be able to trim the audio clock frequency without causing a major disruption as that will cause a phase glitch in the IQ signals. The si5351 does this well, but other methods may be possible...
As far as the external quisk interprogram interfaces go, that's going to be a problem in any case as the new sound api in Rasbian is being revised weekly and the latest revisions appear to have broken quisk's pulse audio IO for wsjtx. It is now being shut down by pipewire after a few minutes of non-use. I'm waiting for that situation to stabilize before I worry about it...
That's all for now - once again a million thanks to Jim for his hard work in getting us this far!
M