23 Commits

Author SHA1 Message Date
Ross Owen
dd8d2675d3 App PLL sync mode improvements:
- Added IIR to reduce jitter into DCO
- Added PID for tracking external clock
- Added basic “fast lock” based on an initial estimate
2023-08-15 11:58:32 +01:00
Ross Owen
7930a5d59c Sync mode 2nd order delta sigma replaced with third order, level output. 2023-08-08 18:19:04 +01:00
Ross Owen
158d79335c Sync mode related build fix 2023-08-02 12:43:04 +01:00
Ross Owen
ebc09e1c4f Fixes for sync mode related build warnings/errors 2023-08-02 12:14:21 +01:00
Ross Owen
a7943a8859 - Improved audio performance in synchronous mode when using the App PLL
- Software PLL code now uses a core rather than running entirely in XUA_Buffer_EP()
2023-08-01 15:56:00 +01:00
Ross Owen
77fad35497 Documentation updates 2023-07-17 14:23:09 +01:00
Ross Owen
50966dda90 Build fixes related to the use of i_pll_ref 2023-07-14 16:07:38 +01:00
Ross Owen
e7b5faed66 Documentation updates and fixes 2023-07-14 15:58:54 +01:00
Ross Owen
7f72c4b842 - Moved audiohw functions from xua_audiohub into user folder in line with other user functions 2023-07-14 15:58:03 +01:00
Ross Owen
d119755313 Do not use sync out pin when using app PLL for sync mode 2023-07-14 11:59:15 +01:00
Ross Owen
2228575e09 Documentation updates 2023-07-14 11:59:15 +01:00
Ross Owen
b6972295e9 Merge pull request #339 from xross/experimetal/sync_app_pll
Experimental synchronous mode using xs3 app pll
2023-07-13 16:15:26 +01:00
Ross Owen
39802f3620 Example app note code now use app pll code from lib_xua 2023-07-13 15:09:29 +01:00
Ross Owen
5bf53fa453 Fix to test_sync_clk_basic 2023-07-13 14:12:52 +01:00
Ross Owen
2f11eda7d8 - Added AudioHwConfig_Mute() and AudioHwConfig_UnMute()
- Added default (empty) implementations of AudioHW.. functions
2023-07-13 14:12:41 +01:00
Ross Owen
1574137dda - Update sofCount type
- Fix sync clock tests
2023-07-13 13:01:25 +01:00
Ross Owen
c7e782179c Added copyright/licence comments 2023-07-12 15:36:00 +01:00
Ross Owen
badcb71c80 - Added app PLL config functions - previously were in sw_usb_audio
- Use app PLL for sync mode
- Use app PLL on xcore.ai devices by default (unless ADAT or SPDIF receive enabled) 
- Added XUA_USE_APP_PLL (which is default 1)
- Some tidy of xua_conf_default.h
- Added DEFAULT_MCLK define
2023-07-11 13:57:14 +01:00
Ross Owen
dff72573f8 Scripted changelog update 2023-06-21 12:14:34 +01:00
Ross Owen
aaaf1e9652 Version bump 3.5.0 -> 3.5.1 2023-06-21 12:11:56 +01:00
Ross Owen
d6b23cf960 Merge pull request #337 from xross/develop
Respect I2S_CHANS_PER_FRAME when calculating bit-clock rates
2023-06-21 10:06:57 +01:00
Ross Owen
fa8329edaa Changelog update 2023-06-20 20:04:17 +01:00
Ross Owen
83d86e885f Respect I2S_CHANS_PER_FRAME when calculating bit-clock rates 2023-06-20 19:36:26 +01:00
25 changed files with 1403 additions and 344 deletions

View File

@@ -1,6 +1,15 @@
lib_xua Change Log
==================
3.5.1
-----
* FIXED: Respect I2S_CHANS_PER_FRAME when calculating bit-clock rates
* Changes to dependencies:
- lib_spdif: 5.0.0 -> 5.0.1
3.5.0
-----

View File

@@ -1,9 +1,8 @@
// Copyright 2017-2022 XMOS LIMITED.
// Copyright 2017-2023 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#include <xs1.h>
#include <platform.h>
#include "xua.h"
#include "../../shared/apppll.h"
on tile[0]: out port p_ctrl = XS1_PORT_8D;
@@ -35,11 +34,6 @@ void ctrlPort()
void AudioHwInit()
{
/* Wait for power supply to come up */
delay_milliseconds(100);
/* Use xCORE Secondary PLL to generate *fixed* master clock */
AppPllEnable_SampleRate(DEFAULT_FREQ);
delay_milliseconds(100);
/* DAC setup: For basic I2S input we don't need any register setup. DACs will clock auto detect etc.
@@ -48,9 +42,12 @@ void AudioHwInit()
*/
}
/* Configures the external audio hardware for the required sample frequency */
/* Configures the external audio hardware for the required sample frequency
* Note, the application PLL in xcore.ai will be configured to the correct master clock frequency
* by lib_xua
*/
void AudioHwConfig(unsigned samFreq, unsigned mClk, unsigned dsdMode, unsigned sampRes_DAC, unsigned sampRes_ADC)
{
AppPllEnable_SampleRate(samFreq);
/* Nothing required since the DAC's will auto detect the sample rate from the clocks */
}

View File

@@ -1,9 +1,8 @@
// Copyright 2017-2022 XMOS LIMITED.
// Copyright 2017-2023 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#include <xs1.h>
#include <platform.h>
#include "xua.h"
#include "../../shared/apppll.h"
on tile[0]: out port p_ctrl = XS1_PORT_8D;
@@ -35,11 +34,6 @@ void ctrlPort()
void AudioHwInit()
{
/* Wait for power supply to come up */
delay_milliseconds(100);
/* Use xCORE Secondary PLL to generate *fixed* master clock */
AppPllEnable_SampleRate(DEFAULT_FREQ);
delay_milliseconds(100);
/* DAC setup: For basic I2S input we don't need any register setup. DACs will clock auto detect etc.
@@ -48,9 +42,12 @@ void AudioHwInit()
*/
}
/* Configures the external audio hardware for the required sample frequency */
/* Configures the external audio hardware for the required sample frequency
* Note, the application PLL in xcore.ai will be configured to the correct master clock frequency
* by lib_xua
*/
void AudioHwConfig(unsigned samFreq, unsigned mClk, unsigned dsdMode, unsigned sampRes_DAC, unsigned sampRes_ADC)
{
AppPllEnable_SampleRate(samFreq);
/* Nothing required since the DAC's will auto detect the sample rate from the clocks */
}

View File

@@ -1,109 +0,0 @@
// Copyright 2022 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#include <stdint.h>
#include "xassert.h"
// App PLL setup
#define APP_PLL_CTL_BYPASS (0) // 0 = no bypass, 1 = bypass.
#define APP_PLL_CTL_INPUT_SEL (0) // 0 = XTAL, 1 = sysPLL
#define APP_PLL_CTL_ENABLE (1) // 0 = disabled, 1 = enabled.
// 24MHz in, 24.576MHz out, integer mode
// Found exact solution: IN 24000000.0, OUT 24576000.0, VCO 2457600000.0, RD 5, FD 512, OD 10, FOD 10
#define APP_PLL_CTL_OD_48 (4) // Output divider = (OD+1)
#define APP_PLL_CTL_F_48 (511) // FB divider = (F+1)/2
#define APP_PLL_CTL_R_48 (4) // Ref divider = (R+1)
#define APP_PLL_CTL_48 ((APP_PLL_CTL_BYPASS << 29) | (APP_PLL_CTL_INPUT_SEL << 28) | (APP_PLL_CTL_ENABLE << 27) |\
(APP_PLL_CTL_OD_48 << 23) | (APP_PLL_CTL_F_48 << 8) | APP_PLL_CTL_R_48)
// Fractional divide is M/N
#define APP_PLL_FRAC_EN_48 (0) // 0 = disabled
#define APP_PLL_FRAC_NPLUS1_CYCLES_48 (0) // M value is this reg value + 1.
#define APP_PLL_FRAC_TOTAL_CYCLES_48 (0) // N value is this reg value + 1.
#define APP_PLL_FRAC_48 ((APP_PLL_FRAC_EN_48 << 31) | (APP_PLL_FRAC_NPLUS1_CYCLES_48 << 8) | APP_PLL_FRAC_TOTAL_CYCLES_48)
// 24MHz in, 22.5792MHz out (44.1kHz * 512), frac mode
// Found exact solution: IN 24000000.0, OUT 22579200.0, VCO 2257920000.0, RD 5, FD 470.400 (m = 2, n = 5), OD 5, FOD 10
#define APP_PLL_CTL_OD_441 (4) // Output divider = (OD+1)
#define APP_PLL_CTL_F_441 (469) // FB divider = (F+1)/2
#define APP_PLL_CTL_R_441 (4) // Ref divider = (R+1)
#define APP_PLL_CTL_441 ((APP_PLL_CTL_BYPASS << 29) | (APP_PLL_CTL_INPUT_SEL << 28) | (APP_PLL_CTL_ENABLE << 27) |\
(APP_PLL_CTL_OD_441 << 23) | (APP_PLL_CTL_F_441 << 8) | APP_PLL_CTL_R_441)
#define APP_PLL_FRAC_EN_44 (1) // 1 = enabled
#define APP_PLL_FRAC_NPLUS1_CYCLES_44 (1) // M value is this reg value + 1.
#define APP_PLL_FRAC_TOTAL_CYCLES_44 (4) // N value is this reg value + 1.define APP_PLL_CTL_R_441 (4) // Ref divider = (R+1)
#define APP_PLL_FRAC_44 ((APP_PLL_FRAC_EN_44 << 31) | (APP_PLL_FRAC_NPLUS1_CYCLES_44 << 8) | APP_PLL_FRAC_TOTAL_CYCLES_44)
#define APP_PLL_DIV_INPUT_SEL (1) // 0 = sysPLL, 1 = app_PLL
#define APP_PLL_DIV_DISABLE (0) // 1 = disabled (pin connected to X1D11), 0 = enabled divider output to pin.
#define APP_PLL_DIV_VALUE (4) // Divide by N+1 - remember there's a /2 also afterwards for 50/50 duty cycle.
#define APP_PLL_DIV ((APP_PLL_DIV_INPUT_SEL << 31) | (APP_PLL_DIV_DISABLE << 16) | APP_PLL_DIV_VALUE)
/* TODO support more than two freqs..*/
void AppPllEnable(int32_t clkFreq_hz)
{
switch(clkFreq_hz)
{
case 44100*512:
// Disable the PLL
write_node_config_reg(tile[1], XS1_SSWITCH_SS_APP_PLL_CTL_NUM, (APP_PLL_CTL_441 & 0xF7FFFFFF));
// Enable the PLL to invoke a reset on the appPLL.
write_node_config_reg(tile[1], XS1_SSWITCH_SS_APP_PLL_CTL_NUM, APP_PLL_CTL_441);
// Must write the CTL register twice so that the F and R divider values are captured using a running clock.
write_node_config_reg(tile[1], XS1_SSWITCH_SS_APP_PLL_CTL_NUM, APP_PLL_CTL_441);
// Now disable and re-enable the PLL so we get the full 5us reset time with the correct F and R values.
write_node_config_reg(tile[1], XS1_SSWITCH_SS_APP_PLL_CTL_NUM, (APP_PLL_CTL_441 & 0xF7FFFFFF));
write_node_config_reg(tile[1], XS1_SSWITCH_SS_APP_PLL_CTL_NUM, APP_PLL_CTL_441);
// Set the fractional divider if used
write_node_config_reg(tile[0], XS1_SSWITCH_SS_APP_PLL_FRAC_N_DIVIDER_NUM, APP_PLL_FRAC_44);
break;
case 48000*512:
// Disable the PLL
write_node_config_reg(tile[1], XS1_SSWITCH_SS_APP_PLL_CTL_NUM, (APP_PLL_CTL_48 & 0xF7FFFFFF));
// Enable the PLL to invoke a reset on the appPLL.
write_node_config_reg(tile[1], XS1_SSWITCH_SS_APP_PLL_CTL_NUM, APP_PLL_CTL_48);
// Must write the CTL register twice so that the F and R divider values are captured using a running clock.
write_node_config_reg(tile[1], XS1_SSWITCH_SS_APP_PLL_CTL_NUM, APP_PLL_CTL_48);
// Now disable and re-enable the PLL so we get the full 5us reset time with the correct F and R values.
write_node_config_reg(tile[1], XS1_SSWITCH_SS_APP_PLL_CTL_NUM, (APP_PLL_CTL_48 & 0xF7FFFFFF));
write_node_config_reg(tile[1], XS1_SSWITCH_SS_APP_PLL_CTL_NUM, APP_PLL_CTL_48);
// Set the fractional divider if used
write_node_config_reg(tile[0], XS1_SSWITCH_SS_APP_PLL_FRAC_N_DIVIDER_NUM, APP_PLL_FRAC_48);
break;
default:
assert(0);
break;
}
// Wait for PLL output frequency to stabilise due to fractional divider enable
delay_microseconds(100);
// Turn on the clock output
write_node_config_reg(tile[0], XS1_SSWITCH_SS_APP_CLK_DIVIDER_NUM, APP_PLL_DIV);
}
void AppPllEnable_SampleRate(int32_t sampleRate_hz)
{
assert(sampleRate_hz >= 22050);
if(sampleRate_hz % 22050 == 0)
{
AppPllEnable(44100*512);
}
else
{
AppPllEnable(48000*512);
}
}

