################################################
AN00247: Using lib_xua with lib_spdif (transmit)
################################################

************
Introduction
************

The XMOS USB Audio (XUA) library provides an implementation of USB Audio Class versions 1.0 and 2.0.

This application note demonstrates the implementation of a basic USB Audio Device with
S/PDIF transmit functionality on the XCORE.AI Multichannel (MC) Audio board.

To reduce complexity this application note does not enable any other audio interfaces other than S/PDIF transmit
(i.e. no I2S).

*******************
Example application
*******************

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

To start using the XMOS XUA library, ``lib_xua`` needs to be added to the dependent module list
in the CMakeLists.txt file. ``lib_spdif`` is a dependency of ``lib_xua`` so does not need to be explicitly added.
The ``lib_board_support`` software repository is also used to provide common
code to configure the XCORE.AI Multichannel (MC) Audio board for use. This should also be added
to the list of dependent modules in the CMakeLists.txt file::

  set(APP_DEPENDENT_MODULES "lib_xua"
                            "lib_board_support")

The ``lib_board_support`` requires a compiler flag to select the hardware type::

  set(APP_COMPILER_FLAGS ... -DBOARD_SUPPORT_BOARD=XK_AUDIO_316_MC_AB ...)

Includes
========

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

.. literalinclude:: ../../app_an00247/src/app_xua_spdiftx.xc
   :start-at: include <xs1.h>
   :end-before: include "xua.h"

The XUA library functions are defined in ``xua.h``. This header must
be included in your code to use the library.  Headers are also required
for ``lib_xud``, ``lib_spdif`` and the board setup code for the
XCORE.AI Multichannel Audio board.

.. literalinclude:: ../../app_an00247/src/app_xua_spdiftx.xc
   :start-at: include "xua.h"
   :end-at: include "xk_audio_316_mc_ab/board.h"

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

Allocating hardware resources for lib_xua
-----------------------------------------

A minimal implementation of a USB Audio device, without I2S functionality,
using ``lib_xua`` requires the follow pins:

- Audio Master clock (from clock source to XCORE)

On an XCORE the pins are controlled by ``ports``. The application therefore declares a
port for the master clock input signal.

.. literalinclude:: ../../app_an00247/src/app_xua_spdiftx.xc
   :start-at: /* Lib_xua port declaration
   :end-at: in port p_mclk_in

``lib_xua`` also requires two ports for internally calculating USB feedback. Please refer to
the ``lib_xua`` library documentation for further details.  The additional input port for the master
clock is required since USB and S/PDIF do not reside of the same tiles on the example hardware.

These ports are declared as follows:

.. literalinclude:: ../../app_an00247/src/app_xua_spdiftx.xc
   :start-at: /* Resources for USB feedback
   :end-at: in port p_mclk_in_usb

In addition to ``port`` resources two clock-block resources are also required:

.. literalinclude:: ../../app_an00247/src/app_xua_spdiftx.xc
   :start-at: /* Clock-block
   :end-at: clock clk_audio_mclk_usb

Again, for the same reasoning as the master-clock ports, two master-clock clock-blocks are required
- one on each tile.

Allocating hardware resources for lib_spdif
-------------------------------------------

The S/PDIF transmitter requires a single (buffered) 1-bit port:

.. literalinclude:: ../../app_an00247/src/app_xua_spdiftx.xc
   :start-at: /* Lib_spdif port
   :end-at: buffered out port

This port must be clocked from the audio master clock. This application note chooses to declare
an extra clock-block as follows:

.. literalinclude:: ../../app_an00247/src/app_xua_spdiftx.xc
   :start-at: clock clk_spdif_tx
   :end-before: /* Lib_xua

Other declarations
------------------

``lib_xua`` requires the manual declaration of tables for the endpoint types for
``lib_xud`` and the calling the main XUD function in a par (``XUD_Main()``).

For a simple application the following endpoints are required:

- ``Control`` endpoint zero
- ``Isochonous`` endpoint for each direction for audio data to/from the USB host

These are declared as follows:

.. literalinclude:: ../../app_an00247/src/app_xua_spdiftx.xc
   :start-at: /* Endpoint type tables
   :end-at: XUD_EpType epTypeTableIn


Hardware specific setup
=======================

Some code is needed to perform the hardware-specific setup for the board being used
in this application note.

The ``xk_audio_316_mc_ab_config_t`` structure is used to specify hardware-specific
configuration options, such as clocking modes and frequencies.

The ``i_i2c_client`` unsafe client interface is required to have a globally-scoped variable
for gaining access to the ``i2c_master_if`` interface from the audio hardware functions.

.. literalinclude:: ../../app_an00247/src/app_xua_spdiftx.xc
   :start-at: /* Board configuration from lib_board_support */
   :end-at: unsafe client interface i2c_master_if i_i2c_client

