37 Commits

Author SHA1 Message Date
Ross Owen
3a2926d1d8 Set default XUA_I2S_DUMMY_SAMPS value to 0 2023-06-12 18:07:10 +01:00
Ross Owen
85fd297336 Merge remote-tracking branch 'upstream' into feat/dummy_samps 2023-06-12 16:22:57 +01:00
Ross Owen
c92a640439 Added support for I2S/TDM “dummy samples” via XUA_I2S_DUMMY_SAMPS 2023-06-12 16:22:35 +01:00
Ross Owen
355df6d6b8 Fixed doc build 2023-06-07 15:24:29 +01:00
Ross Owen
0bff3dc5a8 Removed documentation for XUA_I2S_N_BITS=24 2023-06-07 12:32:07 +01:00
Ross Owen
9abd3b33f3 Bump lib_spdif dependency requirement 2023-06-07 12:17:40 +01:00
Ross Owen
0932ca0ccc Documentation updates relating to TDM/I2S 2023-06-07 11:53:42 +01:00
Ross Owen
f1df805b17 Added checks on XUA_I2S_N_BITS value 2023-06-07 10:24:40 +01:00
Ross Owen
867fb3f228 Use XUA_I2S_N_BITS when deciding whether or not to delay falling edge of bit clock when CODEC_MASTER=1 2023-06-06 20:20:15 +01:00
Ross Owen
9cbdf6374e Copyright date update 2023-06-06 19:34:36 +01:00
Ross Owen
a5922ce3ea Fixed issue with when XUA_I2S_N_BITS !=32 and CODEC_MASTER == 1 2023-06-06 19:13:25 +01:00
Ross Owen
e24bbe42eb test_i2s_loopback: add testing support for 16bit 2023-06-06 18:31:52 +01:00
Ross Owen
1488ace820 Fixed issue with I2S input when XUA_I2S_N_BITS != 32 2023-06-06 18:10:42 +01:00
Ross Owen
06bd547c69 Set XUA_I2S_N_BITS in test_i2s_loopback 2023-06-06 15:27:00 +01:00
Ross Owen
c2e1a8f17a Fixed issue where sample rate not set in test_i2s_loopback 2023-06-06 15:22:34 +01:00
Ross Owen
58bb074f0d Rationalisation of test_i2s_loopback config building 2023-06-06 14:52:03 +01:00
Ross Owen
c794ee77d5 Update copyright comment 2023-06-06 12:01:46 +01:00
Ross Owen
1cd24963d5 Fixed build issues when CODEC_MASTER set 2023-06-05 14:37:01 +01:00
Ross Owen
b27514fd9a Added XUA_I2S_N_BITS (was N_BITS_I2S) and tidied up usage of define 2023-06-05 14:24:59 +01:00
Ross Owen
5d886487fa Fixed operation when N_BITS_I2S define and small tidies 2023-06-02 16:37:43 +01:00
Ross Owen
1b50abb7a2 Resolve build issues post merge 2023-06-02 14:35:15 +01:00
Ross Owen
d3f0f11d9e Removed example 2023-06-02 14:20:44 +01:00
Ross Owen
897328f9c1 Resolved conflicts merging with develop 2023-06-02 14:18:44 +01:00
Ed
f7b05be05b Merge commit 'a44d5466b5ff4d1d766236d7036daceedef9f2c2' into variable_i2s_bit_width 2021-05-19 10:08:20 +01:00
Ed
fbda8fe92a Merge branch 'develop' of github.com:xmos/lib_xua into variable_i2s_bit_width 2021-05-19 10:02:22 +01:00
Ed
be69d3468e Initial guarding of variable bit I2S modifications 2019-08-23 16:15:47 +01:00
Ed
7cae9c385c Merge remote-tracking branch 'xmos/develop' into variable_i2s_bit_width 2019-08-23 15:34:06 +01:00
Ed Clarke
d9de1f0322 Add clock divider checks and remove debug prints 2019-05-01 10:58:15 +01:00
Ed Clarke
dd21ed0a84 Fix LRCLK alignment when N_BITS < 32 2019-05-01 10:25:22 +01:00
Ed Clarke
d50c9510c6 Fix app so that it loops (working 32b I2S master) 2019-05-01 09:49:36 +01:00
Ed Clarke
b032310302 Initial modifications to extend support to variable bit width master 2019-04-30 18:09:23 +01:00
Ed Clarke
8f9828ea2c Add simple test app for I2S loopback (no USB) 2019-04-30 18:07:15 +01:00
Ed Clarke
50097db00d Merge commit 'c59f9a7c0c628bffc9f9de5a6a4ee55e660d32fe' into variable_i2s_bit_width 2019-04-30 16:01:25 +01:00
Ed Clarke
c59f9a7c0c Make lrcheck mask track the data size 2018-10-15 08:56:57 +01:00
Ed Clarke
7ae04ca313 Enable error checking (helps recover from noise) 2018-10-12 14:26:02 +01:00
Ed Clarke
2562f0eb31 Fix I2S alignment 2018-10-12 14:25:47 +01:00
Ed Clarke
baaef3b749 Initial modifications for 24b I2S slave (without sync error check) 2018-10-10 11:21:44 +01:00
34 changed files with 573 additions and 1616 deletions

View File