View File

@@ -12,6 +12,8 @@
#include "dfu_interface.h"
#endif
#include "xua_clocking.h"
/** The audio driver thread.
*
* This function drives I2S ports and handles samples to/from other digital
@@ -34,6 +36,8 @@
*
* \param p_i2s_adc Nullable array of ports for I2S data input lines
*
* \param i_SoftPll Interface to software PLL task
*
* \param c_spdif_tx Channel connected to S/PDIF transmiter core from lib_spdif
*
* \param c_dig Channel connected to the clockGen() thread for
@@ -47,6 +51,9 @@ void XUA_AudioHub(chanend ?c_aud,
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_USE_APP_PLL) || defined(__DOXYGEN__)
, client interface SoftPll_if i_SoftPll
#endif
#if (XUA_SPDIF_TX_EN) || defined(__DOXYGEN__)
, chanend c_spdif_tx
#endif
@@ -63,21 +70,28 @@ void XUA_AudioHub(chanend ?c_aud,
void SpdifTxWrapper(chanend c_spdif_tx);
/* These functions must be implemented for the CODEC/ADC/DAC arrangement of a specific design */
/* Any required clocking and CODEC initialisation - run once at start up */
/* TODO Provide default implementation of this */
void AudioHwInit();
/* Configure audio hardware (clocking, CODECs etc) for a specific mClk/Sample frquency - run on every sample frequency change */
/* TODO Provide default implementation of this */
void AudioHwConfig(unsigned samFreq, unsigned mClk, unsigned dsdMode,
unsigned sampRes_DAC, unsigned sampRes_ADC);
#endif // __XC__
void UserBufferManagementInit();
/**
* @brief User buffer management code
*
* This function is called at the sample rate of the USB Audio stack (e.g,. 48 kHz) and between the two parameter arrays
* contain a full multi-channel audio-frame. The first array carries all the data that has been received from the USB host
* and is to be presented to the audio interfaces. The second array carries all the data received from the interfaces and
* is to be presented to the USB host. The user can chose to intercept and overwrite the samples stored in these arrays.
*
* \param sampsFromUsbToAudio Samples received from USB host and to be presented to audio interfaces
*
* \param sampsFromAudioToUsb Samples received from the audio interfaces and to be presented to the USB host
*/
void UserBufferManagement(unsigned sampsFromUsbToAudio[], unsigned sampsFromAudioToUsb[]);
/**
* @brief User buffer managment init code
*
* This function is called once, before the first call to UserBufferManagement(), and can be used to initialise any
* related user state
*/
void UserBufferManagementInit();
#endif // _XUA_AUDIOHUB_H_

View File

@@ -1,7 +1,7 @@
// Copyright 2011-2022 XMOS LIMITED.
// Copyright 2011-2023 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#ifndef __XUA_BUFFER_H__
#define __XUA_BUFFER_H__
#ifndef _XUA_BUFFER_H_
#define _XUA_BUFFER_H_
#if __XC__
@@ -26,6 +26,7 @@
* \param p_off_mclk A port that is clocked of the MCLK input (not the MCLK input itself)
* \param c_aud Channel connected to XUA_AudioHub() core
* \param i_pll_ref Interface to task that toggles reference pin to CS2100
* \param c_swpll_update Channel connected to software PLL task. Expects master clock counts based on USB frames.
*/
void XUA_Buffer(
chanend c_aud_out,
@@ -51,8 +52,13 @@ void XUA_Buffer(
, chanend c_hid
#endif
, chanend c_aud
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC) || defined(__DOXYGEN__)
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC) || defined(__DOYXGEN__)
#if (!XUA_USE_APP_PLL) || defined(__DOXYGEN__)
, client interface pll_ref_if i_pll_ref
#endif
#if (XUA_USE_APP_PLL) || defined(__DOXYGEN__)
, chanend c_swpll_update
#endif
#endif
);
@@ -81,10 +87,16 @@ void XUA_Buffer_Ep(chanend c_aud_out,
#ifdef CHAN_BUFF_CTRL
, chanend c_buff_ctrl
#endif
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC) || defined(__DOXYGEN__)
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC) || defined(__DOYXGEN__)
#if (!XUA_USE_APP_PLL) || defined(__DOXYGEN__)
, client interface pll_ref_if i_pll_ref
#endif
#if (XUA_USE_APP_PLL) || defined(__DOXYGEN__)
, chanend c_swpll_update
#endif
#endif
);
);
/** Manage the data transfer between the USB audio buffer and the
* Audio I/O driver.

View File

@@ -1,10 +1,11 @@
// Copyright 2011-2022 XMOS LIMITED.
// Copyright 2011-2023 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#ifndef _CLOCKING_H_
#define _CLOCKING_H_
#include <xs1.h>
#include "xua.h"
interface pll_ref_if
{
@@ -28,5 +29,46 @@ void PllRefPinTask(server interface pll_ref_if i_pll_ref, out port p_sync);
interrupts
*/
void clockGen(streaming chanend ?c_spdif_rx, chanend ?c_adat_rx, client interface pll_ref_if i_pll_ref, chanend c_audio, chanend c_clk_ctl, chanend c_clk_int);
#if (XUA_USE_APP_PLL)
struct SoftPllState
{
// Count we expect on MCLK port timer at SW PLL check point.
// Note, we expect wrapping so this is essentiually a modulus
unsigned expectedClkMod;
unsigned initialSetting;
unsigned initialErrorMult;
unsigned setting;
int phaseError;
/* Integrated phase error */
int phaseErrorInt;
/* IIR filter */
int iir_y;
/* Delta sigma modulator */
unsigned ds_in;
int ds_x1;
int ds_x2;
int ds_x3;
};
void AppPllEnable(tileref tile, int mclkFreq_hz);
void AppPllGetSettings(int clkFreq_hz, struct SoftPllState &pllState);
void AppPllUpdate(tileref tile, unsigned short mclk_pt, struct SoftPllState &pllState);
interface SoftPll_if
{
void init(int mclk_hz);
};
#if (XUA_SYNCMODE == XUA_SYNCMODE_ASYNC)
[[distributable]]
#endif
void XUA_SoftPll(tileref tile, server interface SoftPll_if i_softPll, chanend c_update);
#endif
#endif

View File

