Variable i2s bit width (#331)
- Add support for variable width I2S (via XUA_I2S_N_BITS) - Add support for variable width TDM (again via XUD_I2S_N_BITS when XUA_PCM_FORMAT=XUA_PCM_FORMAT_TDM) - Includes support for xcore as I2S/TDM master and slave - Add testing of the the above to test_i2s_loopback - Rationalised test config building in test_i2s_loopback - Documentation updated
This commit is contained in:
@@ -4,9 +4,10 @@ lib_xua Change Log
|
||||
UNRELEASED
|
||||
----------
|
||||
|
||||
* ADDED: Configurable word-length for I2S/TDM via XUA_I2S_N_BITS
|
||||
* FIXED: Memory corruption due to erroneous initialisation of mixer weights when not in use (#152)
|
||||
* FIXED: UserHostActive() not being called as expected (#326)
|
||||
* FIXED: Exception when entering DSD mode
|
||||
* FIXED: Exception when entering DSD mode (#327)
|
||||
|
||||
3.4.0
|
||||
-----
|
||||
|
||||
@@ -93,7 +93,11 @@
|
||||
|
||||
#define XUA_PCM_FORMAT_I2S (0)
|
||||
#define XUA_PCM_FORMAT_TDM (1)
|
||||
|
||||
/**
|
||||
* @brief Format of PCM audio interface. Should be set to XUA_PCM_FORMAT_I2S or XUA_PCM_FORMAT_TDM
|
||||
*
|
||||
* Default: XUA_PCM_FORMAT_I2S
|
||||
*/
|
||||
#ifdef XUA_PCM_FORMAT
|
||||
#if (XUA_PCM_FORMAT != XUA_PCM_FORMAT_I2S) && (XUA_PCM_FORMAT != XUA_PCM_FORMAT_TDM)
|
||||
#error Bad value for XUA_PCM_FORMAT
|
||||
@@ -193,6 +197,19 @@
|
||||
#define I2S_DOWNSAMPLE_CHANS_IN I2S_CHANS_ADC
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Number of bits per channel for I2S/TDM. Supported values: 16/32-bit.
|
||||
*
|
||||
* Default: 32 bits
|
||||
*/
|
||||
#ifndef XUA_I2S_N_BITS
|
||||
#define XUA_I2S_N_BITS (32)
|
||||
#endif
|
||||
|
||||
#if (XUA_I2S_N_BITS != 16) && (XUA_I2S_N_BITS != 32)
|
||||
#error Unsupported value for XUA_I2S_N_BITS (only values 16/32 supported)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Max supported sample frequency for device (Hz). Default: 192000
|
||||
*/
|
||||
|
||||
@@ -50,6 +50,15 @@ Audio Class
|
||||
Feature Configuration
|
||||
---------------------
|
||||
|
||||
I2S/TDM
|
||||
^^^^^^^
|
||||
|
||||
.. doxygendefine:: I2S_CHANS_DAC
|
||||
.. doxygendefine:: I2S_CHANS_ADC
|
||||
.. doxygendefine:: CODEC_MASTER
|
||||
.. doxygendefine:: XUA_I2S_N_BITS
|
||||
.. doxygendefine:: XUA_PCM_FORMAT
|
||||
|
||||
MIDI
|
||||
^^^^
|
||||
|
||||
|
||||
@@ -23,11 +23,14 @@ The defines in :ref:`opt_i2s_defines` effect the I2S implementation.
|
||||
- The desired number of input channels via I2S (0 for disabled)
|
||||
- N/A (Must be defined)
|
||||
* - ``XUA_PCM_FORMAT``
|
||||
- Enabled either TDM or I2S mode
|
||||
- Enables either TDM or I2S mode
|
||||
- ``XUA_PCM_FORMAT_I2S``
|
||||
* - ``CODEC_MASTER``
|
||||
- Sets is xCORE is I2S master or slave
|
||||
- Sets if xCORE is I2S master or slave
|
||||
- ``0`` (xCORE is master)
|
||||
* - ``XUA_I2S_N_BITS``
|
||||
- I2S/TDM word length (16, 32-bit supported)
|
||||
- ``32``
|
||||
|
||||
The I2S code expects that the ports required for I2S (master clock, LR-clock, bit-clock and data lines) are be defined in the application XN file in the relevant `Tile``.
|
||||
For example::
|
||||
@@ -42,8 +45,16 @@ For example::
|
||||
<Port Location="XS1_PORT_1G" Name="PORT_I2S_ADC1"/>
|
||||
</Tile>
|
||||
|
||||
All of the I2S related ports must be 1-bit ports.
|
||||
All of the I2S/TDM related ports must be 1-bit ports.
|
||||
|
||||
.. note::
|
||||
|
||||
TDM mode allows 8 channels (rather than 2) to be supplied on each dataline.
|
||||
TDM mode allows 8 channels (rather than 2) to be supplied on each data-line.
|
||||
|
||||
.. note::
|
||||
|
||||
Data output/input is in "I2S" format, rather than, say "left-justified" or "right-justified" formats.
|
||||
I2S format specifies a single bit-clock delay after the LR-clock transition before sample-data is driven/received.
|
||||
This also applies to TDM mode. TDM support in ADC/DAC hardware is quite varied, an "offset" value may need to be programmed into
|
||||
the external device for compatible operation.
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ full listing of these ``TILE`` defines.
|
||||
- Description
|
||||
- Default
|
||||
* - ``AUDIO_IO_TILE``
|
||||
- Tile on which I2S, ADAT Rx, S/PDIF Rx & mixer resides
|
||||
- Tile on which I2S/TDM, ADAT Rx, S/PDIF Rx & mixer resides
|
||||
- ``0``
|
||||
* - ``XUD_TILE``
|
||||
- Tile on which USB resides, including buffering for all USB interfaces/endppoints
|
||||
|
||||
@@ -25,7 +25,7 @@ Overview
|
||||
| +---------------------------------------------------------------------------------------------+
|
||||
| | `USB Midi Device Class 1.0 <http://www.usb.org/developers/devclass_docs/midi10.pdf>`_ |
|
||||
+---------------------------------+---------------------------------------------------------------------------------------------+
|
||||
| Audio | I2S/TDM |
|
||||
| Audio | I2S/TDM (16/32-bit) |
|
||||
| +---------------------------------------------------------------------------------------------+
|
||||
| | S/PDIF |
|
||||
| +---------------------------------------------------------------------------------------------+
|
||||
|
||||
@@ -5,7 +5,7 @@ I2S/TDM
|
||||
|
||||
I2S/TDM is typically fundamental to most products and is built into the ``XUA_AudioHub()`` core.
|
||||
|
||||
In order to enable I2S on must declare an array of ports for the data-lines (one for each direction)::
|
||||
In order to enable I2S/TDM on must declare an array of ports for the data-lines (one for each direction)::
|
||||
|
||||
/* Port declarations. Note, the defines come from the XN file */
|
||||
buffered out port:32 p_i2s_dac[] = {PORT_I2S_DAC0}; /* I2S Data-line(s) */
|
||||
@@ -22,7 +22,7 @@ Ports for the sample and bit clocks are also required::
|
||||
|
||||
These ports must then be passed to the ``XUA_AudioHub()`` task appropriately.
|
||||
|
||||
I2S functionality also requires two clock-blocks, one for bit and sample clock e.g.::
|
||||
I2S/TDM functionality also requires two clock-blocks, one for bit-clock and another for the master clock e.g.::
|
||||
|
||||
/* Clock-block declarations */
|
||||
clock clk_audio_bclk = on tile[0]: XS1_CLKBLK_4; /* Bit clock */
|
||||
|
||||
@@ -11,7 +11,7 @@ endif
|
||||
DEPENDENT_MODULES = lib_locks(>=2.1.0) \
|
||||
lib_logging(>=3.1.1) \
|
||||
lib_mic_array(>=4.5.0) \
|
||||
lib_spdif(>=4.2.1) \
|
||||
lib_spdif(>=5.0.0) \
|
||||
lib_xassert(>=4.1.0) \
|
||||
lib_xud(>=2.2.3) \
|
||||
lib_adat(>=1.0.0)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// Copyright 2018-2022 XMOS LIMITED.
|
||||
// Copyright 2018-2023 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
#include "xua.h"
|
||||
|
||||
#include "dsd_support.h"
|
||||
|
||||
#if (DSD_CHANS_DAC != 0)
|
||||
@@ -12,7 +11,7 @@ extern buffered out port:32 p_dsd_clk;
|
||||
extern unsigned dsdMode;
|
||||
|
||||
#if !CODEC_MASTER
|
||||
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])
|
||||
void InitPorts_master(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(dsdMode == DSD_MODE_OFF)
|
||||
@@ -39,7 +38,12 @@ void InitPorts_master(unsigned divide, buffered _XUA_CLK_DIR port:32 p_lrclk, bu
|
||||
#endif
|
||||
|
||||
unsigned tmp;
|
||||
p_lrclk <: 0 @ tmp;
|
||||
|
||||
if(XUA_I2S_N_BITS == 32)
|
||||
p_lrclk <: 0 @ tmp;
|
||||
else
|
||||
tmp = partout_timestamped(p_lrclk, XUA_I2S_N_BITS, 0);
|
||||
|
||||
tmp += 100;
|
||||
|
||||
/* Since BCLK is free-running, setup outputs/inputs at a known point in the future */
|
||||
@@ -47,19 +51,30 @@ void InitPorts_master(unsigned divide, buffered _XUA_CLK_DIR port:32 p_lrclk, bu
|
||||
#pragma loop unroll
|
||||
for(int i = 0; i < I2S_WIRES_DAC; i++)
|
||||
{
|
||||
p_i2s_dac[i] @ tmp <: 0;
|
||||
if(XUA_I2S_N_BITS == 32)
|
||||
p_i2s_dac[i] @ tmp <: 0;
|
||||
else
|
||||
partout_timed(p_i2s_dac[i], XUA_I2S_N_BITS, 0, tmp);
|
||||
}
|
||||
#endif
|
||||
|
||||
unsigned lrClkVal = 0x7FFFFFFF;
|
||||
if(XUA_PCM_FORMAT == XUA_PCM_FORMAT_TDM)
|
||||
p_lrclk @ tmp <: 0x80000000;
|
||||
{
|
||||
lrClkVal = 0x80000000;
|
||||
}
|
||||
|
||||
if(XUA_I2S_N_BITS == 32)
|
||||
p_lrclk @ tmp <: lrClkVal;
|
||||
else
|
||||
p_lrclk @ tmp <: 0x7FFFFFFF;
|
||||
partout_timed(p_lrclk, XUA_I2S_N_BITS, lrClkVal, tmp);
|
||||
|
||||
#if (I2S_CHANS_ADC != 0)
|
||||
for(int i = 0; i < I2S_WIRES_ADC; i++)
|
||||
{
|
||||
asm("setpt res[%0], %1"::"r"(p_i2s_adc[i]),"r"(tmp-1));
|
||||
|
||||
if(XUA_I2S_N_BITS != 32)
|
||||
set_port_shift_count(p_i2s_adc[i], XUA_I2S_N_BITS);
|
||||
}
|
||||
#endif
|
||||
#endif /* (I2S_CHANS_ADC != 0 || I2S_CHANS_DAC != 0) */
|
||||
@@ -75,7 +90,7 @@ void InitPorts_master(unsigned divide, buffered _XUA_CLK_DIR port:32 p_lrclk, bu
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
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])
|
||||
void InitPorts_slave(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)
|
||||
unsigned tmp;
|
||||
@@ -92,7 +107,7 @@ void InitPorts_slave(unsigned divide, buffered _XUA_CLK_DIR port:32 p_lrclk, buf
|
||||
p_lrclk when pinseq(0) :> void @ tmp;
|
||||
#endif
|
||||
|
||||
tmp += (I2S_CHANS_PER_FRAME * 32) - 32 + 1 ;
|
||||
tmp += ((I2S_CHANS_PER_FRAME * XUA_I2S_N_BITS) - XUA_I2S_N_BITS + 1) ;
|
||||
/* E.g. 2 * 32 - 32 + 1 = 33 for stereo */
|
||||
/* E.g. 8 * 32 - 32 + 1 = 225 for 8 chan TDM */
|
||||
|
||||
@@ -100,7 +115,10 @@ void InitPorts_slave(unsigned divide, buffered _XUA_CLK_DIR port:32 p_lrclk, buf
|
||||
#pragma loop unroll
|
||||
for(int i = 0; i < I2S_WIRES_DAC; i++)
|
||||
{
|
||||
p_i2s_dac[i] @ tmp <: 0;
|
||||
if(XUA_I2S_N_BITS == 32)
|
||||
p_i2s_dac[i] @ tmp <: 0;
|
||||
else
|
||||
partout_timed(p_i2s_dac[i], XUA_I2S_N_BITS, 0, tmp);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -108,11 +126,15 @@ void InitPorts_slave(unsigned divide, buffered _XUA_CLK_DIR port:32 p_lrclk, buf
|
||||
#pragma loop unroll
|
||||
for(int i = 0; i < I2S_WIRES_ADC; i++)
|
||||
{
|
||||
asm("setpt res[%0], %1"::"r"(p_i2s_adc[i]),"r"(tmp-1));
|
||||
asm("setpt res[%0], %1"::"r"(p_i2s_adc[i]),"r"(tmp-1));
|
||||
if(XUA_I2S_N_BITS != 32)
|
||||
set_port_shift_count(p_i2s_adc[i], XUA_I2S_N_BITS);
|
||||
}
|
||||
#endif
|
||||
|
||||
asm("setpt res[%0], %1"::"r"(p_lrclk),"r"(tmp-1));
|
||||
if(XUA_I2S_N_BITS != 32)
|
||||
set_port_shift_count(p_lrclk, XUA_I2S_N_BITS);
|
||||
#endif /* (I2S_CHANS_ADC != 0 || I2S_CHANS_DAC != 0) */
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
#include <xclib.h>
|
||||
#include <xs1_su.h>
|
||||
#include <string.h>
|
||||
#include <xassert.h>
|
||||
|
||||
|
||||
#include "xua.h"
|
||||
|
||||
@@ -50,19 +52,6 @@ unsigned samplesOut[MAX(NUM_USB_CHAN_OUT, I2S_CHANS_DAC)];
|
||||
|
||||
unsigned samplesIn[2][MAX(NUM_USB_CHAN_IN, IN_CHAN_COUNT)];
|
||||
|
||||
#ifdef XTA_TIMING_AUDIO
|
||||
#pragma xta command "add exclusion received_command"
|
||||
#pragma xta command "analyse path i2s_output_l i2s_output_r"
|
||||
#pragma xta command "set required - 2000 ns"
|
||||
|
||||
#pragma xta command "add exclusion received_command"
|
||||
#pragma xta command "add exclusion received_underflow"
|
||||
#pragma xta command "add exclusion divide_1"
|
||||
#pragma xta command "add exclusion deliver_return"
|
||||
#pragma xta command "analyse path i2s_output_r i2s_output_l"
|
||||
#pragma xta command "set required - 2000 ns"
|
||||
#endif
|
||||
|
||||
#if (XUA_ADAT_TX_EN)
|
||||
extern buffered out port:32 p_adat_tx;
|
||||
#endif
|
||||
@@ -76,7 +65,7 @@ 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 _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]);
|
||||
|
||||
|
||||
@@ -96,7 +85,17 @@ static inline int HandleSampleClock(int frameCount, buffered _XUA_CLK_DIR port:3
|
||||
#if CODEC_MASTER
|
||||
unsigned syncError = 0;
|
||||
unsigned lrval = 0;
|
||||
p_lrclk :> lrval;
|
||||
const unsigned lrval_mask = (0xffffffff << (32 - XUA_I2S_N_BITS));
|
||||
|
||||
if(XUA_I2S_N_BITS != 32)
|
||||
{
|
||||
asm volatile("in %0, res[%1]":"=r"(lrval):"r"(p_lrclk):"memory");
|
||||
set_port_shift_count(p_lrclk, XUA_I2S_N_BITS);
|
||||
}
|
||||
else
|
||||
{
|
||||
p_lrclk :> lrval;
|
||||
}
|
||||
|
||||
if(XUA_PCM_FORMAT == XUA_PCM_FORMAT_TDM)
|
||||
{
|
||||
@@ -114,30 +113,46 @@ static inline int HandleSampleClock(int frameCount, buffered _XUA_CLK_DIR port:3
|
||||
}
|
||||
else
|
||||
{
|
||||
if(frameCount == 0)
|
||||
syncError += (lrval != 0x80000000);
|
||||
if(XUA_I2S_N_BITS == 32)
|
||||
{
|
||||
if(frameCount == 0)
|
||||
syncError = (lrval != 0x80000000);
|
||||
else
|
||||
syncError = (lrval != 0x7FFFFFFF);
|
||||
}
|
||||
else
|
||||
syncError += (lrval != 0x7FFFFFFF);
|
||||
{
|
||||
if(frameCount == 0)
|
||||
syncError = ((lrval & lrval_mask) != 0x80000000);
|
||||
else
|
||||
syncError = ((lrval | (~lrval_mask)) != 0x7FFFFFFF);
|
||||
}
|
||||
}
|
||||
|
||||
return syncError;
|
||||
|
||||
#else
|
||||
unsigned clkVal;
|
||||
if(XUA_PCM_FORMAT == XUA_PCM_FORMAT_TDM)
|
||||
{
|
||||
if(frameCount == (I2S_CHANS_PER_FRAME-1))
|
||||
p_lrclk <: 0x80000000;
|
||||
clkVal = 0x80000000;
|
||||
else
|
||||
p_lrclk <: 0x00000000;
|
||||
clkVal = 0x00000000;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(frameCount == 0)
|
||||
p_lrclk <: 0x80000000;
|
||||
clkVal = 0x80000000;
|
||||
else
|
||||
p_lrclk <: 0x7fffffff;
|
||||
clkVal = 0x7fffffff;
|
||||
}
|
||||
|
||||
if(XUA_I2S_N_BITS == 32)
|
||||
p_lrclk <: clkVal;
|
||||
else
|
||||
partout(p_lrclk, XUA_I2S_N_BITS, clkVal >> (32 - XUA_I2S_N_BITS));
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
@@ -254,9 +269,9 @@ unsigned static AudioHub_MainLoop(chanend ?c_out, chanend ?c_spd_out
|
||||
if ((I2S_CHANS_DAC > 0 || I2S_CHANS_ADC > 0))
|
||||
{
|
||||
#if CODEC_MASTER
|
||||
InitPorts_slave(divide, p_lrclk, p_bclk, p_i2s_dac, p_i2s_adc);
|
||||
InitPorts_slave(p_lrclk, p_bclk, p_i2s_dac, p_i2s_adc);
|
||||
#else
|
||||
InitPorts_master(divide, p_lrclk, p_bclk, p_i2s_dac, p_i2s_adc);
|
||||
InitPorts_master(p_lrclk, p_bclk, p_i2s_dac, p_i2s_adc);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -290,9 +305,17 @@ unsigned static AudioHub_MainLoop(chanend ?c_out, chanend ?c_spd_out
|
||||
// p_i2s_adc[index++] :> sample;
|
||||
// Manual IN instruction since compiler generates an extra setc per IN (bug #15256)
|
||||
unsigned sample;
|
||||
asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++]));
|
||||
asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index]));
|
||||
|
||||
sample = bitrev(sample);
|
||||
int chanIndex = ((frameCount-2)&(I2S_CHANS_PER_FRAME-1))+i; // channels 0, 2, 4.. on each line.
|
||||
if(XUA_I2S_N_BITS != 32)
|
||||
{
|
||||
set_port_shift_count(p_i2s_adc[index], XUA_I2S_N_BITS);
|
||||
sample <<= (32 - XUA_I2S_N_BITS);
|
||||
}
|
||||
index++;
|
||||
|
||||
int chanIndex = ((frameCount-2) & (I2S_CHANS_PER_FRAME-1)) + i; // channels 0, 2, 4.. on each line.
|
||||
|
||||
#if (AUD_TO_USB_RATIO > 1)
|
||||
if ((AUD_TO_USB_RATIO - 1) == audioToUsbRatioCounter)
|
||||
@@ -344,7 +367,10 @@ unsigned static AudioHub_MainLoop(chanend ?c_out, chanend ?c_spd_out
|
||||
src_ff3v_fir_coefs[2-audioToUsbRatioCounter]);
|
||||
}
|
||||
#endif /* (AUD_TO_USB_RATIO > 1) */
|
||||
p_i2s_dac[index++] <: bitrev(samplesOut[frameCount +i]);
|
||||
if(XUA_I2S_N_BITS == 32)
|
||||
p_i2s_dac[index++] <: bitrev(samplesOut[frameCount +i]);
|
||||
else
|
||||
partout(p_i2s_dac[index++], XUA_I2S_N_BITS, bitrev(samplesOut[frameCount +i]));
|
||||
}
|
||||
#endif // (I2S_CHANS_DAC != 0)
|
||||
|
||||
@@ -417,8 +443,15 @@ unsigned static AudioHub_MainLoop(chanend ?c_out, chanend ?c_spd_out
|
||||
{
|
||||
/* Manual IN instruction since compiler generates an extra setc per IN (bug #15256) */
|
||||
unsigned sample;
|
||||
asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++]));
|
||||
asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index]));
|
||||
sample = bitrev(sample);
|
||||
if(XUA_I2S_N_BITS != 32)
|
||||
{
|
||||
set_port_shift_count(p_i2s_adc[index], XUA_I2S_N_BITS);
|
||||
sample <<= (32 - XUA_I2S_N_BITS);
|
||||
}
|
||||
index++;
|
||||
|
||||
int chanIndex = ((frameCount-2)&(I2S_CHANS_PER_FRAME-1))+i; // channels 1, 3, 5.. on each line.
|
||||
#if (AUD_TO_USB_RATIO > 1 && !I2S_DOWNSAMPLE_MONO_IN)
|
||||
if ((AUD_TO_USB_RATIO - 1) == audioToUsbRatioCounter)
|
||||
@@ -450,7 +483,6 @@ unsigned static AudioHub_MainLoop(chanend ?c_out, chanend ?c_spd_out
|
||||
#endif
|
||||
|
||||
index = 0;
|
||||
#pragma xta endpoint "i2s_output_r"
|
||||
#if (I2S_CHANS_DAC != 0)
|
||||
/* Output "odd" channel to DAC (i.e. right) */
|
||||
#pragma loop unroll
|
||||
@@ -469,7 +501,10 @@ unsigned static AudioHub_MainLoop(chanend ?c_out, chanend ?c_spd_out
|
||||
src_ff3v_fir_coefs[2-audioToUsbRatioCounter]);
|
||||
}
|
||||
#endif /* (AUD_TO_USB_RATIO > 1) */
|
||||
p_i2s_dac[index++] <: bitrev(samplesOut[frameCount + i]);
|
||||
if(XUA_I2S_N_BITS == 32)
|
||||
p_i2s_dac[index++] <: bitrev(samplesOut[frameCount + i]);
|
||||
else
|
||||
partout(p_i2s_dac[index++], XUA_I2S_N_BITS, bitrev(samplesOut[frameCount + i]));
|
||||
}
|
||||
#endif // (I2S_CHANS_DAC != 0)
|
||||
|
||||
@@ -523,7 +558,6 @@ unsigned static AudioHub_MainLoop(chanend ?c_out, chanend ?c_spd_out
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma xta endpoint "deliver_return"
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -681,13 +715,13 @@ void XUA_AudioHub(chanend ?c_aud, clock ?clk_audio_mclk, clock ?clk_audio_bclk,
|
||||
/* Calculate master clock to bit clock (or DSD clock) divide for current sample freq
|
||||
* e.g. 11.289600 / (176400 * 64) = 1 */
|
||||
{
|
||||
#if (XUA_PCM_FORMAT == XUA_PCM_FORMAT_TDM)
|
||||
/* I2S has 32 bits per sample. *8 as 8 channels */
|
||||
unsigned numBits = 256;
|
||||
#else
|
||||
/* I2S has 32 bits per sample. *2 as 2 channels */
|
||||
unsigned numBits = 64;
|
||||
#endif
|
||||
unsigned numBits = XUA_I2S_N_BITS * 2;
|
||||
|
||||
if(XUA_PCM_FORMAT == XUA_PCM_FORMAT_TDM)
|
||||
{
|
||||
/* TDM has 8 channels */
|
||||
numBits *= 4;
|
||||
}
|
||||
|
||||
#if (DSD_CHANS_DAC > 0)
|
||||
if(dsdMode == DSD_MODE_DOP)
|
||||
@@ -703,7 +737,15 @@ void XUA_AudioHub(chanend ?c_aud, clock ?clk_audio_mclk, clock ?clk_audio_bclk,
|
||||
#endif
|
||||
divide = mClk / (curSamFreq * numBits);
|
||||
|
||||
/* TODO; we should catch and handle the case when divide is 0. Currently design will lock up */
|
||||
//Do some checks
|
||||
xassert((divide > 0) && "Error: divider is 0, BCLK rate unachievable");
|
||||
|
||||
unsigned remainder = mClk % ( curSamFreq * numBits);
|
||||
xassert((!remainder) && "Error: MCLK not divisible into BCLK by an integer number");
|
||||
|
||||
unsigned divider_is_odd = divide & 0x1;
|
||||
xassert((!divider_is_odd) && "Error: divider is odd, clockblock cannot produce desired BCLK");
|
||||
|
||||
}
|
||||
|
||||
#if (DSD_CHANS_DAC > 0)
|
||||
|
||||
@@ -100,7 +100,7 @@ void ConfigAudioPorts(
|
||||
/* Do some clocking shifting to get data in the valid window */
|
||||
/* E.g. Only shift when running at 88.2+ kHz TDM slave */
|
||||
int bClkDelay_fall = 0;
|
||||
if(curSamFreq * I2S_CHANS_PER_FRAME * 32 >= 20000000)
|
||||
if(curSamFreq * I2S_CHANS_PER_FRAME * XUA_I2S_N_BITS >= 20000000)
|
||||
{
|
||||
/* 18 * 2ns = 36ns. This results in a -4ns (36 - 40) shift at 96KHz and -8ns (36 - 44) at 88.4KHz */
|
||||
bClkDelay_fall = 18;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// Copyright 2013-2021 XMOS LIMITED.
|
||||
// Copyright 2013-2023 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
|
||||
/*
|
||||
Warnings relating to configuration defines located in this XC source file rather than the devicedefines.h header file in order to avoid multiple warnings being issued when the devicedefines.h header file is included in multiple files.
|
||||
Warnings relating to configuration defines located in this XC source file rather than the xua_conf.h header file in order to avoid multiple warnings being issued when the xua_conf.h header file is included in multiple files.
|
||||
*/
|
||||
|
||||
#include "xua_conf_full.h"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright 2018-2022 XMOS LIMITED.
|
||||
# Copyright 2018-2023 XMOS LIMITED.
|
||||
# This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
import pytest
|
||||
import Pyxsim
|
||||
@@ -11,16 +11,21 @@ import sys
|
||||
def test_file(request):
|
||||
return str(request.node.fspath)
|
||||
|
||||
|
||||
def do_test(
|
||||
pcm_format, i2s_role, channel_count, sample_rate, test_file, options, capfd
|
||||
pcm_format, i2s_role, channel_count, sample_rate, word_length, test_file, options, capfd
|
||||
):
|
||||
|
||||
build_options = []
|
||||
output = []
|
||||
testname, _ = os.path.splitext(os.path.basename(test_file))
|
||||
|
||||
desc = f"simulation_{pcm_format}_{i2s_role}_{channel_count}in_{channel_count}out_{sample_rate}"
|
||||
build_options += [f"pcm_format={pcm_format}"]
|
||||
build_options += [f"i2s_role={i2s_role}"]
|
||||
build_options += [f"channel_count={channel_count}"]
|
||||
build_options += [f"sample_rate={sample_rate}"]
|
||||
build_options += [f"word_length={word_length}"]
|
||||
|
||||
desc = f"simulation_{pcm_format}_{i2s_role}_{channel_count}in_{channel_count}out_{sample_rate}_{word_length}bit"
|
||||
binary = f"{testname}/bin/{desc}/{testname}_{desc}.xe"
|
||||
|
||||
tester = testers.ComparisonTester(open("pass.expect"))
|
||||
@@ -52,6 +57,7 @@ def do_test(
|
||||
|
||||
result = Pyxsim.run_on_simulator(
|
||||
binary,
|
||||
build_options=build_options,
|
||||
tester=tester,
|
||||
simargs=simargs,
|
||||
capfd=capfd,
|
||||
@@ -65,25 +71,26 @@ def do_test(
|
||||
@pytest.mark.parametrize("i2s_role", ["master", "slave"])
|
||||
@pytest.mark.parametrize("pcm_format", ["i2s", "tdm"])
|
||||
@pytest.mark.parametrize("channel_count", [2, 8, 16])
|
||||
@pytest.mark.parametrize("sample_rate", ["48khz", "96khz", "192khz"])
|
||||
@pytest.mark.parametrize("word_length", [16, 32]) # I2S world length in bits
|
||||
@pytest.mark.parametrize("sample_rate", [48000, 96000, 192000])
|
||||
def test_i2s_loopback(
|
||||
i2s_role, pcm_format, channel_count, sample_rate, test_file, options, capfd
|
||||
i2s_role, pcm_format, channel_count, sample_rate, word_length, test_file, options, capfd
|
||||
):
|
||||
|
||||
if pcm_format == "i2s" and channel_count == 16:
|
||||
pytest.skip("Invalid parameter combination")
|
||||
|
||||
if pcm_format == "i2s" and sample_rate not in ["48khz", "192khz"]:
|
||||
if pcm_format == "i2s" and sample_rate not in [48000, 192000]:
|
||||
pytest.skip("Invalid parameter combination")
|
||||
|
||||
if pcm_format == "tdm" and channel_count == 2:
|
||||
pytest.skip("Invalid parameter combination")
|
||||
|
||||
if pcm_format == "tdm" and sample_rate == "192khz":
|
||||
if pcm_format == "tdm" and sample_rate == 192000:
|
||||
pytest.skip("Invalid parameter combination")
|
||||
|
||||
result = do_test(
|
||||
pcm_format, i2s_role, channel_count, sample_rate, test_file, options, capfd
|
||||
pcm_format, i2s_role, channel_count, sample_rate, word_length, test_file, options, capfd
|
||||
)
|
||||
|
||||
assert result
|
||||
|
||||
@@ -1,126 +1,44 @@
|
||||
TARGET = xk-audio-216-mc.xn
|
||||
USED_MODULES = lib_xua lib_i2c lib_logging
|
||||
|
||||
BUILD_FLAGS = -O0 -g -lflash -DXUD_CORE_CLOCK=600 -fxscope -save-temps -march=xs2a -DUSB_TILE=tile[1]
|
||||
BUILD_FLAGS = -O3 -g -lflash -DXUD_CORE_CLOCK=600 -fxscope -save-temps -march=xs2a -DUSB_TILE=tile[1] \
|
||||
-DXUA_ADAT_RX_EN=0 -DXUA_ADAT_TX_EN=0 -DXUA_SPDIF_RX_EN=0 -DXUA_SPDIF_TX_EN=0 -DMIDI=0 \
|
||||
-DSIMULATION=1
|
||||
|
||||
BUILD_FLAGS_i2s_master_2in_2out_48khz = $(BUILD_FLAGS) \
|
||||
-D XUA_ADAT_RX_EN=0 -D XUA_ADAT_TX_EN=0 -D XUA_SPDIF_RX_EN=0 -D XUA_SPDIF_TX_EN=0 -D MIDI=0 \
|
||||
-D NUM_USB_CHAN_IN=2 -D NUM_USB_CHAN_OUT=2 -DI2S_CHANS_ADC=2 -DI2S_CHANS_DAC=2 \
|
||||
-D DEFAULT_FREQ=48000
|
||||
ifndef pcm_format
|
||||
$(error pcm_format is not set)
|
||||
endif
|
||||
|
||||
BUILD_FLAGS_i2s_slave_2in_2out_48khz = $(BUILD_FLAGS) \
|
||||
-D XUA_ADAT_RX_EN=0 -D XUA_ADAT_TX_EN=0 -D XUA_SPDIF_RX_EN=0 -D XUA_SPDIF_TX_EN=0 -D MIDI=0 \
|
||||
-D NUM_USB_CHAN_IN=2 -D NUM_USB_CHAN_OUT=2 -DI2S_CHANS_ADC=2 -DI2S_CHANS_DAC=2 \
|
||||
-D DEFAULT_FREQ=48000 -DCODEC_MASTER=1
|
||||
ifndef i2s_role
|
||||
$(error i2s_role is not set)
|
||||
endif
|
||||
|
||||
BUILD_FLAGS_i2s_master_2in_2out_192khz = $(BUILD_FLAGS) \
|
||||
-D XUA_ADAT_RX_EN=0 -D XUA_ADAT_TX_EN=0 -D XUA_SPDIF_RX_EN=0 -D XUA_SPDIF_TX_EN=0 -D MIDI=0 \
|
||||
-D NUM_USB_CHAN_IN=2 -D NUM_USB_CHAN_OUT=2 -D I2S_CHANS_ADC=2 -D I2S_CHANS_DAC=2 \
|
||||
-D DEFAULT_FREQ=192000
|
||||
ifndef channel_count
|
||||
$(error channel_count is not set)
|
||||
endif
|
||||
|
||||
BUILD_FLAGS_i2s_slave_2in_2out_192khz = $(BUILD_FLAGS) \
|
||||
-D XUA_ADAT_RX_EN=0 -D XUA_ADAT_TX_EN=0 -D XUA_SPDIF_RX_EN=0 -D XUA_SPDIF_TX_EN=0 -D MIDI=0 \
|
||||
-D NUM_USB_CHAN_IN=2 -D NUM_USB_CHAN_OUT=2 -DI2S_CHANS_ADC=2 -DI2S_CHANS_DAC=2 \
|
||||
-D DEFAULT_FREQ=192000 -DCODEC_MASTER=1
|
||||
ifndef sample_rate
|
||||
$(error sample_rate is not set)
|
||||
endif
|
||||
|
||||
BUILD_FLAGS_i2s_master_8in_8out_48khz = $(BUILD_FLAGS) \
|
||||
-D XUA_ADAT_RX_EN=0 -D XUA_ADAT_TX_EN=0 -D XUA_SPDIF_RX_EN=0 -D XUA_SPDIF_TX_EN=0 -D MIDI=0 \
|
||||
-D NUM_USB_CHAN_IN=8 -D NUM_USB_CHAN_OUT=8 -D I2S_CHANS_ADC=8 -D I2S_CHANS_DAC=8 \
|
||||
-D DEFAULT_FREQ=48000
|
||||
ifndef word_length
|
||||
$(error word_length is not set)
|
||||
endif
|
||||
|
||||
BUILD_FLAGS_i2s_slave_8in_8out_48khz = $(BUILD_FLAGS) \
|
||||
-D XUA_ADAT_RX_EN=0 -D XUA_ADAT_TX_EN=0 -D XUA_SPDIF_RX_EN=0 -D XUA_SPDIF_TX_EN=0 -D MIDI=0 \
|
||||
-D NUM_USB_CHAN_IN=8 -D NUM_USB_CHAN_OUT=8 -D I2S_CHANS_ADC=8 -D I2S_CHANS_DAC=8 \
|
||||
-D DEFAULT_FREQ=48000 -DCODEC_MASTER=1
|
||||
ifeq ($(pcm_format),tdm)
|
||||
BUILD_FLAGS += -DXUA_PCM_FORMAT=XUA_PCM_FORMAT_TDM
|
||||
endif
|
||||
ifeq ($(i2s_role),slave)
|
||||
BUILD_FLAGS += -DCODEC_MASTER=1
|
||||
endif
|
||||
|
||||
BUILD_FLAGS_i2s_master_8in_8out_192khz = $(BUILD_FLAGS) \
|
||||
-D XUA_ADAT_RX_EN=0 -D XUA_ADAT_TX_EN=0 -D XUA_SPDIF_RX_EN=0 -D XUA_SPDIF_TX_EN=0 -D MIDI=0 \
|
||||
-D NUM_USB_CHAN_IN=8 -D NUM_USB_CHAN_OUT=8 -D I2S_CHANS_ADC=8 -D I2S_CHANS_DAC=8 \
|
||||
-D DEFAULT_FREQ=192000 \
|
||||
-O2 # optimisations to meet timing
|
||||
|
||||
BUILD_FLAGS_i2s_slave_8in_8out_192khz = $(BUILD_FLAGS) \
|
||||
-D XUA_ADAT_RX_EN=0 -D XUA_ADAT_TX_EN=0 -D XUA_SPDIF_RX_EN=0 -D XUA_SPDIF_TX_EN=0 -D MIDI=0 \
|
||||
-D NUM_USB_CHAN_IN=8 -D NUM_USB_CHAN_OUT=8 -D I2S_CHANS_ADC=8 -D I2S_CHANS_DAC=8 \
|
||||
-D DEFAULT_FREQ=192000 -DCODEC_MASTER=1 \
|
||||
-O2 # optimisations to meet timing
|
||||
|
||||
BUILD_FLAGS_tdm_master_8in_8out_48khz = $(BUILD_FLAGS) -D XUA_PCM_FORMAT=XUA_PCM_FORMAT_TDM \
|
||||
-D XUA_ADAT_RX_EN=0 -D XUA_ADAT_TX_EN=0 -D XUA_SPDIF_RX_EN=0 -D XUA_SPDIF_TX_EN=0 -D MIDI=0 \
|
||||
-D NUM_USB_CHAN_IN=8 -D NUM_USB_CHAN_OUT=8 -D I2S_CHANS_ADC=8 -D I2S_CHANS_DAC=8 \
|
||||
-D DEFAULT_FREQ=48000 \
|
||||
-O2 # optimisations to meet timing
|
||||
|
||||
BUILD_FLAGS_tdm_master_8in_8out_96khz = $(BUILD_FLAGS) -D XUA_PCM_FORMAT=XUA_PCM_FORMAT_TDM \
|
||||
-D XUA_ADAT_RX_EN=0 -D XUA_ADAT_TX_EN=0 -D XUA_SPDIF_RX_EN=0 -D XUA_SPDIF_TX_EN=0 -D MIDI=0 \
|
||||
-D NUM_USB_CHAN_IN=8 -D NUM_USB_CHAN_OUT=8 -D I2S_CHANS_ADC=8 -D I2S_CHANS_DAC=8 \
|
||||
-D DEFAULT_FREQ=96000 \
|
||||
-O3 # optimisations to meet timing
|
||||
|
||||
BUILD_FLAGS_tdm_slave_8in_8out_48khz = $(BUILD_FLAGS) -D XUA_PCM_FORMAT=XUA_PCM_FORMAT_TDM \
|
||||
-D XUA_ADAT_RX_EN=0 -D XUA_ADAT_TX_EN=0 -D XUA_SPDIF_RX_EN=0 -D XUA_SPDIF_TX_EN=0 -D MIDI=0 \
|
||||
-D NUM_USB_CHAN_IN=8 -D NUM_USB_CHAN_OUT=8 -D I2S_CHANS_ADC=8 -D I2S_CHANS_DAC=8 \
|
||||
-D DEFAULT_FREQ=48000 -DCODEC_MASTER=1 \
|
||||
-O2 # optimisations to meet timing
|
||||
|
||||
BUILD_FLAGS_tdm_slave_8in_8out_96khz = $(BUILD_FLAGS) -D XUA_PCM_FORMAT=XUA_PCM_FORMAT_TDM \
|
||||
-D XUA_ADAT_RX_EN=0 -D XUA_ADAT_TX_EN=0 -D XUA_SPDIF_RX_EN=0 -D XUA_SPDIF_TX_EN=0 -D MIDI=0 \
|
||||
-D NUM_USB_CHAN_IN=8 -D NUM_USB_CHAN_OUT=8 -D I2S_CHANS_ADC=8 -D I2S_CHANS_DAC=8 \
|
||||
-D DEFAULT_FREQ=96000 -DCODEC_MASTER=1 \
|
||||
-O2 # optimisations to meet timing
|
||||
|
||||
BUILD_FLAGS_tdm_master_16in_16out_48khz = $(BUILD_FLAGS) -D XUA_PCM_FORMAT=XUA_PCM_FORMAT_TDM \
|
||||
-D XUA_ADAT_RX_EN=0 -D XUA_ADAT_TX_EN=0 -D XUA_SPDIF_RX_EN=0 -D XUA_SPDIF_TX_EN=0 -D MIDI=0 \
|
||||
-D NUM_USB_CHAN_IN=16 -D NUM_USB_CHAN_OUT=16 -D I2S_CHANS_ADC=16 -D I2S_CHANS_DAC=16 \
|
||||
-D DEFAULT_FREQ=48000 \
|
||||
-O2 # optimisations to meet timing
|
||||
|
||||
BUILD_FLAGS_tdm_master_16in_16out_96khz = $(BUILD_FLAGS) -D XUA_PCM_FORMAT=XUA_PCM_FORMAT_TDM \
|
||||
-D XUA_ADAT_RX_EN=0 -D XUA_ADAT_TX_EN=0 -D XUA_SPDIF_RX_EN=0 -D XUA_SPDIF_TX_EN=0 -D MIDI=0 \
|
||||
-D NUM_USB_CHAN_IN=16 -D NUM_USB_CHAN_OUT=16 -D I2S_CHANS_ADC=16 -D I2S_CHANS_DAC=16 \
|
||||
-D DEFAULT_FREQ=96000 \
|
||||
-O2 # optimisations to meet timing
|
||||
|
||||
BUILD_FLAGS_tdm_slave_16in_16out_48khz = $(BUILD_FLAGS) -D XUA_PCM_FORMAT=XUA_PCM_FORMAT_TDM \
|
||||
-D XUA_ADAT_RX_EN=0 -D XUA_ADAT_TX_EN=0 -D XUA_SPDIF_RX_EN=0 -D XUA_SPDIF_TX_EN=0 -D MIDI=0 \
|
||||
-D NUM_USB_CHAN_IN=16 -D NUM_USB_CHAN_OUT=16 -D I2S_CHANS_ADC=16 -D I2S_CHANS_DAC=16 \
|
||||
-D DEFAULT_FREQ=48000 -DCODEC_MASTER=1 \
|
||||
-O2 # optimisations to meet timing
|
||||
|
||||
BUILD_FLAGS_tdm_slave_16in_16out_96khz = $(BUILD_FLAGS) -D XUA_PCM_FORMAT=XUA_PCM_FORMAT_TDM \
|
||||
-D XUA_ADAT_RX_EN=0 -D XUA_ADAT_TX_EN=0 -D XUA_SPDIF_RX_EN=0 -D XUA_SPDIF_TX_EN=0 -D MIDI=0 \
|
||||
-D NUM_USB_CHAN_IN=16 -D NUM_USB_CHAN_OUT=16 -D I2S_CHANS_ADC=16 -D I2S_CHANS_DAC=16 \
|
||||
-D DEFAULT_FREQ=96000 -DCODEC_MASTER=1 \
|
||||
-O2 # optimisations to meet timing
|
||||
|
||||
|
||||
#XCC_FLAGS_hardware_i2s_master_2in_2out_48khz = -D HARDWARE $(BUILD_FLAGS_i2s_master_2in_2out_48khz)
|
||||
#XCC_FLAGS_hardware_i2s_master_2in_2out_192khz = -D HARDWARE $(BUILD_FLAGS_i2s_master_2in_2out_192khz)
|
||||
#XCC_FLAGS_hardware_i2s_master_8in_8out_48khz = -D HARDWARE $(BUILD_FLAGS_i2s_master_8in_8out_48khz)
|
||||
#XCC_FLAGS_hardware_i2s_master_8in_8out_192khz = -D HARDWARE $(BUILD_FLAGS_i2s_master_8in_8out_192khz)
|
||||
#XCC_FLAGS_hardware_tdm_master_8in_8out_48khz = -D HARDWARE $(BUILD_FLAGS_tdm_master_8in_8out_48khz)
|
||||
|
||||
XCC_FLAGS_simulation_i2s_master_2in_2out_48khz = -D SIMULATION $(BUILD_FLAGS_i2s_master_2in_2out_48khz)
|
||||
XCC_FLAGS_simulation_i2s_slave_2in_2out_48khz = -D SIMULATION $(BUILD_FLAGS_i2s_slave_2in_2out_48khz)
|
||||
|
||||
XCC_FLAGS_simulation_i2s_master_2in_2out_192khz = -D SIMULATION $(BUILD_FLAGS_i2s_master_2in_2out_192khz)
|
||||
XCC_FLAGS_simulation_i2s_slave_2in_2out_192khz = -D SIMULATION $(BUILD_FLAGS_i2s_slave_2in_2out_192khz)
|
||||
|
||||
XCC_FLAGS_simulation_i2s_master_8in_8out_48khz = -D SIMULATION $(BUILD_FLAGS_i2s_master_8in_8out_48khz)
|
||||
XCC_FLAGS_simulation_i2s_slave_8in_8out_48khz = -D SIMULATION $(BUILD_FLAGS_i2s_slave_8in_8out_48khz)
|
||||
|
||||
XCC_FLAGS_simulation_i2s_master_8in_8out_192khz = -D SIMULATION $(BUILD_FLAGS_i2s_master_8in_8out_192khz)
|
||||
XCC_FLAGS_simulation_i2s_slave_8in_8out_192khz = -D SIMULATION $(BUILD_FLAGS_i2s_slave_8in_8out_192khz)
|
||||
|
||||
XCC_FLAGS_simulation_tdm_master_8in_8out_48khz = -D SIMULATION $(BUILD_FLAGS_tdm_master_8in_8out_48khz)
|
||||
XCC_FLAGS_simulation_tdm_master_8in_8out_96khz = -D SIMULATION $(BUILD_FLAGS_tdm_master_8in_8out_96khz)
|
||||
XCC_FLAGS_simulation_tdm_slave_8in_8out_48khz = -D SIMULATION $(BUILD_FLAGS_tdm_slave_8in_8out_48khz)
|
||||
XCC_FLAGS_simulation_tdm_slave_8in_8out_96khz = -D SIMULATION $(BUILD_FLAGS_tdm_slave_8in_8out_96khz)
|
||||
|
||||
XCC_FLAGS_simulation_tdm_master_16in_16out_48khz = -D SIMULATION $(BUILD_FLAGS_tdm_master_16in_16out_48khz)
|
||||
XCC_FLAGS_simulation_tdm_master_16in_16out_96khz = -D SIMULATION $(BUILD_FLAGS_tdm_master_16in_16out_96khz)
|
||||
XCC_FLAGS_simulation_tdm_slave_16in_16out_48khz = -D SIMULATION $(BUILD_FLAGS_tdm_slave_16in_16out_48khz)
|
||||
XCC_FLAGS_simulation_tdm_slave_16in_16out_96khz = -D SIMULATION $(BUILD_FLAGS_tdm_slave_16in_16out_96khz)
|
||||
XCC_FLAGS_simulation_${pcm_format}_${i2s_role}_$(channel_count)in_$(channel_count)out_$(sample_rate)_$(word_length)bit = $(BUILD_FLAGS) \
|
||||
-DNUM_USB_CHAN_IN=${channel_count} \
|
||||
-DNUM_USB_CHAN_OUT=${channel_count} \
|
||||
-DI2S_CHANS_DAC=${channel_count} \
|
||||
-DI2S_CHANS_ADC=${channel_count} \
|
||||
-DDEFAULT_FREQ=${sample_rate} \
|
||||
-DXUA_I2S_N_BITS=${word_length}
|
||||
|
||||
XMOS_MAKE_PATH ?= ../..
|
||||
-include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.common
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2016-2022 XMOS LIMITED.
|
||||
// Copyright 2016-2023 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
#include <platform.h>
|
||||
#include <stdlib.h>
|
||||
@@ -9,7 +9,6 @@
|
||||
#define DEBUG_UNIT MAIN
|
||||
#include "debug_print.h"
|
||||
|
||||
|
||||
/* Port declarations. Note, the defines come from the xn file */
|
||||
#if I2S_WIRES_DAC > 0
|
||||
on tile[AUDIO_IO_TILE] : buffered out port:32 p_i2s_dac[I2S_WIRES_DAC] =
|
||||
@@ -92,9 +91,10 @@ clock clk_audio_mclk = on tile[AUDIO_IO_TILE]: XS1_CLKBLK_2; /*
|
||||
#define TOTAL_TEST_FRAMES (5 * DEFAULT_FREQ)
|
||||
#endif
|
||||
|
||||
#define SAMPLE(frame_count, channel_num) (((frame_count) << 8) | ((channel_num) & 0xFF))
|
||||
#define SAMPLE_FRAME_NUM(test_word) ((test_word) >> 8)
|
||||
#define SAMPLE_CHANNEL_NUM(test_word) ((test_word) & 0xFF)
|
||||
#define SHIFT (16) /* Note, we shift samples up such that we can test down to 16bit I2S */
|
||||
#define SAMPLE(frame_count, channel_num) ((((frame_count) << 8) | ((channel_num) & 0xFF))<<SHIFT)
|
||||
#define SAMPLE_FRAME_NUM(test_word) ((test_word>>SHIFT) >> 8)
|
||||
#define SAMPLE_CHANNEL_NUM(test_word) ((test_word>>SHIFT) & 0xFF)
|
||||
|
||||
void generator(chanend c_checker, chanend c_out)
|
||||
{
|
||||
@@ -105,7 +105,6 @@ void generator(chanend c_checker, chanend c_out)
|
||||
|
||||
frame_count = 0;
|
||||
|
||||
|
||||
while (1) {
|
||||
underflow_word = inuint(c_out);
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2016-2022 XMOS LIMITED.
|
||||
// Copyright 2016-2023 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
#ifdef SIMULATION
|
||||
|
||||
@@ -41,7 +41,7 @@ extern out port p_lrclk_gen;
|
||||
extern clock clk_audio_lrclk_gen;
|
||||
|
||||
void slave_mode_clk_setup(const unsigned samFreq, const unsigned chans_per_frame){
|
||||
const unsigned data_bits = 32;
|
||||
const unsigned data_bits = XUA_I2S_N_BITS;
|
||||
const unsigned mclk_freq = 24576000;
|
||||
|
||||
const unsigned mclk_bclk_ratio = mclk_freq / (chans_per_frame * samFreq * data_bits);
|
||||
@@ -61,5 +61,4 @@ void slave_mode_clk_setup(const unsigned samFreq, const unsigned chans_per_frame
|
||||
master_mode_clk_setup();
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user