@@ -1,35 +1,14 @@
lib_xua Change Log
==================
3.5.1
-----
UNRELEASED
----------
* 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
-----
* ADDED: Configurable word-length for I2S/TDM via XUA_I2S_N_BITS
* ADDED: Support for statically defined custom HID descriptor
* CHANGED: Rearranged main() such that adding custom code that uses lib_xud
is possible
* CHANGED: bNumConfigurations changed from 2 to 1, removing a work-around to
stop old Windows versions loading the composite driver
* FIXED: Memory corruption due to erroneous initialisation of mixer
weights when not in use (#152)
* 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 (#327)
* Changes to dependencies:
- lib_spdif: 4.2.1 -> 5.0.0
- lib_xud: 2.2.2 -> 2.2.3
3.4.0
-----

View File

@@ -1,8 +1,10 @@
lib_xua
#######
:Version: 3.5.0
:Version: 3.4.0
:Vendor: XMOS
:Scope: General Use
Summary
@@ -39,9 +41,9 @@ Key features of the various components in this repository are as follows
- Synchronisation to external digital streams i.e. S/PDIF or ADAT (when in asynchronous mode)
- I2S (slave/master modes with configurable word-length)
- I2S slave & master modes
- TDM (slave/master modes with configurable word-length)
- TDM slave & master modes
- MIDI input/output (Compliant to USB Class Specification for MIDI devices)
@@ -51,8 +53,6 @@ Key features of the various components in this repository are as follows
- Simple playback controls via USB Human Interface Device (HID) Class
- Support for adding custom HID interfaces
Note, not all features may be supported at all sample frequencies, simultaneously or on all devices.
Some features may also require specific host driver support.

View File

@@ -1,8 +1,9 @@
// Copyright 2017-2023 XMOS LIMITED.
// Copyright 2017-2022 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;
@@ -34,6 +35,11 @@ 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.
@@ -42,12 +48,9 @@ void AudioHwInit()
*/
}
/* 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
*/
/* Configures the external audio hardware for the required sample frequency */
void AudioHwConfig(unsigned samFreq, unsigned mClk, unsigned dsdMode, unsigned sampRes_DAC, unsigned sampRes_ADC)
{
/* Nothing required since the DAC's will auto detect the sample rate from the clocks */
AppPllEnable_SampleRate(samFreq);
}

View File

@@ -1,8 +1,9 @@
// Copyright 2017-2023 XMOS LIMITED.
// Copyright 2017-2022 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;
@@ -34,6 +35,11 @@ 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.
@@ -42,12 +48,9 @@ void AudioHwInit()
*/
}
/* 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
*/
/* Configures the external audio hardware for the required sample frequency */
void AudioHwConfig(unsigned samFreq, unsigned mClk, unsigned dsdMode, unsigned sampRes_DAC, unsigned sampRes_ADC)
{
/* Nothing required since the DAC's will auto detect the sample rate from the clocks */
AppPllEnable_SampleRate(samFreq);
}

109
examples/shared/apppll.h Normal file
View File

@@ -0,0 +1,109 @@
// 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,8 +12,6 @@
#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
@@ -36,8 +34,6 @@
*
* \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
@@ -51,9 +47,6 @@ 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
@@ -70,28 +63,21 @@ 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__
/**
* @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();
void UserBufferManagement(unsigned sampsFromUsbToAudio[], unsigned sampsFromAudioToUsb[]);
#endif // _XUA_AUDIOHUB_H_

View File

@@ -1,7 +1,7 @@
// Copyright 2011-2023 XMOS LIMITED.
// Copyright 2011-2022 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,7 +26,6 @@
* \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,
@@ -52,13 +51,8 @@ void XUA_Buffer(
, chanend c_hid
#endif
, chanend c_aud
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC) || defined(__DOYXGEN__)
#if (!XUA_USE_APP_PLL) || defined(__DOXYGEN__)
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC) || defined(__DOXYGEN__)
, client interface pll_ref_if i_pll_ref
#endif
#if (XUA_USE_APP_PLL) || defined(__DOXYGEN__)
, chanend c_swpll_update
#endif
#endif
);
@@ -87,16 +81,10 @@ void XUA_Buffer_Ep(chanend c_aud_out,
#ifdef CHAN_BUFF_CTRL
, chanend c_buff_ctrl
#endif
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC) || defined(__DOYXGEN__)
#if (!XUA_USE_APP_PLL) || defined(__DOXYGEN__)
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC) || 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,11 +1,10 @@
// Copyright 2011-2023 XMOS LIMITED.
// Copyright 2011-2022 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
{
@@ -29,46 +28,5 @@ 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,9 +11,7 @@
#include "xua_conf.h"
#endif
/*
* Tile arrangement defines
*/
/* Default tile arrangement */
/**
* @brief Location (tile) of audio I/O. Default: 0
@@ -57,9 +55,12 @@
#define PLL_REF_TILE AUDIO_IO_TILE
#endif
/*
* Channel based defines
/**
* @brief Disable USB functionalty just leaving AudioHub
*/
#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)
@@ -78,18 +79,7 @@
#endif
/**
* @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)
* @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)
@@ -101,34 +91,6 @@
#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)
/**
@@ -158,17 +120,30 @@
#endif
#endif
/**
* @brief Number of bits per channel for I2S/TDM. Supported values: 16/32-bit.
* @brief Number of IS2 channesl to DAC/CODEC. Must be a multiple of 2.
*
* Default: 32 bits
* Default: NONE (Must be defined by app)
*/
#ifndef XUA_I2S_N_BITS
#define XUA_I2S_N_BITS (32)
#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
#if (XUA_I2S_N_BITS != 16) && (XUA_I2S_N_BITS != 32)
#error Unsupported value for XUA_I2S_N_BITS (only values 16/32 supported)
/**
* @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
/**
@@ -222,32 +197,52 @@
#define I2S_DOWNSAMPLE_CHANS_IN I2S_CHANS_ADC
#endif
/*
* Clocking related defines
*/
#ifndef XUA_I2S_DUMMY_SAMPS
#define XUA_I2S_DUMMY_SAMPS (0)
#endif
/**
* @brief Max supported sample frequency for device (Hz).
* @brief Number of bits per channel for I2S/TDM. Supported values: 16/32-bit.
*
* Default: 192000Hz
* 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 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
*/
#ifndef MAX_FREQ
#define MAX_FREQ (192000)
#endif
/**
* @brief Min supported sample frequency for device (Hz).
*
* Default: 44100Hz
* @brief Min supported sample frequency for device (Hz). Default 44100
*/
#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
@@ -255,9 +250,7 @@
#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
@@ -265,66 +258,26 @@
#endif
/**
* @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
* @brief Default device sample frequency. A safe default should be used. Default: MIN_FREQ
*/
#ifndef DEFAULT_FREQ
#define DEFAULT_FREQ (MIN_FREQ)
#endif
#define DEFAULT_MCLK (((DEFAULT_FREQ % 7350) == 0) ? MCLK_441 : MCLK_48)
/* Audio Class Defines */
/**
* @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)
* @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 Enable/disable fall back to Audio Class 1.0 in USB Full-speed.
*
* Default: Disabled
* @brief Whether or not to fall back to Audio Class 1.0 in USB Full-speed. Default: 0 (Disabled)
*/
#ifndef AUDIO_CLASS_FALLBACK
#define AUDIO_CLASS_FALLBACK (0)
#define AUDIO_CLASS_FALLBACK 0 /* Default to not falling back to UAC 1 */
#endif
/**
@@ -353,17 +306,14 @@
#error AUDIO_CLASS set to 1 and FULL_SPEED_AUDIO_2 enabled!
#endif
/*
* Feature defines
*/
/* Feature defines */
/**
* @brief Disable USB functionalty just leaving AudioHub
*
* Default: Enabled
* @brief Number of PDM microphones in the design. Default: None
*/
#ifndef XUA_USB_EN
#define XUA_USB_EN (1)
#ifndef XUA_NUM_PDM_MICS
#define XUA_NUM_PDM_MICS (0)
#endif
/**
@@ -516,36 +466,14 @@
#endif
/**
* HID may be required in two forms: the built-in XUA-HID reports, or a
* user-provided static HID. Some sections of code are always needed, they
* are enclosed in XUA_OR_STATIC_HID_ENABLED; code specific to XUA-HID
* reports are enclosed in XUA_HID_ENABLED.
* @brief Defines whether XMOS device runs as master (i.e. drives LR and Bit clocks)
*
* HID_CONTROLS implies that the XUA_HID is used, and hence defines both.
* In order to roll your own, do not enable HID_CONTROLS, but instead
* create a file static_hid_report.h that contains the static descriptor.
* 0: XMOS is I2S master. 1: CODEC is I2s master.
*
* You must also supply your own function to deal with the HID endpoint(s)
* in this case.
* Default: 0 (XMOS is master)
*/
#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
/**
* @brief Enable a HID OUT endpoint. Only use this if you supply your own HID control.
*
* 1 for enabled, 0 for disabled.
*
* Default 0 (Disabled)
*/
#ifndef HID_OUT_REQUIRED
#define HID_OUT_REQUIRED (0)
#ifndef CODEC_MASTER
#define CODEC_MASTER (0)
#endif
/**
@@ -1252,7 +1180,7 @@ enum USBEndpointNumber_In
#ifdef MIDI
ENDPOINT_NUMBER_IN_MIDI,
#endif
#if XUA_OR_STATIC_HID_ENABLED
#if( 0 < HID_CONTROLS )
ENDPOINT_NUMBER_IN_HID,
#endif
#ifdef IAP
@@ -1279,9 +1207,6 @@ enum USBEndpointNumber_Out
#ifdef IAP_EA_NATIVE_TRANS
ENDPOINT_NUMBER_OUT_IAP_EA_NATIVE_TRANS,
#endif
#endif
#if XUA_OR_STATIC_HID_ENABLED && HID_OUT_REQUIRED
ENDPOINT_NUMBER_OUT_HID,
#endif
XUA_ENDPOINT_COUNT_OUT /* End marker */
};

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,7 +38,6 @@ Frequencies and Clocks
.. doxygendefine:: DEFAULT_FREQ
.. doxygendefine:: MCLK_441
.. doxygendefine:: MCLK_48
.. doxygendefine:: XUA_USE_APP_PLL
Audio Class
-----------