@@ -11,7 +11,9 @@
#include "xua_conf.h"
#endif
/* Default tile arrangement */
/*
* Tile arrangement defines
*/
/**
* @brief Location (tile) of audio I/O. Default: 0
@@ -55,12 +57,9 @@
#define PLL_REF_TILE AUDIO_IO_TILE
#endif
/**
* @brief Disable USB functionalty just leaving AudioHub
/*
* Channel based defines
*/
#ifndef XUA_USB_EN
#define XUA_USB_EN (1)
#endif
/**
* @brief Number of input channels (device to host). Default: NONE (Must be defined by app)
@@ -79,7 +78,18 @@
#endif
/**
* @brief Number of DSD output channels. Default: 0 (disabled)
* @brief Number of PDM microphones in the design.
*
* Default: 0
*/
#ifndef XUA_NUM_PDM_MICS
#define XUA_NUM_PDM_MICS (0)
#endif
/**
* @brief Number of DSD output channels.
*
* Default: 0 (disabled)
*/
#if defined(DSD_CHANS_DAC) && (DSD_CHANS_DAC != 0)
#if defined(NATIVE_DSD) && (NATIVE_DSD == 0)
@@ -91,6 +101,34 @@
#define DSD_CHANS_DAC 0
#endif
/**
* @brief Number of I2S channesl to DAC/CODEC. Must be a multiple of 2.
*
* Default: NONE (Must be defined by app)
*/
#ifndef I2S_CHANS_DAC
#error I2S_CHANS_DAC not defined
#define I2S_CHANS_DAC 2 /* Define anyway for doxygen */
#else
#define I2S_WIRES_DAC (I2S_CHANS_DAC / I2S_CHANS_PER_FRAME)
#endif
/**
* @brief Number of I2S channels from ADC/CODEC. Must be a multiple of 2.
*
* Default: NONE (Must be defined by app)
*/
#ifndef I2S_CHANS_ADC
#error I2S_CHANS_ADC not defined
#define I2S_CHANS_ADC 2 /* Define anyway for doxygen */
#else
#define I2S_WIRES_ADC (I2S_CHANS_ADC / I2S_CHANS_PER_FRAME)
#endif
/*
* Defines relating to the interface to external audio hardware i.e. DAC/ADC
*/
#define XUA_PCM_FORMAT_I2S (0)
#define XUA_PCM_FORMAT_TDM (1)
/**
@@ -120,30 +158,17 @@
#endif
#endif
/**
* @brief Number of IS2 channesl to DAC/CODEC. Must be a multiple of 2.
* @brief Number of bits per channel for I2S/TDM. Supported values: 16/32-bit.
*
* Default: NONE (Must be defined by app)
* Default: 32 bits
*/
#ifndef I2S_CHANS_DAC
#error I2S_CHANS_DAC not defined
#define I2S_CHANS_DAC 2 /* Define anyway for doxygen */
#else
#define I2S_WIRES_DAC (I2S_CHANS_DAC / I2S_CHANS_PER_FRAME)
#ifndef XUA_I2S_N_BITS
#define XUA_I2S_N_BITS (32)
#endif
/**
* @brief Number of I2S channels from ADC/CODEC. Must be a multiple of 2.
*
* Default: NONE (Must be defined by app)
*/
#ifndef I2S_CHANS_ADC
#error I2S_CHANS_ADC not defined
#define I2S_CHANS_ADC 2 /* Define anyway for doxygen */
#else
#define I2S_WIRES_ADC (I2S_CHANS_ADC / I2S_CHANS_PER_FRAME)
#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
/**
@@ -197,35 +222,32 @@
#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
/*
* Clocking related defines
*/
#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
* @brief Max supported sample frequency for device (Hz).
*
* Default: 192000Hz
*/
#ifndef MAX_FREQ
#define MAX_FREQ (192000)
#endif
/**
* @brief Min supported sample frequency for device (Hz). Default 44100
* @brief Min supported sample frequency for device (Hz).
*
* Default: 44100Hz
*/
#ifndef MIN_FREQ
#define MIN_FREQ (44100)
#endif
/**
* @brief Master clock defines for 44100 rates (in Hz). Default: NONE (Must be defined by app)
* @brief Master clock defines for 44100 rates (in Hz).
*
* Default: NONE (Must be defined by app)
*/
#ifndef MCLK_441
#error MCLK_441 not defined
@@ -233,7 +255,9 @@
#endif
/**
* @brief Master clock defines for 48000 rates (in Hz). Default: NONE (Must be defined by app)
* @brief Master clock defines for 48000 rates (in Hz).
*
* Default: NONE (Must be defined by app)
*/
#ifndef MCLK_48
#error MCLK_48 not defined
@@ -241,26 +265,66 @@
#endif
/**
* @brief Default device sample frequency. A safe default should be used. Default: MIN_FREQ
* @brief Enable/disable the use of the secondary/application PLL for generating master-clocks.
* Only available on xcore.ai devices.
*
* Default: Enabled (for xcore.ai devices)
*/
#ifndef XUA_USE_APP_PLL
#if defined(__XS3A__)
#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
/* Currently must use an external CS2100 device for syncing to external digital streams */
#define XUA_USE_APP_PLL (0)
#else
#define XUA_USE_APP_PLL (1)
#endif
#else
#define XUA_USE_APP_PLL (0)
#endif
#endif
/**
* @brief Default device sample frequency. A safe default should be used.
*
* Default: MIN_FREQ
*/
#ifndef DEFAULT_FREQ
#define DEFAULT_FREQ (MIN_FREQ)
#endif
/* Audio Class Defines */
#define DEFAULT_MCLK (((DEFAULT_FREQ % 7350) == 0) ? MCLK_441 : MCLK_48)
/**
* @brief USB Audio Class Version. Default: 2 (Audio Class version 2.0)
* @brief Defines whether XMOS device runs as master (i.e. drives LR and Bit clocks)
*
* 0: XMOS is I2S master. 1: CODEC is I2s master.
*
* Default: 0 (XMOS is master)
*/
#ifndef CODEC_MASTER
#define CODEC_MASTER (0)
#endif
/*
* Audio Class defines
*/
/**
* @brief USB Audio Class Version
*
* Default: 2 (Audio Class version 2.0)
*/
#ifndef AUDIO_CLASS
#define AUDIO_CLASS 2
#define AUDIO_CLASS (2)
#endif
/**
* @brief Whether or not to fall back to Audio Class 1.0 in USB Full-speed. Default: 0 (Disabled)
* @brief Enable/disable fall back to Audio Class 1.0 in USB Full-speed.
*
* Default: Disabled
*/
#ifndef AUDIO_CLASS_FALLBACK
#define AUDIO_CLASS_FALLBACK 0 /* Default to not falling back to UAC 1 */
#define AUDIO_CLASS_FALLBACK (0)
#endif
/**
@@ -289,14 +353,17 @@
#error AUDIO_CLASS set to 1 and FULL_SPEED_AUDIO_2 enabled!
#endif
/* Feature defines */
/*
* Feature defines
*/
/**
* @brief Number of PDM microphones in the design. Default: None
* @brief Disable USB functionalty just leaving AudioHub
*
* Default: Enabled
*/
#ifndef XUA_NUM_PDM_MICS
#define XUA_NUM_PDM_MICS (0)
#ifndef XUA_USB_EN
#define XUA_USB_EN (1)
#endif
/**
@@ -461,12 +528,11 @@
* You must also supply your own function to deal with the HID endpoint(s)
* in this case.
*/
#if( 0 < HID_CONTROLS )
#if (HID_CONTROLS) || defined (__DOXYGEN__)
#define XUA_HID_ENABLED (1)
#define XUA_OR_STATIC_HID_ENABLED (1)
#endif
#if defined(__static_hid_report_h_exists__)
#define XUA_OR_STATIC_HID_ENABLED (1)
#endif
@@ -482,17 +548,6 @@
#define HID_OUT_REQUIRED (0)
#endif
/**
* @brief Defines whether XMOS device runs as master (i.e. drives LR and Bit clocks)
*
* 0: XMOS is I2S master. 1: CODEC is I2s master.
*
* Default: 0 (XMOS is master)
*/
#ifndef CODEC_MASTER
#define CODEC_MASTER (0)
#endif
/**
* @brief Serial Number String used by the device
*

View File

@@ -8,9 +8,9 @@ An application using the USB audio framework needs to have defines set for confi
Defaults for these defines are found in ``xua_conf_default.h``.
These defines should be over-ridden in an optional header file ``xua_conf.h`` file or in the ``Makefile``
for a relevant build configuration.
for a relevant build configuration.
This section fully documents all of the settable defines and their default values (where appropriate).
This section fully documents all of the settable defines and their default values (where appropriate).
Code Location (tile)
--------------------
@@ -25,12 +25,12 @@ Code Location (tile)
Channel Counts
--------------
.. doxygendefine:: NUM_USB_CHAN_OUT
.. doxygendefine:: NUM_USB_CHAN_IN
.. doxygendefine:: I2S_CHANS_DAC
.. doxygendefine:: I2S_CHANS_ADC
.. doxygendefine:: NUM_USB_CHAN_OUT
.. doxygendefine:: NUM_USB_CHAN_IN
.. doxygendefine:: I2S_CHANS_DAC
.. doxygendefine:: I2S_CHANS_ADC
Frequencies and Clocks
Frequencies and Clocks
----------------------
.. doxygendefine:: MAX_FREQ
@@ -38,6 +38,7 @@ Frequencies and Clocks
.. doxygendefine:: DEFAULT_FREQ
.. doxygendefine:: MCLK_441
.. doxygendefine:: MCLK_48
.. doxygendefine:: XUA_USE_APP_PLL
Audio Class
-----------

View File

@@ -1,74 +1,49 @@
Required User Function Definitions
==================================
|newpage|
The following functions need to be defined by an application using the XMOS USB Audio framework.
User Function Definitions
=========================
The following functions can be defined by an application using `lib_xua`.
.. note:: Default, empty, implementations of these functions are provided in `lib_xua`. These are marked
as weak symbols so the application can simply define its own version of them.
External Audio Hardware Configuration Functions
-----------------------------------------------
.. c:function:: void AudioHwInit(chanend ?c_codec)
The following functions can be optionally used by the design to configure external audio hardware.
As a minimum, in most applications, it is expected that a implementation of `AudioHwConfig()` will need
to be provided.
This function is called when the audio core starts after the
device boots up and should initialize the external audio harware e.g. clocking, DAC, ADC etc
.. doxygenfunction:: AudioHwInit
.. doxygenfunction:: AudioHwConfig
.. doxygenfunction:: AudioHwConfig_Mute
.. doxygenfunction:: AudioHwConfig_UnMute
:param c_codec: An optional chanend that was original passed into
:c:func:`audio` that can be used to communicate
with other cores.
.. c:function:: void AudioHwConfig(unsigned samFreq, unsigned mclk, chanend ?c_codec, unsigned dsdMode, unsigned sampRes_DAC, unsigned sampRes_ADC)
This function is called when the audio core starts or changes
sample rate. It should configure the extenal audio hardware to run at the specified
sample rate given the supplied master clock frequency.
:param samFreq: The sample frequency in Hz that the hardware should be configured to (in Hz).
:param mclk: The master clock frequency that is required in Hz.
:param c_codec: An optional chanend that was original passed into
:c:func:`audio` that can be used to communicate
with other cores.
:param dsdMode: Signifies if the audio hardware should be configured for DSD operation
:param sampRes_DAC: The sample resolution of the DAC stream
:param sampRes_ADC: The sample resolution of the ADC stream
Audio Streaming Functions
-------------------------
Audio Stream Start/Stop Functions
---------------------------------
The following functions can be optionally used by the design. They can be useful for mute lines etc.
.. c:function:: void AudioStreamStart(void)
.. doxygenfunction:: UserAudioStreamStart
.. doxygenfunction:: UserAudioStreamStop
.. doxygenfunction:: UserAudioInputStreamStart
.. doxygenfunction:: UserAudioInputStreamStop
.. doxygenfunction:: UserAudioOutputStreamStart
.. doxygenfunction:: UserAudioOutputStreamStop
This function is called when the audio stream from device to host
starts.
.. c:function:: void AudioStreamStop(void)
This function is called when the audio stream from device to host stops.
Host Active
-----------
Host Active Functions
---------------------
The following function can be used to signal that the device is connected to a valid host.
This is called on a change in state.
.. c:function:: void AudioStreamStart(int active)
:param active: Indicates if the host is active or not. 1 for active else 0.
.. doxygenfunction:: UserHostActive
HID Controls
------------
The following function is called when the device wishes to read physical user input (buttons etc).
The function should write relevant HID bits into this array. The bit ordering and functionality is defined by the HID report descriptor used.
.. c:function:: void UserReadHIDButtons(unsigned char hidData[])
:param hidData: The function should write relevant HID bits into this array. The bit ordering and functionality is defined by the HID report descriptor used.
.. doxygenfunction:: UserHIDGetData

View File

@@ -1,27 +1,27 @@
|newpage|
Synchronisation
===============
Synchronisation & Clocking
==========================
The codebase supports "Synchronous" and "Asynchronous" modes for USB transfer as defined by the
The codebase supports "Synchronous" and "Asynchronous" modes for USB transfer as defined by the
USB specification(s).
Asynchronous mode (``XUA_SYNCMODE_ASYNC``) has the advantage that the device is clock-master. This means that
a high-quality local master-clock source can be utilised. It also has the benefit that the device may
synchronise it's master clock to an external digital input stream e.g. S/PDIF and thus avoiding sample-rate
Asynchronous mode (``XUA_SYNCMODE_ASYNC``) has the advantage that the device is clock-master. This means that
a high-quality local master-clock source can be utilised. It also has the benefit that the device may
synchronise it's master clock to an external digital input stream e.g. S/PDIF thus avoiding sample-rate
conversion.
The drawback of this mode is that it burdens the host with syncing to the device which some hosts
The drawback of this mode is that it burdens the host with syncing to the device which some hosts
may not support. This is especially pertinent to embedded hosts, however, most PC's and mobile devices
will indeed support this mode.
Synchronous mode (``XUA_SYNCMODE_SYNC``) is an option if the target host does not support asynchronous mode
or if it is desirable to synchronise many devices to a single host. It should be noted, however, that input
or if it is desirable to synchronise many devices to a single host. It should be noted, however, that input
from digital streams, such as S/PDIF, are not currently supported in this mode.
.. note::
The selection of synchronisation mode is done at build time and cannot be changed dynamically.
Setting the synchronisation mode of the device is done using the define in :ref:`opt_sync_defines`
@@ -39,10 +39,17 @@ Setting the synchronisation mode of the device is done using the define in :ref:
- USB synchronisation mode
- ``XUA_SYNCMODE_ASYNC``
When operating in synchronous mode an external Cirrus Logic CS2100 device is required for master clock
generation. The codebase expects to drive a synchronisation signal to this external device
When operating in asynchronous mode xcore.ai based devices will be configured, by default, to use their internal
"Applications" PLL to generated an appropriate master-clock signal. To disable this ``XUA_USE_APP_PLL`` should be
set to ``0``. For all other devices the developer is expected to supply external master-clock generation circuitry.
The programmer should ensure the define in :ref:`opt_sync_ref_defines` is set appropriately.
When operating in synchronous mode an xcore.ai based device, by default, will be configured to used it's internal
"application" PLL to generate a master-clock synchronised to the USB host.
xcore-200 based devices do not have this application PLL and so an external Cirrus Logic CS2100 device is required
for master clock generation. The codebase expects to drive a synchronisation signal to this external device.
In this case the developer should ensure the define in :ref:`opt_sync_ref_defines` is set appropriately.
.. _opt_sync_ref_defines:
@@ -57,10 +64,33 @@ The programmer should ensure the define in :ref:`opt_sync_ref_defines` is set ap
- Tile location of reference to CS2100 device
- ``AUDIO_IO_TILE``
The codebase expects this reference signal port to be defined in the application XN file as ``PORT_PLL_REF``.
The codebase expects this reference signal port to be defined in the application XN file as ``PORT_PLL_REF``.
This may be a port of any bit-width, however, connection to bit[0] is assumed::
<Port Location="XS1_PORT_1A" Name="PORT_PLL_REF"/>
Configuration of the external CS2100 device (typically via I2C) is beyond the scope of this document.
Note, in all cases the master-clocks are generated (when using the xcore.ai Application PLL) or should be generated
(if using external circuitry) to match the defines in :ref:`opt_sync_mclk_defines`.
.. _opt_sync_mclk_defines:
.. list-table:: Master clock frequencies
:header-rows: 1
:widths: 20 80 20
* - Define
- Description
- Default
* - ``MCLK_48``
- Master clock frequency (in Hz)used for sample-rates related to 48KHz
- NOTE
* - ``MCLK_441``
- Master clock frequency (in Hz) used for sample-rates related to 44.1KHz
- NONE
.. note::
The master clock defines above are critical for proper operation and default values are not provided.
If they are not defined by the devloper a build error will be emmited.

View File

@@ -1,5 +1,5 @@
XMOSNEWSTYLE = 2
DOXYGEN_DIRS=../../api
DOXYGEN_DIRS=../../api ../../src/core/user/audiostream ../../src/core/user/hostactive ../../src/core/user/hid ../../src/core/user/audiohw
SOURCE_INCLUDE_DIRS=../../../lib_xua
SPHINX_MASTER_DOC=lib_xua

View File

@@ -1,4 +1,4 @@
VERSION = 3.5.0
VERSION = 3.5.1
DEBUG ?= 0
@@ -55,6 +55,7 @@ INCLUDE_DIRS = $(EXPORT_INCLUDE_DIRS) \
src/core/user/audiostream \
src/core/user/hid \
src/core/user/hostactive \
src/core/user/audiohw \
src/hid \
src/midi
@@ -70,6 +71,7 @@ SOURCE_DIRS = src/core \
src/core/support \
src/core/user/audiostream \
src/core/user/hostactive \
src/core/user/audiohw \
src/core/xuduser \
src/dfu \
src/hid \

View File

@@ -17,9 +17,10 @@
#include <string.h>
#include <xassert.h>
#include "xua.h"
#include "audiohw.h"
#include "audioports.h"
#include "mic_array_conf.h"
#if (XUA_SPDIF_TX_EN)
@@ -86,7 +87,7 @@ static inline int HandleSampleClock(int frameCount, buffered _XUA_CLK_DIR port:3
unsigned syncError = 0;
unsigned lrval = 0;
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");
@@ -306,7 +307,7 @@ 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]));
sample = bitrev(sample);
if(XUA_I2S_N_BITS != 32)
{
@@ -635,6 +636,9 @@ void XUA_AudioHub(chanend ?c_aud, clock ?clk_audio_mclk, clock ?clk_audio_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_USE_APP_PLL)
, client interface SoftPll_if i_softPll
#endif
#if (XUA_SPDIF_TX_EN) //&& (SPDIF_TX_TILE != AUDIO_IO_TILE)
, chanend c_spdif_out
#endif
@@ -662,6 +666,12 @@ void XUA_AudioHub(chanend ?c_aud, clock ?clk_audio_mclk, clock ?clk_audio_bclk,
unsigned divide;
unsigned firstRun = 1;
#if (XUA_USE_APP_PLL)
/* Use xCORE.ai Secondary PLL to generate master clock
* This could be "fixed" for async mode or adjusted if in sync mode */
i_softPll.init(DEFAULT_MCLK);
#endif
/* Clock master clock-block from master-clock port */
/* Note, marked unsafe since other cores may be using this mclk port */
configure_clock_src(clk_audio_mclk, p_mclk_in);
@@ -687,6 +697,8 @@ void XUA_AudioHub(chanend ?c_aud, clock ?clk_audio_mclk, clock ?clk_audio_bclk,
#endif
#endif
/* Perform required CODEC/ADC/DAC initialisation */
AudioHwInit();
@@ -715,13 +727,7 @@ 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 */
{
unsigned numBits = XUA_I2S_N_BITS * 2;
if(XUA_PCM_FORMAT == XUA_PCM_FORMAT_TDM)
{
/* TDM has 8 channels */
numBits *= 4;
}
unsigned numBits = XUA_I2S_N_BITS * I2S_CHANS_PER_FRAME;
#if (DSD_CHANS_DAC > 0)
if(dsdMode == DSD_MODE_DOP)
@@ -804,8 +810,19 @@ void XUA_AudioHub(chanend ?c_aud, clock ?clk_audio_mclk, clock ?clk_audio_bclk,
curFreq *= 16;
}
#endif
/* Configure Clocking/CODEC/DAC/ADC for SampleFreq/MClk */
/* User should mute audio hardware */
AudioHwConfig_Mute();
#if (XUA_USE_APP_PLL)
i_softPll.init(mClk);
#endif
/* User code should configure audio harware for SampleFreq/MClk etc */
AudioHwConfig(curFreq, mClk, dsdMode, curSamRes_DAC, curSamRes_ADC);
/* User should unmute audio hardware */
AudioHwConfig_UnMute();
}
if(!firstRun)

View File

@@ -394,7 +394,7 @@ __builtin_unreachable();
unsigned l;
unsafe
{
mult = multInPtr[i];
mult = multInPtr[i];
}
{h, l} = macs(mult, sample, 0, 0);
sample = h << 3;
@@ -427,7 +427,7 @@ __builtin_unreachable();
unsigned l;
unsafe
{
mult = multInPtr[i];
mult = multInPtr[i];
}
{h, l} = macs(mult, sample, 0, 0);
sample = h << 3;
@@ -461,7 +461,7 @@ __builtin_unreachable();
unsigned l;
unsafe
{
mult = multInPtr[i];
mult = multInPtr[i];
}
{h, l} = macs(mult, sample, 0, 0);
sample = h << 3;

View File

@@ -105,7 +105,11 @@ void XUA_Buffer(
#endif
, chanend c_aud
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC)
#if(XUA_USE_APP_PLL)
, chanend c_swpll_update
#else
, client interface pll_ref_if i_pll_ref
#endif
#endif
)
{
@@ -141,7 +145,11 @@ void XUA_Buffer(
, c_buff_ctrl
#endif
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC)
, i_pll_ref
#if(XUA_USE_APP_PLL)
, c_swpll_update
#else
, i_pll_ref
#endif
#endif
);
@@ -190,8 +198,12 @@ void XUA_Buffer_Ep(register chanend c_aud_out,
#ifdef CHAN_BUFF_CTRL
, chanend c_buff_ctrl
#endif
#if XUA_SYNCMODE == XUA_SYNCMODE_SYNC
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC)
#if (XUA_USE_APP_PLL)
, chanend c_swpll_update
#else
, client interface pll_ref_if i_pll_ref
#endif
#endif
)
{
@@ -247,7 +259,8 @@ void XUA_Buffer_Ep(register chanend c_aud_out,
#if (NUM_USB_CHAN_IN > 0)
unsigned bufferIn = 1;
#endif
unsigned sofCount = 0;
int sofCount = 0;
int pllUpdate = 0;
unsigned mod_from_last_time = 0;
#ifdef FB_TOLERANCE_TEST
@@ -294,7 +307,6 @@ void XUA_Buffer_Ep(register chanend c_aud_out,
unsigned iap_ea_native_interface_alt_setting = 0;
unsigned iap_ea_native_control_to_send = 0;
unsigned iap_ea_native_incoming = 0;
#endif
#endif
@@ -357,12 +369,16 @@ void XUA_Buffer_Ep(register chanend c_aud_out,
#ifndef LOCAL_CLOCK_MARGIN
#define LOCAL_CLOCK_MARGIN (1000)
#endif
#if (!XUA_USE_APP_PLL)
timer t_sofCheck;
unsigned timeLastEdge;
unsigned timeNextEdge;
t_sofCheck :> timeLastEdge;
timeNextEdge + LOCAL_CLOCK_INCREMENT;
i_pll_ref.toggle();
#endif
#endif
while(1)
@@ -427,7 +443,8 @@ void XUA_Buffer_Ep(register chanend c_aud_out,
/* Reset FB */
/* Note, Endpoint 0 will hold off host for a sufficient period to allow our feedback
* to stabilise (i.e. sofCount == 128 to fire) */
sofCount = 1;
sofCount = 0;
pllUpdate = 0;
clocks = 0;
clockcounter = 0;
mod_from_last_time = 0;
@@ -502,13 +519,13 @@ void XUA_Buffer_Ep(register chanend c_aud_out,
}
#endif
/* Pass on sample freq change to decouple() via global flag (saves a chanend) */
/* Note: freqChange flags now used to communicate other commands also */
/* Note: freqChange_flag now used to communicate other commands also */
SET_SHARED_GLOBAL0(g_freqChange, cmd); /* Set command */
SET_SHARED_GLOBAL(g_freqChange_flag, cmd); /* Set Flag */
}
break;
}
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC)
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC) && (!XUA_USE_APP_PLL)
case t_sofCheck when timerafter(timeNextEdge) :> void:
i_pll_ref.toggle();
timeLastEdge = timeNextEdge;
@@ -528,7 +545,6 @@ void XUA_Buffer_Ep(register chanend c_aud_out,
unsigned usbSpeed;
int framesPerSec;
GET_SHARED_GLOBAL(usbSpeed, g_curUsbSpeed);
static int sofCount = 0;
framesPerSec = (usbSpeed == XUD_SPEED_HS) ? 8000 : 1000;
@@ -539,12 +555,27 @@ void XUA_Buffer_Ep(register chanend c_aud_out,
sofCount += 1000;
if (sofCount == framesPerSec)
{
sofCount = 0;
pllUpdate++;
#if (!XUA_USE_APP_PLL)
/* Port is accessed via interface to allow flexibilty with location */
i_pll_ref.toggle();
t_sofCheck :> timeLastEdge;
sofCount = 0;
timeNextEdge = timeLastEdge + LOCAL_CLOCK_INCREMENT + LOCAL_CLOCK_MARGIN;
#endif
}
#if (XUA_USE_APP_PLL)
// Update PLL @ 100Hz
if(pllUpdate == 10)
{
pllUpdate = 0;
unsigned short mclk_pt;
asm volatile("getts %0, res[%1]" : "=r" (mclk_pt) : "r" (p_off_mclk));
outuint(c_swpll_update, mclk_pt);
outct(c_swpll_update, XS1_CT_END);
}
#endif
#elif (XUA_SYNCMODE == XUA_SYNCMODE_ASYNC)
/* NOTE our feedback will be wrong for a couple of SOF's after a SF change due to
@@ -646,7 +677,6 @@ void XUA_Buffer_Ep(register chanend c_aud_out,
clockcounter = 0;
}
#else
/* Assuming 48kHz from a 24.576 master clock (0.0407uS period)
* MCLK ticks per SOF = 125uS / 0.0407 = 3072 MCLK ticks per SOF.
* expected Feedback is 48000/8000 = 6 samples. so 0x60000 in 16:16 format.
@@ -897,8 +927,8 @@ void XUA_Buffer_Ep(register chanend c_aud_out,
#endif
#endif
#if XUA_HID_ENABLED
/* HID Report Data */
#if (XUA_HID_ENABLED)
/* HID Report Data */
case XUD_SetData_Select(c_hid, ep_hid, result):
hid_ready_flag = 0U;
unsigned reportTime;
@@ -911,7 +941,7 @@ void XUA_Buffer_Ep(register chanend c_aud_out,
#endif
#ifdef MIDI
/* Received word from MIDI thread - Check for ACK or Data */
/* Received word from MIDI thread - Check for ACK or Data */
case midi_get_ack_or_data(c_midi, is_ack, datum):
if (is_ack)
{

View File

@@ -0,0 +1,457 @@
// Copyright 2023 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#include <print.h>
#include <platform.h>
#include "xua.h"
#include "xassert.h"
#include <stdio.h>
#if (XUA_USE_APP_PLL)
/*
* Functions for interacting with the secondary/application PLL
*/
#ifndef __XS3A__
#error App PLL not included in device
#endif
/*
* App PLL settings used for syncing to external clocks
*/
// Define the PLL settings to generate the required frequencies.
// All settings allow greater than +-1000ppm lock range.
// Comment out the following line for 2us update.
//#define FAST_FRAC_REG_WRITE
// OPTION 1 - 1us register update rate - Lowest jitter
// 10ps jitter 100Hz-40kHz. Low freq noise floor -100dBc
#ifdef FAST_FRAC_REG_WRITE
#define FRAC_REG_WRITE_DLY (100)
// Found solution: IN 24.000MHz, OUT 22.578947MHz, VCO 3251.37MHz, RD 1, FD 135.474 (m = 9, n = 19), OD 6, FOD 6, ERR -11.189ppm
#define APP_PLL_CTL_SYNC_22M (0x0A808600)
#define APP_PLL_DIV_SYNC_22M (0x80000005)
#define APP_PLL_FRAC_SYNC_22M (0x80000812)
#define APP_PLL_ERR_MULT_22M (627) // round(135(divider)*100Hz*1048576/22579200)
#define APP_PLL_MOD_INIT_22M (498283)
// Fout = Fin*divider/(2*2*6*6) = (fin/144) * divider = (24/144) * divider. = 1/6 * divider.
// To achieve frequency f, Fraction Setting = (6*f) - 135
// So to achieve 22.5792MHz, Fraction Setting = (6*22.5792) - 135 = 0.4752
// Numerical input = round((Fraction setting * 2^20) = 0.4752 * 1048576 = 498283
//Found solution: IN 24.000MHz, OUT 24.575758MHz, VCO 3538.91MHz, RD 1, FD 147.455 (m = 5, n = 11), OD 6, FOD 6, ERR -9.864ppm
#define APP_PLL_CTL_SYNC_24M (0x0A809200)
#define APP_PLL_DIV_SYNC_24M (0x80000005)
#define APP_PLL_FRAC_SYNC_24M (0x8000040A)
#define APP_PLL_ERR_MULT_24M (627) // round(147(divider)*100Hz*1048576/24576000)
#define APP_PLL_MOD_INIT_24M (478151)
// Fout = Fin*divider/(2*2*6*6) = (fin/144) * divider = (24/144) * divider. = 1/6 * divider.
// To achieve frequency f, Fraction Setting = (6*f) - 147
// So to achieve 24.576MHz, Fraction Setting = (6*24.576) - 147 = 0.456
// Numerical input = round((Fraction setting * 2^20) = 0.456 * 1048576 = 478151
#else
// OPTION 2 - 2us register update rate - Higher jitter
// 50ps jitter 100Hz-40kHz. Low freq noise floor -93dBc
#define FRAC_REG_WRITE_DLY (200)
//Found solution: IN 24.000MHz, OUT 22.579186MHz, VCO 3522.35MHz, RD 2, FD 293.529 (m = 9, n = 17), OD 3, FOD 13, ERR -0.641ppm
#define APP_PLL_CTL_SYNC_22M (0x09012401)
#define APP_PLL_DIV_SYNC_22M (0x8000000C)
#define APP_PLL_FRAC_SYNC_22M (0x80000810)
#define APP_PLL_ERR_MULT_22M (1361) // round(293(divider)*100Hz*1048576/22579200)
#define APP_PLL_MOD_INIT_22M (555326)
// Fout = (Fin/2)*divider/(2*2*3*13) = (fin/312) * divider = (24/312) * divider. = 1/13 * divider.
// To achieve frequency f, Fraction Setting = (13*f) - 293
// So to achieve 22.5792MHz, Fraction Setting = (13*22.5792) - 293 = 0.5296
// Numerical input = round((Fraction setting * 2^20) = 0.5296 * 1048576 = 555326
//Found solution: IN 24.000MHz, OUT 24.576125MHz, VCO 3342.35MHz, RD 2, FD 278.529 (m = 9, n = 17), OD 2, FOD 17, ERR 5.069ppm - Runs VCO out fractionally out of spec at 835MHz
#define APP_PLL_CTL_SYNC_24M (0x08811501)
#define APP_PLL_DIV_SYNC_24M (0x80000010)
#define APP_PLL_FRAC_SYNC_24M (0x80000810)
#define APP_PLL_ERR_MULT_24M (1186) // round(278(divider)*100Hz*1048576/24576000)
#define APP_PLL_MOD_INIT_24M (553648)
// Fout = (Fin/2)*divider/(2*2*2*17) = (fin/272) * divider = (24/272) * divider. = 3/34 * divider.
// To achieve frequency f, Fraction Setting = ((34/3)*f) - 278
// So to achieve 24.576MHz, Fraction Setting = ((34/3)*24.576) - 278 = 0.528
// Numerical input = round((Fraction setting * 2^20) = 0.528 * 1048576 = 553648
#endif
/*
* App PLL settings used for low jitter fixed local clocks
*/
//Found solution: IN 24.000MHz, OUT 49.151786MHz, VCO 3145.71MHz, RD 1, FD 131.071 (m = 1, n = 14), OD 8, FOD 2, ERR -4.36ppm
// Measure: 100Hz-40kHz: ~7ps
// 100Hz-1MHz: 70ps.
// 100Hz high pass: 118ps.
#define APP_PLL_CTL_FIXED_49M (0x0B808200)
#define APP_PLL_DIV_FIXED_49M (0x80000001)
#define APP_PLL_FRAC_FIXED_49M (0x8000000D)
//Found solution: IN 24.000MHz, OUT 45.157895MHz, VCO 2709.47MHz, RD 1, FD 112.895 (m = 17, n = 19), OD 5, FOD 3, ERR -11.19ppm
// Measure: 100Hz-40kHz: 6.5ps
// 100Hz-1MHz: 67ps.
// 100Hz high pass: 215ps.
#define APP_PLL_CTL_FIXED_45M (0x0A006F00)
#define APP_PLL_DIV_FIXED_45M (0x80000002)
#define APP_PLL_FRAC_FIXED_45M (0x80001012)
// Found solution: IN 24.000MHz, OUT 24.576000MHz, VCO 2457.60MHz, RD 1, FD 102.400 (m = 2, n = 5), OD 5, FOD 5, ERR 0.0ppm
// Measure: 100Hz-40kHz: ~8ps
// 100Hz-1MHz: 63ps.
// 100Hz high pass: 127ps.
#define APP_PLL_CTL_FIXED_24M (0x0A006500)
#define APP_PLL_DIV_FIXED_24M (0x80000004)
#define APP_PLL_FRAC_FIXED_24M (0x80000104)
// Found solution: IN 24.000MHz, OUT 22.579186MHz, VCO 3522.35MHz, RD 1, FD 146.765 (m = 13, n = 17), OD 3, FOD 13, ERR -0.641ppm
// Measure: 100Hz-40kHz: 7ps
// 100Hz-1MHz: 67ps.
// 100Hz high pass: 260ps.
#define APP_PLL_CTL_FIXED_22M (0x09009100)
#define APP_PLL_DIV_FIXED_22M (0x8000000C)
#define APP_PLL_FRAC_FIXED_22M (0x80000C10)
#define APP_PLL_CTL_FIXED_12M (0x0A006500)
#define APP_PLL_DIV_FIXED_12M (0x80000009)
#define APP_PLL_FRAC_FIXED_12M (0x80000104)
#define APP_PLL_CTL_FIXED_11M (0x09009100)
#define APP_PLL_DIV_FIXED_11M (0x80000009)
#define APP_PLL_FRAC_FIXED_11M (0x80000C10)
#define APP_PLL_CTL_ENABLE (1 << 27)
#define APP_PLL_CLK_OUTPUT_ENABLE (1 << 16)
static void set_app_pll_init(tileref tile, int app_pll_ctrl)
{
// Disable the PLL
write_node_config_reg(tile, XS1_SSWITCH_SS_APP_PLL_CTL_NUM, (app_pll_ctrl & ~APP_PLL_CTL_ENABLE));
// Enable the PLL to invoke a reset on the appPLL.
write_node_config_reg(tile, XS1_SSWITCH_SS_APP_PLL_CTL_NUM, app_pll_ctrl);
// Must write the CTL register twice so that the F and R divider values are captured using a running clock.
write_node_config_reg(tile, XS1_SSWITCH_SS_APP_PLL_CTL_NUM, app_pll_ctrl);
// Now disable and re-enable the PLL so we get the full 5us reset time with the correct F and R values.
write_node_config_reg(tile, XS1_SSWITCH_SS_APP_PLL_CTL_NUM, (app_pll_ctrl & 0xF7FFFFFF));
write_node_config_reg(tile, XS1_SSWITCH_SS_APP_PLL_CTL_NUM, app_pll_ctrl);
// Wait for PLL to lock.
delay_microseconds(500);
}
void AppPllEnable(tileref tile, int clkFreq_hz)
{
unsigned app_pll_ctrl, app_pll_div, app_pll_frac;
/* Decide on App PLL settings */
if(XUA_SYNCMODE == XUA_SYNCMODE_SYNC)
{
switch(clkFreq_hz)
{
case 44100 * 512:
app_pll_ctrl = APP_PLL_CTL_SYNC_22M;
app_pll_div = APP_PLL_DIV_SYNC_22M;
app_pll_frac = APP_PLL_FRAC_SYNC_22M;
break;
case 48000 * 512:
app_pll_ctrl = APP_PLL_CTL_SYNC_24M;
app_pll_div = APP_PLL_DIV_SYNC_24M;
app_pll_frac = APP_PLL_FRAC_SYNC_24M;
break;
default:
assert(0);
break;
}
}
else
{
switch(clkFreq_hz)
{
case 44100 * 256:
app_pll_ctrl = APP_PLL_CTL_FIXED_11M;
app_pll_div = APP_PLL_DIV_FIXED_11M;
app_pll_frac = APP_PLL_FRAC_FIXED_11M;
break;
case 48000 * 256:
app_pll_ctrl = APP_PLL_CTL_FIXED_12M;
app_pll_div = APP_PLL_DIV_FIXED_12M;
app_pll_frac = APP_PLL_FRAC_FIXED_12M;
break;
case 44100 * 512:
app_pll_ctrl = APP_PLL_CTL_FIXED_22M;
app_pll_div = APP_PLL_DIV_FIXED_22M;
app_pll_frac = APP_PLL_FRAC_FIXED_22M;
break;
case 48000 * 512:
app_pll_ctrl = APP_PLL_CTL_FIXED_24M;
app_pll_div = APP_PLL_DIV_FIXED_24M;
app_pll_frac = APP_PLL_FRAC_FIXED_24M;
break;
case 44100 * 1024:
app_pll_ctrl = APP_PLL_CTL_FIXED_45M;
app_pll_div = APP_PLL_DIV_FIXED_45M;
app_pll_frac = APP_PLL_FRAC_FIXED_45M;
break;
case 48000 * 1024:
app_pll_ctrl = APP_PLL_CTL_FIXED_49M;
app_pll_div = APP_PLL_DIV_FIXED_49M;
app_pll_frac = APP_PLL_FRAC_FIXED_49M;
break;
default:
assert(0);
break;
}
}
// Initialise the AppPLL and get it running.
set_app_pll_init(tile, app_pll_ctrl);
// Write the fractional-n register, note, the top bit is set to enable the frac-n block.
write_node_config_reg(tile, XS1_SSWITCH_SS_APP_PLL_FRAC_N_DIVIDER_NUM, app_pll_frac);
// And then write the clock divider register to enable the output
write_node_config_reg(tile, XS1_SSWITCH_SS_APP_CLK_DIVIDER_NUM, app_pll_div);
// Wait for PLL output frequency to stabilise due to fractional divider enable
delay_microseconds(100);
}
void SoftPllInit(int clkFreq_hz, struct SoftPllState &pllState)
{
switch(clkFreq_hz)
{
case 44100 * 512:
pllState.expectedClkMod = 29184; // Count we expect on MCLK port timer at SW PLL check point. For 100Hz, 10ms.
pllState.initialSetting = APP_PLL_MOD_INIT_22M;
pllState.initialErrorMult = APP_PLL_ERR_MULT_22M;
break;
case 48000 * 512:
pllState.expectedClkMod = 49152;
pllState.initialSetting = APP_PLL_MOD_INIT_24M;
pllState.initialErrorMult = APP_PLL_ERR_MULT_24M;
break;
default:
assert(0);
break;
}
pllState.ds_in = pllState.initialSetting;
pllState.ds_x1 = 0;
pllState.ds_x2 = 0;
pllState.ds_x3 = 0;
pllState.iir_y = 0;
pllState.phaseError = 0;
pllState.phaseErrorInt = 0;
}
int SoftPllUpdate(tileref tile, unsigned short mclk_pt, unsigned short mclk_pt_last, struct SoftPllState &pllState, int fastLock)
{
int freq_error, error_p, error_i;
unsigned expectedClksMod = pllState.expectedClkMod;
unsigned initialSetting = pllState.initialSetting;
unsigned init_err_mult = pllState.initialErrorMult;
int newSetting;
unsigned short expectedPt;
int set = -1;
int diff;
// expectedClkMod is the value of the port counter that we expect given the desired MCLK in the 10ms time period we are running at.
expectedPt = mclk_pt_last + expectedClksMod;
// Handle wrapping
if (porttimeafter(mclk_pt, expectedPt))
{
diff = -(short)(expectedPt - mclk_pt);
}
else
{
diff = (short)(mclk_pt - expectedPt);
}
// TODO Add a bounds checker on diff to make sure it's roughly where we expect.
// If it isn't we should ignore it as it's either a glitch or from clock start/stop.
if(fastLock) // Fast lock - set DCO based on measured frequency error in first cycle
{
initialSetting = initialSetting - (diff * init_err_mult); // init_err_mult is the dco input change to cause an output frequency offset equating to a measured input freq error of 1.
diff = 0; // reset diff to zero so following code does not see any error in this cycle.
}
// Absolute frequency error for last measurement cycle. If diff is positive, port timer was beyond where it should have been, so MCLK was too fast. So this needs to describe a negative error.
freq_error = -diff;
// Phase error is the integral of frequency error.
pllState.phaseError += freq_error;
// Integral of phase error for use in PI loop below.
pllState.phaseErrorInt += pllState.phaseError;
error_p = (pllState.phaseError << 5); // << 5 => Kp = 32
error_i = (pllState.phaseErrorInt >> 2); // >> 2 => Ki = 0.25
// input to filter (x) is output of PI controller
int x = (error_p + error_i);
// Filter some noise into DCO to reduce jitter
// First order IIR, make A=0.125
// y = y + A(x-y)
pllState.iir_y += ((x-pllState.iir_y)>>3);
newSetting = pllState.iir_y;
// Only output new frequency tune value if different to the previous setting
if (newSetting != pllState.setting)
{
set = (initialSetting + newSetting); // init_set is our calculation of the setting required after measuring one cycle, should be accurate to +- 1MCLK.
if (set < 0)
set = 0;
else if (set > 0xFFFFF)
set = 0xFFFFF;
}
pllState.setting = newSetting;
// Return the setting to the NCO thread. -1 means no update
return set;
}
#if (XUA_SYNCMODE == XUA_SYNCMODE_ASYNC)
[[distributable]]
#endif
void XUA_SoftPll(tileref tile, server interface SoftPll_if i_softPll, chanend c_update)
{
#if (XUA_SYNCMODE != XUA_SYNCMODE_ASYNC)
unsigned frac_val;
int ds_out;
timer tmr;
int time;
unsigned mclk_pt;
unsigned short mclk_pt_last;
tmr :> time;
#endif
struct SoftPllState pllState;
int running = 0;
int firstUpdate = 1;
int fastLock = 1;
while(1)
{
select
{
/* Interface used for basic frequency setting such that it can be distributed
* when the update code is not required */
case i_softPll.init(int mclk_hz):
AppPllEnable(tile, mclk_hz);
SoftPllInit(mclk_hz, pllState);
running = 1;
firstUpdate = 1;
fastLock = 1;
break;
#if (XUA_SYNCMODE == XUA_SYNCMODE_ASYNC)
}
}
}
#else
/* Channel used for update such that other side is not blocked */
/* TODO add CT handshake before opening route */
case inuint_byref(c_update, mclk_pt):
inct(c_update);
if(firstUpdate)
{
firstUpdate = 0;
}
else
{
int setting = SoftPllUpdate(tile, (unsigned short) mclk_pt, mclk_pt_last, pllState, fastLock);
fastLock = 0;
if(setting != -1)
{
pllState.ds_in = setting;
// Limit input range for modulator stability.
if(pllState.ds_in > 980000)
pllState.ds_in = 980000;
if(pllState.ds_in < 60000)
pllState.ds_in = 60000;
}
}
mclk_pt_last = (unsigned short) mclk_pt;
break;
default :
break;
}
// Third order, 9 level output delta sigma. 20 bit unsigned input.
ds_out = ((pllState.ds_x3<<4) + (pllState.ds_x3<<1)) >> 13;
if (ds_out > 8)
ds_out = 8;
if (ds_out < 0)
ds_out = 0;
pllState.ds_x3 += (pllState.ds_x2>>5) - (ds_out<<9) - (ds_out<<8);
pllState.ds_x2 += (pllState.ds_x1>>5) - (ds_out<<14);
pllState.ds_x1 += pllState.ds_in - (ds_out<<17);
if (ds_out == 0)
frac_val = 0x00000007; // 0/8
else
frac_val = ((ds_out - 1) << 8) | 0x80000007; // 1/8 to 8/8
// Now write the register.
// We need to write the register at a specific period at a fast rate.
// This period needs to be (div ref clk period (ns) * how many times we repeat same value)
// In this case, div ref clk = 24/3 = 8MHz. So div ref clk period = 125ns.
// We're using fraction denominators of 8, so these repeat every 8*125ns = 1us.
// So minimum period we could use is 1us and multiples thereof.
// The slower we write, the higher our jitter will be.
time += FRAC_REG_WRITE_DLY; // Time the reg write.
tmr when timerafter(time) :> void;
// Write the register. Because we are timing the reg writes accurately we do not need to use reg write with ack.
// This saves a lot of time. Additionally, apparently we can shorten the time for this reg write by only setting up the channel once and just doing a few instructions to do the write each time.
// We can hard code this in assembler.
if(running)
{
write_node_config_reg_no_ack(tile, XS1_SSWITCH_SS_APP_PLL_FRAC_N_DIVIDER_NUM, frac_val);
}
}
}
#endif
#endif

View File

@@ -0,0 +1,398 @@
// Copyright 2023 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
// Header file listing fraction options searched
// These values to go in the bottom 16 bits of the secondary PLL fractional-n divider register.
short frac_values_80[391] = {
0x3C4B, // Index: 0 Fraction: 61/76 = 0.8026
0x3846, // Index: 1 Fraction: 57/71 = 0.8028
0x3441, // Index: 2 Fraction: 53/66 = 0.8030
0x303C, // Index: 3 Fraction: 49/61 = 0.8033
0x2C37, // Index: 4 Fraction: 45/56 = 0.8036
0x2832, // Index: 5 Fraction: 41/51 = 0.8039
0x242D, // Index: 6 Fraction: 37/46 = 0.8043
0x2028, // Index: 7 Fraction: 33/41 = 0.8049
0x3D4C, // Index: 8 Fraction: 62/77 = 0.8052
0x1C23, // Index: 9 Fraction: 29/36 = 0.8056
0x3542, // Index: 10 Fraction: 54/67 = 0.8060
0x181E, // Index: 11 Fraction: 25/31 = 0.8065
0x2D38, // Index: 12 Fraction: 46/57 = 0.8070
0x1419, // Index: 13 Fraction: 21/26 = 0.8077
0x3A48, // Index: 14 Fraction: 59/73 = 0.8082
0x252E, // Index: 15 Fraction: 38/47 = 0.8085
0x3643, // Index: 16 Fraction: 55/68 = 0.8088
0x1014, // Index: 17 Fraction: 17/21 = 0.8095
0x3F4E, // Index: 18 Fraction: 64/79 = 0.8101
0x2E39, // Index: 19 Fraction: 47/58 = 0.8103
0x1D24, // Index: 20 Fraction: 30/37 = 0.8108
0x2A34, // Index: 21 Fraction: 43/53 = 0.8113
0x3744, // Index: 22 Fraction: 56/69 = 0.8116
0x0C0F, // Index: 23 Fraction: 13/16 = 0.8125
0x3C4A, // Index: 24 Fraction: 61/75 = 0.8133
0x2F3A, // Index: 25 Fraction: 48/59 = 0.8136
0x222A, // Index: 26 Fraction: 35/43 = 0.8140
0x3845, // Index: 27 Fraction: 57/70 = 0.8143
0x151A, // Index: 28 Fraction: 22/27 = 0.8148
0x3440, // Index: 29 Fraction: 53/65 = 0.8154
0x1E25, // Index: 30 Fraction: 31/38 = 0.8158
0x2730, // Index: 31 Fraction: 40/49 = 0.8163
0x303B, // Index: 32 Fraction: 49/60 = 0.8167
0x3946, // Index: 33 Fraction: 58/71 = 0.8169
0x080A, // Index: 34 Fraction: 9/11 = 0.8182
0x3A47, // Index: 35 Fraction: 59/72 = 0.8194
0x313C, // Index: 36 Fraction: 50/61 = 0.8197
0x2831, // Index: 37 Fraction: 41/50 = 0.8200
0x1F26, // Index: 38 Fraction: 32/39 = 0.8205
0x3642, // Index: 39 Fraction: 55/67 = 0.8209
0x161B, // Index: 40 Fraction: 23/28 = 0.8214
0x3B48, // Index: 41 Fraction: 60/73 = 0.8219
0x242C, // Index: 42 Fraction: 37/45 = 0.8222
0x323D, // Index: 43 Fraction: 51/62 = 0.8226
0x404E, // Index: 44 Fraction: 65/79 = 0.8228
0x0D10, // Index: 45 Fraction: 14/17 = 0.8235
0x3C49, // Index: 46 Fraction: 61/74 = 0.8243
0x2E38, // Index: 47 Fraction: 47/57 = 0.8246
0x2027, // Index: 48 Fraction: 33/40 = 0.8250
0x333E, // Index: 49 Fraction: 52/63 = 0.8254
0x1216, // Index: 50 Fraction: 19/23 = 0.8261
0x3D4A, // Index: 51 Fraction: 62/75 = 0.8267
0x2A33, // Index: 52 Fraction: 43/52 = 0.8269
0x171C, // Index: 53 Fraction: 24/29 = 0.8276
0x343F, // Index: 54 Fraction: 53/64 = 0.8281
0x1C22, // Index: 55 Fraction: 29/35 = 0.8286
0x3E4B, // Index: 56 Fraction: 63/76 = 0.8289
0x2128, // Index: 57 Fraction: 34/41 = 0.8293
0x262E, // Index: 58 Fraction: 39/47 = 0.8298
0x2B34, // Index: 59 Fraction: 44/53 = 0.8302
0x303A, // Index: 60 Fraction: 49/59 = 0.8305
0x3540, // Index: 61 Fraction: 54/65 = 0.8308
0x3A46, // Index: 62 Fraction: 59/71 = 0.8310
0x3F4C, // Index: 63 Fraction: 64/77 = 0.8312
0x0405, // Index: 64 Fraction: 5/6 = 0.8333
0x414E, // Index: 65 Fraction: 66/79 = 0.8354
0x3C48, // Index: 66 Fraction: 61/73 = 0.8356
0x3742, // Index: 67 Fraction: 56/67 = 0.8358
0x323C, // Index: 68 Fraction: 51/61 = 0.8361
0x2D36, // Index: 69 Fraction: 46/55 = 0.8364
0x2830, // Index: 70 Fraction: 41/49 = 0.8367
0x232A, // Index: 71 Fraction: 36/43 = 0.8372
0x424F, // Index: 72 Fraction: 67/80 = 0.8375
0x1E24, // Index: 73 Fraction: 31/37 = 0.8378
0x3843, // Index: 74 Fraction: 57/68 = 0.8382
0x191E, // Index: 75 Fraction: 26/31 = 0.8387
0x2E37, // Index: 76 Fraction: 47/56 = 0.8393
0x1418, // Index: 77 Fraction: 21/25 = 0.8400
0x3944, // Index: 78 Fraction: 58/69 = 0.8406
0x242B, // Index: 79 Fraction: 37/44 = 0.8409
0x343E, // Index: 80 Fraction: 53/63 = 0.8413
0x0F12, // Index: 81 Fraction: 16/19 = 0.8421
0x3A45, // Index: 82 Fraction: 59/70 = 0.8429
0x2A32, // Index: 83 Fraction: 43/51 = 0.8431
0x1A1F, // Index: 84 Fraction: 27/32 = 0.8438
0x404C, // Index: 85 Fraction: 65/77 = 0.8442
0x252C, // Index: 86 Fraction: 38/45 = 0.8444
0x3039, // Index: 87 Fraction: 49/58 = 0.8448
0x3B46, // Index: 88 Fraction: 60/71 = 0.8451
0x0A0C, // Index: 89 Fraction: 11/13 = 0.8462
0x3C47, // Index: 90 Fraction: 61/72 = 0.8472
0x313A, // Index: 91 Fraction: 50/59 = 0.8475
0x262D, // Index: 92 Fraction: 39/46 = 0.8478
0x424E, // Index: 93 Fraction: 67/79 = 0.8481
0x1B20, // Index: 94 Fraction: 28/33 = 0.8485
0x2C34, // Index: 95 Fraction: 45/53 = 0.8491
0x3D48, // Index: 96 Fraction: 62/73 = 0.8493
0x1013, // Index: 97 Fraction: 17/20 = 0.8500
0x3842, // Index: 98 Fraction: 57/67 = 0.8507
0x272E, // Index: 99 Fraction: 40/47 = 0.8511
0x3E49, // Index: 100 Fraction: 63/74 = 0.8514
0x161A, // Index: 101 Fraction: 23/27 = 0.8519
0x333C, // Index: 102 Fraction: 52/61 = 0.8525
0x1C21, // Index: 103 Fraction: 29/34 = 0.8529
0x3F4A, // Index: 104 Fraction: 64/75 = 0.8533
0x2228, // Index: 105 Fraction: 35/41 = 0.8537
0x282F, // Index: 106 Fraction: 41/48 = 0.8542
0x2E36, // Index: 107 Fraction: 47/55 = 0.8545
0x343D, // Index: 108 Fraction: 53/62 = 0.8548
0x3A44, // Index: 109 Fraction: 59/69 = 0.8551
0x404B, // Index: 110 Fraction: 65/76 = 0.8553
0x0506, // Index: 111 Fraction: 6/7 = 0.8571
0x424D, // Index: 112 Fraction: 67/78 = 0.8590
0x3C46, // Index: 113 Fraction: 61/71 = 0.8592
0x363F, // Index: 114 Fraction: 55/64 = 0.8594
0x3038, // Index: 115 Fraction: 49/57 = 0.8596
0x2A31, // Index: 116 Fraction: 43/50 = 0.8600
0x242A, // Index: 117 Fraction: 37/43 = 0.8605
0x434E, // Index: 118 Fraction: 68/79 = 0.8608
0x1E23, // Index: 119 Fraction: 31/36 = 0.8611
0x3740, // Index: 120 Fraction: 56/65 = 0.8615
0x181C, // Index: 121 Fraction: 25/29 = 0.8621
0x444F, // Index: 122 Fraction: 69/80 = 0.8625
0x2B32, // Index: 123 Fraction: 44/51 = 0.8627
0x3E48, // Index: 124 Fraction: 63/73 = 0.8630
0x1215, // Index: 125 Fraction: 19/22 = 0.8636
0x323A, // Index: 126 Fraction: 51/59 = 0.8644
0x1F24, // Index: 127 Fraction: 32/37 = 0.8649
0x2C33, // Index: 128 Fraction: 45/52 = 0.8654
0x3942, // Index: 129 Fraction: 58/67 = 0.8657
0x0C0E, // Index: 130 Fraction: 13/15 = 0.8667
0x3A43, // Index: 131 Fraction: 59/68 = 0.8676
0x2D34, // Index: 132 Fraction: 46/53 = 0.8679
0x2025, // Index: 133 Fraction: 33/38 = 0.8684
0x343C, // Index: 134 Fraction: 53/61 = 0.8689
0x1316, // Index: 135 Fraction: 20/23 = 0.8696
0x424C, // Index: 136 Fraction: 67/77 = 0.8701
0x2E35, // Index: 137 Fraction: 47/54 = 0.8704
0x1A1E, // Index: 138 Fraction: 27/31 = 0.8710
0x3C45, // Index: 139 Fraction: 61/70 = 0.8714
0x2126, // Index: 140 Fraction: 34/39 = 0.8718
0x282E, // Index: 141 Fraction: 41/47 = 0.8723
0x2F36, // Index: 142 Fraction: 48/55 = 0.8727
0x363E, // Index: 143 Fraction: 55/63 = 0.8730
0x3D46, // Index: 144 Fraction: 62/71 = 0.8732
0x444E, // Index: 145 Fraction: 69/79 = 0.8734
0x0607, // Index: 146 Fraction: 7/8 = 0.8750
0x3F48, // Index: 147 Fraction: 64/73 = 0.8767
0x3840, // Index: 148 Fraction: 57/65 = 0.8769
0x3138, // Index: 149 Fraction: 50/57 = 0.8772
0x2A30, // Index: 150 Fraction: 43/49 = 0.8776
0x2328, // Index: 151 Fraction: 36/41 = 0.8780
0x4049, // Index: 152 Fraction: 65/74 = 0.8784
0x1C20, // Index: 153 Fraction: 29/33 = 0.8788
0x3239, // Index: 154 Fraction: 51/58 = 0.8793
0x1518, // Index: 155 Fraction: 22/25 = 0.8800
0x3A42, // Index: 156 Fraction: 59/67 = 0.8806
0x2429, // Index: 157 Fraction: 37/42 = 0.8810
0x333A, // Index: 158 Fraction: 52/59 = 0.8814
0x424B, // Index: 159 Fraction: 67/76 = 0.8816
0x0E10, // Index: 160 Fraction: 15/17 = 0.8824
0x434C, // Index: 161 Fraction: 68/77 = 0.8831
0x343B, // Index: 162 Fraction: 53/60 = 0.8833
0x252A, // Index: 163 Fraction: 38/43 = 0.8837
0x3C44, // Index: 164 Fraction: 61/69 = 0.8841
0x1619, // Index: 165 Fraction: 23/26 = 0.8846
0x353C, // Index: 166 Fraction: 54/61 = 0.8852
0x1E22, // Index: 167 Fraction: 31/35 = 0.8857
0x454E, // Index: 168 Fraction: 70/79 = 0.8861
0x262B, // Index: 169 Fraction: 39/44 = 0.8864
0x2E34, // Index: 170 Fraction: 47/53 = 0.8868
0x363D, // Index: 171 Fraction: 55/62 = 0.8871
0x3E46, // Index: 172 Fraction: 63/71 = 0.8873
0x464F, // Index: 173 Fraction: 71/80 = 0.8875
0x0708, // Index: 174 Fraction: 8/9 = 0.8889
0x4048, // Index: 175 Fraction: 65/73 = 0.8904
0x383F, // Index: 176 Fraction: 57/64 = 0.8906
0x3036, // Index: 177 Fraction: 49/55 = 0.8909
0x282D, // Index: 178 Fraction: 41/46 = 0.8913
0x2024, // Index: 179 Fraction: 33/37 = 0.8919
0x3940, // Index: 180 Fraction: 58/65 = 0.8923
0x181B, // Index: 181 Fraction: 25/28 = 0.8929
0x424A, // Index: 182 Fraction: 67/75 = 0.8933
0x292E, // Index: 183 Fraction: 42/47 = 0.8936
0x3A41, // Index: 184 Fraction: 59/66 = 0.8939
0x1012, // Index: 185 Fraction: 17/19 = 0.8947
0x3B42, // Index: 186 Fraction: 60/67 = 0.8955
0x2A2F, // Index: 187 Fraction: 43/48 = 0.8958
0x444C, // Index: 188 Fraction: 69/77 = 0.8961
0x191C, // Index: 189 Fraction: 26/29 = 0.8966
0x3C43, // Index: 190 Fraction: 61/68 = 0.8971
0x2226, // Index: 191 Fraction: 35/39 = 0.8974
0x2B30, // Index: 192 Fraction: 44/49 = 0.8980
0x343A, // Index: 193 Fraction: 53/59 = 0.8983
0x3D44, // Index: 194 Fraction: 62/69 = 0.8986
0x464E, // Index: 195 Fraction: 71/79 = 0.8987
0x0809, // Index: 196 Fraction: 9/10 = 0.9000
0x3F46, // Index: 197 Fraction: 64/71 = 0.9014
0x363C, // Index: 198 Fraction: 55/61 = 0.9016
0x2D32, // Index: 199 Fraction: 46/51 = 0.9020
0x2428, // Index: 200 Fraction: 37/41 = 0.9024
0x4047, // Index: 201 Fraction: 65/72 = 0.9028
0x1B1E, // Index: 202 Fraction: 28/31 = 0.9032
0x2E33, // Index: 203 Fraction: 47/52 = 0.9038
0x4148, // Index: 204 Fraction: 66/73 = 0.9041
0x1214, // Index: 205 Fraction: 19/21 = 0.9048
0x4249, // Index: 206 Fraction: 67/74 = 0.9054
0x2F34, // Index: 207 Fraction: 48/53 = 0.9057
0x1C1F, // Index: 208 Fraction: 29/32 = 0.9062
0x434A, // Index: 209 Fraction: 68/75 = 0.9067
0x262A, // Index: 210 Fraction: 39/43 = 0.9070
0x3035, // Index: 211 Fraction: 49/54 = 0.9074
0x3A40, // Index: 212 Fraction: 59/65 = 0.9077
0x444B, // Index: 213 Fraction: 69/76 = 0.9079
0x090A, // Index: 214 Fraction: 10/11 = 0.9091
0x464D, // Index: 215 Fraction: 71/78 = 0.9103
0x3C42, // Index: 216 Fraction: 61/67 = 0.9104
0x3237, // Index: 217 Fraction: 51/56 = 0.9107
0x282C, // Index: 218 Fraction: 41/45 = 0.9111
0x474E, // Index: 219 Fraction: 72/79 = 0.9114
0x1E21, // Index: 220 Fraction: 31/34 = 0.9118
0x3338, // Index: 221 Fraction: 52/57 = 0.9123
0x484F, // Index: 222 Fraction: 73/80 = 0.9125
0x1416, // Index: 223 Fraction: 21/23 = 0.9130
0x3439, // Index: 224 Fraction: 53/58 = 0.9138
0x1F22, // Index: 225 Fraction: 32/35 = 0.9143
0x2A2E, // Index: 226 Fraction: 43/47 = 0.9149
0x353A, // Index: 227 Fraction: 54/59 = 0.9153
0x4046, // Index: 228 Fraction: 65/71 = 0.9155
0x0A0B, // Index: 229 Fraction: 11/12 = 0.9167
0x4248, // Index: 230 Fraction: 67/73 = 0.9178
0x373C, // Index: 231 Fraction: 56/61 = 0.9180
0x2C30, // Index: 232 Fraction: 45/49 = 0.9184
0x2124, // Index: 233 Fraction: 34/37 = 0.9189
0x383D, // Index: 234 Fraction: 57/62 = 0.9194
0x1618, // Index: 235 Fraction: 23/25 = 0.9200
0x393E, // Index: 236 Fraction: 58/63 = 0.9206
0x2225, // Index: 237 Fraction: 35/38 = 0.9211
0x2E32, // Index: 238 Fraction: 47/51 = 0.9216
0x3A3F, // Index: 239 Fraction: 59/64 = 0.9219
0x464C, // Index: 240 Fraction: 71/77 = 0.9221
0x0B0C, // Index: 241 Fraction: 12/13 = 0.9231
0x484E, // Index: 242 Fraction: 73/79 = 0.9241
0x3C41, // Index: 243 Fraction: 61/66 = 0.9242
0x3034, // Index: 244 Fraction: 49/53 = 0.9245
0x2427, // Index: 245 Fraction: 37/40 = 0.9250
0x3D42, // Index: 246 Fraction: 62/67 = 0.9254
0x181A, // Index: 247 Fraction: 25/27 = 0.9259
0x3E43, // Index: 248 Fraction: 63/68 = 0.9265
0x2528, // Index: 249 Fraction: 38/41 = 0.9268
0x3236, // Index: 250 Fraction: 51/55 = 0.9273
0x3F44, // Index: 251 Fraction: 64/69 = 0.9275
0x0C0D, // Index: 252 Fraction: 13/14 = 0.9286
0x4146, // Index: 253 Fraction: 66/71 = 0.9296
0x3438, // Index: 254 Fraction: 53/57 = 0.9298
0x272A, // Index: 255 Fraction: 40/43 = 0.9302
0x4247, // Index: 256 Fraction: 67/72 = 0.9306
0x1A1C, // Index: 257 Fraction: 27/29 = 0.9310
0x4348, // Index: 258 Fraction: 68/73 = 0.9315
0x282B, // Index: 259 Fraction: 41/44 = 0.9318
0x363A, // Index: 260 Fraction: 55/59 = 0.9322
0x4449, // Index: 261 Fraction: 69/74 = 0.9324
0x0D0E, // Index: 262 Fraction: 14/15 = 0.9333
0x464B, // Index: 263 Fraction: 71/76 = 0.9342
0x383C, // Index: 264 Fraction: 57/61 = 0.9344
0x2A2D, // Index: 265 Fraction: 43/46 = 0.9348
0x474C, // Index: 266 Fraction: 72/77 = 0.9351
0x1C1E, // Index: 267 Fraction: 29/31 = 0.9355
0x484D, // Index: 268 Fraction: 73/78 = 0.9359
0x2B2E, // Index: 269 Fraction: 44/47 = 0.9362
0x3A3E, // Index: 270 Fraction: 59/63 = 0.9365
0x494E, // Index: 271 Fraction: 74/79 = 0.9367
0x0E0F, // Index: 272 Fraction: 15/16 = 0.9375
0x3C40, // Index: 273 Fraction: 61/65 = 0.9385
0x2D30, // Index: 274 Fraction: 46/49 = 0.9388
0x1E20, // Index: 275 Fraction: 31/33 = 0.9394
0x2E31, // Index: 276 Fraction: 47/50 = 0.9400
0x3E42, // Index: 277 Fraction: 63/67 = 0.9403
0x0F10, // Index: 278 Fraction: 16/17 = 0.9412
0x4044, // Index: 279 Fraction: 65/69 = 0.9420
0x3033, // Index: 280 Fraction: 49/52 = 0.9423
0x2022, // Index: 281 Fraction: 33/35 = 0.9429
0x3134, // Index: 282 Fraction: 50/53 = 0.9434
0x4246, // Index: 283 Fraction: 67/71 = 0.9437
0x1011, // Index: 284 Fraction: 17/18 = 0.9444
0x4448, // Index: 285 Fraction: 69/73 = 0.9452
0x3336, // Index: 286 Fraction: 52/55 = 0.9455
0x2224, // Index: 287 Fraction: 35/37 = 0.9459
0x3437, // Index: 288 Fraction: 53/56 = 0.9464
0x464A, // Index: 289 Fraction: 71/75 = 0.9467
0x1112, // Index: 290 Fraction: 18/19 = 0.9474
0x484C, // Index: 291 Fraction: 73/77 = 0.9481
0x3639, // Index: 292 Fraction: 55/58 = 0.9483
0x2426, // Index: 293 Fraction: 37/39 = 0.9487
0x373A, // Index: 294 Fraction: 56/59 = 0.9492
0x4A4E, // Index: 295 Fraction: 75/79 = 0.9494
0x1213, // Index: 296 Fraction: 19/20 = 0.9500
0x393C, // Index: 297 Fraction: 58/61 = 0.9508
0x2628, // Index: 298 Fraction: 39/41 = 0.9512
0x3A3D, // Index: 299 Fraction: 59/62 = 0.9516
0x1314, // Index: 300 Fraction: 20/21 = 0.9524
0x3C3F, // Index: 301 Fraction: 61/64 = 0.9531
0x282A, // Index: 302 Fraction: 41/43 = 0.9535
0x3D40, // Index: 303 Fraction: 62/65 = 0.9538
0x1415, // Index: 304 Fraction: 21/22 = 0.9545
0x3F42, // Index: 305 Fraction: 64/67 = 0.9552
0x2A2C, // Index: 306 Fraction: 43/45 = 0.9556
0x4043, // Index: 307 Fraction: 65/68 = 0.9559
0x1516, // Index: 308 Fraction: 22/23 = 0.9565
0x4245, // Index: 309 Fraction: 67/70 = 0.9571
0x2C2E, // Index: 310 Fraction: 45/47 = 0.9574
0x4346, // Index: 311 Fraction: 68/71 = 0.9577
0x1617, // Index: 312 Fraction: 23/24 = 0.9583
0x4548, // Index: 313 Fraction: 70/73 = 0.9589
0x2E30, // Index: 314 Fraction: 47/49 = 0.9592
0x4649, // Index: 315 Fraction: 71/74 = 0.9595
0x1718, // Index: 316 Fraction: 24/25 = 0.9600
0x484B, // Index: 317 Fraction: 73/76 = 0.9605
0x3032, // Index: 318 Fraction: 49/51 = 0.9608
0x494C, // Index: 319 Fraction: 74/77 = 0.9610
0x1819, // Index: 320 Fraction: 25/26 = 0.9615
0x4B4E, // Index: 321 Fraction: 76/79 = 0.9620
0x3234, // Index: 322 Fraction: 51/53 = 0.9623
0x4C4F, // Index: 323 Fraction: 77/80 = 0.9625
0x191A, // Index: 324 Fraction: 26/27 = 0.9630
0x3436, // Index: 325 Fraction: 53/55 = 0.9636
0x1A1B, // Index: 326 Fraction: 27/28 = 0.9643
0x3638, // Index: 327 Fraction: 55/57 = 0.9649
0x1B1C, // Index: 328 Fraction: 28/29 = 0.9655
0x383A, // Index: 329 Fraction: 57/59 = 0.9661
0x1C1D, // Index: 330 Fraction: 29/30 = 0.9667
0x3A3C, // Index: 331 Fraction: 59/61 = 0.9672
0x1D1E, // Index: 332 Fraction: 30/31 = 0.9677
0x3C3E, // Index: 333 Fraction: 61/63 = 0.9683
0x1E1F, // Index: 334 Fraction: 31/32 = 0.9688
0x3E40, // Index: 335 Fraction: 63/65 = 0.9692
0x1F20, // Index: 336 Fraction: 32/33 = 0.9697
0x4042, // Index: 337 Fraction: 65/67 = 0.9701
0x2021, // Index: 338 Fraction: 33/34 = 0.9706
0x4244, // Index: 339 Fraction: 67/69 = 0.9710
0x2122, // Index: 340 Fraction: 34/35 = 0.9714
0x4446, // Index: 341 Fraction: 69/71 = 0.9718
0x2223, // Index: 342 Fraction: 35/36 = 0.9722
0x4648, // Index: 343 Fraction: 71/73 = 0.9726
0x2324, // Index: 344 Fraction: 36/37 = 0.9730
0x484A, // Index: 345 Fraction: 73/75 = 0.9733
0x2425, // Index: 346 Fraction: 37/38 = 0.9737
0x4A4C, // Index: 347 Fraction: 75/77 = 0.9740
0x2526, // Index: 348 Fraction: 38/39 = 0.9744
0x4C4E, // Index: 349 Fraction: 77/79 = 0.9747
0x2627, // Index: 350 Fraction: 39/40 = 0.9750
0x2728, // Index: 351 Fraction: 40/41 = 0.9756
0x2829, // Index: 352 Fraction: 41/42 = 0.9762
0x292A, // Index: 353 Fraction: 42/43 = 0.9767
0x2A2B, // Index: 354 Fraction: 43/44 = 0.9773
0x2B2C, // Index: 355 Fraction: 44/45 = 0.9778
0x2C2D, // Index: 356 Fraction: 45/46 = 0.9783
0x2D2E, // Index: 357 Fraction: 46/47 = 0.9787
0x2E2F, // Index: 358 Fraction: 47/48 = 0.9792
0x2F30, // Index: 359 Fraction: 48/49 = 0.9796
0x3031, // Index: 360 Fraction: 49/50 = 0.9800
0x3132, // Index: 361 Fraction: 50/51 = 0.9804
0x3233, // Index: 362 Fraction: 51/52 = 0.9808
0x3334, // Index: 363 Fraction: 52/53 = 0.9811
0x3435, // Index: 364 Fraction: 53/54 = 0.9815
0x3536, // Index: 365 Fraction: 54/55 = 0.9818
0x3637, // Index: 366 Fraction: 55/56 = 0.9821
0x3738, // Index: 367 Fraction: 56/57 = 0.9825
0x3839, // Index: 368 Fraction: 57/58 = 0.9828
0x393A, // Index: 369 Fraction: 58/59 = 0.9831
0x3A3B, // Index: 370 Fraction: 59/60 = 0.9833
0x3B3C, // Index: 371 Fraction: 60/61 = 0.9836
0x3C3D, // Index: 372 Fraction: 61/62 = 0.9839
0x3D3E, // Index: 373 Fraction: 62/63 = 0.9841
0x3E3F, // Index: 374 Fraction: 63/64 = 0.9844
0x3F40, // Index: 375 Fraction: 64/65 = 0.9846
0x4041, // Index: 376 Fraction: 65/66 = 0.9848
0x4142, // Index: 377 Fraction: 66/67 = 0.9851
0x4243, // Index: 378 Fraction: 67/68 = 0.9853
0x4344, // Index: 379 Fraction: 68/69 = 0.9855
0x4445, // Index: 380 Fraction: 69/70 = 0.9857
0x4546, // Index: 381 Fraction: 70/71 = 0.9859
0x4647, // Index: 382 Fraction: 71/72 = 0.9861
0x4748, // Index: 383 Fraction: 72/73 = 0.9863
0x4849, // Index: 384 Fraction: 73/74 = 0.9865
0x494A, // Index: 385 Fraction: 74/75 = 0.9867
0x4A4B, // Index: 386 Fraction: 75/76 = 0.9868
0x4B4C, // Index: 387 Fraction: 76/77 = 0.9870
0x4C4D, // Index: 388 Fraction: 77/78 = 0.9872
0x4D4E, // Index: 389 Fraction: 78/79 = 0.9873
0x4E4F, // Index: 390 Fraction: 79/80 = 0.9875
};

View File

@@ -145,7 +145,7 @@ on stdcore[XUD_TILE] : buffered in port:32 p_adat_rx = PORT_ADAT_IN;
on tile[XUD_TILE] : in port p_spdif_rx = PORT_SPDIF_IN;
#endif
#if (XUA_SPDIF_RX_EN) || (XUA_ADAT_RX_EN) || (XUA_SYNCMODE == XUA_SYNCMODE_SYNC)
#if (XUA_SPDIF_RX_EN) || (XUA_ADAT_RX_EN) || ((XUA_SYNCMODE == XUA_SYNCMODE_SYNC) && (!XUA_USE_APP_PLL))
/* Reference to external clock multiplier */
on tile[PLL_REF_TILE] : out port p_pll_ref = PORT_PLL_REF;
#endif
@@ -314,6 +314,9 @@ void usb_audio_io(chanend ?c_aud_in,
#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
, client interface pll_ref_if i_pll_ref
#endif
#if (XUA_USE_APP_PLL)
, client interface SoftPll_if i_softPll
#endif
)
{
#if (MIXER)
@@ -364,6 +367,9 @@ void usb_audio_io(chanend ?c_aud_in,
#define AUDIO_CHANNEL c_aud_in
#endif
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_USE_APP_PLL)
, i_softPll
#endif
#if (XUA_SPDIF_TX_EN) //&& (SPDIF_TX_TILE != AUDIO_IO_TILE)
, c_spdif_tx
#endif
@@ -467,9 +473,14 @@ int main()
#endif
#endif
#if ((XUA_SYNCMODE == XUA_SYNCMODE_SYNC) || XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
#if (((XUA_SYNCMODE == XUA_SYNCMODE_SYNC) && !XUA_USE_APP_PLL) || XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
interface pll_ref_if i_pll_ref;
#endif
#if (XUA_USE_APP_PLL)
interface SoftPll_if i_softPll;
chan c_swpll_update;
#endif
chan c_sof;
chan c_xud_out[ENDPOINT_COUNT_OUT]; /* Endpoint channels for XUD */
chan c_xud_in[ENDPOINT_COUNT_IN];
@@ -491,7 +502,7 @@ int main()
{
USER_MAIN_CORES
#if ((XUA_SYNCMODE == XUA_SYNCMODE_SYNC) || XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
#if (((XUA_SYNCMODE == XUA_SYNCMODE_SYNC) && XYA_USE_APP_PLL) || XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
on tile[PLL_REF_TILE]: PllRefPinTask(i_pll_ref, p_pll_ref);
#endif
on tile[XUD_TILE]:
@@ -522,6 +533,10 @@ int main()
c_sof, epTypeTableOut, epTypeTableIn, usbSpeed, xudPwrCfg);
}
#if (XUA_USE_APP_PLL)
//XUA_SoftPll(tile[0], i_softPll, c_swpll_update);
#endif
/* Core USB audio task, buffering, USB etc */
{
unsigned x;
@@ -564,7 +579,11 @@ int main()
#endif
, c_mix_out
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC)
#if (!XUA_USE_APP_PLL)
, i_pll_ref
#else
, c_swpll_update
#endif
#endif
);
//:
@@ -579,6 +598,9 @@ int main()
#endif /* XUA_USB_EN */
}
#if(XUA_USE_APP_PLL)
on tile[AUDIO_IO_TILE]: XUA_SoftPll(tile[0], i_softPll, c_swpll_update);
#endif
on tile[AUDIO_IO_TILE]:
{
/* Audio I/O task, includes mixing etc */
@@ -601,6 +623,9 @@ int main()
#endif
#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
, i_pll_ref
#endif
#if (XUA_USE_APP_PLL)
, i_softPll
#endif
);
}

