forked from PAWPAW-Mirror/lib_xua
Further Audiohub tidyups. I2S ports params. Documentation updates inline.
This commit is contained in:
@@ -1,6 +1,13 @@
|
|||||||
lib_xua Change Log
|
lib_xua Change Log
|
||||||
==================
|
==================
|
||||||
|
|
||||||
|
0.2.0
|
||||||
|
-----
|
||||||
|
|
||||||
|
* ADDED: Documentation
|
||||||
|
* CHANGE: I2S hardware resources no longer used globally and must be passed to XUA_AudioHub()
|
||||||
|
* CHANGE: NO_USB define renamed to XUA_USB_EN
|
||||||
|
|
||||||
0.1.2
|
0.1.2
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
// Copyright (c) 2017-2018, XMOS Ltd, All rights reserved
|
// Copyright (c) 2017-2018, XMOS Ltd, All rights reserved
|
||||||
|
|
||||||
|
#ifndef _XUA_CONF_H_
|
||||||
|
#define _XUA_CONF_H_
|
||||||
|
|
||||||
#define NUM_USB_CHAN_OUT 2
|
#define NUM_USB_CHAN_OUT 2
|
||||||
#define NUM_USB_CHAN_IN 2
|
#define NUM_USB_CHAN_IN 2
|
||||||
#define I2S_CHANS_DAC 2
|
#define I2S_CHANS_DAC 2
|
||||||
@@ -22,3 +25,5 @@
|
|||||||
#define AUDIO_CLASS_FALLBACK 0
|
#define AUDIO_CLASS_FALLBACK 0
|
||||||
#define BCD_DEVICE 0x1234
|
#define BCD_DEVICE 0x1234
|
||||||
#define XUA_DFU_EN 0
|
#define XUA_DFU_EN 0
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -24,6 +24,14 @@
|
|||||||
*
|
*
|
||||||
* \param p_mclk_in Master clock inport port (must be 1-bit)
|
* \param p_mclk_in Master clock inport port (must be 1-bit)
|
||||||
*
|
*
|
||||||
|
* \param p_lrclk Nullable port for I2S sample clock
|
||||||
|
*
|
||||||
|
* \param p_bclk Nullable port for I2S bit
|
||||||
|
*
|
||||||
|
* \param p_i2s_dac Nullable array of ports for I2S data output lines
|
||||||
|
*
|
||||||
|
* \param p_i2s_adc Nullable array of ports for I2S data input lines
|
||||||
|
*
|
||||||
* \param c_dig channel connected to the clockGen() thread for
|
* \param c_dig channel connected to the clockGen() thread for
|
||||||
* receiving/transmitting samples
|
* receiving/transmitting samples
|
||||||
*/
|
*/
|
||||||
@@ -32,7 +40,9 @@ void XUA_AudioHub(chanend ?c_aud,
|
|||||||
clock ?clk_audio_bclk,
|
clock ?clk_audio_bclk,
|
||||||
in port p_mclk_in,
|
in port p_mclk_in,
|
||||||
buffered _XUA_CLK_DIR port:32 ?p_lrclk,
|
buffered _XUA_CLK_DIR port:32 ?p_lrclk,
|
||||||
buffered _XUA_CLK_DIR port:32 ?p_bclk
|
buffered _XUA_CLK_DIR port:32 ?p_bclk,
|
||||||
|
buffered out port:32 (&?p_i2s_dac)[I2S_WIRES_DAC],
|
||||||
|
buffered in port:32 (&?p_i2s_adc)[I2S_WIRES_ADC]
|
||||||
#if (XUA_SPDIF_TX_EN) && (SPDIF_TX_TILE != AUDIO_IO_TILE)
|
#if (XUA_SPDIF_TX_EN) && (SPDIF_TX_TILE != AUDIO_IO_TILE)
|
||||||
, chanend c_spdif_tx
|
, chanend c_spdif_tx
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
15
lib_xua/doc/rst/feat.rst
Normal file
15
lib_xua/doc/rst/feat.rst
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
Features & Options
|
||||||
|
------------------
|
||||||
|
|
||||||
|
|
||||||
|
The previous sections describes only the basic core set of ``lib_xua`` details on enabling additional features e.g. S/PDIF are discussed in this section.
|
||||||
|
|
||||||
|
If using the "codeless" programming model then the steps in this section are informational only.
|
||||||
|
|
||||||
|
I2S/TDM
|
||||||
|
~~~~~~~
|
||||||
|
|
||||||
|
S/PDIF Transmit
|
||||||
|
~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
@@ -28,7 +28,7 @@ Host System Requirements
|
|||||||
Hardware Platforms <hw>
|
Hardware Platforms <hw>
|
||||||
Software Overview <sw>
|
Software Overview <sw>
|
||||||
Using lib_xua <using>
|
Using lib_xua <using>
|
||||||
Implementation Detail <sw_arch>
|
Features <feat>
|
||||||
Known Issues <issues>
|
Known Issues <issues>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
Using lib_xud
|
Using lib_xud
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
This sections describes the basic usage of `lib_xud`. It provides a guide on how to program the USB Audio Devices using `lib_xud` including instructions for building and running
|
This sections describes the basic usage of `lib_xud`. It provides a guide on how to program the USB Audio Devices using `lib_xud`.
|
||||||
programs and creating your own custom USB audio applications.
|
|
||||||
|
|
||||||
Reviewing application note AN00246 is highly recommended.
|
Reviewing application note AN00246 is highly recommended at this point.
|
||||||
|
|
||||||
Library structure
|
Library structure
|
||||||
~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~
|
||||||
@@ -27,36 +26,41 @@ Note, the midi and dfu directories are potential candidates for separate libs in
|
|||||||
Including in a project
|
Including in a project
|
||||||
~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
All `lib_xua` functions can be accessed via the ``xud.h`` header filer::
|
All `lib_xua` functions can be accessed via the ``xua.h`` header filer::
|
||||||
|
|
||||||
#include <xua.h>
|
#include <xua.h>
|
||||||
|
|
||||||
It is also requited to to add ``lib_xua`` to the ``USED_MODULES`` field of your application Makefile.
|
It is also required to add ``lib_xua`` to the ``USED_MODULES`` field of your application Makefile::
|
||||||
|
|
||||||
|
USED_MODULES = .. lib_xua ...
|
||||||
|
|
||||||
|
|
||||||
Core hardware resources
|
Core hardware resources
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Currently all hardware resources used by `lib_xua` are simply declared globally.
|
The user must declare and initialise relevant hardware resources (globally) and pass them to the relevant function of `lib_xua`.
|
||||||
|
|
||||||
As an absolute minimum the following resources are required
|
As an absolute minimum the following resources are required:
|
||||||
|
|
||||||
- A 1-bit port for audio master clock input
|
- A 1-bit port for audio master clock input
|
||||||
- A n-bit port for internal feedback calculation (typically a free, unused port is used e.g. `16B`)
|
- A n-bit port for internal feedback calculation (typically a free, unused port is used e.g. `16B`)
|
||||||
- A clock-block, which will be clocked from the master clock input port
|
- A clock-block, which will be clocked from the master clock input port
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
Since these resources are accessed globally naming is of importance
|
|
||||||
|
|
||||||
Example declaration of these resources might look as follows::
|
Example declaration of these resources might look as follows::
|
||||||
|
|
||||||
in port p_mclk_in = PORT_MCLK_IN;
|
in port p_mclk_in = PORT_MCLK_IN;
|
||||||
in port p_for_mclk_count = PORT_MCLK_COUNT; /* Extra port for counting master clock ticks */
|
in port p_for_mclk_count = PORT_MCLK_COUNT; /* Extra port for counting master clock ticks */
|
||||||
clock clk_audio_mclk = on tile[0]: XS1_CLKBLK_5; /* Master clock */
|
clock clk_audio_mclk = on tile[0]: XS1_CLKBLK_5; /* Master clock */
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
If the ``XUD_AudioHub()`` and ``XUD_Buffer()`` cores reside on separate tiles a separate master clock input port must be provided to each, for example::
|
The `PORT_MCLK_IN` and `PORT_MCLK_COUNT` defintions are derived from the projects XN file
|
||||||
|
|
||||||
|
|
||||||
|
The ``XUA_AudioHub()`` function requires an audio master clock input to clock the physical audio I/O. Less obvious is the reasoning for the ``XUA_Buffer()``
|
||||||
|
task having the same requirement - it is used for the USB feedback system and packet sizing.
|
||||||
|
|
||||||
|
Due to the above, if the ``XUD_AudioHub()`` and ``XUA_Buffer()`` cores must reside on separate tiles a separate master clock input port must be provided to each, for example::
|
||||||
|
|
||||||
/* Master clock for the audio IO tile */
|
/* Master clock for the audio IO tile */
|
||||||
in port p_mclk_in = PORT_MCLK_IN;
|
in port p_mclk_in = PORT_MCLK_IN;
|
||||||
@@ -64,8 +68,10 @@ If the ``XUD_AudioHub()`` and ``XUD_Buffer()`` cores reside on separate tiles a
|
|||||||
/* Resources for USB feedback */
|
/* Resources for USB feedback */
|
||||||
in port p_mclk_in_usb = PORT_MCLK_IN_USB; /* Extra master clock input for the USB tile */
|
in port p_mclk_in_usb = PORT_MCLK_IN_USB; /* Extra master clock input for the USB tile */
|
||||||
|
|
||||||
Whilst this satisfies the basic requirements for the operation of `lib_xua` projects typically also needs some additional audio I/O, I2S or SPDIF for example.
|
Whilst the hardware resources described in this section satisfy the basic requirements for the operation (or build) of `lib_xua` projects typically also needs some additional audio I/O,
|
||||||
These should be passed into the various cores as required (see API section)
|
I2S or SPDIF for example.
|
||||||
|
|
||||||
|
These should be passed into the various cores as required - see API and Features sections.
|
||||||
|
|
||||||
Running the core components
|
Running the core components
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
@@ -82,10 +88,10 @@ In their most basic form the core components can be run as follows::
|
|||||||
XUA_Buffer(c_ep_out[1], c_ep_in[1], c_sof, c_aud_ctl, p_for_mclk_count, c_aud);
|
XUA_Buffer(c_ep_out[1], c_ep_in[1], c_sof, c_aud_ctl, p_for_mclk_count, c_aud);
|
||||||
|
|
||||||
/* AudioHub/IO core does most of the audio IO i.e. I2S (also serves as a hub for all audio) */
|
/* AudioHub/IO core does most of the audio IO i.e. I2S (also serves as a hub for all audio) */
|
||||||
XUA_AudioHub(c_aud);
|
XUA_AudioHub(c_aud, ...) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
``XUA_Buffer()`` expects its ``p_for_mclk_count`` argument to be clocked from the audio master clock
|
``XUA_Buffer()`` expects its ``p_for_mclk_count`` argument to be clocked from the audio master clock before being passed it.
|
||||||
The following code satisfies this requirement::
|
The following code satisfies this requirement::
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -98,7 +104,7 @@ The following code satisfies this requirement::
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.. note:: By keeping this configuraiton outside of the ``XUA_Buffer()`` function allow the possiblity to share the ``p_mclk_in_usb`` port with additional components
|
.. note:: Keeping this configuration outside of ``XUA_Buffer()`` does not preclude the possibllty of sharing ``p_mclk_in_usb`` port with additional components
|
||||||
|
|
||||||
To produce a fully operating device a call to ``XUD_Main()`` (from ``lib_xud``) must also be made for USB connectivity::
|
To produce a fully operating device a call to ``XUD_Main()`` (from ``lib_xud``) must also be made for USB connectivity::
|
||||||
|
|
||||||
@@ -121,14 +127,50 @@ Additionally the required communication channels must also be declared::
|
|||||||
chan c_aud_ctl;
|
chan c_aud_ctl;
|
||||||
|
|
||||||
|
|
||||||
|
This section provides enough information to implement a skeleton program for a USB Audio device. When running the xCORE device will present itself as a USB Audio Class device on the bus.
|
||||||
|
|
||||||
|
|
||||||
Configuring XUA
|
Configuring XUA
|
||||||
~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Built in main()
|
Configuration of the various build time options of ``lib_xua`` is done via the optional header `xua_conf.h`. Such build time options include audio class version, sample rates, channel counts etc.
|
||||||
~~~~~~~~~~~~~~~
|
Please see the API section for full listings.
|
||||||
|
|
||||||
|
The build system will automatically include the `xua_conf.h` header file as appropriate - the user should continue to include `xua.h` as previously directed. A simple example is shown below::
|
||||||
|
|
||||||
|
#ifndef _XUA_CONF_H_
|
||||||
|
#define _XUA_CONF_H_
|
||||||
|
|
||||||
|
/* Output channel count */
|
||||||
|
#define XUA_NUM_USB_CHAN_OUT (2)
|
||||||
|
|
||||||
|
/* Product string */
|
||||||
|
#define XUA_PRODUCT_STR_A2 "My Product"
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
User functions
|
||||||
|
~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
To enable custom functionality, such as configuring external audio hardware, custom functionality on stream start/stop etc various user overridable functions are provided (see API section for full listings). The default implementations are empty.
|
||||||
|
|
||||||
|
|
||||||
|
Codeless programming model
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Whilst it is possible to code a USB Audio device using the building blocks provided by `lib_xud` it is realised that this might not be desirable for some classes of customers or product.
|
||||||
|
|
||||||
|
For instance, some users may not have a large software development experience and simply want to customise some basic settings such as strings. Others may want to fully customise the implementation - adding additional functionality such as adding DSD or possibly only using a subset of the functions provided - just ``XUA_AudioHub``, for example.
|
||||||
|
|
||||||
|
In addition, the large number of supported features can lead a large number of tasks, hardware resources, communication channels etc, requiring quite a lot of code to be authored for each product.
|
||||||
|
|
||||||
|
In order to cater for the former class of users, a "codeless" option is provided. Put simply, a file ``main.xc`` is provided which includes a pre-authored ``main()`` function along with all of the required hardware resource declarations. Code is generated based on the options provided in ``xua_conf.h``
|
||||||
|
|
||||||
|
Using this development model the user simply must include a ``xua_conf.h`` with their settings and optionally implementations of any 'user functions' as desired. This, along with an XN file for their hardware platform, is all that is required to build a fully featured and functioning product.
|
||||||
|
|
||||||
|
This model also provides the benefit of a known-good, full codebase as a basis for a product.
|
||||||
|
|
||||||
|
This behaviour described in this section is the default behaviour of `lib_xud`, to disable this please set ``EXCLUDE_USB_AUDIO_MAIN`` to 1 in the application makefile or ``xua_conf.h``.
|
||||||
|
|
||||||
Enabling Additional Features
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
This sections describes only the basic feature set of ``lib_xua`` details on enabling additional features e.g. S/PDIF can be found later in this document.
|
|
||||||
|
|||||||
@@ -1,4 +1,18 @@
|
|||||||
#if (DSD_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT > 0)
|
|
||||||
|
#if (DSD_CHANS_DAC != 0)
|
||||||
|
extern buffered out port:32 p_dsd_dac[DSD_CHANS_DAC];
|
||||||
|
extern buffered out port:32 p_dsd_clk;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* I2S Data I/O*/
|
||||||
|
#if (I2S_CHANS_DAC != 0)
|
||||||
|
extern buffered out port:32 p_i2s_dac[I2S_WIRES_DAC];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (I2S_CHANS_ADC != 0)
|
||||||
|
extern buffered in port:32 p_i2s_adc[I2S_WIRES_ADC];
|
||||||
|
#endif
|
||||||
|
|
||||||
/* This function performs the DSD native loop and outputs a 32b DSD stream per loop */
|
/* This function performs the DSD native loop and outputs a 32b DSD stream per loop */
|
||||||
static inline void DoDsdNative(unsigned samplesOut[], unsigned &dsdSample_l, unsigned &dsdSample_r, unsigned divide)
|
static inline void DoDsdNative(unsigned samplesOut[], unsigned &dsdSample_l, unsigned &dsdSample_r, unsigned divide)
|
||||||
{
|
{
|
||||||
@@ -39,7 +53,6 @@ static inline void DoDsdDop(int &everyOther, unsigned samplesOut[], unsigned &ds
|
|||||||
to restart in I2S mode. */
|
to restart in I2S mode. */
|
||||||
static inline int DoDsdDopCheck(unsigned &dsdMode, int &dsdCount, unsigned curSamFreq, unsigned samplesOut[], unsigned &dsdMarker)
|
static inline int DoDsdDopCheck(unsigned &dsdMode, int &dsdCount, unsigned curSamFreq, unsigned samplesOut[], unsigned &dsdMarker)
|
||||||
{
|
{
|
||||||
#if (DSD_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT > 0)
|
|
||||||
/* Check for DSD - note we only move into DoP mode if valid DoP Freq */
|
/* Check for DSD - note we only move into DoP mode if valid DoP Freq */
|
||||||
/* Currently we only check on channel 0 - we get all 0's on channels without data */
|
/* Currently we only check on channel 0 - we get all 0's on channels without data */
|
||||||
if((dsdMode == DSD_MODE_OFF) && (curSamFreq > 96000))
|
if((dsdMode == DSD_MODE_OFF) && (curSamFreq > 96000))
|
||||||
@@ -53,13 +66,6 @@ static inline int DoDsdDopCheck(unsigned &dsdMode, int &dsdCount, unsigned curSa
|
|||||||
dsdMode = DSD_MODE_DOP;
|
dsdMode = DSD_MODE_DOP;
|
||||||
dsdCount = 0;
|
dsdCount = 0;
|
||||||
dsdMarker = DSD_MARKER_2;
|
dsdMarker = DSD_MARKER_2;
|
||||||
|
|
||||||
#if (I2S_CHANS_ADC != 0) || (I2S_CHANS_DAC != 0)
|
|
||||||
// Set clocks low
|
|
||||||
p_lrclk <: 0;
|
|
||||||
p_bclk <: 0;
|
|
||||||
#endif
|
|
||||||
p_dsd_clk <: 0;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -77,19 +83,11 @@ static inline int DoDsdDopCheck(unsigned &dsdMode, int &dsdCount, unsigned curSa
|
|||||||
if((DSD_MASK(samplesOut[0]) != DSD_MARKER_2) && (DSD_MASK(samplesOut[1]) != DSD_MARKER_2))
|
if((DSD_MASK(samplesOut[0]) != DSD_MARKER_2) && (DSD_MASK(samplesOut[1]) != DSD_MARKER_2))
|
||||||
{
|
{
|
||||||
dsdMode = DSD_MODE_OFF;
|
dsdMode = DSD_MODE_OFF;
|
||||||
// Set clocks low
|
|
||||||
#if (I2S_CHANS_ADC != 0 || I2S_CHANS_DAC != 0)
|
|
||||||
p_lrclk <: 0;
|
|
||||||
p_bclk <: 0;
|
|
||||||
#endif
|
|
||||||
p_dsd_clk <: 0;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,5 +1,16 @@
|
|||||||
|
#include "xua.h"
|
||||||
|
|
||||||
|
#include "dsd_support.h"
|
||||||
|
|
||||||
|
#if (DSD_CHANS_DAC != 0)
|
||||||
|
extern buffered out port:32 p_dsd_dac[DSD_CHANS_DAC];
|
||||||
|
extern buffered out port:32 p_dsd_clk;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern unsigned dsdMode;
|
||||||
|
|
||||||
#if !CODEC_MASTER
|
#if !CODEC_MASTER
|
||||||
static inline void InitPorts_master(unsigned divide, buffered out port:32 p_lrclk, buffered out port:32 p_bclk)
|
void InitPorts_master(unsigned divide, buffered _XUA_CLK_DIR port:32 p_lrclk, buffered _XUA_CLK_DIR port:32 p_bclk, buffered out port:32 (&?p_i2s_dac)[I2S_WIRES_DAC], buffered in port:32 (&?p_i2s_adc)[I2S_WIRES_ADC])
|
||||||
{
|
{
|
||||||
#if (DSD_CHANS_DAC > 0)
|
#if (DSD_CHANS_DAC > 0)
|
||||||
if(dsdMode == DSD_MODE_OFF)
|
if(dsdMode == DSD_MODE_OFF)
|
||||||
@@ -62,7 +73,7 @@ static inline void InitPorts_master(unsigned divide, buffered out port:32 p_lrcl
|
|||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
static inline void InitPorts_slave(unsigned divide, buffered in port:32 p_lrclk, buffered in port:32 p_bclk)
|
void InitPorts_slave(unsigned divide, buffered _XUA_CLK_DIR port:32 p_lrclk, buffered _XUA_CLK_DIR port:32 p_bclk, buffered out port:32 (&?p_i2s_dac)[I2S_WIRES_DAC], buffered in port:32 (&?p_i2s_adc)[I2S_WIRES_ADC])
|
||||||
{
|
{
|
||||||
#if (I2S_CHANS_ADC != 0 || I2S_CHANS_DAC != 0)
|
#if (I2S_CHANS_ADC != 0 || I2S_CHANS_DAC != 0)
|
||||||
unsigned tmp;
|
unsigned tmp;
|
||||||
@@ -49,11 +49,6 @@ static unsigned samplesOut[MAX(NUM_USB_CHAN_OUT, I2S_CHANS_DAC)];
|
|||||||
|
|
||||||
static unsigned samplesIn[2][MAX(NUM_USB_CHAN_IN, IN_CHAN_COUNT)];
|
static unsigned samplesIn[2][MAX(NUM_USB_CHAN_IN, IN_CHAN_COUNT)];
|
||||||
|
|
||||||
#if (DSD_CHANS_DAC != 0)
|
|
||||||
extern buffered out port:32 p_dsd_dac[DSD_CHANS_DAC];
|
|
||||||
extern buffered out port:32 p_dsd_clk;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef XTA_TIMING_AUDIO
|
#ifdef XTA_TIMING_AUDIO
|
||||||
#pragma xta command "add exclusion received_command"
|
#pragma xta command "add exclusion received_command"
|
||||||
#pragma xta command "analyse path i2s_output_l i2s_output_r"
|
#pragma xta command "analyse path i2s_output_l i2s_output_r"
|
||||||
@@ -67,18 +62,6 @@ extern buffered out port:32 p_dsd_clk;
|
|||||||
#pragma xta command "set required - 2000 ns"
|
#pragma xta command "set required - 2000 ns"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* I2S Data I/O*/
|
|
||||||
#if (I2S_CHANS_DAC != 0)
|
|
||||||
extern buffered out port:32 p_i2s_dac[I2S_WIRES_DAC];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (I2S_CHANS_ADC != 0)
|
|
||||||
extern buffered in port:32 p_i2s_adc[I2S_WIRES_ADC];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
unsigned dsdMode = DSD_MODE_OFF;
|
|
||||||
|
|
||||||
#if (XUA_SPDIF_TX_EN)
|
#if (XUA_SPDIF_TX_EN)
|
||||||
extern buffered out port:32 p_spdif_tx;
|
extern buffered out port:32 p_spdif_tx;
|
||||||
#endif
|
#endif
|
||||||
@@ -91,66 +74,28 @@ extern buffered out port:32 p_adat_tx;
|
|||||||
extern clock clk_mst_spd;
|
extern clock clk_mst_spd;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "init_ports.h"
|
#if CODEC_MASTER
|
||||||
|
void InitPorts_slave
|
||||||
|
#else
|
||||||
|
void InitPorts_master
|
||||||
|
#endif
|
||||||
|
(unsigned divide, buffered _XUA_CLK_DIR port:32 p_lrclk, buffered _XUA_CLK_DIR port:32 p_bclk, buffered out port:32 ?p_i2s_dac[I2S_WIRES_DAC],
|
||||||
|
buffered in port:32 ?p_i2s_adc[I2S_WIRES_ADC]);
|
||||||
|
|
||||||
|
|
||||||
|
unsigned dsdMode = DSD_MODE_OFF;
|
||||||
|
|
||||||
|
#if (DSD_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT > 0)
|
||||||
|
#include "audiohub_dsd.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef ADAT_TX
|
#ifdef ADAT_TX
|
||||||
unsigned adatCounter = 0;
|
#include "audiohub_adat.h"
|
||||||
unsigned adatSamples[8];
|
|
||||||
|
|
||||||
|
|
||||||
#pragma unsafe arrays
|
|
||||||
static inline void TransferAdatTxSamples(chanend c_adat_out, const unsigned samplesFromHost[], int smux, int handshake)
|
|
||||||
{
|
|
||||||
|
|
||||||
/* Do some re-arranging for SMUX.. */
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
unsigned * unsafe samplesFromHostAdat = &samplesFromHost[ADAT_TX_INDEX];
|
|
||||||
|
|
||||||
/* Note, when smux == 1 this loop just does a straight 1:1 copy */
|
|
||||||
//if(smux != 1)
|
|
||||||
{
|
|
||||||
int adatSampleIndex = adatCounter;
|
|
||||||
for(int i = 0; i < (8/smux); i++)
|
|
||||||
{
|
|
||||||
adatSamples[adatSampleIndex] = samplesFromHostAdat[i];
|
|
||||||
adatSampleIndex += smux;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
adatCounter++;
|
|
||||||
|
|
||||||
if(adatCounter == smux)
|
|
||||||
{
|
|
||||||
|
|
||||||
#ifdef ADAT_TX_USE_SHARED_BUFF
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
/* Wait for ADAT core to be done with buffer */
|
|
||||||
/* Note, we are "running ahead" of the ADAT core */
|
|
||||||
inuint(c_adat_out);
|
|
||||||
|
|
||||||
/* Send buffer pointer over to ADAT core */
|
|
||||||
volatile unsigned * unsafe samplePtr = &adatSamples;
|
|
||||||
outuint(c_adat_out, (unsigned) samplePtr);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#pragma loop unroll
|
|
||||||
for (int i = 0; i < 8; i++)
|
|
||||||
{
|
|
||||||
outuint(c_adat_out, samplesFromHost[ADAT_TX_INDEX + i]);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
adatCounter = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#pragma unsafe arrays
|
#pragma unsafe arrays
|
||||||
static inline unsigned DoSampleTransfer(chanend c_out, const int readBuffNo, const unsigned underflowWord)
|
static inline unsigned DoSampleTransfer(chanend c_out, const int readBuffNo, const unsigned underflowWord)
|
||||||
{
|
{
|
||||||
|
|
||||||
if(XUA_USB_EN)
|
if(XUA_USB_EN)
|
||||||
{
|
{
|
||||||
outuint(c_out, underflowWord);
|
outuint(c_out, underflowWord);
|
||||||
@@ -277,18 +222,16 @@ unsigned static AudioHub_MainLoop(chanend ?c_out, chanend ?c_spd_out
|
|||||||
#if (NUM_PDM_MICS > 0)
|
#if (NUM_PDM_MICS > 0)
|
||||||
, chanend c_pdm_pcm
|
, chanend c_pdm_pcm
|
||||||
#endif
|
#endif
|
||||||
, buffered _XUA_CLK_DIR port:32 p_lrclk, buffered _XUA_CLK_DIR port:32 p_bclk
|
, buffered _XUA_CLK_DIR port:32 p_lrclk,
|
||||||
|
buffered _XUA_CLK_DIR port:32 p_bclk,
|
||||||
|
buffered out port:32 (&?p_i2s_dac)[I2S_WIRES_DAC],
|
||||||
|
buffered in port:32 (&?p_i2s_adc)[I2S_WIRES_ADC]
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
/* Since DAC and ADC buffered ports off by one sample we buffer previous ADC frame */
|
/* Since DAC and ADC buffered ports off by one sample we buffer previous ADC frame */
|
||||||
unsigned readBuffNo = 0;
|
unsigned readBuffNo = 0;
|
||||||
unsigned index;
|
unsigned index;
|
||||||
|
|
||||||
#ifdef RAMP_CHECK
|
|
||||||
unsigned prev=0;
|
|
||||||
int started = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (DSD_CHANS_DAC != 0)
|
#if (DSD_CHANS_DAC != 0)
|
||||||
unsigned dsdMarker = DSD_MARKER_2; /* This alternates between DSD_MARKER_1 and DSD_MARKER_2 */
|
unsigned dsdMarker = DSD_MARKER_2; /* This alternates between DSD_MARKER_1 and DSD_MARKER_2 */
|
||||||
int dsdCount = 0;
|
int dsdCount = 0;
|
||||||
@@ -375,9 +318,9 @@ unsigned static AudioHub_MainLoop(chanend ?c_out, chanend ?c_spd_out
|
|||||||
unsigned syncError = 0;
|
unsigned syncError = 0;
|
||||||
|
|
||||||
#if CODEC_MASTER
|
#if CODEC_MASTER
|
||||||
InitPorts_slave(divide, p_lrclk, p_bclk);
|
InitPorts_slave(divide, p_lrclk, p_bclk, p_i2s_dac, p_i2s_adc);
|
||||||
#else
|
#else
|
||||||
InitPorts_master(divide, p_lrclk, p_bclk);
|
InitPorts_master(divide, p_lrclk, p_bclk, p_i2s_dac, p_i2s_adc);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Note we always expect syncError to be 0 when we are master */
|
/* Note we always expect syncError to be 0 when we are master */
|
||||||
@@ -599,7 +542,15 @@ unsigned static AudioHub_MainLoop(chanend ?c_out, chanend ?c_spd_out
|
|||||||
|
|
||||||
#if (DSD_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT > 0)
|
#if (DSD_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT > 0)
|
||||||
if(DoDsdDopCheck(dsdMode, dsdCount, curSamFreq, samplesOut, dsdMarker) == 0)
|
if(DoDsdDopCheck(dsdMode, dsdCount, curSamFreq, samplesOut, dsdMarker) == 0)
|
||||||
|
{
|
||||||
|
#if (I2S_CHANS_ADC != 0) || (I2S_CHANS_DAC != 0)
|
||||||
|
// Set clocks low
|
||||||
|
p_lrclk <: 0;
|
||||||
|
p_bclk <: 0;
|
||||||
|
#endif
|
||||||
|
p_dsd_clk <: 0;
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if I2S_MODE_TDM
|
#if I2S_MODE_TDM
|
||||||
@@ -683,7 +634,6 @@ static void dummy_deliver(chanend ?c_out, unsigned &command)
|
|||||||
{
|
{
|
||||||
int ct;
|
int ct;
|
||||||
|
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
select
|
select
|
||||||
@@ -733,7 +683,9 @@ static void dummy_deliver(chanend ?c_out, unsigned &command)
|
|||||||
void XUA_AudioHub(chanend ?c_aud, clock ?clk_audio_mclk, clock ?clk_audio_bclk,
|
void XUA_AudioHub(chanend ?c_aud, clock ?clk_audio_mclk, clock ?clk_audio_bclk,
|
||||||
in port p_mclk_in,
|
in port p_mclk_in,
|
||||||
buffered _XUA_CLK_DIR port:32 ?p_lrclk,
|
buffered _XUA_CLK_DIR port:32 ?p_lrclk,
|
||||||
buffered _XUA_CLK_DIR port:32 ?p_bclk
|
buffered _XUA_CLK_DIR port:32 ?p_bclk,
|
||||||
|
buffered out port:32 (&?p_i2s_dac)[I2S_WIRES_DAC],
|
||||||
|
buffered in port:32 (&?p_i2s_adc)[I2S_WIRES_ADC]
|
||||||
#if (XUA_SPDIF_TX_EN) && (SPDIF_TX_TILE != AUDIO_IO_TILE)
|
#if (XUA_SPDIF_TX_EN) && (SPDIF_TX_TILE != AUDIO_IO_TILE)
|
||||||
, chanend c_spdif_out
|
, chanend c_spdif_out
|
||||||
#endif
|
#endif
|
||||||
@@ -994,9 +946,7 @@ void XUA_AudioHub(chanend ?c_aud, clock ?clk_audio_mclk, clock ?clk_audio_bclk,
|
|||||||
#if (NUM_PDM_MICS > 0)
|
#if (NUM_PDM_MICS > 0)
|
||||||
, c_pdm_in
|
, c_pdm_in
|
||||||
#endif
|
#endif
|
||||||
, p_lrclk,
|
, p_lrclk, p_bclk, p_i2s_dac, p_i2s_adc);
|
||||||
p_bclk
|
|
||||||
);
|
|
||||||
|
|
||||||
#if (XUA_USB_EN)
|
#if (XUA_USB_EN)
|
||||||
if(command == SET_SAMPLE_FREQ)
|
if(command == SET_SAMPLE_FREQ)
|
||||||
@@ -1028,16 +978,16 @@ void XUA_AudioHub(chanend ?c_aud, clock ?clk_audio_mclk, clock ?clk_audio_bclk,
|
|||||||
par
|
par
|
||||||
{
|
{
|
||||||
DFUHandler(dfuInterface, null);
|
DFUHandler(dfuInterface, null);
|
||||||
dummy_deliver(c_mix_out, command);
|
dummy_deliver(c_aud, command);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
dummy_deliver(c_mix_out, command);
|
dummy_deliver(c_aud, command);
|
||||||
#endif
|
#endif
|
||||||
curSamFreq = inuint(c_mix_out);
|
curSamFreq = inuint(c_aud);
|
||||||
|
|
||||||
if (curSamFreq == AUDIO_START_FROM_DFU)
|
if (curSamFreq == AUDIO_START_FROM_DFU)
|
||||||
{
|
{
|
||||||
outct(c_mix_out, XS1_CT_END);
|
outct(c_aud, XS1_CT_END);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,6 +83,8 @@ on tile[AUDIO_IO_TILE] : buffered out port:32 p_i2s_dac[I2S_WIRES_DAC] =
|
|||||||
#endif
|
#endif
|
||||||
#if I2S_WIRES_DAC > 0
|
#if I2S_WIRES_DAC > 0
|
||||||
};
|
};
|
||||||
|
#else
|
||||||
|
#define p_i2s_dac null
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if I2S_WIRES_ADC > 0
|
#if I2S_WIRES_ADC > 0
|
||||||
@@ -112,6 +114,8 @@ on tile[AUDIO_IO_TILE] : buffered in port:32 p_i2s_adc[I2S_WIRES_ADC] =
|
|||||||
#endif
|
#endif
|
||||||
#if I2S_WIRES_ADC > 0
|
#if I2S_WIRES_ADC > 0
|
||||||
};
|
};
|
||||||
|
#else
|
||||||
|
#define p_i2s_adc null
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -468,7 +472,7 @@ void usb_audio_io(chanend ?c_aud_in, chanend ?c_adc,
|
|||||||
#else
|
#else
|
||||||
#define AUDIO_CHANNEL c_aud_in
|
#define AUDIO_CHANNEL c_aud_in
|
||||||
#endif
|
#endif
|
||||||
XUA_AudioHub(AUDIO_CHANNEL
|
XUA_AudioHub(AUDIO_CHANNEL, clk_audio_mclk, clk_audio_bclk, p_mclk_in, p_lrclk, p_bclk, p_i2s_dac, p_i2s_adc
|
||||||
#if (XUA_SPDIF_TX_EN) && (SPDIF_TX_TILE != AUDIO_IO_TILE)
|
#if (XUA_SPDIF_TX_EN) && (SPDIF_TX_TILE != AUDIO_IO_TILE)
|
||||||
, c_spdif_tx
|
, c_spdif_tx
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user