How to handle asynchronous input and synchronous output? - Page 1
Forum section: electronics / projects

author: syntax333
author_rank: Regular Contributor
timestamp: April 21, 2021, 05:54:41 pm
content: Hi,I am currently working on a project where I have USART input and SAI(Serial Audio Interface, similar to SPI) output on an STM32 system.I created a circular buffer which act as pinpong buffer(double buffer) structure. The input samples which received from USART are stored in this buffer where the head pointer points. When SAI peripheral requests new data, data is pulled from this buffer's tail pointer.At the start of my code I wait until half the buffer is filled then activate SAI. SAI outputs at constant rate which is 40kHz. Input samples are received from external device's USART at approximately at same rate 40kHz.Ideally, I expect the difference between my head and tail pointer to be constant.I also implemented a protection mechanism which makes the Tail pointer wait and output the latest sample from SAI until half of the buffer to fill when two pointers are pointing at same location.The code works at start. The problem is when some time passes like approximately 2 minutes we see the head and tail pointers are pointing at the same location which creates discontinuity in our samples. Which means the one pointer is slow or fast than expected. I am sure of SAI protocol outputting 40kHz constantly (I checked it with scope). However, I am not so sure about accuracy of USARTs timing. I cannot modify the external USART device's code and I cannot change the output rate 40kHz it must be this value.Is there a another way (maybe other than ping pong buffer method) to handle asynchronous input and synchronous outputs?

author: magic
author_rank: Super Contributor
timestamp: April 21, 2021, 07:38:30 pm
content: That's simply not going to work unless both 40kHz clocks are perfectly synchronized with each other. Buffering can only help against short term jitter, but it won't help against average speeds being different over the long term.If the signal is digital audio, you could in theory measure the exact difference and apply sample rate interpolation in software, but

author: David Hess
author_rank: Super Contributor
timestamp: April 22, 2021, 12:27:09 am
content: If you have access to one of the clocks, then phase lock it to the clock that you do not have access to. Some USB audio equipment does this.

author: thermistor-guy
author_rank: Frequent Contributor
timestamp: April 22, 2021, 01:34:47 am
content: Quote from: magic on April 21, 2021, 07:38:30 pmIn telecoms, PCM networks used to be plesiochronous: equipment would run at the same nominal clock rate, but there would be a differences in their exact rates. That would produce "sync slips". Send/receive circuitry would either skip data (incoming too fast) or repeat data (incoming too slow) to match the local clock rate.In a synchronous network, a mismatch in clock rates can still come about if a timing fault occurs in the network. So it is still good to have a mechanism to cope with timing errors. The OP's code should have the ability to handle underruns and overruns.

author: SiliconWizard
author_rank: Super Contributor
timestamp: April 22, 2021, 01:42:57 am
content: Quote from: magic on April 21, 2021, 07:38:30 pmYes. This is just not how you do it in this case. It calls for an asynchronous scheme, which here means that the data sent through the UART should definitely be sent with a higher rate than the rate at which it is consumed by the audio interface, with some margin. No problem then. But it will need some handshaking. A "free to send new buffer" signal from the MCU to the device that is sending data through UART would do the job.(Since the OP is using an UART to transmit data, I suppose synchronizing clocks would be unpractical anyway.)Now if you actually don't have means of modifying the sending side - you're screwed.

author: ajb
author_rank: Super Contributor
timestamp: April 22, 2021, 03:06:45 am
content: Locking the clocks is the best way to avoid the problem. If you have the timing resolution on the SAI module you could, with some care, trim the clock rate to match the as-received uart data rate (you'd need to filter out as much jitter as possible, since there will likely be a fair bit of uncertainty introduced by the software on both sides of the uart link). If you can't hit an exact phase match then you may have to dither the clock rate, as long as that won't screw up the output too much. If you don't have enough clock resolution on the output, or can't tolerate changes in the output clock rate, the easiest solution would be to skip or duplicate a sample whenever the pointers move out of sync. You could also fully resample the buffer, interpolating samples at the new clock rate from the samples at the old clock rate, but that's probably not worth the trouble for most applications.

author: srb1954
author_rank: Super Contributor
timestamp: April 22, 2021, 04:18:13 am
content: Quote from: thermistor-guy on April 22, 2021, 01:34:47 amThe plesiochronous networks (PDH) were designed so that they didn't lose data or produce "sync slips" in most circumstances.They allowed for slight variations in the data rate by "stuffing" a variable number filler bits in each frame transmitted. The next device up the chain could ignore some of these filler bits if the oncoming data rate was too fast or add extra filler bits if the incoming data rate was too slow.As a consequence of these filler bits the higher levels of the PDH had to run slightly faster with each level of multiplexing to accommodate the variable number of these extra bits. e.g. four 2.048Mb/s channels multiplexed onto a 8.448Mb/s channel rather than the expected 8.192Mb/s data rate, four 8.448MB/s channels multiplexed onto a 34.368Mb/s channel and so on.