View File

@@ -0,0 +1,29 @@
// Copyright 2023 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
/* Default implementations of AudioHwInit(), AudioHwConfig(), AudioHwConfig_Mute() and AudioHwConfig_UnMute() */
void AudioHwInit() __attribute__ ((weak));
void AudioHwInit()
{
return;
}
void AudioHwConfig(unsigned samFreq, unsigned mClk, unsigned dsdMode, unsigned sampRes_DAC, unsigned sampRes_ADC) __attribute__ ((weak));
void AudioHwConfig(unsigned samFreq, unsigned mClk, unsigned dsdMode, unsigned sampRes_DAC, unsigned sampRes_ADC)
{
return;
}
void AudioHwConfig_Mute() __attribute__ ((weak));
void AudioHwConfig_Mute()
{
return;
}
void AudioHwConfig_UnMute() __attribute__ ((weak));
void AudioHwConfig_UnMute()
{
return;
}

View File

@@ -0,0 +1,54 @@
// Copyright 2023 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#ifndef _AUDIO_HW_H_
#define _AUDIO_HW_H_
/* The functions below should be implemented for the external audio hardware arrangement of a specific design.
* Note, default (empty) implementations of these are provided in audiohub_user.c
*/
/**
* @brief User audio hardware initialisation code
*
* This function is called when the device starts up and should contain user code to perform any required audio hardware initialisation
*/
void AudioHwInit(void);
/**
* @brief User audio hardware configuration code
*
* This function is called when on sample rate change and should contain user code to configure audio hardware
* (clocking, CODECs etc) for a specific mClk/Sample frequency
*
* \param samFreq The new sample frequency (in Hz)
*
* \param mClk The new master clock frequency (in Hz)
*
* \param dsdMode DSD mode, DSD_MODE_NATIVE, DSD_MODE_DOP or DSD_MODE_OFF
*
* \param sampRes_DAC Playback sample resolution (in bits)
*
* \param sampRes_ADC Record sample resolution (in bits)
*/
void AudioHwConfig(unsigned samFreq, unsigned mClk, unsigned dsdMode, unsigned sampRes_DAC, unsigned sampRes_ADC);
/**
* @brief User code mute audio hardware
*
* This function is called before AudioHwConfig() and should contain user code to mute audio hardware before a
* sample rate change in order to reduced audible pops/clicks
*
* Note, if using the application PLL of a xcore.ai device this function will be called before the master-clock is
* changed
*/
void AudioHwConfig_Mute(void);
/**
* @brief User code to un-mute audio hardware
*
* This function is called after AudioHwConfig() and should contain user code to un-mute audio hardware after a
* sample rate change
*/
void AudioHwConfig_UnMute(void);
#endif

