how to initialize array of 'pins' using multi pin ports

Technical questions regarding the XTC tools and programming with XMOS.
shaw
Active Member
Posts: 43
Joined: Fri Mar 25, 2011 12:36 am

how to initialize array of 'pins' using multi pin ports

Post by shaw »

Hi,

I show below,  one way to initialize the array p_i2s_dac[] using eight (1) pin ports.    How should the initialization change, when using two (4) pin ports;

Here is how it is handled when using eight (1) bit ports

/* from XN file */
Port Location="XS1_PORT_1P" Name="PORT_I2S_DAC0"/
port Location="XS1_PORT_1O" Name="PORT_I2S_DAC1"/
port Location="XS1_PORT_1N" Name="PORT_I2S_DAC2"/
port Location="XS1_PORT_1M" Name="PORT_I2S_DAC3"/
Port Location="XS1_PORT_1P" Name="PORT_I2S_DAC4"/
port Location="XS1_PORT_1O" Name="PORT_I2S_DAC5"/
port Location="XS1_PORT_1N" Name="PORT_I2S_DAC6"/
port Location="XS1_PORT_1M" Name="PORT_I2S_DAC7"/

/* from Main.xc */
#define I2S_WIRES_DAC (8)

/* Audio I/O - Port declarations */
on tile[AUDIO_IO_TILE] : buffered out port:32 p_i2s_dac[I2S_WIRES_DAC] =
{
PORT_I2S_DAC0, PORT_I2S_DAC1, PORT_I2S_DAC2, PORT_I2S_DAC3,
PORT_I2S_DAC4, PORT_I2S_DAC5, PORT_I2S_DAC6, PORT_I2S_DAC7
};

Here is how the XN file would be changed to use two (4) pin ports
/* from XN file */
Port Location="XS1_PORT_4B" Name="PORT_I2S_LOW"/
Port Location="XS1_PORT_4C" Name="PORT_I2S_HIGH"/

How should the Audio I/O port declaration be handled when using the two (4) pin ports?

on tile[AUDIO_IO_TILE] : buffered out port:32 p_i2s_dac[I2S_WIRES_DAC] =
{
  tbd
};


Thanks,


User avatar
fabriceo
XCore Addict
Posts: 186
Joined: Mon Jan 08, 2018 4:14 pm

Post by fabriceo »

Hi Shaw,
it seems that you would like to use 2 four bits ports for your 8 I2S channels, instead of 8 one bit ports.
the lib_i2s library is able to handle such situation I think.
but as far as I can see in the file xua_audiohub.xc, the sw usb audio application version 7.3.1 is not yet ready to accommodate this...

so it is not only a problem of pins declaration but also software to be adapted to lib_i2s behaviour.

Basically, to use a 4 bit port for I2S, you need to update the port 4 times per sample (so very fast...) with a 32 bits pattern which combines every bit of 4 audio samples by using the zip (assembly) instruction. if you want to use 2 four bits port then the zip sequence is to be done twice for the 8 samples before updating the 2 four bits ports. De facto this reduce the time you can spend in the audio hub loop and you must optimize the loop to keep enough time for the data transfer with the decouple task.

here you need feedbacks from Ross, or try it yourself (which is an interesting effort to share with everyone)
link on the zip topic for i2s : https://www.xmos.com/download/AN10129:- ... .1rc1).pdf

fabrice
shaw
Active Member
Posts: 43
Joined: Fri Mar 25, 2011 12:36 am

Post by shaw »

Thanks Fabrice. I see what you mean. I'll take a look at pdf and see if this can still work for us. I'll post any helpful findings here.
shaw
Active Member
Posts: 43
Joined: Fri Mar 25, 2011 12:36 am

Post by shaw »

I've looked further into at using a 4-bit port for Audio Out, which requires Using the required zip operation. For obvious reasons, The audio loop execution time has increased. As the loop time increases, I see a shift between the I2S Data being clocked out AND LRCLK edges. I’ve been able to adjust this relationship by changing the bit pattern output by LRCLK in HandleSampleClock(). This seems to work, but I'm not sure this is the best way to keep the I2S data aligned with LR clock. (ie. Left data aligned LR clock being low AND Right data aligned with LR clock being high)

