I2C for Multiple Clients Modification - XCORE 200 MC

Technical discussions related to any XMOS development kit or reference design. Eg XK-1A, sliceKIT, etc.
RitchRock
XCore Addict
Posts: 186
Joined: Tue Jan 17, 2017 9:25 pm

I2C for Multiple Clients Modification - XCORE 200 MC

Post by RitchRock »

I am modifying my xCORE 200 MC development board and using the app_usb_aud_xk_216_mc as my starting point. I realize I need to move from using module_i2C to the lib_I2C, so that multiple clients can use I2C and not just the functions in audiohw.xc which only runs one time. In my case, I also want to continuously update registers with my function PGA_GAIN_CNTRL().

I have read the programming guide section on parallel tasks and communication and am learning about how XMOS uses interfaces and clients, but am still a little hazy on exactly the implementation for my purposes. Since I2C is used across several functions in audiohw.xc, do each one of these functions now need to be a client, or can I just make the usb_audio_io() the client, since it calls audio(), which calls the functions in audiohw.xc?

Would the snippet from my main() i2C setup be something like this?

Code: Select all


    i2c_master_if i2c[2];
    
    par
    {
    
   /* ........setup XUD_Tile, etc..... */
    
       on tile[AUDIO_IO_TILE]: 
        par
        {
            
        i2c_master_single_port(i2c, 2, p_i2c, 100, 1, 2, 0xC);
        
        usb_audio_io(i2c[0], c_mix_out, c_adc
#if defined(SPDIF_TX) && (SPDIF_TX_TILE != AUDIO_IO_TILE)
            , c_spdif_tx
#endif
#ifdef MIXER
            , c_mix_ctl
#endif
            ,c_aud_cfg, c_spdif_rx, c_adat_rx, c_clk_ctl, c_clk_int
#if XUD_TILE != 0
            , dfuInterface
#endif
#if (NUM_PDM_MICS > 0)
            , c_pdm_pcm
#endif
        );
        
        PGA_GAIN_CNTRL(i2c[1], Gain_Value);
        }
        
        
        /* ........setup other Tiles, etc..... */
    }



henk
Respected Member
Posts: 347
Joined: Wed Jan 27, 2016 5:21 pm

Post by henk »

Hi,

I think the short answer is that you need as few clients as you have parallel tasks accessing the I2C server. So, if there is only one parallel task that talks to the I2C server, then you only need one client interface and you pass it in that task around to the right place where it is needed.

Cheers,
Henk
RitchRock
XCore Addict
Posts: 186
Joined: Tue Jan 17, 2017 9:25 pm

Post by RitchRock »

Thanks Henk. This leads me to believe I am on the right track with my above code. Cheers, Colin
RitchRock
XCore Addict
Posts: 186
Joined: Tue Jan 17, 2017 9:25 pm

Post by RitchRock »

I'm still working on this modification and having a little trouble getting the lib_i2c to compile without errors. Is there an example somewhere that uses i2c_master_single_port from i2c_lib?
henk
Respected Member
Posts: 347
Joined: Wed Jan 27, 2016 5:21 pm

Post by henk »

Hi,

What sort of errors do you get?
The following code should do the trick:

Code: Select all

...
#include "i2c.h"
...
port p_i2c                          = on tile[1]: XS1_PORT_4E; // Bit 0: SCLK, Bit 1: SDA
...
void your_function(client i2c_master_if i2c) {
    i2c.write_reg(0x4E, 0x02,  0x01);
    // pass i2c_master_if on to other functions if and when desired.
}
...
int main() {
    ...
    i2c_master_if i_i2c[1];
    ...
    par {
        on tile[1]: i2c_master_single_port(i_i2c, 1, p_i2c, 100, 0, 1, 0);
        on tile[whatever]: your_function(i_i2c);
    }
}
and in your makefile

Code: Select all

USED_MODULES = ... lib_i2c(>=4.0.0) ...
RitchRock
XCore Addict
Posts: 186
Joined: Tue Jan 17, 2017 9:25 pm

Post by RitchRock »

Mine looks very similar to the above, expect I had to put the port definition in i2c.h to get rid of a compile error:

Code: Select all

 port p_i2c = XS1_PORT_4A; 
I'm left with lots of other compile errors in lib_i2c.

Image
henk
Respected Member
Posts: 347
Joined: Wed Jan 27, 2016 5:21 pm

Post by henk »

Putting the port declaration in the include file doesn't sound like a good plan to me; it will cause it to be defined in multiple places.

It looks like SCL_HIGH is #defined somewhere.

At a guess, something (the IDE, maybe yourself), has upgraded I2C from an old to a new version. In an old version you used to #define SCL_HIGH in a file i2c_conf.h. In the modern version you call it using the right value.

Is there an i2c_conf.h in your project? If so, does that contain a #define SCL_HIGH? Or is there an old i2c.h hanging around?

You may want to make a fresh copy of your project before starting the upgrade process.
RitchRock
XCore Addict
Posts: 186
Joined: Tue Jan 17, 2017 9:25 pm

Post by RitchRock »

SCL_HIGH and SDA_HIGH are defined in the build flags, carried over from app_usb_aud_xk_216_mc, which I'm using as my starting point: -DSDA_HIGH=2 -DSCL_HIGH=1

There is an i2c_conf.h in the project, but I haven't made any changes - again it's carried over from the reference code app_usb_aud_xk_216_mc. I'm not sure it's ever referenced, though.

Code: Select all

#ifndef _I2C_CONF_H_
#define _I2C_CONF_H_

#define I2C_BIT_TIME 1000

#define I2C_REPEATED_START_ON_NACK 1
#define I2C_REPEATED_START_MAX_RETRIES 2000
#define I2C_REPEATED_START_DELAY 500

#endif
I'll make a fresh copy and see how it goes. Thanks for helping!
RitchRock
XCore Addict
Posts: 186
Joined: Tue Jan 17, 2017 9:25 pm

Post by RitchRock »

I was able to get it working. I deleted and then re-imported lib_i2c and removed all old module_i2c from directories. Thank you very much for your help.
wizard1238
New User
Posts: 3
Joined: Wed Feb 01, 2017 2:51 pm

Post by wizard1238 »

Does anybody know how many MIPS if it is changed to use lib_I2C run in main par, any MIPS different during i2c client active and idle? anyway to ensure it will not affect the other thread?
Post Reply