View File

@@ -1,30 +1,51 @@
// Copyright 2011-2021 XMOS LIMITED.
// Copyright 2011-2023 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#ifndef _AUDIOSTREAM_H_
#define _AUDIOSTREAM_H_
/* Functions that handle functions that must occur on stream start/stop e.g. DAC mute/un-mute
*
* THESE NEED IMPLEMENTING FOR A SPECIFIC DESIGN
*
* */
/* Functions that handle functionality that occur on stream start/stop e.g. DAC mute/un-mute.
* They should be implemented for the external audio hardware arrangement of a specific design.
*/
/* Any actions required for stream start e.g. DAC un-mute - run every stream start */
/**
* @brief User stream start code
*
* User code to perform any actions required at every stream start - either input or output
*/
void UserAudioStreamStart(void);
/* Any actions required on stream stop e.g. DAC mute - run every steam stop */
/**
* @brief User stream stop code
*
* User code to perform any actions required on every stream stop - either input or output*/
void UserAudioStreamStop(void);
/* Any actions required on input stream start */
/**
* @brief User input stream stop code
*
* User code to perform any actions required on input stream start i.e. device to host
*/
void UserAudioInputStreamStart(void);
/* Any actions required on input stream stop */
/**
* @brief User input stream stop code
*
* User code to perform any actions required on input stream stop i.e. device to host
*/
void UserAudioInputStreamStop(void);
/* Any actions required on output stream start */
/**
* @brief User output stream start code
*
* User code to perform any actions required on output stream start i.e. host to device
*/
void UserAudioOutputStreamStart(void);
/* Any actions required on output stream stop */
/**
* @brief User output stream stop code
*
* User code to perfrom any actions required on output stream stop i.e. host to device
*/
void UserAudioOutputStreamStop(void);
#endif

