forked from PAWPAW-Mirror/lib_xua
Compare commits
157 Commits
v3.3.0
...
experiment
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dd8d2675d3 | ||
|
|
7930a5d59c | ||
|
|
158d79335c | ||
|
|
ebc09e1c4f | ||
|
|
a7943a8859 | ||
|
|
77fad35497 | ||
|
|
50966dda90 | ||
|
|
e7b5faed66 | ||
|
|
7f72c4b842 | ||
|
|
d119755313 | ||
|
|
2228575e09 | ||
|
|
b6972295e9 | ||
|
|
39802f3620 | ||
|
|
5bf53fa453 | ||
|
|
2f11eda7d8 | ||
|
|
1574137dda | ||
|
|
c7e782179c | ||
|
|
badcb71c80 | ||
|
|
dff72573f8 | ||
|
|
aaaf1e9652 | ||
|
|
d6b23cf960 | ||
|
|
fa8329edaa | ||
|
|
83d86e885f | ||
|
|
b1b28f1005 | ||
|
|
6d41cfcbea | ||
|
|
5404127dbf | ||
|
|
e5a270347a | ||
|
|
f509a12e7d | ||
|
|
4528bed740 | ||
|
|
e812ca3e8b | ||
|
|
2accc0429f | ||
|
|
36d5201365 | ||
|
|
cea580ba48 | ||
|
|
6815f12a90 | ||
|
|
799ad7ba86 | ||
|
|
3d7e66bdc0 | ||
|
|
a6387d5fef | ||
|
|
5ca0738b02 | ||
|
|
b0e732110d | ||
|
|
1702078e7c | ||
|
|
136ec2506c | ||
|
|
45e5ef7702 | ||
|
|
1ef5129fde | ||
|
|
b1fe49aff3 | ||
|
|
d3ad29e8a6 | ||
|
|
17944ad908 | ||
|
|
131dd252c0 | ||
|
|
23d043630f | ||
|
|
761a33f5e4 | ||
|
|
12ec1d7536 | ||
|
|
2dba6dce36 | ||
|
|
9cf931898e | ||
|
|
9b104af8cf | ||
|
|
c469dd6cde | ||
|
|
b238196f74 | ||
|
|
e9586b59d3 | ||
|
|
6d168b3209 | ||
|
|
d301fef6d7 | ||
|
|
1f4e9a99b8 | ||
|
|
981ea78be7 | ||
|
|
6cee90d876 | ||
|
|
79d14f8b59 | ||
|
|
05dcb8f3ab | ||
|
|
4e7ddb4036 | ||
|
|
e8fcc80415 | ||
|
|
71a657dc9a | ||
|
|
ccfca90451 | ||
|
|
cb379f5bfb | ||
|
|
e2c36a9a95 | ||
|
|
7e3ae59acc | ||
|
|
f1f453921b | ||
|
|
7703fc1a7d | ||
|
|
53a65344fc | ||
|
|
3b2814f8cb | ||
|
|
55a62cf589 | ||
|
|
4a84c3e1ec | ||
|
|
b17f585004 | ||
|
|
57593bfea3 | ||
|
|
8dc77090bf | ||
|
|
9c20fab216 | ||
|
|
cf1940245f | ||
|
|
837b648bbc | ||
|
|
c1159143ea | ||
|
|
2964861b70 | ||
|
|
208491fe51 | ||
|
|
3fe4593b52 | ||
|
|
49a116c705 | ||
|
|
eee5b474a0 | ||
|
|
4655a07542 | ||
|
|
c578bb92d5 | ||
|
|
d5a614df55 | ||
|
|
495140ab8d | ||
|
|
f53c1bab09 | ||
|
|
0c6d947e67 | ||
|
|
ee271e3769 | ||
|
|
950beb55cb | ||
|
|
ca3276792a | ||
|
|
e26b934233 | ||
|
|
51629dba24 | ||
|
|
c5e944d73d | ||
|
|
22a3d5e043 | ||
|
|
58f691078d | ||
|
|
f80d7647e0 | ||
|
|
fe697929bc | ||
|
|
b265ccd8bf | ||
|
|
6c2e7e3042 | ||
|
|
15ca5ec281 | ||
|
|
71aa64425d | ||
|
|
9080990234 | ||
|
|
6d8cf9913f | ||
|
|
60040de58f | ||
|
|
27a59ab3bc | ||
|
|
317e27e421 | ||
|
|
035c20e01c | ||
|
|
ef97d667de | ||
|
|
0e07dc29bc | ||
|
|
43f77c177d | ||
|
|
6754f812c9 | ||
|
|
fc732b8512 | ||
|
|
39ed235476 | ||
|
|
0d7224bd6d | ||
|
|
fd4dfd40a9 | ||
|
|
3d50c96595 | ||
|
|
379e8eb54c | ||
|
|
63763cf4f5 | ||
|
|
b18c34fb0f | ||
|
|
64d65afeaf | ||
|
|
7a47d70229 | ||
|
|
ce8e5a6dbb | ||
|
|
bbed806aab | ||
|
|
9af31b8c70 | ||
|
|
73955c1a4c | ||
|
|
cffd35d146 | ||
|
|
ab535e0fb3 | ||
|
|
17b039dce8 | ||
|
|
7a0d0e1f97 | ||
|
|
2f31260612 | ||
|
|
9922190450 | ||
|
|
0ce91bec90 | ||
|
|
2404eaf35f | ||
|
|
8966ad1bb9 | ||
|
|
513761ef5b | ||
|
|
da7c45500d | ||
|
|
395c88cb22 | ||
|
|
94e58edfaf | ||
|
|
9f00f9159a | ||
|
|
785a857ca8 | ||
|
|
3130088c91 | ||
|
|
c51ee0c460 | ||
|
|
17ed636a74 | ||
|
|
0db1b08948 | ||
|
|
9c460f753f | ||
|
|
6a9537fb69 | ||
|
|
abfa3a2011 | ||
|
|
a1946f340a | ||
|
|
28be17282f | ||
|
|
a1082b1dfd |
56
.gitignore
vendored
56
.gitignore
vendored
@@ -1,29 +1,25 @@
|
|||||||
*.log
|
# XMOS bin files
|
||||||
*.dSYM
|
|
||||||
*/.build_*/*
|
|
||||||
*/bin/*
|
|
||||||
*.o
|
|
||||||
*.xe
|
*.xe
|
||||||
*.vcd
|
*.bin
|
||||||
*.swo
|
*/bin/*
|
||||||
|
|
||||||
|
# XMOS temp files
|
||||||
|
.build*
|
||||||
|
*.a
|
||||||
|
_build*
|
||||||
|
*.i
|
||||||
*.s
|
*.s
|
||||||
*.xi
|
*.xi
|
||||||
*.i
|
*.o
|
||||||
*.bin
|
*/.build_*/*
|
||||||
*~
|
|
||||||
*.a
|
# Temp files
|
||||||
*.swp
|
|
||||||
*.*~
|
|
||||||
*.pyc
|
|
||||||
.build*
|
|
||||||
.DS_Store
|
.DS_Store
|
||||||
test_results.csv
|
*.*~
|
||||||
_build*
|
*.swp
|
||||||
**/.venv/**
|
*.swn
|
||||||
**/.vscode/**
|
*~
|
||||||
**.egg-info
|
*.swo
|
||||||
*.pdf
|
|
||||||
*tests/logs/*
|
|
||||||
|
|
||||||
# waf build files
|
# waf build files
|
||||||
.lock-waf_*
|
.lock-waf_*
|
||||||
@@ -36,3 +32,19 @@ xscope.xmt
|
|||||||
# Traces
|
# Traces
|
||||||
*.gtkw
|
*.gtkw
|
||||||
*.vcd
|
*.vcd
|
||||||
|
|
||||||
|
# Host binaries
|
||||||
|
host_usb_mixer_control/xmos_mixer
|
||||||
|
|
||||||
|
# Documentation build
|
||||||
|
*.pdf
|
||||||
|
|
||||||
|
# Misc
|
||||||
|
*.log
|
||||||
|
*.dSYM
|
||||||
|
*.vcd
|
||||||
|
*.pyc
|
||||||
|
**/.venv/**
|
||||||
|
**/.vscode/**
|
||||||
|
**.egg-info
|
||||||
|
*tests/logs/*
|
||||||
|
|||||||
@@ -1,6 +1,63 @@
|
|||||||
lib_xua Change Log
|
lib_xua Change Log
|
||||||
==================
|
==================
|
||||||
|
|
||||||
|
3.5.1
|
||||||
|
-----
|
||||||
|
|
||||||
|
* FIXED: Respect I2S_CHANS_PER_FRAME when calculating bit-clock rates
|
||||||
|
|
||||||
|
* Changes to dependencies:
|
||||||
|
|
||||||
|
- lib_spdif: 5.0.0 -> 5.0.1
|
||||||
|
|
||||||
|
3.5.0
|
||||||
|
-----
|
||||||
|
|
||||||
|
* 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)
|
||||||
|
* 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
|
||||||
|
-----
|
||||||
|
|
||||||
|
* ADDED: Unit tests for mixer functionality
|
||||||
|
* ADDED: Host mixer control applications (for Win/macOS)
|
||||||
|
* CHANGED: Small tidies to mixer implementation
|
||||||
|
* CHANGED: Improved mixer control channel communication protocol to avoid
|
||||||
|
deadlock situations
|
||||||
|
* CHANGED: By default, output volume processing occurs in mixer task, if
|
||||||
|
present. Previously occurred in decouple task
|
||||||
|
* CHANGED: Some optimisations in sample transfer from decouple task
|
||||||
|
* FIXED: Exception on startup when USB input disabled
|
||||||
|
* FIXED: Full 32bit volume processing only applied when required
|
||||||
|
* FIXED: Setting OUT_VOLUME_AFTER_MIX to zero now has the expected effect
|
||||||
|
|
||||||
|
* Changes to dependencies:
|
||||||
|
|
||||||
|
- lib_xud: 2.2.1 -> 2.2.2
|
||||||
|
|
||||||
|
3.3.1
|
||||||
|
-----
|
||||||
|
|
||||||
|
* CHANGED: Documentation updates
|
||||||
|
|
||||||
|
* Changes to dependencies:
|
||||||
|
|
||||||
|
- lib_spdif: 4.1.0 -> 4.2.1
|
||||||
|
|
||||||
3.3.0
|
3.3.0
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
|||||||
22
Jenkinsfile
vendored
22
Jenkinsfile
vendored
@@ -1,4 +1,4 @@
|
|||||||
@Library('xmos_jenkins_shared_library@v0.18.0') _
|
@Library('xmos_jenkins_shared_library@v0.24.0') _
|
||||||
|
|
||||||
getApproval()
|
getApproval()
|
||||||
|
|
||||||
@@ -24,7 +24,7 @@ pipeline {
|
|||||||
}
|
}
|
||||||
stage('Library checks') {
|
stage('Library checks') {
|
||||||
steps {
|
steps {
|
||||||
xcoreLibraryChecks("${REPO}")
|
xcoreLibraryChecks("${REPO}", false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stage('Testing') {
|
stage('Testing') {
|
||||||
@@ -106,6 +106,12 @@ pipeline {
|
|||||||
dir("${REPO}/${REPO}/host/xmosdfu") {
|
dir("${REPO}/${REPO}/host/xmosdfu") {
|
||||||
sh 'make -f Makefile.OSX64'
|
sh 'make -f Makefile.OSX64'
|
||||||
}
|
}
|
||||||
|
dir("${REPO}/host_usb_mixer_control") {
|
||||||
|
sh 'make -f Makefile.OSX'
|
||||||
|
sh 'mkdir OSX/x86'
|
||||||
|
sh 'mv xmos_mixer OSX/x86/xmos_mixer'
|
||||||
|
archiveArtifacts artifacts: "OSX/x86/xmos_mixer", fingerprint: true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
post {
|
post {
|
||||||
cleanup {
|
cleanup {
|
||||||
@@ -139,7 +145,17 @@ pipeline {
|
|||||||
dir("${REPO}") {
|
dir("${REPO}") {
|
||||||
checkout scm
|
checkout scm
|
||||||
dir("${REPO}/host/xmosdfu") {
|
dir("${REPO}/host/xmosdfu") {
|
||||||
runVS('nmake /f Makefile.Win32')
|
withVS("vcvars32.bat") {
|
||||||
|
bat "nmake /f Makefile.Win32"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dir("host_usb_mixer_control") {
|
||||||
|
withVS() {
|
||||||
|
bat 'msbuild host_usb_mixer_control.vcxproj /property:Configuration=Release /property:Platform=x64'
|
||||||
|
}
|
||||||
|
bat 'mkdir Win\\x64'
|
||||||
|
bat 'mv bin/Release/x64/host_usb_mixer_control.exe Win/x64/xmos_mixer.exe'
|
||||||
|
archiveArtifacts artifacts: "Win/x64/xmos_mixer.exe", fingerprint: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
59
README.rst
59
README.rst
@@ -1,20 +1,19 @@
|
|||||||
lib_xua
|
lib_xua
|
||||||
=======
|
#######
|
||||||
|
|
||||||
:Latest release: 3.3.0
|
|
||||||
|
|
||||||
|
|
||||||
|
:Version: 3.5.0
|
||||||
|
:Vendor: XMOS
|
||||||
:Scope: General Use
|
:Scope: General Use
|
||||||
|
|
||||||
Summary
|
Summary
|
||||||
-------
|
*******
|
||||||
|
|
||||||
lib_xua contains shared components for use in the XMOS USB Audio (XUA) Reference Designs.
|
lib_xua contains shared components for use in the XMOS USB Audio (XUA) Reference Designs.
|
||||||
|
|
||||||
These components enable the development of USB Audio devices on the XMOS xCORE architecture.
|
These components enable the development of USB Audio devices on the XMOS xCORE architecture.
|
||||||
|
|
||||||
Features
|
Features
|
||||||
~~~~~~~~
|
========
|
||||||
|
|
||||||
Key features of the various components in this repository are as follows
|
Key features of the various components in this repository are as follows
|
||||||
|
|
||||||
@@ -40,9 +39,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)
|
- Synchronisation to external digital streams i.e. S/PDIF or ADAT (when in asynchronous mode)
|
||||||
|
|
||||||
- I2S slave & master modes
|
- I2S (slave/master modes with configurable word-length)
|
||||||
|
|
||||||
- TDM slave & master modes
|
- TDM (slave/master modes with configurable word-length)
|
||||||
|
|
||||||
- MIDI input/output (Compliant to USB Class Specification for MIDI devices)
|
- MIDI input/output (Compliant to USB Class Specification for MIDI devices)
|
||||||
|
|
||||||
@@ -52,11 +51,13 @@ Key features of the various components in this repository are as follows
|
|||||||
|
|
||||||
- Simple playback controls via USB Human Interface Device (HID) Class
|
- 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.
|
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.
|
Some features may also require specific host driver support.
|
||||||
|
|
||||||
Host System Requirements
|
Host System Requirements
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
========================
|
||||||
|
|
||||||
USB Audio devices built using `lib_xua` have the following host system requirements.
|
USB Audio devices built using `lib_xua` have the following host system requirements.
|
||||||
|
|
||||||
@@ -69,27 +70,33 @@ USB Audio devices built using `lib_xua` have the following host system requireme
|
|||||||
Older versions of Windows are not guaranteed to operate as expected. Devices are also expected to operate with various Linux distributions including mobile variants.
|
Older versions of Windows are not guaranteed to operate as expected. Devices are also expected to operate with various Linux distributions including mobile variants.
|
||||||
|
|
||||||
Related Application Notes
|
Related Application Notes
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
=========================
|
||||||
|
|
||||||
The following application notes use this library:
|
The following application notes use this library:
|
||||||
|
|
||||||
* AN000246 - Simple USB Audio Device using lib_xua
|
* AN000246 - Simple USB Audio Device using lib_xua
|
||||||
* AN000247 - Using lib_xua with lib_spdif (transmit)
|
* AN000247 - Using lib_xua with lib_spdif (transmit)
|
||||||
* AN000248 - Using lib_xua with lib_mic_array
|
* AN000248 - Using lib_xua with lib_mic_array
|
||||||
|
|
||||||
Required software (dependencies)
|
Required Software (dependencies)
|
||||||
================================
|
================================
|
||||||
|
|
||||||
* lib_locks (git@github.com:xmos/lib_locks.git)
|
* lib_locks (www.github.com/xmos/lib_locks)
|
||||||
* lib_logging (git@github.com:xmos/lib_logging.git)
|
* lib_logging (www.github.com/xmos/lib_logging)
|
||||||
* lib_mic_array (git@github.com:xmos/lib_mic_array.git)
|
* lib_mic_array (www.github.com/xmos/lib_mic_array)
|
||||||
* lib_xassert (git@github.com:xmos/lib_xassert.git)
|
* lib_xassert (www.github.com/xmos/lib_xassert)
|
||||||
* lib_dsp (git@github.com:xmos/lib_dsp)
|
* lib_dsp (www.github.com/xmos/lib_dsp)
|
||||||
* lib_i2c (git@github.com:xmos/lib_i2c.git)
|
* lib_spdif (www.github.com/xmos/lib_spdif)
|
||||||
* lib_i2s (git@github.com:xmos/lib_i2s.git)
|
* lib_xud (www.github.com/xmos/lib_xud)
|
||||||
* lib_gpio (git@github.com:xmos/lib_gpio.git)
|
* lib_adat (www.github.com/xmos/lib_adat)
|
||||||
* lib_mic_array_board_support (git@github.com:xmos/lib_mic_array_board_support.git)
|
|
||||||
* lib_spdif (git@github.com:xmos/lib_spdif.git)
|
Documentation
|
||||||
* lib_xud (git@github.com:xmos/lib_xud.git)
|
=============
|
||||||
* lib_adat (git@github.com:xmos/lib_adat)
|
|
||||||
|
You can find the documentation for this software in the /doc directory of the package.
|
||||||
|
|
||||||
|
Support
|
||||||
|
=======
|
||||||
|
|
||||||
|
This package is supported by XMOS Ltd. Issues can be raised against the software at: http://www.xmos.com/support
|
||||||
|
|
||||||
|
|||||||
@@ -21,4 +21,3 @@ USED_MODULES = lib_xua lib_xud lib_i2c
|
|||||||
|
|
||||||
XMOS_MAKE_PATH ?= ../..
|
XMOS_MAKE_PATH ?= ../..
|
||||||
include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.common
|
include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.common
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
// Copyright 2017-2022 XMOS LIMITED.
|
// Copyright 2017-2023 XMOS LIMITED.
|
||||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||||
#include <xs1.h>
|
#include <xs1.h>
|
||||||
#include <platform.h>
|
#include <platform.h>
|
||||||
#include "xua.h"
|
#include "xua.h"
|
||||||
#include "../../shared/apppll.h"
|
|
||||||
|
|
||||||
on tile[0]: out port p_ctrl = XS1_PORT_8D;
|
on tile[0]: out port p_ctrl = XS1_PORT_8D;
|
||||||
|
|
||||||
@@ -35,11 +34,6 @@ void ctrlPort()
|
|||||||
void AudioHwInit()
|
void AudioHwInit()
|
||||||
{
|
{
|
||||||
/* Wait for power supply to come up */
|
/* 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);
|
delay_milliseconds(100);
|
||||||
|
|
||||||
/* DAC setup: For basic I2S input we don't need any register setup. DACs will clock auto detect etc.
|
/* DAC setup: For basic I2S input we don't need any register setup. DACs will clock auto detect etc.
|
||||||
@@ -48,9 +42,12 @@ void AudioHwInit()
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Configures the external audio hardware for the required sample frequency */
|
/* Configures the external audio hardware for the required sample frequency
|
||||||
|
* Note, the application PLL in xcore.ai will be configured to the correct master clock frequency
|
||||||
|
* by lib_xua
|
||||||
|
*/
|
||||||
void AudioHwConfig(unsigned samFreq, unsigned mClk, unsigned dsdMode, unsigned sampRes_DAC, unsigned sampRes_ADC)
|
void AudioHwConfig(unsigned samFreq, unsigned mClk, unsigned dsdMode, unsigned sampRes_DAC, unsigned sampRes_ADC)
|
||||||
{
|
{
|
||||||
AppPllEnable_SampleRate(samFreq);
|
/* Nothing required since the DAC's will auto detect the sample rate from the clocks */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,4 +20,3 @@ USED_MODULES = lib_xua lib_xud lib_spdif
|
|||||||
|
|
||||||
XMOS_MAKE_PATH ?= ../..
|
XMOS_MAKE_PATH ?= ../..
|
||||||
include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.common
|
include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.common
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
// Copyright 2017-2022 XMOS LIMITED.
|
// Copyright 2017-2023 XMOS LIMITED.
|
||||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||||
#include <xs1.h>
|
#include <xs1.h>
|
||||||
#include <platform.h>
|
#include <platform.h>
|
||||||
#include "xua.h"
|
#include "xua.h"
|
||||||
#include "../../shared/apppll.h"
|
|
||||||
|
|
||||||
on tile[0]: out port p_ctrl = XS1_PORT_8D;
|
on tile[0]: out port p_ctrl = XS1_PORT_8D;
|
||||||
|
|
||||||
@@ -35,11 +34,6 @@ void ctrlPort()
|
|||||||
void AudioHwInit()
|
void AudioHwInit()
|
||||||
{
|
{
|
||||||
/* Wait for power supply to come up */
|
/* 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);
|
delay_milliseconds(100);
|
||||||
|
|
||||||
/* DAC setup: For basic I2S input we don't need any register setup. DACs will clock auto detect etc.
|
/* DAC setup: For basic I2S input we don't need any register setup. DACs will clock auto detect etc.
|
||||||
@@ -48,9 +42,12 @@ void AudioHwInit()
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Configures the external audio hardware for the required sample frequency */
|
/* Configures the external audio hardware for the required sample frequency
|
||||||
|
* Note, the application PLL in xcore.ai will be configured to the correct master clock frequency
|
||||||
|
* by lib_xua
|
||||||
|
*/
|
||||||
void AudioHwConfig(unsigned samFreq, unsigned mClk, unsigned dsdMode, unsigned sampRes_DAC, unsigned sampRes_ADC)
|
void AudioHwConfig(unsigned samFreq, unsigned mClk, unsigned dsdMode, unsigned sampRes_DAC, unsigned sampRes_ADC)
|
||||||
{
|
{
|
||||||
AppPllEnable_SampleRate(samFreq);
|
/* Nothing required since the DAC's will auto detect the sample rate from the clocks */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,4 +19,3 @@ USED_MODULES = lib_xua lib_xud lib_mic_array
|
|||||||
|
|
||||||
XMOS_MAKE_PATH ?= ../..
|
XMOS_MAKE_PATH ?= ../..
|
||||||
include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.common
|
include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.common
|
||||||
|
|
||||||
|
|||||||
@@ -1,109 +0,0 @@
|
|||||||
// Copyright 2022 XMOS LIMITED.
|
|
||||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "xassert.h"
|
|
||||||
|
|
||||||
// App PLL setup
|
|
||||||
#define APP_PLL_CTL_BYPASS (0) // 0 = no bypass, 1 = bypass.
|
|
||||||
#define APP_PLL_CTL_INPUT_SEL (0) // 0 = XTAL, 1 = sysPLL
|
|
||||||
#define APP_PLL_CTL_ENABLE (1) // 0 = disabled, 1 = enabled.
|
|
||||||
|
|
||||||
// 24MHz in, 24.576MHz out, integer mode
|
|
||||||
// Found exact solution: IN 24000000.0, OUT 24576000.0, VCO 2457600000.0, RD 5, FD 512, OD 10, FOD 10
|
|
||||||
#define APP_PLL_CTL_OD_48 (4) // Output divider = (OD+1)
|
|
||||||
#define APP_PLL_CTL_F_48 (511) // FB divider = (F+1)/2
|
|
||||||
#define APP_PLL_CTL_R_48 (4) // Ref divider = (R+1)
|
|
||||||
|
|
||||||
#define APP_PLL_CTL_48 ((APP_PLL_CTL_BYPASS << 29) | (APP_PLL_CTL_INPUT_SEL << 28) | (APP_PLL_CTL_ENABLE << 27) |\
|
|
||||||
(APP_PLL_CTL_OD_48 << 23) | (APP_PLL_CTL_F_48 << 8) | APP_PLL_CTL_R_48)
|
|
||||||
|
|
||||||
// Fractional divide is M/N
|
|
||||||
#define APP_PLL_FRAC_EN_48 (0) // 0 = disabled
|
|
||||||
#define APP_PLL_FRAC_NPLUS1_CYCLES_48 (0) // M value is this reg value + 1.
|
|
||||||
#define APP_PLL_FRAC_TOTAL_CYCLES_48 (0) // N value is this reg value + 1.
|
|
||||||
#define APP_PLL_FRAC_48 ((APP_PLL_FRAC_EN_48 << 31) | (APP_PLL_FRAC_NPLUS1_CYCLES_48 << 8) | APP_PLL_FRAC_TOTAL_CYCLES_48)
|
|
||||||
|
|
||||||
// 24MHz in, 22.5792MHz out (44.1kHz * 512), frac mode
|
|
||||||
// Found exact solution: IN 24000000.0, OUT 22579200.0, VCO 2257920000.0, RD 5, FD 470.400 (m = 2, n = 5), OD 5, FOD 10
|
|
||||||
#define APP_PLL_CTL_OD_441 (4) // Output divider = (OD+1)
|
|
||||||
#define APP_PLL_CTL_F_441 (469) // FB divider = (F+1)/2
|
|
||||||
#define APP_PLL_CTL_R_441 (4) // Ref divider = (R+1)
|
|
||||||
|
|
||||||
#define APP_PLL_CTL_441 ((APP_PLL_CTL_BYPASS << 29) | (APP_PLL_CTL_INPUT_SEL << 28) | (APP_PLL_CTL_ENABLE << 27) |\
|
|
||||||
(APP_PLL_CTL_OD_441 << 23) | (APP_PLL_CTL_F_441 << 8) | APP_PLL_CTL_R_441)
|
|
||||||
|
|
||||||
#define APP_PLL_FRAC_EN_44 (1) // 1 = enabled
|
|
||||||
#define APP_PLL_FRAC_NPLUS1_CYCLES_44 (1) // M value is this reg value + 1.
|
|
||||||
#define APP_PLL_FRAC_TOTAL_CYCLES_44 (4) // N value is this reg value + 1.define APP_PLL_CTL_R_441 (4) // Ref divider = (R+1)
|
|
||||||
#define APP_PLL_FRAC_44 ((APP_PLL_FRAC_EN_44 << 31) | (APP_PLL_FRAC_NPLUS1_CYCLES_44 << 8) | APP_PLL_FRAC_TOTAL_CYCLES_44)
|
|
||||||
|
|
||||||
#define APP_PLL_DIV_INPUT_SEL (1) // 0 = sysPLL, 1 = app_PLL
|
|
||||||
#define APP_PLL_DIV_DISABLE (0) // 1 = disabled (pin connected to X1D11), 0 = enabled divider output to pin.
|
|
||||||
#define APP_PLL_DIV_VALUE (4) // Divide by N+1 - remember there's a /2 also afterwards for 50/50 duty cycle.
|
|
||||||
#define APP_PLL_DIV ((APP_PLL_DIV_INPUT_SEL << 31) | (APP_PLL_DIV_DISABLE << 16) | APP_PLL_DIV_VALUE)
|
|
||||||
|
|
||||||
/* TODO support more than two freqs..*/
|
|
||||||
void AppPllEnable(int32_t clkFreq_hz)
|
|
||||||
{
|
|
||||||
switch(clkFreq_hz)
|
|
||||||
{
|
|
||||||
case 44100*512:
|
|
||||||
|
|
||||||
// Disable the PLL
|
|
||||||
write_node_config_reg(tile[1], XS1_SSWITCH_SS_APP_PLL_CTL_NUM, (APP_PLL_CTL_441 & 0xF7FFFFFF));
|
|
||||||
// Enable the PLL to invoke a reset on the appPLL.
|
|
||||||
write_node_config_reg(tile[1], XS1_SSWITCH_SS_APP_PLL_CTL_NUM, APP_PLL_CTL_441);
|
|
||||||
// Must write the CTL register twice so that the F and R divider values are captured using a running clock.
|
|
||||||
write_node_config_reg(tile[1], XS1_SSWITCH_SS_APP_PLL_CTL_NUM, APP_PLL_CTL_441);
|
|
||||||
// Now disable and re-enable the PLL so we get the full 5us reset time with the correct F and R values.
|
|
||||||
write_node_config_reg(tile[1], XS1_SSWITCH_SS_APP_PLL_CTL_NUM, (APP_PLL_CTL_441 & 0xF7FFFFFF));
|
|
||||||
write_node_config_reg(tile[1], XS1_SSWITCH_SS_APP_PLL_CTL_NUM, APP_PLL_CTL_441);
|
|
||||||
|
|
||||||
// Set the fractional divider if used
|
|
||||||
write_node_config_reg(tile[0], XS1_SSWITCH_SS_APP_PLL_FRAC_N_DIVIDER_NUM, APP_PLL_FRAC_44);
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 48000*512:
|
|
||||||
|
|
||||||
// Disable the PLL
|
|
||||||
write_node_config_reg(tile[1], XS1_SSWITCH_SS_APP_PLL_CTL_NUM, (APP_PLL_CTL_48 & 0xF7FFFFFF));
|
|
||||||
// Enable the PLL to invoke a reset on the appPLL.
|
|
||||||
write_node_config_reg(tile[1], XS1_SSWITCH_SS_APP_PLL_CTL_NUM, APP_PLL_CTL_48);
|
|
||||||
// Must write the CTL register twice so that the F and R divider values are captured using a running clock.
|
|
||||||
write_node_config_reg(tile[1], XS1_SSWITCH_SS_APP_PLL_CTL_NUM, APP_PLL_CTL_48);
|
|
||||||
// Now disable and re-enable the PLL so we get the full 5us reset time with the correct F and R values.
|
|
||||||
write_node_config_reg(tile[1], XS1_SSWITCH_SS_APP_PLL_CTL_NUM, (APP_PLL_CTL_48 & 0xF7FFFFFF));
|
|
||||||
write_node_config_reg(tile[1], XS1_SSWITCH_SS_APP_PLL_CTL_NUM, APP_PLL_CTL_48);
|
|
||||||
|
|
||||||
// Set the fractional divider if used
|
|
||||||
write_node_config_reg(tile[0], XS1_SSWITCH_SS_APP_PLL_FRAC_N_DIVIDER_NUM, APP_PLL_FRAC_48);
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for PLL output frequency to stabilise due to fractional divider enable
|
|
||||||
delay_microseconds(100);
|
|
||||||
|
|
||||||
// Turn on the clock output
|
|
||||||
write_node_config_reg(tile[0], XS1_SSWITCH_SS_APP_CLK_DIVIDER_NUM, APP_PLL_DIV);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppPllEnable_SampleRate(int32_t sampleRate_hz)
|
|
||||||
{
|
|
||||||
assert(sampleRate_hz >= 22050);
|
|
||||||
|
|
||||||
if(sampleRate_hz % 22050 == 0)
|
|
||||||
{
|
|
||||||
AppPllEnable(44100*512);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
AppPllEnable(48000*512);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
10
host_usb_mixer_control/.makefile
Normal file
10
host_usb_mixer_control/.makefile
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
all:
|
||||||
|
@echo =======================================================
|
||||||
|
@echo Build complete [module only - cannot be run on its own]
|
||||||
|
@echo =======================================================
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@echo =======================================================
|
||||||
|
@echo Build clean [module only - cannot be run on its own]
|
||||||
|
@echo =======================================================
|
||||||
|
|
||||||
77
host_usb_mixer_control/.project
Normal file
77
host_usb_mixer_control/.project
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>host_usb_mixer_control</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
|
||||||
|
<triggers>clean,full,incremental,</triggers>
|
||||||
|
<arguments>
|
||||||
|
<dictionary>
|
||||||
|
<key>?name?</key>
|
||||||
|
<value></value>
|
||||||
|
</dictionary>
|
||||||
|
<dictionary>
|
||||||
|
<key>org.eclipse.cdt.make.core.append_environment</key>
|
||||||
|
<value>true</value>
|
||||||
|
</dictionary>
|
||||||
|
<dictionary>
|
||||||
|
<key>org.eclipse.cdt.make.core.autoBuildTarget</key>
|
||||||
|
<value>all</value>
|
||||||
|
</dictionary>
|
||||||
|
<dictionary>
|
||||||
|
<key>org.eclipse.cdt.make.core.buildArguments</key>
|
||||||
|
<value></value>
|
||||||
|
</dictionary>
|
||||||
|
<dictionary>
|
||||||
|
<key>org.eclipse.cdt.make.core.buildCommand</key>
|
||||||
|
<value>xmake</value>
|
||||||
|
</dictionary>
|
||||||
|
<dictionary>
|
||||||
|
<key>org.eclipse.cdt.make.core.cleanBuildTarget</key>
|
||||||
|
<value>clean</value>
|
||||||
|
</dictionary>
|
||||||
|
<dictionary>
|
||||||
|
<key>org.eclipse.cdt.make.core.contents</key>
|
||||||
|
<value>org.eclipse.cdt.make.core.activeConfigSettings</value>
|
||||||
|
</dictionary>
|
||||||
|
<dictionary>
|
||||||
|
<key>org.eclipse.cdt.make.core.enableAutoBuild</key>
|
||||||
|
<value>false</value>
|
||||||
|
</dictionary>
|
||||||
|
<dictionary>
|
||||||
|
<key>org.eclipse.cdt.make.core.enableCleanBuild</key>
|
||||||
|
<value>true</value>
|
||||||
|
</dictionary>
|
||||||
|
<dictionary>
|
||||||
|
<key>org.eclipse.cdt.make.core.enableFullBuild</key>
|
||||||
|
<value>true</value>
|
||||||
|
</dictionary>
|
||||||
|
<dictionary>
|
||||||
|
<key>org.eclipse.cdt.make.core.fullBuildTarget</key>
|
||||||
|
<value>all</value>
|
||||||
|
</dictionary>
|
||||||
|
<dictionary>
|
||||||
|
<key>org.eclipse.cdt.make.core.stopOnError</key>
|
||||||
|
<value>true</value>
|
||||||
|
</dictionary>
|
||||||
|
<dictionary>
|
||||||
|
<key>org.eclipse.cdt.make.core.useDefaultBuildCmd</key>
|
||||||
|
<value>true</value>
|
||||||
|
</dictionary>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
|
||||||
|
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
|
||||||
|
<nature>org.eclipse.cdt.core.cnature</nature>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
||||||
2
host_usb_mixer_control/Makefile.OSX
Normal file
2
host_usb_mixer_control/Makefile.OSX
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
all:
|
||||||
|
g++ -g -o xmos_mixer usb_mixer.cpp mixer_app.cpp -I. -IOSX OSX/libusb-1.0.0.dylib -arch x86_64
|
||||||
5
host_usb_mixer_control/Makefile.Win
Normal file
5
host_usb_mixer_control/Makefile.Win
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
!if [set SDKPath=C:\Program^ Files\XMOS\tusbaudiosdk]
|
||||||
|
!endif
|
||||||
|
|
||||||
|
all:
|
||||||
|
msbuild host_usb_mixer_control.vcxproj /property:Configuration=Release /property:Platform=x64
|
||||||
BIN
host_usb_mixer_control/OSX/libusb-1.0.0.dylib
Normal file
BIN
host_usb_mixer_control/OSX/libusb-1.0.0.dylib
Normal file
Binary file not shown.
1233
host_usb_mixer_control/OSX/libusb.h
Normal file
1233
host_usb_mixer_control/OSX/libusb.h
Normal file
File diff suppressed because it is too large
Load Diff
117
host_usb_mixer_control/README
Normal file
117
host_usb_mixer_control/README
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
The XMOS USB Audio Reference Design, by default, contains an 18x8 mixer unit
|
||||||
|
(note that at sample rates above 96Khz only the first two outputs are
|
||||||
|
enabled).
|
||||||
|
|
||||||
|
----WINDOWS REQUIREMENTS----
|
||||||
|
Building the mixer on Windows requires the tusbaudio SDK from Thesycon. The
|
||||||
|
default location for the SDK is C:\Program Files\XMOS\tusbaudiosdk\
|
||||||
|
If it can be found on a different path then this can be changed in
|
||||||
|
Makefile.Win.
|
||||||
|
|
||||||
|
The mixer app on windows makes use of a USB dynamic library, also from Thesycon.
|
||||||
|
If required please contact thesycon.de for support.
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
This unit takes input takes 18 inputs: USB OUT channels 1..10 and
|
||||||
|
DEVICE IN channels 1..6,9..10 and produces 8 outputs: Mixer Output
|
||||||
|
1..8
|
||||||
|
|
||||||
|
Before the mixer there is an unit that allows the selection of the 18 mixer inputs
|
||||||
|
from all the possible device inputs (DAW and physical audio). This is
|
||||||
|
an extension unit with id 50 in the descriptors
|
||||||
|
|
||||||
|
After the mixer unit there is are channel map units for each output terminal:
|
||||||
|
Each of these outputs can select a source from one of 28 channels sources: USB OUT
|
||||||
|
channels 1..10, DEVICE IN channels 1..10 and Mixer Output 1..8
|
||||||
|
|
||||||
|
The channel map units are extension unit with init ids 51 and 52. This unit
|
||||||
|
lets you implement arbitrary routings including loopbacks.
|
||||||
|
|
||||||
|
The mixer is controlled on macOS via the command line utility
|
||||||
|
xmos_mixer. Running this application requires having the
|
||||||
|
libusb-1.0.0.dylib in the dynamic library load path. Sourcing the
|
||||||
|
setup.sh script will do this. Source code for the application is
|
||||||
|
provided as a guide on how to communicate with the device.
|
||||||
|
|
||||||
|
Here are the commands for the mixer application (note that the USB
|
||||||
|
audio reference design has only one unit so the mixer_id argument
|
||||||
|
should always be 0):
|
||||||
|
|
||||||
|
--help
|
||||||
|
|
||||||
|
--display-info
|
||||||
|
|
||||||
|
Show information about the device.
|
||||||
|
|
||||||
|
--display-mixer-nodes mixer_id
|
||||||
|
|
||||||
|
Display all the weights of all the mixer nodes (and their id) of a particular mixer.
|
||||||
|
|
||||||
|
--display-min mixer_id
|
||||||
|
|
||||||
|
Display the minimum allowable weights of a particular mixer.
|
||||||
|
|
||||||
|
--display-max mixer_id
|
||||||
|
|
||||||
|
Display the maximum allowable weights of a particular mixer.
|
||||||
|
|
||||||
|
--display-res mixer_id
|
||||||
|
|
||||||
|
Display the resolution of a particular mixer.
|
||||||
|
|
||||||
|
--set-value mixer_id mixer_unit value
|
||||||
|
|
||||||
|
Set the weight value in the mixer. The second argument should
|
||||||
|
correspond to the values shown by the --display-unit command. Values
|
||||||
|
can range from -127db to +128db with the special value -inf for mute.
|
||||||
|
|
||||||
|
--get-value mixer_id mixer_unit
|
||||||
|
|
||||||
|
Get the weight value in the mixer. The second argument should
|
||||||
|
correspond to the values shown by the --display-unit command. Values
|
||||||
|
can range from -127db to +128db with the special value -inf for mute.
|
||||||
|
|
||||||
|
--set-mixer-source mixer_id, dst_channel_id, src_channel_id
|
||||||
|
|
||||||
|
Allows the selection of the mixer inputs. Sets mixer input (dst) to src
|
||||||
|
|
||||||
|
--display-current-mixer-sources mixer_id
|
||||||
|
|
||||||
|
Displays the current inputs to a particular mixer
|
||||||
|
|
||||||
|
--display-available-mixer-sources mixer_id
|
||||||
|
|
||||||
|
Displays all the input channels available that can be fed into the inputs of a particular mixer
|
||||||
|
|
||||||
|
--set-aud-channel-map dst src
|
||||||
|
|
||||||
|
Sets a channel map value for the device audio output
|
||||||
|
|
||||||
|
--display-aud-channel-map
|
||||||
|
|
||||||
|
Show audio output channel map i.e. for each audio output of the device what the source is.
|
||||||
|
|
||||||
|
--display-aud-channel-map-sources
|
||||||
|
|
||||||
|
Show the available audio output channel map sources.
|
||||||
|
|
||||||
|
--set-daw-channel-map dst src
|
||||||
|
|
||||||
|
Sets a channel map value for the DAW output to the host
|
||||||
|
|
||||||
|
--display-daw-channel-map
|
||||||
|
|
||||||
|
Show audio output channel map i.e. for each DAW output to host, what the source is.
|
||||||
|
|
||||||
|
--display-daw-channel-map-sources
|
||||||
|
|
||||||
|
Show the DAW output channel map sources.
|
||||||
|
|
||||||
|
--get-mixer-levels-input
|
||||||
|
|
||||||
|
--get-mixer-levels-output
|
||||||
|
|
||||||
|
--vendor-audio-request-get bRequest, ControlSelector, ChannelNumber, UnitId
|
||||||
|
|
||||||
|
--vendor-audio-request-set bRequest, ControlSelector, ChannelNumber, UnitId, Data[0], Data[1],...
|
||||||
|
|
||||||
48
host_usb_mixer_control/Win/global.h
Normal file
48
host_usb_mixer_control/Win/global.h
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
// Copyright 2022-2023 XMOS LIMITED.
|
||||||
|
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
*
|
||||||
|
* Module: global.h
|
||||||
|
* Description:
|
||||||
|
* APP global includes, constants, declarations, etc.
|
||||||
|
*
|
||||||
|
* Author(s):
|
||||||
|
* Udo Eberhardt
|
||||||
|
*
|
||||||
|
* Companies:
|
||||||
|
* Thesycon GmbH, Germany http://www.thesycon.de
|
||||||
|
*
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
#ifndef __global_h__
|
||||||
|
#define __global_h__
|
||||||
|
|
||||||
|
// define the Windows versions supported by the application
|
||||||
|
#define _WIN32_WINNT 0x0500 //Windows 2000 or later
|
||||||
|
//#define _WIN32_WINNT 0x0501 //Windows XP or later
|
||||||
|
//#define _WIN32_WINNT 0x0600 //Windows Vista or later
|
||||||
|
//#define _WIN32_WINNT 0x0A00 //Windows 10 or later
|
||||||
|
|
||||||
|
// exclude rarely-used stuff from Windows headers
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <tchar.h>
|
||||||
|
|
||||||
|
|
||||||
|
// version defs
|
||||||
|
//#include "version.h"
|
||||||
|
|
||||||
|
// libwn.h pulls in windows.h
|
||||||
|
#include "libwn.h"
|
||||||
|
// TUSBAUDIO driver API
|
||||||
|
#include "tusbaudioapi.h"
|
||||||
|
#include "TUsbAudioApiDll.h"
|
||||||
|
|
||||||
|
|
||||||
|
#endif // __global_h__
|
||||||
|
|
||||||
|
/*************************** EOF **************************************/
|
||||||
177
host_usb_mixer_control/host_usb_mixer_control.vcxproj
Normal file
177
host_usb_mixer_control/host_usb_mixer_control.vcxproj
Normal file
@@ -0,0 +1,177 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Debug|x64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<VCProjectVersion>16.0</VCProjectVersion>
|
||||||
|
<Keyword>Win32Proj</Keyword>
|
||||||
|
<ProjectGuid>{84eacf4f-e405-4909-b440-a04a84a3f8c8}</ProjectGuid>
|
||||||
|
<RootNamespace>
|
||||||
|
</RootNamespace>
|
||||||
|
<SDKPath Condition="'$(SDKPath)' == ''">C:\Program Files\XMOS\tusbaudiosdk</SDKPath>
|
||||||
|
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="Shared">
|
||||||
|
<Import Project="$(SDKPath)\source\tusbaudioapi_inc\tusbaudioapi_inc_vs2019.vcxitems" Label="Shared" />
|
||||||
|
<Import Project="$(SDKPath)\source\libwn_min\_libwn_min_vs2019.vcxitems" Label="Shared" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<OutDir>.\bin\$(Configuration)\$(PlatformName)\</OutDir>
|
||||||
|
<IntDir>$(Configuration)\$(PlatformName)_$(PlatformToolset)</IntDir>
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<OutDir>.\bin\$(Configuration)\$(PlatformName)\</OutDir>
|
||||||
|
<IntDir>$(Configuration)\$(PlatformName)_$(PlatformToolset)</IntDir>
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level4</WarningLevel>
|
||||||
|
<SDLCheck>
|
||||||
|
</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>_DEBUG;_AMD64;_CONSOLE;_UNICODE;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<AdditionalIncludeDirectories>.;.\Win;$(SDKPath)\source\shared;$(SDKPath)\source\inc;$(SDKPath)\source\libwn_min;$(SDKPath)\source\libwtl;$(SDKPath)\source\tusbaudioapi_inc</AdditionalIncludeDirectories>
|
||||||
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||||
|
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||||
|
<ExceptionHandling>Async</ExceptionHandling>
|
||||||
|
<PrecompiledHeaderFile />
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
<EnableUAC>false</EnableUAC>
|
||||||
|
<UACExecutionLevel />
|
||||||
|
<UACUIAccess />
|
||||||
|
<GenerateMapFile>true</GenerateMapFile>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level4</WarningLevel>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>false</IntrinsicFunctions>
|
||||||
|
<SDLCheck>
|
||||||
|
</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>_AMD64;_CONSOLE;_UNICODE;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<AdditionalIncludeDirectories>.;.\Win;$(SDKPath)\source\shared;$(SDKPath)\source\inc;$(SDKPath)\source\libwn_min;$(SDKPath)\source\libwtl;$(SDKPath)\source\tusbaudioapi_inc</AdditionalIncludeDirectories>
|
||||||
|
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||||
|
<ExceptionHandling>Async</ExceptionHandling>
|
||||||
|
<PrecompiledHeaderFile />
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
<EnableUAC>false</EnableUAC>
|
||||||
|
<UACExecutionLevel />
|
||||||
|
<UACUIAccess />
|
||||||
|
<GenerateMapFile>true</GenerateMapFile>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="usb_mixer.h" />
|
||||||
|
<ClInclude Include="Win\global.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="mixer_app.cpp" />
|
||||||
|
<ClCompile Include="usb_mixer.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="Source Files">
|
||||||
|
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||||
|
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Header Files">
|
||||||
|
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||||
|
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Resource Files">
|
||||||
|
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||||
|
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="usb_mixer.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Win\global.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="mixer_app.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="Win\usb_mixer.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup />
|
||||||
|
</Project>
|
||||||
718
host_usb_mixer_control/mixer_app.cpp
Normal file
718
host_usb_mixer_control/mixer_app.cpp
Normal file
@@ -0,0 +1,718 @@
|
|||||||
|
// Copyright 2022-2023 XMOS LIMITED.
|
||||||
|
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "usb_mixer.h"
|
||||||
|
|
||||||
|
#define MIXER_UNIT_DISPLAY_VALUE 2
|
||||||
|
#define MIXER_UNIT_DISPLAY_MIN 3
|
||||||
|
#define MIXER_UNIT_DISPLAY_MAX 4
|
||||||
|
#define MIXER_UNIT_DISPLAY_RES 5
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
// res, min, max
|
||||||
|
|
||||||
|
int mixer_init(void)
|
||||||
|
{
|
||||||
|
/* Open the connection to the USB mixer */
|
||||||
|
if (usb_mixer_connect() == USB_MIXER_FAILURE)
|
||||||
|
{
|
||||||
|
return USB_MIXER_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return USB_MIXER_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mixer_deinit(void) {
|
||||||
|
// Close the connection to the USB mixer
|
||||||
|
if (usb_mixer_disconnect() == USB_MIXER_FAILURE) {
|
||||||
|
return USB_MIXER_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return USB_MIXER_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mixer_display(unsigned int mixer_index, unsigned int type) {
|
||||||
|
int i = 0;
|
||||||
|
int j = 0;
|
||||||
|
|
||||||
|
int num_inputs = usb_mixer_get_num_inputs(mixer_index);
|
||||||
|
int num_outputs = usb_mixer_get_num_outputs(mixer_index);
|
||||||
|
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
switch (type) {
|
||||||
|
case MIXER_UNIT_DISPLAY_VALUE:
|
||||||
|
//mixer_update_all_values(mixer_index);
|
||||||
|
printf(" Mixer Values (%d)\n", mixer_index);
|
||||||
|
printf(" ----------------\n\n");
|
||||||
|
break;
|
||||||
|
case MIXER_UNIT_DISPLAY_MIN:
|
||||||
|
printf(" Mixer Ranges Min (%d)\n", mixer_index);
|
||||||
|
printf(" --------------------\n\n");
|
||||||
|
break;
|
||||||
|
case MIXER_UNIT_DISPLAY_MAX:
|
||||||
|
printf(" Mixer Ranges Max (%d)\n", mixer_index);
|
||||||
|
printf(" --------------------\n\n");
|
||||||
|
break;
|
||||||
|
case MIXER_UNIT_DISPLAY_RES:
|
||||||
|
printf(" Mixer Ranges Res (%d)\n", mixer_index);
|
||||||
|
printf(" --------------------\n\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return USB_MIXER_FAILURE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf(" \t\t\t");
|
||||||
|
printf("Mixer Outputs\n");
|
||||||
|
printf("\t\t ");
|
||||||
|
for (i = 0; i < num_outputs; i++) {
|
||||||
|
printf(" %d", i+1);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
for (i = 0; i < num_inputs; i++) {
|
||||||
|
printf(" %-20s", usb_mixer_get_input_name(mixer_index,i));
|
||||||
|
for (j = 0; j < num_outputs; j++) {
|
||||||
|
switch (type) {
|
||||||
|
case MIXER_UNIT_DISPLAY_VALUE:
|
||||||
|
{
|
||||||
|
double mixNodeVal = usb_mixer_get_value(mixer_index, (i*num_outputs)+j);
|
||||||
|
int nodeid = (i*num_outputs)+j;
|
||||||
|
|
||||||
|
if (mixNodeVal <= -127.996)// todo shoud be < min
|
||||||
|
{
|
||||||
|
printf("\t%3d:[ %s ]", nodeid,"-inf");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("\t%3d:[%08.03f]", nodeid, mixNodeVal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MIXER_UNIT_DISPLAY_MIN:
|
||||||
|
{
|
||||||
|
int nodeid = (i*num_outputs)+j;
|
||||||
|
printf("\t%3d:[%08.03f]", nodeid, usb_mixer_get_min(mixer_index, (i*num_outputs)+j)) ;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MIXER_UNIT_DISPLAY_MAX:
|
||||||
|
{
|
||||||
|
int nodeid = (i*num_outputs)+j;
|
||||||
|
printf("\t%3d:[%08.03f]", nodeid, usb_mixer_get_max(mixer_index, (i*num_outputs)+j)) ;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MIXER_UNIT_DISPLAY_RES:
|
||||||
|
{
|
||||||
|
int nodeid = (i*num_outputs)+j;
|
||||||
|
printf("\t%3d:[%08.03f]", nodeid, usb_mixer_get_res(mixer_index, (i*num_outputs)+j)) ;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return USB_MIXER_FAILURE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
return USB_MIXER_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Displays basic mixer information */
|
||||||
|
int mixer_display_info(void)
|
||||||
|
{
|
||||||
|
unsigned int i = 0;
|
||||||
|
int num_mixers = usb_mixer_get_num_mixers();
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
printf(" Mixer Info\n");
|
||||||
|
printf(" ----------\n\n");
|
||||||
|
printf(" Mixers : %d\n\n", num_mixers);
|
||||||
|
|
||||||
|
for (i = 0; i < num_mixers; i++)
|
||||||
|
{
|
||||||
|
int num_inputs = usb_mixer_get_num_inputs(i);
|
||||||
|
int num_outputs = usb_mixer_get_num_outputs(i);
|
||||||
|
|
||||||
|
|
||||||
|
printf(" Mixer %d\n", i);
|
||||||
|
printf(" -------\n");
|
||||||
|
|
||||||
|
printf(" Inputs : %d\n"
|
||||||
|
" Outputs : %d\n\n", num_inputs, num_outputs);
|
||||||
|
|
||||||
|
printf(" Mixer Output Labels:\n");
|
||||||
|
for(int j = 0; j < num_outputs; j++)
|
||||||
|
{
|
||||||
|
printf(" %d: %s\n", j,usb_mixer_get_output_name(i,j));
|
||||||
|
}
|
||||||
|
|
||||||
|
//printf("\n Selectable Inputs (%d): \n", usb_mixsel_get_input_count(i));
|
||||||
|
//for(int j = 0; j < usb_mixsel_get_input_count(i); j++)
|
||||||
|
//{
|
||||||
|
// printf(" %d: %s\n", j, usb_mixsel_get_input_string(i,j));
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
return USB_MIXER_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void display_available_mixer_sources(int mixIndex)
|
||||||
|
{
|
||||||
|
printf("\n");
|
||||||
|
printf(" Available Mixer Sources (%d)\n", mixIndex);
|
||||||
|
printf(" -------------------------\n\n");
|
||||||
|
|
||||||
|
for(int j = 0; j < usb_mixsel_get_input_count(mixIndex); j++)
|
||||||
|
{
|
||||||
|
printf(" %d: %s\n", j, usb_mixsel_get_input_string(mixIndex,j));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Gets the current mixer inputs from the device an displays them */
|
||||||
|
void display_mixer_sources(int mixerIndex)
|
||||||
|
{
|
||||||
|
printf("\n");
|
||||||
|
printf(" Current Mixer Sources (%d)\n", mixerIndex);
|
||||||
|
printf(" -------------------------\n\n");
|
||||||
|
|
||||||
|
/* Note, mixSel output cound and mixer input chan count should be the same! */
|
||||||
|
printf(" Number of mixer sources: %d\n", usb_mixsel_get_output_count(mixerIndex));
|
||||||
|
|
||||||
|
/* Get the current channel number for every mixer input */
|
||||||
|
for(int i = 0; i < usb_mixsel_get_output_count(mixerIndex); i++)
|
||||||
|
{
|
||||||
|
int inputChan = (int)usb_mixsel_get_state(mixerIndex, i);
|
||||||
|
char *str = usb_mixer_get_input_name(mixerIndex,inputChan);
|
||||||
|
printf(" Mixer input %d: Source chan id: %d (%s)\n", i, inputChan, str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set mixer source */
|
||||||
|
void set_mixer_source(unsigned mixerIndex, unsigned dst, unsigned src)
|
||||||
|
{
|
||||||
|
usb_mixsel_set_state(mixerIndex, dst, src);
|
||||||
|
|
||||||
|
/* String lookup */
|
||||||
|
char *str = usb_mixer_get_input_name(mixerIndex, dst);
|
||||||
|
int state = usb_mixsel_get_state(mixerIndex, dst);
|
||||||
|
|
||||||
|
printf("\n Set mixer(%d) input %d to device input %d (%s)\n", mixerIndex, dst, state, str);
|
||||||
|
}
|
||||||
|
|
||||||
|
void display_aud_channel_map()
|
||||||
|
{
|
||||||
|
printf("\n");
|
||||||
|
printf(" Audio Output Channel Map\n");
|
||||||
|
printf(" ------------------------\n\n");
|
||||||
|
|
||||||
|
for (int i=0;i<usb_get_aud_channel_map_num_outputs();i++)
|
||||||
|
{
|
||||||
|
int x = usb_get_aud_channel_map(i);
|
||||||
|
printf("%d (DEVICE OUT - %s) source is ",i, usb_get_aud_channel_map_name(i));
|
||||||
|
|
||||||
|
switch (usb_get_aud_channel_map_type(x))
|
||||||
|
{
|
||||||
|
case USB_CHAN_OUT:
|
||||||
|
printf(" %d (DAW OUT - %s)\n",x,usb_get_aud_channel_map_name(x));
|
||||||
|
break;
|
||||||
|
case USB_CHAN_IN:
|
||||||
|
printf("%d (DEVICE IN - %s)\n",x,usb_get_aud_channel_map_name(x));
|
||||||
|
break;
|
||||||
|
case USB_CHAN_MIXER:
|
||||||
|
printf("%d (%s)\n",x,usb_get_aud_channel_map_name(x));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void display_daw_channel_map()
|
||||||
|
{
|
||||||
|
printf("\n");
|
||||||
|
printf(" DAW Output To Host Channel Map\n");
|
||||||
|
printf(" ------------------------\n\n");
|
||||||
|
|
||||||
|
for (int i=0;i<usb_get_usb_channel_map_num_outputs();i++)
|
||||||
|
{
|
||||||
|
int x = usb_get_usb_channel_map(i);
|
||||||
|
printf("%d (DAW IN - %s) source is ",i, usb_get_usb_channel_map_name(i + usb_get_aud_channel_map_num_outputs()));
|
||||||
|
|
||||||
|
switch (usb_get_usb_channel_map_type(x))
|
||||||
|
{
|
||||||
|
case USB_CHAN_OUT:
|
||||||
|
printf(" %d (DAW OUT - %s)\n",x,usb_get_usb_channel_map_name(x));
|
||||||
|
break;
|
||||||
|
case USB_CHAN_IN:
|
||||||
|
printf("%d (DEVICE IN - %s)\n",x,usb_get_usb_channel_map_name(x));
|
||||||
|
break;
|
||||||
|
case USB_CHAN_MIXER:
|
||||||
|
printf("%d (%s)\n",x,usb_get_usb_channel_map_name(x));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void display_aud_channel_map_sources(void)
|
||||||
|
{
|
||||||
|
printf("\n");
|
||||||
|
printf(" Audio Output Channel Map Source List\n");
|
||||||
|
printf(" ------------------------------------\n\n");
|
||||||
|
for (int i=0;i<usb_get_aud_channel_map_num_inputs();i++) {
|
||||||
|
switch (usb_get_aud_channel_map_type(i))
|
||||||
|
{
|
||||||
|
case USB_CHAN_OUT:
|
||||||
|
printf("%d (DAW OUT - %s)\n",i,usb_get_aud_channel_map_name(i));
|
||||||
|
break;
|
||||||
|
case USB_CHAN_IN:
|
||||||
|
printf("%d (DEVICE IN - %s)\n",i,usb_get_aud_channel_map_name(i));
|
||||||
|
break;
|
||||||
|
case USB_CHAN_MIXER:
|
||||||
|
printf("%d (%s)\n",i,usb_get_aud_channel_map_name(i));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void display_daw_channel_map_sources(void)
|
||||||
|
{
|
||||||
|
printf("\n");
|
||||||
|
printf(" DAW Output to Host Channel Map Source List\n");
|
||||||
|
printf(" ------------------------------------------\n\n");
|
||||||
|
for (int i=0;i<usb_get_usb_channel_map_num_inputs();i++) {
|
||||||
|
switch (usb_get_usb_channel_map_type(i))
|
||||||
|
{
|
||||||
|
case USB_CHAN_OUT:
|
||||||
|
printf("%d (DAW OUT - %s)\n",i,usb_get_usb_channel_map_name(i));
|
||||||
|
break;
|
||||||
|
case USB_CHAN_IN:
|
||||||
|
printf("%d (DEVICE IN - %s)\n",i,usb_get_usb_channel_map_name(i));
|
||||||
|
break;
|
||||||
|
case USB_CHAN_MIXER:
|
||||||
|
printf("%d (%s)\n",i,usb_get_usb_channel_map_name(i));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int usb_audio_request_get(unsigned bRequest, unsigned cs, unsigned cn, unsigned unitId, unsigned char *data)
|
||||||
|
{
|
||||||
|
char reqStr[] = "Custom";
|
||||||
|
|
||||||
|
if(bRequest == CUR)
|
||||||
|
{
|
||||||
|
strcpy(reqStr, "CUR");
|
||||||
|
}
|
||||||
|
else if(bRequest == RANGE)
|
||||||
|
{
|
||||||
|
strcpy(reqStr, "RANGE");
|
||||||
|
}
|
||||||
|
else if(bRequest == MEM)
|
||||||
|
{
|
||||||
|
strcpy(reqStr, "MEM");
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Performing class GET request to Audio Interface:\n\
|
||||||
|
bRequest: 0x%02x (%s)\n\
|
||||||
|
wValue: 0x%04x (Control Sel: %d, Channel Number: %d)\n\
|
||||||
|
wIndex: 0x%04x (Interface: 0, Entity: %d)\n\
|
||||||
|
\n", bRequest, reqStr, (cs<<8)|cn, cs, cn, unitId<<8, unitId);
|
||||||
|
|
||||||
|
return usb_audio_class_get(bRequest, cs, cn, unitId, 64, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
int usb_audio_request_set(unsigned bRequest, unsigned cs, unsigned cn, unsigned unitId,
|
||||||
|
unsigned char *data, int datalength)
|
||||||
|
{
|
||||||
|
char reqStr[] = "Custom";
|
||||||
|
|
||||||
|
if(bRequest == CUR)
|
||||||
|
{
|
||||||
|
strcpy(reqStr, "CUR");
|
||||||
|
}
|
||||||
|
else if(bRequest == RANGE)
|
||||||
|
{
|
||||||
|
strcpy(reqStr, "RANGE");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
strcpy(reqStr, "MEM");
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Performing class SET request to Audio Interface:\n\
|
||||||
|
bRequest: 0x%02x (%s)\n\
|
||||||
|
wValue: 0x%04x (Control Sel: %d, Channel Number: %d)\n\
|
||||||
|
wIndex: 0x%04x (Interface: 0, Entity: %d)\n\
|
||||||
|
\n", bRequest, reqStr, (cs<<8)|cn, cs, cn, unitId<<8, unitId);
|
||||||
|
|
||||||
|
return usb_audio_class_set(bRequest, cs, cn, unitId, datalength, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int usb_audio_memreq_get(unsigned unitId, unsigned offset, unsigned char *data)
|
||||||
|
{
|
||||||
|
/* Mem requests dont have CS/CN, just an offset.. */
|
||||||
|
return usb_audio_request_get(MEM, (offset>>8), offset&0xff, unitId, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_levels(const char* levelTitle, unsigned char* levels, int levelBytes)
|
||||||
|
{
|
||||||
|
unsigned levelCount = levelBytes/2;
|
||||||
|
unsigned short* levelData = (unsigned short*) levels;
|
||||||
|
|
||||||
|
printf("\n %s Level Data\n"
|
||||||
|
" ----------------------\n\n"
|
||||||
|
"%d bytes (%d channels) returned:\n"
|
||||||
|
, levelTitle, levelBytes, levelCount);
|
||||||
|
|
||||||
|
for(int i = 0; i<levelCount; i++)
|
||||||
|
{
|
||||||
|
printf("%s %d: 0x%04x\n", levelTitle, i,levelData[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void mixer_display_usage(void) {
|
||||||
|
fprintf(stderr, "Usage :\n");
|
||||||
|
fprintf(stderr,
|
||||||
|
" --display-info\n"
|
||||||
|
" --display-mixer-nodes mixer_id\n"
|
||||||
|
" --display-min mixer_id\n"
|
||||||
|
" --display-max mixer_id\n"
|
||||||
|
" --display-res mixer_id\n"
|
||||||
|
" --set-value mixer_id, mixer_node, value\n"
|
||||||
|
" --get-value mixer_id, mixer_node\n"
|
||||||
|
"\n"
|
||||||
|
" --set-mixer-source mixer_id dst channel_id, src_channel_id\n"
|
||||||
|
" --display-current-mixer-sources mixer_id\n"
|
||||||
|
" --display-available-mixer-sources mixer_id\n"
|
||||||
|
"\n"
|
||||||
|
" --set-aud-channel-map dst_channel_id, src_channel_id\n"
|
||||||
|
" --display-aud-channel-map \n"
|
||||||
|
" --display-aud-channel-map-sources\n"
|
||||||
|
" --set-daw-channel-map dst_channel_id, src_channel_id\n"
|
||||||
|
" --display-daw-channel-map \n"
|
||||||
|
" --display-daw-channel-map-sources\n"
|
||||||
|
"\n"
|
||||||
|
" --get-mixer-levels-input mixer_id\n"
|
||||||
|
" --get-mixer-levels-output mixer_id\n"
|
||||||
|
" --vendor-audio-request-get bRequest, ControlSelector, ChannelNumber, UnitId\n"
|
||||||
|
" --vendor-audio-request-set bRequest, ControlSelector, ChannelNumber, UnitId, Data[0], Data[1],...\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void usage_error()
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ERROR :: incorrect number of arguments passed. See --help\n");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int main (int argc, char **argv) {
|
||||||
|
|
||||||
|
unsigned int mixer_index = 0;
|
||||||
|
unsigned int result = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (argc < 2) {
|
||||||
|
fprintf(stderr, "ERROR :: No options passed to mixer application\n");
|
||||||
|
mixer_display_usage();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(argv[1], "--help") == 0) {
|
||||||
|
mixer_display_usage();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mixer_init() != USB_MIXER_SUCCESS) {
|
||||||
|
fprintf(stderr, "ERROR :: Cannot connect\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(argv[1], "--display-info") == 0)
|
||||||
|
{
|
||||||
|
mixer_display_info();
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[1], "--display-mixer-nodes") == 0)
|
||||||
|
{
|
||||||
|
if (argv[2])
|
||||||
|
{
|
||||||
|
mixer_index = atoi(argv[2]);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "ERROR :: No mixer index supplied\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
mixer_display(mixer_index, MIXER_UNIT_DISPLAY_VALUE);
|
||||||
|
} else if (strcmp(argv[1], "--display-mixer-nodes") == 0) {
|
||||||
|
if (argv[2]) {
|
||||||
|
mixer_index = atoi(argv[2]);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "ERROR :: No mixer index supplied\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
mixer_display(mixer_index, MIXER_UNIT_DISPLAY_VALUE);
|
||||||
|
} else if (strcmp(argv[1], "--display-min") == 0) {
|
||||||
|
if (argv[2]) {
|
||||||
|
mixer_index = atoi(argv[2]);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "ERROR :: No mixer index supplied\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
mixer_display(mixer_index, MIXER_UNIT_DISPLAY_MIN);
|
||||||
|
} else if (strcmp(argv[1], "--display-max") == 0) {
|
||||||
|
if (argv[2]) {
|
||||||
|
mixer_index = atoi(argv[2]);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "ERROR :: No mixer index supplied\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
mixer_display(mixer_index, MIXER_UNIT_DISPLAY_MAX);
|
||||||
|
} else if (strcmp(argv[1], "--display-res") == 0) {
|
||||||
|
if (argv[2]) {
|
||||||
|
mixer_index = atoi(argv[2]);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "ERROR :: No mixer index supplied\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
mixer_display(mixer_index, MIXER_UNIT_DISPLAY_RES);
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[1], "--set-value") == 0) {
|
||||||
|
unsigned int mixer_unit = 0;
|
||||||
|
double value = 0;
|
||||||
|
if (argc < 5) {
|
||||||
|
fprintf(stderr, "ERROR :: incorrect number of arguments passed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
mixer_index = atoi(argv[2]);
|
||||||
|
mixer_unit = atoi(argv[3]);
|
||||||
|
if (strcmp(argv[4],"-inf")==0)
|
||||||
|
value = -128;
|
||||||
|
else
|
||||||
|
value = atof(argv[4]);
|
||||||
|
|
||||||
|
usb_mixer_set_value(mixer_index, mixer_unit, value);
|
||||||
|
} else if (strcmp(argv[1], "--get-value") == 0) {
|
||||||
|
unsigned int mixer_unit = 0;
|
||||||
|
double result = 0;
|
||||||
|
if (argc < 4) {
|
||||||
|
fprintf(stderr, "ERROR :: incorrect number of arguments passed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
mixer_index = atoi(argv[2]);
|
||||||
|
mixer_unit = atoi(argv[3]);
|
||||||
|
|
||||||
|
result = usb_mixer_get_value(mixer_index, mixer_unit);
|
||||||
|
if (result <= -127.996)
|
||||||
|
printf("%s\n", "-inf");
|
||||||
|
else
|
||||||
|
printf("%g\n",result);
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[1], "--display-current-mixer-sources") == 0)
|
||||||
|
{
|
||||||
|
if(argc < 3)
|
||||||
|
{
|
||||||
|
usage_error();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
display_mixer_sources(atoi(argv[2]));
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[1], "--display-available-mixer-sources") == 0)
|
||||||
|
{
|
||||||
|
if(argc < 3)
|
||||||
|
{
|
||||||
|
usage_error();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
display_available_mixer_sources(atoi(argv[2]));
|
||||||
|
}
|
||||||
|
else if(strcmp(argv[1], "--set-mixer-source") == 0)
|
||||||
|
{
|
||||||
|
if(argc < 5)
|
||||||
|
{
|
||||||
|
usage_error();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
set_mixer_source(atoi(argv[2]), atoi(argv[3]), atoi(argv[4]));
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[1], "--display-aud-channel-map") == 0)
|
||||||
|
{
|
||||||
|
/* Display the channel mapping to the devices audio outputs */
|
||||||
|
display_aud_channel_map();
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[1], "--display-aud-channel-map-sources") == 0)
|
||||||
|
{
|
||||||
|
display_aud_channel_map_sources();
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[1], "--display-daw-channel-map") == 0)
|
||||||
|
{
|
||||||
|
/* Display the channel mapping to the devices DAW output to host */
|
||||||
|
display_daw_channel_map();
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[1], "--display-daw-channel-map-sources") == 0)
|
||||||
|
{
|
||||||
|
display_daw_channel_map_sources();
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[1], "--set-aud-channel-map") == 0)
|
||||||
|
{
|
||||||
|
unsigned int dst = 0;
|
||||||
|
unsigned int src = 0;
|
||||||
|
if (argc != 4)
|
||||||
|
{
|
||||||
|
usage_error();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
dst = atoi(argv[2]);
|
||||||
|
src = atoi(argv[3]);
|
||||||
|
|
||||||
|
usb_set_aud_channel_map(dst, src);
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[1], "--set-daw-channel-map") == 0)
|
||||||
|
{
|
||||||
|
unsigned int dst = 0;
|
||||||
|
unsigned int src = 0;
|
||||||
|
if (argc != 4)
|
||||||
|
{
|
||||||
|
usage_error();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
dst = atoi(argv[2]);
|
||||||
|
src = atoi(argv[3]);
|
||||||
|
|
||||||
|
usb_set_usb_channel_map(dst, src);
|
||||||
|
}
|
||||||
|
else if(strcmp(argv[1], "--get-mixer-levels-input") == 0 ||
|
||||||
|
strcmp(argv[1],"--get-mixer-levels-output") == 0)
|
||||||
|
{
|
||||||
|
unsigned int dst = 0;
|
||||||
|
unsigned char levels[64];
|
||||||
|
int datalength = 0;
|
||||||
|
int offset = 0;
|
||||||
|
|
||||||
|
if (argc < 3) {
|
||||||
|
fprintf(stderr, "ERROR :: incorrect number of arguments passed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(strcmp(argv[1],"--get-mixer-levels-output") == 0)
|
||||||
|
offset = 1;
|
||||||
|
|
||||||
|
for(int i = 0; i < 64; i++)
|
||||||
|
levels[i] = 0;
|
||||||
|
|
||||||
|
dst = atoi(argv[2]);
|
||||||
|
|
||||||
|
/* Mem request to mixer with offset of 0 gives input levels */
|
||||||
|
datalength = usb_mixer_mem_get(dst, offset, levels);
|
||||||
|
|
||||||
|
if(datalength < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ERROR in control request: %d\n", datalength);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(offset)
|
||||||
|
print_levels("Mixer Output", levels, datalength);
|
||||||
|
else
|
||||||
|
print_levels("Mixer Input", levels, datalength);
|
||||||
|
|
||||||
|
}
|
||||||
|
else if(strcmp(argv[1], "--vendor-audio-request-get") == 0)
|
||||||
|
{
|
||||||
|
unsigned int bRequest = 0;
|
||||||
|
unsigned int cs = 0;
|
||||||
|
unsigned int cn = 0;
|
||||||
|
unsigned int unitId = 0;
|
||||||
|
int datalength = 0;
|
||||||
|
unsigned char data[64];
|
||||||
|
|
||||||
|
if(argc < 6)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ERROR :: incorrect number of arguments passed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < 64; i++)
|
||||||
|
data[i] = 0;
|
||||||
|
|
||||||
|
bRequest = atoi(argv[2]);
|
||||||
|
cs = atoi(argv[3]);
|
||||||
|
cn = atoi(argv[4]);
|
||||||
|
unitId = atoi(argv[5]);
|
||||||
|
|
||||||
|
/* Do request */
|
||||||
|
datalength = usb_audio_request_get(bRequest, cs, cn, unitId, data);
|
||||||
|
|
||||||
|
/* Print result */
|
||||||
|
if(datalength < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ERROR in control request: %d\n", datalength);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Response (%d bytes):\n", datalength);
|
||||||
|
for(int i = 0; i < datalength; i++)
|
||||||
|
printf("0x%02x\n" ,data[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(strcmp(argv[1], "--vendor-audio-request-set") == 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
unsigned int bRequest = 0;
|
||||||
|
unsigned int cs = 0;
|
||||||
|
unsigned int cn = 0;
|
||||||
|
unsigned int unitId = 0;
|
||||||
|
unsigned char data[64];
|
||||||
|
|
||||||
|
for(int i=0; i<64; i++)
|
||||||
|
{
|
||||||
|
data[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(argc < 7)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ERROR :: incorrect number of arguments passed - no data passed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
bRequest = atoi(argv[2]);
|
||||||
|
cs = atoi(argv[3]);
|
||||||
|
cn = atoi(argv[4]);
|
||||||
|
unitId = atoi(argv[5]);
|
||||||
|
|
||||||
|
/* Get data */
|
||||||
|
for(int i=0; i < argc-6; i++)
|
||||||
|
{
|
||||||
|
data[i] = atoi(argv[i+6]);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = usb_audio_request_set(bRequest, cs, cn, unitId, data, argc-6);
|
||||||
|
|
||||||
|
if(result < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ERROR :: Error detected in Set request: %d\n", result);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ERROR :: Invalid option passed to mixer application\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
mixer_deinit();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
1
host_usb_mixer_control/setup.sh
Normal file
1
host_usb_mixer_control/setup.sh
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export DYLD_LIBRARY_PATH=$PWD/OSX:$DYLD_LIBRARY_PATH
|
||||||
1042
host_usb_mixer_control/usb_mixer.cpp
Normal file
1042
host_usb_mixer_control/usb_mixer.cpp
Normal file
File diff suppressed because it is too large
Load Diff
108
host_usb_mixer_control/usb_mixer.h
Normal file
108
host_usb_mixer_control/usb_mixer.h
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
// Copyright 2022-2023 XMOS LIMITED.
|
||||||
|
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||||
|
|
||||||
|
#define USB_MIXER_SUCCESS 0
|
||||||
|
#define USB_MIXER_FAILURE -1
|
||||||
|
|
||||||
|
#define USB_MIXERS 1
|
||||||
|
#define USB_MIXER_INPUTS 18
|
||||||
|
#define USB_MIXER_OUTPUTS 8
|
||||||
|
#define USB_MAX_CHANNEL_MAP_SIZE 40
|
||||||
|
#define USB_MIXER_MAX_NAME_LEN 64
|
||||||
|
|
||||||
|
enum usb_chan_type {
|
||||||
|
USB_CHAN_OUT=0,
|
||||||
|
USB_CHAN_IN=1,
|
||||||
|
USB_CHAN_MIXER=2
|
||||||
|
};
|
||||||
|
|
||||||
|
/* A.14 Audio Class-Specific Request Codes */
|
||||||
|
#define REQUEST_CODE_UNDEFINED 0x00
|
||||||
|
#define CUR (1)
|
||||||
|
#define RANGE (2)
|
||||||
|
#define MEM (3)
|
||||||
|
|
||||||
|
int usb_mixer_connect();
|
||||||
|
int usb_mixer_disconnect();
|
||||||
|
|
||||||
|
/* MIXER UNIT(s) INTERFACE */
|
||||||
|
|
||||||
|
/* Returns total number of mixers in device */
|
||||||
|
int usb_mixer_get_num_mixers();
|
||||||
|
|
||||||
|
/* Returns number of inputs and outputs for a selected mixer */
|
||||||
|
int usb_mixer_get_layout(unsigned int mixer, unsigned int *inputs, unsigned int *outputs);
|
||||||
|
|
||||||
|
/* Returns the name for a selected mixer input */
|
||||||
|
char *usb_mixer_get_input_name(unsigned int mixer, unsigned int input);
|
||||||
|
|
||||||
|
/* Returns the name for a selected mixer output */
|
||||||
|
char *usb_mixer_get_output_name(unsigned int mixer, unsigned int output);
|
||||||
|
|
||||||
|
/* Returns the current value of a selected mixer unit */
|
||||||
|
double usb_mixer_get_value(unsigned int mixer, unsigned int mixer_unit);
|
||||||
|
|
||||||
|
/* Sets the current value for a selected mixer unit */
|
||||||
|
int usb_mixer_set_value(unsigned int mixer, unsigned int mixer_unit, double val);
|
||||||
|
|
||||||
|
/* Returns the range values for a selected mixer unit */
|
||||||
|
int usb_mixer_get_range(unsigned int mixer, unsigned int mixer_unit, double *min, double *max, double *res);
|
||||||
|
|
||||||
|
/* Returns the number of bytes read from a mem request, data is stored in data */
|
||||||
|
int usb_mixer_mem_get(unsigned int mixer, unsigned offset, unsigned char *data);
|
||||||
|
|
||||||
|
|
||||||
|
/* INPUT / OUTPUT / MIXER MAPPING UNIT INTERFACE */
|
||||||
|
|
||||||
|
/* Get the number of selectable inputs */
|
||||||
|
int usb_mixsel_get_input_count(unsigned int mixer);
|
||||||
|
|
||||||
|
/* Get the string of a input */
|
||||||
|
char *usb_mixsel_get_input_string(unsigned int mixer, unsigned int channel);
|
||||||
|
|
||||||
|
int usb_mixsel_get_output_count(unsigned int mixer);
|
||||||
|
|
||||||
|
int usb_mixer_get_num_outputs(unsigned int mixer);
|
||||||
|
|
||||||
|
int usb_mixer_get_num_inputs(unsigned int mixer);
|
||||||
|
|
||||||
|
unsigned char usb_mixsel_get_state(unsigned int mixer, unsigned int channel);
|
||||||
|
|
||||||
|
void usb_mixsel_set_state(unsigned int mixer, unsigned int dst, unsigned int src);
|
||||||
|
|
||||||
|
int usb_set_usb_channel_map(int channel, int val);
|
||||||
|
|
||||||
|
|
||||||
|
/* Get the current map for a specified input / output / mixer channel */
|
||||||
|
int usb_get_usb_channel_map(int channel);
|
||||||
|
int usb_get_aud_channel_map(int channel);
|
||||||
|
|
||||||
|
/* Maps an input / output / mixer channel to another input / output / mixer channel */
|
||||||
|
int usb_set_aud_channel_map(int channel, int val);
|
||||||
|
int usb_set_usb_channel_map(int channel, int val);
|
||||||
|
|
||||||
|
/* Gets the name of a specified channel */
|
||||||
|
char *usb_get_aud_channel_map_name(int channel);
|
||||||
|
char *usb_get_usb_channel_map_name(int channel);
|
||||||
|
|
||||||
|
/* Get the type of a channel map */
|
||||||
|
enum usb_chan_type usb_get_aud_channel_map_type(int channel);
|
||||||
|
enum usb_chan_type usb_get_usb_channel_map_type(int channel);
|
||||||
|
|
||||||
|
int usb_get_aud_channel_map_num_outputs();
|
||||||
|
int usb_get_usb_channel_map_num_outputs();
|
||||||
|
|
||||||
|
int usb_get_aud_channel_map_num_inputs();
|
||||||
|
int usb_get_usb_channel_map_num_inputs();
|
||||||
|
|
||||||
|
/* CUSTOM/GENERIC AUDIO CLASS REQUESTS */
|
||||||
|
|
||||||
|
int usb_audio_class_get(unsigned char bRequest, unsigned char cs, unsigned char cn, unsigned short unitID, unsigned short wLength, unsigned char *data);
|
||||||
|
|
||||||
|
int usb_audio_class_set(unsigned char bRequest, unsigned char cs, unsigned char cn, unsigned short unitID, unsigned short wLength, unsigned char *data);
|
||||||
|
|
||||||
|
double usb_mixer_get_res(unsigned int mixer, unsigned int nodeId);
|
||||||
|
|
||||||
|
double usb_mixer_get_min(unsigned int mixer, unsigned int nodeId) ;
|
||||||
|
|
||||||
|
double usb_mixer_get_max(unsigned int mixer, unsigned int nodeId) ;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2017-2022 XMOS LIMITED.
|
// Copyright 2017-2023 XMOS LIMITED.
|
||||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||||
#ifndef _XUA_H_
|
#ifndef _XUA_H_
|
||||||
#define _XUA_H_
|
#define _XUA_H_
|
||||||
@@ -7,14 +7,14 @@
|
|||||||
|
|
||||||
#include "xua_conf_full.h"
|
#include "xua_conf_full.h"
|
||||||
|
|
||||||
#if __XC__ || __STDC__
|
#ifndef __ASSEMBLER__
|
||||||
#include "xua_audiohub.h"
|
#include "xua_audiohub.h"
|
||||||
#include "xua_endpoint0.h"
|
#include "xua_endpoint0.h"
|
||||||
#include "xua_buffer.h"
|
#include "xua_buffer.h"
|
||||||
#include "xua_mixer.h"
|
#include "xua_mixer.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if __XC__
|
#ifdef __XC__
|
||||||
#include "xua_clocking.h"
|
#include "xua_clocking.h"
|
||||||
#include "xua_midi.h"
|
#include "xua_midi.h"
|
||||||
#if XUA_NUM_PDM_MICS > 0
|
#if XUA_NUM_PDM_MICS > 0
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
// Copyright 2011-2022 XMOS LIMITED.
|
// Copyright 2011-2023 XMOS LIMITED.
|
||||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||||
#ifndef __XUA_AUDIOHUB_H__
|
#ifndef _XUA_AUDIOHUB_H_
|
||||||
#define __XUA_AUDIOHUB_H__
|
#define _XUA_AUDIOHUB_H_
|
||||||
|
|
||||||
#if __XC__
|
#ifdef __XC__
|
||||||
|
|
||||||
#include "xccompat.h"
|
#include "xccompat.h"
|
||||||
#include "xs1.h"
|
#include "xs1.h"
|
||||||
@@ -12,6 +12,8 @@
|
|||||||
#include "dfu_interface.h"
|
#include "dfu_interface.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "xua_clocking.h"
|
||||||
|
|
||||||
/** The audio driver thread.
|
/** The audio driver thread.
|
||||||
*
|
*
|
||||||
* This function drives I2S ports and handles samples to/from other digital
|
* This function drives I2S ports and handles samples to/from other digital
|
||||||
@@ -34,6 +36,8 @@
|
|||||||
*
|
*
|
||||||
* \param p_i2s_adc Nullable array of ports for I2S data input lines
|
* \param 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_spdif_tx Channel connected to S/PDIF transmiter core from lib_spdif
|
||||||
*
|
*
|
||||||
* \param c_dig Channel connected to the clockGen() thread for
|
* \param c_dig Channel connected to the clockGen() thread for
|
||||||
@@ -47,6 +51,9 @@ void XUA_AudioHub(chanend ?c_aud,
|
|||||||
buffered _XUA_CLK_DIR port:32 ?p_bclk,
|
buffered _XUA_CLK_DIR port:32 ?p_bclk,
|
||||||
buffered out port:32 (&?p_i2s_dac)[I2S_WIRES_DAC],
|
buffered out port:32 (&?p_i2s_dac)[I2S_WIRES_DAC],
|
||||||
buffered in port:32 (&?p_i2s_adc)[I2S_WIRES_ADC]
|
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__)
|
#if (XUA_SPDIF_TX_EN) || defined(__DOXYGEN__)
|
||||||
, chanend c_spdif_tx
|
, chanend c_spdif_tx
|
||||||
#endif
|
#endif
|
||||||
@@ -63,21 +70,28 @@ void XUA_AudioHub(chanend ?c_aud,
|
|||||||
|
|
||||||
void SpdifTxWrapper(chanend c_spdif_tx);
|
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__
|
#endif // __XC__
|
||||||
|
|
||||||
void UserBufferManagementInit();
|
/**
|
||||||
|
* @brief User buffer management code
|
||||||
|
*
|
||||||
|
* This function is called at the sample rate of the USB Audio stack (e.g,. 48 kHz) and between the two parameter arrays
|
||||||
|
* contain a full multi-channel audio-frame. The first array carries all the data that has been received from the USB host
|
||||||
|
* and is to be presented to the audio interfaces. The second array carries all the data received from the interfaces and
|
||||||
|
* is to be presented to the USB host. The user can chose to intercept and overwrite the samples stored in these arrays.
|
||||||
|
*
|
||||||
|
* \param sampsFromUsbToAudio Samples received from USB host and to be presented to audio interfaces
|
||||||
|
*
|
||||||
|
* \param sampsFromAudioToUsb Samples received from the audio interfaces and to be presented to the USB host
|
||||||
|
*/
|
||||||
void UserBufferManagement(unsigned sampsFromUsbToAudio[], unsigned sampsFromAudioToUsb[]);
|
void UserBufferManagement(unsigned sampsFromUsbToAudio[], unsigned sampsFromAudioToUsb[]);
|
||||||
|
|
||||||
#endif // __XUA_AUDIOHUB_H__
|
/**
|
||||||
|
* @brief User buffer managment init code
|
||||||
|
*
|
||||||
|
* This function is called once, before the first call to UserBufferManagement(), and can be used to initialise any
|
||||||
|
* related user state
|
||||||
|
*/
|
||||||
|
void UserBufferManagementInit();
|
||||||
|
|
||||||
|
#endif // _XUA_AUDIOHUB_H_
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Copyright 2011-2022 XMOS LIMITED.
|
// Copyright 2011-2023 XMOS LIMITED.
|
||||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||||
#ifndef __XUA_BUFFER_H__
|
#ifndef _XUA_BUFFER_H_
|
||||||
#define __XUA_BUFFER_H__
|
#define _XUA_BUFFER_H_
|
||||||
|
|
||||||
#if __XC__
|
#if __XC__
|
||||||
|
|
||||||
@@ -26,6 +26,7 @@
|
|||||||
* \param p_off_mclk A port that is clocked of the MCLK input (not the MCLK input itself)
|
* \param 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 c_aud Channel connected to XUA_AudioHub() core
|
||||||
* \param i_pll_ref Interface to task that toggles reference pin to CS2100
|
* \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(
|
void XUA_Buffer(
|
||||||
chanend c_aud_out,
|
chanend c_aud_out,
|
||||||
@@ -51,8 +52,13 @@ void XUA_Buffer(
|
|||||||
, chanend c_hid
|
, chanend c_hid
|
||||||
#endif
|
#endif
|
||||||
, chanend c_aud
|
, chanend c_aud
|
||||||
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC) || defined(__DOXYGEN__)
|
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC) || defined(__DOYXGEN__)
|
||||||
|
#if (!XUA_USE_APP_PLL) || defined(__DOXYGEN__)
|
||||||
, client interface pll_ref_if i_pll_ref
|
, client interface pll_ref_if i_pll_ref
|
||||||
|
#endif
|
||||||
|
#if (XUA_USE_APP_PLL) || defined(__DOXYGEN__)
|
||||||
|
, chanend c_swpll_update
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -81,10 +87,16 @@ void XUA_Buffer_Ep(chanend c_aud_out,
|
|||||||
#ifdef CHAN_BUFF_CTRL
|
#ifdef CHAN_BUFF_CTRL
|
||||||
, chanend c_buff_ctrl
|
, chanend c_buff_ctrl
|
||||||
#endif
|
#endif
|
||||||
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC) || defined(__DOXYGEN__)
|
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC) || defined(__DOYXGEN__)
|
||||||
|
#if (!XUA_USE_APP_PLL) || defined(__DOXYGEN__)
|
||||||
, client interface pll_ref_if i_pll_ref
|
, client interface pll_ref_if i_pll_ref
|
||||||
|
#endif
|
||||||
|
#if (XUA_USE_APP_PLL) || defined(__DOXYGEN__)
|
||||||
|
, chanend c_swpll_update
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
/** Manage the data transfer between the USB audio buffer and the
|
/** Manage the data transfer between the USB audio buffer and the
|
||||||
* Audio I/O driver.
|
* Audio I/O driver.
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
// Copyright 2011-2022 XMOS LIMITED.
|
// Copyright 2011-2023 XMOS LIMITED.
|
||||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||||
|
|
||||||
#ifndef _CLOCKING_H_
|
#ifndef _CLOCKING_H_
|
||||||
#define _CLOCKING_H_
|
#define _CLOCKING_H_
|
||||||
|
|
||||||
#include <xs1.h>
|
#include <xs1.h>
|
||||||
|
#include "xua.h"
|
||||||
|
|
||||||
interface pll_ref_if
|
interface pll_ref_if
|
||||||
{
|
{
|
||||||
@@ -28,5 +29,46 @@ void PllRefPinTask(server interface pll_ref_if i_pll_ref, out port p_sync);
|
|||||||
interrupts
|
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);
|
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
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2011-2022 XMOS LIMITED.
|
// Copyright 2011-2023 XMOS LIMITED.
|
||||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||||
/*
|
/*
|
||||||
* @brief Defines relating to device configuration and customisation of lib_xua
|
* @brief Defines relating to device configuration and customisation of lib_xua
|
||||||
@@ -11,7 +11,9 @@
|
|||||||
#include "xua_conf.h"
|
#include "xua_conf.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Default tile arrangement */
|
/*
|
||||||
|
* Tile arrangement defines
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Location (tile) of audio I/O. Default: 0
|
* @brief Location (tile) of audio I/O. Default: 0
|
||||||
@@ -55,12 +57,9 @@
|
|||||||
#define PLL_REF_TILE AUDIO_IO_TILE
|
#define PLL_REF_TILE AUDIO_IO_TILE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* @brief Disable USB functionalty just leaving AudioHub
|
* Channel based defines
|
||||||
*/
|
*/
|
||||||
#ifndef XUA_USB_EN
|
|
||||||
#define XUA_USB_EN (1)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Number of input channels (device to host). Default: NONE (Must be defined by app)
|
* @brief Number of input channels (device to host). Default: NONE (Must be defined by app)
|
||||||
@@ -79,7 +78,18 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Number of DSD output channels. Default: 0 (disabled)
|
* @brief Number of PDM microphones in the design.
|
||||||
|
*
|
||||||
|
* Default: 0
|
||||||
|
*/
|
||||||
|
#ifndef XUA_NUM_PDM_MICS
|
||||||
|
#define XUA_NUM_PDM_MICS (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Number of DSD output channels.
|
||||||
|
*
|
||||||
|
* Default: 0 (disabled)
|
||||||
*/
|
*/
|
||||||
#if defined(DSD_CHANS_DAC) && (DSD_CHANS_DAC != 0)
|
#if defined(DSD_CHANS_DAC) && (DSD_CHANS_DAC != 0)
|
||||||
#if defined(NATIVE_DSD) && (NATIVE_DSD == 0)
|
#if defined(NATIVE_DSD) && (NATIVE_DSD == 0)
|
||||||
@@ -91,9 +101,41 @@
|
|||||||
#define DSD_CHANS_DAC 0
|
#define DSD_CHANS_DAC 0
|
||||||
#endif
|
#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_I2S (0)
|
||||||
#define XUA_PCM_FORMAT_TDM (1)
|
#define XUA_PCM_FORMAT_TDM (1)
|
||||||
|
/**
|
||||||
|
* @brief Format of PCM audio interface. Should be set to XUA_PCM_FORMAT_I2S or XUA_PCM_FORMAT_TDM
|
||||||
|
*
|
||||||
|
* Default: XUA_PCM_FORMAT_I2S
|
||||||
|
*/
|
||||||
#ifdef XUA_PCM_FORMAT
|
#ifdef XUA_PCM_FORMAT
|
||||||
#if (XUA_PCM_FORMAT != XUA_PCM_FORMAT_I2S) && (XUA_PCM_FORMAT != XUA_PCM_FORMAT_TDM)
|
#if (XUA_PCM_FORMAT != XUA_PCM_FORMAT_I2S) && (XUA_PCM_FORMAT != XUA_PCM_FORMAT_TDM)
|
||||||
#error Bad value for XUA_PCM_FORMAT
|
#error Bad value for XUA_PCM_FORMAT
|
||||||
@@ -116,30 +158,17 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Number of IS2 channesl to DAC/CODEC. Must be a multiple of 2.
|
* @brief Number of bits per channel for I2S/TDM. Supported values: 16/32-bit.
|
||||||
*
|
*
|
||||||
* Default: NONE (Must be defined by app)
|
* Default: 32 bits
|
||||||
*/
|
*/
|
||||||
#ifndef I2S_CHANS_DAC
|
#ifndef XUA_I2S_N_BITS
|
||||||
#error I2S_CHANS_DAC not defined
|
#define XUA_I2S_N_BITS (32)
|
||||||
#define I2S_CHANS_DAC 2 /* Define anyway for doxygen */
|
|
||||||
#else
|
|
||||||
#define I2S_WIRES_DAC (I2S_CHANS_DAC / I2S_CHANS_PER_FRAME)
|
|
||||||
#endif
|
#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
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -193,22 +222,32 @@
|
|||||||
#define I2S_DOWNSAMPLE_CHANS_IN I2S_CHANS_ADC
|
#define I2S_DOWNSAMPLE_CHANS_IN I2S_CHANS_ADC
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clocking related defines
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Max supported sample frequency for device (Hz). Default: 192000
|
* @brief Max supported sample frequency for device (Hz).
|
||||||
|
*
|
||||||
|
* Default: 192000Hz
|
||||||
*/
|
*/
|
||||||
#ifndef MAX_FREQ
|
#ifndef MAX_FREQ
|
||||||
#define MAX_FREQ (192000)
|
#define MAX_FREQ (192000)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Min supported sample frequency for device (Hz). Default 44100
|
* @brief Min supported sample frequency for device (Hz).
|
||||||
|
*
|
||||||
|
* Default: 44100Hz
|
||||||
*/
|
*/
|
||||||
#ifndef MIN_FREQ
|
#ifndef MIN_FREQ
|
||||||
#define MIN_FREQ (44100)
|
#define MIN_FREQ (44100)
|
||||||
#endif
|
#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
|
#ifndef MCLK_441
|
||||||
#error MCLK_441 not defined
|
#error MCLK_441 not defined
|
||||||
@@ -216,7 +255,9 @@
|
|||||||
#endif
|
#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
|
#ifndef MCLK_48
|
||||||
#error MCLK_48 not defined
|
#error MCLK_48 not defined
|
||||||
@@ -224,26 +265,66 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Default device sample frequency. A safe default should be used. Default: MIN_FREQ
|
* @brief Enable/disable the use of the secondary/application PLL for generating master-clocks.
|
||||||
|
* Only available on xcore.ai devices.
|
||||||
|
*
|
||||||
|
* Default: Enabled (for xcore.ai devices)
|
||||||
|
*/
|
||||||
|
#ifndef XUA_USE_APP_PLL
|
||||||
|
#if defined(__XS3A__)
|
||||||
|
#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
|
||||||
|
/* Currently must use an external CS2100 device for syncing to external digital streams */
|
||||||
|
#define XUA_USE_APP_PLL (0)
|
||||||
|
#else
|
||||||
|
#define XUA_USE_APP_PLL (1)
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define XUA_USE_APP_PLL (0)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Default device sample frequency. A safe default should be used.
|
||||||
|
*
|
||||||
|
* Default: MIN_FREQ
|
||||||
*/
|
*/
|
||||||
#ifndef DEFAULT_FREQ
|
#ifndef DEFAULT_FREQ
|
||||||
#define DEFAULT_FREQ (MIN_FREQ)
|
#define DEFAULT_FREQ (MIN_FREQ)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Audio Class Defines */
|
#define DEFAULT_MCLK (((DEFAULT_FREQ % 7350) == 0) ? MCLK_441 : MCLK_48)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief USB Audio Class Version. Default: 2 (Audio Class version 2.0)
|
* @brief Defines whether XMOS device runs as master (i.e. drives LR and Bit clocks)
|
||||||
|
*
|
||||||
|
* 0: XMOS is I2S master. 1: CODEC is I2s master.
|
||||||
|
*
|
||||||
|
* Default: 0 (XMOS is master)
|
||||||
|
*/
|
||||||
|
#ifndef CODEC_MASTER
|
||||||
|
#define CODEC_MASTER (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Audio Class defines
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief USB Audio Class Version
|
||||||
|
*
|
||||||
|
* Default: 2 (Audio Class version 2.0)
|
||||||
*/
|
*/
|
||||||
#ifndef AUDIO_CLASS
|
#ifndef AUDIO_CLASS
|
||||||
#define AUDIO_CLASS 2
|
#define AUDIO_CLASS (2)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Whether or not to fall back to Audio Class 1.0 in USB Full-speed. Default: 0 (Disabled)
|
* @brief Enable/disable fall back to Audio Class 1.0 in USB Full-speed.
|
||||||
|
*
|
||||||
|
* Default: Disabled
|
||||||
*/
|
*/
|
||||||
#ifndef AUDIO_CLASS_FALLBACK
|
#ifndef AUDIO_CLASS_FALLBACK
|
||||||
#define AUDIO_CLASS_FALLBACK 0 /* Default to not falling back to UAC 1 */
|
#define AUDIO_CLASS_FALLBACK (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -272,14 +353,17 @@
|
|||||||
#error AUDIO_CLASS set to 1 and FULL_SPEED_AUDIO_2 enabled!
|
#error AUDIO_CLASS set to 1 and FULL_SPEED_AUDIO_2 enabled!
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
/* Feature defines */
|
* Feature defines
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Number of PDM microphones in the design. Default: None
|
* @brief Disable USB functionalty just leaving AudioHub
|
||||||
|
*
|
||||||
|
* Default: Enabled
|
||||||
*/
|
*/
|
||||||
#ifndef XUA_NUM_PDM_MICS
|
#ifndef XUA_USB_EN
|
||||||
#define XUA_NUM_PDM_MICS (0)
|
#define XUA_USB_EN (1)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -432,14 +516,36 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Defines whether XMOS device runs as master (i.e. drives LR and Bit clocks)
|
* 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.
|
||||||
*
|
*
|
||||||
* 0: XMOS is I2S master. 1: CODEC is I2s master.
|
* 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.
|
||||||
*
|
*
|
||||||
* Default: 0 (XMOS is master)
|
* You must also supply your own function to deal with the HID endpoint(s)
|
||||||
|
* in this case.
|
||||||
*/
|
*/
|
||||||
#ifndef CODEC_MASTER
|
#if (HID_CONTROLS) || defined (__DOXYGEN__)
|
||||||
#define CODEC_MASTER (0)
|
#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)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -997,17 +1103,12 @@
|
|||||||
#define MIXER (0)
|
#define MIXER (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Tidy up old ifndef usage */
|
|
||||||
#if defined(MIXER) && (MIXER == 0)
|
|
||||||
#undef MIXER
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Number of seperate mixes to perform
|
* @brief Number of seperate mixes to perform
|
||||||
*
|
*
|
||||||
* Default: 8 if MIXER enabled, else 0
|
* Default: 8 if MIXER enabled, else 0
|
||||||
*/
|
*/
|
||||||
#ifdef MIXER
|
#if (MIXER)
|
||||||
#ifndef MAX_MIX_COUNT
|
#ifndef MAX_MIX_COUNT
|
||||||
#define MAX_MIX_COUNT (8)
|
#define MAX_MIX_COUNT (8)
|
||||||
#endif
|
#endif
|
||||||
@@ -1087,44 +1188,24 @@
|
|||||||
#define VOLUME_RES_MIXER (0x100)
|
#define VOLUME_RES_MIXER (0x100)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Handle out volume control in the mixer */
|
/* Handle out volume control in the mixer - enabled by default */
|
||||||
#if defined(OUT_VOLUME_IN_MIXER) && (OUT_VOLUME_IN_MIXER==0)
|
#ifndef OUT_VOLUME_IN_MIXER
|
||||||
#undef OUT_VOLUME_IN_MIXER
|
#define OUT_VOLUME_IN_MIXER (1)
|
||||||
#else
|
|
||||||
#if defined(MIXER)
|
|
||||||
// Disabled by default
|
|
||||||
//#define OUT_VOLUME_IN_MIXER
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Apply out volume controls after the mix */
|
/* Apply out volume controls after the mix. Only relevant when OUT_VOLUME_IN_MIXER enabled. Enabled by default */
|
||||||
#if defined(OUT_VOLUME_AFTER_MIX) && (OUT_VOLUME_AFTER_MIX==0)
|
#ifndef OUT_VOLUME_AFTER_MIX
|
||||||
#undef OUT_VOLUME_AFTER_MIX
|
#define OUT_VOLUME_AFTER_MIX (1)
|
||||||
#else
|
|
||||||
#if defined(MIXER) && defined(OUT_VOLUME_IN_MIXER)
|
|
||||||
// Enabled by default
|
|
||||||
#define OUT_VOLUME_AFTER_MIX
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Handle in volume control in the mixer */
|
/* Handle in volume control in the mixer - disabled by default */
|
||||||
#if defined(IN_VOLUME_IN_MIXER) && (IN_VOLUME_IN_MIXER==0)
|
#ifndef IN_VOLUME_IN_MIXER
|
||||||
#undef IN_VOLUME_IN_MIXER
|
#define IN_VOLUME_IN_MIXER (0)
|
||||||
#else
|
|
||||||
#if defined(MIXER)
|
|
||||||
/* Disabled by default */
|
|
||||||
//#define IN_VOLUME_IN_MIXER
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Apply in volume controls after the mix */
|
/* Apply in volume controls after the mix. Only relebant when IN_VOLUMNE_IN MIXER enabled. Enabled by default */
|
||||||
#if defined(IN_VOLUME_AFTER_MIX) && (IN_VOLUME_AFTER_MIX==0)
|
#ifndef IN_VOLUME_AFTER_MIX
|
||||||
#undef IN_VOLUME_AFTER_MIX
|
#define IN_VOLUME_AFTER_MIX (1)
|
||||||
#else
|
|
||||||
#if defined(MIXER) && defined(IN_VOLUME_IN_MIXER)
|
|
||||||
// Enabled by default
|
|
||||||
#define IN_VOLUME_AFTER_MIX
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Always enable explicit feedback EP, even when input stream is present */
|
/* Always enable explicit feedback EP, even when input stream is present */
|
||||||
@@ -1171,7 +1252,7 @@ enum USBEndpointNumber_In
|
|||||||
#ifdef MIDI
|
#ifdef MIDI
|
||||||
ENDPOINT_NUMBER_IN_MIDI,
|
ENDPOINT_NUMBER_IN_MIDI,
|
||||||
#endif
|
#endif
|
||||||
#if( 0 < HID_CONTROLS )
|
#if XUA_OR_STATIC_HID_ENABLED
|
||||||
ENDPOINT_NUMBER_IN_HID,
|
ENDPOINT_NUMBER_IN_HID,
|
||||||
#endif
|
#endif
|
||||||
#ifdef IAP
|
#ifdef IAP
|
||||||
@@ -1198,6 +1279,9 @@ enum USBEndpointNumber_Out
|
|||||||
#ifdef IAP_EA_NATIVE_TRANS
|
#ifdef IAP_EA_NATIVE_TRANS
|
||||||
ENDPOINT_NUMBER_OUT_IAP_EA_NATIVE_TRANS,
|
ENDPOINT_NUMBER_OUT_IAP_EA_NATIVE_TRANS,
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
#if XUA_OR_STATIC_HID_ENABLED && HID_OUT_REQUIRED
|
||||||
|
ENDPOINT_NUMBER_OUT_HID,
|
||||||
#endif
|
#endif
|
||||||
XUA_ENDPOINT_COUNT_OUT /* End marker */
|
XUA_ENDPOINT_COUNT_OUT /* End marker */
|
||||||
};
|
};
|
||||||
@@ -1219,7 +1303,8 @@ enum USBEndpointNumber_Out
|
|||||||
#define AUDIO_START_FROM_DFU (0x87654321)
|
#define AUDIO_START_FROM_DFU (0x87654321)
|
||||||
#define AUDIO_REBOOT_FROM_DFU (0xa5a5a5a5)
|
#define AUDIO_REBOOT_FROM_DFU (0xa5a5a5a5)
|
||||||
|
|
||||||
#define MAX_VOL (0x20000000)
|
/* Result of db_to_mult(MAX_VOLUME, 8, 29) */
|
||||||
|
#define MAX_VOLUME_MULT (0x20000000)
|
||||||
|
|
||||||
#if defined(LEVEL_METER_LEDS) && !defined(LEVEL_UPDATE_RATE)
|
#if defined(LEVEL_METER_LEDS) && !defined(LEVEL_UPDATE_RATE)
|
||||||
#define LEVEL_UPDATE_RATE (400000)
|
#define LEVEL_UPDATE_RATE (400000)
|
||||||
@@ -1319,9 +1404,9 @@ enum USBEndpointNumber_Out
|
|||||||
/* Some defines that allow us to remove unused code */
|
/* Some defines that allow us to remove unused code */
|
||||||
|
|
||||||
/* Useful for dropping lower part of macs in volume processing... */
|
/* Useful for dropping lower part of macs in volume processing... */
|
||||||
#if (FS_STREAM_FORMAT_OUTPUT_1_RESOLUTION_BITS > 24) || (FS_STREAM_FORMAT_OUTPUT_2_RESOLUTION_BITS > 24) || \
|
#if (FS_STREAM_FORMAT_OUTPUT_1_RESOLUTION_BITS > 24) || (HS_STREAM_FORMAT_OUTPUT_2_RESOLUTION_BITS > 24) || \
|
||||||
(FS_STREAM_FORMAT_OUTPUT_3_RESOLUTION_BITS > 24) || (HS_STREAM_FORMAT_OUTPUT_1_RESOLUTION_BITS > 24) || \
|
(((FS_STREAM_FORMAT_OUTPUT_2_RESOLUTION_BITS > 24) || (HS_STREAM_FORMAT_OUTPUT_2_RESOLUTION_BITS > 24)) && (OUTPUT_FORMAT_COUNT > 1)) || \
|
||||||
(HS_STREAM_FORMAT_OUTPUT_2_RESOLUTION_BITS > 24) || (HS_STREAM_FORMAT_OUTPUT_3_RESOLUTION_BITS > 24)
|
(((FS_STREAM_FORMAT_OUTPUT_3_RESOLUTION_BITS > 24) || (HS_STREAM_FORMAT_OUTPUT_3_RESOLUTION_BITS > 24)) && (OUTPUT_FORMAT_COUNT > 2))
|
||||||
#define STREAM_FORMAT_OUTPUT_RESOLUTION_32BIT_USED 1
|
#define STREAM_FORMAT_OUTPUT_RESOLUTION_32BIT_USED 1
|
||||||
#else
|
#else
|
||||||
#define STREAM_FORMAT_OUTPUT_RESOLUTION_32BIT_USED 0
|
#define STREAM_FORMAT_OUTPUT_RESOLUTION_32BIT_USED 0
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Copyright 2017-2022 XMOS LIMITED.
|
// Copyright 2017-2023 XMOS LIMITED.
|
||||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||||
#ifndef __XUA_CONF_FULL_H__
|
#ifndef _XUA_CONF_FULL_H_
|
||||||
#define __XUA_CONF_FULL_H__
|
#define _XUA_CONF_FULL_H_
|
||||||
|
|
||||||
#ifdef __xua_conf_h_exists__
|
#ifdef __xua_conf_h_exists__
|
||||||
#include "xua_conf.h"
|
#include "xua_conf.h"
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
// Copyright 2011-2022 XMOS LIMITED.
|
// Copyright 2011-2023 XMOS LIMITED.
|
||||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||||
#ifndef _XUA_MIXER_H_
|
#ifndef _XUA_MIXER_H_
|
||||||
#define _XUA_MIXER_H_
|
#define _XUA_MIXER_H_
|
||||||
|
|
||||||
|
#include "xua.h"
|
||||||
|
|
||||||
enum mix_ctl_cmd {
|
enum mix_ctl_cmd {
|
||||||
SET_SAMPLES_TO_HOST_MAP,
|
SET_SAMPLES_TO_HOST_MAP,
|
||||||
SET_SAMPLES_TO_DEVICE_MAP,
|
SET_SAMPLES_TO_DEVICE_MAP,
|
||||||
@@ -31,4 +33,14 @@ enum mix_ctl_cmd {
|
|||||||
*/
|
*/
|
||||||
void mixer(chanend c_to_host, chanend c_to_audio, chanend c_mix_ctl);
|
void mixer(chanend c_to_host, chanend c_to_audio, chanend c_mix_ctl);
|
||||||
|
|
||||||
|
#define XUA_MIXER_OFFSET_OUT (0)
|
||||||
|
#define XUA_MIXER_OFFSET_IN (NUM_USB_CHAN_OUT)
|
||||||
|
#define XUA_MIXER_OFFSET_MIX (NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN)
|
||||||
|
#define XUA_MIXER_OFFSET_OFF (NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + MAX_MIX_COUNT)
|
||||||
|
|
||||||
|
/* Defines uses for DB to actual muliplier conversion */
|
||||||
|
#define XUA_MIXER_MULT_FRAC_BITS (25)
|
||||||
|
#define XUA_MIXER_DB_FRAC_BITS (8)
|
||||||
|
#define XUA_MIXER_MAX_MULT (1<<XUA_MIXER_MULT_FRAC_BITS) /* i.e. multiply by 0 */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
|
|
||||||
.. _sec_api:
|
.. _sec_api:
|
||||||
|
|
||||||
|
|
||||||
API Reference
|
API Reference
|
||||||
-------------
|
*************
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
.. _sec_api_component:
|
.. _sec_api_component:
|
||||||
|
|
||||||
Component API
|
Component API
|
||||||
-------------
|
=============
|
||||||
|
|
||||||
The following functions can be called from the top level main of an
|
The following functions can be called from the top level main of an
|
||||||
application and implement the various components described in
|
application and implement the various components described in
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
.. _sec_api_defines:
|
.. _sec_api_defines:
|
||||||
|
|
||||||
Configuration Defines
|
Configuration Defines
|
||||||
---------------------
|
=====================
|
||||||
|
|
||||||
An application using the USB audio framework needs to have defines set for configuration.
|
An application using the USB audio framework needs to have defines set for configuration.
|
||||||
Defaults for these defines are found in ``xua_conf_default.h``.
|
Defaults for these defines are found in ``xua_conf_default.h``.
|
||||||
@@ -13,7 +13,7 @@ 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)
|
Code Location (tile)
|
||||||
~~~~~~~~~~~~~~~~~~~~
|
--------------------
|
||||||
|
|
||||||
.. doxygendefine:: AUDIO_IO_TILE
|
.. doxygendefine:: AUDIO_IO_TILE
|
||||||
.. doxygendefine:: XUD_TILE
|
.. doxygendefine:: XUD_TILE
|
||||||
@@ -23,7 +23,7 @@ Code Location (tile)
|
|||||||
.. doxygendefine:: PLL_REF_TILE
|
.. doxygendefine:: PLL_REF_TILE
|
||||||
|
|
||||||
Channel Counts
|
Channel Counts
|
||||||
~~~~~~~~~~~~~~
|
--------------
|
||||||
|
|
||||||
.. doxygendefine:: NUM_USB_CHAN_OUT
|
.. doxygendefine:: NUM_USB_CHAN_OUT
|
||||||
.. doxygendefine:: NUM_USB_CHAN_IN
|
.. doxygendefine:: NUM_USB_CHAN_IN
|
||||||
@@ -31,33 +31,43 @@ Channel Counts
|
|||||||
.. doxygendefine:: I2S_CHANS_ADC
|
.. doxygendefine:: I2S_CHANS_ADC
|
||||||
|
|
||||||
Frequencies and Clocks
|
Frequencies and Clocks
|
||||||
~~~~~~~~~~~~~~~~~~~~~~
|
----------------------
|
||||||
|
|
||||||
.. doxygendefine:: MAX_FREQ
|
.. doxygendefine:: MAX_FREQ
|
||||||
.. doxygendefine:: MIN_FREQ
|
.. doxygendefine:: MIN_FREQ
|
||||||
.. doxygendefine:: DEFAULT_FREQ
|
.. doxygendefine:: DEFAULT_FREQ
|
||||||
.. doxygendefine:: MCLK_441
|
.. doxygendefine:: MCLK_441
|
||||||
.. doxygendefine:: MCLK_48
|
.. doxygendefine:: MCLK_48
|
||||||
|
.. doxygendefine:: XUA_USE_APP_PLL
|
||||||
|
|
||||||
Audio Class
|
Audio Class
|
||||||
~~~~~~~~~~~
|
-----------
|
||||||
|
|
||||||
.. doxygendefine:: AUDIO_CLASS
|
.. doxygendefine:: AUDIO_CLASS
|
||||||
.. doxygendefine:: AUDIO_CLASS_FALLBACK
|
.. doxygendefine:: AUDIO_CLASS_FALLBACK
|
||||||
.. doxygendefine:: FULL_SPEED_AUDIO_2
|
.. doxygendefine:: FULL_SPEED_AUDIO_2
|
||||||
|
|
||||||
|
|
||||||
System Feature Configuration
|
Feature Configuration
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
---------------------
|
||||||
|
|
||||||
|
I2S/TDM
|
||||||
|
^^^^^^^
|
||||||
|
|
||||||
|
.. doxygendefine:: I2S_CHANS_DAC
|
||||||
|
.. doxygendefine:: I2S_CHANS_ADC
|
||||||
|
.. doxygendefine:: CODEC_MASTER
|
||||||
|
.. doxygendefine:: XUA_I2S_N_BITS
|
||||||
|
.. doxygendefine:: XUA_PCM_FORMAT
|
||||||
|
|
||||||
MIDI
|
MIDI
|
||||||
....
|
^^^^
|
||||||
|
|
||||||
.. doxygendefine:: MIDI
|
.. doxygendefine:: MIDI
|
||||||
.. doxygendefine:: MIDI_RX_PORT_WIDTH
|
.. doxygendefine:: MIDI_RX_PORT_WIDTH
|
||||||
|
|
||||||
S/PDIF
|
S/PDIF
|
||||||
......
|
^^^^^^
|
||||||
|
|
||||||
.. doxygendefine:: XUA_SPDIF_TX_EN
|
.. doxygendefine:: XUA_SPDIF_TX_EN
|
||||||
.. doxygendefine:: SPDIF_TX_INDEX
|
.. doxygendefine:: SPDIF_TX_INDEX
|
||||||
@@ -65,37 +75,37 @@ S/PDIF
|
|||||||
.. doxygendefine:: SPDIF_RX_INDEX
|
.. doxygendefine:: SPDIF_RX_INDEX
|
||||||
|
|
||||||
ADAT
|
ADAT
|
||||||
....
|
^^^^
|
||||||
|
|
||||||
.. doxygendefine:: XUA_ADAT_RX_EN
|
.. doxygendefine:: XUA_ADAT_RX_EN
|
||||||
.. doxygendefine:: ADAT_RX_INDEX
|
.. doxygendefine:: ADAT_RX_INDEX
|
||||||
|
|
||||||
PDM Microphones
|
PDM Microphones
|
||||||
...............
|
^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
.. doxygendefine:: XUA_NUM_PDM_MICS
|
.. doxygendefine:: XUA_NUM_PDM_MICS
|
||||||
|
|
||||||
DFU
|
DFU
|
||||||
...
|
^^^
|
||||||
|
|
||||||
.. doxygendefine:: XUA_DFU_EN
|
.. doxygendefine:: XUA_DFU_EN
|
||||||
|
|
||||||
.. .. doxygendefine:: DFU_FLASH_DEVICE
|
.. .. doxygendefine:: DFU_FLASH_DEVICE
|
||||||
|
|
||||||
HID
|
HID
|
||||||
...
|
^^^
|
||||||
|
|
||||||
.. doxygendefine:: HID_CONTROLS
|
.. doxygendefine:: HID_CONTROLS
|
||||||
|
|
||||||
|
|
||||||
CODEC Interface
|
CODEC Interface
|
||||||
...............
|
^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
.. doxygendefine:: CODEC_MASTER
|
.. doxygendefine:: CODEC_MASTER
|
||||||
|
|
||||||
|
|
||||||
USB Device Configuration
|
USB Device Configuration
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
------------------------
|
||||||
|
|
||||||
.. doxygendefine:: VENDOR_STR
|
.. doxygendefine:: VENDOR_STR
|
||||||
.. doxygendefine:: VENDOR_ID
|
.. doxygendefine:: VENDOR_ID
|
||||||
@@ -108,10 +118,10 @@ USB Device Configuration
|
|||||||
|
|
||||||
|
|
||||||
Stream Formats
|
Stream Formats
|
||||||
~~~~~~~~~~~~~~
|
--------------
|
||||||
|
|
||||||
Output/Playback
|
Output/Playback
|
||||||
...............
|
^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
.. doxygendefine:: OUTPUT_FORMAT_COUNT
|
.. doxygendefine:: OUTPUT_FORMAT_COUNT
|
||||||
|
|
||||||
@@ -132,7 +142,8 @@ Output/Playback
|
|||||||
.. doxygendefine:: STREAM_FORMAT_OUTPUT_3_DATAFORMAT
|
.. doxygendefine:: STREAM_FORMAT_OUTPUT_3_DATAFORMAT
|
||||||
|
|
||||||
Input/Recording
|
Input/Recording
|
||||||
...............
|
^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
.. doxygendefine:: INPUT_FORMAT_COUNT
|
.. doxygendefine:: INPUT_FORMAT_COUNT
|
||||||
|
|
||||||
.. doxygendefine:: STREAM_FORMAT_INPUT_1_RESOLUTION_BITS
|
.. doxygendefine:: STREAM_FORMAT_INPUT_1_RESOLUTION_BITS
|
||||||
@@ -144,7 +155,7 @@ Input/Recording
|
|||||||
.. doxygendefine:: STREAM_FORMAT_INPUT_1_DATAFORMAT
|
.. doxygendefine:: STREAM_FORMAT_INPUT_1_DATAFORMAT
|
||||||
|
|
||||||
Volume Control
|
Volume Control
|
||||||
~~~~~~~~~~~~~~
|
--------------
|
||||||
|
|
||||||
.. doxygendefine:: OUTPUT_VOLUME_CONTROL
|
.. doxygendefine:: OUTPUT_VOLUME_CONTROL
|
||||||
.. doxygendefine:: INPUT_VOLUME_CONTROL
|
.. doxygendefine:: INPUT_VOLUME_CONTROL
|
||||||
@@ -152,8 +163,8 @@ Volume Control
|
|||||||
.. doxygendefine:: MAX_VOLUME
|
.. doxygendefine:: MAX_VOLUME
|
||||||
.. doxygendefine:: VOLUME_RES
|
.. doxygendefine:: VOLUME_RES
|
||||||
|
|
||||||
Mixing Parameters
|
Mixing
|
||||||
~~~~~~~~~~~~~~~~~
|
------
|
||||||
|
|
||||||
.. doxygendefine:: MIXER
|
.. doxygendefine:: MIXER
|
||||||
.. doxygendefine:: MAX_MIX_COUNT
|
.. doxygendefine:: MAX_MIX_COUNT
|
||||||
@@ -163,8 +174,7 @@ Mixing Parameters
|
|||||||
.. doxygendefine:: VOLUME_RES_MIXER
|
.. doxygendefine:: VOLUME_RES_MIXER
|
||||||
|
|
||||||
Power
|
Power
|
||||||
~~~~~
|
-----
|
||||||
|
|
||||||
.. doxygendefine:: SELF_POWERED
|
.. doxygendefine:: XUA_POWERMODE
|
||||||
.. doxygendefine:: BMAX_POWER
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,73 +1,49 @@
|
|||||||
Required User Function Definitions
|
|newpage|
|
||||||
----------------------------------
|
|
||||||
|
|
||||||
The following functions need to be defined by an application using the XMOS USB Audio framework.
|
User Function Definitions
|
||||||
|
=========================
|
||||||
|
|
||||||
|
The following functions can be defined by an application using `lib_xua`.
|
||||||
|
|
||||||
|
.. note:: Default, empty, implementations of these functions are provided in `lib_xua`. These are marked
|
||||||
|
as weak symbols so the application can simply define its own version of them.
|
||||||
|
|
||||||
External Audio Hardware Configuration Functions
|
External Audio Hardware Configuration Functions
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
-----------------------------------------------
|
||||||
|
|
||||||
.. c:function:: void AudioHwInit(chanend ?c_codec)
|
The following functions can be optionally used by the design to configure external audio hardware.
|
||||||
|
As a minimum, in most applications, it is expected that a implementation of `AudioHwConfig()` will need
|
||||||
|
to be provided.
|
||||||
|
|
||||||
This function is called when the audio core starts after the
|
.. doxygenfunction:: AudioHwInit
|
||||||
device boots up and should initialize the external audio harware e.g. clocking, DAC, ADC etc
|
.. doxygenfunction:: AudioHwConfig
|
||||||
|
.. doxygenfunction:: AudioHwConfig_Mute
|
||||||
:param c_codec: An optional chanend that was original passed into
|
.. doxygenfunction:: AudioHwConfig_UnMute
|
||||||
:c:func:`audio` that can be used to communicate
|
|
||||||
with other cores.
|
|
||||||
|
|
||||||
|
|
||||||
.. c:function:: void AudioHwConfig(unsigned samFreq, unsigned mclk, chanend ?c_codec, unsigned dsdMode, unsigned sampRes_DAC, unsigned sampRes_ADC)
|
Audio Stream Start/Stop Functions
|
||||||
|
---------------------------------
|
||||||
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.
|
The following functions can be optionally used by the design. They can be useful for mute lines etc.
|
||||||
|
|
||||||
.. c:function:: void AudioStreamStart(void)
|
.. doxygenfunction:: UserAudioStreamStart
|
||||||
|
.. doxygenfunction:: UserAudioStreamStop
|
||||||
|
.. doxygenfunction:: UserAudioInputStreamStart
|
||||||
|
.. doxygenfunction:: UserAudioInputStreamStop
|
||||||
|
.. doxygenfunction:: UserAudioOutputStreamStart
|
||||||
|
.. doxygenfunction:: UserAudioOutputStreamStop
|
||||||
|
|
||||||
This function is called when the audio stream from device to host
|
Host Active Functions
|
||||||
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.
|
The following function can be used to signal that the device is connected to a valid host.
|
||||||
|
|
||||||
This is called on a change in state.
|
.. doxygenfunction:: UserHostActive
|
||||||
|
|
||||||
.. c:function:: void AudioStreamStart(int active)
|
|
||||||
|
|
||||||
:param active: Indicates if the host is active or not. 1 for active else 0.
|
|
||||||
|
|
||||||
|
|
||||||
HID Controls
|
HID Controls
|
||||||
~~~~~~~~~~~~
|
------------
|
||||||
|
|
||||||
The following function is called when the device wishes to read physical user input (buttons etc).
|
The following function is called when the device wishes to read physical user input (buttons etc).
|
||||||
|
The function should write relevant HID bits into this array. The bit ordering and functionality is defined by the HID report descriptor used.
|
||||||
|
|
||||||
.. c:function:: void UserReadHIDButtons(unsigned char hidData[])
|
.. doxygenfunction:: UserHIDGetData
|
||||||
|
|
||||||
: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.
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
.. _usb_audio_sec_architecture:
|
.. _usb_audio_sec_architecture:
|
||||||
|
|
||||||
Software Architecture
|
Software Architecture
|
||||||
---------------------
|
*********************
|
||||||
|
|
||||||
This section describes the required software architecture of a USB Audio device implemented using `lib_xua`, its dependencies and other supporting libraries.
|
This section describes the required software architecture of a USB Audio device implemented using `lib_xua`, its dependencies and other supporting libraries.
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
|
|
||||||
Features & Options
|
Additional Features
|
||||||
------------------
|
*******************
|
||||||
|
|
||||||
The previous section describes the use of core functionality contained within ``lib_xua``
|
The previous chapter describes the use of core functionality contained within ``lib_xua``
|
||||||
This seciton details enabling additional features with supported external dependencies, for example,
|
This seciton details enabling additional features with supported external dependencies, for example,
|
||||||
``lib_xua`` can provide S/PDIF output though the used of ``lib_spdif``
|
``lib_xua`` can provide S/PDIF output though the used of ``lib_spdif``
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
S/PDIF Receive
|
S/PDIF Receive
|
||||||
~~~~~~~~~~~~~~
|
==============
|
||||||
|
|
||||||
``lib_xua`` supports the development of devices with S/PDIF receive functionality through the use of
|
``lib_xua`` supports the development of devices with S/PDIF receive functionality through the use of
|
||||||
``lib_spdif``. The XMOS S/PDIF receiver runs in a single core and supports rates up to 192kHz.
|
``lib_spdif``. The XMOS S/PDIF receiver runs in a single core and supports rates up to 192kHz.
|
||||||
@@ -20,11 +20,11 @@ Finally, a channel for the output samples must be declared, note, this should be
|
|||||||
|
|
||||||
The S/PDIF receiver should be called on the appropriate tile::
|
The S/PDIF receiver should be called on the appropriate tile::
|
||||||
|
|
||||||
SpdifReceive(p_spdif_rx, c_spdif_rx, 1, clk_spd_rx);
|
spdif_rx(c_spdif_rx,p_spdif_rx,clk_spd_rx,192000);
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
It is recomended to use the value 1 for the ``initial_divider`` parameter
|
It is recomended to use the value 192000 for the ``sample_freq_estimate`` parameter
|
||||||
|
|
||||||
With the steps above an S/PDIF stream can be captured by the xCORE. To be functionally useful the audio
|
With the steps above an S/PDIF stream can be captured by the xCORE. To be functionally useful the audio
|
||||||
master clock must be able to synchronise to this external digital stream. Additionally, the host can be
|
master clock must be able to synchronise to this external digital stream. Additionally, the host can be
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
S/PDIF Transmit
|
S/PDIF Transmit
|
||||||
~~~~~~~~~~~~~~~
|
===============
|
||||||
|
|
||||||
``lib_xua`` supports the development of devices with S/PDIF transmit functionality through the use of
|
``lib_xua`` supports the development of devices with S/PDIF transmit functionality through the use of
|
||||||
``lib_spdif``. The XMOS S/PDIF transmitter runs in a single core and supports rates up to 192kHz.
|
``lib_spdif``. The XMOS S/PDIF transmitter runs in a single core and supports rates up to 192kHz.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|appendix|
|
|appendix|
|
||||||
|
|
||||||
Known Issues
|
Known Issues
|
||||||
------------
|
************
|
||||||
|
|
||||||
- Quad-SPI DFU will corrupt the factory image with tools version < 14.0.4 due to an issue with libquadflash
|
- Quad-SPI DFU will corrupt the factory image with tools version < 14.0.4 due to an issue with libquadflash
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,7 @@
|
|||||||
.. include:: ../../../README.rst
|
.. include:: ../../../README.rst
|
||||||
|
|
||||||
About This Document
|
About This Document
|
||||||
~~~~~~~~~~~~~~~~~~~
|
===================
|
||||||
|
|
||||||
|
|
||||||
This document describes the structure of ``lib_xua``, its use and resources required. It also covers some implementation detail.
|
This document describes the structure of ``lib_xua``, its use and resources required. It also covers some implementation detail.
|
||||||
|
|
||||||
@@ -18,7 +17,7 @@ the XMOS tool chain and XC language.
|
|||||||
Options <opt>
|
Options <opt>
|
||||||
Advanced Usage <using_adv>
|
Advanced Usage <using_adv>
|
||||||
Additional Features <feat>
|
Additional Features <feat>
|
||||||
Software Detail <sw>
|
Implementation Detail <sw>
|
||||||
API <api>
|
API <api>
|
||||||
Known Issues <issues>
|
Known Issues <issues>
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
.. _sec_options:
|
.. _sec_options:
|
||||||
|
|
||||||
Options
|
Options
|
||||||
-------
|
*******
|
||||||
|
|
||||||
This section describes key options of ``lib_xua``. These are typically controlled using build time defines.
|
This section describes key options of ``lib_xua``. These are typically controlled using build time defines.
|
||||||
Where something must be defined, it is recommended this is done in `xua_conf.h` but could also be done in the application Makefile.
|
Where something must be defined, it is recommended this is done in `xua_conf.h` but could also be done in the application Makefile.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
|newpage|
|
|newpage|
|
||||||
|
|
||||||
USB Audio Class Version
|
USB Audio Class Version
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~
|
=======================
|
||||||
|
|
||||||
The codebase supports USB Audio Class versions 1.0 and 2.0.
|
The codebase supports USB Audio Class versions 1.0 and 2.0.
|
||||||
|
|
||||||
@@ -15,22 +15,22 @@ Additional improvements, amongst others, include:
|
|||||||
- Extensive support for interrupts to inform the host about dynamic changes that occur to different entities such as Clocks etc
|
- Extensive support for interrupts to inform the host about dynamic changes that occur to different entities such as Clocks etc
|
||||||
|
|
||||||
Driver Support
|
Driver Support
|
||||||
..............
|
--------------
|
||||||
|
|
||||||
Audio Class 1.0
|
Audio Class 1.0
|
||||||
+++++++++++++++
|
^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
Audio Class 1.0 is fully supported in Apple OSX. Audio Class 1.0 is fully supported in all modern Microsoft Windows operating systems (i.e. Windows XP and later).
|
Audio Class 1.0 is fully supported in Apple OSX. Audio Class 1.0 is fully supported in all modern Microsoft Windows operating systems (i.e. Windows XP and later).
|
||||||
|
|
||||||
Audio Class 2.0
|
Audio Class 2.0
|
||||||
+++++++++++++++
|
^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
Audio Class 2.0 is fully supported in Apple OSX since version 10.6.4. Starting with Windows 10, release 1703, a USB Audio 2.0 driver is shipped with Windows.
|
Audio Class 2.0 is fully supported in Apple OSX since version 10.6.4. Starting with Windows 10, release 1703, a USB Audio 2.0 driver is shipped with Windows.
|
||||||
|
|
||||||
Third party Windows drivers are also available, however, documentation of these is beyond the scope of this document, please contact XMOS for further details.
|
Third party Windows drivers are also available, however, documentation of these is beyond the scope of this document, please contact XMOS for further details.
|
||||||
|
|
||||||
Audio Class 1.0 Mode and Fall-back
|
Audio Class 1.0 Mode and Fall-back
|
||||||
..................................
|
----------------------------------
|
||||||
|
|
||||||
The default for XMOS USB Audio applications is to run as a high-speed Audio Class 2.0
|
The default for XMOS USB Audio applications is to run as a high-speed Audio Class 2.0
|
||||||
device. However, some products may prefer to run in Audio Class 1.0 mode, this is normally to
|
device. However, some products may prefer to run in Audio Class 1.0 mode, this is normally to
|
||||||
@@ -64,7 +64,7 @@ Due to bandwidth limitations of full-speed USB the following sample-frequency re
|
|||||||
|
|
||||||
|
|
||||||
Related Defines
|
Related Defines
|
||||||
................
|
---------------
|
||||||
|
|
||||||
:ref:`opt_audio_class_defines` descibes the defines that effect audio class selection.
|
:ref:`opt_audio_class_defines` descibes the defines that effect audio class selection.
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
.. _sec_opt_audio_formats:
|
.. _sec_opt_audio_formats:
|
||||||
|
|
||||||
Audio Stream Formats
|
Audio Stream Formats
|
||||||
~~~~~~~~~~~~~~~~~~~~
|
====================
|
||||||
|
|
||||||
The design currently supports up to three different stream formats for playback, selectable at
|
The design currently supports up to three different stream formats for playback, selectable at
|
||||||
run time. This is implemented using standard Alternative Settings to the Audio Streaming interfaces.
|
run time. This is implemented using standard Alternative Settings to the Audio Streaming interfaces.
|
||||||
@@ -32,7 +32,7 @@ By default the design exposes two sets of Alternative Settings for the playback
|
|||||||
24-bit playback. When DSD is enabled an additional (32-bit) alternative is exposed.
|
24-bit playback. When DSD is enabled an additional (32-bit) alternative is exposed.
|
||||||
|
|
||||||
Audio Subslot
|
Audio Subslot
|
||||||
.............
|
-------------
|
||||||
|
|
||||||
An audio subslot holds a single audio sample. See `USB Device Class Definition for Audio Data Formats
|
An audio subslot holds a single audio sample. See `USB Device Class Definition for Audio Data Formats
|
||||||
<http://www.usb.org/developers/devclass_docs/Audio2.0_final.zip>`_ for full details.
|
<http://www.usb.org/developers/devclass_docs/Audio2.0_final.zip>`_ for full details.
|
||||||
@@ -73,7 +73,7 @@ Values other than 4 may be used for the following reasons:
|
|||||||
|
|
||||||
|
|
||||||
Audio Sample Resolution
|
Audio Sample Resolution
|
||||||
.......................
|
-----------------------
|
||||||
|
|
||||||
An audio sample is represented using a number of bits (`bBitResolution`) less than or equal to the number
|
An audio sample is represented using a number of bits (`bBitResolution`) less than or equal to the number
|
||||||
of total bits available in the audio subslot i.e. `bBitResolution` <= `bSubslotSize` * 8). The design
|
of total bits available in the audio subslot i.e. `bBitResolution` <= `bSubslotSize` * 8). The design
|
||||||
@@ -99,7 +99,7 @@ supports values 16, 24 and 32.
|
|||||||
|
|
||||||
|
|
||||||
Audio Format
|
Audio Format
|
||||||
............
|
------------
|
||||||
|
|
||||||
The design supports two audio formats, PCM and, when "Native" DSD is enabled, Direct Stream Digital (DSD).
|
The design supports two audio formats, PCM and, when "Native" DSD is enabled, Direct Stream Digital (DSD).
|
||||||
A DSD capable DAC is required for the latter.
|
A DSD capable DAC is required for the latter.
|
||||||
@@ -122,7 +122,6 @@ The following options are supported:
|
|||||||
|
|
||||||
* UAC_FORMAT_TYPEI_PCM
|
* UAC_FORMAT_TYPEI_PCM
|
||||||
|
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
Currently DSD is only supported on the output/playback stream
|
Currently DSD is only supported on the output/playback stream
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
|newpage|
|
|newpage|
|
||||||
|
|
||||||
Channel Counts and Sample Rates
|
Channel Counts and Sample Rates
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
===============================
|
||||||
|
|
||||||
The codebase is fully configurable in relation to channel counts and sample rates.
|
The codebase is fully configurable in relation to channel counts and sample rates.
|
||||||
Practical limitations of these are normally based on USB packet size restrictions and I/O
|
Practical limitations of these are normally based on USB packet size restrictions and I/O
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
|newpage|
|
|newpage|
|
||||||
|
|
||||||
Direct Stream Digital (DSD)
|
Direct Stream Digital (DSD)
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
===========================
|
||||||
|
|
||||||
Direct Stream Digital (DSD) is used for digitally encoding audio signals on Super Audio CDs (SACD).
|
Direct Stream Digital (DSD) is used for digitally encoding audio signals on Super Audio CDs (SACD).
|
||||||
It uses pulse-density modulation (PDM) encoding.
|
It uses pulse-density modulation (PDM) encoding.
|
||||||
@@ -48,7 +48,7 @@ If only DoP functionality is desired the Native implementation can be disabled w
|
|||||||
|
|
||||||
|
|
||||||
DSD over PCM (DoP)
|
DSD over PCM (DoP)
|
||||||
..................
|
------------------
|
||||||
|
|
||||||
DoP support follows the method described in the `DoP Open Standard 1.1
|
DoP support follows the method described in the `DoP Open Standard 1.1
|
||||||
<http://dsd-guide.com/sites/default/files/white-papers/DoP_openStandard_1v1.pdf>`_.
|
<http://dsd-guide.com/sites/default/files/white-papers/DoP_openStandard_1v1.pdf>`_.
|
||||||
@@ -81,14 +81,14 @@ of rate.
|
|||||||
DoP requires bit-perfect transmission - therefore any audio/volume processing will break the stream.
|
DoP requires bit-perfect transmission - therefore any audio/volume processing will break the stream.
|
||||||
|
|
||||||
"Native" vs DoP
|
"Native" vs DoP
|
||||||
~~~~~~~~~~~~~~~
|
---------------
|
||||||
|
|
||||||
Since the DoP specification requires header bytes this eats into the data bandwidth. The "Native" implementation
|
Since the DoP specification requires header bytes this eats into the data bandwidth. The "Native" implementation
|
||||||
has no such overhead and can therefore transfer the same DSD rate and half the effective PCM rate of DoP.
|
has no such overhead and can therefore transfer the same DSD rate and half the effective PCM rate of DoP.
|
||||||
Such a property may be desired when upporting DSD128 without exposing a 352.8kHz PCM rate, for example.
|
Such a property may be desired when upporting DSD128 without exposing a 352.8kHz PCM rate, for example.
|
||||||
|
|
||||||
Ports
|
Ports
|
||||||
.....
|
-----
|
||||||
|
|
||||||
The codebase expects 1-bit ports to be defined in the application XN file for the DSD data and
|
The codebase expects 1-bit ports to be defined in the application XN file for the DSD data and
|
||||||
clock lines for example::
|
clock lines for example::
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
|newpage|
|
|newpage|
|
||||||
|
|
||||||
I2S/TDM
|
I2S/TDM
|
||||||
~~~~~~~
|
=======
|
||||||
|
|
||||||
I2S/TDM is typically fundamental to most products and is built into the ``XUA_AudioHub()`` core.
|
I2S/TDM is typically fundamental to most products and is built into the ``XUA_AudioHub()`` core.
|
||||||
|
|
||||||
@@ -23,11 +23,14 @@ The defines in :ref:`opt_i2s_defines` effect the I2S implementation.
|
|||||||
- The desired number of input channels via I2S (0 for disabled)
|
- The desired number of input channels via I2S (0 for disabled)
|
||||||
- N/A (Must be defined)
|
- N/A (Must be defined)
|
||||||
* - ``XUA_PCM_FORMAT``
|
* - ``XUA_PCM_FORMAT``
|
||||||
- Enabled either TDM or I2S mode
|
- Enables either TDM or I2S mode
|
||||||
- ``XUA_PCM_FORMAT_I2S``
|
- ``XUA_PCM_FORMAT_I2S``
|
||||||
* - ``CODEC_MASTER``
|
* - ``CODEC_MASTER``
|
||||||
- Sets is xCORE is I2S master or slave
|
- Sets if xCORE is I2S master or slave
|
||||||
- ``0`` (xCORE is master)
|
- ``0`` (xCORE is master)
|
||||||
|
* - ``XUA_I2S_N_BITS``
|
||||||
|
- I2S/TDM word length (16, 32-bit supported)
|
||||||
|
- ``32``
|
||||||
|
|
||||||
The I2S code expects that the ports required for I2S (master clock, LR-clock, bit-clock and data lines) are be defined in the application XN file in the relevant `Tile``.
|
The I2S code expects that the ports required for I2S (master clock, LR-clock, bit-clock and data lines) are be defined in the application XN file in the relevant `Tile``.
|
||||||
For example::
|
For example::
|
||||||
@@ -42,8 +45,16 @@ For example::
|
|||||||
<Port Location="XS1_PORT_1G" Name="PORT_I2S_ADC1"/>
|
<Port Location="XS1_PORT_1G" Name="PORT_I2S_ADC1"/>
|
||||||
</Tile>
|
</Tile>
|
||||||
|
|
||||||
All of the I2S related ports must be 1-bit ports.
|
All of the I2S/TDM related ports must be 1-bit ports.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
TDM mode allows 8 channels (rather than 2) to be supplied on each dataline.
|
TDM mode allows 8 channels (rather than 2) to be supplied on each data-line.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
Data output/input is in "I2S" format, rather than, say "left-justified" or "right-justified" formats.
|
||||||
|
I2S format specifies a single bit-clock delay after the LR-clock transition before sample-data is driven/received.
|
||||||
|
This also applies to TDM mode. TDM support in ADC/DAC hardware is quite varied, an "offset" value may need to be programmed into
|
||||||
|
the external device for compatible operation.
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
|newpage|
|
|newpage|
|
||||||
|
|
||||||
Code Location
|
Code Location
|
||||||
~~~~~~~~~~~~~
|
=============
|
||||||
|
|
||||||
When designing a system there is a choice as to which hardware resources to use for each interface.
|
When designing a system there is a choice as to which hardware resources to use for each interface.
|
||||||
In a multi-tile system the codebase needs to be informed as to which tiles to use for these hardware
|
In a multi-tile system the codebase needs to be informed as to which tiles to use for these hardware
|
||||||
@@ -21,7 +21,7 @@ full listing of these ``TILE`` defines.
|
|||||||
- Description
|
- Description
|
||||||
- Default
|
- Default
|
||||||
* - ``AUDIO_IO_TILE``
|
* - ``AUDIO_IO_TILE``
|
||||||
- Tile on which I2S, ADAT Rx, S/PDIF Rx & mixer resides
|
- Tile on which I2S/TDM, ADAT Rx, S/PDIF Rx & mixer resides
|
||||||
- ``0``
|
- ``0``
|
||||||
* - ``XUD_TILE``
|
* - ``XUD_TILE``
|
||||||
- Tile on which USB resides, including buffering for all USB interfaces/endppoints
|
- Tile on which USB resides, including buffering for all USB interfaces/endppoints
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|newpage|
|
|newpage|
|
||||||
|
|
||||||
MIDI
|
MIDI
|
||||||
~~~~
|
====
|
||||||
|
|
||||||
The codebase supports MIDI input/output over USB as per `Universal Serial Bus Device Class Definition for MIDI Devices <https://www.usb.org/sites/default/files/midi10.pdf>`_.
|
The codebase supports MIDI input/output over USB as per `Universal Serial Bus Device Class Definition for MIDI Devices <https://www.usb.org/sites/default/files/midi10.pdf>`_.
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
|newpage|
|
|newpage|
|
||||||
|
|
||||||
Mixer
|
Mixer
|
||||||
~~~~~
|
=====
|
||||||
|
|
||||||
The codebase supports audio mixing functionality with highly flexible routing options.
|
The codebase supports audio mixing functionality with highly flexible routing options.
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
|newpage|
|
|newpage|
|
||||||
|
|
||||||
Other Options
|
Other Options
|
||||||
~~~~~~~~~~~~~
|
=============
|
||||||
|
|
||||||
There are a few other, lesser used, options available.
|
There are a few other, lesser used, options available.
|
||||||
|
|
||||||
|
|
||||||
.. _opt_other_defines:
|
.. _opt_other_defines:
|
||||||
|
|
||||||
.. list-table:: Other defines
|
.. list-table:: Other defines
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
|newpage|
|
|newpage|
|
||||||
|
|
||||||
PDM Microphones
|
PDM Microphones
|
||||||
~~~~~~~~~~~~~~~
|
===============
|
||||||
|
|
||||||
The codebase supports input from up to 8 PDM microphones.
|
The codebase supports input from up to 8 PDM microphones.
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
|newpage|
|
|newpage|
|
||||||
|
|
||||||
S/PDIF Receive
|
S/PDIF Receive
|
||||||
~~~~~~~~~~~~~~
|
==============
|
||||||
|
|
||||||
The codebase supports a single, stereo, S/PDIF receiver. This can be input via 75 Ω coaxial or optical fibre.
|
The codebase supports a single, stereo, S/PDIF receiver. This can be input via 75 Ω coaxial or optical fibre.
|
||||||
In order to provide S/PDIF functionality ``lib_xua`` uses ``lib_spdif`` (https://www.github.com/xmos/lib_spdif).
|
In order to provide S/PDIF functionality ``lib_xua`` uses ``lib_spdif`` (https://www.github.com/xmos/lib_spdif).
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
|newpage|
|
|newpage|
|
||||||
|
|
||||||
S/PDIF Transmit
|
S/PDIF Transmit
|
||||||
~~~~~~~~~~~~~~~
|
===============
|
||||||
|
|
||||||
The codebase supports a single, stereo, S/PDIF transmitter. This can be output over 75 Ω coaxial or optical fibre.
|
The codebase supports a single, stereo, S/PDIF transmitter. This can be output over 75 Ω coaxial or optical fibre.
|
||||||
In order to provide S/PDIF transmit functionality ``lib_xua`` uses ``lib_spdif`` (https://www.github.com/xmos/lib_spdif).
|
In order to provide S/PDIF transmit functionality ``lib_xua`` uses ``lib_spdif`` (https://www.github.com/xmos/lib_spdif).
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
Strings and ID's
|
Strings and ID's
|
||||||
~~~~~~~~~~~~~~~~
|
================
|
||||||
|
|
||||||
The codebase includes various strings and ID's that should be customised to match the product requirements.
|
The codebase includes various strings and ID's that should be customised to match the product requirements.
|
||||||
These are listed in ::ref:`opt_strings_defines`.
|
These are listed in ::ref:`opt_strings_defines`.
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
|
|
||||||
|newpage|
|
|newpage|
|
||||||
|
|
||||||
Synchronisation
|
Synchronisation & Clocking
|
||||||
~~~~~~~~~~~~~~~
|
==========================
|
||||||
|
|
||||||
The codebase supports "Synchronous" and "Asynchronous" modes for USB transfer as defined by the
|
The codebase supports "Synchronous" and "Asynchronous" modes for USB transfer as defined by the
|
||||||
USB specification(s).
|
USB specification(s).
|
||||||
|
|
||||||
Asynchronous mode (``XUA_SYNCMODE_ASYNC``) has the advantage that the device is clock-master. This means that
|
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
|
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
|
synchronise it's master clock to an external digital input stream e.g. S/PDIF thus avoiding sample-rate
|
||||||
conversion.
|
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
|
||||||
@@ -39,10 +39,17 @@ Setting the synchronisation mode of the device is done using the define in :ref:
|
|||||||
- USB synchronisation mode
|
- USB synchronisation mode
|
||||||
- ``XUA_SYNCMODE_ASYNC``
|
- ``XUA_SYNCMODE_ASYNC``
|
||||||
|
|
||||||
When operating in synchronous mode an external Cirrus Logic CS2100 device is required for master clock
|
When operating in asynchronous mode xcore.ai based devices will be configured, by default, to use their internal
|
||||||
generation. The codebase expects to drive a synchronisation signal to this external device
|
"Applications" PLL to generated an appropriate master-clock signal. To disable this ``XUA_USE_APP_PLL`` should be
|
||||||
|
set to ``0``. For all other devices the developer is expected to supply external master-clock generation circuitry.
|
||||||
|
|
||||||
The programmer should ensure the define in :ref:`opt_sync_ref_defines` is set appropriately.
|
When operating in synchronous mode an xcore.ai based device, by default, will be configured to used it's internal
|
||||||
|
"application" PLL to generate a master-clock synchronised to the USB host.
|
||||||
|
|
||||||
|
xcore-200 based devices do not have this application PLL and so an external Cirrus Logic CS2100 device is required
|
||||||
|
for master clock generation. The codebase expects to drive a synchronisation signal to this external device.
|
||||||
|
|
||||||
|
In this case the developer should ensure the define in :ref:`opt_sync_ref_defines` is set appropriately.
|
||||||
|
|
||||||
.. _opt_sync_ref_defines:
|
.. _opt_sync_ref_defines:
|
||||||
|
|
||||||
@@ -64,3 +71,26 @@ This may be a port of any bit-width, however, connection to bit[0] is assumed::
|
|||||||
|
|
||||||
Configuration of the external CS2100 device (typically via I2C) is beyond the scope of this document.
|
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.
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
Overview
|
Overview
|
||||||
--------
|
********
|
||||||
|
|
||||||
|
|
||||||
.. table::
|
.. table::
|
||||||
:class: vertical-borders
|
:class: vertical-borders
|
||||||
@@ -26,7 +25,7 @@ Overview
|
|||||||
| +---------------------------------------------------------------------------------------------+
|
| +---------------------------------------------------------------------------------------------+
|
||||||
| | `USB Midi Device Class 1.0 <http://www.usb.org/developers/devclass_docs/midi10.pdf>`_ |
|
| | `USB Midi Device Class 1.0 <http://www.usb.org/developers/devclass_docs/midi10.pdf>`_ |
|
||||||
+---------------------------------+---------------------------------------------------------------------------------------------+
|
+---------------------------------+---------------------------------------------------------------------------------------------+
|
||||||
| Audio | I2S/TDM |
|
| Audio | I2S/TDM (16/32-bit) |
|
||||||
| +---------------------------------------------------------------------------------------------+
|
| +---------------------------------------------------------------------------------------------+
|
||||||
| | S/PDIF |
|
| | S/PDIF |
|
||||||
| +---------------------------------------------------------------------------------------------+
|
| +---------------------------------------------------------------------------------------------+
|
||||||
@@ -75,5 +74,3 @@ Overview
|
|||||||
| Reference code is maintained by XMOS Limited. |
|
| Reference code is maintained by XMOS Limited. |
|
||||||
+-------------------------------------------------------------------------------------------------------------------------------+
|
+-------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
|
|
||||||
Implementation Detail
|
Implementation Detail
|
||||||
---------------------
|
*********************
|
||||||
|
|
||||||
This section examines the implementation of the various components that make up ``lib_xua``. It also examines the integration of dependencies and supporting libraries.
|
This chapter examines the implementation of the various components that make up ``lib_xua``. It also examines the integration of dependencies and supporting libraries.
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
|
|
||||||
@@ -10,8 +10,8 @@ This section examines the implementation of the various components that make up
|
|||||||
sw_ep0
|
sw_ep0
|
||||||
sw_xud
|
sw_xud
|
||||||
sw_clocking
|
sw_clocking
|
||||||
sw_spdif
|
|
||||||
sw_mixer
|
sw_mixer
|
||||||
|
sw_spdif
|
||||||
sw_spdif_rx
|
sw_spdif_rx
|
||||||
sw_adat_rx
|
sw_adat_rx
|
||||||
sw_midi
|
sw_midi
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
|newpage|
|
|newpage|
|
||||||
|
|
||||||
ADAT Receive
|
ADAT Receive
|
||||||
------------
|
============
|
||||||
|
|
||||||
The ADAT receive component receives up to eight channels of audio at a sample rate
|
The ADAT receive component receives up to eight channels of audio at a sample rate
|
||||||
of 44.1kHz or 48kHz. The API for calling the receiver functions is
|
of 44.1kHz or 48kHz. The API for calling the receiver functions is
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
.. _usb_audio_sec_audio:
|
.. _usb_audio_sec_audio:
|
||||||
|
|
||||||
Audio Hub
|
Audio Hub
|
||||||
.........
|
=========
|
||||||
|
|
||||||
The Audio Hub task performs many functions. It receives and transmits samples from/to the Decoupler
|
The Audio Hub task performs many functions. It receives and transmits samples from/to the Decoupler
|
||||||
or Mixer core over a channel.
|
or Mixer core over a channel.
|
||||||
@@ -96,9 +96,8 @@ Two master clock frequencies to support 44.1kHz and 48kHz audio frequencies (e.g
|
|||||||
and 12.288/24.576MHz respectively). This master clock input is then provided to the external audio
|
and 12.288/24.576MHz respectively). This master clock input is then provided to the external audio
|
||||||
hardware and the xCORE device.
|
hardware and the xCORE device.
|
||||||
|
|
||||||
|
|
||||||
Port Configuration (xCORE Master)
|
Port Configuration (xCORE Master)
|
||||||
+++++++++++++++++++++++++++++++++
|
---------------------------------
|
||||||
|
|
||||||
The default software configuration is xCORE is I2S master. That is, the XMOS device provides the BCLK and LRCLK signals to the external audio hardware
|
The default software configuration is xCORE is I2S master. That is, the XMOS device provides the BCLK and LRCLK signals to the external audio hardware
|
||||||
|
|
||||||
@@ -143,7 +142,7 @@ before the data (as required by the I2S standard) and alternates between high an
|
|||||||
and right channels of audio.
|
and right channels of audio.
|
||||||
|
|
||||||
Changing Audio Sample Frequency
|
Changing Audio Sample Frequency
|
||||||
+++++++++++++++++++++++++++++++
|
-------------------------------
|
||||||
|
|
||||||
.. _usb_audio_sec_chang-audio-sample:
|
.. _usb_audio_sec_chang-audio-sample:
|
||||||
|
|
||||||
@@ -159,5 +158,3 @@ functions.
|
|||||||
|
|
||||||
Once this is complete, the I2S/TDM interface (i.e. the main loop in AudioHub) is restarted at the new frequency.
|
Once this is complete, the I2S/TDM interface (i.e. the main loop in AudioHub) is restarted at the new frequency.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
.. _usb_audio_sec_clock_recovery:
|
.. _usb_audio_sec_clock_recovery:
|
||||||
|
|
||||||
External Clock Recovery (Clock Gen)
|
External Clock Recovery (Clock Gen)
|
||||||
-----------------------------------
|
===================================
|
||||||
|
|
||||||
To provide an audio master clock an application may use selectable oscillators, clock
|
To provide an audio master clock an application may use selectable oscillators, clock
|
||||||
generation IC or, in the case of xCORE.ai devices, integrated secondary PLL, to generate fixed
|
generation IC or, in the case of xCORE.ai devices, integrated secondary PLL, to generate fixed
|
||||||
@@ -14,7 +14,7 @@ It may also use an external PLL/Clock Multiplier to generate a master clock base
|
|||||||
the xCORE.
|
the xCORE.
|
||||||
|
|
||||||
Using an external PLL/Clock Multiplier allows an Asynchronous mode design to lock to an external
|
Using an external PLL/Clock Multiplier allows an Asynchronous mode design to lock to an external
|
||||||
clock source from a digital stream (e.g. S/PDIF or ADAT input). The code-base supports the Cirrus
|
clock source from a digital stream (e.g. S/PDIF or ADAT input). The codebase supports the Cirrus
|
||||||
Logic CS2100 device for this purpose. Other devices may be supported via code modification.
|
Logic CS2100 device for this purpose. Other devices may be supported via code modification.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|||||||
@@ -3,14 +3,14 @@
|
|||||||
.. _usb_audio_sec_usb:
|
.. _usb_audio_sec_usb:
|
||||||
|
|
||||||
Endpoint 0: Management and Control
|
Endpoint 0: Management and Control
|
||||||
..................................
|
==================================
|
||||||
|
|
||||||
All USB devices must support a mandatory control endpoint, Endpoint 0. This controls the management tasks of the USB device.
|
All USB devices must support a mandatory control endpoint, Endpoint 0. This controls the management tasks of the USB device.
|
||||||
|
|
||||||
These tasks can be generally split into enumeration, audio configuration and firmware upgrade requests.
|
These tasks can be generally split into enumeration, audio configuration and firmware upgrade requests.
|
||||||
|
|
||||||
Enumeration
|
Enumeration
|
||||||
~~~~~~~~~~~
|
-----------
|
||||||
|
|
||||||
When the device is first attached to a host, enumeration occurs. This process involves the host interrogating the device as to its functionality. The device does this by presenting several interfaces to the host via a set of descriptors.
|
When the device is first attached to a host, enumeration occurs. This process involves the host interrogating the device as to its functionality. The device does this by presenting several interfaces to the host via a set of descriptors.
|
||||||
|
|
||||||
@@ -41,12 +41,13 @@ The function may also return ``XUD_RES_RST`` if a bus-reset has been issued onto
|
|||||||
Since the ``USB_StandardRequests()`` function STALLs an unknown request, the endpoint 0 code must first parse the ``USB_SetupPacket_t`` structure to handle device specific requests and then call ``USB_StandardRequests()`` as required.
|
Since the ``USB_StandardRequests()`` function STALLs an unknown request, the endpoint 0 code must first parse the ``USB_SetupPacket_t`` structure to handle device specific requests and then call ``USB_StandardRequests()`` as required.
|
||||||
|
|
||||||
Over-riding Standard Requests
|
Over-riding Standard Requests
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
-----------------------------
|
||||||
|
|
||||||
The USB Audio design "over-rides" some of the requests handled by ``USB_StandardRequests()``, for example it uses the SET_INTERFACE request to indicate if the host is streaming audio to the device. In this case the setup packet is parsed, the relevant action taken, the ``USB_StandardRequests()`` is still called to handle the response to the host.
|
The USB Audio design "over-rides" some of the requests handled by ``USB_StandardRequests()``, for example it uses the SET_INTERFACE request to indicate if the host is streaming audio to the device. In this case the setup packet is parsed, the relevant action taken, the ``USB_StandardRequests()`` is still called to handle the response to the host.
|
||||||
|
|
||||||
Class Requests
|
Class Requests
|
||||||
~~~~~~~~~~~~~~
|
--------------
|
||||||
|
|
||||||
Before making the call to ``USB_StandardRequests()`` the setup packet is parsed for Class requests. These are handled in functions such as ``AudioClassRequests_1()``, ``AudioClassRequests_2``, ``DFUDeviceRequests()`` etc depending on the type of request.
|
Before making the call to ``USB_StandardRequests()`` the setup packet is parsed for Class requests. These are handled in functions such as ``AudioClassRequests_1()``, ``AudioClassRequests_2``, ``DFUDeviceRequests()`` etc depending on the type of request.
|
||||||
|
|
||||||
Any device specific requests are handled - in this case Audio Class, MIDI class, DFU requests etc.
|
Any device specific requests are handled - in this case Audio Class, MIDI class, DFU requests etc.
|
||||||
@@ -54,7 +55,7 @@ Any device specific requests are handled - in this case Audio Class, MIDI class,
|
|||||||
Some of the common Audio Class requests and their associated behaviour will now be examined.
|
Some of the common Audio Class requests and their associated behaviour will now be examined.
|
||||||
|
|
||||||
Audio Requests
|
Audio Requests
|
||||||
++++++++++++++
|
^^^^^^^^^^^^^^
|
||||||
|
|
||||||
When the host issues an audio request (e.g. sample rate or volume change), it sends a command to Endpoint 0. Like all requests this is returned from ``USB_GetSetupPacket()``. After some parsing (namely as Class Request to an Audio Interface) the request is handled by either the ``AudioClassRequests_1()`` or ``AudioClassRequests_2()`` function (based on whether the device is running in Audio Class 1.0 or 2.0 mode).
|
When the host issues an audio request (e.g. sample rate or volume change), it sends a command to Endpoint 0. Like all requests this is returned from ``USB_GetSetupPacket()``. After some parsing (namely as Class Request to an Audio Interface) the request is handled by either the ``AudioClassRequests_1()`` or ``AudioClassRequests_2()`` function (based on whether the device is running in Audio Class 1.0 or 2.0 mode).
|
||||||
|
|
||||||
@@ -63,7 +64,7 @@ Note, Audio Class 1.0 Sample rate changes are send to the relevant endpoint, rat
|
|||||||
The ``AudioClassRequests_X()`` functions further parses the request in order to ascertain the correct audio operation to execute.
|
The ``AudioClassRequests_X()`` functions further parses the request in order to ascertain the correct audio operation to execute.
|
||||||
|
|
||||||
Audio Request: Set Sample Rate
|
Audio Request: Set Sample Rate
|
||||||
++++++++++++++++++++++++++++++
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
The ``AudioClassRequests_2()`` function parses the passed ``USB_SetupPacket_t`` structure for a ``CUR`` request of type ``SAM_FREQ_CONTROL`` to a Clock Unit in the devices topology (as described in the devices descriptors).
|
The ``AudioClassRequests_2()`` function parses the passed ``USB_SetupPacket_t`` structure for a ``CUR`` request of type ``SAM_FREQ_CONTROL`` to a Clock Unit in the devices topology (as described in the devices descriptors).
|
||||||
|
|
||||||
@@ -72,7 +73,7 @@ The new sample frequency is extracted and passed via channel to the rest of the
|
|||||||
.. _usb_audio_sec_audio-requ-volume:
|
.. _usb_audio_sec_audio-requ-volume:
|
||||||
|
|
||||||
Audio Request: Volume Control
|
Audio Request: Volume Control
|
||||||
+++++++++++++++++++++++++++++
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
When the host requests a volume change, it
|
When the host requests a volume change, it
|
||||||
sends an audio interface request to Endpoint 0. An array is
|
sends an audio interface request to Endpoint 0. An array is
|
||||||
@@ -102,10 +103,10 @@ to the mixer to change the volume. Mixer commands
|
|||||||
are described in :ref:`usb_audio_sec_mixer`.
|
are described in :ref:`usb_audio_sec_mixer`.
|
||||||
|
|
||||||
Audio Endpoints (Endpoint Buffer and Decoupler)
|
Audio Endpoints (Endpoint Buffer and Decoupler)
|
||||||
...............................................
|
===============================================
|
||||||
|
|
||||||
Endpoint Buffer
|
Endpoint Buffer
|
||||||
~~~~~~~~~~~~~~~
|
---------------
|
||||||
|
|
||||||
All endpoints other that Endpoint 0 are handled in one core. This
|
All endpoints other that Endpoint 0 are handled in one core. This
|
||||||
core is implemented in the file ``ep_buffer.xc``. This core communicates directly with the XUD library.
|
core is implemented in the file ``ep_buffer.xc``. This core communicates directly with the XUD library.
|
||||||
@@ -114,7 +115,7 @@ The USB buffer core is also responsible for feedback calculation based on USB St
|
|||||||
(SOF) notification and reads from the port counter of a port connected to the master clock.
|
(SOF) notification and reads from the port counter of a port connected to the master clock.
|
||||||
|
|
||||||
Decouple
|
Decouple
|
||||||
~~~~~~~~
|
--------
|
||||||
|
|
||||||
The decoupler supplies the USB buffering core with buffers to
|
The decoupler supplies the USB buffering core with buffers to
|
||||||
transmit/receive audio data to/from the host. It marshals these buffers into
|
transmit/receive audio data to/from the host. It marshals these buffers into
|
||||||
@@ -125,7 +126,7 @@ matching the audio rate to the USB packet rate). The decoupler is
|
|||||||
implemented in the file ``decouple.xc``.
|
implemented in the file ``decouple.xc``.
|
||||||
|
|
||||||
Audio Buffering Scheme
|
Audio Buffering Scheme
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~
|
----------------------
|
||||||
|
|
||||||
This scheme is executed by co-operation between the buffering
|
This scheme is executed by co-operation between the buffering
|
||||||
core, the decouple core and the XUD library.
|
core, the decouple core and the XUD library.
|
||||||
@@ -133,7 +134,6 @@ core, the decouple core and the XUD library.
|
|||||||
For data going from the device to the host the following scheme is
|
For data going from the device to the host the following scheme is
|
||||||
used:
|
used:
|
||||||
|
|
||||||
|
|
||||||
#. The Decouple core receives samples from the Audio Hub core and
|
#. The Decouple core receives samples from the Audio Hub core and
|
||||||
puts them into a FIFO. This FIFO is split into packets when data is
|
puts them into a FIFO. This FIFO is split into packets when data is
|
||||||
entered into it. Packets are stored in a format consisting of their
|
entered into it. Packets are stored in a format consisting of their
|
||||||
@@ -152,11 +152,9 @@ used:
|
|||||||
Decouple core that the buffer has been sent and the Decouple core
|
Decouple core that the buffer has been sent and the Decouple core
|
||||||
moves the read pointer of the FIFO.
|
moves the read pointer of the FIFO.
|
||||||
|
|
||||||
|
|
||||||
For data going from the host to the device the following scheme is
|
For data going from the host to the device the following scheme is
|
||||||
used:
|
used:
|
||||||
|
|
||||||
|
|
||||||
#. The Decouple core passes a pointer to the Endpoint Buffer core
|
#. The Decouple core passes a pointer to the Endpoint Buffer core
|
||||||
pointing into a FIFO of data and signals to the XUD library that
|
pointing into a FIFO of data and signals to the XUD library that
|
||||||
the Endpoint Buffer core is ready to receive.
|
the Endpoint Buffer core is ready to receive.
|
||||||
@@ -171,9 +169,8 @@ used:
|
|||||||
#. Upon request from the Audio Hub core, the Decouple core sends
|
#. Upon request from the Audio Hub core, the Decouple core sends
|
||||||
samples to the Audio Hub core by reading samples out of the FIFO.
|
samples to the Audio Hub core by reading samples out of the FIFO.
|
||||||
|
|
||||||
|
|
||||||
Decoupler/Audio Core interaction
|
Decoupler/Audio Core interaction
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
--------------------------------
|
||||||
|
|
||||||
To meet timing requirements of the audio system (i.e Audio Hub/Mixer), the Decoupler
|
To meet timing requirements of the audio system (i.e Audio Hub/Mixer), the Decoupler
|
||||||
core must respond to requests from the audio system to
|
core must respond to requests from the audio system to
|
||||||
@@ -200,7 +197,6 @@ in channel count sized chunks (i.e. ``NUM_USB_CHAN_OUT`` and
|
|||||||
The complete communication scheme is shown in the table below (for non sample
|
The complete communication scheme is shown in the table below (for non sample
|
||||||
frequency change case):
|
frequency change case):
|
||||||
|
|
||||||
|
|
||||||
.. table:: Decouple/Audio System Channel Communication
|
.. table:: Decouple/Audio System Channel Communication
|
||||||
|
|
||||||
+-----------------+-----------------+-----------------------------------------+
|
+-----------------+-----------------+-----------------------------------------+
|
||||||
@@ -242,7 +238,7 @@ frequency change case):
|
|||||||
(this is especially advantageous in the DSD over PCM (DoP) case)
|
(this is especially advantageous in the DSD over PCM (DoP) case)
|
||||||
|
|
||||||
Asynchronous Feedback
|
Asynchronous Feedback
|
||||||
+++++++++++++++++++++
|
---------------------
|
||||||
|
|
||||||
When built to operate in Asynchronous mode the device uses a feedback endpoint to report the rate at which
|
When built to operate in Asynchronous mode the device uses a feedback endpoint to report the rate at which
|
||||||
audio is output/input to/from external audio interfaces/devices. This feedback is in accordance with
|
audio is output/input to/from external audio interfaces/devices. This feedback is in accordance with
|
||||||
@@ -265,7 +261,7 @@ sent to the host. In practice this an explicit feedback endpoint is normally use
|
|||||||
in Microsoft Windows operating systems (see ``UAC_FORCE_FEEDBACK_EP``).
|
in Microsoft Windows operating systems (see ``UAC_FORCE_FEEDBACK_EP``).
|
||||||
|
|
||||||
USB Rate Control
|
USB Rate Control
|
||||||
++++++++++++++++
|
----------------
|
||||||
|
|
||||||
.. _usb_audio_sec_usb-rate-control:
|
.. _usb_audio_sec_usb-rate-control:
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
Audio Controls via Human Interface Device (HID)
|
Audio Controls via Human Interface Device (HID)
|
||||||
------------------------------------------------
|
===============================================
|
||||||
|
|
||||||
The design supports simple audio controls such as play/pause, volume up/down etc via the USB Human
|
The design supports simple audio controls such as play/pause, volume up/down etc via the USB Human
|
||||||
Interface Device Class Specification.
|
Interface Device Class Specification.
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
|newpage|
|
|newpage|
|
||||||
|
|
||||||
MIDI
|
MIDI
|
||||||
----
|
====
|
||||||
|
|
||||||
The MIDI core implements a 31250 baud UART for both input and output. On receiving 32-bit USB MIDI events
|
The MIDI core implements a 31250 baud UART for both input and output. On receiving 32=bit USB MIDI events
|
||||||
from the Endpoint Buffer core, it parses these and translates them to 8-bit MIDI messages which are sent
|
from the Endpoint Buffer core, it parses these and translates them to 8-bit MIDI messages which are sent
|
||||||
over UART. Similarly, incoming 8-bit MIDI messages are aggregated into 32-bit USB-MIDI events and
|
over UART. Similarly, incoming 8-bit MIDI messages are aggregated into 32-bit USB MIDI events and
|
||||||
passed on to the Endpoint Buffer core. The MIDI core is implemented in the file ``usb_midi.xc``.
|
passed on to the Endpoint Buffer core. The MIDI core is implemented in the file ``usb_midi.xc``.
|
||||||
|
|
||||||
The Endpoint Buffer core implements the two Bulk endpoints (one In and one Out) as well as interacting
|
The Endpoint Buffer core implements the two Bulk endpoints (one In and one Out) as well as interacting
|
||||||
|
|||||||
@@ -87,6 +87,9 @@ intended as an example of how you might add mixer control to your own control ap
|
|||||||
intended to be exposed to end users.
|
intended to be exposed to end users.
|
||||||
|
|
||||||
For details, consult the README file in the host_usb_mixer_control directory.
|
For details, consult the README file in the host_usb_mixer_control directory.
|
||||||
|
A list of arguments can also be seen with::
|
||||||
|
|
||||||
|
$ ./xmos_mixer --help
|
||||||
|
|
||||||
The main requirements of this control utility are to
|
The main requirements of this control utility are to
|
||||||
|
|
||||||
@@ -102,78 +105,147 @@ The main requirements of this control utility are to
|
|||||||
functionality to their end users.
|
functionality to their end users.
|
||||||
|
|
||||||
Whilst using the XMOS Host control example application, consider the example of setting the
|
Whilst using the XMOS Host control example application, consider the example of setting the
|
||||||
mixer to perform a loop-back from analogue inputs 1 and 2 to analogue outputs 1 and 2.
|
mixer to perform a loop-back from analogue inputs 1 & 2 to analogue outputs 1 & 2.
|
||||||
|
|
||||||
Firstly consider the inputs to the mixer. The following will displays which channels are mapped
|
.. note::
|
||||||
to which mixer inputs::
|
|
||||||
|
|
||||||
./xmos_mixer --display-aud-channel-map 0
|
The command outputs shown are examples; the actual output will depend on the mixer configuration.
|
||||||
|
|
||||||
The following command will displays which channels could possibly be mapped to mixer inputs. Notice
|
The following will show the index for each device output along with which channel is currently mapped to it.
|
||||||
that analogue inputs 1 and 2 are on mixer inputs 10 and 11::
|
In this example the analogue outputs 1 & 2 are 0 & 1 respectively::
|
||||||
|
|
||||||
./xmos_mixer --display-aud-channel-map-sources 0
|
$ ./xmos_mixer --display-aud-channel-map
|
||||||
|
|
||||||
Now examine the audio output mapping using the following command::
|
Audio Output Channel Map
|
||||||
|
------------------------
|
||||||
|
|
||||||
./xmos_mixer --display-aud-channel-map 0
|
0 (DEVICE OUT - Analogue 1) source is 0 (DAW OUT - Analogue 1)
|
||||||
|
1 (DEVICE OUT - Analogue 2) source is 1 (DAW OUT - Analogue 2)
|
||||||
|
2 (DEVICE OUT - SPDIF 1) source is 2 (DAW OUT - SPDIF 1)
|
||||||
|
3 (DEVICE OUT - SPDIF 2) source is 3 (DAW OUT - SPDIF 2)
|
||||||
|
$ _
|
||||||
|
|
||||||
This displays which channels are mapped to which outputs. By default all
|
The DAW Output Map can be seen with::
|
||||||
of these bypass the mixer. We can also see what all the possible
|
|
||||||
mappings are with the following command::
|
|
||||||
|
|
||||||
./xmos_mixer --display-aud-channel-map-sources 0
|
$ ./xmos_mixer --display-daw-channel-map
|
||||||
|
|
||||||
We will now map the first two mixer outputs to physical outputs 1 and 2::
|
DAW Output To Host Channel Map
|
||||||
|
------------------------
|
||||||
|
|
||||||
./xmos_mixer --set-aud-channel-map 0 26
|
0 (DEVICE IN - Analogue 1) source is 4 (DEVICE IN - Analogue 1)
|
||||||
./xmos_mixer --set-aud-channel-map 1 27
|
1 (DEVICE IN - Analogue 2) source is 5 (DEVICE IN - Analogue 2)
|
||||||
|
$ _
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
In both cases, by default, these bypass the mixer.
|
||||||
|
|
||||||
|
The following command will list the channels which can be mapped to the device outputs from the
|
||||||
|
Audio Output Channel Map. Note that, in this example, analogue inputs 1 & 2 are source 4 & 5 and
|
||||||
|
Mix 1 & 2 are source 6 & 7::
|
||||||
|
|
||||||
|
$ ./xmos_mixer --display-aud-channel-map-sources
|
||||||
|
|
||||||
|
Audio Output Channel Map Source List
|
||||||
|
------------------------------------
|
||||||
|
|
||||||
|
0 (DAW OUT - Analogue 1)
|
||||||
|
1 (DAW OUT - Analogue 2)
|
||||||
|
2 (DAW OUT - SPDIF 1)
|
||||||
|
3 (DAW OUT - SPDIF 2)
|
||||||
|
4 (DEVICE IN - Analogue 1)
|
||||||
|
5 (DEVICE IN - Analogue 2)
|
||||||
|
6 (MIX - Mix 1)
|
||||||
|
7 (MIX - Mix 2)
|
||||||
|
$ _
|
||||||
|
|
||||||
|
Using the indices from the previous commands, we will now re-map the first two mixer channels (Mix 1 & Mix 2) to device outputs 1 & 2::
|
||||||
|
|
||||||
|
$ ./xmos_mixer --set-aud-channel-map 0 6
|
||||||
|
$ ./xmos_mixer --set-aud-channel-map 1 7
|
||||||
|
$ _
|
||||||
|
|
||||||
You can confirm the effect of this by re-checking the map::
|
You can confirm the effect of this by re-checking the map::
|
||||||
|
|
||||||
./xmos_mixer --display-aud-channel-map 0
|
$ ./xmos_mixer --display-aud-channel-map
|
||||||
|
|
||||||
This now derives analogue outputs 1 and 2 from the mixer, rather than directly from USB. However,
|
Audio Output Channel Map
|
||||||
since the mixer is still mapped to pass the USB channels through to the outputs there will be no
|
------------------------
|
||||||
|
|
||||||
|
0 (DEVICE OUT - Analogue 1) source is 6 (MIX - Mix 1)
|
||||||
|
1 (DEVICE OUT - Analogue 2) source is 7 (MIX - Mix 2)
|
||||||
|
2 (DEVICE OUT - SPDIF 1) source is 2 (DAW OUT - SPDIF 1)
|
||||||
|
3 (DEVICE OUT - SPDIF 2) source is 3 (DAW OUT - SPDIF 2)
|
||||||
|
$ _
|
||||||
|
|
||||||
|
This now derives analogue outputs 1 & 2 from the mixer, rather than directly from USB. However,
|
||||||
|
since the mixer is mapped, by default, to just pass the USB channels through to the outputs there will be no
|
||||||
functional change.
|
functional change.
|
||||||
|
|
||||||
The mixer nodes need to be individually set. They can be displayed
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
The USB audio reference design has only one unit so the mixer_id argument should always be 0.
|
||||||
|
|
||||||
|
The mixer nodes need to be individually set. The nodes in mixer_id 0 can be displayed
|
||||||
with the following command::
|
with the following command::
|
||||||
|
|
||||||
./xmos_mixer --display-mixer-nodes 0
|
$ ./xmos_mixer --display-mixer-nodes 0
|
||||||
|
|
||||||
To get the audio from the analogue inputs to outputs 1 and 2, nodes 80
|
Mixer Values (0)
|
||||||
and 89 need to be set::
|
----------------
|
||||||
|
|
||||||
./xmos_mixer --set-value 0 80 0
|
Mixer outputs
|
||||||
./xmos_mixer --set-value 0 89 0
|
1 2
|
||||||
|
DAW - Analogue 1 0:[0000.000] 1:[ -inf ]
|
||||||
|
DAW - Analogue 2 2:[ -inf ] 3:[0000.000]
|
||||||
|
DAW - SPDIF 1 4:[ -inf ] 5:[ -inf ]
|
||||||
|
DAW - SPDIF 2 6:[ -inf ] 7:[ -inf ]
|
||||||
|
AUD - Analogue 1 8:[ -inf ] 9:[ -inf ]
|
||||||
|
AUD - Analogue 2 10:[ -inf ] 11:[ -inf ]
|
||||||
|
$ _
|
||||||
|
|
||||||
|
With mixer outputs 1 & 2 mapped to device outputs analogue 1 & 2; to get the audio from the analogue inputs to device
|
||||||
|
outputs mixer_id 0 node 8 and node 11 need to be set to 0db::
|
||||||
|
|
||||||
|
$ ./xmos_mixer --set-value 0 8 0
|
||||||
|
$ ./xmos_mixer --set-value 0 11 0
|
||||||
|
$ _
|
||||||
|
|
||||||
At the same time, the original mixer outputs can be muted::
|
At the same time, the original mixer outputs can be muted::
|
||||||
|
|
||||||
./xmos_mixer --set-value 0 0 -inf
|
$ ./xmos_mixer --set-value 0 0 -inf
|
||||||
./xmos_mixer --set-value 0 9 -inf
|
$ ./xmos_mixer --set-value 0 3 -inf
|
||||||
|
$ _
|
||||||
|
|
||||||
Now audio inputs on analogue 1/2 should be heard on outputs 1/2.
|
Now audio inputs on analogue 1 and 2 should be heard on outputs 1 and 2 respectively.
|
||||||
|
|
||||||
As mentioned above, the flexibility of the mixer is such that there will be multiple ways to create
|
As mentioned above, the flexibility of the mixer is such that there will be multiple ways to create
|
||||||
a particular mix. Another option to create the same routing would be to change the mixer sources
|
a particular mix. Another option to create the same routing would be to change the mixer sources
|
||||||
such that mixer 1/2 outputs come from the analogue inputs.
|
such that mixer outputs 1 and 2 come from the analogue inputs 1 and 2.
|
||||||
|
|
||||||
To demonstrate this, firstly undo the changes above (or simply reset the device)::
|
To demonstrate this, firstly undo the changes above (or simply reset the device)::
|
||||||
|
|
||||||
./xmos_mixer --set-value 0 80 -inf
|
$ ./xmos_mixer --set-value 0 8 -inf
|
||||||
./xmos_mixer --set-value 0 89 -inf
|
$ ./xmos_mixer --set-value 0 11 -inf
|
||||||
./xmos_mixer --set-value 0 0 0
|
$ ./xmos_mixer --set-value 0 0 0
|
||||||
./xmos_mixer --set-value 0 9 0
|
$ ./xmos_mixer --set-value 0 3 0
|
||||||
|
$ _
|
||||||
|
|
||||||
The mixer should now have the default values. The sources for mixer 1/2 can now be changed::
|
The mixer should now have the default values. The sources for mixer 0 output 1 and 2 can now be changed
|
||||||
|
using indices from the Audio Output Channel Map Source List::
|
||||||
|
|
||||||
./xmos_mixer --set-mixer-source 0 0 10
|
$ ./xmos_mixer --set-mixer-source 0 0 4
|
||||||
./xmos_mixer --set-mixer-source 0 1 11
|
|
||||||
|
Set mixer(0) input 0 to device input 4 (AUD - Analogue 1)
|
||||||
|
$ ./xmos_mixer --set-mixer-source 0 1 5
|
||||||
|
|
||||||
|
Set mixer(0) input 1 to device input 5 (AUD - Analogue 2)
|
||||||
|
$ _
|
||||||
|
|
||||||
If you re-run the following command then the first column now has "AUD - Analogue 1 and 2" rather
|
If you re-run the following command then the first column now has "AUD - Analogue 1 and 2" rather
|
||||||
than "DAW (Digital Audio Workstation i.e. the host) - Analogue 1 and 2" confirming the new mapping.
|
than "DAW (Digital Audio Workstation i.e. the host) - Analogue 1 and 2" confirming the new mapping.
|
||||||
Again, by playing audio into analogue inputs 1/2 this can be heard looped through to analogue outputs 1/2::
|
Again, by playing audio into analogue inputs 1/2 this can be heard looped through to analogue outputs 1/2::
|
||||||
|
|
||||||
./xmos_mixer --display-mixer-nodes 0
|
$ ./xmos_mixer --display-mixer-nodes 0
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
|newpage|
|
|newpage|
|
||||||
|
|
||||||
PDM Microphones
|
PDM Microphones
|
||||||
---------------
|
===============
|
||||||
|
|
||||||
The XMOS USB Audio Reference Design firmware is capable of integrating with PDM microphones.
|
The XMOS USB Audio Reference Design firmware is capable of integrating with PDM microphones.
|
||||||
The PDM stream from the microphones is converted to PCM and output to the host via USB.
|
The PDM stream from the microphones is converted to PCM and output to the host via USB.
|
||||||
@@ -46,9 +46,8 @@ After the decimation to the output sample-rate various other steps take place e.
|
|||||||
and compensation etc. Please refer to the documentation provided with ``lib_mic_array`` for further
|
and compensation etc. Please refer to the documentation provided with ``lib_mic_array`` for further
|
||||||
implementation detail and complete feature set.
|
implementation detail and complete feature set.
|
||||||
|
|
||||||
|
|
||||||
PDM Microphone Hardware Characteristics
|
PDM Microphone Hardware Characteristics
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
---------------------------------------
|
||||||
|
|
||||||
The PDM microphones require a *clock input* and provide the PDM signal on a *data output*. All of
|
The PDM microphones require a *clock input* and provide the PDM signal on a *data output*. All of
|
||||||
the PDM microphones must share the same clock signal (buffered on the PCB as appropriate), and
|
the PDM microphones must share the same clock signal (buffered on the PCB as appropriate), and
|
||||||
@@ -78,7 +77,7 @@ divide down 12.288 MHz master clock. Or, if clock accuracy is not important, the
|
|||||||
reference can be divided down to provide an approximate clock.
|
reference can be divided down to provide an approximate clock.
|
||||||
|
|
||||||
Usage & Integration
|
Usage & Integration
|
||||||
~~~~~~~~~~~~~~~~~~~
|
-------------------
|
||||||
|
|
||||||
A PDM microphone wrapper is called from ``main()`` and takes one channel argument connecting it to the rest of the system:
|
A PDM microphone wrapper is called from ``main()`` and takes one channel argument connecting it to the rest of the system:
|
||||||
|
|
||||||
@@ -113,3 +112,4 @@ sends the frame of audio back over this channel.
|
|||||||
|
|
||||||
Note, it is assumed that the system shares a global master-clock, therefore no additional buffering or rate-matching/conversion
|
Note, it is assumed that the system shares a global master-clock, therefore no additional buffering or rate-matching/conversion
|
||||||
is required.
|
is required.
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
.. _usb_audio_sec_resource_usage:
|
.. _usb_audio_sec_resource_usage:
|
||||||
|
|
||||||
Resource Usage
|
Resource Usage
|
||||||
--------------
|
==============
|
||||||
|
|
||||||
The following table details the resource usage of each component of the reference design software.
|
The following table details the resource usage of each component of the reference design software.
|
||||||
Note, memory usage is approximate and varies based on device used, compiler settings etc.
|
Note, memory usage is approximate and varies based on device used, compiler settings etc.
|
||||||
@@ -50,3 +50,4 @@ Note, memory usage is approximate and varies based on device used, compiler sett
|
|||||||
|
|
||||||
Unlike other interfaces, since the USB PHY is internal the USB ports are a fixed set of ports
|
Unlike other interfaces, since the USB PHY is internal the USB ports are a fixed set of ports
|
||||||
and cannot be modified. See ``lib_xud`` documentation for full details.
|
and cannot be modified. See ``lib_xud`` documentation for full details.
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|newpage|
|
|newpage|
|
||||||
|
|
||||||
S/PDIF Transmit
|
S/PDIF Transmit
|
||||||
...............
|
===============
|
||||||
|
|
||||||
``lib_xua`` supports the development of devices with S/PDIF transmit throught the use of ``lib_spdif``.
|
``lib_xua`` supports the development of devices with S/PDIF transmit throught the use of ``lib_spdif``.
|
||||||
The XMOS S/SPDIF transmitter component runs in a single core and supports sample-rates upto 192kHz.
|
The XMOS S/SPDIF transmitter component runs in a single core and supports sample-rates upto 192kHz.
|
||||||
@@ -21,7 +21,7 @@ bits) and transmitted in biphase-mark encoding (BMC) with respect to an *externa
|
|||||||
Note that a minor change to the ``SpdifTransmitPortConfig`` function would enable *internal* master
|
Note that a minor change to the ``SpdifTransmitPortConfig`` function would enable *internal* master
|
||||||
clock generation (e.g. when clock source is already locked to desired audio clock).
|
clock generation (e.g. when clock source is already locked to desired audio clock).
|
||||||
|
|
||||||
.. list-table:: S/PDIF Capabilities
|
.. list-table:: S/PDIF Capabilities
|
||||||
|
|
||||||
* - **Sample frequencies**
|
* - **Sample frequencies**
|
||||||
- 44.1, 48, 88.2, 96, 176.4, 192 kHz
|
- 44.1, 48, 88.2, 96, 176.4, 192 kHz
|
||||||
@@ -31,7 +31,7 @@ clock generation (e.g. when clock source is already locked to desired audio cloc
|
|||||||
- ``lib_spdif``
|
- ``lib_spdif``
|
||||||
|
|
||||||
Clocking
|
Clocking
|
||||||
++++++++
|
--------
|
||||||
|
|
||||||
.. only:: latex
|
.. only:: latex
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@ This resamples the master clock to its clock domain (oscillator), which introduc
|
|||||||
A typical jitter-reduction scheme is an external D-type flip-flop clocked from the master clock (as shown in the preceding diagram).
|
A typical jitter-reduction scheme is an external D-type flip-flop clocked from the master clock (as shown in the preceding diagram).
|
||||||
|
|
||||||
Usage
|
Usage
|
||||||
+++++
|
-----
|
||||||
|
|
||||||
The interface to the S/PDIF transmitter core is via a normal channel with streaming built-ins
|
The interface to the S/PDIF transmitter core is via a normal channel with streaming built-ins
|
||||||
(``outuint``, ``inuint``). Data format should be 24-bit left-aligned in a 32-bit word: ``0x12345600``
|
(``outuint``, ``inuint``). Data format should be 24-bit left-aligned in a 32-bit word: ``0x12345600``
|
||||||
@@ -84,9 +84,8 @@ The following protocol is used on the channel:
|
|||||||
|
|
||||||
This communication is wrapped up in the API functions provided by ``lib_spdif``.
|
This communication is wrapped up in the API functions provided by ``lib_spdif``.
|
||||||
|
|
||||||
|
Output Stream Structure
|
||||||
Output stream structure
|
-----------------------
|
||||||
+++++++++++++++++++++++
|
|
||||||
|
|
||||||
The stream is composed of words with the following structure shown in
|
The stream is composed of words with the following structure shown in
|
||||||
:ref:`usb_audio_spdif_stream_structure`. The channel status bits are
|
:ref:`usb_audio_spdif_stream_structure`. The channel status bits are
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
|newpage|
|
|newpage|
|
||||||
|
|
||||||
S/PDIF Receive
|
S/PDIF Receive
|
||||||
---------------
|
==============
|
||||||
|
|
||||||
XMOS devices can support S/PDIF receive up to 192kHz - see ``lib_spdif`` for full specifications.
|
XMOS devices can support S/PDIF receive up to 192kHz - see ``lib_spdif`` for full specifications.
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ The tag has one of three values:
|
|||||||
See S/PDIF, IEC 60958-3:2006, specification for further details on format, user bits etc.
|
See S/PDIF, IEC 60958-3:2006, specification for further details on format, user bits etc.
|
||||||
|
|
||||||
Usage and Integration
|
Usage and Integration
|
||||||
+++++++++++++++++++++
|
---------------------
|
||||||
|
|
||||||
Since S/PDIF is a digital steam the devices master clock must be synchronised to it. This is typically
|
Since S/PDIF is a digital steam the devices master clock must be synchronised to it. This is typically
|
||||||
done with an external device. See `Clock Recovery` (:ref:`usb_audio_sec_clock_recovery`).
|
done with an external device. See `Clock Recovery` (:ref:`usb_audio_sec_clock_recovery`).
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|newpage|
|
|newpage|
|
||||||
|
|
||||||
XMOS USB Device (XUD) Library
|
XMOS USB Device (XUD) Library
|
||||||
.............................
|
=============================
|
||||||
|
|
||||||
All low level communication with the USB host is handled by the XMOS USB Device (XUD) library - `lib_xud`
|
All low level communication with the USB host is handled by the XMOS USB Device (XUD) library - `lib_xud`
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
|
|
||||||
Basic Usage
|
Basic Usage
|
||||||
-----------
|
***********
|
||||||
|
|
||||||
This sections describes the basic usage of `lib_xua` and provides a guide on how to program USB Audio Devices.
|
This sections describes the basic usage of `lib_xua` and provides a guide on how to program USB Audio Devices.
|
||||||
|
|
||||||
|
|
||||||
Library Structure
|
Library Structure
|
||||||
~~~~~~~~~~~~~~~~~
|
=================
|
||||||
|
|
||||||
The code is split into several directories.
|
The code is split into several directories.
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ Note, the midi and dfu directories are potential candidates for separate libs in
|
|||||||
|
|
||||||
|
|
||||||
Using in a Project
|
Using in a Project
|
||||||
~~~~~~~~~~~~~~~~~~
|
==================
|
||||||
|
|
||||||
All `lib_xua` functions can be accessed via the ``xua.h`` header file::
|
All `lib_xua` functions can be accessed via the ``xua.h`` header file::
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ It is also required to add ``lib_xua`` to the ``USED_MODULES`` field of your app
|
|||||||
.. _sec_basic_usage_codeless:
|
.. _sec_basic_usage_codeless:
|
||||||
|
|
||||||
"Codeless" Programming Model
|
"Codeless" Programming Model
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
============================
|
||||||
|
|
||||||
Whilst it is possible to code a USB Audio device using the building blocks provided by `lib_xua`
|
Whilst it is possible to code a USB Audio device using the building blocks provided by `lib_xua`
|
||||||
it is realised that this might not be desirable for many classes of customers or products.
|
it is realised that this might not be desirable for many classes of customers or products.
|
||||||
@@ -71,7 +71,7 @@ set ``EXCLUDE_USB_AUDIO_MAIN`` to 1 in the application makefile or ``xua_conf.h`
|
|||||||
::ref:`sec_advanced_usage`.
|
::ref:`sec_advanced_usage`.
|
||||||
|
|
||||||
Configuring lib_xua
|
Configuring lib_xua
|
||||||
~~~~~~~~~~~~~~~~~~~
|
===================
|
||||||
|
|
||||||
Configuration of the various build time options of ``lib_xua`` is done via the optional header `xua_conf.h`.
|
Configuration of the various build time options of ``lib_xua`` is done via the optional header `xua_conf.h`.
|
||||||
To allow the build scripts to locate this file it should reside somewhere in the application `src` directory.
|
To allow the build scripts to locate this file it should reside somewhere in the application `src` directory.
|
||||||
@@ -93,9 +93,8 @@ should continue to include `xua.h` as previously directed. A simple example is s
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
User Functions
|
User Functions
|
||||||
~~~~~~~~~~~~~~
|
==============
|
||||||
|
|
||||||
To enable custom functionality, such as configuring external audio hardware, bespoke behaviour on
|
To enable custom functionality, such as configuring external audio hardware, bespoke behaviour on
|
||||||
stream start/stop etc, various functions can be overridden by the user. (see ::ref:`sec_api` for
|
stream start/stop etc, various functions can be overridden by the user. (see ::ref:`sec_api` for
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
.. _sec_advanced_usage:
|
.. _sec_advanced_usage:
|
||||||
|
|
||||||
Advanced Usage
|
Advanced Usage
|
||||||
--------------
|
**************
|
||||||
|
|
||||||
Whilst it is possible to program USB Audio devices using ``lib_xua`` by only setting defines
|
Whilst it is possible to program USB Audio devices using ``lib_xua`` by only setting defines
|
||||||
(see :ref:`sec_basic_usage_codeless`) some developers may want to code a USB Audio device from
|
(see :ref:`sec_basic_usage_codeless`) some developers may want to code a USB Audio device from
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
Running the Core Components
|
Running the Core Components
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
===========================
|
||||||
|
|
||||||
In their most basic form the core components can be run as follows::
|
In their most basic form the core components can be run as follows::
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
Core Hardware Resources
|
Core Hardware Resources
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~
|
=======================
|
||||||
|
|
||||||
The user must declare and initialise relevant hardware resources (globally) and pass them to the
|
The user must declare and initialise relevant hardware resources (globally) and pass them to the
|
||||||
relevant function of `lib_xua`.
|
relevant function of `lib_xua`.
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
|newpage|
|
|newpage|
|
||||||
|
|
||||||
I2S/TDM
|
I2S/TDM
|
||||||
~~~~~~~
|
=======
|
||||||
|
|
||||||
I2S/TDM is typically fundamental to most products and is built into the ``XUA_AudioHub()`` core.
|
I2S/TDM is typically fundamental to most products and is built into the ``XUA_AudioHub()`` core.
|
||||||
|
|
||||||
In order to enable I2S on must declare an array of ports for the data-lines (one for each direction)::
|
In order to enable I2S/TDM on must declare an array of ports for the data-lines (one for each direction)::
|
||||||
|
|
||||||
/* Port declarations. Note, the defines come from the XN file */
|
/* Port declarations. Note, the defines come from the XN file */
|
||||||
buffered out port:32 p_i2s_dac[] = {PORT_I2S_DAC0}; /* I2S Data-line(s) */
|
buffered out port:32 p_i2s_dac[] = {PORT_I2S_DAC0}; /* I2S Data-line(s) */
|
||||||
@@ -22,7 +22,7 @@ Ports for the sample and bit clocks are also required::
|
|||||||
|
|
||||||
These ports must then be passed to the ``XUA_AudioHub()`` task appropriately.
|
These ports must then be passed to the ``XUA_AudioHub()`` task appropriately.
|
||||||
|
|
||||||
I2S functionality also requires two clock-blocks, one for bit and sample clock e.g.::
|
I2S/TDM functionality also requires two clock-blocks, one for bit-clock and another for the master clock e.g.::
|
||||||
|
|
||||||
/* Clock-block declarations */
|
/* Clock-block declarations */
|
||||||
clock clk_audio_bclk = on tile[0]: XS1_CLKBLK_4; /* Bit clock */
|
clock clk_audio_bclk = on tile[0]: XS1_CLKBLK_4; /* Bit clock */
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
|newpage|
|
|newpage|
|
||||||
|
|
||||||
Mixer
|
Mixer
|
||||||
~~~~~
|
=====
|
||||||
|
|
||||||
Since the mixer has no I/O the instantiation is straight forward. Communication wises, the mixer cores are inserted
|
Since the mixer has no I/O the instantiation is straight forward. Communication wises, the mixer cores are inserted
|
||||||
between the `AudioHub` and Buffering core(s)
|
between the `AudioHub` and Buffering core(s)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
XMOSNEWSTYLE = 2
|
XMOSNEWSTYLE = 2
|
||||||
DOXYGEN_DIRS=../../api
|
DOXYGEN_DIRS=../../api ../../src/core/user/audiostream ../../src/core/user/hostactive ../../src/core/user/hid ../../src/core/user/audiohw
|
||||||
SOURCE_INCLUDE_DIRS=../../../lib_xua
|
SOURCE_INCLUDE_DIRS=../../../lib_xua
|
||||||
SPHINX_MASTER_DOC=lib_xua
|
SPHINX_MASTER_DOC=lib_xua
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
VERSION = 3.3.0
|
VERSION = 3.5.1
|
||||||
|
|
||||||
DEBUG ?= 0
|
DEBUG ?= 0
|
||||||
|
|
||||||
ifeq ($(DEBUG),1)
|
ifeq ($(DEBUG),1)
|
||||||
DEBUG_FLAGS = -g -DXASSERT_ENABLE_ASSERTIONS_DECOUPLE=1
|
DEBUG_FLAGS = -g -DXASSERT_ENABLE_ASSERTIONS=1 -DXASSERT_ENABLE_DEBUG=1 -DXASSERT_ENABLE_LINE_NUMBERS=1
|
||||||
else
|
else
|
||||||
DEBUG_FLAGS = -DXASSERT_DISABLE_ASSERTIONS_DECOUPLE=1
|
DEBUG_FLAGS = -DXASSERT_ENABLE_ASSERTIONS=0 -DXASSERT_ENABLE_DEBUG=0 -DXASSERT_ENABLE_LINE_NUMBERS=0
|
||||||
endif
|
endif
|
||||||
|
|
||||||
DEPENDENT_MODULES = lib_locks(>=2.1.0) \
|
DEPENDENT_MODULES = lib_locks(>=2.1.0) \
|
||||||
lib_logging(>=3.1.1) \
|
lib_logging(>=3.1.1) \
|
||||||
lib_mic_array(>=4.5.0) \
|
lib_mic_array(>=4.5.0) \
|
||||||
lib_spdif(>=4.1.0) \
|
lib_spdif(>=5.0.0) \
|
||||||
lib_xassert(>=4.1.0) \
|
lib_xassert(>=4.1.0) \
|
||||||
lib_xud(>=2.2.1) \
|
lib_xud(>=2.2.3) \
|
||||||
lib_adat(>=1.0.0)
|
lib_adat(>=1.0.0)
|
||||||
|
|
||||||
MODULE_XCC_FLAGS = $(XCC_FLAGS) \
|
MODULE_XCC_FLAGS = $(XCC_FLAGS) \
|
||||||
@@ -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_flash_interface.c = $(MODULE_XCC_FLAGS) -Os -mno-dual-issue
|
||||||
XCC_FLAGS_flashlib_user.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
|
OPTIONAL_HEADERS += xua_conf.h static_hid_report.h
|
||||||
|
|
||||||
EXPORT_INCLUDE_DIRS = api \
|
EXPORT_INCLUDE_DIRS = api \
|
||||||
src/core \
|
src/core \
|
||||||
@@ -55,6 +55,7 @@ INCLUDE_DIRS = $(EXPORT_INCLUDE_DIRS) \
|
|||||||
src/core/user/audiostream \
|
src/core/user/audiostream \
|
||||||
src/core/user/hid \
|
src/core/user/hid \
|
||||||
src/core/user/hostactive \
|
src/core/user/hostactive \
|
||||||
|
src/core/user/audiohw \
|
||||||
src/hid \
|
src/hid \
|
||||||
src/midi
|
src/midi
|
||||||
|
|
||||||
@@ -70,6 +71,7 @@ SOURCE_DIRS = src/core \
|
|||||||
src/core/support \
|
src/core/support \
|
||||||
src/core/user/audiostream \
|
src/core/user/audiostream \
|
||||||
src/core/user/hostactive \
|
src/core/user/hostactive \
|
||||||
|
src/core/user/audiohw \
|
||||||
src/core/xuduser \
|
src/core/xuduser \
|
||||||
src/dfu \
|
src/dfu \
|
||||||
src/hid \
|
src/hid \
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2018-2022 XMOS LIMITED.
|
// Copyright 2018-2023 XMOS LIMITED.
|
||||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||||
|
|
||||||
#if (DSD_CHANS_DAC != 0)
|
#if (DSD_CHANS_DAC != 0)
|
||||||
@@ -52,7 +52,7 @@ static inline void DoDsdDop(int &everyOther, unsigned samplesOut[], unsigned &ds
|
|||||||
/* When DSD is enabled and streaming is standard PCM, this function checks for a series of DoP markers in the upper byte.
|
/* When DSD is enabled and streaming is standard PCM, this function checks for a series of DoP markers in the upper byte.
|
||||||
If found it will exit deliver() with the command to restart in DoP mode.
|
If found it will exit deliver() with the command to restart in DoP mode.
|
||||||
When in DoP mode, this function will check for a single absence of the DoP marker and exit deliver() with the command
|
When in DoP mode, this function will check for a single absence of the DoP marker and exit deliver() with the command
|
||||||
to restart in I2S mode. */
|
to restart in I2S/PCM mode. */
|
||||||
static inline int DoDsdDopCheck(unsigned &dsdMode, int &dsdCount, unsigned curSamFreq, unsigned samplesOut[], unsigned &dsdMarker)
|
static inline int DoDsdDopCheck(unsigned &dsdMode, int &dsdCount, unsigned curSamFreq, unsigned samplesOut[], unsigned &dsdMarker)
|
||||||
{
|
{
|
||||||
/* Check for DSD - note we only move into DoP mode if valid DoP Freq */
|
/* Check for DSD - note we only move into DoP mode if valid DoP Freq */
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
// Copyright 2018-2022 XMOS LIMITED.
|
// Copyright 2018-2023 XMOS LIMITED.
|
||||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||||
#include "xua.h"
|
#include "xua.h"
|
||||||
|
|
||||||
#include "dsd_support.h"
|
#include "dsd_support.h"
|
||||||
|
|
||||||
#if (DSD_CHANS_DAC != 0)
|
#if (DSD_CHANS_DAC != 0)
|
||||||
@@ -12,7 +11,7 @@ extern buffered out port:32 p_dsd_clk;
|
|||||||
extern unsigned dsdMode;
|
extern unsigned dsdMode;
|
||||||
|
|
||||||
#if !CODEC_MASTER
|
#if !CODEC_MASTER
|
||||||
void InitPorts_master(unsigned divide, buffered _XUA_CLK_DIR port:32 p_lrclk, buffered _XUA_CLK_DIR port:32 p_bclk, buffered out port:32 (&?p_i2s_dac)[I2S_WIRES_DAC], buffered in port:32 (&?p_i2s_adc)[I2S_WIRES_ADC])
|
void InitPorts_master(buffered _XUA_CLK_DIR port:32 p_lrclk, buffered _XUA_CLK_DIR port:32 p_bclk, buffered out port:32 (&?p_i2s_dac)[I2S_WIRES_DAC], buffered in port:32 (&?p_i2s_adc)[I2S_WIRES_ADC])
|
||||||
{
|
{
|
||||||
#if (DSD_CHANS_DAC > 0)
|
#if (DSD_CHANS_DAC > 0)
|
||||||
if(dsdMode == DSD_MODE_OFF)
|
if(dsdMode == DSD_MODE_OFF)
|
||||||
@@ -38,9 +37,13 @@ void InitPorts_master(unsigned divide, buffered _XUA_CLK_DIR port:32 p_lrclk, bu
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#pragma xta endpoint "divide_1"
|
|
||||||
unsigned tmp;
|
unsigned tmp;
|
||||||
p_lrclk <: 0 @ tmp;
|
|
||||||
|
if(XUA_I2S_N_BITS == 32)
|
||||||
|
p_lrclk <: 0 @ tmp;
|
||||||
|
else
|
||||||
|
tmp = partout_timestamped(p_lrclk, XUA_I2S_N_BITS, 0);
|
||||||
|
|
||||||
tmp += 100;
|
tmp += 100;
|
||||||
|
|
||||||
/* Since BCLK is free-running, setup outputs/inputs at a known point in the future */
|
/* Since BCLK is free-running, setup outputs/inputs at a known point in the future */
|
||||||
@@ -48,19 +51,30 @@ void InitPorts_master(unsigned divide, buffered _XUA_CLK_DIR port:32 p_lrclk, bu
|
|||||||
#pragma loop unroll
|
#pragma loop unroll
|
||||||
for(int i = 0; i < I2S_WIRES_DAC; i++)
|
for(int i = 0; i < I2S_WIRES_DAC; i++)
|
||||||
{
|
{
|
||||||
p_i2s_dac[i] @ tmp <: 0;
|
if(XUA_I2S_N_BITS == 32)
|
||||||
|
p_i2s_dac[i] @ tmp <: 0;
|
||||||
|
else
|
||||||
|
partout_timed(p_i2s_dac[i], XUA_I2S_N_BITS, 0, tmp);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
unsigned lrClkVal = 0x7FFFFFFF;
|
||||||
if(XUA_PCM_FORMAT == XUA_PCM_FORMAT_TDM)
|
if(XUA_PCM_FORMAT == XUA_PCM_FORMAT_TDM)
|
||||||
p_lrclk @ tmp <: 0x80000000;
|
{
|
||||||
|
lrClkVal = 0x80000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(XUA_I2S_N_BITS == 32)
|
||||||
|
p_lrclk @ tmp <: lrClkVal;
|
||||||
else
|
else
|
||||||
p_lrclk @ tmp <: 0x7FFFFFFF;
|
partout_timed(p_lrclk, XUA_I2S_N_BITS, lrClkVal, tmp);
|
||||||
|
|
||||||
#if (I2S_CHANS_ADC != 0)
|
#if (I2S_CHANS_ADC != 0)
|
||||||
for(int i = 0; i < I2S_WIRES_ADC; i++)
|
for(int i = 0; i < I2S_WIRES_ADC; i++)
|
||||||
{
|
{
|
||||||
asm("setpt res[%0], %1"::"r"(p_i2s_adc[i]),"r"(tmp-1));
|
asm("setpt res[%0], %1"::"r"(p_i2s_adc[i]),"r"(tmp-1));
|
||||||
|
|
||||||
|
if(XUA_I2S_N_BITS != 32)
|
||||||
|
set_port_shift_count(p_i2s_adc[i], XUA_I2S_N_BITS);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif /* (I2S_CHANS_ADC != 0 || I2S_CHANS_DAC != 0) */
|
#endif /* (I2S_CHANS_ADC != 0 || I2S_CHANS_DAC != 0) */
|
||||||
@@ -76,7 +90,7 @@ void InitPorts_master(unsigned divide, buffered _XUA_CLK_DIR port:32 p_lrclk, bu
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
void InitPorts_slave(unsigned divide, buffered _XUA_CLK_DIR port:32 p_lrclk, buffered _XUA_CLK_DIR port:32 p_bclk, buffered out port:32 (&?p_i2s_dac)[I2S_WIRES_DAC], buffered in port:32 (&?p_i2s_adc)[I2S_WIRES_ADC])
|
void InitPorts_slave(buffered _XUA_CLK_DIR port:32 p_lrclk, buffered _XUA_CLK_DIR port:32 p_bclk, buffered out port:32 (&?p_i2s_dac)[I2S_WIRES_DAC], buffered in port:32 (&?p_i2s_adc)[I2S_WIRES_ADC])
|
||||||
{
|
{
|
||||||
#if (I2S_CHANS_ADC != 0 || I2S_CHANS_DAC != 0)
|
#if (I2S_CHANS_ADC != 0 || I2S_CHANS_DAC != 0)
|
||||||
unsigned tmp;
|
unsigned tmp;
|
||||||
@@ -93,7 +107,7 @@ void InitPorts_slave(unsigned divide, buffered _XUA_CLK_DIR port:32 p_lrclk, buf
|
|||||||
p_lrclk when pinseq(0) :> void @ tmp;
|
p_lrclk when pinseq(0) :> void @ tmp;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
tmp += (I2S_CHANS_PER_FRAME * 32) - 32 + 1 ;
|
tmp += ((I2S_CHANS_PER_FRAME * XUA_I2S_N_BITS) - XUA_I2S_N_BITS + 1) ;
|
||||||
/* E.g. 2 * 32 - 32 + 1 = 33 for stereo */
|
/* E.g. 2 * 32 - 32 + 1 = 33 for stereo */
|
||||||
/* E.g. 8 * 32 - 32 + 1 = 225 for 8 chan TDM */
|
/* E.g. 8 * 32 - 32 + 1 = 225 for 8 chan TDM */
|
||||||
|
|
||||||
@@ -101,7 +115,10 @@ void InitPorts_slave(unsigned divide, buffered _XUA_CLK_DIR port:32 p_lrclk, buf
|
|||||||
#pragma loop unroll
|
#pragma loop unroll
|
||||||
for(int i = 0; i < I2S_WIRES_DAC; i++)
|
for(int i = 0; i < I2S_WIRES_DAC; i++)
|
||||||
{
|
{
|
||||||
p_i2s_dac[i] @ tmp <: 0;
|
if(XUA_I2S_N_BITS == 32)
|
||||||
|
p_i2s_dac[i] @ tmp <: 0;
|
||||||
|
else
|
||||||
|
partout_timed(p_i2s_dac[i], XUA_I2S_N_BITS, 0, tmp);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -109,11 +126,15 @@ void InitPorts_slave(unsigned divide, buffered _XUA_CLK_DIR port:32 p_lrclk, buf
|
|||||||
#pragma loop unroll
|
#pragma loop unroll
|
||||||
for(int i = 0; i < I2S_WIRES_ADC; i++)
|
for(int i = 0; i < I2S_WIRES_ADC; i++)
|
||||||
{
|
{
|
||||||
asm("setpt res[%0], %1"::"r"(p_i2s_adc[i]),"r"(tmp-1));
|
asm("setpt res[%0], %1"::"r"(p_i2s_adc[i]),"r"(tmp-1));
|
||||||
|
if(XUA_I2S_N_BITS != 32)
|
||||||
|
set_port_shift_count(p_i2s_adc[i], XUA_I2S_N_BITS);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
asm("setpt res[%0], %1"::"r"(p_lrclk),"r"(tmp-1));
|
asm("setpt res[%0], %1"::"r"(p_lrclk),"r"(tmp-1));
|
||||||
|
if(XUA_I2S_N_BITS != 32)
|
||||||
|
set_port_shift_count(p_lrclk, XUA_I2S_N_BITS);
|
||||||
#endif /* (I2S_CHANS_ADC != 0 || I2S_CHANS_DAC != 0) */
|
#endif /* (I2S_CHANS_ADC != 0 || I2S_CHANS_DAC != 0) */
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2011-2022 XMOS LIMITED.
|
// Copyright 2011-2023 XMOS LIMITED.
|
||||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||||
/**
|
/**
|
||||||
* @file xua_audiohub.xc
|
* @file xua_audiohub.xc
|
||||||
@@ -15,9 +15,12 @@
|
|||||||
#include <xclib.h>
|
#include <xclib.h>
|
||||||
#include <xs1_su.h>
|
#include <xs1_su.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <xassert.h>
|
||||||
|
|
||||||
#include "xua.h"
|
#include "xua.h"
|
||||||
|
|
||||||
|
#include "audiohw.h"
|
||||||
|
|
||||||
#include "audioports.h"
|
#include "audioports.h"
|
||||||
#include "mic_array_conf.h"
|
#include "mic_array_conf.h"
|
||||||
#if (XUA_SPDIF_TX_EN)
|
#if (XUA_SPDIF_TX_EN)
|
||||||
@@ -43,25 +46,12 @@
|
|||||||
|
|
||||||
#define MAX(x,y) ((x)>(y) ? (x) : (y))
|
#define MAX(x,y) ((x)>(y) ? (x) : (y))
|
||||||
|
|
||||||
static unsigned samplesOut[MAX(NUM_USB_CHAN_OUT, I2S_CHANS_DAC)];
|
unsigned samplesOut[MAX(NUM_USB_CHAN_OUT, I2S_CHANS_DAC)];
|
||||||
|
|
||||||
/* Two buffers for ADC data to allow for DAC and ADC I2S ports being offset */
|
/* Two buffers for ADC data to allow for DAC and ADC I2S ports being offset */
|
||||||
#define IN_CHAN_COUNT (I2S_CHANS_ADC + XUA_NUM_PDM_MICS + (8*XUA_ADAT_RX_EN) + (2*XUA_SPDIF_RX_EN))
|
#define IN_CHAN_COUNT (I2S_CHANS_ADC + XUA_NUM_PDM_MICS + (8*XUA_ADAT_RX_EN) + (2*XUA_SPDIF_RX_EN))
|
||||||
|
|
||||||
static unsigned samplesIn[2][MAX(NUM_USB_CHAN_IN, IN_CHAN_COUNT)];
|
unsigned samplesIn[2][MAX(NUM_USB_CHAN_IN, IN_CHAN_COUNT)];
|
||||||
|
|
||||||
#ifdef XTA_TIMING_AUDIO
|
|
||||||
#pragma xta command "add exclusion received_command"
|
|
||||||
#pragma xta command "analyse path i2s_output_l i2s_output_r"
|
|
||||||
#pragma xta command "set required - 2000 ns"
|
|
||||||
|
|
||||||
#pragma xta command "add exclusion received_command"
|
|
||||||
#pragma xta command "add exclusion received_underflow"
|
|
||||||
#pragma xta command "add exclusion divide_1"
|
|
||||||
#pragma xta command "add exclusion deliver_return"
|
|
||||||
#pragma xta command "analyse path i2s_output_r i2s_output_l"
|
|
||||||
#pragma xta command "set required - 2000 ns"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (XUA_ADAT_TX_EN)
|
#if (XUA_ADAT_TX_EN)
|
||||||
extern buffered out port:32 p_adat_tx;
|
extern buffered out port:32 p_adat_tx;
|
||||||
@@ -76,7 +66,7 @@ void InitPorts_slave
|
|||||||
#else
|
#else
|
||||||
void InitPorts_master
|
void InitPorts_master
|
||||||
#endif
|
#endif
|
||||||
(unsigned divide, buffered _XUA_CLK_DIR port:32 p_lrclk, buffered _XUA_CLK_DIR port:32 p_bclk, buffered out port:32 (&?p_i2s_dac)[I2S_WIRES_DAC],
|
(buffered _XUA_CLK_DIR port:32 p_lrclk, buffered _XUA_CLK_DIR port:32 p_bclk, buffered out port:32 (&?p_i2s_dac)[I2S_WIRES_DAC],
|
||||||
buffered in port:32 (&?p_i2s_adc)[I2S_WIRES_ADC]);
|
buffered in port:32 (&?p_i2s_adc)[I2S_WIRES_ADC]);
|
||||||
|
|
||||||
|
|
||||||
@@ -89,76 +79,24 @@ unsigned dsdMode = DSD_MODE_OFF;
|
|||||||
#if (XUA_ADAT_TX_EN)
|
#if (XUA_ADAT_TX_EN)
|
||||||
#include "audiohub_adat.h"
|
#include "audiohub_adat.h"
|
||||||
#endif
|
#endif
|
||||||
|
#include "xua_audiohub_st.h"
|
||||||
#pragma unsafe arrays
|
|
||||||
static inline unsigned DoSampleTransfer(chanend ?c_out, const int readBuffNo, const unsigned underflowWord)
|
|
||||||
{
|
|
||||||
if(XUA_USB_EN)
|
|
||||||
{
|
|
||||||
outuint(c_out, underflowWord);
|
|
||||||
|
|
||||||
/* Check for sample freq change (or other command) or new samples from mixer*/
|
|
||||||
if(testct(c_out))
|
|
||||||
{
|
|
||||||
unsigned command = inct(c_out);
|
|
||||||
#ifndef CODEC_MASTER
|
|
||||||
if(dsdMode == DSD_MODE_OFF)
|
|
||||||
{
|
|
||||||
#if (I2S_CHANS_ADC != 0 || I2S_CHANS_DAC != 0)
|
|
||||||
/* Set clocks low */
|
|
||||||
p_lrclk <: 0;
|
|
||||||
p_bclk <: 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
#if(DSD_CHANS_DAC != 0)
|
|
||||||
/* DSD Clock might not be shared with lrclk or bclk... */
|
|
||||||
p_dsd_clk <: 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#if (DSD_CHANS_DAC > 0)
|
|
||||||
if(dsdMode == DSD_MODE_DOP)
|
|
||||||
dsdMode = DSD_MODE_OFF;
|
|
||||||
#endif
|
|
||||||
return command;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
#if NUM_USB_CHAN_OUT > 0
|
|
||||||
#pragma loop unroll
|
|
||||||
for(int i = 0; i < NUM_USB_CHAN_OUT; i++)
|
|
||||||
{
|
|
||||||
int tmp = inuint(c_out);
|
|
||||||
samplesOut[i] = tmp;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
inuint(c_out);
|
|
||||||
#endif
|
|
||||||
UserBufferManagement(samplesOut, samplesIn[readBuffNo]);
|
|
||||||
|
|
||||||
#if NUM_USB_CHAN_IN > 0
|
|
||||||
#pragma loop unroll
|
|
||||||
for(int i = 0; i < NUM_USB_CHAN_IN; i++)
|
|
||||||
{
|
|
||||||
outuint(c_out, samplesIn[readBuffNo][i]);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
UserBufferManagement(samplesOut, samplesIn[readBuffNo]);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int HandleSampleClock(int frameCount, buffered _XUA_CLK_DIR port:32 p_lrclk)
|
static inline int HandleSampleClock(int frameCount, buffered _XUA_CLK_DIR port:32 p_lrclk)
|
||||||
{
|
{
|
||||||
#if CODEC_MASTER
|
#if CODEC_MASTER
|
||||||
unsigned syncError = 0;
|
unsigned syncError = 0;
|
||||||
unsigned lrval = 0;
|
unsigned lrval = 0;
|
||||||
p_lrclk :> lrval;
|
const unsigned lrval_mask = (0xffffffff << (32 - XUA_I2S_N_BITS));
|
||||||
|
|
||||||
|
if(XUA_I2S_N_BITS != 32)
|
||||||
|
{
|
||||||
|
asm volatile("in %0, res[%1]":"=r"(lrval):"r"(p_lrclk):"memory");
|
||||||
|
set_port_shift_count(p_lrclk, XUA_I2S_N_BITS);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p_lrclk :> lrval;
|
||||||
|
}
|
||||||
|
|
||||||
if(XUA_PCM_FORMAT == XUA_PCM_FORMAT_TDM)
|
if(XUA_PCM_FORMAT == XUA_PCM_FORMAT_TDM)
|
||||||
{
|
{
|
||||||
@@ -176,30 +114,46 @@ static inline int HandleSampleClock(int frameCount, buffered _XUA_CLK_DIR port:3
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(frameCount == 0)
|
if(XUA_I2S_N_BITS == 32)
|
||||||
syncError += (lrval != 0x80000000);
|
{
|
||||||
|
if(frameCount == 0)
|
||||||
|
syncError = (lrval != 0x80000000);
|
||||||
|
else
|
||||||
|
syncError = (lrval != 0x7FFFFFFF);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
syncError += (lrval != 0x7FFFFFFF);
|
{
|
||||||
|
if(frameCount == 0)
|
||||||
|
syncError = ((lrval & lrval_mask) != 0x80000000);
|
||||||
|
else
|
||||||
|
syncError = ((lrval | (~lrval_mask)) != 0x7FFFFFFF);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return syncError;
|
return syncError;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
unsigned clkVal;
|
||||||
if(XUA_PCM_FORMAT == XUA_PCM_FORMAT_TDM)
|
if(XUA_PCM_FORMAT == XUA_PCM_FORMAT_TDM)
|
||||||
{
|
{
|
||||||
if(frameCount == (I2S_CHANS_PER_FRAME-1))
|
if(frameCount == (I2S_CHANS_PER_FRAME-1))
|
||||||
p_lrclk <: 0x80000000;
|
clkVal = 0x80000000;
|
||||||
else
|
else
|
||||||
p_lrclk <: 0x00000000;
|
clkVal = 0x00000000;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(frameCount == 0)
|
if(frameCount == 0)
|
||||||
p_lrclk <: 0x80000000;
|
clkVal = 0x80000000;
|
||||||
else
|
else
|
||||||
p_lrclk <: 0x7fffffff;
|
clkVal = 0x7fffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(XUA_I2S_N_BITS == 32)
|
||||||
|
p_lrclk <: clkVal;
|
||||||
|
else
|
||||||
|
partout(p_lrclk, XUA_I2S_N_BITS, clkVal >> (32 - XUA_I2S_N_BITS));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -316,9 +270,9 @@ unsigned static AudioHub_MainLoop(chanend ?c_out, chanend ?c_spd_out
|
|||||||
if ((I2S_CHANS_DAC > 0 || I2S_CHANS_ADC > 0))
|
if ((I2S_CHANS_DAC > 0 || I2S_CHANS_ADC > 0))
|
||||||
{
|
{
|
||||||
#if CODEC_MASTER
|
#if CODEC_MASTER
|
||||||
InitPorts_slave(divide, p_lrclk, p_bclk, p_i2s_dac, p_i2s_adc);
|
InitPorts_slave(p_lrclk, p_bclk, p_i2s_dac, p_i2s_adc);
|
||||||
#else
|
#else
|
||||||
InitPorts_master(divide, p_lrclk, p_bclk, p_i2s_dac, p_i2s_adc);
|
InitPorts_master(p_lrclk, p_bclk, p_i2s_dac, p_i2s_adc);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -352,9 +306,17 @@ unsigned static AudioHub_MainLoop(chanend ?c_out, chanend ?c_spd_out
|
|||||||
// p_i2s_adc[index++] :> sample;
|
// p_i2s_adc[index++] :> sample;
|
||||||
// Manual IN instruction since compiler generates an extra setc per IN (bug #15256)
|
// Manual IN instruction since compiler generates an extra setc per IN (bug #15256)
|
||||||
unsigned sample;
|
unsigned sample;
|
||||||
asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++]));
|
asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index]));
|
||||||
|
|
||||||
sample = bitrev(sample);
|
sample = bitrev(sample);
|
||||||
int chanIndex = ((frameCount-2)&(I2S_CHANS_PER_FRAME-1))+i; // channels 0, 2, 4.. on each line.
|
if(XUA_I2S_N_BITS != 32)
|
||||||
|
{
|
||||||
|
set_port_shift_count(p_i2s_adc[index], XUA_I2S_N_BITS);
|
||||||
|
sample <<= (32 - XUA_I2S_N_BITS);
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
|
||||||
|
int chanIndex = ((frameCount-2) & (I2S_CHANS_PER_FRAME-1)) + i; // channels 0, 2, 4.. on each line.
|
||||||
|
|
||||||
#if (AUD_TO_USB_RATIO > 1)
|
#if (AUD_TO_USB_RATIO > 1)
|
||||||
if ((AUD_TO_USB_RATIO - 1) == audioToUsbRatioCounter)
|
if ((AUD_TO_USB_RATIO - 1) == audioToUsbRatioCounter)
|
||||||
@@ -406,7 +368,10 @@ unsigned static AudioHub_MainLoop(chanend ?c_out, chanend ?c_spd_out
|
|||||||
src_ff3v_fir_coefs[2-audioToUsbRatioCounter]);
|
src_ff3v_fir_coefs[2-audioToUsbRatioCounter]);
|
||||||
}
|
}
|
||||||
#endif /* (AUD_TO_USB_RATIO > 1) */
|
#endif /* (AUD_TO_USB_RATIO > 1) */
|
||||||
p_i2s_dac[index++] <: bitrev(samplesOut[frameCount +i]);
|
if(XUA_I2S_N_BITS == 32)
|
||||||
|
p_i2s_dac[index++] <: bitrev(samplesOut[frameCount +i]);
|
||||||
|
else
|
||||||
|
partout(p_i2s_dac[index++], XUA_I2S_N_BITS, bitrev(samplesOut[frameCount +i]));
|
||||||
}
|
}
|
||||||
#endif // (I2S_CHANS_DAC != 0)
|
#endif // (I2S_CHANS_DAC != 0)
|
||||||
|
|
||||||
@@ -443,9 +408,8 @@ unsigned static AudioHub_MainLoop(chanend ?c_out, chanend ?c_spd_out
|
|||||||
outuint(c_dig_rx, 0);
|
outuint(c_dig_rx, 0);
|
||||||
#endif
|
#endif
|
||||||
#if (XUA_SPDIF_TX_EN) && (NUM_USB_CHAN_OUT > 0)
|
#if (XUA_SPDIF_TX_EN) && (NUM_USB_CHAN_OUT > 0)
|
||||||
outuint(c_spd_out, samplesOut[SPDIF_TX_INDEX]); /* Forward sample to S/PDIF Tx thread */
|
outuint(c_spd_out, samplesOut[SPDIF_TX_INDEX]); /* Forward samples to S/PDIF Tx thread */
|
||||||
unsigned sample = samplesOut[SPDIF_TX_INDEX + 1];
|
outuint(c_spd_out, samplesOut[SPDIF_TX_INDEX + 1]);
|
||||||
outuint(c_spd_out, sample); /* Forward sample to S/PDIF Tx thread */
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (XUA_NUM_PDM_MICS > 0)
|
#if (XUA_NUM_PDM_MICS > 0)
|
||||||
@@ -480,8 +444,15 @@ unsigned static AudioHub_MainLoop(chanend ?c_out, chanend ?c_spd_out
|
|||||||
{
|
{
|
||||||
/* Manual IN instruction since compiler generates an extra setc per IN (bug #15256) */
|
/* Manual IN instruction since compiler generates an extra setc per IN (bug #15256) */
|
||||||
unsigned sample;
|
unsigned sample;
|
||||||
asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index++]));
|
asm volatile("in %0, res[%1]" : "=r"(sample) : "r"(p_i2s_adc[index]));
|
||||||
sample = bitrev(sample);
|
sample = bitrev(sample);
|
||||||
|
if(XUA_I2S_N_BITS != 32)
|
||||||
|
{
|
||||||
|
set_port_shift_count(p_i2s_adc[index], XUA_I2S_N_BITS);
|
||||||
|
sample <<= (32 - XUA_I2S_N_BITS);
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
|
||||||
int chanIndex = ((frameCount-2)&(I2S_CHANS_PER_FRAME-1))+i; // channels 1, 3, 5.. on each line.
|
int chanIndex = ((frameCount-2)&(I2S_CHANS_PER_FRAME-1))+i; // channels 1, 3, 5.. on each line.
|
||||||
#if (AUD_TO_USB_RATIO > 1 && !I2S_DOWNSAMPLE_MONO_IN)
|
#if (AUD_TO_USB_RATIO > 1 && !I2S_DOWNSAMPLE_MONO_IN)
|
||||||
if ((AUD_TO_USB_RATIO - 1) == audioToUsbRatioCounter)
|
if ((AUD_TO_USB_RATIO - 1) == audioToUsbRatioCounter)
|
||||||
@@ -513,7 +484,6 @@ unsigned static AudioHub_MainLoop(chanend ?c_out, chanend ?c_spd_out
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
index = 0;
|
index = 0;
|
||||||
#pragma xta endpoint "i2s_output_r"
|
|
||||||
#if (I2S_CHANS_DAC != 0)
|
#if (I2S_CHANS_DAC != 0)
|
||||||
/* Output "odd" channel to DAC (i.e. right) */
|
/* Output "odd" channel to DAC (i.e. right) */
|
||||||
#pragma loop unroll
|
#pragma loop unroll
|
||||||
@@ -532,7 +502,10 @@ unsigned static AudioHub_MainLoop(chanend ?c_out, chanend ?c_spd_out
|
|||||||
src_ff3v_fir_coefs[2-audioToUsbRatioCounter]);
|
src_ff3v_fir_coefs[2-audioToUsbRatioCounter]);
|
||||||
}
|
}
|
||||||
#endif /* (AUD_TO_USB_RATIO > 1) */
|
#endif /* (AUD_TO_USB_RATIO > 1) */
|
||||||
p_i2s_dac[index++] <: bitrev(samplesOut[frameCount + i]);
|
if(XUA_I2S_N_BITS == 32)
|
||||||
|
p_i2s_dac[index++] <: bitrev(samplesOut[frameCount + i]);
|
||||||
|
else
|
||||||
|
partout(p_i2s_dac[index++], XUA_I2S_N_BITS, bitrev(samplesOut[frameCount + i]));
|
||||||
}
|
}
|
||||||
#endif // (I2S_CHANS_DAC != 0)
|
#endif // (I2S_CHANS_DAC != 0)
|
||||||
|
|
||||||
@@ -586,7 +559,6 @@ unsigned static AudioHub_MainLoop(chanend ?c_out, chanend ?c_spd_out
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#pragma xta endpoint "deliver_return"
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -664,6 +636,9 @@ void XUA_AudioHub(chanend ?c_aud, clock ?clk_audio_mclk, clock ?clk_audio_bclk,
|
|||||||
buffered _XUA_CLK_DIR port:32 ?p_bclk,
|
buffered _XUA_CLK_DIR port:32 ?p_bclk,
|
||||||
buffered out port:32 (&?p_i2s_dac)[I2S_WIRES_DAC],
|
buffered out port:32 (&?p_i2s_dac)[I2S_WIRES_DAC],
|
||||||
buffered in port:32 (&?p_i2s_adc)[I2S_WIRES_ADC]
|
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)
|
#if (XUA_SPDIF_TX_EN) //&& (SPDIF_TX_TILE != AUDIO_IO_TILE)
|
||||||
, chanend c_spdif_out
|
, chanend c_spdif_out
|
||||||
#endif
|
#endif
|
||||||
@@ -691,6 +666,12 @@ void XUA_AudioHub(chanend ?c_aud, clock ?clk_audio_mclk, clock ?clk_audio_bclk,
|
|||||||
unsigned divide;
|
unsigned divide;
|
||||||
unsigned firstRun = 1;
|
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 */
|
/* Clock master clock-block from master-clock port */
|
||||||
/* Note, marked unsafe since other cores may be using this mclk port */
|
/* Note, marked unsafe since other cores may be using this mclk port */
|
||||||
configure_clock_src(clk_audio_mclk, p_mclk_in);
|
configure_clock_src(clk_audio_mclk, p_mclk_in);
|
||||||
@@ -716,6 +697,8 @@ void XUA_AudioHub(chanend ?c_aud, clock ?clk_audio_mclk, clock ?clk_audio_bclk,
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Perform required CODEC/ADC/DAC initialisation */
|
/* Perform required CODEC/ADC/DAC initialisation */
|
||||||
AudioHwInit();
|
AudioHwInit();
|
||||||
|
|
||||||
@@ -744,13 +727,7 @@ void XUA_AudioHub(chanend ?c_aud, clock ?clk_audio_mclk, clock ?clk_audio_bclk,
|
|||||||
/* Calculate master clock to bit clock (or DSD clock) divide for current sample freq
|
/* Calculate master clock to bit clock (or DSD clock) divide for current sample freq
|
||||||
* e.g. 11.289600 / (176400 * 64) = 1 */
|
* e.g. 11.289600 / (176400 * 64) = 1 */
|
||||||
{
|
{
|
||||||
#if (XUA_PCM_FORMAT == XUA_PCM_FORMAT_TDM)
|
unsigned numBits = XUA_I2S_N_BITS * I2S_CHANS_PER_FRAME;
|
||||||
/* I2S has 32 bits per sample. *8 as 8 channels */
|
|
||||||
unsigned numBits = 256;
|
|
||||||
#else
|
|
||||||
/* I2S has 32 bits per sample. *2 as 2 channels */
|
|
||||||
unsigned numBits = 64;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (DSD_CHANS_DAC > 0)
|
#if (DSD_CHANS_DAC > 0)
|
||||||
if(dsdMode == DSD_MODE_DOP)
|
if(dsdMode == DSD_MODE_DOP)
|
||||||
@@ -764,17 +741,24 @@ void XUA_AudioHub(chanend ?c_aud, clock ?clk_audio_mclk, clock ?clk_audio_bclk,
|
|||||||
numBits = 32;
|
numBits = 32;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
divide = mClk / ( curSamFreq * numBits);
|
divide = mClk / (curSamFreq * numBits);
|
||||||
|
|
||||||
|
//Do some checks
|
||||||
|
xassert((divide > 0) && "Error: divider is 0, BCLK rate unachievable");
|
||||||
|
|
||||||
|
unsigned remainder = mClk % ( curSamFreq * numBits);
|
||||||
|
xassert((!remainder) && "Error: MCLK not divisible into BCLK by an integer number");
|
||||||
|
|
||||||
|
unsigned divider_is_odd = divide & 0x1;
|
||||||
|
xassert((!divider_is_odd) && "Error: divider is odd, clockblock cannot produce desired BCLK");
|
||||||
|
|
||||||
/* TODO; we should catch and handle the case when divide is 0. Currently design will lock up */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if (DSD_CHANS_DAC > 0)
|
#if (DSD_CHANS_DAC > 0)
|
||||||
if(dsdMode)
|
if(dsdMode)
|
||||||
{
|
{
|
||||||
/* Configure audio ports */
|
/* Configure audio ports */
|
||||||
ConfigAudioPortsWrapper(
|
ConfigAudioPortsWrapper(
|
||||||
#if (I2S_CHANS_DAC != 0) || (DSD_CHANS_DAC != 0)
|
#if (I2S_CHANS_DAC != 0) || (DSD_CHANS_DAC != 0)
|
||||||
p_dsd_dac,
|
p_dsd_dac,
|
||||||
DSD_CHANS_DAC,
|
DSD_CHANS_DAC,
|
||||||
@@ -787,7 +771,7 @@ void XUA_AudioHub(chanend ?c_aud, clock ?clk_audio_mclk, clock ?clk_audio_bclk,
|
|||||||
null,
|
null,
|
||||||
p_dsd_clk,
|
p_dsd_clk,
|
||||||
#endif
|
#endif
|
||||||
p_mclk_in, clk_audio_bclk, divide, curSamFreq, dsdMode);
|
p_mclk_in, clk_audio_bclk, divide, curSamFreq);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
@@ -810,9 +794,8 @@ void XUA_AudioHub(chanend ?c_aud, clock ?clk_audio_mclk, clock ?clk_audio_bclk,
|
|||||||
p_bclk,
|
p_bclk,
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
p_mclk_in, clk_audio_bclk, divide, curSamFreq, dsdMode);
|
p_mclk_in, clk_audio_bclk, divide, curSamFreq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
unsigned curFreq = curSamFreq;
|
unsigned curFreq = curSamFreq;
|
||||||
@@ -827,8 +810,19 @@ void XUA_AudioHub(chanend ?c_aud, clock ?clk_audio_mclk, clock ?clk_audio_bclk,
|
|||||||
curFreq *= 16;
|
curFreq *= 16;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
/* Configure Clocking/CODEC/DAC/ADC for SampleFreq/MClk */
|
|
||||||
|
/* User should mute audio hardware */
|
||||||
|
AudioHwConfig_Mute();
|
||||||
|
|
||||||
|
#if (XUA_USE_APP_PLL)
|
||||||
|
i_softPll.init(mClk);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* User code should configure audio harware for SampleFreq/MClk etc */
|
||||||
AudioHwConfig(curFreq, mClk, dsdMode, curSamRes_DAC, curSamRes_ADC);
|
AudioHwConfig(curFreq, mClk, dsdMode, curSamRes_DAC, curSamRes_ADC);
|
||||||
|
|
||||||
|
/* User should unmute audio hardware */
|
||||||
|
AudioHwConfig_UnMute();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!firstRun)
|
if(!firstRun)
|
||||||
|
|||||||
66
lib_xua/src/core/audiohub/xua_audiohub_st.h
Normal file
66
lib_xua/src/core/audiohub/xua_audiohub_st.h
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
// Copyright 2011-2023 XMOS LIMITED.
|
||||||
|
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||||
|
|
||||||
|
#pragma unsafe arrays
|
||||||
|
static inline unsigned DoSampleTransfer(chanend ?c_out, const int readBuffNo, const unsigned underflowWord)
|
||||||
|
{
|
||||||
|
if(XUA_USB_EN)
|
||||||
|
{
|
||||||
|
outuint(c_out, underflowWord);
|
||||||
|
|
||||||
|
/* Check for sample freq change (or other command) or new samples from mixer*/
|
||||||
|
if(testct(c_out))
|
||||||
|
{
|
||||||
|
unsigned command = inct(c_out);
|
||||||
|
#ifndef CODEC_MASTER
|
||||||
|
if(dsdMode == DSD_MODE_OFF)
|
||||||
|
{
|
||||||
|
#if (I2S_CHANS_ADC != 0 || I2S_CHANS_DAC != 0)
|
||||||
|
/* Set clocks low */
|
||||||
|
p_lrclk <: 0;
|
||||||
|
p_bclk <: 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#if(DSD_CHANS_DAC != 0)
|
||||||
|
/* DSD Clock might not be shared with lrclk or bclk... */
|
||||||
|
p_dsd_clk <: 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if (DSD_CHANS_DAC > 0)
|
||||||
|
if(dsdMode == DSD_MODE_DOP)
|
||||||
|
dsdMode = DSD_MODE_OFF;
|
||||||
|
#endif
|
||||||
|
return command;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#if NUM_USB_CHAN_OUT > 0
|
||||||
|
#pragma loop unroll
|
||||||
|
for(int i = 0; i < NUM_USB_CHAN_OUT; i++)
|
||||||
|
{
|
||||||
|
int tmp = inuint(c_out);
|
||||||
|
samplesOut[i] = tmp;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
inuint(c_out);
|
||||||
|
#endif
|
||||||
|
UserBufferManagement(samplesOut, samplesIn[readBuffNo]);
|
||||||
|
|
||||||
|
#if NUM_USB_CHAN_IN > 0
|
||||||
|
#pragma loop unroll
|
||||||
|
for(int i = 0; i < NUM_USB_CHAN_IN; i++)
|
||||||
|
{
|
||||||
|
outuint(c_out, samplesIn[readBuffNo][i]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
UserBufferManagement(samplesOut, samplesIn[readBuffNo]);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2011-2022 XMOS LIMITED.
|
// Copyright 2011-2023 XMOS LIMITED.
|
||||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||||
#include "xua.h"
|
#include "xua.h"
|
||||||
|
|
||||||
@@ -43,7 +43,7 @@
|
|||||||
|
|
||||||
/*** BUFFER SIZES ***/
|
/*** BUFFER SIZES ***/
|
||||||
|
|
||||||
#define BUFFER_PACKET_COUNT 4 /* How many packets too allow for in buffer - minimum is 4 */
|
#define BUFFER_PACKET_COUNT (4) /* How many packets too allow for in buffer - minimum is 4 */
|
||||||
|
|
||||||
#define BUFF_SIZE_OUT_HS MAX_DEVICE_AUD_PACKET_SIZE_OUT_HS * BUFFER_PACKET_COUNT
|
#define BUFF_SIZE_OUT_HS MAX_DEVICE_AUD_PACKET_SIZE_OUT_HS * BUFFER_PACKET_COUNT
|
||||||
#define BUFF_SIZE_OUT_FS MAX_DEVICE_AUD_PACKET_SIZE_OUT_FS * BUFFER_PACKET_COUNT
|
#define BUFF_SIZE_OUT_FS MAX_DEVICE_AUD_PACKET_SIZE_OUT_FS * BUFFER_PACKET_COUNT
|
||||||
@@ -55,18 +55,25 @@
|
|||||||
#define BUFF_SIZE_IN MAX(BUFF_SIZE_IN_HS, BUFF_SIZE_IN_FS)
|
#define BUFF_SIZE_IN MAX(BUFF_SIZE_IN_HS, BUFF_SIZE_IN_FS)
|
||||||
|
|
||||||
#define OUT_BUFFER_PREFILL (MAX(MAX_DEVICE_AUD_PACKET_SIZE_OUT_HS, MAX_DEVICE_AUD_PACKET_SIZE_OUT_FS))
|
#define OUT_BUFFER_PREFILL (MAX(MAX_DEVICE_AUD_PACKET_SIZE_OUT_HS, MAX_DEVICE_AUD_PACKET_SIZE_OUT_FS))
|
||||||
#define IN_BUFFER_PREFILL (MAX(MAX_DEVICE_AUD_PACKET_SIZE_IN_HS, MAX_DEVICE_AUD_PACKET_SIZE_IN_FS)*2)
|
#define IN_BUFFER_PREFILL (MAX(MAX_DEVICE_AUD_PACKET_SIZE_IN_HS, MAX_DEVICE_AUD_PACKET_SIZE_IN_FS)*2)
|
||||||
|
|
||||||
/* Volume and mute tables */
|
/* Volume and mute tables */
|
||||||
#if !defined(OUT_VOLUME_IN_MIXER) && (OUTPUT_VOLUME_CONTROL == 1)
|
#if (OUT_VOLUME_IN_MIXER == 0) && (OUTPUT_VOLUME_CONTROL == 1)
|
||||||
unsigned int multOut[NUM_USB_CHAN_OUT + 1];
|
unsigned int multOut[NUM_USB_CHAN_OUT + 1];
|
||||||
static xc_ptr p_multOut;
|
unsafe
|
||||||
|
{
|
||||||
|
unsigned int volatile * unsafe multOutPtr = multOut;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#if !defined(IN_VOLUME_IN_MIXER) && (INPUT_VOLUME_CONTROL == 1)
|
#if (IN_VOLUME_IN_MIXER == 0) && (INPUT_VOLUME_CONTROL == 1)
|
||||||
unsigned int multIn[NUM_USB_CHAN_IN + 1];
|
unsigned int multIn[NUM_USB_CHAN_IN + 1];
|
||||||
static xc_ptr p_multIn;
|
unsafe
|
||||||
|
{
|
||||||
|
unsigned int volatile * unsafe multInPtr = multIn;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Default to something sensible but the following are setup at stream start (unless UAC1 only..) */
|
||||||
#if (AUDIO_CLASS == 2)
|
#if (AUDIO_CLASS == 2)
|
||||||
int g_numUsbChan_In = NUM_USB_CHAN_IN; /* Number of channels to/from the USB bus - initialised to HS for UAC2.0 */
|
int g_numUsbChan_In = NUM_USB_CHAN_IN; /* Number of channels to/from the USB bus - initialised to HS for UAC2.0 */
|
||||||
int g_numUsbChan_Out = NUM_USB_CHAN_OUT;
|
int g_numUsbChan_Out = NUM_USB_CHAN_OUT;
|
||||||
@@ -143,7 +150,72 @@ unsigned unpackData = 0;
|
|||||||
unsigned packState = 0;
|
unsigned packState = 0;
|
||||||
unsigned packData = 0;
|
unsigned packData = 0;
|
||||||
|
|
||||||
/* Default to something sensible but the following are setup at stream start (unless UAC1 only..) */
|
static inline void SendSamples4(chanend c_mix_out)
|
||||||
|
{
|
||||||
|
/* Doing this checking allows us to unroll */
|
||||||
|
if(g_numUsbChan_Out == NUM_USB_CHAN_OUT)
|
||||||
|
{
|
||||||
|
/* Buffering not underflow condition send out some samples...*/
|
||||||
|
#pragma loop unroll
|
||||||
|
for(int i = 0; i < NUM_USB_CHAN_OUT; i++)
|
||||||
|
{
|
||||||
|
int sample;
|
||||||
|
int mult;
|
||||||
|
int h;
|
||||||
|
unsigned l;
|
||||||
|
|
||||||
|
read_via_xc_ptr(sample, g_aud_from_host_rdptr);
|
||||||
|
g_aud_from_host_rdptr+=4;
|
||||||
|
|
||||||
|
#if (OUTPUT_VOLUME_CONTROL == 1) && (!OUT_VOLUME_IN_MIXER)
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
mult = multOutPtr[i];
|
||||||
|
}
|
||||||
|
{h, l} = macs(mult, sample, 0, 0);
|
||||||
|
h <<= 3;
|
||||||
|
#if (STREAM_FORMAT_OUTPUT_RESOLUTION_32BIT_USED == 1)
|
||||||
|
h |= (l >>29) & 0x7; // Note: This step is not required if we assume sample depth is 24bit (rather than 32bit)
|
||||||
|
// Note: We need all 32bits for Native DSD
|
||||||
|
#endif
|
||||||
|
outuint(c_mix_out, h);
|
||||||
|
#else
|
||||||
|
outuint(c_mix_out, sample);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#pragma loop unroll
|
||||||
|
for(int i = 0; i < NUM_USB_CHAN_OUT_FS; i++)
|
||||||
|
{
|
||||||
|
int sample;
|
||||||
|
int mult;
|
||||||
|
int h;
|
||||||
|
unsigned l;
|
||||||
|
|
||||||
|
read_via_xc_ptr(sample, g_aud_from_host_rdptr);
|
||||||
|
g_aud_from_host_rdptr+=4;
|
||||||
|
|
||||||
|
#if (OUTPUT_VOLUME_CONTROL == 1) && (!OUT_VOLUME_IN_MIXER)
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
mult = multOutPtr[i];
|
||||||
|
}
|
||||||
|
{h, l} = macs(mult, sample, 0, 0);
|
||||||
|
h <<= 3;
|
||||||
|
#if (STREAM_FORMAT_OUTPUT_RESOLUTION_32BIT_USED == 1)
|
||||||
|
h |= (l >>29) & 0x7; // Note: This step is not required if we assume sample depth is 24bit (rather than 32bit)
|
||||||
|
// Note: We need all 32bits for Native DSD
|
||||||
|
#endif
|
||||||
|
outuint(c_mix_out, h);
|
||||||
|
#else
|
||||||
|
outuint(c_mix_out, sample);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#pragma select handler
|
#pragma select handler
|
||||||
#pragma unsafe arrays
|
#pragma unsafe arrays
|
||||||
@@ -206,8 +278,11 @@ __builtin_unreachable();
|
|||||||
g_aud_from_host_rdptr+=2;
|
g_aud_from_host_rdptr+=2;
|
||||||
sample <<= 16;
|
sample <<= 16;
|
||||||
|
|
||||||
#if (OUTPUT_VOLUME_CONTROL == 1) && !defined(OUT_VOLUME_IN_MIXER)
|
#if (OUTPUT_VOLUME_CONTROL == 1) && (!OUT_VOLUME_IN_MIXER)
|
||||||
asm volatile("ldw %0, %1[%2]":"=r"(mult):"r"(p_multOut),"r"(i));
|
unsafe
|
||||||
|
{
|
||||||
|
mult = multOutPtr[i];
|
||||||
|
}
|
||||||
{h, l} = macs(mult, sample, 0, 0);
|
{h, l} = macs(mult, sample, 0, 0);
|
||||||
/* Note, in 2 byte subslot mode - ignore lower result of macs */
|
/* Note, in 2 byte subslot mode - ignore lower result of macs */
|
||||||
h <<= 3;
|
h <<= 3;
|
||||||
@@ -223,41 +298,17 @@ __builtin_unreachable();
|
|||||||
__builtin_unreachable();
|
__builtin_unreachable();
|
||||||
#endif
|
#endif
|
||||||
/* Buffering not underflow condition send out some samples...*/
|
/* Buffering not underflow condition send out some samples...*/
|
||||||
for(int i = 0; i < g_numUsbChan_Out; i++)
|
SendSamples4(c_mix_out);
|
||||||
{
|
|
||||||
#pragma xta endpoint "mixer_request"
|
|
||||||
int sample;
|
|
||||||
int mult;
|
|
||||||
int h;
|
|
||||||
unsigned l;
|
|
||||||
|
|
||||||
read_via_xc_ptr(sample, g_aud_from_host_rdptr);
|
|
||||||
g_aud_from_host_rdptr+=4;
|
|
||||||
|
|
||||||
#if (OUTPUT_VOLUME_CONTROL == 1) && !defined(OUT_VOLUME_IN_MIXER)
|
|
||||||
asm volatile("ldw %0, %1[%2]":"=r"(mult):"r"(p_multOut),"r"(i));
|
|
||||||
{h, l} = macs(mult, sample, 0, 0);
|
|
||||||
h <<= 3;
|
|
||||||
#if (STREAM_FORMAT_OUTPUT_RESOLUTION_32BIT_USED == 1)
|
|
||||||
h |= (l >>29)& 0x7; // Note: This step is not required if we assume sample depth is 24bit (rather than 32bit)
|
|
||||||
// Note: We need all 32bits for Native DSD
|
|
||||||
#endif
|
|
||||||
outuint(c_mix_out, h);
|
|
||||||
#else
|
|
||||||
outuint(c_mix_out, sample);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
#if (STREAM_FORMAT_OUTPUT_SUBSLOT_3_USED == 0)
|
#if (STREAM_FORMAT_OUTPUT_SUBSLOT_3_USED == 0)
|
||||||
__builtin_unreachable();
|
__builtin_unreachable();
|
||||||
#endif
|
#endif
|
||||||
/* Buffering not underflow condition send out some samples...*/
|
/* Note, in this case the unpacking of data is more of an overhead than the loop overhead
|
||||||
|
* so we do not currently make attempts to unroll */
|
||||||
for(int i = 0; i < g_numUsbChan_Out; i++)
|
for(int i = 0; i < g_numUsbChan_Out; i++)
|
||||||
{
|
{
|
||||||
#pragma xta endpoint "mixer_request"
|
|
||||||
int sample;
|
int sample;
|
||||||
int mult;
|
int mult;
|
||||||
int h;
|
int h;
|
||||||
@@ -289,19 +340,20 @@ __builtin_unreachable();
|
|||||||
}
|
}
|
||||||
unpackState++;
|
unpackState++;
|
||||||
|
|
||||||
#if (OUTPUT_VOLUME_CONTROL == 1) && !defined(OUT_VOLUME_IN_MIXER)
|
#if (OUTPUT_VOLUME_CONTROL == 1) && (!OUT_VOLUME_IN_MIXER)
|
||||||
asm volatile("ldw %0, %1[%2]":"=r"(mult):"r"(p_multOut),"r"(i));
|
unsafe
|
||||||
|
{
|
||||||
|
mult = multOutPtr[i];
|
||||||
|
}
|
||||||
{h, l} = macs(mult, sample, 0, 0);
|
{h, l} = macs(mult, sample, 0, 0);
|
||||||
h <<= 3;
|
h <<= 3;
|
||||||
outuint(c_mix_out, h);
|
outuint(c_mix_out, h);
|
||||||
#else
|
#else
|
||||||
outuint(c_mix_out, sample);
|
outuint(c_mix_out, sample);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
__builtin_unreachable();
|
__builtin_unreachable();
|
||||||
break;
|
break;
|
||||||
@@ -335,17 +387,20 @@ __builtin_unreachable();
|
|||||||
/* Receive sample */
|
/* Receive sample */
|
||||||
int sample = inuint(c_mix_out);
|
int sample = inuint(c_mix_out);
|
||||||
#if (INPUT_VOLUME_CONTROL == 1)
|
#if (INPUT_VOLUME_CONTROL == 1)
|
||||||
#if !defined(IN_VOLUME_IN_MIXER)
|
#if (!IN_VOLUME_IN_MIXER)
|
||||||
/* Apply volume */
|
/* Apply volume */
|
||||||
int mult;
|
int mult;
|
||||||
int h;
|
int h;
|
||||||
unsigned l;
|
unsigned l;
|
||||||
asm volatile("ldw %0, %1[%2]":"=r"(mult):"r"(p_multIn),"r"(i));
|
unsafe
|
||||||
|
{
|
||||||
|
mult = multInPtr[i];
|
||||||
|
}
|
||||||
{h, l} = macs(mult, sample, 0, 0);
|
{h, l} = macs(mult, sample, 0, 0);
|
||||||
sample = h << 3;
|
sample = h << 3;
|
||||||
|
|
||||||
/* Note, in 2 byte sub slot - ignore lower bits of macs */
|
/* Note, in 2 byte sub slot - ignore lower bits of macs */
|
||||||
#elif defined(IN_VOLUME_IN_MIXER) && defined(IN_VOLUME_AFTER_MIX)
|
#elif (IN_VOLUME_IN_MIXER) && defined(IN_VOLUME_AFTER_MIX)
|
||||||
sample = sample << 3;
|
sample = sample << 3;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
@@ -365,18 +420,21 @@ __builtin_unreachable();
|
|||||||
/* Receive sample */
|
/* Receive sample */
|
||||||
int sample = inuint(c_mix_out);
|
int sample = inuint(c_mix_out);
|
||||||
#if(INPUT_VOLUME_CONTROL == 1)
|
#if(INPUT_VOLUME_CONTROL == 1)
|
||||||
#if !defined(IN_VOLUME_IN_MIXER)
|
#if (!IN_VOLUME_IN_MIXER)
|
||||||
/* Apply volume */
|
/* Apply volume */
|
||||||
int mult;
|
int mult;
|
||||||
int h;
|
int h;
|
||||||
unsigned l;
|
unsigned l;
|
||||||
asm volatile("ldw %0, %1[%2]":"=r"(mult):"r"(p_multIn),"r"(i));
|
unsafe
|
||||||
|
{
|
||||||
|
mult = multInPtr[i];
|
||||||
|
}
|
||||||
{h, l} = macs(mult, sample, 0, 0);
|
{h, l} = macs(mult, sample, 0, 0);
|
||||||
sample = h << 3;
|
sample = h << 3;
|
||||||
#if (STREAM_FORMAT_INPUT_RESOLUTION_32BIT_USED == 1)
|
#if (STREAM_FORMAT_INPUT_RESOLUTION_32BIT_USED == 1)
|
||||||
sample |= (l >> 29) & 0x7; // Note, this step is not required if we assume sample depth is 24 (rather than 32)
|
sample |= (l >> 29) & 0x7; // Note, this step is not required if we assume sample depth is 24 (rather than 32)
|
||||||
#endif
|
#endif
|
||||||
#elif defined(IN_VOLUME_IN_MIXER) && defined(IN_VOLUME_AFTER_MIX)
|
#elif (IN_VOLUME_IN_MIXER) && (IN_VOLUME_AFTER_MIX)
|
||||||
sample = sample << 3;
|
sample = sample << 3;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
@@ -396,12 +454,15 @@ __builtin_unreachable();
|
|||||||
{
|
{
|
||||||
/* Receive sample */
|
/* Receive sample */
|
||||||
int sample = inuint(c_mix_out);
|
int sample = inuint(c_mix_out);
|
||||||
#if (INPUT_VOLUME_CONTROL) && !defined(IN_VOLUME_IN_MIXER)
|
#if (INPUT_VOLUME_CONTROL) && (!IN_VOLUME_IN_MIXER)
|
||||||
/* Apply volume */
|
/* Apply volume */
|
||||||
int mult;
|
int mult;
|
||||||
int h;
|
int h;
|
||||||
unsigned l;
|
unsigned l;
|
||||||
asm volatile("ldw %0, %1[%2]":"=r"(mult):"r"(p_multIn),"r"(i));
|
unsafe
|
||||||
|
{
|
||||||
|
mult = multInPtr[i];
|
||||||
|
}
|
||||||
{h, l} = macs(mult, sample, 0, 0);
|
{h, l} = macs(mult, sample, 0, 0);
|
||||||
sample = h << 3;
|
sample = h << 3;
|
||||||
#endif
|
#endif
|
||||||
@@ -588,6 +649,7 @@ __builtin_unreachable();
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if (NUM_USB_CHAN_IN > 0)
|
||||||
/* Mark Endpoint (IN) ready with an appropriately sized zero buffer */
|
/* Mark Endpoint (IN) ready with an appropriately sized zero buffer */
|
||||||
static inline void SetupZerosSendBuffer(XUD_ep aud_to_host_usb_ep, unsigned sampFreq, unsigned slotSize,
|
static inline void SetupZerosSendBuffer(XUD_ep aud_to_host_usb_ep, unsigned sampFreq, unsigned slotSize,
|
||||||
xc_ptr aud_to_host_zeros)
|
xc_ptr aud_to_host_zeros)
|
||||||
@@ -619,6 +681,7 @@ static inline void SetupZerosSendBuffer(XUD_ep aud_to_host_usb_ep, unsigned samp
|
|||||||
|
|
||||||
XUD_SetReady_InPtr(aud_to_host_usb_ep, aud_to_host_zeros+4, mid);
|
XUD_SetReady_InPtr(aud_to_host_usb_ep, aud_to_host_zeros+4, mid);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#pragma unsafe arrays
|
#pragma unsafe arrays
|
||||||
void XUA_Buffer_Decouple(chanend c_mix_out
|
void XUA_Buffer_Decouple(chanend c_mix_out
|
||||||
@@ -638,13 +701,6 @@ void XUA_Buffer_Decouple(chanend c_mix_out
|
|||||||
|
|
||||||
int t = array_to_xc_ptr(outAudioBuff);
|
int t = array_to_xc_ptr(outAudioBuff);
|
||||||
|
|
||||||
#if !defined(OUT_VOLUME_IN_MIXER) && (OUTPUT_VOLUME_CONTROL == 1)
|
|
||||||
p_multOut = array_to_xc_ptr(multOut);
|
|
||||||
#endif
|
|
||||||
#if !defined(IN_VOLUME_IN_MIXER) && (INPUT_VOLUME_CONTROL == 1)
|
|
||||||
p_multIn = array_to_xc_ptr(multIn);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
aud_from_host_fifo_start = t;
|
aud_from_host_fifo_start = t;
|
||||||
aud_from_host_fifo_end = aud_from_host_fifo_start + BUFF_SIZE_OUT;
|
aud_from_host_fifo_end = aud_from_host_fifo_start + BUFF_SIZE_OUT;
|
||||||
g_aud_from_host_wrptr = aud_from_host_fifo_start;
|
g_aud_from_host_wrptr = aud_from_host_fifo_start;
|
||||||
@@ -668,17 +724,17 @@ void XUA_Buffer_Decouple(chanend c_mix_out
|
|||||||
xc_ptr aud_to_host_zeros = t;
|
xc_ptr aud_to_host_zeros = t;
|
||||||
|
|
||||||
/* Init vol mult tables */
|
/* Init vol mult tables */
|
||||||
#if !defined(OUT_VOLUME_IN_MIXER) && (OUTPUT_VOLUME_CONTROL == 1)
|
#if (OUT_VOLUME_IN_MIXER == 0) && (OUTPUT_VOLUME_CONTROL == 1)
|
||||||
for (int i = 0; i < NUM_USB_CHAN_OUT + 1; i++)
|
for (int i = 0; i < NUM_USB_CHAN_OUT + 1; i++)
|
||||||
{
|
unsafe{
|
||||||
asm volatile("stw %0, %1[%2]"::"r"(MAX_VOL),"r"(p_multOut),"r"(i));
|
multOutPtr[i] = MAX_VOLUME_MULT;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(IN_VOLUME_IN_MIXER) && (INPUT_VOLUME_CONTROL == 1)
|
#if (IN_VOLUME_IN_MIXER == 0) && (INPUT_VOLUME_CONTROL == 1)
|
||||||
for (int i = 0; i < NUM_USB_CHAN_IN + 1; i++)
|
for (int i = 0; i < NUM_USB_CHAN_IN + 1; i++)
|
||||||
{
|
unsafe{
|
||||||
asm volatile("stw %0, %1[%2]"::"r"(MAX_VOL),"r"(p_multIn),"r"(i));
|
multInPtr[i] = MAX_VOLUME_MULT;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -760,8 +816,10 @@ void XUA_Buffer_Decouple(chanend c_mix_out
|
|||||||
/* Set buffer to send back to zeros buffer */
|
/* Set buffer to send back to zeros buffer */
|
||||||
aud_to_host_buffer = aud_to_host_zeros;
|
aud_to_host_buffer = aud_to_host_zeros;
|
||||||
|
|
||||||
|
#if (NUM_USB_CHAN_IN > 0)
|
||||||
/* Update size of zeros buffer (and sampsToWrite) */
|
/* Update size of zeros buffer (and sampsToWrite) */
|
||||||
SetupZerosSendBuffer(aud_to_host_usb_ep, sampFreq, g_curSubSlot_In, aud_to_host_zeros);
|
SetupZerosSendBuffer(aud_to_host_usb_ep, sampFreq, g_curSubSlot_In, aud_to_host_zeros);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Reset OUT buffer state */
|
/* Reset OUT buffer state */
|
||||||
outUnderflow = 1;
|
outUnderflow = 1;
|
||||||
@@ -815,8 +873,10 @@ void XUA_Buffer_Decouple(chanend c_mix_out
|
|||||||
/* Set buffer back to zeros buffer */
|
/* Set buffer back to zeros buffer */
|
||||||
aud_to_host_buffer = aud_to_host_zeros;
|
aud_to_host_buffer = aud_to_host_zeros;
|
||||||
|
|
||||||
|
#if (NUM_USB_CHAN_IN > 0)
|
||||||
/* Update size of zeros buffer (and sampsToWrite) */
|
/* Update size of zeros buffer (and sampsToWrite) */
|
||||||
SetupZerosSendBuffer(aud_to_host_usb_ep, sampFreq, g_curSubSlot_In, aud_to_host_zeros);
|
SetupZerosSendBuffer(aud_to_host_usb_ep, sampFreq, g_curSubSlot_In, aud_to_host_zeros);
|
||||||
|
#endif
|
||||||
|
|
||||||
GET_SHARED_GLOBAL(usbSpeed, g_curUsbSpeed);
|
GET_SHARED_GLOBAL(usbSpeed, g_curUsbSpeed);
|
||||||
if (usbSpeed == XUD_SPEED_HS)
|
if (usbSpeed == XUD_SPEED_HS)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2011-2022 XMOS LIMITED.
|
// Copyright 2011-2023 XMOS LIMITED.
|
||||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||||
#include "xua.h"
|
#include "xua.h"
|
||||||
#if XUA_USB_EN
|
#if XUA_USB_EN
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
#include "xud.h"
|
#include "xud.h"
|
||||||
#include "testct_byref.h"
|
#include "testct_byref.h"
|
||||||
|
|
||||||
#if( 0 < HID_CONTROLS )
|
#if XUA_HID_ENABLED
|
||||||
#include "xua_hid_report.h"
|
#include "xua_hid_report.h"
|
||||||
#include "user_hid.h"
|
#include "user_hid.h"
|
||||||
#include "xua_hid.h"
|
#include "xua_hid.h"
|
||||||
@@ -105,7 +105,11 @@ void XUA_Buffer(
|
|||||||
#endif
|
#endif
|
||||||
, chanend c_aud
|
, chanend c_aud
|
||||||
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC)
|
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC)
|
||||||
|
#if(XUA_USE_APP_PLL)
|
||||||
|
, chanend c_swpll_update
|
||||||
|
#else
|
||||||
, client interface pll_ref_if i_pll_ref
|
, client interface pll_ref_if i_pll_ref
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@@ -134,14 +138,18 @@ void XUA_Buffer(
|
|||||||
c_clk_int,
|
c_clk_int,
|
||||||
#endif
|
#endif
|
||||||
c_sof, c_aud_ctl, p_off_mclk
|
c_sof, c_aud_ctl, p_off_mclk
|
||||||
#if( 0 < HID_CONTROLS )
|
#if XUA_HID_ENABLED
|
||||||
, c_hid
|
, c_hid
|
||||||
#endif
|
#endif
|
||||||
#ifdef CHAN_BUFF_CTRL
|
#ifdef CHAN_BUFF_CTRL
|
||||||
, c_buff_ctrl
|
, c_buff_ctrl
|
||||||
#endif
|
#endif
|
||||||
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC)
|
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC)
|
||||||
, i_pll_ref
|
#if(XUA_USE_APP_PLL)
|
||||||
|
, c_swpll_update
|
||||||
|
#else
|
||||||
|
, i_pll_ref
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -190,8 +198,12 @@ void XUA_Buffer_Ep(register chanend c_aud_out,
|
|||||||
#ifdef CHAN_BUFF_CTRL
|
#ifdef CHAN_BUFF_CTRL
|
||||||
, chanend c_buff_ctrl
|
, chanend c_buff_ctrl
|
||||||
#endif
|
#endif
|
||||||
#if XUA_SYNCMODE == XUA_SYNCMODE_SYNC
|
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC)
|
||||||
|
#if (XUA_USE_APP_PLL)
|
||||||
|
, chanend c_swpll_update
|
||||||
|
#else
|
||||||
, client interface pll_ref_if i_pll_ref
|
, client interface pll_ref_if i_pll_ref
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@@ -224,7 +236,7 @@ void XUA_Buffer_Ep(register chanend c_aud_out,
|
|||||||
XUD_ep ep_int = XUD_InitEp(c_ep_int);
|
XUD_ep ep_int = XUD_InitEp(c_ep_int);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if( 0 < HID_CONTROLS )
|
#if XUA_HID_ENABLED
|
||||||
XUD_ep ep_hid = XUD_InitEp(c_hid);
|
XUD_ep ep_hid = XUD_InitEp(c_hid);
|
||||||
#endif
|
#endif
|
||||||
unsigned u_tmp;
|
unsigned u_tmp;
|
||||||
@@ -247,7 +259,8 @@ void XUA_Buffer_Ep(register chanend c_aud_out,
|
|||||||
#if (NUM_USB_CHAN_IN > 0)
|
#if (NUM_USB_CHAN_IN > 0)
|
||||||
unsigned bufferIn = 1;
|
unsigned bufferIn = 1;
|
||||||
#endif
|
#endif
|
||||||
unsigned sofCount = 0;
|
int sofCount = 0;
|
||||||
|
int pllUpdate = 0;
|
||||||
|
|
||||||
unsigned mod_from_last_time = 0;
|
unsigned mod_from_last_time = 0;
|
||||||
#ifdef FB_TOLERANCE_TEST
|
#ifdef FB_TOLERANCE_TEST
|
||||||
@@ -294,7 +307,6 @@ void XUA_Buffer_Ep(register chanend c_aud_out,
|
|||||||
unsigned iap_ea_native_interface_alt_setting = 0;
|
unsigned iap_ea_native_interface_alt_setting = 0;
|
||||||
unsigned iap_ea_native_control_to_send = 0;
|
unsigned iap_ea_native_control_to_send = 0;
|
||||||
unsigned iap_ea_native_incoming = 0;
|
unsigned iap_ea_native_incoming = 0;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -332,7 +344,7 @@ void XUA_Buffer_Ep(register chanend c_aud_out,
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if( 0 < HID_CONTROLS )
|
#if XUA_HID_ENABLED
|
||||||
|
|
||||||
while (!hidIsReportDescriptorPrepared())
|
while (!hidIsReportDescriptorPrepared())
|
||||||
;
|
;
|
||||||
@@ -357,12 +369,16 @@ void XUA_Buffer_Ep(register chanend c_aud_out,
|
|||||||
#ifndef LOCAL_CLOCK_MARGIN
|
#ifndef LOCAL_CLOCK_MARGIN
|
||||||
#define LOCAL_CLOCK_MARGIN (1000)
|
#define LOCAL_CLOCK_MARGIN (1000)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if (!XUA_USE_APP_PLL)
|
||||||
timer t_sofCheck;
|
timer t_sofCheck;
|
||||||
unsigned timeLastEdge;
|
unsigned timeLastEdge;
|
||||||
unsigned timeNextEdge;
|
unsigned timeNextEdge;
|
||||||
t_sofCheck :> timeLastEdge;
|
t_sofCheck :> timeLastEdge;
|
||||||
timeNextEdge + LOCAL_CLOCK_INCREMENT;
|
timeNextEdge + LOCAL_CLOCK_INCREMENT;
|
||||||
i_pll_ref.toggle();
|
i_pll_ref.toggle();
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
while(1)
|
while(1)
|
||||||
@@ -427,7 +443,8 @@ void XUA_Buffer_Ep(register chanend c_aud_out,
|
|||||||
/* Reset FB */
|
/* Reset FB */
|
||||||
/* Note, Endpoint 0 will hold off host for a sufficient period to allow our feedback
|
/* Note, Endpoint 0 will hold off host for a sufficient period to allow our feedback
|
||||||
* to stabilise (i.e. sofCount == 128 to fire) */
|
* to stabilise (i.e. sofCount == 128 to fire) */
|
||||||
sofCount = 1;
|
sofCount = 0;
|
||||||
|
pllUpdate = 0;
|
||||||
clocks = 0;
|
clocks = 0;
|
||||||
clockcounter = 0;
|
clockcounter = 0;
|
||||||
mod_from_last_time = 0;
|
mod_from_last_time = 0;
|
||||||
@@ -502,13 +519,13 @@ void XUA_Buffer_Ep(register chanend c_aud_out,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
/* Pass on sample freq change to decouple() via global flag (saves a chanend) */
|
/* Pass on sample freq change to decouple() via global flag (saves a chanend) */
|
||||||
/* Note: freqChange flags now used to communicate other commands also */
|
/* Note: freqChange_flag now used to communicate other commands also */
|
||||||
SET_SHARED_GLOBAL0(g_freqChange, cmd); /* Set command */
|
SET_SHARED_GLOBAL0(g_freqChange, cmd); /* Set command */
|
||||||
SET_SHARED_GLOBAL(g_freqChange_flag, cmd); /* Set Flag */
|
SET_SHARED_GLOBAL(g_freqChange_flag, cmd); /* Set Flag */
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC)
|
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC) && (!XUA_USE_APP_PLL)
|
||||||
case t_sofCheck when timerafter(timeNextEdge) :> void:
|
case t_sofCheck when timerafter(timeNextEdge) :> void:
|
||||||
i_pll_ref.toggle();
|
i_pll_ref.toggle();
|
||||||
timeLastEdge = timeNextEdge;
|
timeLastEdge = timeNextEdge;
|
||||||
@@ -528,7 +545,6 @@ void XUA_Buffer_Ep(register chanend c_aud_out,
|
|||||||
unsigned usbSpeed;
|
unsigned usbSpeed;
|
||||||
int framesPerSec;
|
int framesPerSec;
|
||||||
GET_SHARED_GLOBAL(usbSpeed, g_curUsbSpeed);
|
GET_SHARED_GLOBAL(usbSpeed, g_curUsbSpeed);
|
||||||
static int sofCount = 0;
|
|
||||||
|
|
||||||
framesPerSec = (usbSpeed == XUD_SPEED_HS) ? 8000 : 1000;
|
framesPerSec = (usbSpeed == XUD_SPEED_HS) ? 8000 : 1000;
|
||||||
|
|
||||||
@@ -539,12 +555,27 @@ void XUA_Buffer_Ep(register chanend c_aud_out,
|
|||||||
sofCount += 1000;
|
sofCount += 1000;
|
||||||
if (sofCount == framesPerSec)
|
if (sofCount == framesPerSec)
|
||||||
{
|
{
|
||||||
|
sofCount = 0;
|
||||||
|
pllUpdate++;
|
||||||
|
#if (!XUA_USE_APP_PLL)
|
||||||
/* Port is accessed via interface to allow flexibilty with location */
|
/* Port is accessed via interface to allow flexibilty with location */
|
||||||
i_pll_ref.toggle();
|
i_pll_ref.toggle();
|
||||||
t_sofCheck :> timeLastEdge;
|
t_sofCheck :> timeLastEdge;
|
||||||
sofCount = 0;
|
|
||||||
timeNextEdge = timeLastEdge + LOCAL_CLOCK_INCREMENT + LOCAL_CLOCK_MARGIN;
|
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)
|
#elif (XUA_SYNCMODE == XUA_SYNCMODE_ASYNC)
|
||||||
|
|
||||||
/* NOTE our feedback will be wrong for a couple of SOF's after a SF change due to
|
/* NOTE our feedback will be wrong for a couple of SOF's after a SF change due to
|
||||||
@@ -646,7 +677,6 @@ void XUA_Buffer_Ep(register chanend c_aud_out,
|
|||||||
clockcounter = 0;
|
clockcounter = 0;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|
||||||
/* Assuming 48kHz from a 24.576 master clock (0.0407uS period)
|
/* Assuming 48kHz from a 24.576 master clock (0.0407uS period)
|
||||||
* MCLK ticks per SOF = 125uS / 0.0407 = 3072 MCLK ticks per SOF.
|
* 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.
|
* expected Feedback is 48000/8000 = 6 samples. so 0x60000 in 16:16 format.
|
||||||
@@ -897,8 +927,8 @@ void XUA_Buffer_Ep(register chanend c_aud_out,
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if( 0 < HID_CONTROLS )
|
#if (XUA_HID_ENABLED)
|
||||||
/* HID Report Data */
|
/* HID Report Data */
|
||||||
case XUD_SetData_Select(c_hid, ep_hid, result):
|
case XUD_SetData_Select(c_hid, ep_hid, result):
|
||||||
hid_ready_flag = 0U;
|
hid_ready_flag = 0U;
|
||||||
unsigned reportTime;
|
unsigned reportTime;
|
||||||
@@ -911,7 +941,7 @@ void XUA_Buffer_Ep(register chanend c_aud_out,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MIDI
|
#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):
|
case midi_get_ack_or_data(c_midi, is_ack, datum):
|
||||||
if (is_ack)
|
if (is_ack)
|
||||||
{
|
{
|
||||||
|
|||||||
457
lib_xua/src/core/clocking/apppll.xc
Normal file
457
lib_xua/src/core/clocking/apppll.xc
Normal file
@@ -0,0 +1,457 @@
|
|||||||
|
// Copyright 2023 XMOS LIMITED.
|
||||||
|
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||||
|
#include <print.h>
|
||||||
|
#include <platform.h>
|
||||||
|
#include "xua.h"
|
||||||
|
#include "xassert.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#if (XUA_USE_APP_PLL)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Functions for interacting with the secondary/application PLL
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __XS3A__
|
||||||
|
#error App PLL not included in device
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* App PLL settings used for syncing to external clocks
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Define the PLL settings to generate the required frequencies.
|
||||||
|
// All settings allow greater than +-1000ppm lock range.
|
||||||
|
// Comment out the following line for 2us update.
|
||||||
|
|
||||||
|
//#define FAST_FRAC_REG_WRITE
|
||||||
|
|
||||||
|
// OPTION 1 - 1us register update rate - Lowest jitter
|
||||||
|
// 10ps jitter 100Hz-40kHz. Low freq noise floor -100dBc
|
||||||
|
|
||||||
|
#ifdef FAST_FRAC_REG_WRITE
|
||||||
|
|
||||||
|
#define FRAC_REG_WRITE_DLY (100)
|
||||||
|
|
||||||
|
// Found solution: IN 24.000MHz, OUT 22.578947MHz, VCO 3251.37MHz, RD 1, FD 135.474 (m = 9, n = 19), OD 6, FOD 6, ERR -11.189ppm
|
||||||
|
#define APP_PLL_CTL_SYNC_22M (0x0A808600)
|
||||||
|
#define APP_PLL_DIV_SYNC_22M (0x80000005)
|
||||||
|
#define APP_PLL_FRAC_SYNC_22M (0x80000812)
|
||||||
|
#define APP_PLL_ERR_MULT_22M (627) // round(135(divider)*100Hz*1048576/22579200)
|
||||||
|
#define APP_PLL_MOD_INIT_22M (498283)
|
||||||
|
|
||||||
|
// Fout = Fin*divider/(2*2*6*6) = (fin/144) * divider = (24/144) * divider. = 1/6 * divider.
|
||||||
|
// To achieve frequency f, Fraction Setting = (6*f) - 135
|
||||||
|
// So to achieve 22.5792MHz, Fraction Setting = (6*22.5792) - 135 = 0.4752
|
||||||
|
// Numerical input = round((Fraction setting * 2^20) = 0.4752 * 1048576 = 498283
|
||||||
|
|
||||||
|
//Found solution: IN 24.000MHz, OUT 24.575758MHz, VCO 3538.91MHz, RD 1, FD 147.455 (m = 5, n = 11), OD 6, FOD 6, ERR -9.864ppm
|
||||||
|
#define APP_PLL_CTL_SYNC_24M (0x0A809200)
|
||||||
|
#define APP_PLL_DIV_SYNC_24M (0x80000005)
|
||||||
|
#define APP_PLL_FRAC_SYNC_24M (0x8000040A)
|
||||||
|
#define APP_PLL_ERR_MULT_24M (627) // round(147(divider)*100Hz*1048576/24576000)
|
||||||
|
#define APP_PLL_MOD_INIT_24M (478151)
|
||||||
|
|
||||||
|
// Fout = Fin*divider/(2*2*6*6) = (fin/144) * divider = (24/144) * divider. = 1/6 * divider.
|
||||||
|
// To achieve frequency f, Fraction Setting = (6*f) - 147
|
||||||
|
// So to achieve 24.576MHz, Fraction Setting = (6*24.576) - 147 = 0.456
|
||||||
|
// Numerical input = round((Fraction setting * 2^20) = 0.456 * 1048576 = 478151
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
// OPTION 2 - 2us register update rate - Higher jitter
|
||||||
|
// 50ps jitter 100Hz-40kHz. Low freq noise floor -93dBc
|
||||||
|
|
||||||
|
#define FRAC_REG_WRITE_DLY (200)
|
||||||
|
|
||||||
|
//Found solution: IN 24.000MHz, OUT 22.579186MHz, VCO 3522.35MHz, RD 2, FD 293.529 (m = 9, n = 17), OD 3, FOD 13, ERR -0.641ppm
|
||||||
|
#define APP_PLL_CTL_SYNC_22M (0x09012401)
|
||||||
|
#define APP_PLL_DIV_SYNC_22M (0x8000000C)
|
||||||
|
#define APP_PLL_FRAC_SYNC_22M (0x80000810)
|
||||||
|
#define APP_PLL_ERR_MULT_22M (1361) // round(293(divider)*100Hz*1048576/22579200)
|
||||||
|
#define APP_PLL_MOD_INIT_22M (555326)
|
||||||
|
|
||||||
|
// Fout = (Fin/2)*divider/(2*2*3*13) = (fin/312) * divider = (24/312) * divider. = 1/13 * divider.
|
||||||
|
// To achieve frequency f, Fraction Setting = (13*f) - 293
|
||||||
|
// So to achieve 22.5792MHz, Fraction Setting = (13*22.5792) - 293 = 0.5296
|
||||||
|
// Numerical input = round((Fraction setting * 2^20) = 0.5296 * 1048576 = 555326
|
||||||
|
|
||||||
|
//Found solution: IN 24.000MHz, OUT 24.576125MHz, VCO 3342.35MHz, RD 2, FD 278.529 (m = 9, n = 17), OD 2, FOD 17, ERR 5.069ppm - Runs VCO out fractionally out of spec at 835MHz
|
||||||
|
#define APP_PLL_CTL_SYNC_24M (0x08811501)
|
||||||
|
#define APP_PLL_DIV_SYNC_24M (0x80000010)
|
||||||
|
#define APP_PLL_FRAC_SYNC_24M (0x80000810)
|
||||||
|
#define APP_PLL_ERR_MULT_24M (1186) // round(278(divider)*100Hz*1048576/24576000)
|
||||||
|
#define APP_PLL_MOD_INIT_24M (553648)
|
||||||
|
|
||||||
|
// Fout = (Fin/2)*divider/(2*2*2*17) = (fin/272) * divider = (24/272) * divider. = 3/34 * divider.
|
||||||
|
// To achieve frequency f, Fraction Setting = ((34/3)*f) - 278
|
||||||
|
// So to achieve 24.576MHz, Fraction Setting = ((34/3)*24.576) - 278 = 0.528
|
||||||
|
// Numerical input = round((Fraction setting * 2^20) = 0.528 * 1048576 = 553648
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* App PLL settings used for low jitter fixed local clocks
|
||||||
|
*/
|
||||||
|
|
||||||
|
//Found solution: IN 24.000MHz, OUT 49.151786MHz, VCO 3145.71MHz, RD 1, FD 131.071 (m = 1, n = 14), OD 8, FOD 2, ERR -4.36ppm
|
||||||
|
// Measure: 100Hz-40kHz: ~7ps
|
||||||
|
// 100Hz-1MHz: 70ps.
|
||||||
|
// 100Hz high pass: 118ps.
|
||||||
|
#define APP_PLL_CTL_FIXED_49M (0x0B808200)
|
||||||
|
#define APP_PLL_DIV_FIXED_49M (0x80000001)
|
||||||
|
#define APP_PLL_FRAC_FIXED_49M (0x8000000D)
|
||||||
|
|
||||||
|
//Found solution: IN 24.000MHz, OUT 45.157895MHz, VCO 2709.47MHz, RD 1, FD 112.895 (m = 17, n = 19), OD 5, FOD 3, ERR -11.19ppm
|
||||||
|
// Measure: 100Hz-40kHz: 6.5ps
|
||||||
|
// 100Hz-1MHz: 67ps.
|
||||||
|
// 100Hz high pass: 215ps.
|
||||||
|
#define APP_PLL_CTL_FIXED_45M (0x0A006F00)
|
||||||
|
#define APP_PLL_DIV_FIXED_45M (0x80000002)
|
||||||
|
#define APP_PLL_FRAC_FIXED_45M (0x80001012)
|
||||||
|
|
||||||
|
// Found solution: IN 24.000MHz, OUT 24.576000MHz, VCO 2457.60MHz, RD 1, FD 102.400 (m = 2, n = 5), OD 5, FOD 5, ERR 0.0ppm
|
||||||
|
// Measure: 100Hz-40kHz: ~8ps
|
||||||
|
// 100Hz-1MHz: 63ps.
|
||||||
|
// 100Hz high pass: 127ps.
|
||||||
|
#define APP_PLL_CTL_FIXED_24M (0x0A006500)
|
||||||
|
#define APP_PLL_DIV_FIXED_24M (0x80000004)
|
||||||
|
#define APP_PLL_FRAC_FIXED_24M (0x80000104)
|
||||||
|
|
||||||
|
// Found solution: IN 24.000MHz, OUT 22.579186MHz, VCO 3522.35MHz, RD 1, FD 146.765 (m = 13, n = 17), OD 3, FOD 13, ERR -0.641ppm
|
||||||
|
// Measure: 100Hz-40kHz: 7ps
|
||||||
|
// 100Hz-1MHz: 67ps.
|
||||||
|
// 100Hz high pass: 260ps.
|
||||||
|
#define APP_PLL_CTL_FIXED_22M (0x09009100)
|
||||||
|
#define APP_PLL_DIV_FIXED_22M (0x8000000C)
|
||||||
|
#define APP_PLL_FRAC_FIXED_22M (0x80000C10)
|
||||||
|
|
||||||
|
#define APP_PLL_CTL_FIXED_12M (0x0A006500)
|
||||||
|
#define APP_PLL_DIV_FIXED_12M (0x80000009)
|
||||||
|
#define APP_PLL_FRAC_FIXED_12M (0x80000104)
|
||||||
|
|
||||||
|
#define APP_PLL_CTL_FIXED_11M (0x09009100)
|
||||||
|
#define APP_PLL_DIV_FIXED_11M (0x80000009)
|
||||||
|
#define APP_PLL_FRAC_FIXED_11M (0x80000C10)
|
||||||
|
|
||||||
|
#define APP_PLL_CTL_ENABLE (1 << 27)
|
||||||
|
#define APP_PLL_CLK_OUTPUT_ENABLE (1 << 16)
|
||||||
|
|
||||||
|
static void set_app_pll_init(tileref tile, int app_pll_ctrl)
|
||||||
|
{
|
||||||
|
// Disable the PLL
|
||||||
|
write_node_config_reg(tile, XS1_SSWITCH_SS_APP_PLL_CTL_NUM, (app_pll_ctrl & ~APP_PLL_CTL_ENABLE));
|
||||||
|
|
||||||
|
// Enable the PLL to invoke a reset on the appPLL.
|
||||||
|
write_node_config_reg(tile, XS1_SSWITCH_SS_APP_PLL_CTL_NUM, app_pll_ctrl);
|
||||||
|
|
||||||
|
// Must write the CTL register twice so that the F and R divider values are captured using a running clock.
|
||||||
|
write_node_config_reg(tile, XS1_SSWITCH_SS_APP_PLL_CTL_NUM, app_pll_ctrl);
|
||||||
|
|
||||||
|
// Now disable and re-enable the PLL so we get the full 5us reset time with the correct F and R values.
|
||||||
|
write_node_config_reg(tile, XS1_SSWITCH_SS_APP_PLL_CTL_NUM, (app_pll_ctrl & 0xF7FFFFFF));
|
||||||
|
write_node_config_reg(tile, XS1_SSWITCH_SS_APP_PLL_CTL_NUM, app_pll_ctrl);
|
||||||
|
|
||||||
|
// Wait for PLL to lock.
|
||||||
|
delay_microseconds(500);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void AppPllEnable(tileref tile, int clkFreq_hz)
|
||||||
|
{
|
||||||
|
unsigned app_pll_ctrl, app_pll_div, app_pll_frac;
|
||||||
|
|
||||||
|
/* Decide on App PLL settings */
|
||||||
|
if(XUA_SYNCMODE == XUA_SYNCMODE_SYNC)
|
||||||
|
{
|
||||||
|
switch(clkFreq_hz)
|
||||||
|
{
|
||||||
|
case 44100 * 512:
|
||||||
|
app_pll_ctrl = APP_PLL_CTL_SYNC_22M;
|
||||||
|
app_pll_div = APP_PLL_DIV_SYNC_22M;
|
||||||
|
app_pll_frac = APP_PLL_FRAC_SYNC_22M;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 48000 * 512:
|
||||||
|
app_pll_ctrl = APP_PLL_CTL_SYNC_24M;
|
||||||
|
app_pll_div = APP_PLL_DIV_SYNC_24M;
|
||||||
|
app_pll_frac = APP_PLL_FRAC_SYNC_24M;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch(clkFreq_hz)
|
||||||
|
{
|
||||||
|
case 44100 * 256:
|
||||||
|
app_pll_ctrl = APP_PLL_CTL_FIXED_11M;
|
||||||
|
app_pll_div = APP_PLL_DIV_FIXED_11M;
|
||||||
|
app_pll_frac = APP_PLL_FRAC_FIXED_11M;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 48000 * 256:
|
||||||
|
app_pll_ctrl = APP_PLL_CTL_FIXED_12M;
|
||||||
|
app_pll_div = APP_PLL_DIV_FIXED_12M;
|
||||||
|
app_pll_frac = APP_PLL_FRAC_FIXED_12M;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 44100 * 512:
|
||||||
|
app_pll_ctrl = APP_PLL_CTL_FIXED_22M;
|
||||||
|
app_pll_div = APP_PLL_DIV_FIXED_22M;
|
||||||
|
app_pll_frac = APP_PLL_FRAC_FIXED_22M;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 48000 * 512:
|
||||||
|
app_pll_ctrl = APP_PLL_CTL_FIXED_24M;
|
||||||
|
app_pll_div = APP_PLL_DIV_FIXED_24M;
|
||||||
|
app_pll_frac = APP_PLL_FRAC_FIXED_24M;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 44100 * 1024:
|
||||||
|
app_pll_ctrl = APP_PLL_CTL_FIXED_45M;
|
||||||
|
app_pll_div = APP_PLL_DIV_FIXED_45M;
|
||||||
|
app_pll_frac = APP_PLL_FRAC_FIXED_45M;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 48000 * 1024:
|
||||||
|
app_pll_ctrl = APP_PLL_CTL_FIXED_49M;
|
||||||
|
app_pll_div = APP_PLL_DIV_FIXED_49M;
|
||||||
|
app_pll_frac = APP_PLL_FRAC_FIXED_49M;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialise the AppPLL and get it running.
|
||||||
|
set_app_pll_init(tile, app_pll_ctrl);
|
||||||
|
|
||||||
|
// Write the fractional-n register, note, the top bit is set to enable the frac-n block.
|
||||||
|
write_node_config_reg(tile, XS1_SSWITCH_SS_APP_PLL_FRAC_N_DIVIDER_NUM, app_pll_frac);
|
||||||
|
|
||||||
|
// And then write the clock divider register to enable the output
|
||||||
|
write_node_config_reg(tile, XS1_SSWITCH_SS_APP_CLK_DIVIDER_NUM, app_pll_div);
|
||||||
|
|
||||||
|
// Wait for PLL output frequency to stabilise due to fractional divider enable
|
||||||
|
delay_microseconds(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoftPllInit(int clkFreq_hz, struct SoftPllState &pllState)
|
||||||
|
{
|
||||||
|
switch(clkFreq_hz)
|
||||||
|
{
|
||||||
|
case 44100 * 512:
|
||||||
|
pllState.expectedClkMod = 29184; // Count we expect on MCLK port timer at SW PLL check point. For 100Hz, 10ms.
|
||||||
|
pllState.initialSetting = APP_PLL_MOD_INIT_22M;
|
||||||
|
pllState.initialErrorMult = APP_PLL_ERR_MULT_22M;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 48000 * 512:
|
||||||
|
pllState.expectedClkMod = 49152;
|
||||||
|
pllState.initialSetting = APP_PLL_MOD_INIT_24M;
|
||||||
|
pllState.initialErrorMult = APP_PLL_ERR_MULT_24M;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pllState.ds_in = pllState.initialSetting;
|
||||||
|
pllState.ds_x1 = 0;
|
||||||
|
pllState.ds_x2 = 0;
|
||||||
|
pllState.ds_x3 = 0;
|
||||||
|
pllState.iir_y = 0;
|
||||||
|
pllState.phaseError = 0;
|
||||||
|
pllState.phaseErrorInt = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SoftPllUpdate(tileref tile, unsigned short mclk_pt, unsigned short mclk_pt_last, struct SoftPllState &pllState, int fastLock)
|
||||||
|
{
|
||||||
|
int freq_error, error_p, error_i;
|
||||||
|
|
||||||
|
unsigned expectedClksMod = pllState.expectedClkMod;
|
||||||
|
unsigned initialSetting = pllState.initialSetting;
|
||||||
|
unsigned init_err_mult = pllState.initialErrorMult;
|
||||||
|
|
||||||
|
int newSetting;
|
||||||
|
unsigned short expectedPt;
|
||||||
|
|
||||||
|
int set = -1;
|
||||||
|
int diff;
|
||||||
|
|
||||||
|
// expectedClkMod is the value of the port counter that we expect given the desired MCLK in the 10ms time period we are running at.
|
||||||
|
expectedPt = mclk_pt_last + expectedClksMod;
|
||||||
|
|
||||||
|
// Handle wrapping
|
||||||
|
if (porttimeafter(mclk_pt, expectedPt))
|
||||||
|
{
|
||||||
|
diff = -(short)(expectedPt - mclk_pt);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
diff = (short)(mclk_pt - expectedPt);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO Add a bounds checker on diff to make sure it's roughly where we expect.
|
||||||
|
// If it isn't we should ignore it as it's either a glitch or from clock start/stop.
|
||||||
|
|
||||||
|
if(fastLock) // Fast lock - set DCO based on measured frequency error in first cycle
|
||||||
|
{
|
||||||
|
initialSetting = initialSetting - (diff * init_err_mult); // init_err_mult is the dco input change to cause an output frequency offset equating to a measured input freq error of 1.
|
||||||
|
diff = 0; // reset diff to zero so following code does not see any error in this cycle.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Absolute frequency error for last measurement cycle. If diff is positive, port timer was beyond where it should have been, so MCLK was too fast. So this needs to describe a negative error.
|
||||||
|
freq_error = -diff;
|
||||||
|
|
||||||
|
// Phase error is the integral of frequency error.
|
||||||
|
pllState.phaseError += freq_error;
|
||||||
|
|
||||||
|
// Integral of phase error for use in PI loop below.
|
||||||
|
pllState.phaseErrorInt += pllState.phaseError;
|
||||||
|
|
||||||
|
error_p = (pllState.phaseError << 5); // << 5 => Kp = 32
|
||||||
|
error_i = (pllState.phaseErrorInt >> 2); // >> 2 => Ki = 0.25
|
||||||
|
|
||||||
|
// input to filter (x) is output of PI controller
|
||||||
|
int x = (error_p + error_i);
|
||||||
|
|
||||||
|
// Filter some noise into DCO to reduce jitter
|
||||||
|
// First order IIR, make A=0.125
|
||||||
|
// y = y + A(x-y)
|
||||||
|
pllState.iir_y += ((x-pllState.iir_y)>>3);
|
||||||
|
|
||||||
|
newSetting = pllState.iir_y;
|
||||||
|
|
||||||
|
// Only output new frequency tune value if different to the previous setting
|
||||||
|
if (newSetting != pllState.setting)
|
||||||
|
{
|
||||||
|
set = (initialSetting + newSetting); // init_set is our calculation of the setting required after measuring one cycle, should be accurate to +- 1MCLK.
|
||||||
|
|
||||||
|
if (set < 0)
|
||||||
|
set = 0;
|
||||||
|
else if (set > 0xFFFFF)
|
||||||
|
set = 0xFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
pllState.setting = newSetting;
|
||||||
|
|
||||||
|
// Return the setting to the NCO thread. -1 means no update
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if (XUA_SYNCMODE == XUA_SYNCMODE_ASYNC)
|
||||||
|
[[distributable]]
|
||||||
|
#endif
|
||||||
|
void XUA_SoftPll(tileref tile, server interface SoftPll_if i_softPll, chanend c_update)
|
||||||
|
{
|
||||||
|
#if (XUA_SYNCMODE != XUA_SYNCMODE_ASYNC)
|
||||||
|
unsigned frac_val;
|
||||||
|
int ds_out;
|
||||||
|
timer tmr;
|
||||||
|
int time;
|
||||||
|
unsigned mclk_pt;
|
||||||
|
unsigned short mclk_pt_last;
|
||||||
|
tmr :> time;
|
||||||
|
#endif
|
||||||
|
struct SoftPllState pllState;
|
||||||
|
int running = 0;
|
||||||
|
int firstUpdate = 1;
|
||||||
|
int fastLock = 1;
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
select
|
||||||
|
{
|
||||||
|
/* Interface used for basic frequency setting such that it can be distributed
|
||||||
|
* when the update code is not required */
|
||||||
|
case i_softPll.init(int mclk_hz):
|
||||||
|
AppPllEnable(tile, mclk_hz);
|
||||||
|
SoftPllInit(mclk_hz, pllState);
|
||||||
|
running = 1;
|
||||||
|
firstUpdate = 1;
|
||||||
|
fastLock = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
#if (XUA_SYNCMODE == XUA_SYNCMODE_ASYNC)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/* Channel used for update such that other side is not blocked */
|
||||||
|
/* TODO add CT handshake before opening route */
|
||||||
|
case inuint_byref(c_update, mclk_pt):
|
||||||
|
inct(c_update);
|
||||||
|
|
||||||
|
if(firstUpdate)
|
||||||
|
{
|
||||||
|
firstUpdate = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int setting = SoftPllUpdate(tile, (unsigned short) mclk_pt, mclk_pt_last, pllState, fastLock);
|
||||||
|
|
||||||
|
fastLock = 0;
|
||||||
|
|
||||||
|
if(setting != -1)
|
||||||
|
{
|
||||||
|
pllState.ds_in = setting;
|
||||||
|
// Limit input range for modulator stability.
|
||||||
|
if(pllState.ds_in > 980000)
|
||||||
|
pllState.ds_in = 980000;
|
||||||
|
if(pllState.ds_in < 60000)
|
||||||
|
pllState.ds_in = 60000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mclk_pt_last = (unsigned short) mclk_pt;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default :
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Third order, 9 level output delta sigma. 20 bit unsigned input.
|
||||||
|
ds_out = ((pllState.ds_x3<<4) + (pllState.ds_x3<<1)) >> 13;
|
||||||
|
if (ds_out > 8)
|
||||||
|
ds_out = 8;
|
||||||
|
if (ds_out < 0)
|
||||||
|
ds_out = 0;
|
||||||
|
pllState.ds_x3 += (pllState.ds_x2>>5) - (ds_out<<9) - (ds_out<<8);
|
||||||
|
pllState.ds_x2 += (pllState.ds_x1>>5) - (ds_out<<14);
|
||||||
|
pllState.ds_x1 += pllState.ds_in - (ds_out<<17);
|
||||||
|
|
||||||
|
if (ds_out == 0)
|
||||||
|
frac_val = 0x00000007; // 0/8
|
||||||
|
else
|
||||||
|
frac_val = ((ds_out - 1) << 8) | 0x80000007; // 1/8 to 8/8
|
||||||
|
|
||||||
|
// Now write the register.
|
||||||
|
// We need to write the register at a specific period at a fast rate.
|
||||||
|
// This period needs to be (div ref clk period (ns) * how many times we repeat same value)
|
||||||
|
// In this case, div ref clk = 24/3 = 8MHz. So div ref clk period = 125ns.
|
||||||
|
// We're using fraction denominators of 8, so these repeat every 8*125ns = 1us.
|
||||||
|
// So minimum period we could use is 1us and multiples thereof.
|
||||||
|
// The slower we write, the higher our jitter will be.
|
||||||
|
|
||||||
|
time += FRAC_REG_WRITE_DLY; // Time the reg write.
|
||||||
|
tmr when timerafter(time) :> void;
|
||||||
|
|
||||||
|
// Write the register. Because we are timing the reg writes accurately we do not need to use reg write with ack.
|
||||||
|
// This saves a lot of time. Additionally, apparently we can shorten the time for this reg write by only setting up the channel once and just doing a few instructions to do the write each time.
|
||||||
|
// We can hard code this in assembler.
|
||||||
|
if(running)
|
||||||
|
{
|
||||||
|
write_node_config_reg_no_ack(tile, XS1_SSWITCH_SS_APP_PLL_FRAC_N_DIVIDER_NUM, frac_val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2011-2022 XMOS LIMITED.
|
// Copyright 2011-2023 XMOS LIMITED.
|
||||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||||
|
|
||||||
#include <xs1.h>
|
#include <xs1.h>
|
||||||
@@ -13,14 +13,14 @@
|
|||||||
#include "spdif.h"
|
#include "spdif.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define LOCAL_CLOCK_INCREMENT 166667
|
#define LOCAL_CLOCK_INCREMENT (166667)
|
||||||
#define LOCAL_CLOCK_MARGIN 1666
|
#define LOCAL_CLOCK_MARGIN (1666)
|
||||||
|
|
||||||
#define MAX_SAMPLES 64 /* Must be power of 2 */
|
#define MAX_SAMPLES (64) /* Must be power of 2 */
|
||||||
#define MAX_SPDIF_SAMPLES (2 * MAX_SAMPLES) /* Must be power of 2 */
|
#define MAX_SPDIF_SAMPLES (2 * MAX_SAMPLES) /* Must be power of 2 */
|
||||||
#define MAX_ADAT_SAMPLES (8 * MAX_SAMPLES) /* Must be power of 2 */
|
#define MAX_ADAT_SAMPLES (8 * MAX_SAMPLES) /* Must be power of 2 */
|
||||||
|
|
||||||
#define SPDIF_FRAME_ERRORS_THRESH 40
|
#define SPDIF_FRAME_ERRORS_THRESH (40)
|
||||||
|
|
||||||
unsigned g_digData[10];
|
unsigned g_digData[10];
|
||||||
|
|
||||||
@@ -241,12 +241,7 @@ extern int samples_to_host_inputs_buff[NUM_USB_CHAN_IN];
|
|||||||
int VendorAudCoreReqs(unsigned cmd, chanend c);
|
int VendorAudCoreReqs(unsigned cmd, chanend c);
|
||||||
|
|
||||||
#pragma unsafe arrays
|
#pragma unsafe arrays
|
||||||
//#if (AUDIO_IO_TILE == PLL_REF_TILE)
|
|
||||||
#if 0
|
|
||||||
void clockGen (streaming chanend ?c_spdif_rx, chanend ?c_adat_rx, out port p, chanend c_dig_rx, chanend c_clk_ctl, chanend c_clk_int)
|
|
||||||
#else
|
|
||||||
void clockGen (streaming chanend ?c_spdif_rx, chanend ?c_adat_rx, client interface pll_ref_if i_pll_ref, chanend c_dig_rx, chanend c_clk_ctl, chanend c_clk_int)
|
void clockGen (streaming chanend ?c_spdif_rx, chanend ?c_adat_rx, client interface pll_ref_if i_pll_ref, chanend c_dig_rx, chanend c_clk_ctl, chanend c_clk_int)
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
timer t_local;
|
timer t_local;
|
||||||
unsigned timeNextEdge, timeLastEdge, timeNextClockDetection;
|
unsigned timeNextEdge, timeLastEdge, timeNextClockDetection;
|
||||||
@@ -723,7 +718,7 @@ void clockGen (streaming chanend ?c_spdif_rx, chanend ?c_adat_rx, client interfa
|
|||||||
|
|
||||||
|
|
||||||
#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
|
#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
|
||||||
/* Mixer requests data */
|
/* AudioHub requests data */
|
||||||
case inuint_byref(c_dig_rx, tmp):
|
case inuint_byref(c_dig_rx, tmp):
|
||||||
#if (XUA_SPDIF_RX_EN)
|
#if (XUA_SPDIF_RX_EN)
|
||||||
if(spdifUnderflow)
|
if(spdifUnderflow)
|
||||||
|
|||||||
398
lib_xua/src/core/clocking/fractions_80_top.h
Normal file
398
lib_xua/src/core/clocking/fractions_80_top.h
Normal file
@@ -0,0 +1,398 @@
|
|||||||
|
// Copyright 2023 XMOS LIMITED.
|
||||||
|
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||||
|
|
||||||
|
// Header file listing fraction options searched
|
||||||
|
// These values to go in the bottom 16 bits of the secondary PLL fractional-n divider register.
|
||||||
|
short frac_values_80[391] = {
|
||||||
|
0x3C4B, // Index: 0 Fraction: 61/76 = 0.8026
|
||||||
|
0x3846, // Index: 1 Fraction: 57/71 = 0.8028
|
||||||
|
0x3441, // Index: 2 Fraction: 53/66 = 0.8030
|
||||||
|
0x303C, // Index: 3 Fraction: 49/61 = 0.8033
|
||||||
|
0x2C37, // Index: 4 Fraction: 45/56 = 0.8036
|
||||||
|
0x2832, // Index: 5 Fraction: 41/51 = 0.8039
|
||||||
|
0x242D, // Index: 6 Fraction: 37/46 = 0.8043
|
||||||
|
0x2028, // Index: 7 Fraction: 33/41 = 0.8049
|
||||||
|
0x3D4C, // Index: 8 Fraction: 62/77 = 0.8052
|
||||||
|
0x1C23, // Index: 9 Fraction: 29/36 = 0.8056
|
||||||
|
0x3542, // Index: 10 Fraction: 54/67 = 0.8060
|
||||||
|
0x181E, // Index: 11 Fraction: 25/31 = 0.8065
|
||||||
|
0x2D38, // Index: 12 Fraction: 46/57 = 0.8070
|
||||||
|
0x1419, // Index: 13 Fraction: 21/26 = 0.8077
|
||||||
|
0x3A48, // Index: 14 Fraction: 59/73 = 0.8082
|
||||||
|
0x252E, // Index: 15 Fraction: 38/47 = 0.8085
|
||||||
|
0x3643, // Index: 16 Fraction: 55/68 = 0.8088
|
||||||
|
0x1014, // Index: 17 Fraction: 17/21 = 0.8095
|
||||||
|
0x3F4E, // Index: 18 Fraction: 64/79 = 0.8101
|
||||||
|
0x2E39, // Index: 19 Fraction: 47/58 = 0.8103
|
||||||
|
0x1D24, // Index: 20 Fraction: 30/37 = 0.8108
|
||||||
|
0x2A34, // Index: 21 Fraction: 43/53 = 0.8113
|
||||||
|
0x3744, // Index: 22 Fraction: 56/69 = 0.8116
|
||||||
|
0x0C0F, // Index: 23 Fraction: 13/16 = 0.8125
|
||||||
|
0x3C4A, // Index: 24 Fraction: 61/75 = 0.8133
|
||||||
|
0x2F3A, // Index: 25 Fraction: 48/59 = 0.8136
|
||||||
|
0x222A, // Index: 26 Fraction: 35/43 = 0.8140
|
||||||
|
0x3845, // Index: 27 Fraction: 57/70 = 0.8143
|
||||||
|
0x151A, // Index: 28 Fraction: 22/27 = 0.8148
|
||||||
|
0x3440, // Index: 29 Fraction: 53/65 = 0.8154
|
||||||
|
0x1E25, // Index: 30 Fraction: 31/38 = 0.8158
|
||||||
|
0x2730, // Index: 31 Fraction: 40/49 = 0.8163
|
||||||
|
0x303B, // Index: 32 Fraction: 49/60 = 0.8167
|
||||||
|
0x3946, // Index: 33 Fraction: 58/71 = 0.8169
|
||||||
|
0x080A, // Index: 34 Fraction: 9/11 = 0.8182
|
||||||
|
0x3A47, // Index: 35 Fraction: 59/72 = 0.8194
|
||||||
|
0x313C, // Index: 36 Fraction: 50/61 = 0.8197
|
||||||
|
0x2831, // Index: 37 Fraction: 41/50 = 0.8200
|
||||||
|
0x1F26, // Index: 38 Fraction: 32/39 = 0.8205
|
||||||
|
0x3642, // Index: 39 Fraction: 55/67 = 0.8209
|
||||||
|
0x161B, // Index: 40 Fraction: 23/28 = 0.8214
|
||||||
|
0x3B48, // Index: 41 Fraction: 60/73 = 0.8219
|
||||||
|
0x242C, // Index: 42 Fraction: 37/45 = 0.8222
|
||||||
|
0x323D, // Index: 43 Fraction: 51/62 = 0.8226
|
||||||
|
0x404E, // Index: 44 Fraction: 65/79 = 0.8228
|
||||||
|
0x0D10, // Index: 45 Fraction: 14/17 = 0.8235
|
||||||
|
0x3C49, // Index: 46 Fraction: 61/74 = 0.8243
|
||||||
|
0x2E38, // Index: 47 Fraction: 47/57 = 0.8246
|
||||||
|
0x2027, // Index: 48 Fraction: 33/40 = 0.8250
|
||||||
|
0x333E, // Index: 49 Fraction: 52/63 = 0.8254
|
||||||
|
0x1216, // Index: 50 Fraction: 19/23 = 0.8261
|
||||||
|
0x3D4A, // Index: 51 Fraction: 62/75 = 0.8267
|
||||||
|
0x2A33, // Index: 52 Fraction: 43/52 = 0.8269
|
||||||
|
0x171C, // Index: 53 Fraction: 24/29 = 0.8276
|
||||||
|
0x343F, // Index: 54 Fraction: 53/64 = 0.8281
|
||||||
|
0x1C22, // Index: 55 Fraction: 29/35 = 0.8286
|
||||||
|
0x3E4B, // Index: 56 Fraction: 63/76 = 0.8289
|
||||||
|
0x2128, // Index: 57 Fraction: 34/41 = 0.8293
|
||||||
|
0x262E, // Index: 58 Fraction: 39/47 = 0.8298
|
||||||
|
0x2B34, // Index: 59 Fraction: 44/53 = 0.8302
|
||||||
|
0x303A, // Index: 60 Fraction: 49/59 = 0.8305
|
||||||
|
0x3540, // Index: 61 Fraction: 54/65 = 0.8308
|
||||||
|
0x3A46, // Index: 62 Fraction: 59/71 = 0.8310
|
||||||
|
0x3F4C, // Index: 63 Fraction: 64/77 = 0.8312
|
||||||
|
0x0405, // Index: 64 Fraction: 5/6 = 0.8333
|
||||||
|
0x414E, // Index: 65 Fraction: 66/79 = 0.8354
|
||||||
|
0x3C48, // Index: 66 Fraction: 61/73 = 0.8356
|
||||||
|
0x3742, // Index: 67 Fraction: 56/67 = 0.8358
|
||||||
|
0x323C, // Index: 68 Fraction: 51/61 = 0.8361
|
||||||
|
0x2D36, // Index: 69 Fraction: 46/55 = 0.8364
|
||||||
|
0x2830, // Index: 70 Fraction: 41/49 = 0.8367
|
||||||
|
0x232A, // Index: 71 Fraction: 36/43 = 0.8372
|
||||||
|
0x424F, // Index: 72 Fraction: 67/80 = 0.8375
|
||||||
|
0x1E24, // Index: 73 Fraction: 31/37 = 0.8378
|
||||||
|
0x3843, // Index: 74 Fraction: 57/68 = 0.8382
|
||||||
|
0x191E, // Index: 75 Fraction: 26/31 = 0.8387
|
||||||
|
0x2E37, // Index: 76 Fraction: 47/56 = 0.8393
|
||||||
|
0x1418, // Index: 77 Fraction: 21/25 = 0.8400
|
||||||
|
0x3944, // Index: 78 Fraction: 58/69 = 0.8406
|
||||||
|
0x242B, // Index: 79 Fraction: 37/44 = 0.8409
|
||||||
|
0x343E, // Index: 80 Fraction: 53/63 = 0.8413
|
||||||
|
0x0F12, // Index: 81 Fraction: 16/19 = 0.8421
|
||||||
|
0x3A45, // Index: 82 Fraction: 59/70 = 0.8429
|
||||||
|
0x2A32, // Index: 83 Fraction: 43/51 = 0.8431
|
||||||
|
0x1A1F, // Index: 84 Fraction: 27/32 = 0.8438
|
||||||
|
0x404C, // Index: 85 Fraction: 65/77 = 0.8442
|
||||||
|
0x252C, // Index: 86 Fraction: 38/45 = 0.8444
|
||||||
|
0x3039, // Index: 87 Fraction: 49/58 = 0.8448
|
||||||
|
0x3B46, // Index: 88 Fraction: 60/71 = 0.8451
|
||||||
|
0x0A0C, // Index: 89 Fraction: 11/13 = 0.8462
|
||||||
|
0x3C47, // Index: 90 Fraction: 61/72 = 0.8472
|
||||||
|
0x313A, // Index: 91 Fraction: 50/59 = 0.8475
|
||||||
|
0x262D, // Index: 92 Fraction: 39/46 = 0.8478
|
||||||
|
0x424E, // Index: 93 Fraction: 67/79 = 0.8481
|
||||||
|
0x1B20, // Index: 94 Fraction: 28/33 = 0.8485
|
||||||
|
0x2C34, // Index: 95 Fraction: 45/53 = 0.8491
|
||||||
|
0x3D48, // Index: 96 Fraction: 62/73 = 0.8493
|
||||||
|
0x1013, // Index: 97 Fraction: 17/20 = 0.8500
|
||||||
|
0x3842, // Index: 98 Fraction: 57/67 = 0.8507
|
||||||
|
0x272E, // Index: 99 Fraction: 40/47 = 0.8511
|
||||||
|
0x3E49, // Index: 100 Fraction: 63/74 = 0.8514
|
||||||
|
0x161A, // Index: 101 Fraction: 23/27 = 0.8519
|
||||||
|
0x333C, // Index: 102 Fraction: 52/61 = 0.8525
|
||||||
|
0x1C21, // Index: 103 Fraction: 29/34 = 0.8529
|
||||||
|
0x3F4A, // Index: 104 Fraction: 64/75 = 0.8533
|
||||||
|
0x2228, // Index: 105 Fraction: 35/41 = 0.8537
|
||||||
|
0x282F, // Index: 106 Fraction: 41/48 = 0.8542
|
||||||
|
0x2E36, // Index: 107 Fraction: 47/55 = 0.8545
|
||||||
|
0x343D, // Index: 108 Fraction: 53/62 = 0.8548
|
||||||
|
0x3A44, // Index: 109 Fraction: 59/69 = 0.8551
|
||||||
|
0x404B, // Index: 110 Fraction: 65/76 = 0.8553
|
||||||
|
0x0506, // Index: 111 Fraction: 6/7 = 0.8571
|
||||||
|
0x424D, // Index: 112 Fraction: 67/78 = 0.8590
|
||||||
|
0x3C46, // Index: 113 Fraction: 61/71 = 0.8592
|
||||||
|
0x363F, // Index: 114 Fraction: 55/64 = 0.8594
|
||||||
|
0x3038, // Index: 115 Fraction: 49/57 = 0.8596
|
||||||
|
0x2A31, // Index: 116 Fraction: 43/50 = 0.8600
|
||||||
|
0x242A, // Index: 117 Fraction: 37/43 = 0.8605
|
||||||
|
0x434E, // Index: 118 Fraction: 68/79 = 0.8608
|
||||||
|
0x1E23, // Index: 119 Fraction: 31/36 = 0.8611
|
||||||
|
0x3740, // Index: 120 Fraction: 56/65 = 0.8615
|
||||||
|
0x181C, // Index: 121 Fraction: 25/29 = 0.8621
|
||||||
|
0x444F, // Index: 122 Fraction: 69/80 = 0.8625
|
||||||
|
0x2B32, // Index: 123 Fraction: 44/51 = 0.8627
|
||||||
|
0x3E48, // Index: 124 Fraction: 63/73 = 0.8630
|
||||||
|
0x1215, // Index: 125 Fraction: 19/22 = 0.8636
|
||||||
|
0x323A, // Index: 126 Fraction: 51/59 = 0.8644
|
||||||
|
0x1F24, // Index: 127 Fraction: 32/37 = 0.8649
|
||||||
|
0x2C33, // Index: 128 Fraction: 45/52 = 0.8654
|
||||||
|
0x3942, // Index: 129 Fraction: 58/67 = 0.8657
|
||||||
|
0x0C0E, // Index: 130 Fraction: 13/15 = 0.8667
|
||||||
|
0x3A43, // Index: 131 Fraction: 59/68 = 0.8676
|
||||||
|
0x2D34, // Index: 132 Fraction: 46/53 = 0.8679
|
||||||
|
0x2025, // Index: 133 Fraction: 33/38 = 0.8684
|
||||||
|
0x343C, // Index: 134 Fraction: 53/61 = 0.8689
|
||||||
|
0x1316, // Index: 135 Fraction: 20/23 = 0.8696
|
||||||
|
0x424C, // Index: 136 Fraction: 67/77 = 0.8701
|
||||||
|
0x2E35, // Index: 137 Fraction: 47/54 = 0.8704
|
||||||
|
0x1A1E, // Index: 138 Fraction: 27/31 = 0.8710
|
||||||
|
0x3C45, // Index: 139 Fraction: 61/70 = 0.8714
|
||||||
|
0x2126, // Index: 140 Fraction: 34/39 = 0.8718
|
||||||
|
0x282E, // Index: 141 Fraction: 41/47 = 0.8723
|
||||||
|
0x2F36, // Index: 142 Fraction: 48/55 = 0.8727
|
||||||
|
0x363E, // Index: 143 Fraction: 55/63 = 0.8730
|
||||||
|
0x3D46, // Index: 144 Fraction: 62/71 = 0.8732
|
||||||
|
0x444E, // Index: 145 Fraction: 69/79 = 0.8734
|
||||||
|
0x0607, // Index: 146 Fraction: 7/8 = 0.8750
|
||||||
|
0x3F48, // Index: 147 Fraction: 64/73 = 0.8767
|
||||||
|
0x3840, // Index: 148 Fraction: 57/65 = 0.8769
|
||||||
|
0x3138, // Index: 149 Fraction: 50/57 = 0.8772
|
||||||
|
0x2A30, // Index: 150 Fraction: 43/49 = 0.8776
|
||||||
|
0x2328, // Index: 151 Fraction: 36/41 = 0.8780
|
||||||
|
0x4049, // Index: 152 Fraction: 65/74 = 0.8784
|
||||||
|
0x1C20, // Index: 153 Fraction: 29/33 = 0.8788
|
||||||
|
0x3239, // Index: 154 Fraction: 51/58 = 0.8793
|
||||||
|
0x1518, // Index: 155 Fraction: 22/25 = 0.8800
|
||||||
|
0x3A42, // Index: 156 Fraction: 59/67 = 0.8806
|
||||||
|
0x2429, // Index: 157 Fraction: 37/42 = 0.8810
|
||||||
|
0x333A, // Index: 158 Fraction: 52/59 = 0.8814
|
||||||
|
0x424B, // Index: 159 Fraction: 67/76 = 0.8816
|
||||||
|
0x0E10, // Index: 160 Fraction: 15/17 = 0.8824
|
||||||
|
0x434C, // Index: 161 Fraction: 68/77 = 0.8831
|
||||||
|
0x343B, // Index: 162 Fraction: 53/60 = 0.8833
|
||||||
|
0x252A, // Index: 163 Fraction: 38/43 = 0.8837
|
||||||
|
0x3C44, // Index: 164 Fraction: 61/69 = 0.8841
|
||||||
|
0x1619, // Index: 165 Fraction: 23/26 = 0.8846
|
||||||
|
0x353C, // Index: 166 Fraction: 54/61 = 0.8852
|
||||||
|
0x1E22, // Index: 167 Fraction: 31/35 = 0.8857
|
||||||
|
0x454E, // Index: 168 Fraction: 70/79 = 0.8861
|
||||||
|
0x262B, // Index: 169 Fraction: 39/44 = 0.8864
|
||||||
|
0x2E34, // Index: 170 Fraction: 47/53 = 0.8868
|
||||||
|
0x363D, // Index: 171 Fraction: 55/62 = 0.8871
|
||||||
|
0x3E46, // Index: 172 Fraction: 63/71 = 0.8873
|
||||||
|
0x464F, // Index: 173 Fraction: 71/80 = 0.8875
|
||||||
|
0x0708, // Index: 174 Fraction: 8/9 = 0.8889
|
||||||
|
0x4048, // Index: 175 Fraction: 65/73 = 0.8904
|
||||||
|
0x383F, // Index: 176 Fraction: 57/64 = 0.8906
|
||||||
|
0x3036, // Index: 177 Fraction: 49/55 = 0.8909
|
||||||
|
0x282D, // Index: 178 Fraction: 41/46 = 0.8913
|
||||||
|
0x2024, // Index: 179 Fraction: 33/37 = 0.8919
|
||||||
|
0x3940, // Index: 180 Fraction: 58/65 = 0.8923
|
||||||
|
0x181B, // Index: 181 Fraction: 25/28 = 0.8929
|
||||||
|
0x424A, // Index: 182 Fraction: 67/75 = 0.8933
|
||||||
|
0x292E, // Index: 183 Fraction: 42/47 = 0.8936
|
||||||
|
0x3A41, // Index: 184 Fraction: 59/66 = 0.8939
|
||||||
|
0x1012, // Index: 185 Fraction: 17/19 = 0.8947
|
||||||
|
0x3B42, // Index: 186 Fraction: 60/67 = 0.8955
|
||||||
|
0x2A2F, // Index: 187 Fraction: 43/48 = 0.8958
|
||||||
|
0x444C, // Index: 188 Fraction: 69/77 = 0.8961
|
||||||
|
0x191C, // Index: 189 Fraction: 26/29 = 0.8966
|
||||||
|
0x3C43, // Index: 190 Fraction: 61/68 = 0.8971
|
||||||
|
0x2226, // Index: 191 Fraction: 35/39 = 0.8974
|
||||||
|
0x2B30, // Index: 192 Fraction: 44/49 = 0.8980
|
||||||
|
0x343A, // Index: 193 Fraction: 53/59 = 0.8983
|
||||||
|
0x3D44, // Index: 194 Fraction: 62/69 = 0.8986
|
||||||
|
0x464E, // Index: 195 Fraction: 71/79 = 0.8987
|
||||||
|
0x0809, // Index: 196 Fraction: 9/10 = 0.9000
|
||||||
|
0x3F46, // Index: 197 Fraction: 64/71 = 0.9014
|
||||||
|
0x363C, // Index: 198 Fraction: 55/61 = 0.9016
|
||||||
|
0x2D32, // Index: 199 Fraction: 46/51 = 0.9020
|
||||||
|
0x2428, // Index: 200 Fraction: 37/41 = 0.9024
|
||||||
|
0x4047, // Index: 201 Fraction: 65/72 = 0.9028
|
||||||
|
0x1B1E, // Index: 202 Fraction: 28/31 = 0.9032
|
||||||
|
0x2E33, // Index: 203 Fraction: 47/52 = 0.9038
|
||||||
|
0x4148, // Index: 204 Fraction: 66/73 = 0.9041
|
||||||
|
0x1214, // Index: 205 Fraction: 19/21 = 0.9048
|
||||||
|
0x4249, // Index: 206 Fraction: 67/74 = 0.9054
|
||||||
|
0x2F34, // Index: 207 Fraction: 48/53 = 0.9057
|
||||||
|
0x1C1F, // Index: 208 Fraction: 29/32 = 0.9062
|
||||||
|
0x434A, // Index: 209 Fraction: 68/75 = 0.9067
|
||||||
|
0x262A, // Index: 210 Fraction: 39/43 = 0.9070
|
||||||
|
0x3035, // Index: 211 Fraction: 49/54 = 0.9074
|
||||||
|
0x3A40, // Index: 212 Fraction: 59/65 = 0.9077
|
||||||
|
0x444B, // Index: 213 Fraction: 69/76 = 0.9079
|
||||||
|
0x090A, // Index: 214 Fraction: 10/11 = 0.9091
|
||||||
|
0x464D, // Index: 215 Fraction: 71/78 = 0.9103
|
||||||
|
0x3C42, // Index: 216 Fraction: 61/67 = 0.9104
|
||||||
|
0x3237, // Index: 217 Fraction: 51/56 = 0.9107
|
||||||
|
0x282C, // Index: 218 Fraction: 41/45 = 0.9111
|
||||||
|
0x474E, // Index: 219 Fraction: 72/79 = 0.9114
|
||||||
|
0x1E21, // Index: 220 Fraction: 31/34 = 0.9118
|
||||||
|
0x3338, // Index: 221 Fraction: 52/57 = 0.9123
|
||||||
|
0x484F, // Index: 222 Fraction: 73/80 = 0.9125
|
||||||
|
0x1416, // Index: 223 Fraction: 21/23 = 0.9130
|
||||||
|
0x3439, // Index: 224 Fraction: 53/58 = 0.9138
|
||||||
|
0x1F22, // Index: 225 Fraction: 32/35 = 0.9143
|
||||||
|
0x2A2E, // Index: 226 Fraction: 43/47 = 0.9149
|
||||||
|
0x353A, // Index: 227 Fraction: 54/59 = 0.9153
|
||||||
|
0x4046, // Index: 228 Fraction: 65/71 = 0.9155
|
||||||
|
0x0A0B, // Index: 229 Fraction: 11/12 = 0.9167
|
||||||
|
0x4248, // Index: 230 Fraction: 67/73 = 0.9178
|
||||||
|
0x373C, // Index: 231 Fraction: 56/61 = 0.9180
|
||||||
|
0x2C30, // Index: 232 Fraction: 45/49 = 0.9184
|
||||||
|
0x2124, // Index: 233 Fraction: 34/37 = 0.9189
|
||||||
|
0x383D, // Index: 234 Fraction: 57/62 = 0.9194
|
||||||
|
0x1618, // Index: 235 Fraction: 23/25 = 0.9200
|
||||||
|
0x393E, // Index: 236 Fraction: 58/63 = 0.9206
|
||||||
|
0x2225, // Index: 237 Fraction: 35/38 = 0.9211
|
||||||
|
0x2E32, // Index: 238 Fraction: 47/51 = 0.9216
|
||||||
|
0x3A3F, // Index: 239 Fraction: 59/64 = 0.9219
|
||||||
|
0x464C, // Index: 240 Fraction: 71/77 = 0.9221
|
||||||
|
0x0B0C, // Index: 241 Fraction: 12/13 = 0.9231
|
||||||
|
0x484E, // Index: 242 Fraction: 73/79 = 0.9241
|
||||||
|
0x3C41, // Index: 243 Fraction: 61/66 = 0.9242
|
||||||
|
0x3034, // Index: 244 Fraction: 49/53 = 0.9245
|
||||||
|
0x2427, // Index: 245 Fraction: 37/40 = 0.9250
|
||||||
|
0x3D42, // Index: 246 Fraction: 62/67 = 0.9254
|
||||||
|
0x181A, // Index: 247 Fraction: 25/27 = 0.9259
|
||||||
|
0x3E43, // Index: 248 Fraction: 63/68 = 0.9265
|
||||||
|
0x2528, // Index: 249 Fraction: 38/41 = 0.9268
|
||||||
|
0x3236, // Index: 250 Fraction: 51/55 = 0.9273
|
||||||
|
0x3F44, // Index: 251 Fraction: 64/69 = 0.9275
|
||||||
|
0x0C0D, // Index: 252 Fraction: 13/14 = 0.9286
|
||||||
|
0x4146, // Index: 253 Fraction: 66/71 = 0.9296
|
||||||
|
0x3438, // Index: 254 Fraction: 53/57 = 0.9298
|
||||||
|
0x272A, // Index: 255 Fraction: 40/43 = 0.9302
|
||||||
|
0x4247, // Index: 256 Fraction: 67/72 = 0.9306
|
||||||
|
0x1A1C, // Index: 257 Fraction: 27/29 = 0.9310
|
||||||
|
0x4348, // Index: 258 Fraction: 68/73 = 0.9315
|
||||||
|
0x282B, // Index: 259 Fraction: 41/44 = 0.9318
|
||||||
|
0x363A, // Index: 260 Fraction: 55/59 = 0.9322
|
||||||
|
0x4449, // Index: 261 Fraction: 69/74 = 0.9324
|
||||||
|
0x0D0E, // Index: 262 Fraction: 14/15 = 0.9333
|
||||||
|
0x464B, // Index: 263 Fraction: 71/76 = 0.9342
|
||||||
|
0x383C, // Index: 264 Fraction: 57/61 = 0.9344
|
||||||
|
0x2A2D, // Index: 265 Fraction: 43/46 = 0.9348
|
||||||
|
0x474C, // Index: 266 Fraction: 72/77 = 0.9351
|
||||||
|
0x1C1E, // Index: 267 Fraction: 29/31 = 0.9355
|
||||||
|
0x484D, // Index: 268 Fraction: 73/78 = 0.9359
|
||||||
|
0x2B2E, // Index: 269 Fraction: 44/47 = 0.9362
|
||||||
|
0x3A3E, // Index: 270 Fraction: 59/63 = 0.9365
|
||||||
|
0x494E, // Index: 271 Fraction: 74/79 = 0.9367
|
||||||
|
0x0E0F, // Index: 272 Fraction: 15/16 = 0.9375
|
||||||
|
0x3C40, // Index: 273 Fraction: 61/65 = 0.9385
|
||||||
|
0x2D30, // Index: 274 Fraction: 46/49 = 0.9388
|
||||||
|
0x1E20, // Index: 275 Fraction: 31/33 = 0.9394
|
||||||
|
0x2E31, // Index: 276 Fraction: 47/50 = 0.9400
|
||||||
|
0x3E42, // Index: 277 Fraction: 63/67 = 0.9403
|
||||||
|
0x0F10, // Index: 278 Fraction: 16/17 = 0.9412
|
||||||
|
0x4044, // Index: 279 Fraction: 65/69 = 0.9420
|
||||||
|
0x3033, // Index: 280 Fraction: 49/52 = 0.9423
|
||||||
|
0x2022, // Index: 281 Fraction: 33/35 = 0.9429
|
||||||
|
0x3134, // Index: 282 Fraction: 50/53 = 0.9434
|
||||||
|
0x4246, // Index: 283 Fraction: 67/71 = 0.9437
|
||||||
|
0x1011, // Index: 284 Fraction: 17/18 = 0.9444
|
||||||
|
0x4448, // Index: 285 Fraction: 69/73 = 0.9452
|
||||||
|
0x3336, // Index: 286 Fraction: 52/55 = 0.9455
|
||||||
|
0x2224, // Index: 287 Fraction: 35/37 = 0.9459
|
||||||
|
0x3437, // Index: 288 Fraction: 53/56 = 0.9464
|
||||||
|
0x464A, // Index: 289 Fraction: 71/75 = 0.9467
|
||||||
|
0x1112, // Index: 290 Fraction: 18/19 = 0.9474
|
||||||
|
0x484C, // Index: 291 Fraction: 73/77 = 0.9481
|
||||||
|
0x3639, // Index: 292 Fraction: 55/58 = 0.9483
|
||||||
|
0x2426, // Index: 293 Fraction: 37/39 = 0.9487
|
||||||
|
0x373A, // Index: 294 Fraction: 56/59 = 0.9492
|
||||||
|
0x4A4E, // Index: 295 Fraction: 75/79 = 0.9494
|
||||||
|
0x1213, // Index: 296 Fraction: 19/20 = 0.9500
|
||||||
|
0x393C, // Index: 297 Fraction: 58/61 = 0.9508
|
||||||
|
0x2628, // Index: 298 Fraction: 39/41 = 0.9512
|
||||||
|
0x3A3D, // Index: 299 Fraction: 59/62 = 0.9516
|
||||||
|
0x1314, // Index: 300 Fraction: 20/21 = 0.9524
|
||||||
|
0x3C3F, // Index: 301 Fraction: 61/64 = 0.9531
|
||||||
|
0x282A, // Index: 302 Fraction: 41/43 = 0.9535
|
||||||
|
0x3D40, // Index: 303 Fraction: 62/65 = 0.9538
|
||||||
|
0x1415, // Index: 304 Fraction: 21/22 = 0.9545
|
||||||
|
0x3F42, // Index: 305 Fraction: 64/67 = 0.9552
|
||||||
|
0x2A2C, // Index: 306 Fraction: 43/45 = 0.9556
|
||||||
|
0x4043, // Index: 307 Fraction: 65/68 = 0.9559
|
||||||
|
0x1516, // Index: 308 Fraction: 22/23 = 0.9565
|
||||||
|
0x4245, // Index: 309 Fraction: 67/70 = 0.9571
|
||||||
|
0x2C2E, // Index: 310 Fraction: 45/47 = 0.9574
|
||||||
|
0x4346, // Index: 311 Fraction: 68/71 = 0.9577
|
||||||
|
0x1617, // Index: 312 Fraction: 23/24 = 0.9583
|
||||||
|
0x4548, // Index: 313 Fraction: 70/73 = 0.9589
|
||||||
|
0x2E30, // Index: 314 Fraction: 47/49 = 0.9592
|
||||||
|
0x4649, // Index: 315 Fraction: 71/74 = 0.9595
|
||||||
|
0x1718, // Index: 316 Fraction: 24/25 = 0.9600
|
||||||
|
0x484B, // Index: 317 Fraction: 73/76 = 0.9605
|
||||||
|
0x3032, // Index: 318 Fraction: 49/51 = 0.9608
|
||||||
|
0x494C, // Index: 319 Fraction: 74/77 = 0.9610
|
||||||
|
0x1819, // Index: 320 Fraction: 25/26 = 0.9615
|
||||||
|
0x4B4E, // Index: 321 Fraction: 76/79 = 0.9620
|
||||||
|
0x3234, // Index: 322 Fraction: 51/53 = 0.9623
|
||||||
|
0x4C4F, // Index: 323 Fraction: 77/80 = 0.9625
|
||||||
|
0x191A, // Index: 324 Fraction: 26/27 = 0.9630
|
||||||
|
0x3436, // Index: 325 Fraction: 53/55 = 0.9636
|
||||||
|
0x1A1B, // Index: 326 Fraction: 27/28 = 0.9643
|
||||||
|
0x3638, // Index: 327 Fraction: 55/57 = 0.9649
|
||||||
|
0x1B1C, // Index: 328 Fraction: 28/29 = 0.9655
|
||||||
|
0x383A, // Index: 329 Fraction: 57/59 = 0.9661
|
||||||
|
0x1C1D, // Index: 330 Fraction: 29/30 = 0.9667
|
||||||
|
0x3A3C, // Index: 331 Fraction: 59/61 = 0.9672
|
||||||
|
0x1D1E, // Index: 332 Fraction: 30/31 = 0.9677
|
||||||
|
0x3C3E, // Index: 333 Fraction: 61/63 = 0.9683
|
||||||
|
0x1E1F, // Index: 334 Fraction: 31/32 = 0.9688
|
||||||
|
0x3E40, // Index: 335 Fraction: 63/65 = 0.9692
|
||||||
|
0x1F20, // Index: 336 Fraction: 32/33 = 0.9697
|
||||||
|
0x4042, // Index: 337 Fraction: 65/67 = 0.9701
|
||||||
|
0x2021, // Index: 338 Fraction: 33/34 = 0.9706
|
||||||
|
0x4244, // Index: 339 Fraction: 67/69 = 0.9710
|
||||||
|
0x2122, // Index: 340 Fraction: 34/35 = 0.9714
|
||||||
|
0x4446, // Index: 341 Fraction: 69/71 = 0.9718
|
||||||
|
0x2223, // Index: 342 Fraction: 35/36 = 0.9722
|
||||||
|
0x4648, // Index: 343 Fraction: 71/73 = 0.9726
|
||||||
|
0x2324, // Index: 344 Fraction: 36/37 = 0.9730
|
||||||
|
0x484A, // Index: 345 Fraction: 73/75 = 0.9733
|
||||||
|
0x2425, // Index: 346 Fraction: 37/38 = 0.9737
|
||||||
|
0x4A4C, // Index: 347 Fraction: 75/77 = 0.9740
|
||||||
|
0x2526, // Index: 348 Fraction: 38/39 = 0.9744
|
||||||
|
0x4C4E, // Index: 349 Fraction: 77/79 = 0.9747
|
||||||
|
0x2627, // Index: 350 Fraction: 39/40 = 0.9750
|
||||||
|
0x2728, // Index: 351 Fraction: 40/41 = 0.9756
|
||||||
|
0x2829, // Index: 352 Fraction: 41/42 = 0.9762
|
||||||
|
0x292A, // Index: 353 Fraction: 42/43 = 0.9767
|
||||||
|
0x2A2B, // Index: 354 Fraction: 43/44 = 0.9773
|
||||||
|
0x2B2C, // Index: 355 Fraction: 44/45 = 0.9778
|
||||||
|
0x2C2D, // Index: 356 Fraction: 45/46 = 0.9783
|
||||||
|
0x2D2E, // Index: 357 Fraction: 46/47 = 0.9787
|
||||||
|
0x2E2F, // Index: 358 Fraction: 47/48 = 0.9792
|
||||||
|
0x2F30, // Index: 359 Fraction: 48/49 = 0.9796
|
||||||
|
0x3031, // Index: 360 Fraction: 49/50 = 0.9800
|
||||||
|
0x3132, // Index: 361 Fraction: 50/51 = 0.9804
|
||||||
|
0x3233, // Index: 362 Fraction: 51/52 = 0.9808
|
||||||
|
0x3334, // Index: 363 Fraction: 52/53 = 0.9811
|
||||||
|
0x3435, // Index: 364 Fraction: 53/54 = 0.9815
|
||||||
|
0x3536, // Index: 365 Fraction: 54/55 = 0.9818
|
||||||
|
0x3637, // Index: 366 Fraction: 55/56 = 0.9821
|
||||||
|
0x3738, // Index: 367 Fraction: 56/57 = 0.9825
|
||||||
|
0x3839, // Index: 368 Fraction: 57/58 = 0.9828
|
||||||
|
0x393A, // Index: 369 Fraction: 58/59 = 0.9831
|
||||||
|
0x3A3B, // Index: 370 Fraction: 59/60 = 0.9833
|
||||||
|
0x3B3C, // Index: 371 Fraction: 60/61 = 0.9836
|
||||||
|
0x3C3D, // Index: 372 Fraction: 61/62 = 0.9839
|
||||||
|
0x3D3E, // Index: 373 Fraction: 62/63 = 0.9841
|
||||||
|
0x3E3F, // Index: 374 Fraction: 63/64 = 0.9844
|
||||||
|
0x3F40, // Index: 375 Fraction: 64/65 = 0.9846
|
||||||
|
0x4041, // Index: 376 Fraction: 65/66 = 0.9848
|
||||||
|
0x4142, // Index: 377 Fraction: 66/67 = 0.9851
|
||||||
|
0x4243, // Index: 378 Fraction: 67/68 = 0.9853
|
||||||
|
0x4344, // Index: 379 Fraction: 68/69 = 0.9855
|
||||||
|
0x4445, // Index: 380 Fraction: 69/70 = 0.9857
|
||||||
|
0x4546, // Index: 381 Fraction: 70/71 = 0.9859
|
||||||
|
0x4647, // Index: 382 Fraction: 71/72 = 0.9861
|
||||||
|
0x4748, // Index: 383 Fraction: 72/73 = 0.9863
|
||||||
|
0x4849, // Index: 384 Fraction: 73/74 = 0.9865
|
||||||
|
0x494A, // Index: 385 Fraction: 74/75 = 0.9867
|
||||||
|
0x4A4B, // Index: 386 Fraction: 75/76 = 0.9868
|
||||||
|
0x4B4C, // Index: 387 Fraction: 76/77 = 0.9870
|
||||||
|
0x4C4D, // Index: 388 Fraction: 77/78 = 0.9872
|
||||||
|
0x4D4E, // Index: 389 Fraction: 78/79 = 0.9873
|
||||||
|
0x4E4F, // Index: 390 Fraction: 79/80 = 0.9875
|
||||||
|
};
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2015-2021 XMOS LIMITED.
|
// Copyright 2015-2023 XMOS LIMITED.
|
||||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||||
|
|
||||||
#ifndef __DESCRIPTOR_DEFS_H__
|
#ifndef __DESCRIPTOR_DEFS_H__
|
||||||
@@ -33,6 +33,7 @@
|
|||||||
#define ENDPOINT_ADDRESS_OUT_MIDI (ENDPOINT_NUMBER_OUT_MIDI)
|
#define ENDPOINT_ADDRESS_OUT_MIDI (ENDPOINT_NUMBER_OUT_MIDI)
|
||||||
#define ENDPOINT_ADDRESS_OUT_IAP (ENDPOINT_NUMBER_OUT_IAP)
|
#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_IAP_EA_NATIVE_TRANS (ENDPOINT_NUMBER_OUT_IAP_EA_NATIVE_TRANS)
|
||||||
|
#define ENDPOINT_ADDRESS_OUT_HID (ENDPOINT_NUMBER_OUT_HID)
|
||||||
|
|
||||||
/* Interface numbers enum */
|
/* Interface numbers enum */
|
||||||
enum USBInterfaceNumber
|
enum USBInterfaceNumber
|
||||||
@@ -60,7 +61,7 @@ enum USBInterfaceNumber
|
|||||||
INTERFACE_NUMBER_IAP_EA_NATIVE_TRANS,
|
INTERFACE_NUMBER_IAP_EA_NATIVE_TRANS,
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#if( 0 < HID_CONTROLS )
|
#if XUA_OR_STATIC_HID_ENABLED
|
||||||
INTERFACE_NUMBER_HID,
|
INTERFACE_NUMBER_HID,
|
||||||
#endif
|
#endif
|
||||||
INTERFACE_COUNT /* End marker */
|
INTERFACE_COUNT /* End marker */
|
||||||
@@ -70,4 +71,8 @@ enum USBInterfaceNumber
|
|||||||
#define ENDPOINT_INT_INTERVAL_IN_HID 0x08
|
#define ENDPOINT_INT_INTERVAL_IN_HID 0x08
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef ENDPOINT_INT_INTERVAL_OUT_HID
|
||||||
|
#define ENDPOINT_INT_INTERVAL_OUT_HID 0x08
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2011-2022 XMOS LIMITED.
|
// Copyright 2011-2023 XMOS LIMITED.
|
||||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||||
/**
|
/**
|
||||||
* @brief Implements endpoint zero for an USB Audio 1.0/2.0 device
|
* @brief Implements endpoint zero for an USB Audio 1.0/2.0 device
|
||||||
@@ -26,7 +26,7 @@
|
|||||||
#include "xc_ptr.h"
|
#include "xc_ptr.h"
|
||||||
#include "xua_ep0_uacreqs.h"
|
#include "xua_ep0_uacreqs.h"
|
||||||
|
|
||||||
#if( 0 < HID_CONTROLS )
|
#if XUA_OR_STATIC_HID_ENABLED
|
||||||
#include "hid.h"
|
#include "hid.h"
|
||||||
#include "xua_hid.h"
|
#include "xua_hid.h"
|
||||||
#include "xua_hid_report.h"
|
#include "xua_hid_report.h"
|
||||||
@@ -106,13 +106,17 @@ unsigned int mutesOut[NUM_USB_CHAN_OUT + 1];
|
|||||||
int volsIn[NUM_USB_CHAN_IN + 1];
|
int volsIn[NUM_USB_CHAN_IN + 1];
|
||||||
unsigned int mutesIn[NUM_USB_CHAN_IN + 1];
|
unsigned int mutesIn[NUM_USB_CHAN_IN + 1];
|
||||||
|
|
||||||
#ifdef MIXER
|
#if (MIXER)
|
||||||
unsigned char mixer1Crossbar[18];
|
short mixer1Weights[MIX_INPUTS * MAX_MIX_COUNT];
|
||||||
short mixer1Weights[18*8];
|
|
||||||
|
|
||||||
unsigned char channelMap[NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + MAX_MIX_COUNT];
|
//unsigned char channelMap[NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + MAX_MIX_COUNT];
|
||||||
|
/* Mapping of channels to output audio interfaces */
|
||||||
unsigned char channelMapAud[NUM_USB_CHAN_OUT];
|
unsigned char channelMapAud[NUM_USB_CHAN_OUT];
|
||||||
|
|
||||||
|
/* Mapping of channels to USB host */
|
||||||
unsigned char channelMapUsb[NUM_USB_CHAN_IN];
|
unsigned char channelMapUsb[NUM_USB_CHAN_IN];
|
||||||
|
|
||||||
|
/* Mapping of channels to Mixer(s) */
|
||||||
unsigned char mixSel[MAX_MIX_COUNT][MIX_INPUTS];
|
unsigned char mixSel[MAX_MIX_COUNT][MIX_INPUTS];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -262,6 +266,44 @@ void XUA_Endpoint0_setVendorId(unsigned short vid) {
|
|||||||
#endif // AUDIO_CLASS == 1}
|
#endif // AUDIO_CLASS == 1}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if (MIXER)
|
||||||
|
void InitLocalMixerState()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < MIX_INPUTS * MAX_MIX_COUNT; i++)
|
||||||
|
{
|
||||||
|
mixer1Weights[i] = 0x8001; //-inf
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Configure default connections */
|
||||||
|
for (int i = 0; i < MAX_MIX_COUNT; i++)
|
||||||
|
{
|
||||||
|
mixer1Weights[(i * MAX_MIX_COUNT) + i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if NUM_USB_CHAN_OUT > 0
|
||||||
|
/* Setup up audio output channel mapping */
|
||||||
|
for(int i = 0; i < NUM_USB_CHAN_OUT; i++)
|
||||||
|
{
|
||||||
|
channelMapAud[i] = i;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if NUM_USB_CHAN_IN > 0
|
||||||
|
for(int i = 0; i < NUM_USB_CHAN_IN; i++)
|
||||||
|
{
|
||||||
|
channelMapUsb[i] = i + NUM_USB_CHAN_OUT;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Init mixer inputs */
|
||||||
|
for(int j = 0; j < MAX_MIX_COUNT; j++)
|
||||||
|
for(int i = 0; i < MIX_INPUTS; i++)
|
||||||
|
{
|
||||||
|
mixSel[j][i] = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void concatenateAndCopyStrings(char* string1, char* string2, char* string_buffer) {
|
void concatenateAndCopyStrings(char* string1, char* string2, char* string_buffer) {
|
||||||
debug_printf("concatenateAndCopyStrings() for \"%s\" and \"%s\"\n", string1, string2);
|
debug_printf("concatenateAndCopyStrings() for \"%s\" and \"%s\"\n", string1, string2);
|
||||||
|
|
||||||
@@ -400,6 +442,15 @@ void XUA_Endpoint0_setBcdDevice(unsigned short bcd) {
|
|||||||
#endif // AUDIO_CLASS == 1}
|
#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),
|
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_)
|
chanend c_mix_ctl, chanend c_clk_ctl, chanend c_EANativeTransport_ctrl, CLIENT_INTERFACE(i_dfu, dfuInterface) VENDOR_REQUESTS_PARAMS_DEC_)
|
||||||
{
|
{
|
||||||
@@ -408,75 +459,11 @@ void XUA_Endpoint0_init(chanend c_ep0_out, chanend c_ep0_in, NULLABLE_RESOURCE(c
|
|||||||
|
|
||||||
XUA_Endpoint0_setStrTable();
|
XUA_Endpoint0_setStrTable();
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* Dont need to init globals.. */
|
|
||||||
/* Init tables for volumes (+ 1 for master) */
|
|
||||||
for(int i = 0; i < NUM_USB_CHAN_OUT + 1; i++)
|
|
||||||
{
|
|
||||||
volsOut[i] = 0;
|
|
||||||
mutesOut[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(int i = 0; i < NUM_USB_CHAN_IN + 1; i++)
|
|
||||||
{
|
|
||||||
volsIn[i] = 0;
|
|
||||||
mutesIn[i] = 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
VendorRequests_Init(VENDOR_REQUESTS_PARAMS);
|
VendorRequests_Init(VENDOR_REQUESTS_PARAMS);
|
||||||
|
|
||||||
#ifdef MIXER
|
#if (MIXER)
|
||||||
/* Set up mixer default state */
|
/* Set up mixer default state */
|
||||||
for (int i = 0; i < 18*8; i++)
|
InitLocalMixerState();
|
||||||
{
|
|
||||||
mixer1Weights[i] = 0x8001; //-inf
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Configure default connections */
|
|
||||||
mixer1Weights[0] = 0;
|
|
||||||
mixer1Weights[9] = 0;
|
|
||||||
mixer1Weights[18] = 0;
|
|
||||||
mixer1Weights[27] = 0;
|
|
||||||
mixer1Weights[36] = 0;
|
|
||||||
mixer1Weights[45] = 0;
|
|
||||||
mixer1Weights[54] = 0;
|
|
||||||
mixer1Weights[63] = 0;
|
|
||||||
|
|
||||||
#if NUM_USB_CHAN_OUT > 0
|
|
||||||
/* Setup up audio output channel mapping */
|
|
||||||
for(int i = 0; i < NUM_USB_CHAN_OUT; i++)
|
|
||||||
{
|
|
||||||
channelMapAud[i] = i;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if NUM_USB_CHAN_IN > 0
|
|
||||||
for(int i = 0; i < NUM_USB_CHAN_IN; i++)
|
|
||||||
{
|
|
||||||
channelMapUsb[i] = i + NUM_USB_CHAN_OUT;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Set up channel mapping default */
|
|
||||||
for (int i = 0; i < NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN; i++)
|
|
||||||
{
|
|
||||||
channelMap[i] = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if MAX_MIX_COUNT > 0
|
|
||||||
/* Mixer outputs mapping defaults */
|
|
||||||
for (int i = 0; i < MAX_MIX_COUNT; i++)
|
|
||||||
{
|
|
||||||
channelMap[NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + i] = i;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Init mixer inputs */
|
|
||||||
for(int j = 0; j < MAX_MIX_COUNT; j++)
|
|
||||||
for(int i = 0; i < MIX_INPUTS; i++)
|
|
||||||
{
|
|
||||||
mixSel[j][i] = i;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef VENDOR_AUDIO_REQS
|
#ifdef VENDOR_AUDIO_REQS
|
||||||
@@ -529,18 +516,19 @@ void XUA_Endpoint0_init(chanend c_ep0_out, chanend c_ep0_in, NULLABLE_RESOURCE(c
|
|||||||
cfgDesc_Audio1[USB_AS_OUT_INTERFACE_DESCRIPTOR_OFFSET_FREQ + 3*i + 2] = (get_usb_to_device_rate() & 0xff0000)>> 16;
|
cfgDesc_Audio1[USB_AS_OUT_INTERFACE_DESCRIPTOR_OFFSET_FREQ + 3*i + 2] = (get_usb_to_device_rate() & 0xff0000)>> 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
cfgDesc_Audio1[USB_AS_OUT_EP_DESCRIPTOR_OFFSET_MAXPACKETSIZE] = ((get_usb_to_device_bit_res() >> 3) * MAX_PACKET_SIZE_MULT_OUT_FS) & 0xff; //max packet size
|
cfgDesc_Audio1[USB_AS_OUT_EP_DESCRIPTOR_OFFSET_MAXPACKETSIZE] = ((get_usb_to_device_bit_res() >> 3) * MAX_PACKET_SIZE_MULT_OUT_FS) & 0xff; //max packet size
|
||||||
cfgDesc_Audio1[USB_AS_OUT_EP_DESCRIPTOR_OFFSET_MAXPACKETSIZE + 1] = (((get_usb_to_device_bit_res() >> 3) * MAX_PACKET_SIZE_MULT_OUT_FS) & 0xff00) >> 8; //max packet size
|
cfgDesc_Audio1[USB_AS_OUT_EP_DESCRIPTOR_OFFSET_MAXPACKETSIZE + 1] = (((get_usb_to_device_bit_res() >> 3) * MAX_PACKET_SIZE_MULT_OUT_FS) & 0xff00) >> 8; //max packet size
|
||||||
#endif // NUM_USB_CHAN_OUT
|
#endif // NUM_USB_CHAN_OUT
|
||||||
|
|
||||||
#endif // XUA_USB_DESCRIPTOR_OVERWRITE_RATE_RES
|
#endif // XUA_USB_DESCRIPTOR_OVERWRITE_RATE_RES
|
||||||
|
|
||||||
#if( 0 < HID_CONTROLS )
|
#if XUA_OR_STATIC_HID_ENABLED
|
||||||
|
#if XUA_HID_ENABLED
|
||||||
hidReportInit();
|
hidReportInit();
|
||||||
hidPrepareReportDescriptor();
|
hidPrepareReportDescriptor();
|
||||||
|
|
||||||
size_t hidReportDescriptorLength = hidGetReportDescriptorLength();
|
size_t hidReportDescriptorLength = hidGetReportDescriptorLength();
|
||||||
|
#endif
|
||||||
unsigned char hidReportDescriptorLengthLo = hidReportDescriptorLength & 0xFF;
|
unsigned char hidReportDescriptorLengthLo = hidReportDescriptorLength & 0xFF;
|
||||||
unsigned char hidReportDescriptorLengthHi = (hidReportDescriptorLength & 0xFF00) >> 8;
|
unsigned char hidReportDescriptorLengthHi = (hidReportDescriptorLength & 0xFF00) >> 8;
|
||||||
|
|
||||||
@@ -551,6 +539,7 @@ 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 ] = hidReportDescriptorLengthLo;
|
||||||
hidDescriptor[HID_DESCRIPTOR_LENGTH_FIELD_OFFSET + 1] = hidReportDescriptorLengthHi;
|
hidDescriptor[HID_DESCRIPTOR_LENGTH_FIELD_OFFSET + 1] = hidReportDescriptorLengthHi;
|
||||||
|
|
||||||
#endif // 0 < HID_CONTROLS
|
#endif // 0 < HID_CONTROLS
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -754,7 +743,7 @@ void XUA_Endpoint0_loop(XUD_Result_t result, USB_SetupPacket_t sp, chanend c_ep0
|
|||||||
|
|
||||||
switch(sp.bRequest)
|
switch(sp.bRequest)
|
||||||
{
|
{
|
||||||
#if( 0 < HID_CONTROLS )
|
#if XUA_OR_STATIC_HID_ENABLED
|
||||||
case USB_GET_DESCRIPTOR:
|
case USB_GET_DESCRIPTOR:
|
||||||
|
|
||||||
/* Check what inteface request is for */
|
/* Check what inteface request is for */
|
||||||
@@ -769,15 +758,17 @@ void XUA_Endpoint0_loop(XUD_Result_t result, USB_SetupPacket_t sp, chanend c_ep0
|
|||||||
{
|
{
|
||||||
/* Return HID Descriptor */
|
/* Return HID Descriptor */
|
||||||
result = XUD_DoGetRequest(ep0_out, ep0_in, hidDescriptor,
|
result = XUD_DoGetRequest(ep0_out, ep0_in, hidDescriptor,
|
||||||
sizeof(hidDescriptor), sp.wLength);
|
hidDescriptor[0], sp.wLength);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case HID_REPORT:
|
case HID_REPORT:
|
||||||
{
|
{
|
||||||
/* Return HID report descriptor */
|
/* Return HID report descriptor */
|
||||||
|
#if XUA_HID_ENABLED
|
||||||
unsigned char* hidReportDescriptorPtr;
|
unsigned char* hidReportDescriptorPtr;
|
||||||
hidReportDescriptorPtr = hidGetReportDescriptor();
|
hidReportDescriptorPtr = hidGetReportDescriptor();
|
||||||
size_t hidReportDescriptorLength = hidGetReportDescriptorLength();
|
size_t hidReportDescriptorLength = hidGetReportDescriptorLength();
|
||||||
|
#endif
|
||||||
result = XUD_DoGetRequest(ep0_out, ep0_in, hidReportDescriptorPtr,
|
result = XUD_DoGetRequest(ep0_out, ep0_in, hidReportDescriptorPtr,
|
||||||
hidReportDescriptorLength, sp.wLength);
|
hidReportDescriptorLength, sp.wLength);
|
||||||
}
|
}
|
||||||
@@ -881,7 +872,7 @@ void XUA_Endpoint0_loop(XUD_Result_t result, USB_SetupPacket_t sp, chanend c_ep0
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if( 0 < HID_CONTROLS )
|
#if XUA_HID_ENABLED
|
||||||
if (interfaceNum == INTERFACE_NUMBER_HID)
|
if (interfaceNum == INTERFACE_NUMBER_HID)
|
||||||
{
|
{
|
||||||
result = HidInterfaceClassRequests(ep0_out, ep0_in, &sp);
|
result = HidInterfaceClassRequests(ep0_out, ep0_in, &sp);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2011-2022 XMOS LIMITED.
|
// Copyright 2011-2023 XMOS LIMITED.
|
||||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||||
/**
|
/**
|
||||||
* @file xua_ep0_descriptors.h
|
* @file xua_ep0_descriptors.h
|
||||||
@@ -308,28 +308,28 @@ typedef struct
|
|||||||
#error NUM_USB_CHAN > 32
|
#error NUM_USB_CHAN > 32
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(MIXER) && (MAX_MIX_COUNT > 0)
|
#if (MIXER) && (MAX_MIX_COUNT > 0)
|
||||||
STR_TABLE_ENTRY(mixOutStr_1);
|
STR_TABLE_ENTRY(mixOutStr_1);
|
||||||
#endif
|
#endif
|
||||||
#if defined(MIXER) && (MAX_MIX_COUNT > 1)
|
#if (MIXER) && (MAX_MIX_COUNT > 1)
|
||||||
STR_TABLE_ENTRY(mixOutStr_2);
|
STR_TABLE_ENTRY(mixOutStr_2);
|
||||||
#endif
|
#endif
|
||||||
#if defined(MIXER) && (MAX_MIX_COUNT > 2)
|
#if (MIXER) && (MAX_MIX_COUNT > 2)
|
||||||
STR_TABLE_ENTRY(mixOutStr_3);
|
STR_TABLE_ENTRY(mixOutStr_3);
|
||||||
#endif
|
#endif
|
||||||
#if defined(MIXER) && (MAX_MIX_COUNT > 3)
|
#if (MIXER) && (MAX_MIX_COUNT > 3)
|
||||||
STR_TABLE_ENTRY(mixOutStr_4);
|
STR_TABLE_ENTRY(mixOutStr_4);
|
||||||
#endif
|
#endif
|
||||||
#if defined(MIXER) && (MAX_MIX_COUNT > 4)
|
#if (MIXER) && (MAX_MIX_COUNT > 4)
|
||||||
STR_TABLE_ENTRY(mixOutStr_5);
|
STR_TABLE_ENTRY(mixOutStr_5);
|
||||||
#endif
|
#endif
|
||||||
#if defined(MIXER) && (MAX_MIX_COUNT > 5)
|
#if (MIXER) && (MAX_MIX_COUNT > 5)
|
||||||
STR_TABLE_ENTRY(mixOutStr_6);
|
STR_TABLE_ENTRY(mixOutStr_6);
|
||||||
#endif
|
#endif
|
||||||
#if defined(MIXER) && (MAX_MIX_COUNT > 6)
|
#if (MIXER) && (MAX_MIX_COUNT > 6)
|
||||||
STR_TABLE_ENTRY(mixOutStr_7);
|
STR_TABLE_ENTRY(mixOutStr_7);
|
||||||
#endif
|
#endif
|
||||||
#if defined(MIXER) && (MAX_MIX_COUNT > 7)
|
#if (MIXER) && (MAX_MIX_COUNT > 7)
|
||||||
STR_TABLE_ENTRY(mixOutStr_8);
|
STR_TABLE_ENTRY(mixOutStr_8);
|
||||||
#endif
|
#endif
|
||||||
#ifdef IAP
|
#ifdef IAP
|
||||||
@@ -391,31 +391,31 @@ StringDescTable_t g_strTable =
|
|||||||
#error NUM_USB_CHAN_IN > 32
|
#error NUM_USB_CHAN_IN > 32
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(MIXER) && (MAX_MIX_COUNT > 0)
|
#if (MIXER) && (MAX_MIX_COUNT > 0)
|
||||||
.mixOutStr_1 = "Mix 1",
|
.mixOutStr_1 = "Mix 1",
|
||||||
#endif
|
#endif
|
||||||
#if defined(MIXER) && (MAX_MIX_COUNT > 1)
|
#if (MIXER) && (MAX_MIX_COUNT > 1)
|
||||||
.mixOutStr_2 = "Mix 2",
|
.mixOutStr_2 = "Mix 2",
|
||||||
#endif
|
#endif
|
||||||
#if defined(MIXER) && (MAX_MIX_COUNT > 2)
|
#if (MIXER) && (MAX_MIX_COUNT > 2)
|
||||||
.mixOutStr_3 = "Mix 3",
|
.mixOutStr_3 = "Mix 3",
|
||||||
#endif
|
#endif
|
||||||
#if defined(MIXER) && (MAX_MIX_COUNT > 3)
|
#if (MIXER) && (MAX_MIX_COUNT > 3)
|
||||||
.mixOutStr_4 = "Mix 4",
|
.mixOutStr_4 = "Mix 4",
|
||||||
#endif
|
#endif
|
||||||
#if defined(MIXER) && (MAX_MIX_COUNT > 4)
|
#if (MIXER) && (MAX_MIX_COUNT > 4)
|
||||||
.mixOutStr_5 = "Mix 5",
|
.mixOutStr_5 = "Mix 5",
|
||||||
#endif
|
#endif
|
||||||
#if defined(MIXER) && (MAX_MIX_COUNT > 5)
|
#if (MIXER) && (MAX_MIX_COUNT > 5)
|
||||||
.mixOutStr_6 = "Mix 6",
|
.mixOutStr_6 = "Mix 6",
|
||||||
#endif
|
#endif
|
||||||
#if defined(MIXER) && (MAX_MIX_COUNT > 6)
|
#if (MIXER) && (MAX_MIX_COUNT > 6)
|
||||||
.mixOutStr_7 = "Mix 7",
|
.mixOutStr_7 = "Mix 7",
|
||||||
#endif
|
#endif
|
||||||
#if defined(MIXER) && (MAX_MIX_COUNT > 7)
|
#if (MIXER) && (MAX_MIX_COUNT > 7)
|
||||||
.mixOutStr_8 = "Mix 8",
|
.mixOutStr_8 = "Mix 8",
|
||||||
#endif
|
#endif
|
||||||
#if defined(MIXER) && (MAX_MIX_COUNT > 8)
|
#if (MIXER) && (MAX_MIX_COUNT > 8)
|
||||||
#error
|
#error
|
||||||
#endif
|
#endif
|
||||||
#ifdef IAP
|
#ifdef IAP
|
||||||
@@ -481,7 +481,7 @@ USB_Descriptor_Device_t devDesc_Audio2 =
|
|||||||
.iManufacturer = offsetof(StringDescTable_t, vendorStr)/sizeof(char *),
|
.iManufacturer = offsetof(StringDescTable_t, vendorStr)/sizeof(char *),
|
||||||
.iProduct = offsetof(StringDescTable_t, productStr_Audio2)/sizeof(char *),
|
.iProduct = offsetof(StringDescTable_t, productStr_Audio2)/sizeof(char *),
|
||||||
.iSerialNumber = offsetof(StringDescTable_t, serialStr)/sizeof(char *),
|
.iSerialNumber = offsetof(StringDescTable_t, serialStr)/sizeof(char *),
|
||||||
.bNumConfigurations = 0x02 /* Set to 2 such that windows does not load composite driver */
|
.bNumConfigurations = 0x01
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Device Descriptor for Null Device */
|
/* Device Descriptor for Null Device */
|
||||||
@@ -558,7 +558,7 @@ unsigned char devQualDesc_Null[] =
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#if defined(MIXER) && !defined(AUDIO_PATH_XUS) && (MAX_MIX_COUNT > 0)
|
#if (MIXER) && !defined(AUDIO_PATH_XUS) && (MAX_MIX_COUNT > 0)
|
||||||
//#warning Extension units on the audio path are required for mixer. Enabling them now.
|
//#warning Extension units on the audio path are required for mixer. Enabling them now.
|
||||||
#define AUDIO_PATH_XUS
|
#define AUDIO_PATH_XUS
|
||||||
#endif
|
#endif
|
||||||
@@ -575,7 +575,7 @@ unsigned char devQualDesc_Null[] =
|
|||||||
#define DFU_LENGTH (0)
|
#define DFU_LENGTH (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MIXER
|
#if (MIXER)
|
||||||
#define MIX_BMCONTROLS_LEN_TMP ((MAX_MIX_COUNT * MIX_INPUTS) / 8)
|
#define MIX_BMCONTROLS_LEN_TMP ((MAX_MIX_COUNT * MIX_INPUTS) / 8)
|
||||||
|
|
||||||
#if ((MAX_MIX_COUNT * MIX_INPUTS)%8)==0
|
#if ((MAX_MIX_COUNT * MIX_INPUTS)%8)==0
|
||||||
@@ -666,7 +666,7 @@ typedef struct
|
|||||||
#if (NUM_USB_CHAN_OUT > 0)
|
#if (NUM_USB_CHAN_OUT > 0)
|
||||||
/* Output path */
|
/* Output path */
|
||||||
USB_Descriptor_Audio_InputTerminal_t Audio_Out_InputTerminal;
|
USB_Descriptor_Audio_InputTerminal_t Audio_Out_InputTerminal;
|
||||||
#if defined(MIXER) && (MAX_MIX_COUNT > 0)
|
#if (MIXER) && (MAX_MIX_COUNT > 0)
|
||||||
USB_Descriptor_Audio_ExtensionUnit_t Audio_Out_ExtensionUnit;
|
USB_Descriptor_Audio_ExtensionUnit_t Audio_Out_ExtensionUnit;
|
||||||
#endif
|
#endif
|
||||||
#if(OUTPUT_VOLUME_CONTROL == 1)
|
#if(OUTPUT_VOLUME_CONTROL == 1)
|
||||||
@@ -677,7 +677,7 @@ typedef struct
|
|||||||
#if (NUM_USB_CHAN_IN > 0)
|
#if (NUM_USB_CHAN_IN > 0)
|
||||||
/* Input path */
|
/* Input path */
|
||||||
USB_Descriptor_Audio_InputTerminal_t Audio_In_InputTerminal;
|
USB_Descriptor_Audio_InputTerminal_t Audio_In_InputTerminal;
|
||||||
#if defined(MIXER) && (MAX_MIX_COUNT > 0)
|
#if (MIXER) && (MAX_MIX_COUNT > 0)
|
||||||
USB_Descriptor_Audio_ExtensionUnit_t Audio_In_ExtensionUnit;
|
USB_Descriptor_Audio_ExtensionUnit_t Audio_In_ExtensionUnit;
|
||||||
#endif
|
#endif
|
||||||
#if(INPUT_VOLUME_CONTROL == 1)
|
#if(INPUT_VOLUME_CONTROL == 1)
|
||||||
@@ -685,7 +685,7 @@ typedef struct
|
|||||||
#endif
|
#endif
|
||||||
USB_Descriptor_Audio_OutputTerminal_t Audio_In_OutputTerminal;
|
USB_Descriptor_Audio_OutputTerminal_t Audio_In_OutputTerminal;
|
||||||
#endif
|
#endif
|
||||||
#if defined(MIXER) && (MAX_MIX_COUNT > 0)
|
#if (MIXER) && (MAX_MIX_COUNT > 0)
|
||||||
USB_Descriptor_Audio_ExtensionUnit2_t Audio_Mix_ExtensionUnit;
|
USB_Descriptor_Audio_ExtensionUnit2_t Audio_Mix_ExtensionUnit;
|
||||||
// Currently no struct for mixer unit
|
// Currently no struct for mixer unit
|
||||||
// USB_Descriptor_Audio_MixerUnit_t Audio_MixerUnit;
|
// USB_Descriptor_Audio_MixerUnit_t Audio_MixerUnit;
|
||||||
@@ -787,10 +787,13 @@ typedef struct
|
|||||||
#endif
|
#endif
|
||||||
#endif // IAP
|
#endif // IAP
|
||||||
|
|
||||||
#if( 0 < HID_CONTROLS )
|
#if XUA_OR_STATIC_HID_ENABLED
|
||||||
USB_Descriptor_Interface_t HID_Interface;
|
USB_Descriptor_Interface_t HID_Interface;
|
||||||
USB_HID_Descriptor_t HID_Descriptor;
|
USB_HID_Descriptor_t HID_Descriptor;
|
||||||
USB_Descriptor_Endpoint_t HID_In_Endpoint;
|
USB_Descriptor_Endpoint_t HID_In_Endpoint;
|
||||||
|
#if HID_OUT_REQUIRED
|
||||||
|
USB_Descriptor_Endpoint_t HID_Out_Endpoint;
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}__attribute__((packed)) USB_Config_Descriptor_Audio2_t;
|
}__attribute__((packed)) USB_Config_Descriptor_Audio2_t;
|
||||||
@@ -1168,7 +1171,7 @@ USB_Config_Descriptor_Audio2_t cfgDesc_Audio2=
|
|||||||
UAC_CS_DESCTYPE_INTERFACE, /* 1 bDescriptorType: CS_INTERFACE */
|
UAC_CS_DESCTYPE_INTERFACE, /* 1 bDescriptorType: CS_INTERFACE */
|
||||||
UAC_CS_AC_INTERFACE_SUBTYPE_FEATURE_UNIT, /* 2 bDescriptorSubType: FEATURE_UNIT */
|
UAC_CS_AC_INTERFACE_SUBTYPE_FEATURE_UNIT, /* 2 bDescriptorSubType: FEATURE_UNIT */
|
||||||
FU_USBIN, /* 3 bUnitID */
|
FU_USBIN, /* 3 bUnitID */
|
||||||
#if defined(MIXER) && (MAX_MIX_COUNT > 0)
|
#if (MIXER) && (MAX_MIX_COUNT > 0)
|
||||||
ID_XU_IN, /* 4 bSourceID */
|
ID_XU_IN, /* 4 bSourceID */
|
||||||
#else
|
#else
|
||||||
ID_IT_AUD, /* 4 bSourceID */
|
ID_IT_AUD, /* 4 bSourceID */
|
||||||
@@ -1300,7 +1303,7 @@ USB_Config_Descriptor_Audio2_t cfgDesc_Audio2=
|
|||||||
},
|
},
|
||||||
#endif /* (NUM_USB_CHAN_IN > 0) */
|
#endif /* (NUM_USB_CHAN_IN > 0) */
|
||||||
|
|
||||||
#if defined(MIXER) && (MAX_MIX_COUNT > 0)
|
#if (MIXER) && (MAX_MIX_COUNT > 0)
|
||||||
/* Extension Unit Descriptor (4.7.2.12) */
|
/* Extension Unit Descriptor (4.7.2.12) */
|
||||||
.Audio_Mix_ExtensionUnit =
|
.Audio_Mix_ExtensionUnit =
|
||||||
{
|
{
|
||||||
@@ -1392,7 +1395,7 @@ USB_Config_Descriptor_Audio2_t cfgDesc_Audio2=
|
|||||||
0x00, /* bmControls */
|
0x00, /* bmControls */
|
||||||
0 /* Mixer unit string descriptor index */
|
0 /* Mixer unit string descriptor index */
|
||||||
},
|
},
|
||||||
#endif /* defined(MIXER) && (MAX_MIX_COUNT > 0) */
|
#endif /* (MIXER) && (MAX_MIX_COUNT > 0) */
|
||||||
|
|
||||||
#if (XUA_SPDIF_RX_EN) || (XUA_ADAT_RX_EN)
|
#if (XUA_SPDIF_RX_EN) || (XUA_ADAT_RX_EN)
|
||||||
/* Standard AS Interrupt Endpoint Descriptor (4.8.2.1): */
|
/* Standard AS Interrupt Endpoint Descriptor (4.8.2.1): */
|
||||||
@@ -2208,14 +2211,14 @@ USB_Config_Descriptor_Audio2_t cfgDesc_Audio2=
|
|||||||
#endif
|
#endif
|
||||||
#endif /* IAP */
|
#endif /* IAP */
|
||||||
|
|
||||||
#if( 0 < HID_CONTROLS )
|
#if XUA_OR_STATIC_HID_ENABLED
|
||||||
#include "xua_hid_descriptors.h"
|
#include "xua_hid_descriptors.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
};
|
};
|
||||||
#endif /* (AUDIO_CLASS == 2) */
|
#endif /* (AUDIO_CLASS == 2) */
|
||||||
|
|
||||||
#if( 0 < HID_CONTROLS )
|
#if XUA_OR_STATIC_HID_ENABLED
|
||||||
#if (AUDIO_CLASS ==1 )
|
#if (AUDIO_CLASS ==1 )
|
||||||
unsigned char hidDescriptor[] =
|
unsigned char hidDescriptor[] =
|
||||||
{
|
{
|
||||||
@@ -2330,14 +2333,14 @@ const unsigned num_freqs_a1 = MAX(3, (0
|
|||||||
#define DFU_INTERFACES_A1 0
|
#define DFU_INTERFACES_A1 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if( 0 < HID_CONTROLS )
|
#if XUA_OR_STATIC_HID_ENABLED
|
||||||
/*
|
/*
|
||||||
* The value of HID_INTERFACE_BYTES must match the length of the descriptors defined in
|
* The value of HID_INTERFACE_BYTES must match the length of the descriptors defined in
|
||||||
* - xua_hid_descriptor_contents.h
|
* - xua_hid_descriptor_contents.h
|
||||||
* - xua_hid_endpoint_descriptor_contents.h and
|
* - xua_hid_endpoint_descriptor_contents.h and
|
||||||
* - xua_hid_interface_descriptor_contents.h
|
* - xua_hid_interface_descriptor_contents.h
|
||||||
*/
|
*/
|
||||||
#define HID_INTERFACE_BYTES ( 9 + 9 + 7 )
|
#define HID_INTERFACE_BYTES ( 9 + 9 + (7 * (1 + HID_OUT_REQUIRED))) // always IN
|
||||||
#define HID_INTERFACES_A1 1
|
#define HID_INTERFACES_A1 1
|
||||||
#else
|
#else
|
||||||
#define HID_INTERFACE_BYTES 0
|
#define HID_INTERFACE_BYTES 0
|
||||||
@@ -2379,7 +2382,7 @@ const unsigned num_freqs_a1 = MAX(3, (0
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if( 0 < HID_CONTROLS )
|
#if XUA_OR_STATIC_HID_ENABLED
|
||||||
#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)
|
#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
|
#endif
|
||||||
|
|
||||||
@@ -2893,7 +2896,7 @@ unsigned char cfgDesc_Audio1[] =
|
|||||||
offsetof(StringDescTable_t, ctrlStr)/sizeof(char *), /* 8 iInterface */
|
offsetof(StringDescTable_t, ctrlStr)/sizeof(char *), /* 8 iInterface */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if( 0 < HID_CONTROLS )
|
#if XUA_OR_STATIC_HID_ENABLED
|
||||||
#include "xua_hid_descriptors.h"
|
#include "xua_hid_descriptors.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2011-2022 XMOS LIMITED.
|
// Copyright 2011-2023 XMOS LIMITED.
|
||||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||||
/**
|
/**
|
||||||
* @brief Implements relevant requests from the USB Audio 2.0 Specification
|
* @brief Implements relevant requests from the USB Audio 2.0 Specification
|
||||||
@@ -14,26 +14,29 @@
|
|||||||
#include "usbaudio10.h"
|
#include "usbaudio10.h"
|
||||||
#include "dbcalc.h"
|
#include "dbcalc.h"
|
||||||
#include "xua_commands.h"
|
#include "xua_commands.h"
|
||||||
#include "xc_ptr.h"
|
|
||||||
|
|
||||||
#define CS_XU_MIXSEL (0x06)
|
#define CS_XU_MIXSEL (0x06)
|
||||||
|
|
||||||
|
/* From decouple.xc */
|
||||||
|
#if (OUT_VOLUME_IN_MIXER == 0) && (OUTPUT_VOLUME_CONTROL == 1)
|
||||||
extern unsigned int multOut[NUM_USB_CHAN_OUT + 1];
|
extern unsigned int multOut[NUM_USB_CHAN_OUT + 1];
|
||||||
|
#endif
|
||||||
|
#if (IN_VOLUME_IN_MIXER == 0) && (INPUT_VOLUME_CONTROL == 1)
|
||||||
extern unsigned int multIn[NUM_USB_CHAN_IN + 1];
|
extern unsigned int multIn[NUM_USB_CHAN_IN + 1];
|
||||||
|
#endif
|
||||||
|
|
||||||
extern int interfaceAlt[];
|
extern int interfaceAlt[];
|
||||||
|
|
||||||
/* Global volume and mute tables */
|
/* Global volume and mute tables - from xua_endpoint0.c */
|
||||||
extern int volsOut[];
|
extern int volsOut[];
|
||||||
extern unsigned int mutesOut[];
|
extern unsigned int mutesOut[];
|
||||||
|
|
||||||
extern int volsIn[];
|
extern int volsIn[];
|
||||||
extern unsigned int mutesIn[];
|
extern unsigned int mutesIn[];
|
||||||
|
|
||||||
/* Mixer settings */
|
#if (MIXER)
|
||||||
#ifdef MIXER
|
/* Mixer weights */
|
||||||
extern unsigned char mixer1Crossbar[];
|
extern short mixer1Weights[MIX_INPUTS * MAX_MIX_COUNT];
|
||||||
extern short mixer1Weights[];
|
|
||||||
|
|
||||||
/* Device channel mapping */
|
/* Device channel mapping */
|
||||||
extern unsigned char channelMapAud[NUM_USB_CHAN_OUT];
|
extern unsigned char channelMapAud[NUM_USB_CHAN_OUT];
|
||||||
@@ -102,20 +105,6 @@ void FeedbackStabilityDelay()
|
|||||||
t when timerafter(time + delay):> void;
|
t when timerafter(time + delay):> void;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* Original feedback implementation */
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
unsigned * unsafe curSamFreqMultiplier = &g_curSamFreqMultiplier;
|
|
||||||
|
|
||||||
static void setG_curSamFreqMultiplier(unsigned x)
|
|
||||||
{
|
|
||||||
// asm(" stw %0, dp[g_curSamFreqMultiplier]" :: "r"(x));
|
|
||||||
*curSamFreqMultiplier = x;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (OUTPUT_VOLUME_CONTROL == 1) || (INPUT_VOLUME_CONTROL == 1)
|
#if (OUTPUT_VOLUME_CONTROL == 1) || (INPUT_VOLUME_CONTROL == 1)
|
||||||
static unsigned longMul(unsigned a, unsigned b, int prec)
|
static unsigned longMul(unsigned a, unsigned b, int prec)
|
||||||
{
|
{
|
||||||
@@ -130,16 +119,9 @@ static unsigned longMul(unsigned a, unsigned b, int prec)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Update master volume i.e. i.e update weights for all channels */
|
/* Update master volume i.e. i.e update weights for all channels */
|
||||||
static void updateMasterVol( int unitID, chanend ?c_mix_ctl)
|
static void updateMasterVol(int unitID, chanend ?c_mix_ctl)
|
||||||
{
|
{
|
||||||
int x;
|
switch(unitID)
|
||||||
#ifndef OUT_VOLUME_IN_MIXER
|
|
||||||
xc_ptr p_multOut = array_to_xc_ptr(multOut);
|
|
||||||
#endif
|
|
||||||
#ifndef IN_VOLUME_IN_MIXER
|
|
||||||
xc_ptr p_multIn = array_to_xc_ptr(multIn);
|
|
||||||
#endif
|
|
||||||
switch( unitID)
|
|
||||||
{
|
{
|
||||||
case FU_USBOUT:
|
case FU_USBOUT:
|
||||||
{
|
{
|
||||||
@@ -151,18 +133,24 @@ static void updateMasterVol( int unitID, chanend ?c_mix_ctl)
|
|||||||
/* 0x8000 is a special value representing -inf (i.e. mute) */
|
/* 0x8000 is a special value representing -inf (i.e. mute) */
|
||||||
unsigned vol = volsOut[i] == 0x8000 ? 0 : db_to_mult(volsOut[i], 8, 29);
|
unsigned vol = volsOut[i] == 0x8000 ? 0 : db_to_mult(volsOut[i], 8, 29);
|
||||||
|
|
||||||
x = longMul(master_vol, vol, 29) * !mutesOut[0] * !mutesOut[i];
|
int x = longMul(master_vol, vol, 29) * !mutesOut[0] * !mutesOut[i];
|
||||||
|
|
||||||
#ifdef OUT_VOLUME_IN_MIXER
|
#if (OUT_VOLUME_IN_MIXER)
|
||||||
if (!isnull(c_mix_ctl))
|
if (!isnull(c_mix_ctl))
|
||||||
{
|
{
|
||||||
|
outct(c_mix_ctl, XS1_CT_END);
|
||||||
|
inct(c_mix_ctl);
|
||||||
outuint(c_mix_ctl, SET_MIX_OUT_VOL);
|
outuint(c_mix_ctl, SET_MIX_OUT_VOL);
|
||||||
outuint(c_mix_ctl, i-1);
|
outuint(c_mix_ctl, i-1);
|
||||||
outuint(c_mix_ctl, x);
|
outuint(c_mix_ctl, x);
|
||||||
outct(c_mix_ctl, XS1_CT_END);
|
outct(c_mix_ctl, XS1_CT_END);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
asm("stw %0, %1[%2]"::"r"(x),"r"(p_multOut),"r"(i-1));
|
unsafe
|
||||||
|
{
|
||||||
|
unsigned int * unsafe multOutPtr = multOut;
|
||||||
|
multOutPtr[i-1] = x;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -177,18 +165,24 @@ static void updateMasterVol( int unitID, chanend ?c_mix_ctl)
|
|||||||
/* 0x8000 is a special value representing -inf (i.e. mute) */
|
/* 0x8000 is a special value representing -inf (i.e. mute) */
|
||||||
unsigned vol = volsIn[i] == 0x8000 ? 0 : db_to_mult(volsIn[i], 8, 29);
|
unsigned vol = volsIn[i] == 0x8000 ? 0 : db_to_mult(volsIn[i], 8, 29);
|
||||||
|
|
||||||
x = longMul(master_vol, vol, 29) * !mutesIn[0] * !mutesIn[i];
|
int x = longMul(master_vol, vol, 29) * !mutesIn[0] * !mutesIn[i];
|
||||||
|
|
||||||
#ifdef IN_VOLUME_IN_MIXER
|
#if (IN_VOLUME_IN_MIXER)
|
||||||
if (!isnull(c_mix_ctl))
|
if (!isnull(c_mix_ctl))
|
||||||
{
|
{
|
||||||
|
outct(c_mix_ctl, XS1_CT_END);
|
||||||
|
inct(c_mix_ctl);
|
||||||
outuint(c_mix_ctl, SET_MIX_IN_VOL);
|
outuint(c_mix_ctl, SET_MIX_IN_VOL);
|
||||||
outuint(c_mix_ctl, i-1);
|
outuint(c_mix_ctl, i-1);
|
||||||
outuint(c_mix_ctl, x);
|
outuint(c_mix_ctl, x);
|
||||||
outct(c_mix_ctl, XS1_CT_END);
|
outct(c_mix_ctl, XS1_CT_END);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
asm("stw %0, %1[%2]"::"r"(x),"r"(p_multIn),"r"(i-1));
|
unsafe
|
||||||
|
{
|
||||||
|
unsigned int * unsafe multInPtr = multIn;
|
||||||
|
multInPtr[i-1] = x;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -202,12 +196,6 @@ static void updateMasterVol( int unitID, chanend ?c_mix_ctl)
|
|||||||
static void updateVol(int unitID, int channel, chanend ?c_mix_ctl)
|
static void updateVol(int unitID, int channel, chanend ?c_mix_ctl)
|
||||||
{
|
{
|
||||||
int x;
|
int x;
|
||||||
#ifndef OUT_VOLUME_IN_MIXER
|
|
||||||
xc_ptr p_multOut = array_to_xc_ptr(multOut);
|
|
||||||
#endif
|
|
||||||
#ifndef IN_VOLUME_IN_MIXER
|
|
||||||
xc_ptr p_multIn = array_to_xc_ptr(multIn);
|
|
||||||
#endif
|
|
||||||
/* Check for master volume update */
|
/* Check for master volume update */
|
||||||
if (channel == 0)
|
if (channel == 0)
|
||||||
{
|
{
|
||||||
@@ -226,16 +214,22 @@ static void updateVol(int unitID, int channel, chanend ?c_mix_ctl)
|
|||||||
|
|
||||||
x = longMul(master_vol, vol, 29) * !mutesOut[0] * !mutesOut[channel];
|
x = longMul(master_vol, vol, 29) * !mutesOut[0] * !mutesOut[channel];
|
||||||
|
|
||||||
#ifdef OUT_VOLUME_IN_MIXER
|
#if (OUT_VOLUME_IN_MIXER)
|
||||||
if (!isnull(c_mix_ctl))
|
if (!isnull(c_mix_ctl))
|
||||||
{
|
{
|
||||||
|
outct(c_mix_ctl, XS1_CT_END);
|
||||||
|
inct(c_mix_ctl);
|
||||||
outuint(c_mix_ctl, SET_MIX_OUT_VOL);
|
outuint(c_mix_ctl, SET_MIX_OUT_VOL);
|
||||||
outuint(c_mix_ctl, channel-1);
|
outuint(c_mix_ctl, channel-1);
|
||||||
outuint(c_mix_ctl, x);
|
outuint(c_mix_ctl, x);
|
||||||
outct(c_mix_ctl, XS1_CT_END);
|
outct(c_mix_ctl, XS1_CT_END);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
asm("stw %0, %1[%2]"::"r"(x),"r"(p_multOut),"r"(channel-1));
|
unsafe
|
||||||
|
{
|
||||||
|
unsigned int * unsafe multOutPtr = multOut;
|
||||||
|
multOutPtr[channel-1] = x;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -244,20 +238,26 @@ static void updateVol(int unitID, int channel, chanend ?c_mix_ctl)
|
|||||||
/* Calc multipliers with 29 fractional bits from a db value with 8 fractional bits */
|
/* Calc multipliers with 29 fractional bits from a db value with 8 fractional bits */
|
||||||
/* 0x8000 is a special value representing -inf (i.e. mute) */
|
/* 0x8000 is a special value representing -inf (i.e. mute) */
|
||||||
unsigned master_vol = volsIn[0] == 0x8000 ? 0 : db_to_mult(volsIn[0], 8, 29);
|
unsigned master_vol = volsIn[0] == 0x8000 ? 0 : db_to_mult(volsIn[0], 8, 29);
|
||||||
unsigned vol = volsIn[channel] == 0x8000 ? 0 : db_to_mult(volsIn[channel], 8, 29);
|
unsigned vol = volsIn[channel] == 0x8000 ? 0 : db_to_mult(volsIn[channel], 8, 29);
|
||||||
|
|
||||||
x = longMul(master_vol, vol, 29) * !mutesIn[0] * !mutesIn[channel];
|
x = longMul(master_vol, vol, 29) * !mutesIn[0] * !mutesIn[channel];
|
||||||
|
|
||||||
#ifdef IN_VOLUME_IN_MIXER
|
#if (IN_VOLUME_IN_MIXER)
|
||||||
if (!isnull(c_mix_ctl))
|
if (!isnull(c_mix_ctl))
|
||||||
{
|
{
|
||||||
|
outct(c_mix_ctl, XS1_CT_END);
|
||||||
|
inct(c_mix_ctl);
|
||||||
outuint(c_mix_ctl, SET_MIX_IN_VOL);
|
outuint(c_mix_ctl, SET_MIX_IN_VOL);
|
||||||
outuint(c_mix_ctl, channel-1);
|
outuint(c_mix_ctl, channel-1);
|
||||||
outuint(c_mix_ctl, x);
|
outuint(c_mix_ctl, x);
|
||||||
outct(c_mix_ctl, XS1_CT_END);
|
outct(c_mix_ctl, XS1_CT_END);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
asm("stw %0, %1[%2]"::"r"(x),"r"(p_multIn),"r"(channel-1));
|
unsafe
|
||||||
|
{
|
||||||
|
unsigned int * unsafe multInPtr = multIn;
|
||||||
|
multInPtr[channel-1] = x;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -266,6 +266,38 @@ static void updateVol(int unitID, int channel, chanend ?c_mix_ctl)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void UpdateMixerOutputRouting(chanend c_mix_ctl, unsigned map, unsigned dst, unsigned src)
|
||||||
|
{
|
||||||
|
outct(c_mix_ctl, XS1_CT_END);
|
||||||
|
inct(c_mix_ctl);
|
||||||
|
outuint(c_mix_ctl, map);
|
||||||
|
outuint(c_mix_ctl, dst);
|
||||||
|
outuint(c_mix_ctl, src);
|
||||||
|
outct(c_mix_ctl, XS1_CT_END);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateMixMap(chanend c_mix_ctl, int mix, int input, int src)
|
||||||
|
{
|
||||||
|
outct(c_mix_ctl, XS1_CT_END);
|
||||||
|
inct(c_mix_ctl);
|
||||||
|
outuint(c_mix_ctl, SET_MIX_MAP);
|
||||||
|
outuint(c_mix_ctl, mix); /* Mix bus */
|
||||||
|
outuint(c_mix_ctl, input); /* Mixer input (cn) */
|
||||||
|
outuint(c_mix_ctl, src); /* Source (mixSel[cn]) */
|
||||||
|
outct(c_mix_ctl, XS1_CT_END);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateMixerWeight(chanend c_mix_ctl, int mix, int index, unsigned mult)
|
||||||
|
{
|
||||||
|
outct(c_mix_ctl, XS1_CT_END);
|
||||||
|
inct(c_mix_ctl);
|
||||||
|
outuint(c_mix_ctl, SET_MIX_MULT);
|
||||||
|
outuint(c_mix_ctl, mix);
|
||||||
|
outuint(c_mix_ctl, index);
|
||||||
|
outuint(c_mix_ctl, mult);
|
||||||
|
outct(c_mix_ctl, XS1_CT_END);
|
||||||
|
}
|
||||||
|
|
||||||
/* Handles the audio class specific requests
|
/* Handles the audio class specific requests
|
||||||
* returns: XUD_RES_OKAY if request dealt with successfully without error,
|
* returns: XUD_RES_OKAY if request dealt with successfully without error,
|
||||||
* XUD_RES_RST for device reset
|
* XUD_RES_RST for device reset
|
||||||
@@ -282,7 +314,6 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
|
|||||||
/* Inspect request, NOTE: these are class specific requests */
|
/* Inspect request, NOTE: these are class specific requests */
|
||||||
switch( sp.bRequest )
|
switch( sp.bRequest )
|
||||||
{
|
{
|
||||||
|
|
||||||
/* CUR Request*/
|
/* CUR Request*/
|
||||||
case CUR:
|
case CUR:
|
||||||
{
|
{
|
||||||
@@ -318,7 +349,7 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
|
|||||||
int newSampleRate = buffer[0];
|
int newSampleRate = buffer[0];
|
||||||
|
|
||||||
/* Instruct audio thread to change sample freq (if change required) */
|
/* Instruct audio thread to change sample freq (if change required) */
|
||||||
//if(newSampleRate != g_curSamFreq)
|
if(newSampleRate != g_curSamFreq)
|
||||||
{
|
{
|
||||||
int newMasterClock;
|
int newMasterClock;
|
||||||
|
|
||||||
@@ -371,7 +402,7 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
|
|||||||
}
|
}
|
||||||
#endif /* MAX_FREQ != MIN_FREQ */
|
#endif /* MAX_FREQ != MIN_FREQ */
|
||||||
/* Send 0 Length as status stage */
|
/* Send 0 Length as status stage */
|
||||||
int x = XUD_DoSetRequestStatus(ep0_in);
|
return XUD_DoSetRequestStatus(ep0_in);
|
||||||
}
|
}
|
||||||
/* Direction: Device-to-host: Send Current Sample Freq */
|
/* Direction: Device-to-host: Send Current Sample Freq */
|
||||||
else
|
else
|
||||||
@@ -537,7 +568,7 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
|
|||||||
if ((sp.wValue & 0xff) <= NUM_USB_CHAN_OUT)
|
if ((sp.wValue & 0xff) <= NUM_USB_CHAN_OUT)
|
||||||
{
|
{
|
||||||
volsOut[ sp.wValue&0xff ] = (buffer, unsigned char[])[0] | (((int) (signed char) (buffer, unsigned char[])[1]) << 8);
|
volsOut[ sp.wValue&0xff ] = (buffer, unsigned char[])[0] | (((int) (signed char) (buffer, unsigned char[])[1]) << 8);
|
||||||
updateVol( unitID, ( sp.wValue & 0xff ), c_mix_ctl );
|
updateVol( unitID, ( sp.wValue & 0xff ), c_mix_ctl);
|
||||||
return XUD_DoSetRequestStatus(ep0_in);
|
return XUD_DoSetRequestStatus(ep0_in);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -546,7 +577,7 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
|
|||||||
if ((sp.wValue & 0xff) <= NUM_USB_CHAN_IN)
|
if ((sp.wValue & 0xff) <= NUM_USB_CHAN_IN)
|
||||||
{
|
{
|
||||||
volsIn[ sp.wValue&0xff ] = (buffer, unsigned char[])[0] | (((int) (signed char) (buffer, unsigned char[])[1]) << 8);
|
volsIn[ sp.wValue&0xff ] = (buffer, unsigned char[])[0] | (((int) (signed char) (buffer, unsigned char[])[1]) << 8);
|
||||||
updateVol( unitID, ( sp.wValue & 0xff ), c_mix_ctl );
|
updateVol( unitID, ( sp.wValue & 0xff ), c_mix_ctl);
|
||||||
return XUD_DoSetRequestStatus(ep0_in);
|
return XUD_DoSetRequestStatus(ep0_in);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -632,85 +663,76 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
|
|||||||
break; /* FU_USBIN */
|
break; /* FU_USBIN */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(MIXER) && (MAX_MIX_COUNT > 0)
|
#if ((MIXER) && (MAX_MIX_COUNT > 0))
|
||||||
case ID_XU_OUT:
|
case ID_XU_OUT:
|
||||||
{
|
|
||||||
if(sp.bmRequestType.Direction == USB_BM_REQTYPE_DIRECTION_H2D) /* Direction: Host-to-device */
|
|
||||||
{
|
{
|
||||||
unsigned volume = 0;
|
int dst = sp.wValue & 0xff;
|
||||||
int c = sp.wValue & 0xff;
|
|
||||||
|
|
||||||
|
if(sp.bmRequestType.Direction == USB_BM_REQTYPE_DIRECTION_H2D) /* Direction: Host-to-device */
|
||||||
if((result = XUD_GetBuffer(ep0_out, (buffer, unsigned char[]), datalength)) != XUD_RES_OKAY)
|
|
||||||
{
|
{
|
||||||
return result;
|
if((result = XUD_GetBuffer(ep0_out, (buffer, unsigned char[]), datalength)) != XUD_RES_OKAY)
|
||||||
}
|
|
||||||
|
|
||||||
channelMapAud[c] = (buffer, unsigned char[])[0] | (buffer, unsigned char[])[1] << 8;
|
|
||||||
|
|
||||||
if (!isnull(c_mix_ctl))
|
|
||||||
{
|
|
||||||
if (c < NUM_USB_CHAN_OUT)
|
|
||||||
{
|
{
|
||||||
outuint(c_mix_ctl, SET_SAMPLES_TO_DEVICE_MAP);
|
return result;
|
||||||
outuint(c_mix_ctl, c);
|
|
||||||
outuint(c_mix_ctl, channelMapAud[c]);
|
|
||||||
outct(c_mix_ctl, XS1_CT_END);
|
|
||||||
/* Send 0 Length as status stage */
|
|
||||||
return XUD_DoSetRequestStatus(ep0_in);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dst < NUM_USB_CHAN_OUT)
|
||||||
|
{
|
||||||
|
channelMapAud[dst] = (buffer, unsigned char[])[0] | (buffer, unsigned char[])[1] << 8;
|
||||||
|
|
||||||
|
if (!isnull(c_mix_ctl))
|
||||||
|
{
|
||||||
|
UpdateMixerOutputRouting(c_mix_ctl, SET_SAMPLES_TO_DEVICE_MAP, dst, channelMapAud[dst]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Send 0 Length as status stage */
|
||||||
|
return XUD_DoSetRequestStatus(ep0_in);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
(buffer, unsigned char[])[0] = channelMapAud[dst];
|
||||||
|
(buffer, unsigned char[])[1] = 0;
|
||||||
|
return XUD_DoGetRequest(ep0_out, ep0_in, (buffer, unsigned char[]), sp.wLength, sp.wLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
(buffer, unsigned char[])[0] = channelMapAud[sp.wValue & 0xff];
|
|
||||||
(buffer, unsigned char[])[1] = 0;
|
|
||||||
|
|
||||||
return XUD_DoGetRequest(ep0_out, ep0_in, (buffer, unsigned char[]), sp.wLength, sp.wLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ID_XU_IN:
|
case ID_XU_IN:
|
||||||
if(sp.bmRequestType.Direction == USB_BM_REQTYPE_DIRECTION_H2D) /* Direction: Host-to-device */
|
|
||||||
{
|
{
|
||||||
unsigned volume = 0;
|
int dst = sp.wValue & 0xff;
|
||||||
int c = sp.wValue & 0xff;
|
|
||||||
|
|
||||||
if((result = XUD_GetBuffer(ep0_out, (buffer, unsigned char[]), datalength)) != XUD_RES_OKAY)
|
if(sp.bmRequestType.Direction == USB_BM_REQTYPE_DIRECTION_H2D) /* Direction: Host-to-device */
|
||||||
{
|
{
|
||||||
return result;
|
if((result = XUD_GetBuffer(ep0_out, (buffer, unsigned char[]), datalength)) != XUD_RES_OKAY)
|
||||||
}
|
|
||||||
|
|
||||||
channelMapUsb[c] = (buffer, unsigned char[])[0] | (buffer, unsigned char[])[1] << 8;
|
|
||||||
|
|
||||||
if (c < NUM_USB_CHAN_IN)
|
|
||||||
{
|
|
||||||
if (!isnull(c_mix_ctl))
|
|
||||||
{
|
{
|
||||||
outuint(c_mix_ctl, SET_SAMPLES_TO_HOST_MAP);
|
return result;
|
||||||
outuint(c_mix_ctl, c);
|
|
||||||
outuint(c_mix_ctl, channelMapUsb[c]);
|
|
||||||
outct(c_mix_ctl, XS1_CT_END);
|
|
||||||
return XUD_DoSetRequestStatus(ep0_in);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dst < NUM_USB_CHAN_IN)
|
||||||
|
{
|
||||||
|
channelMapUsb[dst] = (buffer, unsigned char[])[0] | (buffer, unsigned char[])[1] << 8;
|
||||||
|
|
||||||
|
if (!isnull(c_mix_ctl))
|
||||||
|
{
|
||||||
|
UpdateMixerOutputRouting(c_mix_ctl, SET_SAMPLES_TO_HOST_MAP, dst, channelMapUsb[dst]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return XUD_DoSetRequestStatus(ep0_in);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Direction: Device-to-host */
|
||||||
|
(buffer, unsigned char[])[0] = channelMapUsb[dst];
|
||||||
|
(buffer, unsigned char[])[1] = 0;
|
||||||
|
return XUD_DoGetRequest(ep0_out, ep0_in, (buffer, unsigned char[]), sp.wLength, sp.wLength);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Direction: Device-to-host */
|
|
||||||
(buffer, unsigned char[])[0] = channelMapUsb[sp.wValue & 0xff];
|
|
||||||
(buffer, unsigned char[])[1] = 0;
|
|
||||||
return XUD_DoGetRequest(ep0_out, ep0_in, (buffer, unsigned char[]), sp.wLength, sp.wLength);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ID_XU_MIXSEL:
|
case ID_XU_MIXSEL:
|
||||||
{
|
{
|
||||||
int cs = sp.wValue >> 8; /* Control Selector */
|
int cs = sp.wValue >> 8; /* Control Selector */
|
||||||
int cn = sp.wValue & 0xff; /* Channel number */
|
int cn = sp.wValue & 0xff; /* Channel Number */
|
||||||
|
|
||||||
/* Check for Get or Set */
|
/* Check for Get or Set */
|
||||||
if(sp.bmRequestType.Direction == USB_BM_REQTYPE_DIRECTION_H2D)
|
if(sp.bmRequestType.Direction == USB_BM_REQTYPE_DIRECTION_H2D)
|
||||||
@@ -723,21 +745,19 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
|
|||||||
|
|
||||||
if(datalength > 0)
|
if(datalength > 0)
|
||||||
{
|
{
|
||||||
/* cn bounds check for safety..*/
|
/* CN bounds check for safety..*/
|
||||||
if(cn < MIX_INPUTS)
|
if(cn < MIX_INPUTS)
|
||||||
{
|
{
|
||||||
//if(cs == CS_XU_MIXSEL)
|
//if(cs == CS_XU_MIXSEL)
|
||||||
/* cs now contains mix number */
|
/* cs now contains mix number */
|
||||||
if(cs < (MAX_MIX_COUNT + 1))
|
if(cs < (MAX_MIX_COUNT + 1))
|
||||||
{
|
{
|
||||||
|
int source = (buffer, unsigned char[])[0];
|
||||||
|
|
||||||
/* Check for "off" - update local state */
|
/* Check for "off" - update local state */
|
||||||
if((buffer, unsigned char[])[0] == 0xFF)
|
if(source == 0xFF)
|
||||||
{
|
{
|
||||||
mixSel[cs][cn] = (NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + MAX_MIX_COUNT);
|
source = (NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + MAX_MIX_COUNT);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mixSel[cs][cn] = (buffer, unsigned char[])[0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(cs == 0)
|
if(cs == 0)
|
||||||
@@ -745,21 +765,17 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
|
|||||||
/* Update all mix maps */
|
/* Update all mix maps */
|
||||||
for (int i = 0; i < MAX_MIX_COUNT; i++)
|
for (int i = 0; i < MAX_MIX_COUNT; i++)
|
||||||
{
|
{
|
||||||
outuint(c_mix_ctl, SET_MIX_MAP);
|
/* i : Mix bus */
|
||||||
outuint(c_mix_ctl, i); /* Mix bus */
|
/* cn: Mixer input */
|
||||||
outuint(c_mix_ctl, cn); /* Mixer input */
|
mixSel[i][cn] = source;
|
||||||
outuint(c_mix_ctl, (int) mixSel[cn]); /* Source */
|
UpdateMixMap(c_mix_ctl, i, cn, mixSel[i][cn]);
|
||||||
outct(c_mix_ctl, XS1_CT_END);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Update relevant mix map */
|
/* Update relevant mix map */
|
||||||
outuint(c_mix_ctl, SET_MIX_MAP); /* Command */
|
mixSel[cs-1][cn] = source;
|
||||||
outuint(c_mix_ctl, (cs-1)); /* Mix bus */
|
UpdateMixMap(c_mix_ctl, cs-1, cn, mixSel[cs-1][cn]);
|
||||||
outuint(c_mix_ctl, cn); /* Mixer input */
|
|
||||||
outuint(c_mix_ctl, (int) mixSel[cs][cn]); /* Source */
|
|
||||||
outct(c_mix_ctl, XS1_CT_END); /* Wait for handshake back */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return XUD_DoSetRequestStatus(ep0_in);
|
return XUD_DoSetRequestStatus(ep0_in);
|
||||||
@@ -780,7 +796,7 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
|
|||||||
if((cs > 0) && (cs < (MAX_MIX_COUNT+1)))
|
if((cs > 0) && (cs < (MAX_MIX_COUNT+1)))
|
||||||
{
|
{
|
||||||
(buffer, unsigned char[])[0] = mixSel[cs-1][cn];
|
(buffer, unsigned char[])[0] = mixSel[cs-1][cn];
|
||||||
return XUD_DoGetRequest(ep0_out, ep0_in, (buffer, unsigned char[]), 1, 1 );
|
return XUD_DoGetRequest(ep0_out, ep0_in, (buffer, unsigned char[]), 1, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -788,49 +804,53 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
|
|||||||
}
|
}
|
||||||
|
|
||||||
case ID_MIXER_1:
|
case ID_MIXER_1:
|
||||||
|
|
||||||
if(sp.bmRequestType.Direction == USB_BM_REQTYPE_DIRECTION_H2D) /* Direction: Host-to-device */
|
|
||||||
{
|
{
|
||||||
unsigned volume = 0;
|
int cs = sp.wValue >> 8; /* Control Selector - currently unused */
|
||||||
|
int cn = sp.wValue & 0xff; /* Channel number - used for mixer node index */
|
||||||
|
|
||||||
/* Expect OUT here with mute */
|
if(sp.bmRequestType.Direction == USB_BM_REQTYPE_DIRECTION_H2D) /* Direction: Host-to-device */
|
||||||
if((result = XUD_GetBuffer(ep0_out, (buffer, unsigned char[]), datalength)) != XUD_RES_OKAY)
|
|
||||||
{
|
{
|
||||||
return result;
|
unsigned weightMult = 0;
|
||||||
}
|
|
||||||
|
|
||||||
mixer1Weights[sp.wValue & 0xff] = (buffer, unsigned char[])[0] | (buffer, unsigned char[])[1] << 8;
|
/* Expect OUT here with weight */
|
||||||
|
if((result = XUD_GetBuffer(ep0_out, (buffer, unsigned char[]), datalength)) != XUD_RES_OKAY)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
if (mixer1Weights[sp.wValue & 0xff] == 0x8000)
|
if(cn < sizeof(mixer1Weights)/sizeof(mixer1Weights[0]))
|
||||||
{
|
{
|
||||||
volume = 0;
|
mixer1Weights[cn] = (buffer, unsigned char[])[0] | (buffer, unsigned char[])[1] << 8;
|
||||||
|
|
||||||
|
if (mixer1Weights[cn] != 0x8000)
|
||||||
|
{
|
||||||
|
weightMult = db_to_mult(mixer1Weights[cn], XUA_MIXER_DB_FRAC_BITS, XUA_MIXER_MULT_FRAC_BITS);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isnull(c_mix_ctl))
|
||||||
|
{
|
||||||
|
UpdateMixerWeight(c_mix_ctl, (cn) % 8, (cn) / 8, weightMult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Send 0 Length as status stage */
|
||||||
|
return XUD_DoSetRequestStatus(ep0_in);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
volume = db_to_mult(mixer1Weights[sp.wValue & 0xff], 8, 25);
|
short weight = 0x8000;
|
||||||
}
|
|
||||||
if (!isnull(c_mix_ctl))
|
|
||||||
{
|
|
||||||
outuint(c_mix_ctl, SET_MIX_MULT);
|
|
||||||
outuint(c_mix_ctl, (sp.wValue & 0xff) % 8);
|
|
||||||
outuint(c_mix_ctl, (sp.wValue & 0xff) / 8);
|
|
||||||
outuint(c_mix_ctl, volume);
|
|
||||||
outct(c_mix_ctl, XS1_CT_END);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Send 0 Length as status stage */
|
if(cn < sizeof(mixer1Weights)/sizeof(mixer1Weights[0]))
|
||||||
return XUD_DoSetRequestStatus(ep0_in);
|
{
|
||||||
}
|
weight = mixer1Weights[cn];
|
||||||
else
|
}
|
||||||
{
|
|
||||||
short weight = mixer1Weights[sp.wValue & 0xff];
|
|
||||||
(buffer, unsigned char[])[0] = weight & 0xff;
|
|
||||||
(buffer, unsigned char[])[1] = (weight >> 8) & 0xff;
|
|
||||||
|
|
||||||
return XUD_DoGetRequest(ep0_out, ep0_in, (buffer, unsigned char[]), sp.wLength, sp.wLength);
|
storeShort((buffer, unsigned char[]), 0, weight);
|
||||||
|
|
||||||
|
return XUD_DoGetRequest(ep0_out, ep0_in, (buffer, unsigned char[]), sp.wLength, sp.wLength);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
/* We dont have a unit with this ID! */
|
/* We dont have a unit with this ID! */
|
||||||
@@ -919,7 +939,6 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
|
|||||||
num_freqs++;
|
num_freqs++;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
storeShort((buffer, unsigned char[]), 0, num_freqs);
|
storeShort((buffer, unsigned char[]), 0, num_freqs);
|
||||||
|
|
||||||
return XUD_DoGetRequest(ep0_out, ep0_in, (buffer, unsigned char[]), i, sp.wLength);
|
return XUD_DoGetRequest(ep0_out, ep0_in, (buffer, unsigned char[]), i, sp.wLength);
|
||||||
@@ -957,7 +976,7 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#ifdef MIXER
|
#if (MIXER)
|
||||||
/* Mixer Unit */
|
/* Mixer Unit */
|
||||||
case ID_MIXER_1:
|
case ID_MIXER_1:
|
||||||
storeShort((buffer, unsigned char[]), 0, 1);
|
storeShort((buffer, unsigned char[]), 0, 1);
|
||||||
@@ -967,7 +986,6 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
|
|||||||
return XUD_DoGetRequest(ep0_out, ep0_in, (buffer, unsigned char[]), sp.wLength, sp.wLength);
|
return XUD_DoGetRequest(ep0_out, ep0_in, (buffer, unsigned char[]), sp.wLength, sp.wLength);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* Unknown Unit ID in Range Request selector for FU */
|
/* Unknown Unit ID in Range Request selector for FU */
|
||||||
break;
|
break;
|
||||||
@@ -977,7 +995,7 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
|
|||||||
break; /* case: RANGE */
|
break; /* case: RANGE */
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined (MIXER) && (MAX_MIX_COUNT > 0)
|
#if ((MIXER) && (MAX_MIX_COUNT > 0))
|
||||||
case MEM: /* Memory Requests (5.2.7.1) */
|
case MEM: /* Memory Requests (5.2.7.1) */
|
||||||
|
|
||||||
unitID = sp.wIndex >> 8;
|
unitID = sp.wIndex >> 8;
|
||||||
@@ -1003,6 +1021,8 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
|
|||||||
{
|
{
|
||||||
if (!isnull(c_mix_ctl))
|
if (!isnull(c_mix_ctl))
|
||||||
{
|
{
|
||||||
|
outct(c_mix_ctl, XS1_CT_END);
|
||||||
|
inct(c_mix_ctl);
|
||||||
outuint(c_mix_ctl, GET_STREAM_LEVELS);
|
outuint(c_mix_ctl, GET_STREAM_LEVELS);
|
||||||
outuint(c_mix_ctl, i);
|
outuint(c_mix_ctl, i);
|
||||||
outct(c_mix_ctl, XS1_CT_END);
|
outct(c_mix_ctl, XS1_CT_END);
|
||||||
@@ -1018,6 +1038,8 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
|
|||||||
{
|
{
|
||||||
if (!isnull(c_mix_ctl))
|
if (!isnull(c_mix_ctl))
|
||||||
{
|
{
|
||||||
|
outct(c_mix_ctl, XS1_CT_END);
|
||||||
|
inct(c_mix_ctl);
|
||||||
outuint(c_mix_ctl, GET_INPUT_LEVELS);
|
outuint(c_mix_ctl, GET_INPUT_LEVELS);
|
||||||
outuint(c_mix_ctl, (i - NUM_USB_CHAN_OUT));
|
outuint(c_mix_ctl, (i - NUM_USB_CHAN_OUT));
|
||||||
outct(c_mix_ctl, XS1_CT_END);
|
outct(c_mix_ctl, XS1_CT_END);
|
||||||
@@ -1040,6 +1062,8 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
|
|||||||
{
|
{
|
||||||
if (!isnull(c_mix_ctl))
|
if (!isnull(c_mix_ctl))
|
||||||
{
|
{
|
||||||
|
outct(c_mix_ctl, XS1_CT_END);
|
||||||
|
inct(c_mix_ctl);
|
||||||
outuint(c_mix_ctl, GET_OUTPUT_LEVELS);
|
outuint(c_mix_ctl, GET_OUTPUT_LEVELS);
|
||||||
outuint(c_mix_ctl, i);
|
outuint(c_mix_ctl, i);
|
||||||
outct(c_mix_ctl, XS1_CT_END);
|
outct(c_mix_ctl, XS1_CT_END);
|
||||||
@@ -1107,13 +1131,10 @@ int AudioEndpointRequests_1(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp
|
|||||||
|
|
||||||
if(newSampleRate != g_curSamFreq)
|
if(newSampleRate != g_curSamFreq)
|
||||||
{
|
{
|
||||||
int curSamFreq44100Family;
|
|
||||||
int curSamFreq48000Family;
|
|
||||||
|
|
||||||
/* Windows Audio Class driver has a nice habbit of sending invalid SF's (e.g. 48001Hz)
|
/* Windows Audio Class driver has a nice habbit of sending invalid SF's (e.g. 48001Hz)
|
||||||
* when under stress. Lets double check it here and ignore if not valid. */
|
* when under stress. Lets double check it here and ignore if not valid. */
|
||||||
curSamFreq48000Family = MCLK_48 % newSampleRate == 0;
|
int curSamFreq48000Family = MCLK_48 % newSampleRate == 0;
|
||||||
curSamFreq44100Family = MCLK_441 % newSampleRate == 0;
|
int curSamFreq44100Family = MCLK_441 % newSampleRate == 0;
|
||||||
|
|
||||||
if(curSamFreq48000Family || curSamFreq44100Family)
|
if(curSamFreq48000Family || curSamFreq44100Family)
|
||||||
{
|
{
|
||||||
@@ -1128,7 +1149,7 @@ int AudioEndpointRequests_1(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp
|
|||||||
|
|
||||||
/* Allow time for the change - feedback to stabilise */
|
/* Allow time for the change - feedback to stabilise */
|
||||||
FeedbackStabilityDelay();
|
FeedbackStabilityDelay();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return XUD_SetBuffer(ep0_in, (buffer, unsigned char[]), 0);
|
return XUD_SetBuffer(ep0_in, (buffer, unsigned char[]), 0);
|
||||||
}
|
}
|
||||||
@@ -1190,12 +1211,12 @@ XUD_Result_t AudioClassRequests_1(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket
|
|||||||
{
|
{
|
||||||
case FU_USBOUT:
|
case FU_USBOUT:
|
||||||
volsOut[ sp.wValue & 0xff ] = buffer[0] | (((int) (signed char) buffer[1]) << 8);
|
volsOut[ sp.wValue & 0xff ] = buffer[0] | (((int) (signed char) buffer[1]) << 8);
|
||||||
updateVol( unitID, ( sp.wValue & 0xff ), c_mix_ctl );
|
updateVol( unitID, ( sp.wValue & 0xff ), c_mix_ctl);
|
||||||
return XUD_DoSetRequestStatus(ep0_in);
|
return XUD_DoSetRequestStatus(ep0_in);
|
||||||
|
|
||||||
case FU_USBIN:
|
case FU_USBIN:
|
||||||
volsIn[ sp.wValue & 0xff ] = buffer[0] | (((int) (signed char) buffer[1]) << 8);
|
volsIn[ sp.wValue & 0xff ] = buffer[0] | (((int) (signed char) buffer[1]) << 8);
|
||||||
updateVol( unitID, ( sp.wValue & 0xff ), c_mix_ctl );
|
updateVol( unitID, ( sp.wValue & 0xff ), c_mix_ctl);
|
||||||
return XUD_DoSetRequestStatus(ep0_in);
|
return XUD_DoSetRequestStatus(ep0_in);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1209,12 +1230,12 @@ XUD_Result_t AudioClassRequests_1(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket
|
|||||||
{
|
{
|
||||||
case FU_USBOUT:
|
case FU_USBOUT:
|
||||||
mutesOut[ sp.wValue & 0xff ] = buffer[0];
|
mutesOut[ sp.wValue & 0xff ] = buffer[0];
|
||||||
updateVol( unitID, ( sp.wValue & 0xff ), c_mix_ctl );
|
updateVol( unitID, ( sp.wValue & 0xff ), c_mix_ctl);
|
||||||
return XUD_DoSetRequestStatus(ep0_in);
|
return XUD_DoSetRequestStatus(ep0_in);
|
||||||
|
|
||||||
case FU_USBIN:
|
case FU_USBIN:
|
||||||
mutesIn[ sp.wValue & 0xff ] = buffer[0];
|
mutesIn[ sp.wValue & 0xff ] = buffer[0];
|
||||||
updateVol( unitID, ( sp.wValue & 0xff ), c_mix_ctl );
|
updateVol( unitID, ( sp.wValue & 0xff ), c_mix_ctl);
|
||||||
return XUD_DoSetRequestStatus(ep0_in);
|
return XUD_DoSetRequestStatus(ep0_in);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2012-2022 XMOS LIMITED.
|
// Copyright 2012-2023 XMOS LIMITED.
|
||||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||||
|
|
||||||
#include "xua.h" /* Device specific defines */
|
#include "xua.h" /* Device specific defines */
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (XUA_SPDIF_RX_EN)
|
#if (XUA_SPDIF_RX_EN)
|
||||||
#include "SpdifReceive.h"
|
#include "spdif.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (XUA_ADAT_RX_EN)
|
#if (XUA_ADAT_RX_EN)
|
||||||
@@ -142,10 +142,10 @@ on stdcore[XUD_TILE] : buffered in port:32 p_adat_rx = PORT_ADAT_IN;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (XUA_SPDIF_RX_EN)
|
#if (XUA_SPDIF_RX_EN)
|
||||||
on tile[XUD_TILE] : buffered in port:4 p_spdif_rx = PORT_SPDIF_IN;
|
on tile[XUD_TILE] : in port p_spdif_rx = PORT_SPDIF_IN;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (XUA_SPDIF_RX_EN) || (XUA_ADAT_RX_EN) || (XUA_SYNCMODE == XUA_SYNCMODE_SYNC)
|
#if (XUA_SPDIF_RX_EN) || (XUA_ADAT_RX_EN) || ((XUA_SYNCMODE == XUA_SYNCMODE_SYNC) && (!XUA_USE_APP_PLL))
|
||||||
/* Reference to external clock multiplier */
|
/* Reference to external clock multiplier */
|
||||||
on tile[PLL_REF_TILE] : out port p_pll_ref = PORT_PLL_REF;
|
on tile[PLL_REF_TILE] : out port p_pll_ref = PORT_PLL_REF;
|
||||||
#endif
|
#endif
|
||||||
@@ -213,6 +213,9 @@ XUD_EpType epTypeTableOut[ENDPOINT_COUNT_OUT] = { XUD_EPTYPE_CTL | XUD_STATUS_EN
|
|||||||
#ifdef MIDI
|
#ifdef MIDI
|
||||||
XUD_EPTYPE_BUL, /* MIDI */
|
XUD_EPTYPE_BUL, /* MIDI */
|
||||||
#endif
|
#endif
|
||||||
|
#if HID_OUT_REQUIRED
|
||||||
|
XUD_EPTYPE_INT,
|
||||||
|
#endif
|
||||||
#ifdef IAP
|
#ifdef IAP
|
||||||
XUD_EPTYPE_BUL, /* iAP */
|
XUD_EPTYPE_BUL, /* iAP */
|
||||||
#ifdef IAP_EA_NATIVE_TRANS
|
#ifdef IAP_EA_NATIVE_TRANS
|
||||||
@@ -228,12 +231,12 @@ XUD_EpType epTypeTableIn[ENDPOINT_COUNT_IN] = { XUD_EPTYPE_CTL | XUD_STATUS_ENAB
|
|||||||
XUD_EPTYPE_ISO, /* Async feedback endpoint */
|
XUD_EPTYPE_ISO, /* Async feedback endpoint */
|
||||||
#endif
|
#endif
|
||||||
#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
|
#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
|
||||||
XUD_EPTYPE_BUL,
|
XUD_EPTYPE_INT,
|
||||||
#endif
|
#endif
|
||||||
#ifdef MIDI
|
#ifdef MIDI
|
||||||
XUD_EPTYPE_BUL,
|
XUD_EPTYPE_BUL,
|
||||||
#endif
|
#endif
|
||||||
#if( 0 < HID_CONTROLS )
|
#if XUA_OR_STATIC_HID_ENABLED
|
||||||
XUD_EPTYPE_INT,
|
XUD_EPTYPE_INT,
|
||||||
#endif
|
#endif
|
||||||
#ifdef IAP
|
#ifdef IAP
|
||||||
@@ -267,115 +270,6 @@ void xscope_user_init()
|
|||||||
}
|
}
|
||||||
#endif
|
#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
|
|
||||||
#ifdef 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;
|
|
||||||
|
|
||||||
#ifndef 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)
|
#if (XUA_SPDIF_TX_EN) && (SPDIF_TX_TILE != AUDIO_IO_TILE)
|
||||||
void SpdifTxWrapper(chanend c_spdif_tx)
|
void SpdifTxWrapper(chanend c_spdif_tx)
|
||||||
{
|
{
|
||||||
@@ -401,7 +295,7 @@ void usb_audio_io(chanend ?c_aud_in,
|
|||||||
#if (XUA_SPDIF_TX_EN) && (SPDIF_TX_TILE != AUDIO_IO_TILE)
|
#if (XUA_SPDIF_TX_EN) && (SPDIF_TX_TILE != AUDIO_IO_TILE)
|
||||||
chanend c_spdif_tx,
|
chanend c_spdif_tx,
|
||||||
#endif
|
#endif
|
||||||
#ifdef MIXER
|
#if (MIXER)
|
||||||
chanend c_mix_ctl,
|
chanend c_mix_ctl,
|
||||||
#endif
|
#endif
|
||||||
streaming chanend ?c_spdif_rx,
|
streaming chanend ?c_spdif_rx,
|
||||||
@@ -420,9 +314,12 @@ void usb_audio_io(chanend ?c_aud_in,
|
|||||||
#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
|
#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
|
||||||
, client interface pll_ref_if i_pll_ref
|
, client interface pll_ref_if i_pll_ref
|
||||||
#endif
|
#endif
|
||||||
|
#if (XUA_USE_APP_PLL)
|
||||||
|
, client interface SoftPll_if i_softPll
|
||||||
|
#endif
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
#ifdef MIXER
|
#if (MIXER)
|
||||||
chan c_mix_out;
|
chan c_mix_out;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -446,7 +343,7 @@ void usb_audio_io(chanend ?c_aud_in,
|
|||||||
|
|
||||||
par
|
par
|
||||||
{
|
{
|
||||||
#ifdef MIXER
|
#if (MIXER)
|
||||||
/* Mixer cores(s) */
|
/* Mixer cores(s) */
|
||||||
{
|
{
|
||||||
thread_speed();
|
thread_speed();
|
||||||
@@ -464,12 +361,15 @@ void usb_audio_io(chanend ?c_aud_in,
|
|||||||
/* Audio I/O core (pars additional S/PDIF TX Core) */
|
/* Audio I/O core (pars additional S/PDIF TX Core) */
|
||||||
{
|
{
|
||||||
thread_speed();
|
thread_speed();
|
||||||
#ifdef MIXER
|
#if (MIXER)
|
||||||
#define AUDIO_CHANNEL c_mix_out
|
#define AUDIO_CHANNEL c_mix_out
|
||||||
#else
|
#else
|
||||||
#define AUDIO_CHANNEL c_aud_in
|
#define AUDIO_CHANNEL c_aud_in
|
||||||
#endif
|
#endif
|
||||||
XUA_AudioHub(AUDIO_CHANNEL, clk_audio_mclk, clk_audio_bclk, p_mclk_in, p_lrclk, p_bclk, p_i2s_dac, p_i2s_adc
|
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)
|
#if (XUA_SPDIF_TX_EN) //&& (SPDIF_TX_TILE != AUDIO_IO_TILE)
|
||||||
, c_spdif_tx
|
, c_spdif_tx
|
||||||
#endif
|
#endif
|
||||||
@@ -531,7 +431,7 @@ int main()
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MIXER
|
#if (MIXER)
|
||||||
chan c_mix_ctl;
|
chan c_mix_ctl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -573,17 +473,36 @@ int main()
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ((XUA_SYNCMODE == XUA_SYNCMODE_SYNC) || XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
|
#if (((XUA_SYNCMODE == XUA_SYNCMODE_SYNC) && !XUA_USE_APP_PLL) || XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
|
||||||
interface pll_ref_if i_pll_ref;
|
interface pll_ref_if i_pll_ref;
|
||||||
#endif
|
#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
|
USER_MAIN_DECLARATIONS
|
||||||
|
|
||||||
par
|
par
|
||||||
{
|
{
|
||||||
USER_MAIN_CORES
|
USER_MAIN_CORES
|
||||||
|
|
||||||
#if ((XUA_SYNCMODE == XUA_SYNCMODE_SYNC) || XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
|
#if (((XUA_SYNCMODE == XUA_SYNCMODE_SYNC) && XYA_USE_APP_PLL) || XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
|
||||||
on tile[PLL_REF_TILE]: PllRefPinTask(i_pll_ref, p_pll_ref);
|
on tile[PLL_REF_TILE]: PllRefPinTask(i_pll_ref, p_pll_ref);
|
||||||
#endif
|
#endif
|
||||||
on tile[XUD_TILE]:
|
on tile[XUD_TILE]:
|
||||||
@@ -597,30 +516,91 @@ int main()
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#if XUA_USB_EN
|
#if XUA_USB_EN
|
||||||
/* Core USB audio task, buffering, USB etc */
|
|
||||||
usb_audio_core(c_mix_out
|
|
||||||
#ifdef MIDI
|
|
||||||
, c_midi
|
|
||||||
#endif
|
|
||||||
#ifdef IAP
|
|
||||||
, c_iap
|
|
||||||
#ifdef IAP_EA_NATIVE_TRANS
|
|
||||||
, c_ea_data
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#ifdef MIXER
|
|
||||||
, c_mix_ctl
|
|
||||||
#endif
|
|
||||||
, c_clk_int, c_clk_ctl, dfuInterface
|
|
||||||
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC)
|
|
||||||
, i_pll_ref
|
|
||||||
#endif
|
|
||||||
VENDOR_REQUESTS_PARAMS_
|
|
||||||
|
|
||||||
);
|
/* 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
|
||||||
|
#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 (XUA_HID_ENABLED)
|
||||||
|
, c_xud_in[ENDPOINT_NUMBER_IN_HID]
|
||||||
|
#endif
|
||||||
|
, c_mix_out
|
||||||
|
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC)
|
||||||
|
#if (!XUA_USE_APP_PLL)
|
||||||
|
, i_pll_ref
|
||||||
|
#else
|
||||||
|
, c_swpll_update
|
||||||
|
#endif
|
||||||
|
#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 */
|
#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]:
|
on tile[AUDIO_IO_TILE]:
|
||||||
{
|
{
|
||||||
/* Audio I/O task, includes mixing etc */
|
/* Audio I/O task, includes mixing etc */
|
||||||
@@ -628,7 +608,7 @@ int main()
|
|||||||
#if (XUA_SPDIF_TX_EN) && (SPDIF_TX_TILE != AUDIO_IO_TILE)
|
#if (XUA_SPDIF_TX_EN) && (SPDIF_TX_TILE != AUDIO_IO_TILE)
|
||||||
, c_spdif_tx
|
, c_spdif_tx
|
||||||
#endif
|
#endif
|
||||||
#ifdef MIXER
|
#if (MIXER)
|
||||||
, c_mix_ctl
|
, c_mix_ctl
|
||||||
#endif
|
#endif
|
||||||
, c_spdif_rx, c_adat_rx, c_clk_ctl, c_clk_int
|
, c_spdif_rx, c_adat_rx, c_clk_ctl, c_clk_int
|
||||||
@@ -643,6 +623,9 @@ int main()
|
|||||||
#endif
|
#endif
|
||||||
#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
|
#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
|
||||||
, i_pll_ref
|
, i_pll_ref
|
||||||
|
#endif
|
||||||
|
#if (XUA_USE_APP_PLL)
|
||||||
|
, i_softPll
|
||||||
#endif
|
#endif
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -685,7 +668,7 @@ int main()
|
|||||||
on tile[XUD_TILE]:
|
on tile[XUD_TILE]:
|
||||||
{
|
{
|
||||||
thread_speed();
|
thread_speed();
|
||||||
SpdifReceive(p_spdif_rx, c_spdif_rx, 1, clk_spd_rx);
|
spdif_rx(c_spdif_rx,p_spdif_rx,clk_spd_rx,192000);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,21 @@
|
|||||||
// Copyright 2018-2021 XMOS LIMITED.
|
// Copyright 2018-2023 XMOS LIMITED.
|
||||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||||
|
|
||||||
#define MAX_MIX_COUNT 8
|
#include "xua.h"
|
||||||
#define MIX_INPUTS 18
|
|
||||||
|
#ifndef MAX_MIX_COUNT
|
||||||
|
#error
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MIX_INPUTS
|
||||||
|
#error
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (MAX_MIX_COUNT > 0)
|
||||||
|
|
||||||
#define DOMIX_TOP(i) \
|
#define DOMIX_TOP(i) \
|
||||||
.cc_top doMix##i.function,doMix##i; \
|
.cc_top doMix##i.function,doMix##i; \
|
||||||
.align 4 ;\
|
.align 16 ;\
|
||||||
.globl doMix##i ;\
|
.globl doMix##i ;\
|
||||||
.type doMix##i, @function ;\
|
.type doMix##i, @function ;\
|
||||||
.globl doMix##i##.nstackwords ;\
|
.globl doMix##i##.nstackwords ;\
|
||||||
@@ -124,7 +133,7 @@ DOMIX_BOT(7)
|
|||||||
#undef BODY
|
#undef BODY
|
||||||
#define N MAX_MIX_COUNT
|
#define N MAX_MIX_COUNT
|
||||||
.cc_top setPtr.function,setPtr;
|
.cc_top setPtr.function,setPtr;
|
||||||
.align 4 ;
|
.align 16 ;
|
||||||
.globl setPtr;
|
.globl setPtr;
|
||||||
.type setPtr, @function
|
.type setPtr, @function
|
||||||
.globl setPtr.nstackwords;
|
.globl setPtr.nstackwords;
|
||||||
@@ -173,5 +182,5 @@ setPtr_go:
|
|||||||
#undef N
|
#undef N
|
||||||
#undef BODY
|
#undef BODY
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -1,25 +1,39 @@
|
|||||||
// Copyright 2011-2022 XMOS LIMITED.
|
// Copyright 2011-2023 XMOS LIMITED.
|
||||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||||
|
#define XASSERT_UNIT MIXER
|
||||||
|
#include "xassert.h"
|
||||||
|
|
||||||
#include <xs1.h>
|
#include <xs1.h>
|
||||||
#include <print.h>
|
|
||||||
#include "xua.h"
|
#include "xua.h"
|
||||||
#include "xc_ptr.h"
|
|
||||||
#include "xua_commands.h"
|
#include "xua_commands.h"
|
||||||
#include "dbcalc.h"
|
#include "dbcalc.h"
|
||||||
|
|
||||||
#ifdef MIXER
|
/* FAST_MIXER has a bit of a nasty implentation but is more efficient */
|
||||||
|
#ifndef FAST_MIXER
|
||||||
|
#define FAST_MIXER (1)
|
||||||
|
#endif
|
||||||
|
|
||||||
/* FAST_MIXER has a bit of a nasty implentation but is more effcient */
|
#if defined (LEVEL_METER_HOST) || defined(LEVEL_METER_LEDS) || !FAST_MIXER
|
||||||
#define FAST_MIXER 1
|
#include "xc_ptr.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
//#ifdef OUT_VOLUME_IN_MIXER
|
#if (MIXER)
|
||||||
|
|
||||||
|
#if (OUT_VOLUME_IN_MIXER)
|
||||||
static unsigned int multOut_array[NUM_USB_CHAN_OUT + 1];
|
static unsigned int multOut_array[NUM_USB_CHAN_OUT + 1];
|
||||||
static xc_ptr multOut;
|
unsafe
|
||||||
//#endif
|
{
|
||||||
//#ifdef IN_VOLUME_IN_MIXER
|
unsigned int volatile * unsafe multOut = multOut_array;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (IN_VOLUME_IN_MIXER)
|
||||||
static unsigned int multIn_array[NUM_USB_CHAN_IN + 1];
|
static unsigned int multIn_array[NUM_USB_CHAN_IN + 1];
|
||||||
static xc_ptr multIn;
|
unsafe
|
||||||
//#endif
|
{
|
||||||
|
unsigned int volatile * unsafe multIn = multIn_array;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined (LEVEL_METER_LEDS) || defined (LEVEL_METER_HOST)
|
#if defined (LEVEL_METER_LEDS) || defined (LEVEL_METER_HOST)
|
||||||
static unsigned abs(int x)
|
static unsigned abs(int x)
|
||||||
@@ -35,35 +49,38 @@ static unsigned abs(int x)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static const int SOURCE_COUNT = NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + MAX_MIX_COUNT + 1;
|
||||||
|
|
||||||
static int samples_array[NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + MAX_MIX_COUNT + 1]; /* One larger for an "off" channel for mixer sources" */
|
static int samples_array[NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + MAX_MIX_COUNT + 1]; /* One larger for an "off" channel for mixer sources" */
|
||||||
xc_ptr samples;
|
static int samples_to_host_map_array[NUM_USB_CHAN_IN];
|
||||||
|
static int samples_to_device_map_array[NUM_USB_CHAN_OUT];
|
||||||
|
|
||||||
unsafe
|
unsafe
|
||||||
{
|
{
|
||||||
static int volatile * const unsafe ptr_samples = samples_array;
|
int volatile * const unsafe ptr_samples = samples_array;
|
||||||
|
int volatile * const unsafe samples_to_host_map = samples_to_host_map_array;
|
||||||
|
int volatile * const unsafe samples_to_device_map = samples_to_device_map_array;
|
||||||
}
|
}
|
||||||
|
|
||||||
int savedsamples2[NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + MAX_MIX_COUNT];
|
#if (MAX_MIX_COUNT > 0)
|
||||||
|
int mix_mult_array[MAX_MIX_COUNT * MIX_INPUTS];
|
||||||
int samples_to_host_map_array[NUM_USB_CHAN_IN];
|
#if (FAST_MIXER == 0)
|
||||||
xc_ptr samples_to_host_map;
|
int mix_map_array[MAX_MIX_COUNT * MIX_INPUTS];
|
||||||
|
|
||||||
int samples_to_device_map_array[NUM_USB_CHAN_OUT];
|
|
||||||
xc_ptr samples_to_device_map;
|
|
||||||
|
|
||||||
#if MAX_MIX_COUNT > 0
|
|
||||||
int mix_mult_array[MAX_MIX_COUNT][MIX_INPUTS];
|
|
||||||
xc_ptr mix_mult;
|
|
||||||
#define write_word_to_mix_mult(x,y,val) write_via_xc_ptr_indexed(mix_mult,((x)*MIX_INPUTS)+(y), val)
|
|
||||||
#define mix_mult_slice(x) (mix_mult + x * MIX_INPUTS * sizeof(int))
|
|
||||||
#ifndef FAST_MIXER
|
|
||||||
int mix_map_array[MAX_MIX_COUNT][MIX_INPUTS];
|
|
||||||
xc_ptr mix_map;
|
|
||||||
#define write_word_to_mix_map(x,y,val) write_via_xc_ptr_indexed(mix_map,((x)*MIX_INPUTS)+(y), val)
|
|
||||||
#define mix_map_slice(x) (mix_map + x * MIX_INPUTS * sizeof(int))
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
int volatile * const unsafe mix_mult = mix_mult_array;
|
||||||
|
#if (FAST_MIXER == 0)
|
||||||
|
int volatile * const unsafe mix_map = mix_map_array;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#define slice(a, i) (a + i * MIX_INPUTS)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined (LEVEL_METER_HOST) || defined(LEVEL_METER_LEDS)
|
||||||
/* Arrays for level data */
|
/* Arrays for level data */
|
||||||
int samples_to_host_inputs[NUM_USB_CHAN_IN]; /* Audio transmitted to host i.e. device inputs */
|
int samples_to_host_inputs[NUM_USB_CHAN_IN]; /* Audio transmitted to host i.e. device inputs */
|
||||||
xc_ptr samples_to_host_inputs_ptr;
|
xc_ptr samples_to_host_inputs_ptr;
|
||||||
@@ -77,19 +94,6 @@ static int samples_from_host_streams[NUM_USB_CHAN_OUT]; /* Peak samples for audi
|
|||||||
static int samples_mixer_outputs[MAX_MIX_COUNT]; /* Peak samples out of the mixer */
|
static int samples_mixer_outputs[MAX_MIX_COUNT]; /* Peak samples out of the mixer */
|
||||||
xc_ptr samples_mixer_outputs_ptr;
|
xc_ptr samples_mixer_outputs_ptr;
|
||||||
|
|
||||||
#if 0
|
|
||||||
#pragma xta command "add exclusion mixer1_rate_change"
|
|
||||||
#pragma xta command "analyse path mixer1_req mixer1_req"
|
|
||||||
#pragma xta command "set required - 10400 ns" /* 96kHz */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
#pragma xta command "add exclusion mixer2_rate_change"
|
|
||||||
#pragma xta command "analyse path mixer2_req mixer2_req"
|
|
||||||
#pragma xta command "set required - 10400 ns" /* 96kHz */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined (LEVEL_METER_LEDS) || defined (LEVEL_METER_HOST)
|
|
||||||
static inline void ComputeMixerLevel(int sample, int i)
|
static inline void ComputeMixerLevel(int sample, int i)
|
||||||
{
|
{
|
||||||
int x;
|
int x;
|
||||||
@@ -108,42 +112,40 @@ static inline void ComputeMixerLevel(int sample, int i)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef FAST_MIXER
|
|
||||||
|
#if (FAST_MIXER)
|
||||||
void setPtr(int src, int dst, int mix);
|
void setPtr(int src, int dst, int mix);
|
||||||
int doMix0(xc_ptr samples, xc_ptr mult);
|
int doMix0(volatile int * const unsafe samples, volatile int * const unsafe mult);
|
||||||
int doMix1(xc_ptr samples, xc_ptr mult);
|
int doMix1(volatile int * const unsafe samples, volatile int * const unsafe mult);
|
||||||
int doMix2(xc_ptr samples, xc_ptr mult);
|
int doMix2(volatile int * const unsafe samples, volatile int * const unsafe mult);
|
||||||
int doMix3(xc_ptr samples, xc_ptr mult);
|
int doMix3(volatile int * const unsafe samples, volatile int * const unsafe mult);
|
||||||
int doMix4(xc_ptr samples, xc_ptr mult);
|
int doMix4(volatile int * const unsafe samples, volatile int * const unsafe mult);
|
||||||
int doMix5(xc_ptr samples, xc_ptr mult);
|
int doMix5(volatile int * const unsafe samples, volatile int * const unsafe mult);
|
||||||
int doMix6(xc_ptr samples, xc_ptr mult);
|
int doMix6(volatile int * const unsafe samples, volatile int * const unsafe mult);
|
||||||
int doMix7(xc_ptr samples, xc_ptr mult);
|
int doMix7(volatile int * const unsafe samples, volatile int * const unsafe mult);
|
||||||
int doMix8(xc_ptr samples, xc_ptr mult);
|
|
||||||
#else
|
#else
|
||||||
/* DO NOT inline, causes 10.4.2 tools to add extra loads in loop */
|
|
||||||
/* At 18 x 12dB we could get 64 x bigger */
|
|
||||||
#pragma unsafe arrays
|
#pragma unsafe arrays
|
||||||
static inline int doMix(xc_ptr samples, xc_ptr ptr, xc_ptr mult)
|
static inline int doMix(volatile int * unsafe samples, volatile int * unsafe const mixMap, volatile int * const unsafe mult)
|
||||||
{
|
{
|
||||||
int h=0;
|
int h=0;
|
||||||
int l=0;
|
int l=0;
|
||||||
|
|
||||||
/* By breaking up the loop we keep things in the encoding for ldw (0-11) */
|
|
||||||
#pragma loop unroll
|
#pragma loop unroll
|
||||||
for (int i=0; i<MIX_INPUTS; i++)
|
for (int i=0; i<MIX_INPUTS; i++)
|
||||||
{
|
unsafe{
|
||||||
int sample;
|
int sample;
|
||||||
int index;
|
int source;
|
||||||
int m;
|
int weight;
|
||||||
read_via_xc_ptr_indexed(index, ptr, i);
|
read_via_xc_ptr_indexed(source, mixMap, i);
|
||||||
read_via_xc_ptr_indexed(sample,samples,index);
|
sample = samples[source];
|
||||||
read_via_xc_ptr_indexed(m, mult, i);
|
read_via_xc_ptr_indexed(weight, mult, i);
|
||||||
{h,l} = macs(sample, m, h, l);
|
|
||||||
|
|
||||||
|
{h,l} = macs(sample, weight, h, l);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 1
|
|
||||||
/* Perform saturation */
|
/* Perform saturation */
|
||||||
l = sext(h, 25);
|
l = sext(h, XUA_MIXER_MULT_FRAC_BITS);
|
||||||
|
|
||||||
if(l != h)
|
if(l != h)
|
||||||
{
|
{
|
||||||
@@ -152,15 +154,14 @@ static inline int doMix(xc_ptr samples, xc_ptr ptr, xc_ptr mult)
|
|||||||
else
|
else
|
||||||
h = (0x7fffff00>>7);
|
h = (0x7fffff00>>7);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
return h<<7;
|
return h<<7;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#pragma unsafe arrays
|
#pragma unsafe arrays
|
||||||
static inline void GiveSamplesToHost(chanend c, xc_ptr ptr, xc_ptr multIn)
|
static inline void GiveSamplesToHost(chanend c, volatile int * unsafe hostMap)
|
||||||
{
|
{
|
||||||
#if defined(IN_VOLUME_IN_MIXER) && defined(IN_VOLUME_AFTER_MIX)
|
#if (IN_VOLUME_IN_MIXER && IN_VOLUME_AFTER_MIX)
|
||||||
int mult;
|
int mult;
|
||||||
int h;
|
int h;
|
||||||
unsigned l;
|
unsigned l;
|
||||||
@@ -170,23 +171,26 @@ static inline void GiveSamplesToHost(chanend c, xc_ptr ptr, xc_ptr multIn)
|
|||||||
for (int i=0; i<NUM_USB_CHAN_IN; i++)
|
for (int i=0; i<NUM_USB_CHAN_IN; i++)
|
||||||
{
|
{
|
||||||
int sample;
|
int sample;
|
||||||
int index;
|
|
||||||
|
|
||||||
#if MAX_MIX_COUNT > 0
|
#if (MAX_MIX_COUNT > 0)
|
||||||
read_via_xc_ptr_indexed(index,ptr,i);
|
|
||||||
#else
|
|
||||||
index = i + NUM_USB_CHAN_OUT;
|
|
||||||
#endif
|
|
||||||
unsafe
|
unsafe
|
||||||
{
|
{
|
||||||
//read_via_xc_ptr_indexed(sample,samples,index);
|
sample = ptr_samples[hostMap[i]];
|
||||||
sample = ptr_samples[index];
|
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
sample = ptr_samples[i + NUM_USB_CHAN_OUT];
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(IN_VOLUME_IN_MIXER) && defined(IN_VOLUME_AFTER_MIX)
|
#if (IN_VOLUME_IN_MIXER && IN_VOLUME_AFTER_MIX)
|
||||||
#warning IN Vols in mixer, AFTER mix & map
|
#warning IN Vols in mixer, AFTER mix & map
|
||||||
//asm("ldw %0, %1[%2]":"=r"(mult):"r"(multIn),"r"(i));
|
|
||||||
read_via_xc_ptr_indexed(mult, multIn, i);
|
unsafe
|
||||||
|
{
|
||||||
|
mult = multIn[i];
|
||||||
|
}
|
||||||
{h, l} = macs(mult, sample, 0, 0);
|
{h, l} = macs(mult, sample, 0, 0);
|
||||||
|
|
||||||
//h <<= 3 done on other side */
|
//h <<= 3 done on other side */
|
||||||
@@ -209,7 +213,7 @@ static inline void GetSamplesFromHost(chanend c)
|
|||||||
for (int i=0; i<NUM_USB_CHAN_OUT; i++)
|
for (int i=0; i<NUM_USB_CHAN_OUT; i++)
|
||||||
unsafe {
|
unsafe {
|
||||||
int sample, x;
|
int sample, x;
|
||||||
#if defined(OUT_VOLUME_IN_MIXER) && !defined(OUT_VOLUME_AFTER_MIX)
|
#if (OUT_VOLUME_IN_MIXER && !OUT_VOLUME_AFTER_MIX)
|
||||||
int mult;
|
int mult;
|
||||||
int h;
|
int h;
|
||||||
unsigned l;
|
unsigned l;
|
||||||
@@ -226,50 +230,47 @@ static inline void GetSamplesFromHost(chanend c)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(OUT_VOLUME_IN_MIXER) && !defined(OUT_VOLUME_AFTER_MIX)
|
#if (OUT_VOLUME_IN_MIXER && !OUT_VOLUME_AFTER_MIX)
|
||||||
#warning OUT Vols in mixer, BEFORE mix & map
|
#warning OUT Vols in mixer, BEFORE mix & map
|
||||||
read_via_xc_ptr_indexed(mult, multOut, i);
|
mult = multOut[i];
|
||||||
{h, l} = macs(mult, sample, 0, 0);
|
{h, l} = macs(mult, sample, 0, 0);
|
||||||
h<<=3;
|
h<<=3;
|
||||||
#if (STREAM_FORMAT_OUTPUT_RESOLUTION_32BIT_USED == 1)
|
#if (STREAM_FORMAT_OUTPUT_RESOLUTION_32BIT_USED == 1)
|
||||||
h |= (l >>29)& 0x7; // Note: This step is not required if we assume sample depth is 24bit (rather than 32bit)
|
h |= (l >>29)& 0x7; // Note: This step is not required if we assume sample depth is 24bit (rather than 32bit)
|
||||||
// Note: We need all 32bits for Native DSD
|
// Note: We need all 32bits for Native DSD
|
||||||
|
#endif
|
||||||
|
sample = h;
|
||||||
#endif
|
#endif
|
||||||
write_via_xc_ptr_indexed(multOut, index, val);
|
|
||||||
write_via_xc_ptr_indexed(samples_array, i, h);
|
|
||||||
#else
|
|
||||||
ptr_samples[i] = sample;
|
ptr_samples[i] = sample;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma unsafe arrays
|
#pragma unsafe arrays
|
||||||
static inline void GiveSamplesToDevice(chanend c, xc_ptr ptr, xc_ptr multOut)
|
static inline void GiveSamplesToDevice(chanend c, volatile int * unsafe deviceMap)
|
||||||
{
|
{
|
||||||
#if(NUM_USB_CHAN_OUT == 0)
|
#if (NUM_USB_CHAN_OUT == 0)
|
||||||
outuint(c, 0);
|
outuint(c, 0);
|
||||||
#else
|
#else
|
||||||
#pragma loop unroll
|
#pragma loop unroll
|
||||||
for (int i=0; i<NUM_USB_CHAN_OUT; i++)
|
for (int i=0; i<NUM_USB_CHAN_OUT; i++)
|
||||||
{
|
{
|
||||||
int sample, x;
|
int sample, x;
|
||||||
#if defined(OUT_VOLUME_IN_MIXER) && defined(OUT_VOLUME_AFTER_MIX)
|
#if (OUT_VOLUME_IN_MIXER && OUT_VOLUME_AFTER_MIX)
|
||||||
int mult;
|
int mult;
|
||||||
int h;
|
int h;
|
||||||
unsigned l;
|
unsigned l;
|
||||||
#endif
|
#endif
|
||||||
int index;
|
int index;
|
||||||
|
|
||||||
#if MAX_MIX_COUNT > 0
|
#if (MAX_MIX_COUNT > 0)
|
||||||
/* If mixer turned on sort out the channel mapping */
|
/* If mixer turned on sort out the channel mapping */
|
||||||
|
unsafe
|
||||||
/* Read pointer to sample from the map */
|
{
|
||||||
read_via_xc_ptr_indexed(index, ptr, i);
|
/* Read index to sample from the map then Read the actual sample value */
|
||||||
|
sample = ptr_samples[deviceMap[i]];
|
||||||
/* Read the actual sample value */
|
}
|
||||||
read_via_xc_ptr_indexed(sample, samples, index);
|
|
||||||
#else
|
#else
|
||||||
unsafe
|
unsafe
|
||||||
{
|
{
|
||||||
@@ -278,16 +279,19 @@ static inline void GiveSamplesToDevice(chanend c, xc_ptr ptr, xc_ptr multOut)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(OUT_VOLUME_IN_MIXER) && defined(OUT_VOLUME_AFTER_MIX)
|
#if (OUT_VOLUME_IN_MIXER && OUT_VOLUME_AFTER_MIX)
|
||||||
/* Do volume control processing */
|
/* Do volume control processing */
|
||||||
#warning OUT Vols in mixer, AFTER mix & map
|
#warning OUT Vols in mixer, AFTER mix & map
|
||||||
read_via_xc_ptr_indexed(mult, multOut, i);
|
unsafe
|
||||||
|
{
|
||||||
|
mult = multOut[i];
|
||||||
|
}
|
||||||
|
|
||||||
{h, l} = macs(mult, sample, 0, 0);
|
{h, l} = macs(mult, sample, 0, 0);
|
||||||
h<<=3; // Shift used to be done in audio thread but now done here incase of 32bit support
|
h<<=3; // Shift used to be done in audio thread but now done here incase of 32bit support
|
||||||
#error
|
|
||||||
#if (STREAM_FORMAT_OUTPUT_RESOLUTION_32BIT_USED == 1)
|
#if (STREAM_FORMAT_OUTPUT_RESOLUTION_32BIT_USED == 1)
|
||||||
h |= (l >>29)& 0x7; // Note: This step is not required if we assume sample depth is 24bit (rather than 32bit)
|
h |= (l >>29)& 0x7; // Note: This step is not required if we assume sample depth is 24bit (rather than 32bit)
|
||||||
// Note: We need all 32bits for Native DSD
|
// Note: We need all 32bits for Native DSD
|
||||||
#endif
|
#endif
|
||||||
outuint(c, h);
|
outuint(c, h);
|
||||||
#else
|
#else
|
||||||
@@ -300,14 +304,14 @@ static inline void GiveSamplesToDevice(chanend c, xc_ptr ptr, xc_ptr multOut)
|
|||||||
#pragma unsafe arrays
|
#pragma unsafe arrays
|
||||||
static inline void GetSamplesFromDevice(chanend c)
|
static inline void GetSamplesFromDevice(chanend c)
|
||||||
{
|
{
|
||||||
#if defined(IN_VOLUME_IN_MIXER) && !defined(IN_VOLUME_AFTER_MIX)
|
#if (IN_VOLUME_IN_MIXER && IN_VOLUME_AFTER_MIX)
|
||||||
int mult;
|
int mult;
|
||||||
int h;
|
int h;
|
||||||
unsigned l;
|
unsigned l;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#pragma loop unroll
|
#pragma loop unroll
|
||||||
for (int i=0;i<NUM_USB_CHAN_IN;i++)
|
for (int i=0; i<NUM_USB_CHAN_IN; i++)
|
||||||
{
|
{
|
||||||
int sample;
|
int sample;
|
||||||
int x;
|
int x;
|
||||||
@@ -327,22 +331,24 @@ static inline void GetSamplesFromDevice(chanend c)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(IN_VOLUME_IN_MIXER) && !defined(IN_VOLUME_AFTER_MIX)
|
#if (IN_VOLUME_IN_MIXER && IN_VOLUME_AFTER_MIX)
|
||||||
/* Read relevant multiplier */
|
/* Volume processing - read relevant multiplier */
|
||||||
read_via_xc_ptr_indexed(mult, multIn, i);
|
unsafe
|
||||||
|
{
|
||||||
|
mult = multIn[i];
|
||||||
|
}
|
||||||
|
|
||||||
/* Do the multiply */
|
/* Do the multiply */
|
||||||
{h, l} = macs(mult, sample, 0, 0);
|
{h, l} = macs(mult, sample, 0, 0);
|
||||||
h <<=3;
|
h <<= 3;
|
||||||
write_via_xc_ptr_indexed(samples_array, NUM_USB_CHAN_OUT+i, h);
|
sample = h;
|
||||||
#else
|
#endif
|
||||||
/* No volume processing */
|
|
||||||
unsafe
|
unsafe
|
||||||
{
|
{
|
||||||
ptr_samples[NUM_USB_CHAN_OUT + i] = sample;
|
assert((XUA_MIXER_OFFSET_IN + i) < (NUM_USB_CHAN_IN + NUM_USB_CHAN_OUT));
|
||||||
|
ptr_samples[XUA_MIXER_OFFSET_IN + i] = sample;
|
||||||
}
|
}
|
||||||
#endif
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mixer1_mix2_flag = (DEFAULT_FREQ > 96000);
|
static int mixer1_mix2_flag = (DEFAULT_FREQ > 96000);
|
||||||
@@ -353,12 +359,14 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2)
|
|||||||
#if (MAX_MIX_COUNT > 0)
|
#if (MAX_MIX_COUNT > 0)
|
||||||
int mixed;
|
int mixed;
|
||||||
#endif
|
#endif
|
||||||
|
#if (MAX_MIX_COUNT > 0) || (IN_VOLUME_IN_MIXER) || (OUT_VOLUME_IN_MIXER) || defined (LEVEL_METER_HOST) || defined(LEVEL_METER_LEDS)
|
||||||
unsigned cmd;
|
unsigned cmd;
|
||||||
|
unsigned char ct;
|
||||||
|
#endif
|
||||||
unsigned request = 0;
|
unsigned request = 0;
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
#pragma xta endpoint "mixer1_req"
|
|
||||||
/* Request from audio()/mixer2() */
|
/* Request from audio()/mixer2() */
|
||||||
request = inuint(c_mixer2);
|
request = inuint(c_mixer2);
|
||||||
|
|
||||||
@@ -369,28 +377,62 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2)
|
|||||||
/* Sync */
|
/* Sync */
|
||||||
outuint(c_mixer2, 0);
|
outuint(c_mixer2, 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Between request to decouple and response ~ 400nS latency for interrupt to fire */
|
/* Between request to decouple and response ~ 400nS latency for interrupt to fire */
|
||||||
|
|
||||||
|
#if (MAX_MIX_COUNT > 0) || (IN_VOLUME_IN_MIXER) || (OUT_VOLUME_IN_MIXER) || defined (LEVEL_METER_HOST) || defined(LEVEL_METER_LEDS)
|
||||||
select
|
select
|
||||||
{
|
{
|
||||||
case inuint_byref(c_mix_ctl, cmd):
|
/* Check if EP0 intends to send us a control command */
|
||||||
|
case inct_byref(c_mix_ctl, ct):
|
||||||
{
|
{
|
||||||
int mix, index, val;
|
int mix, index, val;
|
||||||
|
|
||||||
|
/* Handshake back to tell EP0 we are ready for an update */
|
||||||
|
outct(c_mix_ctl, XS1_CT_END);
|
||||||
|
|
||||||
|
/* Receive command from EP0 */
|
||||||
|
cmd = inuint(c_mix_ctl);
|
||||||
|
|
||||||
|
/* Interpret control command */
|
||||||
switch (cmd)
|
switch (cmd)
|
||||||
{
|
{
|
||||||
#if MAX_MIX_COUNT > 0
|
#if (MAX_MIX_COUNT > 0)
|
||||||
case SET_SAMPLES_TO_HOST_MAP:
|
case SET_SAMPLES_TO_HOST_MAP:
|
||||||
index = inuint(c_mix_ctl);
|
{
|
||||||
val = inuint(c_mix_ctl);
|
int dst = inuint(c_mix_ctl);
|
||||||
inct(c_mix_ctl);
|
int src = inuint(c_mix_ctl);
|
||||||
write_via_xc_ptr_indexed(samples_to_host_map, index, val);
|
inct(c_mix_ctl);
|
||||||
|
|
||||||
|
assert((dst < NUM_USB_CHAN_IN) && msg("Host map destination out of range"));
|
||||||
|
assert((src < SOURCE_COUNT) && msg("Host map source out of range"));
|
||||||
|
|
||||||
|
if((dst < NUM_USB_CHAN_IN) && (src < SOURCE_COUNT))
|
||||||
|
{
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
samples_to_host_map[dst] = src;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SET_SAMPLES_TO_DEVICE_MAP:
|
case SET_SAMPLES_TO_DEVICE_MAP:
|
||||||
index = inuint(c_mix_ctl);
|
{
|
||||||
val = inuint(c_mix_ctl);
|
int dst = inuint(c_mix_ctl);
|
||||||
inct(c_mix_ctl);
|
int src = inuint(c_mix_ctl);
|
||||||
write_via_xc_ptr_indexed(samples_to_device_map,index,val);
|
inct(c_mix_ctl);
|
||||||
|
|
||||||
|
assert((dst < NUM_USB_CHAN_OUT) && msg("Device map destination out of range"));
|
||||||
|
assert((src < SOURCE_COUNT) && msg("Device map source out of range"));
|
||||||
|
|
||||||
|
if((dst < NUM_USB_CHAN_OUT) && (src < SOURCE_COUNT))
|
||||||
|
{
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
samples_to_device_map[dst] = src;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SET_MIX_MULT:
|
case SET_MIX_MULT:
|
||||||
@@ -399,40 +441,80 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2)
|
|||||||
val = inuint(c_mix_ctl);
|
val = inuint(c_mix_ctl);
|
||||||
inct(c_mix_ctl);
|
inct(c_mix_ctl);
|
||||||
|
|
||||||
write_word_to_mix_mult(mix, index, val);
|
assert((mix < MAX_MIX_COUNT) && msg("Mix mult mix out of range"));
|
||||||
|
assert((index < MIX_INPUTS) && msg("Mix mult index out of range"));
|
||||||
|
|
||||||
|
if((index < MIX_INPUTS) && (mix < MAX_MIX_COUNT))
|
||||||
|
{
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
mix_mult[(mix * MIX_INPUTS) + index] = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SET_MIX_MAP:
|
case SET_MIX_MAP:
|
||||||
mix = inuint(c_mix_ctl);
|
{
|
||||||
index = inuint(c_mix_ctl); /* mixer input */
|
unsigned mix = inuint(c_mix_ctl);
|
||||||
val = inuint(c_mix_ctl); /* source */
|
unsigned input = inuint(c_mix_ctl); /* mixer input */
|
||||||
inct(c_mix_ctl);
|
unsigned source = inuint(c_mix_ctl); /* source */
|
||||||
#ifdef FAST_MIXER
|
inct(c_mix_ctl);
|
||||||
setPtr(index, val, mix);
|
|
||||||
|
assert((mix < MAX_MIX_COUNT) && msg("Mix map mix out of range"));
|
||||||
|
assert((input < MIX_INPUTS) && msg("Mix map index out of range"));
|
||||||
|
assert((source < SOURCE_COUNT) && msg("Mix map source out of range"));
|
||||||
|
|
||||||
|
if((input < MIX_INPUTS) && (mix < MAX_MIX_COUNT) && (source < SOURCE_COUNT))
|
||||||
|
{
|
||||||
|
#if (FAST_MIXER)
|
||||||
|
setPtr(input, source, mix);
|
||||||
#else
|
#else
|
||||||
write_word_to_mix_map(mix, index, val);
|
unsafe
|
||||||
|
{
|
||||||
|
mix_map[(mix * MIX_INPUTS) + input] = source;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
#endif /* if MAX_MIX_COUNT > 0 */
|
#endif /* if MAX_MIX_COUNT > 0 */
|
||||||
#ifdef IN_VOLUME_IN_MIXER
|
|
||||||
|
#if (IN_VOLUME_IN_MIXER)
|
||||||
case SET_MIX_IN_VOL:
|
case SET_MIX_IN_VOL:
|
||||||
index = inuint(c_mix_ctl);
|
index = inuint(c_mix_ctl);
|
||||||
val = inuint(c_mix_ctl);
|
val = inuint(c_mix_ctl);
|
||||||
inct(c_mix_ctl);
|
inct(c_mix_ctl);
|
||||||
|
|
||||||
write_via_xc_ptr_indexed(multIn, index, val);
|
assert((index < (NUM_USB_CHAN_IN + 1)) && msg("In volume index out of range"));
|
||||||
|
|
||||||
|
if(index < NUM_USB_CHAN_IN + 1)
|
||||||
|
{
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
multIn[index] = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef OUT_VOLUME_IN_MIXER
|
#if (OUT_VOLUME_IN_MIXER)
|
||||||
case SET_MIX_OUT_VOL:
|
case SET_MIX_OUT_VOL:
|
||||||
index = inuint(c_mix_ctl);
|
index = inuint(c_mix_ctl);
|
||||||
val = inuint(c_mix_ctl);
|
val = inuint(c_mix_ctl);
|
||||||
inct(c_mix_ctl);
|
inct(c_mix_ctl);
|
||||||
|
|
||||||
write_via_xc_ptr_indexed(multOut, index, val);
|
assert((index < (NUM_USB_CHAN_OUT + 1)) && msg("Out volume index out of range"));
|
||||||
|
|
||||||
|
if(index < NUM_USB_CHAN_OUT + 1)
|
||||||
|
{
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
multOut[index] = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined (LEVEL_METER_HOST) || defined(LEVEL_METER_LEDS)
|
||||||
/* Peak samples of stream from host to device (via USB) */
|
/* Peak samples of stream from host to device (via USB) */
|
||||||
case GET_STREAM_LEVELS:
|
case GET_STREAM_LEVELS:
|
||||||
index = inuint(c_mix_ctl);
|
index = inuint(c_mix_ctl);
|
||||||
@@ -441,42 +523,6 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2)
|
|||||||
outct(c_mix_ctl, XS1_CT_END);
|
outct(c_mix_ctl, XS1_CT_END);
|
||||||
samples_from_host_streams[index] = 0;
|
samples_from_host_streams[index] = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GET_INPUT_LEVELS:
|
|
||||||
index = inuint(c_mix_ctl);
|
|
||||||
chkct(c_mix_ctl, XS1_CT_END);
|
|
||||||
#ifdef LEVEL_METER_LEDS
|
|
||||||
/* Level LEDS process reseting samples_to_host_inputs
|
|
||||||
* Other side makes sure we don't miss a peak */
|
|
||||||
//val = samples_to_host_inputs_buff[index];
|
|
||||||
//samples_to_host_inputs_buff[index] = 0;
|
|
||||||
/* Access funcs used to avoid disjointness check */
|
|
||||||
read_via_xc_ptr_indexed(val, samples_to_host_inputs_buff_ptr, index);
|
|
||||||
write_via_xc_ptr_indexed(samples_to_host_inputs_buff_ptr, index, 0);
|
|
||||||
#else
|
|
||||||
/* We dont have a level LEDs process, so reset ourselves */
|
|
||||||
//val = samples_to_host_inputs[index];
|
|
||||||
//samples_to_host_inputs[index] = 0;
|
|
||||||
/* Access funcs used to avoid disjointness check */
|
|
||||||
read_via_xc_ptr_indexed(val, samples_to_host_inputs_ptr, index);
|
|
||||||
write_via_xc_ptr_indexed(samples_to_host_inputs_ptr, index, 0);
|
|
||||||
#endif
|
|
||||||
outuint(c_mix_ctl, val);
|
|
||||||
outct(c_mix_ctl, XS1_CT_END);
|
|
||||||
break;
|
|
||||||
|
|
||||||
#if (MAX_MIX_COUNT > 0)
|
|
||||||
/* Peak samples of the mixer outputs */
|
|
||||||
case GET_OUTPUT_LEVELS:
|
|
||||||
index = inuint(c_mix_ctl);
|
|
||||||
chkct(c_mix_ctl, XS1_CT_END);
|
|
||||||
read_via_xc_ptr_indexed(val, samples_mixer_outputs, index);
|
|
||||||
write_via_xc_ptr_indexed(samples_mixer_outputs, index, 0);
|
|
||||||
//val = samples_mixer_outputs[index];
|
|
||||||
//samples_mixer_outputs[index] = 0;
|
|
||||||
outuint(c_mix_ctl, val);
|
|
||||||
outct(c_mix_ctl, XS1_CT_END);
|
|
||||||
break;
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -484,14 +530,13 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2)
|
|||||||
default:
|
default:
|
||||||
/* Select default */
|
/* Select default */
|
||||||
break;
|
break;
|
||||||
}
|
} // select
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Get response from decouple */
|
/* Get response from decouple */
|
||||||
if(testct(c_host))
|
if(testct(c_host))
|
||||||
{
|
{
|
||||||
int sampFreq;
|
int sampFreq;
|
||||||
#pragma xta endpoint "mixer1_rate_change"
|
|
||||||
unsigned command = inct(c_host);
|
unsigned command = inct(c_host);
|
||||||
|
|
||||||
switch(command)
|
switch(command)
|
||||||
@@ -520,9 +565,8 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2)
|
|||||||
|
|
||||||
#pragma loop unroll
|
#pragma loop unroll
|
||||||
/* Reset the mix values back to 0 */
|
/* Reset the mix values back to 0 */
|
||||||
for (int i=0;i<MAX_MIX_COUNT;i++)
|
for (int i=0; i<MAX_MIX_COUNT; i++)
|
||||||
{
|
{
|
||||||
//write_via_xc_ptr_indexed(samples, (NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + i), 0);
|
|
||||||
unsafe
|
unsafe
|
||||||
{
|
{
|
||||||
ptr_samples[NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + i] = 0;
|
ptr_samples[NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + i] = 0;
|
||||||
@@ -535,21 +579,24 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#if MAX_MIX_COUNT > 0
|
#if (MAX_MIX_COUNT > 0)
|
||||||
GetSamplesFromHost(c_host);
|
GetSamplesFromHost(c_host);
|
||||||
GiveSamplesToHost(c_host, samples_to_host_map, multIn);
|
GiveSamplesToHost(c_host, samples_to_host_map);
|
||||||
|
|
||||||
/* Sync with mixer 2 (once it has swapped samples with audiohub) */
|
/* Sync with mixer 2 (once it has swapped samples with audiohub) */
|
||||||
outuint(c_mixer2, 0);
|
outuint(c_mixer2, 0);
|
||||||
inuint(c_mixer2);
|
inuint(c_mixer2);
|
||||||
|
|
||||||
/* Do the mixing */
|
/* Do the mixing */
|
||||||
#ifdef FAST_MIXER
|
unsafe
|
||||||
mixed = doMix0(samples, mix_mult_slice(0));
|
{
|
||||||
|
#if (FAST_MIXER)
|
||||||
|
mixed = doMix0(ptr_samples, slice(mix_mult, 0));
|
||||||
#else
|
#else
|
||||||
mixed = doMix(samples, mix_map_slice(0),mix_mult_slice(0));
|
mixed = doMix(ptr_samples, slice(mix_map, 0), slice(mix_mult, 0));
|
||||||
#endif
|
#endif
|
||||||
write_via_xc_ptr_indexed(samples_array, (NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + 0), mixed);
|
ptr_samples[NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + 0] = mixed;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined (LEVEL_METER_HOST) || defined(LEVEL_METER_LEDS)
|
#if defined (LEVEL_METER_HOST) || defined(LEVEL_METER_LEDS)
|
||||||
ComputeMixerLevel(mixed, 0);
|
ComputeMixerLevel(mixed, 0);
|
||||||
@@ -560,40 +607,46 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2)
|
|||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
|
||||||
#if MAX_MIX_COUNT > 2
|
#if (MAX_MIX_COUNT > 2)
|
||||||
#ifdef FAST_MIXER
|
unsafe
|
||||||
mixed = doMix2(samples, mix_mult_slice(2));
|
{
|
||||||
|
#if (FAST_MIXER)
|
||||||
|
mixed = doMix2(ptr_samples, slice(mix_mult, 2));
|
||||||
#else
|
#else
|
||||||
mixed = doMix(samples, mix_map_slice(2),mix_mult_slice(2));
|
mixed = doMix(ptr_samples, slice(mix_map, 2), slice(mix_mult, 2));
|
||||||
#endif
|
#endif
|
||||||
write_via_xc_ptr_indexed(samples_array, (NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + 2), mixed);
|
ptr_samples[NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + 2] = mixed;
|
||||||
|
}
|
||||||
#if defined (LEVEL_METER_HOST) || defined(LEVEL_METER_LEDS)
|
#if defined (LEVEL_METER_HOST) || defined(LEVEL_METER_LEDS)
|
||||||
ComputeMixerLevel(mixed, 2);
|
ComputeMixerLevel(mixed, 2);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if MAX_MIX_COUNT > 4
|
#if (MAX_MIX_COUNT > 4)
|
||||||
#ifdef FAST_MIXER
|
unsafe
|
||||||
mixed = doMix4(samples, mix_mult_slice(4));
|
{
|
||||||
|
#if (FAST_MIXER)
|
||||||
|
mixed = doMix4(ptr_samples, slice(mix_mult, 4));
|
||||||
#else
|
#else
|
||||||
mixed = doMix(samples, mix_map_slice(4),mix_mult_slice(4));
|
mixed = doMix(ptr_samples, slice(mix_map, 4), slice(mix_mult, 4));
|
||||||
#endif
|
#endif
|
||||||
write_via_xc_ptr_indexed(samples_array, (NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + 4), mixed);
|
ptr_samples[XUA_MIXER_OFFSET_MIX + 4] = mixed;
|
||||||
|
}
|
||||||
#if defined (LEVEL_METER_HOST) || defined(LEVEL_METER_LEDS)
|
#if defined (LEVEL_METER_HOST) || defined(LEVEL_METER_LEDS)
|
||||||
ComputeMixerLevel(mixed, 4);
|
ComputeMixerLevel(mixed, 4);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if MAX_MIX_COUNT > 6
|
#if (MAX_MIX_COUNT > 6)
|
||||||
#ifdef FAST_MIXER
|
unsafe
|
||||||
mixed = doMix6(samples, mix_mult_slice(6));
|
{
|
||||||
|
#if (FAST_MIXER)
|
||||||
|
mixed = doMix6(ptr_samples, slice(mix_mult, 6));
|
||||||
#else
|
#else
|
||||||
mixed = doMix(samples, mix_map_slice(6),mix_mult_slice(6));
|
mixed = doMix(ptr_samples, slice(mix_map, 6), slice(mix_mult, 6));
|
||||||
#endif
|
#endif
|
||||||
write_via_xc_ptr_indexed(samples, (NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + 6), mixed);
|
ptr_samples[XUA_MIXER_OFFSET_MIX + 6] = mixed;
|
||||||
|
}
|
||||||
#if defined (LEVEL_METER_HOST) || defined(LEVEL_METER_LEDS)
|
#if defined (LEVEL_METER_HOST) || defined(LEVEL_METER_LEDS)
|
||||||
ComputeMixerLevel(mixed, 6);
|
ComputeMixerLevel(mixed, 6);
|
||||||
#endif
|
#endif
|
||||||
@@ -601,10 +654,10 @@ static void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2)
|
|||||||
}
|
}
|
||||||
#else /* IF MAX_MIX_COUNT > 0 */
|
#else /* IF MAX_MIX_COUNT > 0 */
|
||||||
/* No mixes, this thread runs on its own doing just volume */
|
/* No mixes, this thread runs on its own doing just volume */
|
||||||
GiveSamplesToDevice(c_mixer2, samples_to_device_map, multOut);
|
GiveSamplesToDevice(c_mixer2, samples_to_device_map);
|
||||||
GetSamplesFromDevice(c_mixer2);
|
GetSamplesFromDevice(c_mixer2);
|
||||||
GetSamplesFromHost(c_host);
|
GetSamplesFromHost(c_host);
|
||||||
GiveSamplesToHost(c_host, samples_to_host_map, multIn);
|
GiveSamplesToHost(c_host, samples_to_host_map);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -621,7 +674,6 @@ static void mixer2(chanend c_mixer1, chanend c_audio)
|
|||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
#pragma xta endpoint "mixer2_req"
|
|
||||||
request = inuint(c_audio);
|
request = inuint(c_audio);
|
||||||
|
|
||||||
/* Forward the request on */
|
/* Forward the request on */
|
||||||
@@ -633,7 +685,6 @@ static void mixer2(chanend c_mixer1, chanend c_audio)
|
|||||||
if(testct(c_mixer1))
|
if(testct(c_mixer1))
|
||||||
{
|
{
|
||||||
int sampFreq;
|
int sampFreq;
|
||||||
#pragma xta endpoint "mixer2_rate_change"
|
|
||||||
unsigned command = inct(c_mixer1);
|
unsigned command = inct(c_mixer1);
|
||||||
|
|
||||||
switch(command)
|
switch(command)
|
||||||
@@ -660,8 +711,8 @@ static void mixer2(chanend c_mixer1, chanend c_audio)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (int i=0;i<MAX_MIX_COUNT;i++)
|
for (int i=0;i<MAX_MIX_COUNT;i++)
|
||||||
{
|
unsafe{
|
||||||
write_via_xc_ptr_indexed(samples, (NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + i), 0);
|
ptr_samples[NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait for handshake and pass on */
|
/* Wait for handshake and pass on */
|
||||||
@@ -670,7 +721,7 @@ static void mixer2(chanend c_mixer1, chanend c_audio)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GiveSamplesToDevice(c_audio, samples_to_device_map, multOut);
|
GiveSamplesToDevice(c_audio, samples_to_device_map);
|
||||||
GetSamplesFromDevice(c_audio);
|
GetSamplesFromDevice(c_audio);
|
||||||
|
|
||||||
/* Sync with mixer 1 (once it has swapped samples with the buffering sub-system) */
|
/* Sync with mixer 1 (once it has swapped samples with the buffering sub-system) */
|
||||||
@@ -678,61 +729,67 @@ static void mixer2(chanend c_mixer1, chanend c_audio)
|
|||||||
outuint(c_mixer1, 0);
|
outuint(c_mixer1, 0);
|
||||||
|
|
||||||
/* Do the mixing */
|
/* Do the mixing */
|
||||||
#if MAX_MIX_COUNT > 1
|
#if (MAX_MIX_COUNT > 1)
|
||||||
#ifdef FAST_MIXER
|
unsafe
|
||||||
mixed = doMix1(samples, mix_mult_slice(1));
|
{
|
||||||
|
#if (FAST_MIXER)
|
||||||
|
mixed = doMix1(ptr_samples, slice(mix_mult, 1));
|
||||||
#else
|
#else
|
||||||
mixed = doMix(samples, mix_map_slice(1),mix_mult_slice(1));
|
mixed = doMix(ptr_samples, slice(mix_map, 1), slice(mix_mult, 1));
|
||||||
#endif
|
#endif
|
||||||
|
ptr_samples[NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + 1] = mixed;
|
||||||
write_via_xc_ptr_indexed(samples, (NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + 1), mixed);
|
}
|
||||||
|
|
||||||
#if defined (LEVEL_METER_HOST) || defined(LEVEL_METER_LEDS)
|
#if defined (LEVEL_METER_HOST) || defined(LEVEL_METER_LEDS)
|
||||||
ComputeMixerLevel(mixed, 1);
|
ComputeMixerLevel(mixed, 1);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#if (MAX_FREQ > 96000)
|
#if (MAX_FREQ > 96000)
|
||||||
/* Fewer mixes when running higher than 96kHz */
|
/* Fewer mixes when running higher than 96kHz */
|
||||||
if (!mixer2_mix2_flag)
|
if (!mixer2_mix2_flag)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
#if MAX_MIX_COUNT > 3
|
#if (MAX_MIX_COUNT > 3)
|
||||||
#ifdef FAST_MIXER
|
unsafe
|
||||||
mixed = doMix3(samples, mix_mult_slice(3));
|
{
|
||||||
|
#if (FAST_MIXER)
|
||||||
|
mixed = doMix3(ptr_samples, slice(mix_mult, 3));
|
||||||
#else
|
#else
|
||||||
mixed = doMix(samples, mix_map_slice(3),mix_mult_slice(3));
|
mixed = doMix(ptr_samples, slice(mix_map, 3), slice(mix_mult, 3));
|
||||||
#endif
|
#endif
|
||||||
|
ptr_samples[NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + 3] = mixed;
|
||||||
write_via_xc_ptr_indexed(samples, (NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + 3), mixed);
|
}
|
||||||
|
|
||||||
#if defined (LEVEL_METER_HOST) || defined(LEVEL_METER_LEDS)
|
#if defined (LEVEL_METER_HOST) || defined(LEVEL_METER_LEDS)
|
||||||
ComputeMixerLevel(mixed, 3);
|
ComputeMixerLevel(mixed, 3);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if MAX_MIX_COUNT > 5
|
#if (MAX_MIX_COUNT > 5)
|
||||||
#ifdef FAST_MIXER
|
unsafe
|
||||||
mixed = doMix5(samples, mix_mult_slice(5));
|
{
|
||||||
|
#if (FAST_MIXER)
|
||||||
|
mixed = doMix5(ptr_samples, slice(mix_mult, 5));
|
||||||
#else
|
#else
|
||||||
mixed = doMix(samples, mix_map_slice(5),mix_mult_slice(5));
|
mixed = doMix(ptr_samples, slice(mix_map, 5), slice(mix_mult, 5));
|
||||||
#endif
|
#endif
|
||||||
write_via_xc_ptr_indexed(samples, NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + 5, mixed);
|
ptr_samples[NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + 5] = mixed;
|
||||||
|
|
||||||
|
}
|
||||||
#if defined (LEVEL_METER_HOST) || defined(LEVEL_METER_LEDS)
|
#if defined (LEVEL_METER_HOST) || defined(LEVEL_METER_LEDS)
|
||||||
ComputeMixerLevel(mixed, 5);
|
ComputeMixerLevel(mixed, 5);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if MAX_MIX_COUNT > 7
|
#if (MAX_MIX_COUNT > 7)
|
||||||
#ifdef FAST_MIXER
|
unsafe
|
||||||
mixed = doMix7(samples, mix_mult_slice(7));
|
{
|
||||||
|
#if (FAST_MIXER)
|
||||||
|
mixed = doMix7(ptr_samples, slice(mix_mult, 7));
|
||||||
#else
|
#else
|
||||||
mixed = doMix(samples, mix_map_slice(7),mix_mult_slice(7));
|
mixed = doMix(ptr_samples, slice(mix_map, 7), slice(mix_mult, 7));
|
||||||
#endif
|
#endif
|
||||||
|
ptr_samples[NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + 7] = mixed;
|
||||||
write_via_xc_ptr_indexed(samples, NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + 7, mixed);
|
}
|
||||||
#if defined (LEVEL_METER_HOST) || defined(LEVEL_METER_LEDS)
|
#if defined (LEVEL_METER_HOST) || defined(LEVEL_METER_LEDS)
|
||||||
ComputeMixerLevel(mixed, 7);
|
ComputeMixerLevel(mixed, 7);
|
||||||
#endif
|
#endif
|
||||||
@@ -748,68 +805,52 @@ void mixer(chanend c_mix_in, chanend c_mix_out, chanend c_mix_ctl)
|
|||||||
#if (MAX_MIX_COUNT > 0)
|
#if (MAX_MIX_COUNT > 0)
|
||||||
chan c;
|
chan c;
|
||||||
#endif
|
#endif
|
||||||
multOut = array_to_xc_ptr((multOut_array,unsigned[]));
|
|
||||||
multIn = array_to_xc_ptr((multIn_array,unsigned[]));
|
|
||||||
|
|
||||||
samples = array_to_xc_ptr((samples_array,unsigned[]));
|
|
||||||
samples_to_host_map = array_to_xc_ptr((samples_to_host_map_array,unsigned[]));
|
|
||||||
samples_to_device_map = array_to_xc_ptr((samples_to_device_map_array,unsigned[]));
|
|
||||||
|
|
||||||
|
#if defined (LEVEL_METER_HOST) || defined(LEVEL_METER_LEDS)
|
||||||
samples_to_host_inputs_ptr = array_to_xc_ptr((samples_to_host_inputs, unsigned[]));
|
samples_to_host_inputs_ptr = array_to_xc_ptr((samples_to_host_inputs, unsigned[]));
|
||||||
#ifdef LEVEL_METER_LEDS
|
#ifdef LEVEL_METER_LEDS
|
||||||
samples_to_host_inputs_buff_ptr = array_to_xc_ptr((samples_to_host_inputs, unsigned[]));
|
samples_to_host_inputs_buff_ptr = array_to_xc_ptr((samples_to_host_inputs, unsigned[]));
|
||||||
#endif
|
#endif
|
||||||
samples_mixer_outputs_ptr = array_to_xc_ptr((samples_mixer_outputs, unsigned[]));
|
samples_mixer_outputs_ptr = array_to_xc_ptr((samples_mixer_outputs, unsigned[]));
|
||||||
|
|
||||||
#if MAX_MIX_COUNT >0
|
|
||||||
mix_mult = array_to_xc_ptr((mix_mult_array,unsigned[]));
|
|
||||||
#ifndef FAST_MIXER
|
|
||||||
mix_map = array_to_xc_ptr((mix_map_array,unsigned[]));
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (int i=0;i<NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + MAX_MIX_COUNT;i++)
|
for (int i=0;i<NUM_USB_CHAN_OUT + NUM_USB_CHAN_IN + MAX_MIX_COUNT;i++)
|
||||||
unsafe {
|
unsafe {
|
||||||
//write_via_xc_ptr_indexed(samples,i,0);
|
|
||||||
ptr_samples[i] = 0;
|
ptr_samples[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i=0; i<NUM_USB_CHAN_OUT; i++)
|
||||||
{
|
{
|
||||||
int num_mixes = DEFAULT_FREQ > 96000 ? 2 : MAX_MIX_COUNT;
|
samples_to_device_map_array[i] = i;
|
||||||
for (int i=0;i<NUM_USB_CHAN_OUT;i++)
|
|
||||||
{
|
|
||||||
//samples_to_device_map_array[i] = i;
|
|
||||||
asm("stw %0, %1[%2]":: "r"(i), "r"(samples_to_device_map), "r"(i));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef OUT_VOLUME_IN_MIXER
|
#if (OUT_VOLUME_IN_MIXER)
|
||||||
for (int i=0;i<NUM_USB_CHAN_OUT;i++)
|
for (int i=0; i<NUM_USB_CHAN_OUT; i++)
|
||||||
{
|
unsafe{
|
||||||
write_via_xc_ptr_indexed(multOut, i, MAX_VOL);
|
multOut[i] = MAX_VOLUME_MULT;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef IN_VOLUME_IN_MIXER
|
#if (IN_VOLUME_IN_MIXER)
|
||||||
for (int i=0;i<NUM_USB_CHAN_IN;i++)
|
for (int i=0; i<NUM_USB_CHAN_IN; i++)
|
||||||
{
|
unsafe{
|
||||||
write_via_xc_ptr_indexed(multIn, i, MAX_VOL);
|
multIn[i] = MAX_VOLUME_MULT;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (int i=0;i<NUM_USB_CHAN_IN;i++)
|
for (int i=0; i<NUM_USB_CHAN_IN; i++)
|
||||||
{
|
unsafe{
|
||||||
write_via_xc_ptr_indexed(samples_to_host_map, i, NUM_USB_CHAN_OUT + i);
|
samples_to_host_map[i] = XUA_MIXER_OFFSET_IN + i;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if MAX_MIX_COUNT> 0
|
#if (MAX_MIX_COUNT> 0)
|
||||||
for (int i=0;i<MAX_MIX_COUNT;i++)
|
for (int i=0;i<MAX_MIX_COUNT;i++)
|
||||||
for (int j=0;j<MIX_INPUTS;j++)
|
for (int j=0;j<MIX_INPUTS;j++)
|
||||||
{
|
unsafe{
|
||||||
#ifndef FAST_MIXER
|
#if (FAST_MIXER == 0)
|
||||||
write_word_to_mix_map(i,j, j < 16 ? j : j + 2);
|
mix_map[i * MIX_INPUTS + j] = (j < 16 ? j : j + 2);
|
||||||
#endif
|
#endif
|
||||||
write_word_to_mix_mult(i,j, i==j ? db_to_mult(0, 8, 25) : 0);
|
mix_mult[i * MIX_INPUTS + j] = (i==j ? db_to_mult(0, XUA_MIXER_DB_FRAC_BITS, XUA_MIXER_MULT_FRAC_BITS) : 0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2013-2022 XMOS LIMITED.
|
// Copyright 2013-2023 XMOS LIMITED.
|
||||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||||
|
|
||||||
#include <xs1.h>
|
#include <xs1.h>
|
||||||
@@ -9,17 +9,17 @@
|
|||||||
#include "xua.h"
|
#include "xua.h"
|
||||||
|
|
||||||
/* Note since DSD ports could be reused for I2S ports we do all the setup manually in C */
|
/* Note since DSD ports could be reused for I2S ports we do all the setup manually in C */
|
||||||
#if DSD_CHANS_DAC > 0
|
#if (DSD_CHANS_DAC > 0)
|
||||||
port p_dsd_dac[DSD_CHANS_DAC] = {
|
port p_dsd_dac[DSD_CHANS_DAC] = {
|
||||||
PORT_DSD_DAC0,
|
PORT_DSD_DAC0,
|
||||||
#endif
|
#endif
|
||||||
#if DSD_CHANS_DAC > 1
|
#if (DSD_CHANS_DAC > 1)
|
||||||
PORT_DSD_DAC1,
|
PORT_DSD_DAC1,
|
||||||
#endif
|
#endif
|
||||||
#if DSD_CHANS_DAC > 2
|
#if (DSD_CHANS_DAC > 2)
|
||||||
#error > 2 DSD chans currently not supported
|
#error > 2 DSD chans currently not supported
|
||||||
#endif
|
#endif
|
||||||
#if DSD_CHANS_DAC > 0
|
#if (DSD_CHANS_DAC > 0)
|
||||||
};
|
};
|
||||||
port p_dsd_clk = PORT_DSD_CLK;
|
port p_dsd_clk = PORT_DSD_CLK;
|
||||||
#endif
|
#endif
|
||||||
@@ -45,7 +45,7 @@ void ConfigAudioPortsWrapper(
|
|||||||
port p_lrclk,
|
port p_lrclk,
|
||||||
port p_bclk,
|
port p_bclk,
|
||||||
#endif
|
#endif
|
||||||
port p_mclk_in, clock clk_audio_bclk, unsigned int divide, unsigned curSamFreq, unsigned int dsdMode)
|
port p_mclk_in, clock clk_audio_bclk, unsigned int divide, unsigned curSamFreq)
|
||||||
{
|
{
|
||||||
ConfigAudioPorts(
|
ConfigAudioPorts(
|
||||||
#if (I2S_CHANS_DAC != 0) || (DSD_CHANS_DAC != 0)
|
#if (I2S_CHANS_DAC != 0) || (DSD_CHANS_DAC != 0)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2011-2022 XMOS LIMITED.
|
// Copyright 2011-2023 XMOS LIMITED.
|
||||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||||
#ifndef _AUDIOPORTS_H_
|
#ifndef _AUDIOPORTS_H_
|
||||||
#define _AUDIOPORTS_H_
|
#define _AUDIOPORTS_H_
|
||||||
@@ -79,7 +79,7 @@ void ConfigAudioPortsWrapper(
|
|||||||
buffered in port:32 p_bclk,
|
buffered in port:32 p_bclk,
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
in port p_mclk_in, clock clk_audio_bclk, unsigned int divide, unsigned curSamFreq, unsigned int dsdMode);
|
in port p_mclk_in, clock clk_audio_bclk, unsigned int divide, unsigned curSamFreq);
|
||||||
#else
|
#else
|
||||||
|
|
||||||
void ConfigAudioPortsWrapper(
|
void ConfigAudioPortsWrapper(
|
||||||
@@ -95,7 +95,7 @@ void ConfigAudioPortsWrapper(
|
|||||||
port p_lrclk,
|
port p_lrclk,
|
||||||
port p_bclk,
|
port p_bclk,
|
||||||
#endif
|
#endif
|
||||||
port p_mclk_in, clock clk_audio_bclk, unsigned int divide, unsigned curSamFreq, unsigned int dsdMode);
|
port p_mclk_in, clock clk_audio_bclk, unsigned int divide, unsigned curSamFreq);
|
||||||
|
|
||||||
|
|
||||||
#endif /* __XC__*/
|
#endif /* __XC__*/
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2011-2022 XMOS LIMITED.
|
// Copyright 2011-2023 XMOS LIMITED.
|
||||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||||
#include <xs1.h>
|
#include <xs1.h>
|
||||||
#include <platform.h>
|
#include <platform.h>
|
||||||
@@ -6,9 +6,7 @@
|
|||||||
#include "xua.h"
|
#include "xua.h"
|
||||||
#include "audioports.h"
|
#include "audioports.h"
|
||||||
|
|
||||||
//extern in port p_mclk_in;
|
|
||||||
extern clock clk_audio_mclk;
|
extern clock clk_audio_mclk;
|
||||||
//extern clock clk_audio_bclk;
|
|
||||||
|
|
||||||
void ConfigAudioPorts(
|
void ConfigAudioPorts(
|
||||||
#if (I2S_CHANS_DAC != 0) || (DSD_CHANS_DAC != 0)
|
#if (I2S_CHANS_DAC != 0) || (DSD_CHANS_DAC != 0)
|
||||||
@@ -58,7 +56,7 @@ void ConfigAudioPorts(
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (I2S_CHANS_DAC != 0)
|
#if (I2S_CHANS_DAC != 0)|| (DSD_CHANS_DAC != 0)
|
||||||
for(int i = 0; i < numPortsDac; i++)
|
for(int i = 0; i < numPortsDac; i++)
|
||||||
{
|
{
|
||||||
clearbuf(p_i2s_dac[i]);
|
clearbuf(p_i2s_dac[i]);
|
||||||
@@ -82,7 +80,7 @@ void ConfigAudioPorts(
|
|||||||
/* Some adustments for timing. Sample ADC lines on negative edge and add some delay */
|
/* Some adustments for timing. Sample ADC lines on negative edge and add some delay */
|
||||||
if(XUA_PCM_FORMAT == XUA_PCM_FORMAT_TDM)
|
if(XUA_PCM_FORMAT == XUA_PCM_FORMAT_TDM)
|
||||||
{
|
{
|
||||||
for(int i = 0; i < I2S_WIRES_ADC; i++)
|
for(int i = 0; i < numPortsAdc; i++)
|
||||||
{
|
{
|
||||||
set_port_sample_delay(p_i2s_adc[i]);
|
set_port_sample_delay(p_i2s_adc[i]);
|
||||||
set_pad_delay(p_i2s_adc[i], 4);
|
set_pad_delay(p_i2s_adc[i], 4);
|
||||||
@@ -91,7 +89,6 @@ void ConfigAudioPorts(
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#elif (CODEC_MASTER)
|
#elif (CODEC_MASTER)
|
||||||
|
|
||||||
/* Stop bit and master clock blocks */
|
/* Stop bit and master clock blocks */
|
||||||
stop_clock(clk_audio_bclk);
|
stop_clock(clk_audio_bclk);
|
||||||
|
|
||||||
@@ -103,20 +100,18 @@ void ConfigAudioPorts(
|
|||||||
/* Do some clocking shifting to get data in the valid window */
|
/* Do some clocking shifting to get data in the valid window */
|
||||||
/* E.g. Only shift when running at 88.2+ kHz TDM slave */
|
/* E.g. Only shift when running at 88.2+ kHz TDM slave */
|
||||||
int bClkDelay_fall = 0;
|
int bClkDelay_fall = 0;
|
||||||
if(curSamFreq * I2S_CHANS_PER_FRAME * 32 >= 20000000)
|
if(curSamFreq * I2S_CHANS_PER_FRAME * XUA_I2S_N_BITS >= 20000000)
|
||||||
{
|
{
|
||||||
/* 18 * 2ns = 36ns. This results in a -4ns (36 - 40) shift at 96KHz and -8ns (36 - 44) at 88.4KHz */
|
/* 18 * 2ns = 36ns. This results in a -4ns (36 - 40) shift at 96KHz and -8ns (36 - 44) at 88.4KHz */
|
||||||
bClkDelay_fall = 18;
|
bClkDelay_fall = 18;
|
||||||
}
|
}
|
||||||
|
|
||||||
set_clock_fall_delay(clk_audio_bclk, bClkDelay_fall);
|
set_clock_fall_delay(clk_audio_bclk, bClkDelay_fall);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if (I2S_CHANS_DAC != 0) || (DSD_CHANS_DAC != 0)
|
||||||
#if (I2S_CHANS_DAC != 0)
|
/* Clock I2S/DSD output data ports from b-clock clock block */
|
||||||
/* Clock I2S output data ports from b-clock clock block */
|
for(int i = 0; i < numPortsDac; i++)
|
||||||
for(int i = 0; i < I2S_WIRES_DAC; i++)
|
|
||||||
{
|
{
|
||||||
configure_out_port_no_ready(p_i2s_dac[i], clk_audio_bclk, 0);
|
configure_out_port_no_ready(p_i2s_dac[i], clk_audio_bclk, 0);
|
||||||
}
|
}
|
||||||
@@ -124,7 +119,7 @@ void ConfigAudioPorts(
|
|||||||
|
|
||||||
#if (I2S_CHANS_ADC != 0)
|
#if (I2S_CHANS_ADC != 0)
|
||||||
/* Clock I2S input data ports from clock block */
|
/* Clock I2S input data ports from clock block */
|
||||||
for(int i = 0; i < I2S_WIRES_ADC; i++)
|
for(int i = 0; i < numPortsAdc; i++)
|
||||||
{
|
{
|
||||||
configure_in_port_no_ready(p_i2s_adc[i], clk_audio_bclk);
|
configure_in_port_no_ready(p_i2s_adc[i], clk_audio_bclk);
|
||||||
}
|
}
|
||||||
|
|||||||
29
lib_xua/src/core/user/audiohw/audiohw.c
Normal file
29
lib_xua/src/core/user/audiohw/audiohw.c
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
// Copyright 2023 XMOS LIMITED.
|
||||||
|
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||||
|
|
||||||
|
/* Default implementations of AudioHwInit(), AudioHwConfig(), AudioHwConfig_Mute() and AudioHwConfig_UnMute() */
|
||||||
|
|
||||||
|
void AudioHwInit() __attribute__ ((weak));
|
||||||
|
void AudioHwInit()
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioHwConfig(unsigned samFreq, unsigned mClk, unsigned dsdMode, unsigned sampRes_DAC, unsigned sampRes_ADC) __attribute__ ((weak));
|
||||||
|
void AudioHwConfig(unsigned samFreq, unsigned mClk, unsigned dsdMode, unsigned sampRes_DAC, unsigned sampRes_ADC)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioHwConfig_Mute() __attribute__ ((weak));
|
||||||
|
void AudioHwConfig_Mute()
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioHwConfig_UnMute() __attribute__ ((weak));
|
||||||
|
void AudioHwConfig_UnMute()
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
54
lib_xua/src/core/user/audiohw/audiohw.h
Normal file
54
lib_xua/src/core/user/audiohw/audiohw.h
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
// Copyright 2023 XMOS LIMITED.
|
||||||
|
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||||
|
#ifndef _AUDIO_HW_H_
|
||||||
|
#define _AUDIO_HW_H_
|
||||||
|
|
||||||
|
/* The functions below should be implemented for the external audio hardware arrangement of a specific design.
|
||||||
|
* Note, default (empty) implementations of these are provided in audiohub_user.c
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief User audio hardware initialisation code
|
||||||
|
*
|
||||||
|
* This function is called when the device starts up and should contain user code to perform any required audio hardware initialisation
|
||||||
|
*/
|
||||||
|
void AudioHwInit(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief User audio hardware configuration code
|
||||||
|
*
|
||||||
|
* This function is called when on sample rate change and should contain user code to configure audio hardware
|
||||||
|
* (clocking, CODECs etc) for a specific mClk/Sample frequency
|
||||||
|
*
|
||||||
|
* \param samFreq The new sample frequency (in Hz)
|
||||||
|
*
|
||||||
|
* \param mClk The new master clock frequency (in Hz)
|
||||||
|
*
|
||||||
|
* \param dsdMode DSD mode, DSD_MODE_NATIVE, DSD_MODE_DOP or DSD_MODE_OFF
|
||||||
|
*
|
||||||
|
* \param sampRes_DAC Playback sample resolution (in bits)
|
||||||
|
*
|
||||||
|
* \param sampRes_ADC Record sample resolution (in bits)
|
||||||
|
*/
|
||||||
|
void AudioHwConfig(unsigned samFreq, unsigned mClk, unsigned dsdMode, unsigned sampRes_DAC, unsigned sampRes_ADC);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief User code mute audio hardware
|
||||||
|
*
|
||||||
|
* This function is called before AudioHwConfig() and should contain user code to mute audio hardware before a
|
||||||
|
* sample rate change in order to reduced audible pops/clicks
|
||||||
|
*
|
||||||
|
* Note, if using the application PLL of a xcore.ai device this function will be called before the master-clock is
|
||||||
|
* changed
|
||||||
|
*/
|
||||||
|
void AudioHwConfig_Mute(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief User code to un-mute audio hardware
|
||||||
|
*
|
||||||
|
* This function is called after AudioHwConfig() and should contain user code to un-mute audio hardware after a
|
||||||
|
* sample rate change
|
||||||
|
*/
|
||||||
|
void AudioHwConfig_UnMute(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user