.. include:: ../../README.rst

|newpage|

Overview
--------

Introduction
............

The XMOS |I2C| library provides software defined, industry-standard,
|I2C| components that allow you to create devices which can be either |I2C|
bus masters or slaves using xCORE GPIO ports.

|I2C| is a two-wire bus with defined protocols for connecting devices. There
is a clock and a data line, both of which are pulled high by external pull-up
resistors and driven low by the |I2C| devices.

The XMOS |I2C| library includes support for master and slave devices at speeds of
up to 400kb/s.

This application note demonstrates using the |I2C| master library to work with
the FXOS8700CQ accelerometer device on the xCORE-200 eXplorerKIT board.

Block diagram
.............

.. figure:: images/block_diagram.*
   :width: 80%

   Application block diagram

The application uses a single logical core which runs the application and makes
calls to the |I2C| master library functions as required.

How to use |I2C| master
-----------------------

The Makefile
............

To start using the |I2C|, you need to add ``lib_i2c`` to you Makefile::

  USED_MODULES = .. lib_i2c ...

This demo also uses the logging library (``lib_logging``) for the ``debug_printf``
function. This is a faster, but more limited version of the C-Standard Library
``printf`` function. So the Makefile also includes::

  USED_MODULES = .. lib_logging ..

The logging library is configurable at compile-time allowing calls to
``debug_printf()`` to be easily enabled or disabled. For the prints to
be enabled it is necessary to add the following to the compile flags::

  XCC_FLAGS = .. -DDEBUG_PRINT_ENABLE=1 ..

Includes
........

This application requires the system header that defines XMOS xCORE specific
defines for declaring and initialising hardware:

.. literalinclude:: main.xc
   :start-on: include <xs1.h>
   :end-before: include "i2c.h"

The |I2C| library functions are defined in ``i2c.h``. This header must
be included in your code to use the library. The logging functions are
provided by ``debug_print.h``.

.. literalinclude:: main.xc
   :start-on: include "i2c.h"
   :end-on: include "debug_print.h"

Allocating hardware resources
.............................

An |I2C| master requires a clock and a data pin. On an xCORE the pins are
controlled by ``ports``. The application therefore declares two 1-bit ports:

.. literalinclude:: main.xc
   :start-on: port p_scl
   :end-on: port p_sda

Accelerometer defines
.....................

A number of defines are used for the accelerometer device address and
register numbers:

.. literalinclude:: main.xc
   :start-on: define FXOS8700EQ_I2C_ADDR 0x1E
   :end-on: define FXOS8700EQ_OUT_Z_MSB 0x5

Reading over |I2C|
..................

The ``read_acceleration()`` function is used to get an accelerometer reading
for a given axis. It uses the |I2C| master to read the MSB and LSB registers
and then combines their results into the 10-bit value for the specified axis.
Each register read is checked to ensure that it has completed correctly.

.. literalinclude:: main.xc
   :start-on: int read_acceleration
   :end-before: void accelerometer

The |I2C| ``read_reg()`` function takes the device address, the register number
to read and a variable in which to return whether the read was successful.

By default it is assumed that the device address, register number and data are
all 8-bit. The |I2C| library provides other functions with different data-width
operands. Refer to the library documentation for details.

Writing over |I2C|
..................

The core of the application is the ``accelerometer()`` function which starts
by writing to the accelerometer device to configure and then enable it:

.. literalinclude:: main.xc
   :start-on: void accelerometer
   :end-before: while (1)

|newpage|

After that it continually loops polling the accelerometer until it is ready
and then reading the values from the three axes and displaying the current
status.

.. literalinclude:: main.xc
   :start-on: while (1)
   :end-before: // End accelerometer

The print uses a ``\r`` to ensure that only a single line of the screen is used.

The application main() function
...............................

The ``main()`` function sets up the tasks in the application.

Firstly, the ``interface`` is declared. In xC interfaces provide a
means of concurrent tasks communicating with each other. In this
application there is a single interface between the application and the |I2C|
master.

.. literalinclude:: main.xc
   :start-on: i2c_master_if i2c[1];
   :end-before: par

The rest of the ``main()`` function starts all the tasks in parallel
using the xC ``par`` construct:

.. literalinclude:: main.xc
   :start-on: par
   :end-before: return 0

This code starts the |I2C| master and the application. Because the |I2C| master
is marked as ``distributable`` it will not actually use a logical core but will
be run on the logical cores with the application. As a result, the entire system
only requires on logical core.

|appendix|
|newpage|

Demo Hardware Setup
-------------------

To run the demo, connect a USB cable to power the xCORE-200 eXplorerKIT
and plug the xTAG to the board and connect the xTAG USB cable to your
development machine.

.. figure:: images/hw_setup.*
   :width: 80%

   Hardware setup

|newpage|

Launching the demo application
------------------------------

Once the demo example has been built either from the command line using xmake or
via the build mechanism of xTIMEcomposer studio it can be executed on the xCORE-200
eXplorerKIT.

Once built there will be a ``bin/`` directory within the project which contains
the binary for the xCORE device. The xCORE binary has a XMOS standard .xe extension.

Launching from the command line
...............................

From the command line you use the ``xrun`` tool to download and run the code
on the xCORE device::

  xrun --xscope bin/xs2/AN00156_i2c_master_example.xe

Once this command has executed the application will be running on the
xCORE-200 eXplorerKIT.

Launching from xTIMEcomposer Studio
...................................

From xTIMEcomposer Studio use the run mechanism to download code to xCORE device.
Select the xCORE binary from the ``bin/`` directory, right click and go to Run
Configurations. Double click on xCORE application to create a new run configuration,
enable the xSCOPE I/O mode in the dialog box and then
select Run.

Once this command has executed the application will be running on the
xCORE-200 eXplorerKIT.

Running the application
.......................

Once the application is started using either of the above methods there should
be output printed to the console showing the x, y and z axis values and as you
move the development board these will change.

|newpage|

References
----------

.. nopoints::

  * XMOS Tools User Guide

    http://www.xmos.com/published/xtimecomposer-user-guide

  * XMOS xCORE Programming Guide

    http://www.xmos.com/published/xmos-programming-guide

  * XMOS |I2C| Library

    http://www.xmos.com/support/libraries/lib_i2c

|newpage|

Full source code listing
------------------------

Source code for main.xc
.......................

.. literalinclude:: main.xc
  :largelisting:

|newpage|