View File

@@ -5,13 +5,13 @@
* @brief Human Interface Device (HID) API
*
* This file defines the Application Programming Interface (API) used to record HID
* events and retrieve a HID Report for sending to a host.
* events and retrieve a HID Report for sending to a host.
* The using application has the responsibility to fulfill this API.
* Document section numbers refer to the HID Device Class Definition, version 1.11.
*/
#ifndef __USER_HID_H__
#define __USER_HID_H__
#ifndef _USER_HID_H_
#define _USER_HID_H_
#include <stddef.h>
@@ -34,22 +34,16 @@ typedef struct hidEvent_t {
#define HID_MAX_DATA_BYTES ( 4 )
#define HID_EVENT_INVALID_ID ( 0x100 )
#if XUA_HID_ENABLED
/**
* \brief Get the data for the next HID Report
*
* \note This function returns the HID data as a list of unsigned char because the
* \c XUD_SetReady_In() accepts data for transmission to the USB Host using
* this type.
*
* \param[in] id The HID Report ID (see 5.6, 6.2.2.7, 8.1 and 8.2)
* Set to zero if the application provides only one HID Report
* which does not include a Report ID
* which does not include a Report ID
* \param[out] hidData The HID data
* If using Report IDs, this function places the Report ID in
* the first element; otherwise the first element holds the
* first byte of HID event data.
* the first element; otherwise the first element holds the
* first byte of HID event data.
*
* \returns The length of the HID Report in the \a hidData argument
* \retval Zero means no new HID event data has been recorded for the given \a id
@@ -61,5 +55,4 @@ size_t UserHIDGetData( const unsigned id, unsigned char hidData[ HID_MAX_DATA_BY
*/
void UserHIDInit( void );
#endif /* ( 0 < HID_CONTROLS ) */
#endif /* __USER_HID_H__ */
#endif /* _USER_HID_H_ */

View File

@@ -1,4 +1,12 @@
// Copyright 2013-2021 XMOS LIMITED.
// Copyright 2013-2023 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
/**
* @brief User host active code
*
* This function can be used to perform user defined actions based on host present/not-present events.
* This function is called on a change in state.
*
* \param active Indicates if the host is active or not. 1 for active, else 0
*/
void UserHostActive(int active);

View File

@@ -3,10 +3,12 @@ TEST_FLAGS ?=
XCC_FLAGS_HS = -O3 -g -DXUD_CORE_CLOCK=600 -save-temps -DUSB_TILE=tile[0] -DLOCAL_CLOCK_INCREMENT=10000 -DLOCAL_CLOCK_MARGIN=100 \
-DBUS_SPEED=2 \
-DXUA_USE_APP_PLL=0 \
$(TEST_FLAGS)
XCC_FLAGS_FS = -O3 -g -DXUD_CORE_CLOCK=600 -save-temps -DUSB_TILE=tile[0] -DLOCAL_CLOCK_INCREMENT=10000 -DLOCAL_CLOCK_MARGIN=100 \
-DBUS_SPEED=1 \
-DXUA_USE_APP_PLL=0 \
$(TEST_FLAGS)
TARGET = test_xs3_600.xn