Audio Sync bewteen 2 tiles

Technical questions regarding the XTC tools and programming with XMOS.
Post Reply
nico
Active Member
Posts: 33
Joined: Tue Feb 16, 2016 12:51 pm

Audio Sync bewteen 2 tiles

Post by nico »

Hi all,

I am experiencing a strange problem.
I have a custom board based on xCORE-200 Multichannel Audio Platform design but I added 4 I2S DAC outputs on tile 1 (audio is on tile 0 and USB on tile 1).

I took the code of sw_usb_audio_6.15.2_rc1.

I have a task on tile 1 that receives samples through a channel from the main audio I2S task : "deliver" in audio.xc and on tile 0.
In the function "deliver", I added a simple line like this :
c_send <: samplesOut[0];
to send the left sample to my custom thread located on tile 1.

My task on tile 1 looks like this for testing purpose :

while (1) {
c_receive :> sample;
p_lrclk <: 1;
p_ch1 <: 1;
p_ch2 <: 1;
p_ch3 <: 1;
p_ch4 <: 1;
}

Then I monitor my 5 signals to check the synchronicity. The signals p_lrclk show a perfect 96kHz (my sample rate) but the edges of the other signals are not in sync.
p_lrclk and p_ch1 are aligned, p_ch2 and p_ch3 are shift by 1 bit and p_ch4 by 2 bits.
If I comment the first line (c_receive :> sample;), then all the signals are in sync (at at rate > 700kHz).

To be honest, I do not understand this behaviour and I can't find any solution to that problem.

The ports are clocked like on the main audio clock on tile 1 :

set_clock_src(clk_audio_mclk2, p_mclk_in2);
set_port_clock(p_for_mclk_count, clk_audio_mclk2);
configure_out_port_no_ready(p_lrclk, clk_audio_mclk2, 0);
configure_out_port_no_ready(p_ch1, clk_audio_mclk2, 0);
configure_out_port_no_ready(p_ch2, clk_audio_mclk2, 0);
configure_out_port_no_ready(p_ch3, clk_audio_mclk2, 0);
configure_out_port_no_ready(p_ch4, clk_audio_mclk2, 0);
start_clock(clk_audio_mclk2);

They are initialized like this :
on tile[1] : buffered out port:32 p_lrclk = PORT_LRCLK2;
on tile[1] : buffered out port:32 p_ch1 = PORT_CH1;
on tile[1] : buffered out port:32 p_ch2 = PORT_CH2;
on tile[1] : buffered out port:32 p_ch3 = PORT_CH3;
on tile[1] : buffered out port:32 p_ch4 = PORT_CH4;

I tried with both a standard channel and a streaming channel to send the samples but the behaviour is the same ...

Any ideas ? Is this possible to sync several I2S outputs on two tiles using the same main audio clock ?

I would appreciate any help on this ...

Thanks
Best regards,
Nicolas


User avatar
mon2
XCore Legend
Posts: 1913
Joined: Thu Jun 10, 2010 11:43 am
Contact:

Post by mon2 »

Hi Nicolas.

Code: Select all

while (1) {
 c_receive :> sample;
 p_lrclk <: 1;
 p_ch1 <: 1;
 p_ch2 <: 1;
 p_ch3 <: 1;
 p_ch4 <: 1;
 }
The above while(1) loop is running sequentially. Respectively, during each XMOS clock cycle, this thread can only perform so many tasks before moving to the next clock cycle and sequential task. So your observation sounds logical that 2 lines of your code are being executed before moving to the next clock cycle and so on.

Consider the following idea:

a) insert another clocked output port pin. It can be any free single bit port pin. So you will have to add to your initialization routine to map to the same clk_audio_mclk2 so for example:

Code: Select all

configure_out_port_no_ready(my_trigger, clk_audio_mclk2, 0);
where my_trigger is just a single bit port that will not actually be used by your project.

Then use the timed output feature of the XMOS CPU.

Reference:
https://www.xmos.com/published/how-perf ... utput-port

Code: Select all

while (1) {

 my_trigger <: 1 @ count; // will output a 1 to your single bit port and record a copy of the port counter value into count when the output on my_trigger is driven

 c_receive :> sample;

 count+=1; // apply the clock cycle when you wish to output your data (in this case it is the above recorded value+1 in the future
 
 // when the count period is +1, the following outputs should spit out your data at the same time
 p_lrclk  @ count <: 1;
 p_ch1   @ count <: 1;
 p_ch2   @ count <: 1;
 p_ch3   @ count <: 1;
 p_ch4   @ count <: 1;
 }
Give it a try and post your results. There are bound to be other ideas so the above is only one approach.
nico
Active Member
Posts: 33
Joined: Tue Feb 16, 2016 12:51 pm

Post by nico »

Thanks a lot for your answer, I will give a try (probably at the end of the week since I switched on another project).
What I do not understand is why if I comment the line with the sample reception, then all the signals are aligned ...
User avatar
mon2
XCore Legend
Posts: 1913
Joined: Thu Jun 10, 2010 11:43 am
Contact:

Post by mon2 »

What I do not understand is why if I comment the line with the sample reception, then all the signals are aligned ...
It is possible that the compiler is optimizing the output port pin code so that in a single clock cycle, all of your required outputs are being processed at the same time.

You can also study and consider to use the sync feature of XMOS. This informs the CPU to wait till the falling clock and then perform some work. The idea again is to allow ample time for the processor to perform multiple tasks before the next clock cycle.

Again, these are a few ideas worth testing and there may be better solutions.

https://www.xmos.com/published/xc-port-buffering
nico
Active Member
Posts: 33
Joined: Tue Feb 16, 2016 12:51 pm

Post by nico »

Thanks again for your help. I will also try to tweak compiler optimization.
In fact I did simplify a little bit the problem so that someone can reproduce it.
In this project, I need to output 4 TDM signals ie 32 channels (coming from a single sample, don't ask me why ...). I have exactly 256 clock edges to do so (32*8 = 256). I tried some options (maybe not all) with sync but each time, I lost clock edges and the I2S main thread was delayed and I had noise on the main audio.
So I do not know what would give the timed output option ...
(I will not be able to try before next monday)
Post Reply