View File

@@ -1,49 +1,74 @@
|newpage|
Required User Function Definitions
==================================
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.
The following functions need to be defined by an application using the XMOS USB Audio framework.
External Audio Hardware Configuration Functions
-----------------------------------------------
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.
.. c:function:: void AudioHwInit(chanend ?c_codec)
.. doxygenfunction:: AudioHwInit
.. doxygenfunction:: AudioHwConfig
.. doxygenfunction:: AudioHwConfig_Mute
.. doxygenfunction:: AudioHwConfig_UnMute
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
:param c_codec: An optional chanend that was original passed into
:c:func:`audio` that can be used to communicate
with other cores.
Audio Stream Start/Stop Functions
---------------------------------
.. 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
-------------------------
The following functions can be optionally used by the design. They can be useful for mute lines etc.
.. doxygenfunction:: UserAudioStreamStart
.. doxygenfunction:: UserAudioStreamStop
.. doxygenfunction:: UserAudioInputStreamStart
.. doxygenfunction:: UserAudioInputStreamStop
.. doxygenfunction:: UserAudioOutputStreamStart
.. doxygenfunction:: UserAudioOutputStreamStop
.. c:function:: void AudioStreamStart(void)
Host Active Functions
---------------------
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
-----------
The following function can be used to signal that the device is connected to a valid host.
.. doxygenfunction:: UserHostActive
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.
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.
.. doxygenfunction:: UserHIDGetData
.. 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.

View File

