
########################
lib_adat: ADAT lightpipe
########################

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

The ADAT Lightpipe, officially the ADAT Optical Interface, is a standard for the transfer of digital
audio between equipment via optical cable.
The data transmission rate is determined by the transmitter, and the receiver has to recover the
sample rate. ADAT can carry eight channels of uncompressed digital audio at sample-rates of 44.1 or
48 kHz.

Important characteristics of ``lib_adat`` are the following:

* The sample rate(s) supported. Typical values are 44.1 or 48. Higher rates are supported with a
  reduced number of samples via S/MUX ('sample multiplexing')

* Transmit and Receive support. Some systems require only ADAT output, or
  only ADAT input. Others require both.

Note that ADAT of eight channels at 48 Khz is identical to four channels at
96 KHz - a single bit in the data stream differentiates it (but the bit
rates, transmit, and receive code are identical).

Transmit
========

This module can transmit ADAT signals at the following rates
(assuming eight threads on a 500 MHz part)

+---------------------------+-------------------------------+
| Functionality provided    | Resources required            |
+----------+----------------+------------+---------+--------+
| Channels | Sample Rate    | 1-bit port | Threads | Memory |
+----------+----------------+------------+---------+--------+
| 8        | up to 48 KHz   | 1-2        | 1+      | 3.6K   |
+----------+----------------+------------+---------+--------+
| 8        | up to 48 KHz   | 1-2        | 1       | 3.5K   |
+----------+----------------+------------+---------+--------+

It requires a single thread to run the transmit code. The number of 1-bit
ports depends on whether the master clock is already available on a one-bit
port. If available, then only a single 1-bit port is required to output
ADAT. If not, then two ports are required, one for the signal output, and
one for the master-clock input.

The precise transmission frequencies supported depend on the availability
of an external clock (eg, a PLL or a crystal oscillator) that runs at a
frequency of::

    512 * sampleRate

or a power-of-2 multiple. For example, for 48 Khz the
external clock has to run at a frequency of 24.576 MHz.
If both 44,1 and 48 Khz frequencies are to be supported, both a
24.587 MHz and a 22.579 MHz master clock are required. This is normally not
an issue since the same clocks can be used to drive the audio codecs.

When using an `xcore.ai` based device these frequencies can be generated by the on-chip
application/secondary PLL.

Receive
=======

This module can receive ADAT signals at the following rates (assuming 8 threads on a 500 MHz part)

+---------------------------+-------------------------+
| Functionality provided    | Resources required      |
+----------+----------------+------------+------------+
| Channels | Sample Rate    | 1-bit port | Memory     |
+----------+----------------+------------+------------+
| 8        | up to 48 KHz   | 1          | 3.5 KB     |
+----------+----------------+------------+------------+

A single 62.5-MIPS core is required. The receiver does not require any
external clock, but can only recover 44.1 and 48 KHz sample rates.

************
ADAT receive
************

The ADAT receiver comprises a single thread that parses data as it
arrives on a one-bit port and that outputs words of data onto a
streaming channel end. Each word of data carries 24 bits of sample data and 4 bits of
channel information.

The receiver requires the `xcore` reference clock being exactly 100 Mhz (default value).

The receiver API comprises two functions, one that receives adat at 48 KHz, and one
that receives ADAT at 44.1 KHz. If the frequency of the input signal is
known a priori, the call that function in a non terminating ``while(1)``
loop. If the frequency could be either, then call the two functions in
succession from a ``while(1)`` loop (recommended).

Receive API
===========

Compile time defines
--------------------

*ADAT_REF*
  Define this to 100 to state that the reference clock is exactly
  100 MHz (for example when using a 20 or 25 MHz crystal), or 999375
  to state that the reference clock is 99.9375 MHz (the
  result of using a 13 MHz crystal on an XS1-L series devices). Other values are at
  present not supported.

Functions
---------

.. doxygengroup:: lib_adat_rx
   :content-only:

Receive example
===============

A simple receive program is provided in ``examples/app_adat_rx_example``. This application simply
receives samples and periodically emits the number of frames received to the terminal. This section
examines this simple example.

The input port needs to be declared as a buffered port:

.. literalinclude:: ../../examples/app_adat_rx_example/src/main.xc
  :start-after: /* Port declarations
  :end-before: out port

The receive functions should be called from a ``while(1)`` loop.

.. literalinclude:: ../../examples/app_adat_rx_example/src/main.xc
  :start-after: /* Receive loop
  :end-before: //::

A data handler task inspects the received data samples and synchronises with
the beginning of each frame. In this case, we expect every 9th value to be
marked with a '1' nibble to indicate end-of-frame.

.. literalinclude:: ../../examples/app_adat_rx_example/src/main.xc
  :start-after: /* Data handler
  :end-before: //::

``main()`` simply forks the data handling task and the receiver in
parallel in two threads:

.. literalinclude:: ../../examples/app_adat_rx_example/src/main.xc
  :start-after: /* Top-level main
  :end-before: //::

*************
ADAT transmit
*************

There are two functions in the API that can produce an ADAT signal. The simplest
is a single thread that inputs samples over a channel and that outputs data on a 1-bit port.

A more complex version has a thread that inputs samples over a channel and that produces an ADAT
signal onto a second channel. Another thread is required to copy this data from the channel onto a
port. This second version is useful if the ADAT output port resides on a different
tile.

This document provides example usage for both variants.

An identical protocol is used by both variants for inputting sample values
to be transmitted over ADAT. The first word transmitted over the
chanend should be the multiplier of the master clock (either 1024 or 512),
the second word should be the S/MUX setting (either 0 or 2), then there should be N
x 8 words of sample values, terminated by an ``XS1_CT_END`` control token. If no
control token is sent, the transmission process will not terminate, and an
infinite stream of ADAT data can be sent.

The multiplier is the ratio between the master clock and the bit-rate; 1024
refers to a 49.152 MHz master-clock, 512 assumes a 24.576 MHz master clock.

The output of the ADAT transmit thread has to be synchronised with an
external flip-flop. In order to make sure that the flip-flop captures the
signal on the right edge, the output port should be set up as follows::

  set_clock_src(mck_blk, mck);        // Connect Master Clock Block to mclk pin
  set_port_clock(adat_port, mck_blk); // Set ADAT_tx to be clocked from mck_blk
  set_clock_fall_delay(mck_blk, 7);   // Delay falling edge of mck_blk
  start_clock(mck_blk);               // Start mck_blk

Transmit API
============

Functions
---------

.. doxygengroup:: lib_adat_tx
   :content-only:

Transmit example
================

Example applications are provided for both the 'direct port' and 'remote port' API variants. These
are ``app_adat_tx_direct_example`` and ``app_adat_tx_example`` respectively.

Both examples transmit sine waves on all channels and are described in this section.

Direct port example
-------------------

The output port is declared as a 32-bit buffered port, and the master clock input must be
declared as an unbuffered input port. A clock block is also required:

.. literalinclude:: ../../examples/app_adat_tx_direct_example/src/main.xc
  :start-after: /* Port declarations
  :end-before: //:

The ports are setup such that the output port is clocked from the master clock with a suitable delay
(to enable the external flop to latch the signal). Starting the clock block is a critical step,
otherwise outputs to the transmit port will pause:

.. literalinclude:: ../../examples/app_adat_tx_direct_example/src/main.xc
  :start-after: /* Setup ports and clocks
  :end-before: adat_tx_port

The data generator task initially communicates the clock multiplier and the S/MUX flags, prior to
transmitting data.

The task uses a table to generate sine-waves of various frequencies and phase-shifts (allowing for
channel identification):

.. literalinclude:: ../../examples/app_adat_tx_direct_example/src/main.xc
  :start-after: /* Data generation task
  :end-before: //:

The main program simply forks the data generating and the transmitter tasks in parallel in two
threads. A channel is declared and passed to both tasks to allow communication.
A ``board_setup`` tasks is also spawned that configures the external hardware and configures
the `xcore.ai` application PLL to generate a suitable master-clock.

.. literalinclude:: ../../examples/app_adat_tx_direct_example/src/main.xc
  :start-after: /* Top-level main
  :end-before: //:

Remote port example
-------------------

Much of the remote port example matches the direct port example.
The output port is declared as a buffered port, and the master clock input must be declared as an
unbuffered input port. A clock block is also required:

.. literalinclude:: ../../examples/app_adat_tx_example/src/main.xc
  :start-after: /* Port declarations
  :end-before: //:

Again, the ports are setup so that the output port is clocked from the master clock with a suitable
delay (to enable the external flop to latch the signal). Starting the clock block is a critical step,
otherwise outputs to the transmit port will pause:

.. literalinclude:: ../../examples/app_adat_tx_example/src/main.xc
  :start-after: /* Port and clock setup
  :end-before: //:

The thread that drives the port should input words from the channel, and
output them with *reversed byte order*. Note that this activity of input,
byte-reverse and output takes only three instructions and can often be merged
with other task; for example if there is an I²S thread that delivers
data synchronised to the same master clock, then that thread can
simultaneously drive the ADAT and I²S ports:

.. literalinclude:: ../../examples/app_adat_tx_example/src/main.xc
  :start-after: /* Port driver
  :end-before: //:

For simplicity, this example spawns the ``adat_tx`` and port-driving tasks on the same tile:

.. literalinclude:: ../../examples/app_adat_tx_example/src/main.xc
  :start-after: /* Par port-driver
  :end-before: //:

The data generation task closely matches the previous example, first communicating the clock
multiplier and the S/MUX flags, prior to transmitting data:

.. literalinclude:: ../../examples/app_adat_tx_example/src/main.xc
  :start-after: /* Data generation
  :end-before: //:

The main program simply forks the data generating thread and the transmitter in
parallel in two threads. Prior to starting the transmitter, the clocks
should be set up:

.. literalinclude:: ../../examples/app_adat_tx_example/src/main.xc
  :start-after: /* Top-level main
  :end-before: //:

*******************
Additional examples
*******************

An additional example, ``app_adat_loopback``, is also provided. This expects a cable to be connected
between transmit and receive. The application transmits counters on all channels and checks for the
correct reception of these counters. This application can be useful for initial debugging and
validation of external transmit/receive circuitry.

