#######################################
AN00156: Using the |I2C| master library
#######################################

********
Overview
********

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 XK-EVK-XE216 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.

**********************************
|I2C| master library usage example
**********************************

The CMakeLists.txt file
=======================

To start using the |I2C|, you need to add ``lib_i2c`` to the dependent module list
in the CMakeLists.txt file. This application note also uses ``lib_logging``, so this must be
added to the list::

  set(APP_DEPENDENT_MODULES "lib_i2c"
                            "lib_logging")

The dependencies for this example are specified by ``deps.cmake`` in the ``examples`` directory
and are included in the application ``CMakeLists.txt`` file.

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::

  set(APP_COMPILER_FLAGS ... -DDEBUG_PRINT_ENABLE=1 ...)


Includes
========

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

.. literalinclude:: ../../src/main.xc
   :start-at: 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:: ../../src/main.xc
   :start-at: include "i2c.h"
   :end-at: 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:: ../../src/main.xc
   :start-at: port p_scl
   :end-at: port p_sda

Declarations
============

Accelerometer defines
---------------------

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

.. literalinclude:: ../../src/main.xc
   :start-at: define FXOS8700CQ_I2C_ADDR 0x1E
   :end-at: define FXOS8700CQ_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:: ../../src/main.xc
   :start-at: 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:: ../../src/main.xc
   :start-at: 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:: ../../src/main.xc
   :start-at: 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:: ../../src/main.xc
   :start-at: 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:: ../../src/main.xc
   :start-at: 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.

|newpage|

Building the Application
========================

The following section assumes you have downloaded and installed the `XMOS XTC tools <https://www.xmos.com/software-tools/>`_
(see `README` for required version). Installation instructions can be found `here <https://xmos.com/xtc-install-guide>`_.
Be sure to pay attention to the section `Installation of required third-party tools
<https://www.xmos.com/documentation/XM-014363-PC-10/html/installation/install-configure/install-tools/install_prerequisites.html>`_.

The application uses the `xcommon-cmake <https://www.xmos.com/file/xcommon-cmake-documentation/?version=latest>`_
build system as bundled with the XTC tools.

The ``AN00156_i2c_master_example`` software zip-file should be downloaded and unzipped to a chosen directory.

To configure the build run the following from an XTC command prompt::

    cd examples
    cd AN00156_i2c_master_example
    cmake -G "Unix Makefiles" -B build

Finally, the application binaries can be built using ``xmake``::

    xmake -C build


Demo Hardware Setup
===================

To run the demo, connect a USB cable to power the XK-EVK-XE216
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, 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.

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
XK-EVK-XE216.


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|

***************
Further Reading
***************

   * XMOS XTC Tools Installation Guide

     https://xmos.com/xtc-install-guide

      * XMOS XTC Tools User Guide

        https://www.xmos.com/view/Tools-15-Documentation

      * XMOS application build and dependency management system; xcommon-cmake

        https://www.xmos.com/file/xcommon-cmake-documentation/?version=latest