@@ -1,27 +1,27 @@
|newpage|
Synchronisation & Clocking
==========================
Synchronisation
===============
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 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 and 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,17 +39,10 @@ Setting the synchronisation mode of the device is done using the define in :ref:
- USB synchronisation mode
- ``XUA_SYNCMODE_ASYNC``
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.
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 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.
The programmer should ensure the define in :ref:`opt_sync_ref_defines` is set appropriately.
.. _opt_sync_ref_defines:
@@ -64,33 +57,10 @@ In this case the developer should ensure the define in :ref:`opt_sync_ref_define
- 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 ../../src/core/user/audiostream ../../src/core/user/hostactive ../../src/core/user/hid ../../src/core/user/audiohw
DOXYGEN_DIRS=../../api
SOURCE_INCLUDE_DIRS=../../../lib_xua
SPHINX_MASTER_DOC=lib_xua

View File

@@ -1,4 +1,4 @@
VERSION = 3.5.1
VERSION = 3.4.0
DEBUG ?= 0
@@ -35,7 +35,7 @@ XCC_FLAGS_dfu.xc = $(MODULE_XCC_FLAGS) -Os -mno-dual-issue
XCC_FLAGS_flash_interface.c = $(MODULE_XCC_FLAGS) -Os -mno-dual-issue
XCC_FLAGS_flashlib_user.c = $(MODULE_XCC_FLAGS) -Os -mno-dual-issue
OPTIONAL_HEADERS += xua_conf.h static_hid_report.h
OPTIONAL_HEADERS += xua_conf.h
EXPORT_INCLUDE_DIRS = api \
src/core \
@@ -55,7 +55,6 @@ 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
@@ -71,7 +70,6 @@ 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,8 @@
#include <string.h>
#include <xassert.h>
#include "xua.h"
#include "audiohw.h"
#include "xua.h"
#include "audioports.h"
#include "mic_array_conf.h"
@@ -81,13 +80,21 @@ unsigned dsdMode = DSD_MODE_OFF;
#endif
#include "xua_audiohub_st.h"
static inline void PortOutput(buffered out port:32 p, int bits, int value)
{
if(bits == 32)
p <: value;
else
partout(p, bits, value);
}
static inline int HandleSampleClock(int frameCount, buffered _XUA_CLK_DIR port:32 p_lrclk)
{
#if CODEC_MASTER
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");
@@ -287,6 +294,19 @@ unsigned static AudioHub_MainLoop(chanend ?c_out, chanend ?c_spd_out
else
#endif
{
#if XUA_I2S_DUMMY_SAMPS
if(frameCount == 0)
{
for(int j = 0; j < XUA_I2S_DUMMY_SAMPS; j++)
for(int i = 0; i < I2S_WIRES_DAC; i++)
{
PortOutput(p_i2s_dac[i], XUA_I2S_N_BITS, 0);
}
}
#endif
#if (I2S_CHANS_ADC != 0)
#if (AUD_TO_USB_RATIO > 1)
if (0 == audioToUsbRatioCounter)
@@ -307,7 +327,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)
{
@@ -479,6 +499,25 @@ unsigned static AudioHub_MainLoop(chanend ?c_out, chanend ?c_spd_out
}
#endif
#if XUA_I2S_DUMMY_SAMPS
if(frameCount == 1)
{
int dummyBits;
for(int j = 0; j < XUA_I2S_DUMMY_SAMPS; j++)
{
for(int i = 0; i < I2S_WIRES_ADC; i++)
{
asm volatile("in %0, res[%1]" : "=r"(dummyBits) : "r"(p_i2s_adc[i]));
if(XUA_I2S_N_BITS)
set_port_shift_count(p_i2s_adc[i], XUA_I2S_N_BITS);
}
asm volatile("in %0, res[%1]" : "=r"(dummyBits) : "r"(p_lrclk));
if(XUA_I2S_N_BITS)
set_port_shift_count(p_lrclk, XUA_I2S_N_BITS);
}
}
#endif
#if (I2S_CHANS_ADC != 0 || I2S_CHANS_DAC != 0)
syncError += HandleSampleClock(frameCount, p_lrclk);
#endif
@@ -636,9 +675,6 @@ 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
@@ -666,12 +702,6 @@ 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);
@@ -697,8 +727,6 @@ void XUA_AudioHub(chanend ?c_aud, clock ?clk_audio_mclk, clock ?clk_audio_bclk,
#endif
#endif
/* Perform required CODEC/ADC/DAC initialisation */
AudioHwInit();
@@ -727,7 +755,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 */
{
unsigned numBits = XUA_I2S_N_BITS * I2S_CHANS_PER_FRAME;
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)
@@ -810,19 +844,8 @@ void XUA_AudioHub(chanend ?c_aud, clock ?clk_audio_mclk, clock ?clk_audio_bclk,
curFreq *= 16;
}
#endif
/* 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 */
/* Configure Clocking/CODEC/DAC/ADC for SampleFreq/MClk */
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

@@ -1,4 +1,4 @@
// Copyright 2011-2023 XMOS LIMITED.
// Copyright 2011-2022 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#include "xua.h"
#if XUA_USB_EN
@@ -10,7 +10,7 @@
#include "xud.h"
#include "testct_byref.h"
#if XUA_HID_ENABLED
#if( 0 < HID_CONTROLS )
#include "xua_hid_report.h"
#include "user_hid.h"
#include "xua_hid.h"
@@ -105,11 +105,7 @@ 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
)
{
@@ -138,18 +134,14 @@ void XUA_Buffer(
c_clk_int,
#endif
c_sof, c_aud_ctl, p_off_mclk
#if XUA_HID_ENABLED
#if( 0 < HID_CONTROLS )
, c_hid
#endif
#ifdef CHAN_BUFF_CTRL
, c_buff_ctrl
#endif
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC)
#if(XUA_USE_APP_PLL)
, c_swpll_update
#else
, i_pll_ref
#endif
, i_pll_ref
#endif
);
@@ -198,12 +190,8 @@ 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_USE_APP_PLL)
, chanend c_swpll_update
#else
#if XUA_SYNCMODE == XUA_SYNCMODE_SYNC
, client interface pll_ref_if i_pll_ref
#endif
#endif
)
{
@@ -236,7 +224,7 @@ void XUA_Buffer_Ep(register chanend c_aud_out,
XUD_ep ep_int = XUD_InitEp(c_ep_int);
#endif
#if XUA_HID_ENABLED
#if( 0 < HID_CONTROLS )
XUD_ep ep_hid = XUD_InitEp(c_hid);
#endif
unsigned u_tmp;
@@ -259,8 +247,7 @@ void XUA_Buffer_Ep(register chanend c_aud_out,
#if (NUM_USB_CHAN_IN > 0)
unsigned bufferIn = 1;
#endif
int sofCount = 0;
int pllUpdate = 0;
unsigned sofCount = 0;
unsigned mod_from_last_time = 0;
#ifdef FB_TOLERANCE_TEST
@@ -307,6 +294,7 @@ 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
@@ -344,7 +332,7 @@ void XUA_Buffer_Ep(register chanend c_aud_out,
#endif
#endif
#if XUA_HID_ENABLED
#if( 0 < HID_CONTROLS )
while (!hidIsReportDescriptorPrepared())
;
@@ -369,16 +357,12 @@ 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)
@@ -443,8 +427,7 @@ 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 = 0;
pllUpdate = 0;
sofCount = 1;
clocks = 0;
clockcounter = 0;
mod_from_last_time = 0;
@@ -519,13 +502,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_flag now used to communicate other commands also */
/* Note: freqChange flags 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) && (!XUA_USE_APP_PLL)
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC)
case t_sofCheck when timerafter(timeNextEdge) :> void:
i_pll_ref.toggle();
timeLastEdge = timeNextEdge;
@@ -545,6 +528,7 @@ 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;
@@ -555,27 +539,12 @@ 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
@@ -677,6 +646,7 @@ 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.
@@ -927,8 +897,8 @@ void XUA_Buffer_Ep(register chanend c_aud_out,
#endif
#endif
#if (XUA_HID_ENABLED)
/* HID Report Data */
#if( 0 < HID_CONTROLS )
/* HID Report Data */
case XUD_SetData_Select(c_hid, ep_hid, result):
hid_ready_flag = 0U;
unsigned reportTime;
@@ -941,7 +911,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

@@ -1,457 +0,0 @@
// 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

@@ -1,398 +0,0 @@
// 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

@@ -1,4 +1,4 @@
// Copyright 2015-2023 XMOS LIMITED.
// Copyright 2015-2021 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#ifndef __DESCRIPTOR_DEFS_H__
@@ -33,7 +33,6 @@
#define ENDPOINT_ADDRESS_OUT_MIDI (ENDPOINT_NUMBER_OUT_MIDI)
#define ENDPOINT_ADDRESS_OUT_IAP (ENDPOINT_NUMBER_OUT_IAP)
#define ENDPOINT_ADDRESS_OUT_IAP_EA_NATIVE_TRANS (ENDPOINT_NUMBER_OUT_IAP_EA_NATIVE_TRANS)
#define ENDPOINT_ADDRESS_OUT_HID (ENDPOINT_NUMBER_OUT_HID)
/* Interface numbers enum */
enum USBInterfaceNumber
@@ -61,7 +60,7 @@ enum USBInterfaceNumber
INTERFACE_NUMBER_IAP_EA_NATIVE_TRANS,
#endif
#endif
#if XUA_OR_STATIC_HID_ENABLED
#if( 0 < HID_CONTROLS )
INTERFACE_NUMBER_HID,
#endif
INTERFACE_COUNT /* End marker */
@@ -71,8 +70,4 @@ enum USBInterfaceNumber
#define ENDPOINT_INT_INTERVAL_IN_HID 0x08
#endif
#ifndef ENDPOINT_INT_INTERVAL_OUT_HID
#define ENDPOINT_INT_INTERVAL_OUT_HID 0x08
#endif
#endif

View File

@@ -26,7 +26,7 @@
#include "xc_ptr.h"
#include "xua_ep0_uacreqs.h"
#if XUA_OR_STATIC_HID_ENABLED
#if( 0 < HID_CONTROLS )
#include "hid.h"
#include "xua_hid.h"
#include "xua_hid_report.h"
@@ -442,15 +442,6 @@ void XUA_Endpoint0_setBcdDevice(unsigned short bcd) {
#endif // AUDIO_CLASS == 1}
}
#if defined(__static_hid_report_h_exists__)
#define hidReportDescriptorLength (sizeof(hidReportDescriptorPtr))
static unsigned char hidReportDescriptorPtr[] = {
#include "static_hid_report.h"
};
#endif
void XUA_Endpoint0_init(chanend c_ep0_out, chanend c_ep0_in, NULLABLE_RESOURCE(chanend, c_audioControl),
chanend c_mix_ctl, chanend c_clk_ctl, chanend c_EANativeTransport_ctrl, CLIENT_INTERFACE(i_dfu, dfuInterface) VENDOR_REQUESTS_PARAMS_DEC_)
{
@@ -522,13 +513,11 @@ void XUA_Endpoint0_init(chanend c_ep0_out, chanend c_ep0_in, NULLABLE_RESOURCE(c
#endif // XUA_USB_DESCRIPTOR_OVERWRITE_RATE_RES
#if XUA_OR_STATIC_HID_ENABLED
#if XUA_HID_ENABLED
#if( 0 < HID_CONTROLS )
hidReportInit();
hidPrepareReportDescriptor();
size_t hidReportDescriptorLength = hidGetReportDescriptorLength();
#endif
unsigned char hidReportDescriptorLengthLo = hidReportDescriptorLength & 0xFF;
unsigned char hidReportDescriptorLengthHi = (hidReportDescriptorLength & 0xFF00) >> 8;
@@ -539,7 +528,6 @@ void XUA_Endpoint0_init(chanend c_ep0_out, chanend c_ep0_in, NULLABLE_RESOURCE(c
hidDescriptor[HID_DESCRIPTOR_LENGTH_FIELD_OFFSET ] = hidReportDescriptorLengthLo;
hidDescriptor[HID_DESCRIPTOR_LENGTH_FIELD_OFFSET + 1] = hidReportDescriptorLengthHi;
#endif // 0 < HID_CONTROLS
}
@@ -743,7 +731,7 @@ void XUA_Endpoint0_loop(XUD_Result_t result, USB_SetupPacket_t sp, chanend c_ep0
switch(sp.bRequest)
{
#if XUA_OR_STATIC_HID_ENABLED
#if( 0 < HID_CONTROLS )
case USB_GET_DESCRIPTOR:
/* Check what inteface request is for */
@@ -758,17 +746,15 @@ void XUA_Endpoint0_loop(XUD_Result_t result, USB_SetupPacket_t sp, chanend c_ep0
{
/* Return HID Descriptor */
result = XUD_DoGetRequest(ep0_out, ep0_in, hidDescriptor,
hidDescriptor[0], sp.wLength);
sizeof(hidDescriptor), sp.wLength);
}
break;
case HID_REPORT:
{
/* Return HID report descriptor */
#if XUA_HID_ENABLED
unsigned char* hidReportDescriptorPtr;
hidReportDescriptorPtr = hidGetReportDescriptor();
size_t hidReportDescriptorLength = hidGetReportDescriptorLength();
#endif
result = XUD_DoGetRequest(ep0_out, ep0_in, hidReportDescriptorPtr,
hidReportDescriptorLength, sp.wLength);
}
@@ -872,7 +858,7 @@ void XUA_Endpoint0_loop(XUD_Result_t result, USB_SetupPacket_t sp, chanend c_ep0
}
}
#endif
#if XUA_HID_ENABLED
#if( 0 < HID_CONTROLS )
if (interfaceNum == INTERFACE_NUMBER_HID)
{
result = HidInterfaceClassRequests(ep0_out, ep0_in, &sp);

View File

@@ -481,7 +481,7 @@ USB_Descriptor_Device_t devDesc_Audio2 =
.iManufacturer = offsetof(StringDescTable_t, vendorStr)/sizeof(char *),
.iProduct = offsetof(StringDescTable_t, productStr_Audio2)/sizeof(char *),
.iSerialNumber = offsetof(StringDescTable_t, serialStr)/sizeof(char *),
.bNumConfigurations = 0x01
.bNumConfigurations = 0x02 /* Set to 2 such that windows does not load composite driver */
};
/* Device Descriptor for Null Device */
@@ -787,13 +787,10 @@ typedef struct
#endif
#endif // IAP
#if XUA_OR_STATIC_HID_ENABLED
#if( 0 < HID_CONTROLS )
USB_Descriptor_Interface_t HID_Interface;
USB_HID_Descriptor_t HID_Descriptor;
USB_Descriptor_Endpoint_t HID_In_Endpoint;
#if HID_OUT_REQUIRED
USB_Descriptor_Endpoint_t HID_Out_Endpoint;
#endif
#endif
}__attribute__((packed)) USB_Config_Descriptor_Audio2_t;
@@ -2211,14 +2208,14 @@ USB_Config_Descriptor_Audio2_t cfgDesc_Audio2=
#endif
#endif /* IAP */
#if XUA_OR_STATIC_HID_ENABLED
#if( 0 < HID_CONTROLS )
#include "xua_hid_descriptors.h"
#endif
};
#endif /* (AUDIO_CLASS == 2) */
#if XUA_OR_STATIC_HID_ENABLED
#if( 0 < HID_CONTROLS )
#if (AUDIO_CLASS ==1 )
unsigned char hidDescriptor[] =
{
@@ -2333,14 +2330,14 @@ const unsigned num_freqs_a1 = MAX(3, (0
#define DFU_INTERFACES_A1 0
#endif
#if XUA_OR_STATIC_HID_ENABLED
#if( 0 < HID_CONTROLS )
/*
* The value of HID_INTERFACE_BYTES must match the length of the descriptors defined in
* - xua_hid_descriptor_contents.h
* - xua_hid_endpoint_descriptor_contents.h and
* - xua_hid_interface_descriptor_contents.h
*/
#define HID_INTERFACE_BYTES ( 9 + 9 + (7 * (1 + HID_OUT_REQUIRED))) // always IN
#define HID_INTERFACE_BYTES ( 9 + 9 + 7 )
#define HID_INTERFACES_A1 1
#else
#define HID_INTERFACE_BYTES 0
@@ -2382,7 +2379,7 @@ const unsigned num_freqs_a1 = MAX(3, (0
#endif
#if XUA_OR_STATIC_HID_ENABLED
#if( 0 < HID_CONTROLS )
#define USB_HID_DESCRIPTOR_OFFSET (18 + AC_TOTAL_LENGTH + (INPUT_INTERFACES_A1 * (49 + num_freqs_a1 * 3)) + (OUTPUT_INTERFACES_A1 * (49 + num_freqs_a1 * 3)) + CONTROL_INTERFACE_BYTES + DFU_INTERFACE_BYTES + INTERFACE_DESCRIPTOR_BYTES)
#endif
@@ -2896,7 +2893,7 @@ unsigned char cfgDesc_Audio1[] =
offsetof(StringDescTable_t, ctrlStr)/sizeof(char *), /* 8 iInterface */
#endif
#if XUA_OR_STATIC_HID_ENABLED
#if( 0 < HID_CONTROLS )
#include "xua_hid_descriptors.h"
#endif

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) && (!XUA_USE_APP_PLL))
#if (XUA_SPDIF_RX_EN) || (XUA_ADAT_RX_EN) || (XUA_SYNCMODE == XUA_SYNCMODE_SYNC)
/* Reference to external clock multiplier */
on tile[PLL_REF_TILE] : out port p_pll_ref = PORT_PLL_REF;
#endif
@@ -213,9 +213,6 @@ XUD_EpType epTypeTableOut[ENDPOINT_COUNT_OUT] = { XUD_EPTYPE_CTL | XUD_STATUS_EN
#ifdef MIDI
XUD_EPTYPE_BUL, /* MIDI */
#endif
#if HID_OUT_REQUIRED
XUD_EPTYPE_INT,
#endif
#ifdef IAP
XUD_EPTYPE_BUL, /* iAP */
#ifdef IAP_EA_NATIVE_TRANS
@@ -236,7 +233,7 @@ XUD_EpType epTypeTableIn[ENDPOINT_COUNT_IN] = { XUD_EPTYPE_CTL | XUD_STATUS_ENAB
#ifdef MIDI
XUD_EPTYPE_BUL,
#endif
#if XUA_OR_STATIC_HID_ENABLED
#if( 0 < HID_CONTROLS )
XUD_EPTYPE_INT,
#endif
#ifdef IAP
@@ -270,6 +267,115 @@ void xscope_user_init()
}
#endif
#if XUA_USB_EN
/* Core USB Audio functions - must be called on the Tile connected to the USB Phy */
void usb_audio_core(chanend c_mix_out
#ifdef MIDI
, chanend c_midi
#endif
#if (MIXER)
, chanend c_mix_ctl
#endif
, chanend ?c_clk_int
, chanend ?c_clk_ctl
, client interface i_dfu ?dfuInterface
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC)
, client interface pll_ref_if i_pll_ref
#endif
VENDOR_REQUESTS_PARAMS_DEC_
)
{
chan c_sof;
chan c_xud_out[ENDPOINT_COUNT_OUT]; /* Endpoint channels for XUD */
chan c_xud_in[ENDPOINT_COUNT_IN];
chan c_aud_ctl;
#if (!MIXER)
#define c_mix_ctl null
#endif
#ifdef IAP_EA_NATIVE_TRANS
chan c_EANativeTransport_ctrl;
#else
#define c_EANativeTransport_ctrl null
#endif
par
{
{
#ifdef XUD_PRIORITY_HIGH
set_core_high_priority_on();
#endif
/* Run UAC2.0 at high-speed, UAC1.0 at full-speed */
unsigned usbSpeed = (AUDIO_CLASS == 2) ? XUD_SPEED_HS : XUD_SPEED_FS;
unsigned xudPwrCfg = (XUA_POWERMODE == XUA_POWERMODE_SELF) ? XUD_PWR_SELF : XUD_PWR_BUS;
/* USB interface core */
XUD_Main(c_xud_out, ENDPOINT_COUNT_OUT, c_xud_in, ENDPOINT_COUNT_IN,
c_sof, epTypeTableOut, epTypeTableIn, usbSpeed, xudPwrCfg);
}
{
unsigned x;
thread_speed();
/* Attach mclk count port to mclk clock-block (for feedback) */
//set_port_clock(p_for_mclk_count, clk_audio_mclk);
#if(AUDIO_IO_TILE != XUD_TILE)
set_clock_src(clk_audio_mclk_usb, p_mclk_in_usb);
set_port_clock(p_for_mclk_count, clk_audio_mclk_usb);
start_clock(clk_audio_mclk_usb);
#else
/* Clock port from same clock-block as I2S */
/* TODO remove asm() */
asm("ldw %0, dp[clk_audio_mclk]":"=r"(x));
asm("setclk res[%0], %1"::"r"(p_for_mclk_count), "r"(x));
#endif
/* Endpoint & audio buffering cores */
XUA_Buffer(c_xud_out[ENDPOINT_NUMBER_OUT_AUDIO],/* Audio Out*/
#if (NUM_USB_CHAN_IN > 0)
c_xud_in[ENDPOINT_NUMBER_IN_AUDIO], /* Audio In */
#endif
#if (NUM_USB_CHAN_IN == 0) || defined(UAC_FORCE_FEEDBACK_EP)
c_xud_in[ENDPOINT_NUMBER_IN_FEEDBACK], /* Audio FB */
#endif
#ifdef MIDI
c_xud_out[ENDPOINT_NUMBER_OUT_MIDI], /* MIDI Out */ // 2
c_xud_in[ENDPOINT_NUMBER_IN_MIDI], /* MIDI In */ // 4
c_midi,
#endif
#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
/* Audio Interrupt - only used for interrupts on external clock change */
c_xud_in[ENDPOINT_NUMBER_IN_INTERRUPT],
c_clk_int,
#endif
c_sof, c_aud_ctl, p_for_mclk_count
#if (HID_CONTROLS)
, c_xud_in[ENDPOINT_NUMBER_IN_HID]
#endif
, c_mix_out
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC)
, i_pll_ref
#endif
);
//:
}
/* Endpoint 0 Core */
{
thread_speed();
XUA_Endpoint0( c_xud_out[0], c_xud_in[0], c_aud_ctl, c_mix_ctl, c_clk_ctl, c_EANativeTransport_ctrl, dfuInterface VENDOR_REQUESTS_PARAMS_);
}
//:
}
}
#endif /* XUA_USB_EN */
#if (XUA_SPDIF_TX_EN) && (SPDIF_TX_TILE != AUDIO_IO_TILE)
void SpdifTxWrapper(chanend c_spdif_tx)
{
@@ -314,9 +420,6 @@ 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)
@@ -367,9 +470,6 @@ 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
@@ -473,36 +573,17 @@ int main()
#endif
#endif
#if (((XUA_SYNCMODE == XUA_SYNCMODE_SYNC) && !XUA_USE_APP_PLL) || XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
#if ((XUA_SYNCMODE == XUA_SYNCMODE_SYNC) || 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];
chan c_aud_ctl;
#if (!MIXER)
#define c_mix_ctl null
#endif
#ifdef IAP_EA_NATIVE_TRANS
chan c_EANativeTransport_ctrl;
#else
#define c_EANativeTransport_ctrl null
#endif
USER_MAIN_DECLARATIONS
par
{
USER_MAIN_CORES
#if (((XUA_SYNCMODE == XUA_SYNCMODE_SYNC) && XYA_USE_APP_PLL) || XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
#if ((XUA_SYNCMODE == XUA_SYNCMODE_SYNC) || 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]:
@@ -516,91 +597,30 @@ int main()
#endif
#endif
#if XUA_USB_EN
/* Core USB task, buffering, USB etc */
{
#ifdef XUD_PRIORITY_HIGH
set_core_high_priority_on();
#endif
/* Run UAC2.0 at high-speed, UAC1.0 at full-speed */
unsigned usbSpeed = (AUDIO_CLASS == 2) ? XUD_SPEED_HS : XUD_SPEED_FS;
unsigned xudPwrCfg = (XUA_POWERMODE == XUA_POWERMODE_SELF) ? XUD_PWR_SELF : XUD_PWR_BUS;
/* USB interface core */
XUD_Main(c_xud_out, ENDPOINT_COUNT_OUT, c_xud_in, ENDPOINT_COUNT_IN,
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;
thread_speed();
/* Attach mclk count port to mclk clock-block (for feedback) */
//set_port_clock(p_for_mclk_count, clk_audio_mclk);
#if(AUDIO_IO_TILE != XUD_TILE)
set_clock_src(clk_audio_mclk_usb, p_mclk_in_usb);
set_port_clock(p_for_mclk_count, clk_audio_mclk_usb);
start_clock(clk_audio_mclk_usb);
#else
/* Clock port from same clock-block as I2S */
/* TODO remove asm() */
asm("ldw %0, dp[clk_audio_mclk]":"=r"(x));
asm("setclk res[%0], %1"::"r"(p_for_mclk_count), "r"(x));
#endif
/* Endpoint & audio buffering cores */
XUA_Buffer(c_xud_out[ENDPOINT_NUMBER_OUT_AUDIO],/* Audio Out*/
#if (NUM_USB_CHAN_IN > 0)
c_xud_in[ENDPOINT_NUMBER_IN_AUDIO], /* Audio In */
#endif
#if (NUM_USB_CHAN_IN == 0) || defined(UAC_FORCE_FEEDBACK_EP)
c_xud_in[ENDPOINT_NUMBER_IN_FEEDBACK], /* Audio FB */
#endif
usb_audio_core(c_mix_out
#ifdef MIDI
c_xud_out[ENDPOINT_NUMBER_OUT_MIDI], /* MIDI Out */ // 2
c_xud_in[ENDPOINT_NUMBER_IN_MIDI], /* MIDI In */ // 4
c_midi,
, c_midi
#endif
#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
/* Audio Interrupt - only used for interrupts on external clock change */
c_xud_in[ENDPOINT_NUMBER_IN_INTERRUPT],
c_clk_int,
#ifdef IAP
, c_iap
#ifdef IAP_EA_NATIVE_TRANS
, c_ea_data
#endif
c_sof, c_aud_ctl, p_for_mclk_count
#if (XUA_HID_ENABLED)
, c_xud_in[ENDPOINT_NUMBER_IN_HID]
#endif
, c_mix_out
#if (MIXER)
, c_mix_ctl
#endif
, c_clk_int, c_clk_ctl, dfuInterface
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC)
#if (!XUA_USE_APP_PLL)
, i_pll_ref
#else
, c_swpll_update
#endif
, i_pll_ref
#endif
);
//:
}
/* Endpoint 0 Core */
{
thread_speed();
XUA_Endpoint0( c_xud_out[0], c_xud_in[0], c_aud_ctl, c_mix_ctl, c_clk_ctl, c_EANativeTransport_ctrl, dfuInterface VENDOR_REQUESTS_PARAMS_);
}
VENDOR_REQUESTS_PARAMS_
);
#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 */
@@ -623,9 +643,6 @@ 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

@@ -1,29 +0,0 @@
// 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

@@ -1,54 +0,0 @@
// 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,51 +1,30 @@
// Copyright 2011-2023 XMOS LIMITED.
// Copyright 2011-2021 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 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.
*/
/**
* @brief User stream start code
/* Functions that handle functions that must occur on stream start/stop e.g. DAC mute/un-mute
*
* User code to perform any actions required at every stream start - either input or output
*/
* THESE NEED IMPLEMENTING FOR A SPECIFIC DESIGN
*
* */
/* Any actions required for stream start e.g. DAC un-mute - run every stream start */
void UserAudioStreamStart(void);
/**
* @brief User stream stop code
*
* User code to perform any actions required on every stream stop - either input or output*/
/* Any actions required on stream stop e.g. DAC mute - run every steam stop */
void UserAudioStreamStop(void);
/**
* @brief User input stream stop code
*
* User code to perform any actions required on input stream start i.e. device to host
*/
/* Any actions required on input stream start */
void UserAudioInputStreamStart(void);
/**
* @brief User input stream stop code
*
* User code to perform any actions required on input stream stop i.e. device to host
*/
/* Any actions required on input stream stop */
void UserAudioInputStreamStop(void);
/**
* @brief User output stream start code
*
* User code to perform any actions required on output stream start i.e. host to device
*/
/* Any actions required on output stream start */
void UserAudioOutputStreamStart(void);
/**
* @brief User output stream stop code
*
* User code to perfrom any actions required on output stream stop i.e. host to device
*/
/* Any actions required on output stream stop */
void UserAudioOutputStreamStop(void);
#endif

View File

@@ -1,17 +1,17 @@
// Copyright 2013-2023 XMOS LIMITED.
// Copyright 2013-2021 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
/**
* @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,16 +34,22 @@ typedef struct hidEvent_t {
#define HID_MAX_DATA_BYTES ( 4 )
#define HID_EVENT_INVALID_ID ( 0x100 )
#if( 0 < HID_CONTROLS )
/**
* \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
@@ -55,4 +61,21 @@ size_t UserHIDGetData( const unsigned id, unsigned char hidData[ HID_MAX_DATA_BY
*/
void UserHIDInit( void );
#endif /* _USER_HID_H_ */
/**
* \brief Record that a HID event has occurred
*
* \param[in] hidEvent A list of events which have occurred.
* Each element specifies a HID Report ID, a bit and byte
* within the HID Report and the value for it.
* Set the Report ID to zero if not using Report IDs
* (see 5.6, 6.2.2.7, 8.1 and 8.2).
* \param[in] hidEventCnt The length of the \a hidEvent list.
*
* \returns The index of the first unrecorded event in \a hidEvent
* \retval Zero indicates no events were recorded
* \retval \a hidEventCnt indicates all events were recorded
*/
size_t UserHIDRecordEvent( const hidEvent_t hidEvent[], const size_t hidEventCnt );
#endif /* ( 0 < HID_CONTROLS ) */
#endif /* __USER_HID_H__ */

View File

@@ -1,12 +1,4 @@
// Copyright 2013-2023 XMOS LIMITED.
// Copyright 2013-2021 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

@@ -1,4 +1,4 @@
// Copyright 2019-2023 XMOS LIMITED.
// Copyright 2019-2022 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#include <stdint.h>
#include <xs1.h>
@@ -13,7 +13,7 @@
#define DEBUG_PRINT_ENABLE_HID_XC 0
#include "debug_print.h"
#if XUA_HID_ENABLED
#if( 0 < HID_CONTROLS )
static unsigned HidCalcNewReportTime( const unsigned currentPeriod, const unsigned reportTime, const unsigned reportToSetIdleInterval, const unsigned newPeriod );
static unsigned HidCalcReportToSetIdleInterval( const unsigned reportTime );
static unsigned HidFindSetIdleActivationPoint( const unsigned currentPeriod, const unsigned timeWithinPeriod );

View File

@@ -1,7 +1,7 @@
// Copyright 2021-2023 XMOS LIMITED.
// Copyright 2021-2022 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#include "xua_conf_full.h"
#if XUA_HID_ENABLED
#if( 0 < HID_CONTROLS )
#include <assert.h>
#include <stddef.h>

View File

@@ -1,4 +1,4 @@
// Copyright 2021-2023 XMOS LIMITED.
// Copyright 2021 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
/**
@@ -31,19 +31,6 @@
HID_ENDPOINT_DESCRIPTOR_PACKET_SIZE_HI, /* 5 wMaxPacketSize */
ENDPOINT_INT_INTERVAL_IN_HID, /* 6 bInterval */
#if (HID_OUT_REQUIRED)
/* HID Endpoint descriptor (OUT) */
HID_ENDPOINT_DESCRIPTOR_LENGTH, /* 0 bLength */
HID_ENDPOINT_DESCRIPTOR_TYPE, /* 1 bDescriptorType */
ENDPOINT_ADDRESS_OUT_HID, /* 2 bEndpointAddress */
HID_ENDPOINT_ATTRIBUTES, /* 3 bmAttributes (INTERRUPT) */
HID_ENDPOINT_DESCRIPTOR_PACKET_SIZE_LO, /* 4 wMaxPacketSize */
HID_ENDPOINT_DESCRIPTOR_PACKET_SIZE_HI, /* 5 wMaxPacketSize */
ENDPOINT_INT_INTERVAL_OUT_HID, /* 6 bInterval */
#endif
#elif (AUDIO_CLASS == 2)
.HID_In_Endpoint =
@@ -57,21 +44,6 @@
.bInterval = ENDPOINT_INT_INTERVAL_IN_HID,
},
#if (HID_OUT_REQUIRED)
.HID_Out_Endpoint =
{
/* Endpoint descriptor (OUT) */
.bLength = sizeof(USB_Descriptor_Endpoint_t),
.bDescriptorType = HID_ENDPOINT_DESCRIPTOR_TYPE,
.bEndpointAddress = ENDPOINT_ADDRESS_OUT_HID,
.bmAttributes = HID_ENDPOINT_ATTRIBUTES,
.wMaxPacketSize = HID_ENDPOINT_DESCRIPTOR_PACKET_SIZE_LO,
.bInterval = ENDPOINT_INT_INTERVAL_OUT_HID,
},
#endif
#else
#error "Unknown Audio Class"
#endif

View File

@@ -1,4 +1,4 @@
// Copyright 2021-2023 XMOS LIMITED.
// Copyright 2021 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
/**
@@ -15,8 +15,7 @@
#define HID_INTERFACE_DESCRIPTOR_LENGTH ( 0x09 ) /* Size of descriptor in Bytes */
#define HID_INTERFACE_DESCRIPTOR_TYPE ( 0x04 ) /* Interface 0x04 */
#define HID_INTERFACE_ALTERNATE_SETTING ( 0x00 ) /* Value used alternate interfaces using SetInterface Request */
#define HID_INTERFACE_NUMBER_OF_ENDPOINTS ( 0x01 + HID_OUT_REQUIRED )
/* Number of endpoints for this interface (excluding 0) */
#define HID_INTERFACE_NUMBER_OF_ENDPOINTS ( 0x01 ) /* Number of endpoitns for this interface (excluding 0) */
#define HID_INTERFACE_CLASS ( 0x03 )
#define HID_INTERFACE_SUBCLASS ( 0x00 ) /* No boot device */
#define HID_INTERFACE_PROTOCOL ( 0x00 )

View File

@@ -1,6 +1,7 @@
// Copyright 2016-2023 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#ifdef SIMULATION
#include "xua.h"
#include <platform.h>
#include <print.h>
@@ -45,7 +46,7 @@ void slave_mode_clk_setup(const unsigned samFreq, const unsigned chans_per_frame
const unsigned mclk_freq = 24576000;
const unsigned mclk_bclk_ratio = mclk_freq / (chans_per_frame * samFreq * data_bits);
const unsigned bclk_lrclk_ratio = (chans_per_frame * data_bits); // 48.828Hz LRCLK
const unsigned bclk_lrclk_ratio = (chans_per_frame * data_bits + (data_bits * XUA_I2S_DUMMY_SAMPS)); // 48.828Hz LRCLK
//bclk
configure_clock_src_divide(clk_audio_bclk_gen, p_mclk_gen, mclk_bclk_ratio/2);

View File

@@ -3,12 +3,10 @@ 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