The following functions are called by ``XUA_AudioHub`` to configure the hardware; they are
defined as wrapper functions around the board-specific code from ``lib_board_support``.

.. literalinclude:: ../../app_an00247/src/app_xua_spdiftx.xc
   :start-at: void AudioHwInit()
   :end-before: int main()

Configuring lib_xua
===================

``lib_xua`` must be configured to enable S/PDIF Tx functionality.

``lib_xua`` has many parameters than can be configured at build time, some examples include:

- Sample-rates
- Channel counts
- Audio Class version
- Product/Vendor IDs
- Various product strings
- Master clock frequency

To enable S/PDIF functionality ``XUA_SPDIF_TX_EN`` must be set to a non-zero value. Setting this will cause the ``XUA_AudioHub``
tasks to forward samples and sample rate information to the S/PDIF transmitter task.

These parameters are set via defines in an optional ``xua_conf.h`` header file. For this simple application the
complete contents of this file are as follows:

.. literalinclude:: ../../app_an00247/src/xua_conf.h
   :start-at: // Copyright
   :end-at: #endif

The application main() function
===============================

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

Various channels/interfaces are required in order to allow the required tasks to communicate.
These must first be declared:

.. literalinclude:: ../../app_an00247/src/app_xua_spdiftx.xc
   :start-at: /* Channels for lib_xud
   :end-at: interface i2c_master_if i2c[1]

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

.. literalinclude:: ../../app_an00247/src/app_xua_spdiftx.xc
   :start-at: par
   :end-before: return 0

This code starts the low-level USB task, an Endpoint 0 task, an Audio buffering task and a task to handle
the audio I/O. Note, since there is no I2S functionality in this example this task simply forwards samples to the
SPDIF transmitter task. In addition the ``spdif_tx()`` task is also run.

Note that the ``spdif_tx_port_config()`` function is called before a nested ``par`` of ``spdif_tx()`` and ``XUA_AudioHub()``.
This is because of the "shared" nature of ``p_mclk_in`` and avoids a parallel usage check failure by the XMOS tool-chain.

It also runs ``xk_audio_316_mc_ab_board_setup()`` and ``xk_audio_316_mc_ab_i2c_master()`` from ``lib_board_support``
that are used for setting up the hardware.


Building the example
====================

This section assumes that the `XMOS XTC Tools <https://www.xmos.com/software-tools/>`_ have been
downloaded and installed. The required version is specified in the accompanying ``README``.

Installation instructions can be found `here <https://xmos.com/xtc-install-guide>`_.

Special attention should be paid to the section on
`Installation of Required Third-Party Tools <https://www.xmos.com/documentation/XM-014363-PC/html/installation/install-configure/install-tools/install_prerequisites.html>`_.

The application is built using the `xcommon-cmake <https://www.xmos.com/file/xcommon-cmake-documentation/?version=latest>`_
build system, which is provided with the XTC tools and is based on `CMake <https://cmake.org/>`_.

The ``an00247`` software ZIP package should be downloaded and extracted to a chosen working
directory.

To configure the build, the following commands should be run from an XTC command prompt::

    cd an00247
    cd app_an00247
    cmake -G "Unix Makefiles" -B build

All required dependencies are included in the software package. If any dependencies are missing,
they will be retrieved automatically during this step.

The application binaries should then be built using ``xmake``::

    xmake -j -C build

Binary artifacts (.xe files) will be generated under the appropriate subdirectories of the
``app_an00247/bin`` directory — one for each supported build configuration.

For subsequent builds, the ``cmake`` step may be omitted.
If ``CMakeLists.txt`` or other build files are modified, ``cmake`` will be re-run automatically
by ``xmake`` as needed.


Hardware setup
==============

To run the application, use a USB cable to connect the on-board xTAG debug adapter (marked DEBUG) to your development computer.
Use another USB cable to connect the USB receptacle marked USB DEVICE to the device you wish to play audio from.

A device capable of receiving an S/PDIF signal (i.e. a speaker) should be connected to COAX TX.

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

   Hardware setup


Running the example
===================

From an XTC command prompt, the following command should be run from the ``an00247/app_an00247``
directory::

    xrun ./bin/app_an00247.xe

Alternatively, the application can be programmed into flash memory for standalone execution::

    xflash ./bin/app_an00247.xe

Once running, a USB audio device called ``XUA SPDIF Example`` should enumerate on the host machine - note, Windows operating
systems may require a third party driver for correct operation. The USB OUT stream from the host to device
is routed to SPDIF TX.