How is the MSB of the Left/Right I2S data actually being aligned with the LRCLK rising and falling edges? I will have to keep the audio data MSB aligned with the LRCLK edges, as I add the additional processing time required for zipping 4-bit port data, etc. I can do this by making change sin LR clock bit pattern in HandleSampleClock(), But I thought there might be a better way, like double buffering data. But First I wanted to see if I could better understand how I2S data and LR clock edges are currently being aligned.

Thanks,
User avatar
fabriceo
XCore Addict
Posts: 186
Joined: Mon Jan 08, 2018 4:14 pm

Post by fabriceo »

Hi, there is a procedure called initport() which sync dac and lrclk and then start the clock. If you have an ADC then there is a special sync using port time stamp. Otherwise the dac and lrclk are just sync together and then the lrclk value as 1 bit shift to accommodate I2s format.(7fffffff or 80000000)

The i2s task just write the dac and then the lrclk. Due to internal register fifo, writing in first dac is blocked until the serdes register is empty, then the processor release the task and the other dac registers are set and then lrclk, they stay in sync. In your case you write 4 times in the 4bitport fifo and they are all blocking once the 3rd time is transferred to the serdes then the process is released and you have 1/4th of the time to write lrclk. This is ok for the left but the right takes more time due to data exchange with decouple. Please use timer trace to verify all timings, normally the lrclk should stay aligned without changing its value (if 1/4th time is enough to complete data exchange, otherwise youll have to optimise it…)
Joe
Member++
Posts: 24
Joined: Sun Dec 13, 2009 1:12 am

Post by Joe »

I'm not sure on your specific application but using a 4 bit port for i2s is supported in the lib_i2s library. See example below:

https://github.com/xmos/lib_i2s/tree/de ... _master_4b
shaw
Active Member
Posts: 43
Joined: Fri Mar 25, 2011 12:36 am

Post by shaw »

Fabriceo,

Thank-you for that explanation. that helps alot. I will look at this more closely and update on what I find.
User avatar
fabriceo
XCore Addict
Posts: 186
Joined: Mon Jan 08, 2018 4:14 pm

Post by fabriceo »

Hi Shaw,
I looked into this in sw usb 7.31. and inside xua_audiohub.xc.

there are couple of challenges to consider.

to pass the 4-bit port, you could just pass it as if it was a 1-bit port and then you modify some routines (initport) to check if this is a 1 bit or 4 bit port. this is easy to detect by just extracting the bits 16,17,18 of the port adress:
unsafe { port4bit = (((unsigned) myport >>16) == 4); }

then you keep I2S_WIRE_DACS to 2 if you only use one 4 bit port, and you force NUM_USB_CHAN_OUT to 8.

then you have to modify the dac output routines , in the "if(XUA_I2S_N_BITS == 32)" to write 4 times in your port instead of 1. The zip process is to be done before the 4 outputs, but later you can optimize and distributes the instruction in between.

to check all the timing, you can declare a table like timetrace[32] at the top of xua_audiohub.xc, and fill it a different place in the code with :
asm volatile ("gettime %0":"=r"(timetrace[x]); where x depends on the code area.

I recommend you put one trace before and after the ADC access, and before and after the LRCK access. to be considered twice for left and right.
then you can trace time also just before your first 4bitoutput and then one after each.
put one trace before and after DoSampleTransfer()

you can print all the timetrace with subtracting timetrace[0] to get a relative time. This can be done just before the "return command" after the call to DoSampleTransfer(). then when you switch sample freq (eg 44 to 48), this will print the timing in the console.

just some thoughts
shaw
Active Member
Posts: 43
Joined: Fri Mar 25, 2011 12:36 am

Post by shaw »

Fabriceo,

Thank-you for all of the feedback. To output on 4 pin port for DAC, I had essentially modified audio loop in audiohub, as you described. Just for the DAC first. I'm currently outputting a fixed pattern for DAC I2S data outputs. I'm still inputting from ADC, just ignoring data for now. I'm watching how the LRclk alignment with the I2S MSB, changes as I increase processing. Should be okay, As long as the data is aligned with LR clock and All 32 bits from the fixed pattern are output as expected. At all sample rates. I'm looking at the 4 I2S data lines out on logic analyzer. I'll take a look at doing traces for more detail, as I move forward.