forked from PAWPAW-Mirror/lib_xua
Compare commits
258 Commits
v3.2.0rc1
...
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 | ||
|
|
2183dd1b53 | ||
|
|
16ce73391a | ||
|
|
3fff130e4e | ||
|
|
155dc9a21a | ||
|
|
4f38e40f04 | ||
|
|
036ebc0d33 | ||
|
|
51270516e4 | ||
|
|
e86e9a156b | ||
|
|
f5da215428 | ||
|
|
9e5e196073 | ||
|
|
7500ed9a31 | ||
|
|
918e2ed0f1 | ||
|
|
77b20c13dc | ||
|
|
a8d9df4107 | ||
|
|
e04373d4a6 | ||
|
|
22a6a2505a | ||
|
|
eb86a72882 | ||
|
|
0c368e0356 | ||
|
|
86bea717da | ||
|
|
49592f6e24 | ||
|
|
d754bff62b | ||
|
|
a08e4535f2 | ||
|
|
1259fb68fd | ||
|
|
f24d0c2822 | ||
|
|
dd933ebe55 | ||
|
|
dde2363481 | ||
|
|
30cb913519 | ||
|
|
b7a90a3235 | ||
|
|
e1d0974912 | ||
|
|
fe39cd7c11 | ||
|
|
6beb1f34ae | ||
|
|
351a38fa4b | ||
|
|
ff6547b75c | ||
|
|
9c2d77e216 | ||
|
|
4643d14b04 | ||
|
|
b38ce229cb | ||
|
|
7a2dd0b644 | ||
|
|
9d6927ade1 | ||
|
|
e6d3c65902 | ||
|
|
d6bc7325c4 | ||
|
|
9f105dd48a | ||
|
|
ea7e20a3d9 | ||
|
|
b982632bdb | ||
|
|
085d222f45 | ||
|
|
8b3f5abc86 | ||
|
|
4f86d2c581 | ||
|
|
0f1e0e1822 | ||
|
|
23cabe80ee | ||
|
|
8f77f2a7ca | ||
|
|
a3cee96166 | ||
|
|
2d697aab40 | ||
|
|
11f5a9d9e1 | ||
|
|
5812ce752b | ||
|
|
3336aa344d | ||
|
|
598acc629d | ||
|
|
b7f9dd5781 | ||
|
|
aea1e97d9d | ||
|
|
769e7b9a99 | ||
|
|
8204211742 | ||
|
|
a8fb40401c | ||
|
|
ce41732440 | ||
|
|
c811aac320 | ||
|
|
51f5d1f0b8 | ||
|
|
5d331e7f27 | ||
|
|
f363475529 | ||
|
|
80e6f047ab | ||
|
|
dfc406e322 | ||
|
|
5a32d60c29 | ||
|
|
b17cc0de6d | ||
|
|
5690442a4b | ||
|
|
3a9f2fff3a | ||
|
|
2c01f440fd | ||
|
|
2b1909757b | ||
|
|
43c561c831 | ||
|
|
2b679d1572 | ||
|
|
4f36ce4df7 | ||
|
|
9fdacb2903 | ||
|
|
a0f5591e0b | ||
|
|
36dedc494c | ||
|
|
06822c7499 | ||
|
|
8157a76667 | ||
|
|
f534537b76 | ||
|
|
1ad26f6bac | ||
|
|
2a8f3b11d9 | ||
|
|
0659b1c536 | ||
|
|
d6abd5d159 | ||
|
|
a913cd85f1 | ||
|
|
7e098c7139 | ||
|
|
5c1773a883 | ||
|
|
9401bfff83 | ||
|
|
476e3d9f2f | ||
|
|
438c24d436 | ||
|
|
5441081927 | ||
|
|
bb0dec4923 | ||
|
|
3e0f127b92 | ||
|
|
f3a149076b | ||
|
|
29bd1a575b | ||
|
|
6f56d2ed1a | ||
|
|
e6a8527631 | ||
|
|
ff42c23a6d | ||
|
|
22a79d9231 |
59
.gitignore
vendored
59
.gitignore
vendored
@@ -1,28 +1,25 @@
|
||||
*.log
|
||||
*.dSYM
|
||||
*/.build_*/*
|
||||
*/bin/*
|
||||
*.o
|
||||
# XMOS bin files
|
||||
*.xe
|
||||
*.vcd
|
||||
*.swo
|
||||
*.bin
|
||||
*/bin/*
|
||||
|
||||
# XMOS temp files
|
||||
.build*
|
||||
*.a
|
||||
_build*
|
||||
*.i
|
||||
*.s
|
||||
*.xi
|
||||
*.i
|
||||
*.bin
|
||||
*~
|
||||
*.a
|
||||
*.swp
|
||||
*.*~
|
||||
*.pyc
|
||||
.build*
|
||||
*.o
|
||||
*/.build_*/*
|
||||
|
||||
# Temp files
|
||||
.DS_Store
|
||||
test_results.csv
|
||||
_build*
|
||||
**/.venv/**
|
||||
**/.vscode/**
|
||||
**.egg-info
|
||||
*.pdf
|
||||
*.*~
|
||||
*.swp
|
||||
*.swn
|
||||
*~
|
||||
*.swo
|
||||
|
||||
# waf build files
|
||||
.lock-waf_*
|
||||
@@ -31,3 +28,23 @@ build/
|
||||
.build*
|
||||
*.pyc
|
||||
xscope.xmt
|
||||
|
||||
# Traces
|
||||
*.gtkw
|
||||
*.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,84 @@
|
||||
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
|
||||
-----
|
||||
|
||||
* CHANGED: Define ADAT_RX renamed to XUA_ADAT_RX_EN
|
||||
* CHANGED: Define ADAT_TX renamed to XUA_ADAT_TX_EN
|
||||
* CHANGED: Define SPDIF_RX renamed to XUA_SPDIF_RX_EN
|
||||
* CHANGED: Define SELF_POWERED changed to XUA_POWERMODE and associated
|
||||
defines
|
||||
* CHANGED: Drive strength of I2S clock lines upped to 8mA on xCORE.ai
|
||||
* CHANGED: ADC datalines sampled on falling edge of clock in TDM mode
|
||||
* CHANGED: Improved startup behaviour of TDM clocks
|
||||
* FIXED: Intermittent underflow at MAX_FREQ on input stream start due to
|
||||
insufficient packet buffering
|
||||
* FIXED: Decouple buffer accounting to avoid corruption of samples
|
||||
|
||||
* Changes to dependencies:
|
||||
|
||||
- lib_adat: Added dependency 1.0.1
|
||||
|
||||
- lib_xud: 2.1.0 -> 2.2.1
|
||||
|
||||
3.2.0
|
||||
-----
|
||||
|
||||
|
||||
76
Jenkinsfile
vendored
76
Jenkinsfile
vendored
@@ -1,4 +1,4 @@
|
||||
@Library('xmos_jenkins_shared_library@v0.18.0') _
|
||||
@Library('xmos_jenkins_shared_library@v0.24.0') _
|
||||
|
||||
getApproval()
|
||||
|
||||
@@ -24,26 +24,30 @@ pipeline {
|
||||
}
|
||||
stage('Library checks') {
|
||||
steps {
|
||||
xcoreLibraryChecks("${REPO}")
|
||||
xcoreLibraryChecks("${REPO}", false)
|
||||
}
|
||||
}
|
||||
stage('XS2 Tests') {
|
||||
stage('Testing') {
|
||||
failFast true
|
||||
parallel {
|
||||
stage('Legacy tests') {
|
||||
stage('Tests') {
|
||||
steps {
|
||||
runXmostest("${REPO}", 'legacy_tests')
|
||||
dir("${REPO}/tests"){
|
||||
viewEnv(){
|
||||
withVenv{
|
||||
runPytest('--numprocesses=4')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Unit tests') {
|
||||
stage('Unity tests') {
|
||||
steps {
|
||||
dir("${REPO}") {
|
||||
dir('tests') {
|
||||
dir('xua_unit_tests') {
|
||||
withVenv {
|
||||
runWaf('.', "configure clean build --target=xcore200")
|
||||
// runWaf('.', "configure clean build --target=xcoreai")
|
||||
// stash name: 'xua_unit_tests', includes: 'bin/*xcoreai.xe, '
|
||||
viewEnv() {
|
||||
runPython("TARGET=XCORE200 pytest -s")
|
||||
}
|
||||
@@ -55,42 +59,6 @@ pipeline {
|
||||
}
|
||||
}
|
||||
}
|
||||
// stage('xcore.ai Verification') {
|
||||
// agent {
|
||||
// label 'xcore.ai-explorer'
|
||||
// }
|
||||
// options {
|
||||
// skipDefaultCheckout()
|
||||
// }
|
||||
// stages{
|
||||
// stage('Get View') {
|
||||
// steps {
|
||||
// xcorePrepareSandbox("${VIEW}", "${REPO}")
|
||||
// }
|
||||
// }
|
||||
// stage('Unit tests') {
|
||||
// steps {
|
||||
// dir("${REPO}") {
|
||||
// dir('tests') {
|
||||
// dir('xua_unit_tests') {
|
||||
// withVenv {
|
||||
// unstash 'xua_unit_tests'
|
||||
// viewEnv() {
|
||||
// runPython("TARGET=XCOREAI pytest -s")
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// } // stages
|
||||
// post {
|
||||
// cleanup {
|
||||
// cleanWs()
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
stage('xCORE builds') {
|
||||
steps {
|
||||
dir("${REPO}") {
|
||||
@@ -99,6 +67,8 @@ pipeline {
|
||||
runXdoc('doc')
|
||||
}
|
||||
}
|
||||
// Archive all the generated .pdf docs
|
||||
archiveArtifacts artifacts: "${REPO}/**/pdf/*.pdf", fingerprint: true, allowEmptyArchive: true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -136,6 +106,12 @@ pipeline {
|
||||
dir("${REPO}/${REPO}/host/xmosdfu") {
|
||||
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 {
|
||||
cleanup {
|
||||
@@ -169,7 +145,17 @@ pipeline {
|
||||
dir("${REPO}") {
|
||||
checkout scm
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
86
README.rst
86
README.rst
@@ -1,30 +1,29 @@
|
||||
lib_xua
|
||||
=======
|
||||
|
||||
:Latest release: 3.2.0rc1
|
||||
|
||||
#######
|
||||
|
||||
:Version: 3.5.0
|
||||
:Vendor: XMOS
|
||||
:Scope: General Use
|
||||
|
||||
Summary
|
||||
-------
|
||||
*******
|
||||
|
||||
USB Audio Shared Components for use in the XMOS USB Audio Refererence Designs.
|
||||
lib_xua contains shared components for use in the XMOS USB Audio (XUA) Reference Designs.
|
||||
|
||||
This library enables 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
|
||||
........
|
||||
========
|
||||
|
||||
Key features of the various applications in this repository are as follows
|
||||
Key features of the various components in this repository are as follows
|
||||
|
||||
- USB Audio Class 1.0/2.0 Compliant
|
||||
|
||||
- Fully Asynchronous operation
|
||||
- Fully Asynchronous operation (synchronous mode as an option)
|
||||
|
||||
- Support for the following sample frequencies: 8, 11.025, 12, 16, 32, 44.1, 48, 88.2, 96, 176.4, 192, 352.8, 384kHz
|
||||
|
||||
- Input/output channel and individual volume/mute controls supported
|
||||
- Volume/mute controls for input/output (for both master and individual channels)
|
||||
|
||||
- Support for dynamically selectable output audio formats (e.g. resolution)
|
||||
|
||||
@@ -38,47 +37,66 @@ Key features of the various applications in this repository are as follows
|
||||
|
||||
- ADAT input
|
||||
|
||||
- Synchronisation to external digital streams i.e. S/PDIF or ADAT
|
||||
- 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)
|
||||
|
||||
- DSD output (Native and DoP mode) at DSD64 and DSD128 rates
|
||||
- DSD output ("native" and DoP mode) at DSD64 and DSD128 rates
|
||||
|
||||
- Mixer with flexible routing
|
||||
|
||||
- Simple playback controls via Human Interface Device (HID)
|
||||
- Simple playback controls via USB Human Interface Device (HID) Class
|
||||
|
||||
- Support for operation with Apple devices (requires software module sc_mfi for MFI licensees only - please contact XMOS)
|
||||
- Support for adding custom HID interfaces
|
||||
|
||||
Note, not all features may be supported at all sample frequencies, simultaneously or on all devices. Some features also require specific host driver support.
|
||||
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.
|
||||
|
||||
Software version and dependencies
|
||||
.................................
|
||||
Host System Requirements
|
||||
========================
|
||||
|
||||
The CHANGELOG contains information about the current and previous versions.
|
||||
For a list of direct dependencies, look for DEPENDENT_MODULES in lib_xua/module_build_info.
|
||||
USB Audio devices built using `lib_xua` have the following host system requirements.
|
||||
|
||||
- Mac OSX version 10.6 or later
|
||||
|
||||
- Windows Vista, 7, 8 or 10 with Thesycon Audio Class 2.0 driver for Windows (Tested against version 3.20). Please contact XMOS for details.
|
||||
|
||||
- Windows Vista, 7, 8 or 10 with built-in USB Audio Class 1.0 driver.
|
||||
|
||||
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
|
||||
.........................
|
||||
=========================
|
||||
|
||||
The following application notes use this library:
|
||||
|
||||
* AN000246 - Simple USB Audio Device using lib_xua
|
||||
* AN000247 - Using lib_xua with lib_spdif (transmit)
|
||||
* AN000248 - Using lib_xua with lib_mic_array
|
||||
* AN000246 - Simple USB Audio Device using lib_xua
|
||||
* AN000247 - Using lib_xua with lib_spdif (transmit)
|
||||
* AN000248 - Using lib_xua with lib_mic_array
|
||||
|
||||
Required software (dependencies)
|
||||
Required Software (dependencies)
|
||||
================================
|
||||
|
||||
* lib_locks (git@github.com:xmos/lib_locks.git)
|
||||
* lib_logging (git@github.com:xmos/lib_logging)
|
||||
* lib_mic_array (git@github.com:xmos/lib_mic_array.git)
|
||||
* lib_xassert (git@github.com:xmos/lib_xassert)
|
||||
* lib_dsp (git@github.com:xmos/lib_dsp)
|
||||
* lib_spdif (git@github.com:xmos/lib_spdif)
|
||||
* lib_xud (git@github.com:xmos/lib_xud)
|
||||
* lib_locks (www.github.com/xmos/lib_locks)
|
||||
* lib_logging (www.github.com/xmos/lib_logging)
|
||||
* lib_mic_array (www.github.com/xmos/lib_mic_array)
|
||||
* lib_xassert (www.github.com/xmos/lib_xassert)
|
||||
* lib_dsp (www.github.com/xmos/lib_dsp)
|
||||
* lib_spdif (www.github.com/xmos/lib_spdif)
|
||||
* lib_xud (www.github.com/xmos/lib_xud)
|
||||
* lib_adat (www.github.com/xmos/lib_adat)
|
||||
|
||||
Documentation
|
||||
=============
|
||||
|
||||
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
|
||||
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
APP_NAME = app_xua_simple
|
||||
|
||||
TARGET = xk-audio-216-mc.xn
|
||||
TARGET = xk-audio-316-mc.xn
|
||||
|
||||
# The flags passed to xcc when building the application
|
||||
XCC_FLAGS = -fcomment-asm -Xmapper --map -Xmapper MAPFILE -O3 -report -save-temps \
|
||||
-g -Wno-unused-function -Wno-timing -DXUD_SERIES_SUPPORT=XUD_X200_SERIES \
|
||||
-DXUD_CORE_CLOCK=600 -DUSB_TILE=tile[1] -fxscope -DUAC_FORCE_FEEDBACK_EP=0
|
||||
XCC_FLAGS = -O3 -report \
|
||||
-g -Wno-unused-function \
|
||||
-DXUD_CORE_CLOCK=600 \
|
||||
-DUSB_TILE=tile[0] \
|
||||
-fxscope \
|
||||
-DUAC_FORCE_FEEDBACK_EP=0
|
||||
|
||||
# The USED_MODULES variable lists other module used by the application. These
|
||||
# modules will extend the SOURCE_DIRS, INCLUDE_DIRS and LIB_DIRS variables.
|
||||
# Modules are expected to be in the directory above the BASE_DIR directory.
|
||||
USED_MODULES = lib_xua lib_device_control lib_xud lib_i2c
|
||||
USED_MODULES = lib_xua lib_xud lib_i2c
|
||||
|
||||
#=============================================================================
|
||||
# The following part of the Makefile includes the common build infrastructure
|
||||
@@ -18,4 +21,3 @@ USED_MODULES = lib_xua lib_device_control lib_xud lib_i2c
|
||||
|
||||
XMOS_MAKE_PATH ?= ../..
|
||||
include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.common
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ Introduction
|
||||
The XMOS USB Audio (XUA) library provides an implemention of USB Audio Class versions 1.0 and 2.0.
|
||||
|
||||
This application note demonstrates the implementation of a basic USB Audio Device on
|
||||
the xCORE-200 MC Audio board.
|
||||
the xCORE.ai Multichannel (MC) Audio board (XK-AUDIO-316-MC).
|
||||
|
||||
|
||||
The Makefile
|
||||
@@ -26,14 +26,10 @@ The Makefile also includes::
|
||||
|
||||
USED_MODULES = .. lib_xud ..
|
||||
|
||||
``lib_xud`` library requires some flags for correct operation. Firstly the
|
||||
``lib_xud`` library requires some flags for correct operation. Namely the
|
||||
tile on which ``lib_xud`` will be execute, for example::
|
||||
|
||||
XCC_FLAGS = .. -DUSB_TILE=tile[1] ..
|
||||
|
||||
Secondly, the architecture of the target device, for example::
|
||||
|
||||
XCC_FLAGS = .. -DXUD_SERIES_SUPPORT=XUD_X200_SERIES ..
|
||||
XCC_FLAGS = .. -DUSB_TILE=tile[0] ..
|
||||
|
||||
Includes
|
||||
........
|
||||
@@ -52,23 +48,22 @@ be included in your code to use the library.
|
||||
:start-on: include "xua.h"
|
||||
:end-on: include "xud_device.h"
|
||||
|
||||
Allocating hardware resources
|
||||
Allocating Hardware Resources
|
||||
.............................
|
||||
|
||||
A basic implementation of a USB Audio device (i.e. simple stereo input and output via I2S)
|
||||
A basic implementation of a USB Audio device (i.e. simple stereo output via I2S)
|
||||
using ``lib_xua`` requires the follow pins:
|
||||
|
||||
- I2S Bit Clock (from xCORE to DAC)
|
||||
- I2S L/R clock (from xCORE to DAC)
|
||||
- I2S Data line (from xCORE to DAC)
|
||||
- I2S Data line (from ADC to xCORE)
|
||||
- Audio Master clock (from clock source to xCORE)
|
||||
|
||||
.. note::
|
||||
|
||||
This application note assumes xCORE is I2S bus master
|
||||
|
||||
On an xCORE the pins are controlled by ``ports``. The application therefore declares various ``ports``
|
||||
In the xCORE architecture the I/O pins are controlled and accessed by ``ports``. The application therefore declares various ``ports``
|
||||
for this purpose:
|
||||
|
||||
.. literalinclude:: app_xua_simple.xc
|
||||
@@ -76,8 +71,8 @@ for this purpose:
|
||||
:end-on: in port p_mclk_in
|
||||
|
||||
``lib_xua`` also requires two ports for internally calculating USB feedback. Please refer to
|
||||
the ``lib_xua`` library documentation for further details. The additonal input port for the master
|
||||
clock is required since USB and S/PDIF do not reside of the same tiles on the example hardware.
|
||||
the ``lib_xua`` library documentation for further details. The additional input port for the master
|
||||
clock is required since USB and S/PDIF do not reside of the same tiles on the xCORE.ai MC Audio Board.
|
||||
|
||||
These ports are declared as follows:
|
||||
|
||||
@@ -95,11 +90,11 @@ Again, for the same reasoning as the master-clock ports, two master-clock clock-
|
||||
- one on each tile.
|
||||
|
||||
|
||||
Other declarations
|
||||
Other Declarations
|
||||
..................
|
||||
|
||||
``lib_xua`` currently requires the manual declaration of tables for the endpoint types for
|
||||
``lib_xud`` and the calling the main XUD funtion in a par (``XUD_Main()``).
|
||||
``lib_xud`` and the calling the main XUD function in a par (``XUD_Main()``).
|
||||
|
||||
For a simple application the following endpoints are required:
|
||||
|
||||
@@ -112,12 +107,12 @@ These are declared as follows:
|
||||
:start-on: /* Endpoint type tables
|
||||
:end-on: XUD_EpType epTypeTableIn
|
||||
|
||||
The application main() function
|
||||
The Application main() Function
|
||||
-------------------------------
|
||||
|
||||
The ``main()`` function sets up the tasks in the application.
|
||||
|
||||
Various channels are required in order to allow the required tasks to communcate.
|
||||
Various channels are required in order to allow the required tasks to communicate.
|
||||
These must first be declared:
|
||||
|
||||
.. literalinclude:: app_xua_simple.xc
|
||||
@@ -134,6 +129,9 @@ using the xC ``par`` construct:
|
||||
This code starts the low-level USB task, an Endpoint 0 task, an Audio buffering task and a task to handle
|
||||
the audio I/O (i.e. I2S signalling).
|
||||
|
||||
It also runs a small function ``ctrlPort()`` that simply writes some values to an I/O port to configure some external
|
||||
hardware (it enables analogue power supplies and correctly routes the master clock) and then closes.
|
||||
|
||||
Configuration
|
||||
.............
|
||||
|
||||
@@ -162,9 +160,10 @@ implentation e.g. master clock frequencies and must be defined. Please see the
|
||||
Demo Hardware Setup
|
||||
-------------------
|
||||
|
||||
To run the demo, connect a USB cable to power the xCORE-200 MC Audio board
|
||||
and plug the xTAG to the board and connect the xTAG USB cable to your
|
||||
development machine.
|
||||
To run the demo, use a USB cable to connect the on-board xTAG debug adapter (marked ``DEBUG``) to your development computer.
|
||||
Use another USB cable to connect the USB receptacle marked ``USB DEVICE`` to the device you wish to play audio from.
|
||||
|
||||
Plug a device capable of receiving analogue audio (i.e. an amplified speaker) to the 3.5mm jack marked ``OUT 1/2``.
|
||||
|
||||
.. figure:: images/hw_setup.*
|
||||
:width: 80%
|
||||
@@ -173,40 +172,27 @@ development machine.
|
||||
|
||||
|newpage|
|
||||
|
||||
Launching the demo application
|
||||
Launching the Demo Application
|
||||
------------------------------
|
||||
|
||||
Once the demo example has been built either from the command line using xmake or
|
||||
via the build mechanism of xTIMEcomposer studio it can be executed on the xCORE-200
|
||||
MC Audio board.
|
||||
Once the demo example has been built from the command line using ``xmake``
|
||||
it can be executed on the xCORE.ai MC Audio Board.
|
||||
|
||||
Once built there will be a ``bin/`` directory within the project which contains
|
||||
the binary for the xCORE device. The xCORE binary has a XMOS standard .xe extension.
|
||||
|
||||
Launching from the command line
|
||||
Launching from the Command Line
|
||||
...............................
|
||||
|
||||
From the command line you use the ``xrun`` tool to download and run the code
|
||||
on the xCORE device::
|
||||
|
||||
xrun --xscope bin/app_xua_simple.xe
|
||||
xrun ./bin/app_xua_simple.xe
|
||||
|
||||
Once this command has executed the application will be running on the
|
||||
xCORE-200 MC Audio Board
|
||||
xCORE.ai MC Audio Board
|
||||
|
||||
Launching from xTIMEcomposer Studio
|
||||
...................................
|
||||
|
||||
From xTIMEcomposer Studio use the run mechanism to download code to xCORE device.
|
||||
Select the xCORE binary from the ``bin/`` directory, right click and go to Run
|
||||
Configurations. Double click on xCORE application to create a new run configuration,
|
||||
enable the xSCOPE I/O mode in the dialog box and then
|
||||
select Run.
|
||||
|
||||
Once this command has executed the application will be running on the
|
||||
xCORE-200 MC Audio board.
|
||||
|
||||
Running the application
|
||||
Running the Application
|
||||
.......................
|
||||
|
||||
Once running the device will be detected as a USB Audio device - note, Windows operating
|
||||
@@ -237,11 +223,11 @@ References
|
||||
|
||||
|newpage|
|
||||
|
||||
Full source code listing
|
||||
Full Source Code Listing
|
||||
------------------------
|
||||
|
||||
Source code for main.xc
|
||||
.......................
|
||||
Source Code for app_xua_simple.xc
|
||||
.................................
|
||||
|
||||
.. literalinclude:: app_xua_simple.xc
|
||||
:largelisting:
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 4.7 MiB |
@@ -5,7 +5,7 @@
|
||||
*
|
||||
* It uses the main blocks from the lib_xua
|
||||
*
|
||||
* - 2 in/ 2 out I2S only
|
||||
* - 2 channels out I2S only
|
||||
* - No DFU
|
||||
* - I2S only
|
||||
*
|
||||
@@ -19,7 +19,6 @@
|
||||
|
||||
/* 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 in port:32 p_i2s_adc[] = {PORT_I2S_ADC0}; /* I2S Data-line(s) */
|
||||
buffered out port:32 p_lrclk = PORT_I2S_LRCLK; /* I2S Bit-clock */
|
||||
buffered out port:32 p_bclk = PORT_I2S_BCLK; /* I2S L/R-clock */
|
||||
|
||||
@@ -31,15 +30,22 @@ in port p_for_mclk_count = PORT_MCLK_COUNT; /* Extra port for count
|
||||
in port p_mclk_in_usb = PORT_MCLK_IN_USB; /* Extra master clock input for the USB tile */
|
||||
|
||||
/* Clock-block declarations */
|
||||
clock clk_audio_bclk = on tile[0]: XS1_CLKBLK_4; /* Bit clock */
|
||||
clock clk_audio_mclk = on tile[0]: XS1_CLKBLK_5; /* Master clock */
|
||||
clock clk_audio_mclk_usb = on tile[1]: XS1_CLKBLK_1; /* Master clock for USB tile */
|
||||
clock clk_audio_bclk = on tile[1]: XS1_CLKBLK_4; /* Bit clock */
|
||||
clock clk_audio_mclk = on tile[1]: XS1_CLKBLK_5; /* Master clock */
|
||||
clock clk_audio_mclk_usb = on tile[0]: XS1_CLKBLK_1; /* Master clock for USB tile */
|
||||
|
||||
/* Endpoint type tables - informs XUD what the transfer types for each Endpoint in use and also
|
||||
* if the endpoint wishes to be informed of USB bus resets */
|
||||
XUD_EpType epTypeTableOut[] = {XUD_EPTYPE_CTL | XUD_STATUS_ENABLE, XUD_EPTYPE_ISO};
|
||||
XUD_EpType epTypeTableIn[] = {XUD_EPTYPE_CTL | XUD_STATUS_ENABLE, XUD_EPTYPE_ISO};
|
||||
|
||||
/* Port declarations for I2C to config ADC's */
|
||||
on tile[0]: port p_scl = XS1_PORT_1L;
|
||||
on tile[0]: port p_sda = XS1_PORT_1M;
|
||||
|
||||
/* See hwsupport.xc */
|
||||
void ctrlPort();
|
||||
|
||||
int main()
|
||||
{
|
||||
/* Channels for lib_xud */
|
||||
@@ -58,17 +64,17 @@ int main()
|
||||
par
|
||||
{
|
||||
/* Low level USB device layer core */
|
||||
on tile[1]: XUD_Main(c_ep_out, 2, c_ep_in, 2,
|
||||
on tile[0]: XUD_Main(c_ep_out, 2, c_ep_in, 2,
|
||||
c_sof, epTypeTableOut, epTypeTableIn,
|
||||
XUD_SPEED_HS, XUD_PWR_SELF);
|
||||
|
||||
/* Endpoint 0 core from lib_xua */
|
||||
/* Note, since we are not using many features we pass in null for quite a few params.. */
|
||||
on tile[1]: XUA_Endpoint0(c_ep_out[0], c_ep_in[0], c_aud_ctl, null, null, null, null);
|
||||
on tile[0]: XUA_Endpoint0(c_ep_out[0], c_ep_in[0], c_aud_ctl, null, null, null, null);
|
||||
|
||||
/* Buffering cores - handles audio data to/from EP's and gives/gets data to/from the audio I/O core */
|
||||
/* Note, this spawns two cores */
|
||||
on tile[1]: {
|
||||
on tile[0]: {
|
||||
|
||||
/* Connect master-clock clock-block to clock-block pin */
|
||||
set_clock_src(clk_audio_mclk_usb, p_mclk_in_usb); /* Clock clock-block from mclk pin */
|
||||
@@ -80,7 +86,9 @@ int main()
|
||||
}
|
||||
|
||||
/* AudioHub/IO core does most of the audio IO i.e. I2S (also serves as a hub for all audio) */
|
||||
on tile[0]: XUA_AudioHub(c_aud, clk_audio_mclk, clk_audio_bclk, p_mclk_in, p_lrclk, p_bclk, p_i2s_dac, p_i2s_adc);
|
||||
on tile[1]: XUA_AudioHub(c_aud, clk_audio_mclk, clk_audio_bclk, p_mclk_in, p_lrclk, p_bclk, p_i2s_dac, null);
|
||||
|
||||
on tile[0]: ctrlPort();
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -1,168 +0,0 @@
|
||||
// Copyright 2021-2022 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
#ifndef __hid_report_descriptor_h__
|
||||
#define __hid_report_descriptor_h__
|
||||
|
||||
#include "xua_hid_report.h"
|
||||
|
||||
#if 0
|
||||
/* Existing static report descriptor kept for reference */
|
||||
unsigned char hidReportDescriptor[] =
|
||||
{
|
||||
0x05, 0x0c, /* Usage Page (Consumer Device) */
|
||||
0x09, 0x01, /* Usage (Consumer Control) */
|
||||
0xa1, 0x01, /* Collection (Application) */
|
||||
0x15, 0x00, /* Logical Minimum (0) */
|
||||
0x25, 0x01, /* Logical Maximum (1) */
|
||||
0x09, 0xb0, /* Usage (Play) */
|
||||
0x09, 0xb5, /* Usage (Scan Next Track) */
|
||||
0x09, 0xb6, /* Usage (Scan Previous Track) */
|
||||
0x09, 0xe9, /* Usage (Volume Up) */
|
||||
0x09, 0xea, /* Usage (Volume Down) */
|
||||
0x09, 0xe2, /* Usage (Mute) */
|
||||
0x75, 0x01, /* Report Size (1) */
|
||||
0x95, 0x06, /* Report Count (6) */
|
||||
0x81, 0x02, /* Input (Data, Var, Abs) */
|
||||
0x95, 0x02, /* Report Count (2) */
|
||||
0x81, 0x01, /* Input (Cnst, Ary, Abs) */
|
||||
0xc0 /* End collection */
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Define non-configurable items in the HID Report descriptor.
|
||||
*/
|
||||
static const USB_HID_Short_Item_t hidCollectionApplication = {
|
||||
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_MAIN, HID_REPORT_ITEM_TAG_COLLECTION),
|
||||
.data = { 0x01, 0x00 } };
|
||||
static const USB_HID_Short_Item_t hidCollectionEnd = {
|
||||
.header = HID_REPORT_SET_HEADER(0, HID_REPORT_ITEM_TYPE_MAIN, HID_REPORT_ITEM_TAG_END_COLLECTION),
|
||||
.data = { 0x00, 0x00 } };
|
||||
|
||||
static const USB_HID_Short_Item_t hidInputConstArray = {
|
||||
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_MAIN, HID_REPORT_ITEM_TAG_INPUT),
|
||||
.data = { 0x01, 0x00 } };
|
||||
static const USB_HID_Short_Item_t hidInputDataVar = {
|
||||
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_MAIN, HID_REPORT_ITEM_TAG_INPUT),
|
||||
.data = { 0x02, 0x00 } };
|
||||
|
||||
static const USB_HID_Short_Item_t hidLogicalMaximum0 = {
|
||||
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_LOGICAL_MAXIMUM),
|
||||
.data = { 0x00, 0x00 } };
|
||||
static const USB_HID_Short_Item_t hidLogicalMaximum1 = {
|
||||
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_LOGICAL_MAXIMUM),
|
||||
.data = { 0x01, 0x00 } };
|
||||
static const USB_HID_Short_Item_t hidLogicalMinimum0 = {
|
||||
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_LOGICAL_MINIMUM),
|
||||
.data = { 0x00, 0x00 } };
|
||||
|
||||
static const USB_HID_Short_Item_t hidReportCount2 = {
|
||||
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_REPORT_COUNT),
|
||||
.data = { 0x02, 0x00 } };
|
||||
static const USB_HID_Short_Item_t hidReportCount6 = {
|
||||
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_REPORT_COUNT),
|
||||
.data = { 0x06, 0x00 } };
|
||||
static const USB_HID_Short_Item_t hidReportSize1 = {
|
||||
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_REPORT_SIZE),
|
||||
.data = { 0x01, 0x00 } };
|
||||
|
||||
static const USB_HID_Short_Item_t hidUsageConsumerControl = {
|
||||
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
|
||||
.data = { 0x01, 0x00 } };
|
||||
|
||||
/*
|
||||
* Define the HID Report Descriptor Item, Usage Page, Report ID and length for each HID Report
|
||||
* For internal purposes, a report element with ID of 0 must be included if report IDs are not being used.
|
||||
*/
|
||||
static const USB_HID_Report_Element_t hidReportPageConsumer = {
|
||||
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_USAGE_PAGE),
|
||||
.item.data = { USB_HID_USAGE_PAGE_ID_CONSUMER, 0x00 },
|
||||
.location = HID_REPORT_SET_LOC( 0, 2, 0, 0 )
|
||||
};
|
||||
|
||||
/*
|
||||
* Define configurable items in the HID Report descriptor.
|
||||
*/
|
||||
static USB_HID_Report_Element_t hidUsageByte0Bit5 = {
|
||||
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
|
||||
.item.data = { 0xE2, 0x00 },
|
||||
.location = HID_REPORT_SET_LOC(0, 0, 0, 5)
|
||||
}; // Mute
|
||||
static USB_HID_Report_Element_t hidUsageByte0Bit4 = {
|
||||
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
|
||||
.item.data = { 0xEA, 0x00 },
|
||||
.location = HID_REPORT_SET_LOC(0, 0, 0, 4)
|
||||
}; // Vol-
|
||||
static USB_HID_Report_Element_t hidUsageByte0Bit3 = {
|
||||
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
|
||||
.item.data = { 0xE9, 0x00 },
|
||||
.location = HID_REPORT_SET_LOC(0, 0, 0, 3)
|
||||
}; // Vol+
|
||||
static USB_HID_Report_Element_t hidUsageByte0Bit2 = {
|
||||
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
|
||||
.item.data = { 0xB6, 0x00 },
|
||||
.location = HID_REPORT_SET_LOC(0, 0, 0, 2)
|
||||
}; // Scan Prev
|
||||
static USB_HID_Report_Element_t hidUsageByte0Bit1 = {
|
||||
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
|
||||
.item.data = { 0xB5, 0x00 },
|
||||
.location = HID_REPORT_SET_LOC(0, 0, 0, 1)
|
||||
}; // Scan Next
|
||||
static USB_HID_Report_Element_t hidUsageByte0Bit0 = {
|
||||
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
|
||||
.item.data = { 0xB0, 0x00 },
|
||||
.location = HID_REPORT_SET_LOC(0, 0, 0, 0)
|
||||
}; // Play
|
||||
|
||||
/*
|
||||
* List the configurable elements in the HID Report descriptor.
|
||||
*/
|
||||
static USB_HID_Report_Element_t* const hidConfigurableElements[] = {
|
||||
&hidUsageByte0Bit0,
|
||||
&hidUsageByte0Bit1,
|
||||
&hidUsageByte0Bit2,
|
||||
&hidUsageByte0Bit3,
|
||||
&hidUsageByte0Bit4,
|
||||
&hidUsageByte0Bit5
|
||||
};
|
||||
|
||||
/*
|
||||
* List HID Reports, one per Report ID. This should be a usage page item with the relevant
|
||||
* If not using report IDs - still have one with report ID 0
|
||||
*/
|
||||
static const USB_HID_Report_Element_t* const hidReports[] = {
|
||||
&hidReportPageConsumer
|
||||
};
|
||||
|
||||
/*
|
||||
* List all items in the HID Report descriptor.
|
||||
*/
|
||||
static const USB_HID_Short_Item_t* const hidReportDescriptorItems[] = {
|
||||
&(hidReportPageConsumer.item),
|
||||
&hidUsageConsumerControl,
|
||||
&hidCollectionApplication,
|
||||
&hidLogicalMinimum0,
|
||||
&hidLogicalMaximum1,
|
||||
&(hidUsageByte0Bit0.item),
|
||||
&(hidUsageByte0Bit1.item),
|
||||
&(hidUsageByte0Bit2.item),
|
||||
&(hidUsageByte0Bit3.item),
|
||||
&(hidUsageByte0Bit4.item),
|
||||
&(hidUsageByte0Bit5.item),
|
||||
&hidReportSize1,
|
||||
&hidReportCount6,
|
||||
&hidInputDataVar,
|
||||
&hidLogicalMaximum0,
|
||||
&hidReportCount2,
|
||||
&hidInputConstArray,
|
||||
&hidCollectionEnd
|
||||
};
|
||||
|
||||
/*
|
||||
* Define the number of HID Reports
|
||||
* Due to XC not supporting designated initializers, this constant has a hard-coded value.
|
||||
* It must equal ( sizeof hidReports / sizeof ( USB_HID_Report_Element_t* ))
|
||||
*/
|
||||
#define HID_REPORT_COUNT ( 1 )
|
||||
|
||||
#endif // __hid_report_descriptor_h__
|
||||
@@ -1,146 +1,53 @@
|
||||
// Copyright 2016-2022 XMOS LIMITED.
|
||||
// Copyright 2017-2023 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
|
||||
#include <xs1.h>
|
||||
#include <platform.h>
|
||||
#include <timer.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "xua.h"
|
||||
#include "i2c.h" /* From lib_i2c */
|
||||
|
||||
#include "cs5368.h"
|
||||
#include "cs4384.h"
|
||||
on tile[0]: out port p_ctrl = XS1_PORT_8D;
|
||||
|
||||
port p_i2c = on tile[0]:XS1_PORT_4A;
|
||||
/* p_ctrl:
|
||||
* [0:3] - Unused
|
||||
* [4] - EN_3v3_N
|
||||
* [5] - EN_3v3A
|
||||
* [6] - EXT_PLL_SEL (CS2100:0, SI: 1)
|
||||
* [7] - MCLK_DIR (Out:0, In: 1)
|
||||
*/
|
||||
#define EXT_PLL_SEL__MCLK_DIR (0x80)
|
||||
|
||||
/* General output port bit definitions */
|
||||
#define P_GPIO_DSD_MODE (1 << 0) /* DSD mode select 0 = 8i/8o I2S, 1 = 8o DSD*/
|
||||
#define P_GPIO_DAC_RST_N (1 << 1)
|
||||
#define P_GPIO_USB_SEL0 (1 << 2)
|
||||
#define P_GPIO_USB_SEL1 (1 << 3)
|
||||
#define P_GPIO_VBUS_EN (1 << 4)
|
||||
#define P_GPIO_PLL_SEL (1 << 5) /* 1 = CS2100, 0 = Phaselink clock source */
|
||||
#define P_GPIO_ADC_RST_N (1 << 6)
|
||||
#define P_GPIO_MCLK_FSEL (1 << 7) /* Select frequency on Phaselink clock. 0 = 24.576MHz for 48k, 1 = 22.5792MHz for 44.1k.*/
|
||||
|
||||
#define DAC_REGWRITE(reg, val) result = i2c.write_reg(CS4384_I2C_ADDR, reg, val);
|
||||
#define DAC_REGREAD(reg) data = i2c.read_reg(CS4384_I2C_ADDR, reg, result);
|
||||
#define ADC_REGWRITE(reg, val) result = i2c.write_reg(CS5368_I2C_ADDR, reg, val);
|
||||
|
||||
out port p_gpio = on tile[0]:XS1_PORT_8C;
|
||||
|
||||
void AudioHwConfig2(unsigned samFreq, unsigned mClk, unsigned dsdMode, unsigned sampRes_DAC, unsigned sampRes_ADC, client interface i2c_master_if i2c)
|
||||
/* Note, this runs on Tile[0] */
|
||||
void ctrlPort()
|
||||
{
|
||||
unsigned char gpioVal = 0;
|
||||
i2c_regop_res_t result;
|
||||
|
||||
/* Set master clock select appropriately and put ADC and DAC into reset */
|
||||
if (mClk == MCLK_441)
|
||||
// Drive control port to turn on 3V3 and set MCLK_DIR
|
||||
// Note, "soft-start" to reduce current spike
|
||||
// Note, 3v3_EN is inverted
|
||||
for (int i = 0; i < 30; i++)
|
||||
{
|
||||
gpioVal = P_GPIO_USB_SEL0 | P_GPIO_USB_SEL1;
|
||||
p_ctrl <: EXT_PLL_SEL__MCLK_DIR | 0x30; /* 3v3: off, 3v3A: on */
|
||||
delay_microseconds(5);
|
||||
p_ctrl <: EXT_PLL_SEL__MCLK_DIR | 0x20; /* 3v3: on, 3v3A: on */
|
||||
delay_microseconds(5);
|
||||
}
|
||||
else
|
||||
{
|
||||
gpioVal = P_GPIO_USB_SEL0 | P_GPIO_USB_SEL1 | P_GPIO_MCLK_FSEL;
|
||||
}
|
||||
|
||||
p_gpio <: gpioVal;
|
||||
|
||||
/* Allow MCLK to settle */
|
||||
delay_microseconds(20000);
|
||||
|
||||
/* Take ADC out of reset */
|
||||
gpioVal |= P_GPIO_ADC_RST_N;
|
||||
p_gpio <: gpioVal;
|
||||
|
||||
/* Configure ADC for I2S slave mode via I2C */
|
||||
unsigned dif = 0, mode = 0;
|
||||
dif = 0x01; /* I2S */
|
||||
mode = 0x03; /* Slave mode all speeds */
|
||||
|
||||
/* Reg 0x01: (GCTL) Global Mode Control Register
|
||||
* Bit[7]: CP-EN: Manages control-port mode
|
||||
* Bit[6]: CLKMODE: Setting puts part in 384x mode
|
||||
* Bit[5:4]: MDIV[1:0]: Set to 01 for /2
|
||||
* Bit[3:2]: DIF[1:0]: Data Format: 0x01 for I2S, 0x02 for TDM
|
||||
* Bit[1:0]: MODE[1:0]: Mode: 0x11 for slave mode
|
||||
*/
|
||||
ADC_REGWRITE(CS5368_GCTL_MDE, 0b10010000 | (dif << 2) | mode);
|
||||
|
||||
|
||||
/* Reg 0x06: (PDN) Power Down Register */
|
||||
/* Bit[7:6]: Reserved
|
||||
* Bit[5]: PDN-BG: When set, this bit powers-own the bandgap reference
|
||||
* Bit[4]: PDM-OSC: Controls power to internal oscillator core
|
||||
* Bit[3:0]: PDN: When any bit is set all clocks going to that channel pair are turned off
|
||||
*/
|
||||
ADC_REGWRITE(CS5368_PWR_DN, 0b00000000);
|
||||
|
||||
/* Configure DAC with PCM values. Note 2 writes to mode control to enable/disable freeze/power down */
|
||||
/* Take DAC out of reset */
|
||||
gpioVal |= P_GPIO_DAC_RST_N;
|
||||
p_gpio <: gpioVal;
|
||||
|
||||
delay_microseconds(500);
|
||||
|
||||
/* Mode Control 1 (Address: 0x02) */
|
||||
/* bit[7] : Control Port Enable (CPEN) : Set to 1 for enable
|
||||
* bit[6] : Freeze controls (FREEZE) : Set to 1 for freeze
|
||||
* bit[5] : PCM/DSD Selection (DSD/PCM) : Set to 0 for PCM
|
||||
* bit[4:1] : DAC Pair Disable (DACx_DIS) : All Dac Pairs enabled
|
||||
* bit[0] : Power Down (PDN) : Powered down
|
||||
*/
|
||||
DAC_REGWRITE(CS4384_MODE_CTRL, 0b11000001);
|
||||
|
||||
/* PCM Control (Address: 0x03) */
|
||||
/* bit[7:4] : Digital Interface Format (DIF) : 0b0001 for I2S up to 24bit
|
||||
* bit[3:2] : Reserved
|
||||
* bit[1:0] : Functional Mode (FM) : 0x00 - single-speed mode (4-50kHz)
|
||||
* : 0x01 - double-speed mode (50-100kHz)
|
||||
* : 0x10 - quad-speed mode (100-200kHz)
|
||||
* : 0x11 - auto-speed detect (32 to 200kHz)
|
||||
* (note, some Mclk/SR ratios not supported in auto)
|
||||
*
|
||||
*/
|
||||
unsigned char regVal = 0;
|
||||
if(samFreq < 50000)
|
||||
regVal = 0b00010100;
|
||||
else if(samFreq < 100000)
|
||||
regVal = 0b00010101;
|
||||
else //if(samFreq < 200000)
|
||||
regVal = 0b00010110;
|
||||
|
||||
DAC_REGWRITE(CS4384_PCM_CTRL, regVal);
|
||||
|
||||
/* Mode Control 1 (Address: 0x02) */
|
||||
/* bit[7] : Control Port Enable (CPEN) : Set to 1 for enable
|
||||
* bit[6] : Freeze controls (FREEZE) : Set to 0 for freeze
|
||||
* bit[5] : PCM/DSD Selection (DSD/PCM) : Set to 0 for PCM
|
||||
* bit[4:1] : DAC Pair Disable (DACx_DIS) : All Dac Pairs enabled
|
||||
* bit[0] : Power Down (PDN) : Not powered down
|
||||
*/
|
||||
DAC_REGWRITE(CS4384_MODE_CTRL, 0b10000000);
|
||||
|
||||
/* Kill the i2c task */
|
||||
i2c.shutdown();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Configures the external audio hardware at startup. Note this runs on Tile[1] */
|
||||
void AudioHwInit()
|
||||
{
|
||||
/* Set USB Mux to micro-b */
|
||||
/* ADC and DAC in reset */
|
||||
p_gpio <: P_GPIO_USB_SEL0 | P_GPIO_USB_SEL1;
|
||||
/* Wait for power supply to come up */
|
||||
delay_milliseconds(100);
|
||||
|
||||
/* DAC setup: For basic I2S input we don't need any register setup. DACs will clock auto detect etc.
|
||||
* It holds DAC in reset until it gets clocks anyway.
|
||||
* Note, this example doesn't use the ADC's
|
||||
*/
|
||||
}
|
||||
|
||||
void AudioHwConfig(unsigned samFreq, unsigned mClk, unsigned dsdMode,
|
||||
unsigned sampRes_DAC, unsigned sampRes_ADC)
|
||||
/* 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)
|
||||
{
|
||||
i2c_master_if i2c[1];
|
||||
par
|
||||
{
|
||||
i2c_master_single_port(i2c, 1, p_i2c, 10, 0, 1, 0);
|
||||
AudioHwConfig2(samFreq, mClk, dsdMode, sampRes_DAC, sampRes_ADC, i2c[0]);
|
||||
}
|
||||
/* Nothing required since the DAC's will auto detect the sample rate from the clocks */
|
||||
}
|
||||
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Network xmlns="http://www.xmos.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.xmos.com http://www.xmos.com" ManuallySpecifiedRouting="true">
|
||||
<Type>Board</Type>
|
||||
<Name>XS2 MC Audio</Name>
|
||||
<Declarations>
|
||||
<Declaration>tileref tile[2]</Declaration>
|
||||
<Declaration>tileref usb_tile</Declaration>
|
||||
</Declarations>
|
||||
<Packages>
|
||||
<Package id="0" Type="XS2-UnA-512-FB236">
|
||||
<Nodes>
|
||||
<Node Id="0" InPackageId="0" Type="XS2-L16A-512" Oscillator="24MHz" SystemFrequency="500MHz" referencefrequency="100MHz">
|
||||
<Boot>
|
||||
<Source Location="SPI:bootFlash"/>
|
||||
</Boot>
|
||||
<Tile Number="0" Reference="tile[0]">
|
||||
<Port Location="XS1_PORT_1B" Name="PORT_SQI_CS"/>
|
||||
<Port Location="XS1_PORT_1C" Name="PORT_SQI_SCLK"/>
|
||||
<Port Location="XS1_PORT_4B" Name="PORT_SQI_SIO"/>
|
||||
|
||||
<!-- Audio Ports -->
|
||||
<Port Location="XS1_PORT_1A" Name="PORT_PLL_REF"/>
|
||||
<Port Location="XS1_PORT_1F" Name="PORT_MCLK_IN"/>
|
||||
<Port Location="XS1_PORT_1G" Name="PORT_I2S_LRCLK"/>
|
||||
<Port Location="XS1_PORT_1H" Name="PORT_I2S_BCLK"/>
|
||||
<Port Location="XS1_PORT_1M" Name="PORT_I2S_DAC0"/>
|
||||
<port Location="XS1_PORT_1N" Name="PORT_I2S_DAC1"/>
|
||||
<port Location="XS1_PORT_1O" Name="PORT_I2S_DAC2"/>
|
||||
<port Location="XS1_PORT_1P" Name="PORT_I2S_DAC3"/>
|
||||
<Port Location="XS1_PORT_1I" Name="PORT_I2S_ADC0"/>
|
||||
<Port Location="XS1_PORT_1J" Name="PORT_I2S_ADC1"/>
|
||||
<Port Location="XS1_PORT_1K" Name="PORT_I2S_ADC2"/>
|
||||
<Port Location="XS1_PORT_1L" Name="PORT_I2S_ADC3"/>
|
||||
<Port Location="XS1_PORT_4A" Name="PORT_I2C"/>
|
||||
<Port Location="XS1_PORT_1M" Name="PORT_DSD_DAC0"/>
|
||||
<port Location="XS1_PORT_1N" Name="PORT_DSD_DAC1"/>
|
||||
<Port Location="XS1_PORT_1G" Name="PORT_DSD_CLK"/>
|
||||
<Port Location="XS1_PORT_1E" Name="PORT_ADAT_OUT"/>--> <!-- D: COAX E: OPT -->
|
||||
<Port Location="XS1_PORT_1D" Name="PORT_SPDIF_OUT"/>--> <!-- D: COAX E: OPT -->
|
||||
</Tile>
|
||||
<Tile Number="1" Reference="tile[1]">
|
||||
<!-- USB intended to run on this tile -->
|
||||
<!-- Ports for USB feedback calculation -->
|
||||
<Port Location="XS1_PORT_16B" Name="PORT_MCLK_COUNT"/>
|
||||
<Port Location="XS1_PORT_1L" Name="PORT_MCLK_IN_USB"/>
|
||||
<!-- Audio Ports -->
|
||||
<Port Location="XS1_PORT_1M" Name="PORT_MIDI_IN"/>
|
||||
<Port Location="XS1_PORT_1N" Name="PORT_MIDI_OUT"/>
|
||||
<Port Location="XS1_PORT_1O" Name="PORT_ADAT_IN"/>--> <!-- P: COAX O: OPT -->
|
||||
<Port Location="XS1_PORT_1P" Name="PORT_SPDIF_IN"/>--> <!-- P: COAX O: OPT -->
|
||||
</Tile>
|
||||
</Node>
|
||||
<Node Id="1" InPackageId="1" Type="periph:XS1-SU" Reference="usb_tile" Oscillator="24MHz">
|
||||
</Node>
|
||||
</Nodes>
|
||||
<Links>
|
||||
<Link Encoding="5wire">
|
||||
<LinkEndpoint NodeId="0" Link="8" Delays="52clk,52clk"/>
|
||||
<LinkEndpoint NodeId="1" Link="XL0" Delays="1clk,1clk"/>
|
||||
</Link>
|
||||
</Links>
|
||||
</Package>
|
||||
</Packages>
|
||||
<Nodes>
|
||||
<Node Id="2" Type="device:" RoutingId="0x8000">
|
||||
<Service Id="0" Proto="xscope_host_data(chanend c);">
|
||||
<Chanend Identifier="c" end="3"/>
|
||||
</Service>
|
||||
</Node>
|
||||
</Nodes>
|
||||
<Links>
|
||||
<Link Encoding="2wire" Delays="4,4" Flags="XSCOPE">
|
||||
<LinkEndpoint NodeId="0" Link="XL0"/>
|
||||
<LinkEndpoint NodeId="2" Chanend="1"/>
|
||||
</Link>
|
||||
</Links>
|
||||
<ExternalDevices>
|
||||
<Device NodeId="0" Tile="0" Class="SQIFlash" Name="bootFlash" Type="S25FL116K" PageSize="256" SectorSize="4096" NumPages="8192">
|
||||
<Attribute Name="PORT_SQI_CS" Value="PORT_SQI_CS"/>
|
||||
<Attribute Name="PORT_SQI_SCLK" Value="PORT_SQI_SCLK"/>
|
||||
<Attribute Name="PORT_SQI_SIO" Value="PORT_SQI_SIO"/>
|
||||
</Device>
|
||||
</ExternalDevices>
|
||||
<JTAGChain>
|
||||
<JTAGDevice NodeId="0"/>
|
||||
<JTAGDevice NodeId="1"/>
|
||||
</JTAGChain>
|
||||
</Network>
|
||||
92
examples/AN00246_xua_example/src/xk-audio-316-mc.xn
Normal file
92
examples/AN00246_xua_example/src/xk-audio-316-mc.xn
Normal file
@@ -0,0 +1,92 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Network xmlns="http://www.xmos.com"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.xmos.com http://www.xmos.com">
|
||||
<Type>Board</Type>
|
||||
<Name>xcore.ai MC Audio Board</Name>
|
||||
|
||||
<Declarations>
|
||||
<Declaration>tileref tile[2]</Declaration>
|
||||
</Declarations>
|
||||
|
||||
<Packages>
|
||||
<Package id="0" Type="XS3-UnA-1024-FB265">
|
||||
<Nodes>
|
||||
<Node Id="0" InPackageId="0" Type="XS3-L16A-1024" Oscillator="24MHz" SystemFrequency="600MHz" ReferenceFrequency="100MHz">
|
||||
<Boot>
|
||||
<Source Location="bootFlash"/>
|
||||
</Boot>
|
||||
<Tile Number="0" Reference="tile[0]">
|
||||
<Port Location="XS1_PORT_1B" Name="PORT_SQI_CS"/>
|
||||
<Port Location="XS1_PORT_1C" Name="PORT_SQI_SCLK"/>
|
||||
<Port Location="XS1_PORT_4B" Name="PORT_SQI_SIO"/>
|
||||
|
||||
<!-- Various ctrl signals -->
|
||||
<Port Location="XS1_PORT_8D" Name="PORT_CTRL"/>
|
||||
|
||||
<!-- I2C -->
|
||||
<Port Location="XS1_PORT_8D" Name="PORT_CTRL"/>
|
||||
<Port Location="XS1_PORT_8D" Name="PORT_CTRL"/>
|
||||
|
||||
<!-- Clocking -->
|
||||
<Port Location="XS1_PORT_16B" Name="PORT_MCLK_COUNT"/>
|
||||
<Port Location="XS1_PORT_1D" Name="PORT_MCLK_IN_USB"/>
|
||||
<Port Location="XS1_PORT_1A" Name="PORT_PLL_REF"/>
|
||||
|
||||
<!-- Audio Ports: Digital -->
|
||||
<Port Location="XS1_PORT_1O" Name="PORT_ADAT_IN"/> <!-- N: Coax O: Optical -->
|
||||
<Port Location="XS1_PORT_1N" Name="PORT_SPDIF_IN"/> <!-- N: Coax O: Optical -->
|
||||
|
||||
</Tile>
|
||||
<Tile Number="1" Reference="tile[1]">
|
||||
<!-- Audio Ports: I2S -->
|
||||
<Port Location="XS1_PORT_1D" Name="PORT_MCLK_IN"/>
|
||||
<Port Location="XS1_PORT_1B" Name="PORT_I2S_LRCLK"/>
|
||||
<Port Location="XS1_PORT_1C" Name="PORT_I2S_BCLK"/>
|
||||
<Port Location="XS1_PORT_1P" Name="PORT_I2S_DAC0"/>
|
||||
<port Location="XS1_PORT_1O" Name="PORT_I2S_DAC1"/>
|
||||
<port Location="XS1_PORT_1N" Name="PORT_I2S_DAC2"/>
|
||||
<port Location="XS1_PORT_1M" Name="PORT_I2S_DAC3"/>
|
||||
<Port Location="XS1_PORT_1I" Name="PORT_I2S_ADC0"/>
|
||||
<Port Location="XS1_PORT_1J" Name="PORT_I2S_ADC1"/>
|
||||
<Port Location="XS1_PORT_1K" Name="PORT_I2S_ADC2"/>
|
||||
<Port Location="XS1_PORT_1L" Name="PORT_I2S_ADC3"/>
|
||||
|
||||
<!-- Audio Ports: Digital -->
|
||||
<Port Location="XS1_PORT_1E" Name="PORT_ADAT_OUT"/> <!-- A: Coax E: Optical -->
|
||||
<Port Location="XS1_PORT_1A" Name="PORT_SPDIF_OUT"/> <!-- A: Coax E: Optical -->
|
||||
|
||||
<!-- MIDI -->
|
||||
<Port Location="XS1_PORT_1F" Name="PORT_MIDI_IN"/>
|
||||
<Port Location="XS1_PORT_4C" Name="PORT_MIDI_OUT"/> <!-- bit[0] -->
|
||||
|
||||
</Tile>
|
||||
</Node>
|
||||
</Nodes>
|
||||
</Package>
|
||||
</Packages>
|
||||
<Nodes>
|
||||
<Node Id="2" Type="device:" RoutingId="0x8000">
|
||||
<Service Id="0" Proto="xscope_host_data(chanend c);">
|
||||
<Chanend Identifier="c" end="3"/>
|
||||
</Service>
|
||||
</Node>
|
||||
</Nodes>
|
||||
<Links>
|
||||
<Link Encoding="2wire" Delays="5clk" Flags="XSCOPE">
|
||||
<LinkEndpoint NodeId="0" Link="XL0"/>
|
||||
<LinkEndpoint NodeId="2" Chanend="1"/>
|
||||
</Link>
|
||||
</Links>
|
||||
<ExternalDevices>
|
||||
<Device NodeId="0" Tile="0" Class="SQIFlash" Name="bootFlash" PageSize="256" SectorSize="4096" NumPages="8192">
|
||||
<Attribute Name="PORT_SQI_CS" Value="PORT_SQI_CS"/>
|
||||
<Attribute Name="PORT_SQI_SCLK" Value="PORT_SQI_SCLK"/>
|
||||
<Attribute Name="PORT_SQI_SIO" Value="PORT_SQI_SIO"/>
|
||||
</Device>
|
||||
</ExternalDevices>
|
||||
<JTAGChain>
|
||||
<JTAGDevice NodeId="0"/>
|
||||
</JTAGChain>
|
||||
|
||||
</Network>
|
||||
@@ -5,9 +5,9 @@
|
||||
#define _XUA_CONF_H_
|
||||
|
||||
#define NUM_USB_CHAN_OUT 2 /* Number of channels from host to device */
|
||||
#define NUM_USB_CHAN_IN 2 /* Number of channels from device to host */
|
||||
#define NUM_USB_CHAN_IN 0 /* Number of channels from device to host */
|
||||
#define I2S_CHANS_DAC 2 /* Number of I2S channels out of xCORE */
|
||||
#define I2S_CHANS_ADC 2 /* Number of I2S channels in to xCORE */
|
||||
#define I2S_CHANS_ADC 0 /* Number of I2S channels in to xCORE */
|
||||
#define MCLK_441 (512 * 44100) /* 44.1kHz family master clock frequency */
|
||||
#define MCLK_48 (512 * 48000) /* 48kHz family master clock frequency */
|
||||
#define MIN_FREQ 48000 /* Minimum sample rate */
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
APP_NAME = app_xua_simple
|
||||
APP_NAME = app_xua_spdiftx
|
||||
|
||||
TARGET = xk-audio-216-mc.xn
|
||||
TARGET = xk-audio-316-mc.xn
|
||||
|
||||
# The flags passed to xcc when building the application
|
||||
XCC_FLAGS = -fcomment-asm -Xmapper --map -Xmapper MAPFILE -O3 -report -save-temps \
|
||||
-g -Wno-unused-function -Wno-timing -DXUD_SERIES_SUPPORT=XUD_X200_SERIES \
|
||||
-DXUD_CORE_CLOCK=600 -DUSB_TILE=tile[1] -DSDA_HIGH=2 -DSCL_HIGH=1 -fxscope \
|
||||
-DUAC_FORCE_FEEDBACK_EP=0
|
||||
XCC_FLAGS = -O3 -report \
|
||||
-g -Wno-unused-function \
|
||||
-DXUD_CORE_CLOCK=600 \
|
||||
-DUSB_TILE=tile[0] \
|
||||
-fxscope
|
||||
|
||||
# The USED_MODULES variable lists other module used by the application. These
|
||||
# modules will extend the SOURCE_DIRS, INCLUDE_DIRS and LIB_DIRS variables.
|
||||
@@ -19,4 +20,3 @@ USED_MODULES = lib_xua lib_xud lib_spdif
|
||||
|
||||
XMOS_MAKE_PATH ?= ../..
|
||||
include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.common
|
||||
|
||||
|
||||
@@ -8,13 +8,13 @@ Overview
|
||||
Introduction
|
||||
............
|
||||
|
||||
The XMOS USB Audio (XUA) library provides an implemention of USB Audio Class versions 1.0 and 2.0.
|
||||
The XMOS USB Audio (XUA) library provides an implementation of USB Audio Class versions 1.0 and 2.0.
|
||||
|
||||
This application note demonstrates the implementation of a basic USB Audio Device with
|
||||
S/PDIF transmit functionality the xCORE-200 MC Audio board.
|
||||
S/PDIF transmit functionality the xCORE.ai Multichannel (MC) Audio board.
|
||||
|
||||
To reduce complexity this application note does not enable any other audio interfaces other that S/PDIF transmit
|
||||
(i.e. no I2S). Readers are encouraged to read applicaition note AN00246 in conjunction with this application
|
||||
(i.e. no I2S). Readers are encouraged to read application note AN00246 in conjunction with this application
|
||||
note.
|
||||
|
||||
|
||||
@@ -30,14 +30,11 @@ The Makefile also includes::
|
||||
|
||||
USED_MODULES = .. lib_xud ..
|
||||
|
||||
``lib_xud`` library requires some flags for correct operation. Firstly the
|
||||
``lib_xud`` library requires some flags for correct operation. Namely the
|
||||
tile on which ``lib_xud`` will be execute, for example::
|
||||
|
||||
XCC_FLAGS = .. -DUSB_TILE=tile[1] ..
|
||||
XCC_FLAGS = .. -DUSB_TILE=tile[0] ..
|
||||
|
||||
Secondly, the architecture of the target device, for example::
|
||||
|
||||
XCC_FLAGS = .. -DXUD_SERIES_SUPPORT=XUD_X200_SERIES ..
|
||||
|
||||
Includes
|
||||
--------
|
||||
@@ -45,21 +42,21 @@ Includes
|
||||
This application requires the system header that defines XMOS xCORE specific
|
||||
defines for declaring and initialising hardware:
|
||||
|
||||
.. literalinclude:: app_xua_simple.xc
|
||||
.. literalinclude:: app_xua_spdiftx.xc
|
||||
:start-on: include <xs1.h>
|
||||
:end-before: include "xua.h"
|
||||
|
||||
The XUA library functions are defined in ``xua.h``. This header must
|
||||
be included in your code to use the library.
|
||||
|
||||
.. literalinclude:: app_xua_simple.xc
|
||||
.. literalinclude:: app_xua_spdiftx.xc
|
||||
:start-on: include "xua.h"
|
||||
:end-on: include "xud_device.h"
|
||||
|
||||
The application uses the S/PDIF transmitter from ``lib_spdif``. This header
|
||||
must be included in your code.
|
||||
|
||||
.. literalinclude:: app_xua_simple.xc
|
||||
.. literalinclude:: app_xua_spdiftx.xc
|
||||
:start-on: /* From lib_spdif
|
||||
:end-on: include "spdif.h"
|
||||
|
||||
@@ -69,7 +66,7 @@ Declarations
|
||||
Allocating hardware resources for lib_xua
|
||||
.........................................
|
||||
|
||||
A minimal implementation of a USB Audio device, without I2S functionalilty,
|
||||
A minimal implementation of a USB Audio device, without I2S functionality,
|
||||
using ``lib_xua`` requires the follow pins:
|
||||
|
||||
- Audio Master clock (from clock source to xCORE)
|
||||
@@ -77,23 +74,23 @@ using ``lib_xua`` requires the follow pins:
|
||||
On an xCORE the pins are controlled by ``ports``. The application therefore declares a
|
||||
port for the master clock input signal.
|
||||
|
||||
.. literalinclude:: app_xua_simple.xc
|
||||
.. literalinclude:: app_xua_spdiftx.xc
|
||||
:start-on: /* Lib_xua port declaration
|
||||
:end-on: in port p_mclk_in
|
||||
|
||||
``lib_xua`` also requires two ports for internally calculating USB feedback. Please refer to
|
||||
the ``lib_xua`` library documentation for further details. The additonal input port for the master
|
||||
the ``lib_xua`` library documentation for further details. The additional input port for the master
|
||||
clock is required since USB and S/PDIF do not reside of the same tiles on the example hardware.
|
||||
|
||||
These ports are declared as follows:
|
||||
|
||||
.. literalinclude:: app_xua_simple.xc
|
||||
.. literalinclude:: app_xua_spdiftx.xc
|
||||
:start-on: /* Resources for USB feedback
|
||||
:end-on: in port p_mclk_in_usb
|
||||
|
||||
In addition to ``port`` resources two clock-block resources are also required:
|
||||
|
||||
.. literalinclude:: app_xua_simple.xc
|
||||
.. literalinclude:: app_xua_spdiftx.xc
|
||||
:start-on: /* Clock-block
|
||||
:end-on: clock clk_audio_mclk_usb
|
||||
|
||||
@@ -106,14 +103,14 @@ Allocating hardware resources for lib_spdif
|
||||
|
||||
The S/PDIF transmitter requires a single (buffered) 1-bit port:
|
||||
|
||||
.. literalinclude:: app_xua_simple.xc
|
||||
.. literalinclude:: app_xua_spdiftx.xc
|
||||
:start-on: /* Lib_spdif port
|
||||
:end-on: buffered out port
|
||||
|
||||
This port must be clocked from the audio master clock. This application note chooses to declare
|
||||
an extra clock-block as follows:
|
||||
|
||||
.. literalinclude:: app_xua_simple.xc
|
||||
.. literalinclude:: app_xua_spdiftx.xc
|
||||
:start-on: clock clk_spdif_tx
|
||||
:end-before: /* Lib_xua
|
||||
|
||||
@@ -126,19 +123,19 @@ Other declarations
|
||||
|
||||
For a simple application the following endpoints are required:
|
||||
|
||||
- ``Control`` enpoint zero
|
||||
- ``Control`` endpoint zero
|
||||
- ``Isochonous`` endpoint for each direction for audio data to/from the USB host
|
||||
|
||||
These are declared as follows:
|
||||
|
||||
.. literalinclude:: app_xua_simple.xc
|
||||
.. literalinclude:: app_xua_spdiftx.xc
|
||||
:start-on: /* Endpoint type tables
|
||||
:end-on: XUD_EpType epTypeTableIn
|
||||
|
||||
Configuring lib_xua
|
||||
-------------------
|
||||
|
||||
``lib_xua`` must be configued to enable S/PDIF Tx functionality.
|
||||
``lib_xua`` must be configured to enable S/PDIF Tx functionality.
|
||||
|
||||
``lib_xua`` has many parameters than can be configured at build time, some examples include:
|
||||
|
||||
@@ -164,26 +161,26 @@ The application main() function
|
||||
|
||||
The ``main()`` function sets up the tasks in the application.
|
||||
|
||||
Various channels are required in order to allow the required tasks to communcate.
|
||||
Various channels are required in order to allow the required tasks to communicate.
|
||||
These must first be declared:
|
||||
|
||||
.. literalinclude:: app_xua_simple.xc
|
||||
.. literalinclude:: app_xua_spdiftx.xc
|
||||
:start-on: /* Channels for lib_xud
|
||||
:end-on: chan c_spdif_tx
|
||||
|
||||
The rest of the ``main()`` function starts all of the tasks in parallel
|
||||
using the xC ``par`` construct:
|
||||
|
||||
.. literalinclude:: app_xua_simple.xc
|
||||
.. literalinclude:: app_xua_spdiftx.xc
|
||||
:start-on: par
|
||||
:end-before: return 0
|
||||
|
||||
This code starts the low-level USB task, an Endpoint 0 task, an Audio buffering task and a task to handle
|
||||
the audio I/O. Note, since there is no I2S funcitonality in this example this task simply forwards samples to the
|
||||
the audio I/O. Note, since there is no I2S functionality in this example this task simply forwards samples to the
|
||||
SPDIF transmitter task. In addition the ``spdif_tx()`` task is also run.
|
||||
|
||||
Note that the ``spdif_tx_port_config()`` function is called before a nested ``par`` of ``spdif_tx()`` and ``XUA_AudioHub()``.
|
||||
This is because of the "shared" nature of ``p_mclk_in`` and avoids a parrallel usage check failure by the XMOS toolchain.
|
||||
This is because of the "shared" nature of ``p_mclk_in`` and avoids a parallel usage check failure by the XMOS tool-chain.
|
||||
|
||||
|appendix|
|
||||
|newpage|
|
||||
@@ -191,9 +188,10 @@ This is because of the "shared" nature of ``p_mclk_in`` and avoids a parrallel u
|
||||
Demo Hardware Setup
|
||||
-------------------
|
||||
|
||||
To run the demo, connect a USB cable to power the xCORE-200 MC Audio board
|
||||
and plug the xTAG to the board and connect the xTAG USB cable to your
|
||||
development machine.
|
||||
To run the demo, use a USB cable to connect the on-board xTAG debug adapter (marked DEBUG) to your development computer.
|
||||
Use another USB cable to connect the USB receptacle marked USB DEVICE to the device you wish to play audio from.
|
||||
|
||||
A device capable of receiving an S/PDIF signal (ie. a speaker) should be connected to COAX TX.
|
||||
|
||||
.. figure:: images/hw_setup.*
|
||||
:width: 80%
|
||||
@@ -206,7 +204,7 @@ Launching the demo application
|
||||
------------------------------
|
||||
|
||||
Once the demo example has been built either from the command line using xmake or
|
||||
via the build mechanism of xTIMEcomposer studio it can be executed on the xCORE-200
|
||||
via the build mechanism of xTIMEcomposer studio it can be executed on the xCORE.ai
|
||||
MC Audio board.
|
||||
|
||||
Once built there will be a ``bin/`` directory within the project which contains
|
||||
@@ -221,7 +219,7 @@ on the xCORE device::
|
||||
xrun --xscope bin/app_xua_simple.xe
|
||||
|
||||
Once this command has executed the application will be running on the
|
||||
xCORE-200 MC Audio Board
|
||||
xCORE.ai MC Audio Board
|
||||
|
||||
Launching from xTIMEcomposer Studio
|
||||
...................................
|
||||
@@ -233,7 +231,7 @@ enable the xSCOPE I/O mode in the dialog box and then
|
||||
select Run.
|
||||
|
||||
Once this command has executed the application will be running on the
|
||||
xCORE-200 MC Audio board.
|
||||
xCORE.ai MC Audio board.
|
||||
|
||||
Running the application
|
||||
.......................
|
||||
@@ -272,7 +270,7 @@ Full source code listing
|
||||
Source code for main.xc
|
||||
.......................
|
||||
|
||||
.. literalinclude:: app_xua_simple.xc
|
||||
.. literalinclude:: app_xua_spdiftx.xc
|
||||
:largelisting:
|
||||
|
||||
|newpage|
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 4.2 MiB |
@@ -20,9 +20,9 @@
|
||||
#include "spdif.h"
|
||||
|
||||
/* Lib_spdif port declarations. Note, the defines come from the xn file */
|
||||
buffered out port:32 p_spdif_tx = PORT_SPDIF_OUT; /* SPDIF transmit port */
|
||||
buffered out port:32 p_spdif_tx = PORT_COAX_OUT; /* SPDIF transmit port */
|
||||
|
||||
clock clk_spdif_tx = on tile[0]: XS1_CLKBLK_4; /* Clock block for S/PDIF transmit */
|
||||
clock clk_spdif_tx = on tile[1]: XS1_CLKBLK_4; /* Clock block for S/PDIF transmit */
|
||||
|
||||
/* Lib_xua port declarations. Note, the defines come from the xn file */
|
||||
in port p_mclk_in = PORT_MCLK_IN; /* Master clock for the audio IO tile */
|
||||
@@ -32,14 +32,17 @@ in port p_for_mclk_count = PORT_MCLK_COUNT; /* Extra port for count
|
||||
in port p_mclk_in_usb = PORT_MCLK_IN_USB; /* Extra master clock input for the USB tile */
|
||||
|
||||
/* Clock-block declarations */
|
||||
clock clk_audio_mclk = on tile[0]: XS1_CLKBLK_5; /* Master clock */
|
||||
clock clk_audio_mclk_usb = on tile[1]: XS1_CLKBLK_1; /* Master clock for USB tile */
|
||||
clock clk_audio_mclk = on tile[1]: XS1_CLKBLK_5; /* Master clock */
|
||||
clock clk_audio_mclk_usb = on tile[0]: XS1_CLKBLK_1; /* Master clock for USB tile */
|
||||
|
||||
/* Endpoint type tables - informs XUD what the transfer types for each Endpoint in use and also
|
||||
* if the endpoint wishes to be informed of USB bus resets */
|
||||
XUD_EpType epTypeTableOut[] = {XUD_EPTYPE_CTL | XUD_STATUS_ENABLE, XUD_EPTYPE_ISO};
|
||||
XUD_EpType epTypeTableIn[] = {XUD_EPTYPE_CTL | XUD_STATUS_ENABLE, XUD_EPTYPE_ISO};
|
||||
|
||||
/* From hwsupport.h */
|
||||
void ctrlPort();
|
||||
|
||||
int main()
|
||||
{
|
||||
/* Channels for lib_xud */
|
||||
@@ -61,15 +64,15 @@ int main()
|
||||
par
|
||||
{
|
||||
/* Low level USB device layer core */
|
||||
on tile[1]: XUD_Main(c_ep_out, 2, c_ep_in, 2, c_sof, epTypeTableOut, epTypeTableIn, XUD_SPEED_HS, XUD_PWR_SELF);
|
||||
on tile[0]: XUD_Main(c_ep_out, 2, c_ep_in, 2, c_sof, epTypeTableOut, epTypeTableIn, XUD_SPEED_HS, XUD_PWR_SELF);
|
||||
|
||||
/* Endpoint 0 core from lib_xua */
|
||||
/* Note, since we are not using many features we pass in null for quite a few params.. */
|
||||
on tile[1]: XUA_Endpoint0(c_ep_out[0], c_ep_in[0], c_aud_ctl, null, null, null, null);
|
||||
on tile[0]: XUA_Endpoint0(c_ep_out[0], c_ep_in[0], c_aud_ctl, null, null, null, null);
|
||||
|
||||
/* Buffering cores - handles audio data to/from EP's and gives/gets data to/from the audio I/O core */
|
||||
/* Note, this spawns two cores */
|
||||
on tile[1]: {
|
||||
on tile[0]: {
|
||||
|
||||
/* Connect master-clock clock-block to clock-block pin */
|
||||
set_clock_src(clk_audio_mclk_usb, p_mclk_in_usb); /* Clock clock-block from mclk pin */
|
||||
@@ -80,11 +83,13 @@ int main()
|
||||
}
|
||||
|
||||
/* AudioHub() (I2S) and S/SPDIF Tx are on the same tile */
|
||||
on tile[0]: {
|
||||
on tile[1]: {
|
||||
|
||||
/* Setup S/PDIF tx port from clock etc - note we do this before par to avoid parallel usage */
|
||||
spdif_tx_port_config(p_spdif_tx, clk_spdif_tx, p_mclk_in, 7);
|
||||
|
||||
start_clock(clk_spdif_tx);
|
||||
|
||||
par
|
||||
{
|
||||
while(1)
|
||||
@@ -98,6 +103,8 @@ int main()
|
||||
XUA_AudioHub(c_aud, clk_audio_mclk, null, p_mclk_in, null, null, null, null, c_spdif_tx);
|
||||
}
|
||||
}
|
||||
|
||||
on tile[0]: ctrlPort();
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1,168 +0,0 @@
|
||||
// Copyright 2021-2022 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
#ifndef __hid_report_descriptor_h__
|
||||
#define __hid_report_descriptor_h__
|
||||
|
||||
#include "xua_hid_report.h"
|
||||
|
||||
#if 0
|
||||
/* Existing static report descriptor kept for reference */
|
||||
unsigned char hidReportDescriptor[] =
|
||||
{
|
||||
0x05, 0x0c, /* Usage Page (Consumer Device) */
|
||||
0x09, 0x01, /* Usage (Consumer Control) */
|
||||
0xa1, 0x01, /* Collection (Application) */
|
||||
0x15, 0x00, /* Logical Minimum (0) */
|
||||
0x25, 0x01, /* Logical Maximum (1) */
|
||||
0x09, 0xb0, /* Usage (Play) */
|
||||
0x09, 0xb5, /* Usage (Scan Next Track) */
|
||||
0x09, 0xb6, /* Usage (Scan Previous Track) */
|
||||
0x09, 0xe9, /* Usage (Volume Up) */
|
||||
0x09, 0xea, /* Usage (Volume Down) */
|
||||
0x09, 0xe2, /* Usage (Mute) */
|
||||
0x75, 0x01, /* Report Size (1) */
|
||||
0x95, 0x06, /* Report Count (6) */
|
||||
0x81, 0x02, /* Input (Data, Var, Abs) */
|
||||
0x95, 0x02, /* Report Count (2) */
|
||||
0x81, 0x01, /* Input (Cnst, Ary, Abs) */
|
||||
0xc0 /* End collection */
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Define non-configurable items in the HID Report descriptor.
|
||||
*/
|
||||
static const USB_HID_Short_Item_t hidCollectionApplication = {
|
||||
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_MAIN, HID_REPORT_ITEM_TAG_COLLECTION),
|
||||
.data = { 0x01, 0x00 } };
|
||||
static const USB_HID_Short_Item_t hidCollectionEnd = {
|
||||
.header = HID_REPORT_SET_HEADER(0, HID_REPORT_ITEM_TYPE_MAIN, HID_REPORT_ITEM_TAG_END_COLLECTION),
|
||||
.data = { 0x00, 0x00 } };
|
||||
|
||||
static const USB_HID_Short_Item_t hidInputConstArray = {
|
||||
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_MAIN, HID_REPORT_ITEM_TAG_INPUT),
|
||||
.data = { 0x01, 0x00 } };
|
||||
static const USB_HID_Short_Item_t hidInputDataVar = {
|
||||
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_MAIN, HID_REPORT_ITEM_TAG_INPUT),
|
||||
.data = { 0x02, 0x00 } };
|
||||
|
||||
static const USB_HID_Short_Item_t hidLogicalMaximum0 = {
|
||||
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_LOGICAL_MAXIMUM),
|
||||
.data = { 0x00, 0x00 } };
|
||||
static const USB_HID_Short_Item_t hidLogicalMaximum1 = {
|
||||
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_LOGICAL_MAXIMUM),
|
||||
.data = { 0x01, 0x00 } };
|
||||
static const USB_HID_Short_Item_t hidLogicalMinimum0 = {
|
||||
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_LOGICAL_MINIMUM),
|
||||
.data = { 0x00, 0x00 } };
|
||||
|
||||
static const USB_HID_Short_Item_t hidReportCount2 = {
|
||||
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_REPORT_COUNT),
|
||||
.data = { 0x02, 0x00 } };
|
||||
static const USB_HID_Short_Item_t hidReportCount6 = {
|
||||
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_REPORT_COUNT),
|
||||
.data = { 0x06, 0x00 } };
|
||||
static const USB_HID_Short_Item_t hidReportSize1 = {
|
||||
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_REPORT_SIZE),
|
||||
.data = { 0x01, 0x00 } };
|
||||
|
||||
static const USB_HID_Short_Item_t hidUsageConsumerControl = {
|
||||
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
|
||||
.data = { 0x01, 0x00 } };
|
||||
|
||||
/*
|
||||
* Define the HID Report Descriptor Item, Usage Page, Report ID and length for each HID Report
|
||||
* For internal purposes, a report element with ID of 0 must be included if report IDs are not being used.
|
||||
*/
|
||||
static const USB_HID_Report_Element_t hidReportPageConsumer = {
|
||||
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_USAGE_PAGE),
|
||||
.item.data = { USB_HID_USAGE_PAGE_ID_CONSUMER, 0x00 },
|
||||
.location = HID_REPORT_SET_LOC( 0, 2, 0, 0 )
|
||||
};
|
||||
|
||||
/*
|
||||
* Define configurable items in the HID Report descriptor.
|
||||
*/
|
||||
static USB_HID_Report_Element_t hidUsageByte0Bit5 = {
|
||||
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
|
||||
.item.data = { 0xE2, 0x00 },
|
||||
.location = HID_REPORT_SET_LOC(0, 0, 0, 5)
|
||||
}; // Mute
|
||||
static USB_HID_Report_Element_t hidUsageByte0Bit4 = {
|
||||
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
|
||||
.item.data = { 0xEA, 0x00 },
|
||||
.location = HID_REPORT_SET_LOC(0, 0, 0, 4)
|
||||
}; // Vol-
|
||||
static USB_HID_Report_Element_t hidUsageByte0Bit3 = {
|
||||
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
|
||||
.item.data = { 0xE9, 0x00 },
|
||||
.location = HID_REPORT_SET_LOC(0, 0, 0, 3)
|
||||
}; // Vol+
|
||||
static USB_HID_Report_Element_t hidUsageByte0Bit2 = {
|
||||
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
|
||||
.item.data = { 0xB6, 0x00 },
|
||||
.location = HID_REPORT_SET_LOC(0, 0, 0, 2)
|
||||
}; // Scan Prev
|
||||
static USB_HID_Report_Element_t hidUsageByte0Bit1 = {
|
||||
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
|
||||
.item.data = { 0xB5, 0x00 },
|
||||
.location = HID_REPORT_SET_LOC(0, 0, 0, 1)
|
||||
}; // Scan Next
|
||||
static USB_HID_Report_Element_t hidUsageByte0Bit0 = {
|
||||
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
|
||||
.item.data = { 0xB0, 0x00 },
|
||||
.location = HID_REPORT_SET_LOC(0, 0, 0, 0)
|
||||
}; // Play
|
||||
|
||||
/*
|
||||
* List the configurable elements in the HID Report descriptor.
|
||||
*/
|
||||
static USB_HID_Report_Element_t* const hidConfigurableElements[] = {
|
||||
&hidUsageByte0Bit0,
|
||||
&hidUsageByte0Bit1,
|
||||
&hidUsageByte0Bit2,
|
||||
&hidUsageByte0Bit3,
|
||||
&hidUsageByte0Bit4,
|
||||
&hidUsageByte0Bit5
|
||||
};
|
||||
|
||||
/*
|
||||
* List HID Reports, one per Report ID. This should be a usage page item with the relevant
|
||||
* If not using report IDs - still have one with report ID 0
|
||||
*/
|
||||
static const USB_HID_Report_Element_t* const hidReports[] = {
|
||||
&hidReportPageConsumer
|
||||
};
|
||||
|
||||
/*
|
||||
* List all items in the HID Report descriptor.
|
||||
*/
|
||||
static const USB_HID_Short_Item_t* const hidReportDescriptorItems[] = {
|
||||
&(hidReportPageConsumer.item),
|
||||
&hidUsageConsumerControl,
|
||||
&hidCollectionApplication,
|
||||
&hidLogicalMinimum0,
|
||||
&hidLogicalMaximum1,
|
||||
&(hidUsageByte0Bit0.item),
|
||||
&(hidUsageByte0Bit1.item),
|
||||
&(hidUsageByte0Bit2.item),
|
||||
&(hidUsageByte0Bit3.item),
|
||||
&(hidUsageByte0Bit4.item),
|
||||
&(hidUsageByte0Bit5.item),
|
||||
&hidReportSize1,
|
||||
&hidReportCount6,
|
||||
&hidInputDataVar,
|
||||
&hidLogicalMaximum0,
|
||||
&hidReportCount2,
|
||||
&hidInputConstArray,
|
||||
&hidCollectionEnd
|
||||
};
|
||||
|
||||
/*
|
||||
* Define the number of HID Reports
|
||||
* Due to XC not supporting designated initializers, this constant has a hard-coded value.
|
||||
* It must equal ( sizeof hidReports / sizeof ( USB_HID_Report_Element_t* ))
|
||||
*/
|
||||
#define HID_REPORT_COUNT ( 1 )
|
||||
|
||||
#endif // __hid_report_descriptor_h__
|
||||
@@ -1,52 +1,53 @@
|
||||
// Copyright 2016-2021 XMOS LIMITED.
|
||||
// Copyright 2017-2023 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
|
||||
#include <xs1.h>
|
||||
#include <platform.h>
|
||||
#include <timer.h>
|
||||
|
||||
#include "xua.h"
|
||||
|
||||
/* General output port bit definitions */
|
||||
#define P_GPIO_DSD_MODE (1 << 0) /* DSD mode select 0 = 8i/8o I2S, 1 = 8o DSD*/
|
||||
#define P_GPIO_DAC_RST_N (1 << 1)
|
||||
#define P_GPIO_USB_SEL0 (1 << 2)
|
||||
#define P_GPIO_USB_SEL1 (1 << 3)
|
||||
#define P_GPIO_VBUS_EN (1 << 4)
|
||||
#define P_GPIO_PLL_SEL (1 << 5) /* 1 = CS2100, 0 = Phaselink clock source */
|
||||
#define P_GPIO_ADC_RST_N (1 << 6)
|
||||
#define P_GPIO_MCLK_FSEL (1 << 7) /* Select frequency on Phaselink clock. 0 = 24.576MHz for 48k, 1 = 22.5792MHz for 44.1k.*/
|
||||
on tile[0]: out port p_ctrl = XS1_PORT_8D;
|
||||
|
||||
/* p_ctrl:
|
||||
* [0:3] - Unused
|
||||
* [4] - EN_3v3_N
|
||||
* [5] - EN_3v3A
|
||||
* [6] - EXT_PLL_SEL (CS2100:0, SI: 1)
|
||||
* [7] - MCLK_DIR (Out:0, In: 1)
|
||||
*/
|
||||
#define EXT_PLL_SEL__MCLK_DIR (0x80)
|
||||
|
||||
out port p_gpio = on tile[0]:XS1_PORT_8C;
|
||||
|
||||
void AudioHwConfig(unsigned samFreq, unsigned mClk, unsigned dsdMode,
|
||||
unsigned sampRes_DAC, unsigned sampRes_ADC)
|
||||
/* Note, this runs on Tile[0] */
|
||||
void ctrlPort()
|
||||
{
|
||||
unsigned char gpioVal = 0;
|
||||
|
||||
/* Set master clock select appropriately and put ADC and DAC into reset */
|
||||
if (mClk == MCLK_441)
|
||||
// Drive control port to turn on 3V3 and set MCLK_DIR
|
||||
// Note, "soft-start" to reduce current spike
|
||||
// Note, 3v3_EN is inverted
|
||||
for (int i = 0; i < 30; i++)
|
||||
{
|
||||
gpioVal = P_GPIO_USB_SEL0 | P_GPIO_USB_SEL1;
|
||||
p_ctrl <: EXT_PLL_SEL__MCLK_DIR | 0x30; /* 3v3: off, 3v3A: on */
|
||||
delay_microseconds(5);
|
||||
p_ctrl <: EXT_PLL_SEL__MCLK_DIR | 0x20; /* 3v3: on, 3v3A: on */
|
||||
delay_microseconds(5);
|
||||
}
|
||||
else
|
||||
{
|
||||
gpioVal = P_GPIO_USB_SEL0 | P_GPIO_USB_SEL1 | P_GPIO_MCLK_FSEL;
|
||||
}
|
||||
|
||||
/* Note, DAC and ADC held in reset */
|
||||
p_gpio <: gpioVal;
|
||||
|
||||
/* Allow MCLK to settle */
|
||||
delay_microseconds(20000);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Configures the external audio hardware at startup. Note this runs on Tile[1] */
|
||||
void AudioHwInit()
|
||||
{
|
||||
/* Set USB Mux to micro-b */
|
||||
/* ADC and DAC in reset */
|
||||
p_gpio <: P_GPIO_USB_SEL0 | P_GPIO_USB_SEL1;
|
||||
/* Wait for power supply to come up */
|
||||
delay_milliseconds(100);
|
||||
|
||||
/* DAC setup: For basic I2S input we don't need any register setup. DACs will clock auto detect etc.
|
||||
* It holds DAC in reset until it gets clocks anyway.
|
||||
* Note, this example doesn't use the ADC's
|
||||
*/
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
/* Nothing required since the DAC's will auto detect the sample rate from the clocks */
|
||||
}
|
||||
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Network xmlns="http://www.xmos.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.xmos.com http://www.xmos.com" ManuallySpecifiedRouting="true">
|
||||
<Type>Board</Type>
|
||||
<Name>XS2 MC Audio</Name>
|
||||
<Declarations>
|
||||
<Declaration>tileref tile[2]</Declaration>
|
||||
<Declaration>tileref usb_tile</Declaration>
|
||||
</Declarations>
|
||||
<Packages>
|
||||
<Package id="0" Type="XS2-UnA-512-FB236">
|
||||
<Nodes>
|
||||
<Node Id="0" InPackageId="0" Type="XS2-L16A-512" Oscillator="24MHz" SystemFrequency="500MHz" referencefrequency="100MHz">
|
||||
<Boot>
|
||||
<Source Location="SPI:bootFlash"/>
|
||||
</Boot>
|
||||
<Tile Number="0" Reference="tile[0]">
|
||||
<Port Location="XS1_PORT_1B" Name="PORT_SQI_CS"/>
|
||||
<Port Location="XS1_PORT_1C" Name="PORT_SQI_SCLK"/>
|
||||
<Port Location="XS1_PORT_4B" Name="PORT_SQI_SIO"/>
|
||||
|
||||
<!-- Audio Ports -->
|
||||
<Port Location="XS1_PORT_1A" Name="PORT_PLL_REF"/>
|
||||
<Port Location="XS1_PORT_1F" Name="PORT_MCLK_IN"/>
|
||||
<Port Location="XS1_PORT_1G" Name="PORT_I2S_LRCLK"/>
|
||||
<Port Location="XS1_PORT_1H" Name="PORT_I2S_BCLK"/>
|
||||
<Port Location="XS1_PORT_1M" Name="PORT_I2S_DAC0"/>
|
||||
<port Location="XS1_PORT_1N" Name="PORT_I2S_DAC1"/>
|
||||
<port Location="XS1_PORT_1O" Name="PORT_I2S_DAC2"/>
|
||||
<port Location="XS1_PORT_1P" Name="PORT_I2S_DAC3"/>
|
||||
<Port Location="XS1_PORT_1I" Name="PORT_I2S_ADC0"/>
|
||||
<Port Location="XS1_PORT_1J" Name="PORT_I2S_ADC1"/>
|
||||
<Port Location="XS1_PORT_1K" Name="PORT_I2S_ADC2"/>
|
||||
<Port Location="XS1_PORT_1L" Name="PORT_I2S_ADC3"/>
|
||||
<Port Location="XS1_PORT_4A" Name="PORT_I2C"/>
|
||||
<Port Location="XS1_PORT_1M" Name="PORT_DSD_DAC0"/>
|
||||
<port Location="XS1_PORT_1N" Name="PORT_DSD_DAC1"/>
|
||||
<Port Location="XS1_PORT_1G" Name="PORT_DSD_CLK"/>
|
||||
<Port Location="XS1_PORT_1E" Name="PORT_ADAT_OUT"/>--> <!-- D: COAX E: OPT -->
|
||||
<Port Location="XS1_PORT_1D" Name="PORT_SPDIF_OUT"/>--> <!-- D: COAX E: OPT -->
|
||||
</Tile>
|
||||
<Tile Number="1" Reference="tile[1]">
|
||||
<!-- USB intended to run on this tile -->
|
||||
<!-- Ports for USB feedback calculation -->
|
||||
<Port Location="XS1_PORT_16B" Name="PORT_MCLK_COUNT"/>
|
||||
<Port Location="XS1_PORT_1L" Name="PORT_MCLK_IN_USB"/>
|
||||
<!-- Audio Ports -->
|
||||
<Port Location="XS1_PORT_1M" Name="PORT_MIDI_IN"/>
|
||||
<Port Location="XS1_PORT_1N" Name="PORT_MIDI_OUT"/>
|
||||
<Port Location="XS1_PORT_1O" Name="PORT_ADAT_IN"/>--> <!-- P: COAX O: OPT -->
|
||||
<Port Location="XS1_PORT_1P" Name="PORT_SPDIF_IN"/>--> <!-- P: COAX O: OPT -->
|
||||
</Tile>
|
||||
</Node>
|
||||
<Node Id="1" InPackageId="1" Type="periph:XS1-SU" Reference="usb_tile" Oscillator="24MHz">
|
||||
</Node>
|
||||
</Nodes>
|
||||
<Links>
|
||||
<Link Encoding="5wire">
|
||||
<LinkEndpoint NodeId="0" Link="8" Delays="52clk,52clk"/>
|
||||
<LinkEndpoint NodeId="1" Link="XL0" Delays="1clk,1clk"/>
|
||||
</Link>
|
||||
</Links>
|
||||
</Package>
|
||||
</Packages>
|
||||
<Nodes>
|
||||
<Node Id="2" Type="device:" RoutingId="0x8000">
|
||||
<Service Id="0" Proto="xscope_host_data(chanend c);">
|
||||
<Chanend Identifier="c" end="3"/>
|
||||
</Service>
|
||||
</Node>
|
||||
</Nodes>
|
||||
<Links>
|
||||
<Link Encoding="2wire" Delays="4,4" Flags="XSCOPE">
|
||||
<LinkEndpoint NodeId="0" Link="XL0"/>
|
||||
<LinkEndpoint NodeId="2" Chanend="1"/>
|
||||
</Link>
|
||||
</Links>
|
||||
<ExternalDevices>
|
||||
<Device NodeId="0" Tile="0" Class="SQIFlash" Name="bootFlash" Type="S25FL116K" PageSize="256" SectorSize="4096" NumPages="8192">
|
||||
<Attribute Name="PORT_SQI_CS" Value="PORT_SQI_CS"/>
|
||||
<Attribute Name="PORT_SQI_SCLK" Value="PORT_SQI_SCLK"/>
|
||||
<Attribute Name="PORT_SQI_SIO" Value="PORT_SQI_SIO"/>
|
||||
</Device>
|
||||
</ExternalDevices>
|
||||
<JTAGChain>
|
||||
<JTAGDevice NodeId="0"/>
|
||||
<JTAGDevice NodeId="1"/>
|
||||
</JTAGChain>
|
||||
</Network>
|
||||
92
examples/AN00247_xua_example_spdif_tx/src/xk-audio-316-mc.xn
Normal file
92
examples/AN00247_xua_example_spdif_tx/src/xk-audio-316-mc.xn
Normal file
@@ -0,0 +1,92 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Network xmlns="http://www.xmos.com"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.xmos.com http://www.xmos.com">
|
||||
<Type>Board</Type>
|
||||
<Name>xcore.ai MC Audio Board</Name>
|
||||
|
||||
<Declarations>
|
||||
<Declaration>tileref tile[2]</Declaration>
|
||||
</Declarations>
|
||||
|
||||
<Packages>
|
||||
<Package id="0" Type="XS3-UnA-1024-FB265">
|
||||
<Nodes>
|
||||
<Node Id="0" InPackageId="0" Type="XS3-L16A-1024" Oscillator="24MHz" SystemFrequency="600MHz" ReferenceFrequency="100MHz">
|
||||
<Boot>
|
||||
<Source Location="bootFlash"/>
|
||||
</Boot>
|
||||
<Tile Number="0" Reference="tile[0]">
|
||||
<Port Location="XS1_PORT_1B" Name="PORT_SQI_CS"/>
|
||||
<Port Location="XS1_PORT_1C" Name="PORT_SQI_SCLK"/>
|
||||
<Port Location="XS1_PORT_4B" Name="PORT_SQI_SIO"/>
|
||||
|
||||
<!-- Various ctrl signals -->
|
||||
<Port Location="XS1_PORT_8D" Name="PORT_CTRL"/>
|
||||
|
||||
<!-- I2C -->
|
||||
<Port Location="XS1_PORT_8D" Name="PORT_CTRL"/>
|
||||
<Port Location="XS1_PORT_8D" Name="PORT_CTRL"/>
|
||||
|
||||
<!-- Clocking -->
|
||||
<Port Location="XS1_PORT_16B" Name="PORT_MCLK_COUNT"/>
|
||||
<Port Location="XS1_PORT_1D" Name="PORT_MCLK_IN_USB"/>
|
||||
<Port Location="XS1_PORT_1A" Name="PORT_PLL_REF"/>
|
||||
|
||||
<!-- Audio Ports: Digital -->
|
||||
<Port Location="XS1_PORT_1O" Name="PORT_OPTICAL_IN"/>
|
||||
<Port Location="XS1_PORT_1N" Name="PORT_COAX_IN"/>
|
||||
|
||||
</Tile>
|
||||
<Tile Number="1" Reference="tile[1]">
|
||||
<!-- Audio Ports: I2S -->
|
||||
<Port Location="XS1_PORT_1D" Name="PORT_MCLK_IN"/>
|
||||
<Port Location="XS1_PORT_1B" Name="PORT_I2S_LRCLK"/>
|
||||
<Port Location="XS1_PORT_1C" Name="PORT_I2S_BCLK"/>
|
||||
<Port Location="XS1_PORT_1P" Name="PORT_I2S_DAC0"/>
|
||||
<port Location="XS1_PORT_1O" Name="PORT_I2S_DAC1"/>
|
||||
<port Location="XS1_PORT_1N" Name="PORT_I2S_DAC2"/>
|
||||
<port Location="XS1_PORT_1M" Name="PORT_I2S_DAC3"/>
|
||||
<Port Location="XS1_PORT_1I" Name="PORT_I2S_ADC0"/>
|
||||
<Port Location="XS1_PORT_1J" Name="PORT_I2S_ADC1"/>
|
||||
<Port Location="XS1_PORT_1K" Name="PORT_I2S_ADC2"/>
|
||||
<Port Location="XS1_PORT_1L" Name="PORT_I2S_ADC3"/>
|
||||
|
||||
<!-- Audio Ports: Digital -->
|
||||
<Port Location="XS1_PORT_1G" Name="PORT_OPTICAL_OUT"/>
|
||||
<Port Location="XS1_PORT_1A" Name="PORT_COAX_OUT"/>
|
||||
|
||||
<!-- MIDI -->
|
||||
<Port Location="XS1_PORT_1F" Name="PORT_MIDI_IN"/>
|
||||
<Port Location="XS1_PORT_4C" Name="PORT_MIDI_OUT"/> <!-- bit[0] -->
|
||||
|
||||
</Tile>
|
||||
</Node>
|
||||
</Nodes>
|
||||
</Package>
|
||||
</Packages>
|
||||
<Nodes>
|
||||
<Node Id="2" Type="device:" RoutingId="0x8000">
|
||||
<Service Id="0" Proto="xscope_host_data(chanend c);">
|
||||
<Chanend Identifier="c" end="3"/>
|
||||
</Service>
|
||||
</Node>
|
||||
</Nodes>
|
||||
<Links>
|
||||
<Link Encoding="2wire" Delays="5clk" Flags="XSCOPE">
|
||||
<LinkEndpoint NodeId="0" Link="XL0"/>
|
||||
<LinkEndpoint NodeId="2" Chanend="1"/>
|
||||
</Link>
|
||||
</Links>
|
||||
<ExternalDevices>
|
||||
<Device NodeId="0" Tile="0" Class="SQIFlash" Name="bootFlash" PageSize="256" SectorSize="4096" NumPages="8192">
|
||||
<Attribute Name="PORT_SQI_CS" Value="PORT_SQI_CS"/>
|
||||
<Attribute Name="PORT_SQI_SCLK" Value="PORT_SQI_SCLK"/>
|
||||
<Attribute Name="PORT_SQI_SIO" Value="PORT_SQI_SIO"/>
|
||||
</Device>
|
||||
</ExternalDevices>
|
||||
<JTAGChain>
|
||||
<JTAGDevice NodeId="0"/>
|
||||
</JTAGChain>
|
||||
|
||||
</Network>
|
||||
@@ -4,29 +4,28 @@
|
||||
#ifndef _XUA_CONF_H_
|
||||
#define _XUA_CONF_H_
|
||||
|
||||
#define NUM_USB_CHAN_OUT 2
|
||||
#define NUM_USB_CHAN_IN 0
|
||||
#define I2S_CHANS_DAC 0
|
||||
#define I2S_CHANS_ADC 0
|
||||
#define MCLK_441 (512 * 44100)
|
||||
#define MCLK_48 (512 * 48000)
|
||||
#define MIN_FREQ 48000
|
||||
#define MAX_FREQ 48000
|
||||
#define NUM_USB_CHAN_OUT (2)
|
||||
#define NUM_USB_CHAN_IN (0)
|
||||
#define I2S_CHANS_DAC (0)
|
||||
#define I2S_CHANS_ADC (0)
|
||||
#define MCLK_441 (512 * 44100)
|
||||
#define MCLK_48 (512 * 48000)
|
||||
#define MIN_FREQ (48000)
|
||||
#define MAX_FREQ (48000)
|
||||
|
||||
#define EXCLUDE_USB_AUDIO_MAIN
|
||||
|
||||
#define XUA_SPDIF_TX_EN 1
|
||||
#define SPDIF_TX_INDEX 0
|
||||
#define VENDOR_STR "XMOS"
|
||||
#define VENDOR_ID 0x20B1
|
||||
#define PRODUCT_STR_A2 "XUA SPDIF Example"
|
||||
#define PRODUCT_STR_A1 "XUA SPDIF Example"
|
||||
#define PID_AUDIO_1 1
|
||||
#define PID_AUDIO_2 2
|
||||
#define AUDIO_CLASS 2
|
||||
#define AUDIO_CLASS_FALLBACK 0
|
||||
#define BCD_DEVICE 0x1234
|
||||
#define XUA_DFU_EN 0
|
||||
#define MIC_DUAL_ENABLED 0 // Use multi-threaded design
|
||||
#define XUA_SPDIF_TX_EN (1)
|
||||
#define SPDIF_TX_INDEX (0)
|
||||
#define VENDOR_STR "XMOS"
|
||||
#define VENDOR_ID 0x20B1
|
||||
#define PRODUCT_STR_A2 "XUA SPDIF Example"
|
||||
#define PRODUCT_STR_A1 "XUA SPDIF Example"
|
||||
#define PID_AUDIO_1 (1)
|
||||
#define PID_AUDIO_2 (2)
|
||||
#define AUDIO_CLASS (2)
|
||||
#define AUDIO_CLASS_FALLBACK (0)
|
||||
#define BCD_DEVICE (0x1234)
|
||||
#define XUA_DFU_EN (0)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
// Copyright 2017-2021 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
|
||||
#include "xua_conf.h"
|
||||
|
||||
/* TODO */
|
||||
#define XUD_UAC_NUM_USB_CHAN_OUT NUM_USB_CHAN_OUT
|
||||
#define XUD_UAC_NUM_USB_CHAN_IN NUM_USB_CHAN_IN
|
||||
@@ -19,4 +19,3 @@ USED_MODULES = lib_xua lib_xud lib_mic_array
|
||||
|
||||
XMOS_MAKE_PATH ?= ../..
|
||||
include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.common
|
||||
|
||||
|
||||
@@ -36,15 +36,11 @@ The Makefile therefore also includes this lib::
|
||||
|
||||
USED_MODULES = .. lib_xud ..
|
||||
|
||||
``lib_xud`` library requires some flags for correct operation. Firstly the
|
||||
``lib_xud`` library requires some flags for correct operation. Namely the
|
||||
tile on which ``lib_xud`` will be executed, for example::
|
||||
|
||||
XCC_FLAGS = .. -DUSB_TILE=tile[1] ..
|
||||
|
||||
Secondly, the architecture of the target device, for example::
|
||||
|
||||
XCC_FLAGS = .. -DXUD_SERIES_SUPPORT=XUD_X200_SERIES ..
|
||||
|
||||
Includes
|
||||
--------
|
||||
|
||||
@@ -228,7 +224,7 @@ The ``mic_array_pdm_rx()`` task expects the PDM microphone port to be clocked fr
|
||||
Demo Hardware Setup
|
||||
-------------------
|
||||
|
||||
To run the demo, connect a USB cable to power the xCORE-200 MC Audio board
|
||||
To run the demo, connect a USB cable to power the xCORE-200 Array Microphone board
|
||||
and plug the xTAG to the board and connect the xTAG USB cable to your
|
||||
development machine.
|
||||
|
||||
@@ -244,7 +240,7 @@ Launching the demo application
|
||||
|
||||
Once the demo example has been built either from the command line using xmake or
|
||||
via the build mechanism of xTIMEcomposer studio it can be executed on the xCORE-200
|
||||
MC Audio board.
|
||||
Array Microphone board.
|
||||
|
||||
Once built there will be a ``bin/`` directory within the project which contains
|
||||
the binary for the xCORE device. The xCORE binary has a XMOS standard .xe extension.
|
||||
@@ -258,7 +254,7 @@ on the xCORE device::
|
||||
xrun --xscope bin/app_xua_simple.xe
|
||||
|
||||
Once this command has executed the application will be running on the
|
||||
xCORE-200 MC Audio Board
|
||||
xCORE-200 Array Microphone board
|
||||
|
||||
Launching from xTIMEcomposer Studio
|
||||
...................................
|
||||
@@ -270,7 +266,7 @@ enable the xSCOPE I/O mode in the dialog box and then
|
||||
select Run.
|
||||
|
||||
Once this command has executed the application will be running on the
|
||||
xCORE-200 MC Audio board.
|
||||
xCORE-200 Array Microphone board.
|
||||
|
||||
Running the application
|
||||
.......................
|
||||
|
||||
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,97 +0,0 @@
|
||||
TARGET = xk-audio-216-mc.xn
|
||||
USED_MODULES = lib_xua lib_i2c lib_logging
|
||||
|
||||
BUILD_FLAGS = -O0 -g -lflash -DXUD_SERIES_SUPPORT=4 -DXUD_CORE_CLOCK=600 -fxscope -save-temps -march=xs2a -DUSB_TILE=tile[1]
|
||||
|
||||
BUILD_FLAGS_i2s_master_2in_2out_48khz = $(BUILD_FLAGS) \
|
||||
-D ADAT_RX=0 -D ADAT_TX=0 -D SPDIF_RX=0 -D SPDIF_TX=0 -D MIDI=0 \
|
||||
-D NUM_USB_CHAN_IN=2 -D NUM_USB_CHAN_OUT=2 -DI2S_CHANS_ADC=2 -DI2S_CHANS_DAC=2 \
|
||||
-D DEFAULT_FREQ=48000
|
||||
|
||||
BUILD_FLAGS_i2s_slave_2in_2out_48khz = $(BUILD_FLAGS) \
|
||||
-D ADAT_RX=0 -D ADAT_TX=0 -D SPDIF_RX=0 -D SPDIF_TX=0 -D MIDI=0 \
|
||||
-D NUM_USB_CHAN_IN=2 -D NUM_USB_CHAN_OUT=2 -DI2S_CHANS_ADC=2 -DI2S_CHANS_DAC=2 \
|
||||
-D DEFAULT_FREQ=48000 -DCODEC_MASTER=1
|
||||
|
||||
BUILD_FLAGS_i2s_master_2in_2out_192khz = $(BUILD_FLAGS) \
|
||||
-D ADAT_RX=0 -D ADAT_TX=0 -D SPDIF_RX=0 -D SPDIF_TX=0 -D MIDI=0 \
|
||||
-D NUM_USB_CHAN_IN=2 -D NUM_USB_CHAN_OUT=2 -D I2S_CHANS_ADC=2 -D I2S_CHANS_DAC=2 \
|
||||
-D DEFAULT_FREQ=192000
|
||||
|
||||
BUILD_FLAGS_i2s_slave_2in_2out_192khz = $(BUILD_FLAGS) \
|
||||
-D ADAT_RX=0 -D ADAT_TX=0 -D SPDIF_RX=0 -D SPDIF_TX=0 -D MIDI=0 \
|
||||
-D NUM_USB_CHAN_IN=2 -D NUM_USB_CHAN_OUT=2 -DI2S_CHANS_ADC=2 -DI2S_CHANS_DAC=2 \
|
||||
-D DEFAULT_FREQ=192000 -DCODEC_MASTER=1
|
||||
|
||||
BUILD_FLAGS_i2s_master_8in_8out_48khz = $(BUILD_FLAGS) \
|
||||
-D ADAT_RX=0 -D ADAT_TX=0 -D SPDIF_RX=0 -D SPDIF_TX=0 -D MIDI=0 \
|
||||
-D NUM_USB_CHAN_IN=8 -D NUM_USB_CHAN_OUT=8 -D I2S_CHANS_ADC=8 -D I2S_CHANS_DAC=8 \
|
||||
-D DEFAULT_FREQ=48000
|
||||
|
||||
BUILD_FLAGS_i2s_slave_8in_8out_48khz = $(BUILD_FLAGS) \
|
||||
-D ADAT_RX=0 -D ADAT_TX=0 -D SPDIF_RX=0 -D SPDIF_TX=0 -D MIDI=0 \
|
||||
-D NUM_USB_CHAN_IN=8 -D NUM_USB_CHAN_OUT=8 -D I2S_CHANS_ADC=8 -D I2S_CHANS_DAC=8 \
|
||||
-D DEFAULT_FREQ=48000 -DCODEC_MASTER=1
|
||||
|
||||
BUILD_FLAGS_i2s_master_8in_8out_192khz = $(BUILD_FLAGS) \
|
||||
-D ADAT_RX=0 -D ADAT_TX=0 -D SPDIF_RX=0 -D SPDIF_TX=0 -D MIDI=0 \
|
||||
-D NUM_USB_CHAN_IN=8 -D NUM_USB_CHAN_OUT=8 -D I2S_CHANS_ADC=8 -D I2S_CHANS_DAC=8 \
|
||||
-D DEFAULT_FREQ=192000 \
|
||||
-O2 # optimisations to meet timing
|
||||
|
||||
BUILD_FLAGS_i2s_slave_8in_8out_192khz = $(BUILD_FLAGS) \
|
||||
-D ADAT_RX=0 -D ADAT_TX=0 -D SPDIF_RX=0 -D SPDIF_TX=0 -D MIDI=0 \
|
||||
-D NUM_USB_CHAN_IN=8 -D NUM_USB_CHAN_OUT=8 -D I2S_CHANS_ADC=8 -D I2S_CHANS_DAC=8 \
|
||||
-D DEFAULT_FREQ=192000 -DCODEC_MASTER=1 \
|
||||
-O2 # optimisations to meet timing
|
||||
|
||||
BUILD_FLAGS_tdm_master_8in_8out_48khz = $(BUILD_FLAGS) -D I2S_MODE_TDM=1 \
|
||||
-D ADAT_RX=0 -D ADAT_TX=0 -D SPDIF_RX=0 -D SPDIF_TX=0 -D MIDI=0 \
|
||||
-D NUM_USB_CHAN_IN=8 -D NUM_USB_CHAN_OUT=8 -D I2S_CHANS_ADC=8 -D I2S_CHANS_DAC=8 \
|
||||
-D DEFAULT_FREQ=48000 \
|
||||
-O2 # optimisations to meet timing
|
||||
|
||||
BUILD_FLAGS_tdm_slave_8in_8out_48khz = $(BUILD_FLAGS) -D I2S_MODE_TDM=1 \
|
||||
-D ADAT_RX=0 -D ADAT_TX=0 -D SPDIF_RX=0 -D SPDIF_TX=0 -D MIDI=0 \
|
||||
-D NUM_USB_CHAN_IN=8 -D NUM_USB_CHAN_OUT=8 -D I2S_CHANS_ADC=8 -D I2S_CHANS_DAC=8 \
|
||||
-D DEFAULT_FREQ=48000 -DCODEC_MASTER=1 \
|
||||
-O2 # optimisations to meet timing
|
||||
|
||||
BUILD_FLAGS_tdm_master_16in_16out_48khz = $(BUILD_FLAGS) -D I2S_MODE_TDM=1 \
|
||||
-D ADAT_RX=0 -D ADAT_TX=0 -D SPDIF_RX=0 -D SPDIF_TX=0 -D MIDI=0 \
|
||||
-D NUM_USB_CHAN_IN=16 -D NUM_USB_CHAN_OUT=16 -D I2S_CHANS_ADC=16 -D I2S_CHANS_DAC=16 \
|
||||
-D DEFAULT_FREQ=48000 \
|
||||
-O2 # optimisations to meet timing
|
||||
|
||||
BUILD_FLAGS_tdm_slave_16in_16out_48khz = $(BUILD_FLAGS) -D I2S_MODE_TDM=1 \
|
||||
-D ADAT_RX=0 -D ADAT_TX=0 -D SPDIF_RX=0 -D SPDIF_TX=0 -D MIDI=0 \
|
||||
-D NUM_USB_CHAN_IN=16 -D NUM_USB_CHAN_OUT=16 -D I2S_CHANS_ADC=16 -D I2S_CHANS_DAC=16 \
|
||||
-D DEFAULT_FREQ=48000 -DCODEC_MASTER=1 \
|
||||
-O2 # optimisations to meet timing
|
||||
|
||||
#XCC_FLAGS_hardware_i2s_master_2in_2out_48khz = -D HARDWARE $(BUILD_FLAGS_i2s_master_2in_2out_48khz)
|
||||
#XCC_FLAGS_hardware_i2s_master_2in_2out_192khz = -D HARDWARE $(BUILD_FLAGS_i2s_master_2in_2out_192khz)
|
||||
#XCC_FLAGS_hardware_i2s_master_8in_8out_48khz = -D HARDWARE $(BUILD_FLAGS_i2s_master_8in_8out_48khz)
|
||||
#XCC_FLAGS_hardware_i2s_master_8in_8out_192khz = -D HARDWARE $(BUILD_FLAGS_i2s_master_8in_8out_192khz)
|
||||
#XCC_FLAGS_hardware_tdm_master_8in_8out_48khz = -D HARDWARE $(BUILD_FLAGS_tdm_master_8in_8out_48khz)
|
||||
|
||||
XCC_FLAGS_simulation_i2s_master_2in_2out_48khz = -D SIMULATION $(BUILD_FLAGS_i2s_master_2in_2out_48khz)
|
||||
XCC_FLAGS_simulation_i2s_slave_2in_2out_48khz = -D SIMULATION $(BUILD_FLAGS_i2s_slave_2in_2out_48khz)
|
||||
|
||||
XCC_FLAGS_simulation_i2s_master_2in_2out_192khz = -D SIMULATION $(BUILD_FLAGS_i2s_master_2in_2out_192khz)
|
||||
XCC_FLAGS_simulation_i2s_slave_2in_2out_192khz = -D SIMULATION $(BUILD_FLAGS_i2s_slave_2in_2out_192khz)
|
||||
|
||||
XCC_FLAGS_simulation_i2s_master_8in_8out_48khz = -D SIMULATION $(BUILD_FLAGS_i2s_master_8in_8out_48khz)
|
||||
XCC_FLAGS_simulation_i2s_slave_8in_8out_48khz = -D SIMULATION $(BUILD_FLAGS_i2s_slave_8in_8out_48khz)
|
||||
|
||||
XCC_FLAGS_simulation_i2s_master_8in_8out_192khz = -D SIMULATION $(BUILD_FLAGS_i2s_master_8in_8out_192khz)
|
||||
XCC_FLAGS_simulation_i2s_slave_8in_8out_192khz = -D SIMULATION $(BUILD_FLAGS_i2s_slave_8in_8out_192khz)
|
||||
|
||||
XCC_FLAGS_simulation_tdm_master_8in_8out_48khz = -D SIMULATION $(BUILD_FLAGS_tdm_master_8in_8out_48khz)
|
||||
XCC_FLAGS_simulation_tdm_slave_8in_8out_48khz = -D SIMULATION $(BUILD_FLAGS_tdm_slave_8in_8out_48khz)
|
||||
|
||||
XCC_FLAGS_simulation_tdm_master_16in_16out_48khz = -D SIMULATION $(BUILD_FLAGS_tdm_master_16in_16out_48khz)
|
||||
XCC_FLAGS_simulation_tdm_slave_16in_16out_48khz = -D SIMULATION $(BUILD_FLAGS_tdm_slave_16in_16out_48khz)
|
||||
|
||||
XMOS_MAKE_PATH ?= ../..
|
||||
-include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.common
|
||||
@@ -1,33 +0,0 @@
|
||||
// Copyright 2017-2021 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
#ifndef CS4384_H_
|
||||
#define CS4384_H_
|
||||
|
||||
//Address on I2C bus
|
||||
#define CS4384_I2C_ADDR (0x18)
|
||||
|
||||
//Register Addresess
|
||||
#define CS4384_CHIP_REV 0x01
|
||||
#define CS4384_MODE_CTRL 0x02
|
||||
#define CS4384_PCM_CTRL 0x03
|
||||
#define CS4384_DSD_CTRL 0x04
|
||||
#define CS4384_FLT_CTRL 0x05
|
||||
#define CS4384_INV_CTRL 0x06
|
||||
#define CS4384_GRP_CTRL 0x07
|
||||
#define CS4384_RMP_MUTE 0x08
|
||||
#define CS4384_MUTE_CTRL 0x09
|
||||
#define CS4384_MIX_PR1 0x0a
|
||||
#define CS4384_VOL_A1 0x0b
|
||||
#define CS4384_VOL_B1 0x0c
|
||||
#define CS4384_MIX_PR2 0x0d
|
||||
#define CS4384_VOL_A2 0x0e
|
||||
#define CS4384_VOL_B2 0x0f
|
||||
#define CS4384_MIX_PR3 0x10
|
||||
#define CS4384_VOL_A3 0x11
|
||||
#define CS4384_VOL_B3 0x12
|
||||
#define CS4384_MIX_PR4 0x13
|
||||
#define CS4384_VOL_A4 0x14
|
||||
#define CS4384_VOL_B4 0x15
|
||||
#define CS4384_CM_MODE 0x16
|
||||
|
||||
#endif /* CS4384_H_ */
|
||||
@@ -1,19 +0,0 @@
|
||||
// Copyright 2017-2021 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
#ifndef _CS5368_H_
|
||||
#define _CS5368_H_
|
||||
|
||||
//Address on I2C bus
|
||||
#define CS5368_I2C_ADDR (0x4C)
|
||||
|
||||
//Register Addresess
|
||||
#define CS5368_CHIP_REV 0x00
|
||||
#define CS5368_GCTL_MDE 0x01
|
||||
#define CS5368_OVFL_ST 0x02
|
||||
#define CS5368_OVFL_MSK 0x03
|
||||
#define CS5368_HPF_CTRL 0x04
|
||||
#define CS5368_PWR_DN 0x06
|
||||
#define CS5368_MUTE_CTRL 0x08
|
||||
#define CS5368_SDO_EN 0x0a
|
||||
|
||||
#endif /* _CS5368_H_ */
|
||||
@@ -1,23 +0,0 @@
|
||||
#!/usr/bin/env python2.7
|
||||
# Copyright 2018-2021 XMOS LIMITED.
|
||||
# This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
import xmostest
|
||||
import os.path
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
|
||||
xmostest.init()
|
||||
|
||||
xmostest.register_group("lib_xua",
|
||||
"i2s_loopback_sim_tests",
|
||||
"I2S loopback simulator tests",
|
||||
|
||||
"""
|
||||
Tests are performed by running the audiohub code connected to a
|
||||
loopback plugin
|
||||
""")
|
||||
|
||||
xmostest.runtests()
|
||||
|
||||
xmostest.finish()
|
||||
@@ -1,51 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# Copyright 2018-2021 XMOS LIMITED.
|
||||
# This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
import xmostest
|
||||
|
||||
def runtest_one_config(env, format, i2s_role, num_chans_in, num_chans_out, sample_rate):
|
||||
testlevel = 'smoke'
|
||||
resources = xmostest.request_resource('xsim')
|
||||
|
||||
binary = 'app_test_i2s_loopback/bin/{env}_{format}_{i2s_role}_{num_chans_in}in_{num_chans_out}out_{sample_rate}/app_test_i2s_loopback_{env}_{format}_{i2s_role}_{num_chans_in}in_{num_chans_out}out_{sample_rate}.xe'.format(env=env, format=format, i2s_role=i2s_role, num_chans_in=num_chans_in, num_chans_out=num_chans_out, sample_rate=sample_rate)
|
||||
tester = xmostest.ComparisonTester(open('pass.expect'),
|
||||
'lib_xua',
|
||||
'i2s_loopback_sim_tests',
|
||||
'i2s_loopback',
|
||||
{'env':env,
|
||||
'format':format,
|
||||
'i2s_role':i2s_role,
|
||||
'num_chans_in':num_chans_in,
|
||||
'num_chans_out':num_chans_out,
|
||||
'sample_rate':sample_rate})
|
||||
tester.set_min_testlevel(testlevel)
|
||||
loopback_args= '-port tile[0] XS1_PORT_1M 1 0 -port tile[0] XS1_PORT_1I 1 0 ' + \
|
||||
'-port tile[0] XS1_PORT_1N 1 0 -port tile[0] XS1_PORT_1J 1 0 ' + \
|
||||
'-port tile[0] XS1_PORT_1O 1 0 -port tile[0] XS1_PORT_1K 1 0 ' + \
|
||||
'-port tile[0] XS1_PORT_1P 1 0 -port tile[0] XS1_PORT_1L 1 0 ' + \
|
||||
'-port tile[0] XS1_PORT_1A 1 0 -port tile[0] XS1_PORT_1F 1 0 '
|
||||
if i2s_role == 'slave':
|
||||
loopback_args += '-port tile[0] XS1_PORT_1B 1 0 -port tile[0] XS1_PORT_1H 1 0 ' #bclk
|
||||
loopback_args += '-port tile[0] XS1_PORT_1C 1 0 -port tile[0] XS1_PORT_1G 1 0 ' #lrclk
|
||||
|
||||
max_cycles = 1500000 #enough to reach the 10 skip + 100 test in sim at 48kHz
|
||||
xmostest.run_on_simulator(resources['xsim'], binary, tester=tester, simargs=['--max-cycles', str(max_cycles), '--plugin', 'LoopbackPort.dll', loopback_args])
|
||||
|
||||
def runtest():
|
||||
runtest_one_config('simulation', 'i2s', 'master', 2, 2, '48khz')
|
||||
runtest_one_config('simulation', 'i2s', 'slave', 2, 2, '48khz')
|
||||
|
||||
runtest_one_config('simulation', 'i2s', 'master', 2, 2, '192khz')
|
||||
runtest_one_config('simulation', 'i2s', 'slave', 2, 2, '192khz')
|
||||
|
||||
runtest_one_config('simulation', 'i2s', 'master', 8, 8, '48khz')
|
||||
runtest_one_config('simulation', 'i2s', 'slave', 8, 8, '48khz')
|
||||
|
||||
runtest_one_config('simulation', 'i2s', 'master', 8, 8, '192khz')
|
||||
runtest_one_config('simulation', 'i2s', 'slave', 8, 8, '192khz')
|
||||
|
||||
runtest_one_config('simulation', 'tdm', 'master', 8, 8, '48khz')
|
||||
runtest_one_config('simulation', 'tdm', 'slave', 8, 8, '48khz')
|
||||
|
||||
runtest_one_config('simulation', 'tdm', 'master', 16, 16, '48khz')
|
||||
runtest_one_config('simulation', 'tdm', 'slave', 16, 16, '48khz')
|
||||
@@ -1,20 +1,22 @@
|
||||
// Copyright 2017-2021 XMOS LIMITED.
|
||||
// Copyright 2017-2023 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
#ifndef _XUA_H_
|
||||
#define _XUA_H_
|
||||
|
||||
#ifndef __XUA_H__
|
||||
#define __XUA_H__
|
||||
#include <xs1.h>
|
||||
|
||||
#include "xua_conf_full.h"
|
||||
|
||||
#if __XC__ || __STDC__
|
||||
#ifndef __ASSEMBLER__
|
||||
#include "xua_audiohub.h"
|
||||
|
||||
#include "xua_endpoint0.h"
|
||||
|
||||
#include "xua_buffer.h"
|
||||
#include "xua_mixer.h"
|
||||
#endif
|
||||
|
||||
#if __XC__
|
||||
#ifdef __XC__
|
||||
#include "xua_clocking.h"
|
||||
#include "xua_midi.h"
|
||||
#if XUA_NUM_PDM_MICS > 0
|
||||
#include "xua_pdm_mic.h"
|
||||
#endif
|
||||
|
||||
@@ -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.
|
||||
#ifndef __XUA_AUDIOHUB_H__
|
||||
#define __XUA_AUDIOHUB_H__
|
||||
#ifndef _XUA_AUDIOHUB_H_
|
||||
#define _XUA_AUDIOHUB_H_
|
||||
|
||||
#if __XC__
|
||||
#ifdef __XC__
|
||||
|
||||
#include "xccompat.h"
|
||||
#include "xs1.h"
|
||||
@@ -12,6 +12,8 @@
|
||||
#include "dfu_interface.h"
|
||||
#endif
|
||||
|
||||
#include "xua_clocking.h"
|
||||
|
||||
/** The audio driver thread.
|
||||
*
|
||||
* This function drives I2S ports and handles samples to/from other digital
|
||||
@@ -22,7 +24,7 @@
|
||||
*
|
||||
* \param clk_audio_mclk Nullable clockblock to be clocked from master clock
|
||||
*
|
||||
* \param clk_audio_mclk Nullable clockblock to be clocked from i2s clock
|
||||
* \param clk_audio_bclk Nullable clockblock to be clocked from i2s bit clock
|
||||
*
|
||||
* \param p_mclk_in Master clock inport port (must be 1-bit)
|
||||
*
|
||||
@@ -34,7 +36,11 @@
|
||||
*
|
||||
* \param p_i2s_adc Nullable array of ports for I2S data input lines
|
||||
*
|
||||
* \param c_dig channel connected to the clockGen() thread for
|
||||
* \param i_SoftPll Interface to software PLL task
|
||||
*
|
||||
* \param c_spdif_tx Channel connected to S/PDIF transmiter core from lib_spdif
|
||||
*
|
||||
* \param c_dig Channel connected to the clockGen() thread for
|
||||
* receiving/transmitting samples
|
||||
*/
|
||||
void XUA_AudioHub(chanend ?c_aud,
|
||||
@@ -45,10 +51,13 @@ void XUA_AudioHub(chanend ?c_aud,
|
||||
buffered _XUA_CLK_DIR port:32 ?p_bclk,
|
||||
buffered out port:32 (&?p_i2s_dac)[I2S_WIRES_DAC],
|
||||
buffered in port:32 (&?p_i2s_adc)[I2S_WIRES_ADC]
|
||||
#if (XUA_SPDIF_TX_EN) //&& (SPDIF_TX_TILE != AUDIO_IO_TILE)
|
||||
#if (XUA_USE_APP_PLL) || defined(__DOXYGEN__)
|
||||
, client interface SoftPll_if i_SoftPll
|
||||
#endif
|
||||
#if (XUA_SPDIF_TX_EN) || defined(__DOXYGEN__)
|
||||
, chanend c_spdif_tx
|
||||
#endif
|
||||
#if((SPDIF_RX) || (ADAT_RX))
|
||||
#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN || defined(__DOXYGEN__))
|
||||
, chanend c_dig
|
||||
#endif
|
||||
#if (XUD_TILE != 0) && (AUDIO_IO_TILE == 0) && (XUA_DFU_EN == 1)
|
||||
@@ -61,21 +70,28 @@ void XUA_AudioHub(chanend ?c_aud,
|
||||
|
||||
void SpdifTxWrapper(chanend c_spdif_tx);
|
||||
|
||||
/* These functions must be implemented for the CODEC/ADC/DAC arrangement of a specific design */
|
||||
|
||||
/* Any required clocking and CODEC initialisation - run once at start up */
|
||||
/* TODO Provide default implementation of this */
|
||||
void AudioHwInit();
|
||||
|
||||
/* Configure audio hardware (clocking, CODECs etc) for a specific mClk/Sample frquency - run on every sample frequency change */
|
||||
/* TODO Provide default implementation of this */
|
||||
void AudioHwConfig(unsigned samFreq, unsigned mClk, unsigned dsdMode,
|
||||
unsigned sampRes_DAC, unsigned sampRes_ADC);
|
||||
|
||||
#endif // __XC__
|
||||
|
||||
void UserBufferManagementInit();
|
||||
|
||||
/**
|
||||
* @brief User buffer management code
|
||||
*
|
||||
* This function is called at the sample rate of the USB Audio stack (e.g,. 48 kHz) and between the two parameter arrays
|
||||
* contain a full multi-channel audio-frame. The first array carries all the data that has been received from the USB host
|
||||
* and is to be presented to the audio interfaces. The second array carries all the data received from the interfaces and
|
||||
* is to be presented to the USB host. The user can chose to intercept and overwrite the samples stored in these arrays.
|
||||
*
|
||||
* \param sampsFromUsbToAudio Samples received from USB host and to be presented to audio interfaces
|
||||
*
|
||||
* \param sampsFromAudioToUsb Samples received from the audio interfaces and to be presented to the USB host
|
||||
*/
|
||||
void UserBufferManagement(unsigned sampsFromUsbToAudio[], unsigned sampsFromAudioToUsb[]);
|
||||
|
||||
#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,72 +1,69 @@
|
||||
// Copyright 2011-2021 XMOS LIMITED.
|
||||
// Copyright 2011-2023 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
#ifndef __XUA_BUFFER_H__
|
||||
#define __XUA_BUFFER_H__
|
||||
#ifndef _XUA_BUFFER_H_
|
||||
#define _XUA_BUFFER_H_
|
||||
|
||||
#if __XC__
|
||||
|
||||
#include "xua.h"
|
||||
#include "xua_clocking.h" /* Required for pll_ref_if */
|
||||
|
||||
/** USB Audio Buffering Core.
|
||||
/** USB Audio Buffering Core(s).
|
||||
*
|
||||
* This function buffers USB audio data between the XUD layer and the decouple
|
||||
* thread. Most of the chanend parameters to the function should be connected to
|
||||
* XUD_Manager()
|
||||
* This function buffers USB audio data between the XUD and the audio subsystem.
|
||||
* Most of the chanend parameters to the function should be connected to
|
||||
* XUD_Manager(). The uses two cores.
|
||||
*
|
||||
* \param c_aud_out Audio OUT endpoint channel connected to the XUD
|
||||
* \param c_aud_in Audio IN endpoint channel connected to the XUD
|
||||
* \param c_aud_fb Audio feedback endpoint channel connected to the XUD
|
||||
* \param c_midi_from_host MIDI OUT endpoint channel connected to the XUD
|
||||
* \param c_midi_to_host MIDI IN endpoint channel connected to the XUD
|
||||
* \param c_int Audio clocking interrupt endpoint channel connected to the XUD
|
||||
* \param c_clk_int Optional chanend connected to the clockGen() thread if present
|
||||
* \param c_sof Start of frame channel connected to the XUD
|
||||
* \param c_aud_ctl Audio control channel connected to Endpoint0()
|
||||
* \param p_off_mclk A port that is clocked of the MCLK input (not the MCLK input itself)
|
||||
* \param c_aud_out Audio OUT endpoint channel connected to the XUD
|
||||
* \param c_aud_in Audio IN endpoint channel connected to the XUD
|
||||
* \param c_aud_fb Audio feedback endpoint channel connected to the XUD
|
||||
* \param c_midi_from_host MIDI OUT endpoint channel connected to the XUD
|
||||
* \param c_midi_to_host MIDI IN endpoint channel connected to the XUD
|
||||
* \param c_midi Channel connected to MIDI core
|
||||
* \param c_int Audio clocking interrupt endpoint channel connected to the XUD
|
||||
* \param c_clk_int Optional chanend connected to the clockGen() thread if present
|
||||
* \param c_sof Start of frame channel connected to the XUD
|
||||
* \param c_aud_ctl Audio control channel connected to Endpoint0()
|
||||
* \param p_off_mclk A port that is clocked of the MCLK input (not the MCLK input itself)
|
||||
* \param c_aud Channel connected to XUA_AudioHub() core
|
||||
* \param i_pll_ref Interface to task that toggles reference pin to CS2100
|
||||
* \param c_swpll_update Channel connected to software PLL task. Expects master clock counts based on USB frames.
|
||||
*/
|
||||
|
||||
void XUA_Buffer(
|
||||
chanend c_aud_out,
|
||||
#if (NUM_USB_CHAN_IN > 0)
|
||||
#if (NUM_USB_CHAN_IN > 0) || defined(__DOXYGEN__)
|
||||
chanend c_aud_in,
|
||||
#endif
|
||||
#if (NUM_USB_CHAN_IN == 0) || defined (UAC_FORCE_FEEDBACK_EP)
|
||||
chanend c_aud_fb,
|
||||
#endif
|
||||
#ifdef MIDI
|
||||
#if defined(MIDI) || defined(__DOXYGEN__)
|
||||
chanend c_midi_from_host,
|
||||
chanend c_midi_to_host,
|
||||
chanend c_midi,
|
||||
#endif
|
||||
#ifdef IAP
|
||||
chanend c_iap_from_host,
|
||||
chanend c_iap_to_host,
|
||||
#ifdef IAP_INT_EP
|
||||
chanend c_iap_to_host_int,
|
||||
#endif
|
||||
chanend c_iap,
|
||||
#ifdef IAP_EA_NATIVE_TRANS
|
||||
chanend c_iap_ea_native_out,
|
||||
chanend c_iap_ea_native_in,
|
||||
chanend c_iap_ea_native_ctrl,
|
||||
chanend c_iap_ea_native_data,
|
||||
#endif
|
||||
#endif
|
||||
#if (SPDIF_RX) || (ADAT_RX)
|
||||
#if XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN || defined(__DOXYGEN__)
|
||||
chanend ?c_int,
|
||||
chanend ?c_clk_int,
|
||||
#endif
|
||||
chanend c_sof,
|
||||
chanend c_aud_ctl,
|
||||
in port p_off_mclk
|
||||
#if( 0 < HID_CONTROLS )
|
||||
#if (HID_CONTROLS)
|
||||
, chanend c_hid
|
||||
#endif
|
||||
, chanend c_aud
|
||||
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC) || defined(__DOYXGEN__)
|
||||
#if (!XUA_USE_APP_PLL) || defined(__DOXYGEN__)
|
||||
, client interface pll_ref_if i_pll_ref
|
||||
#endif
|
||||
#if (XUA_USE_APP_PLL) || defined(__DOXYGEN__)
|
||||
, chanend c_swpll_update
|
||||
#endif
|
||||
#endif
|
||||
);
|
||||
|
||||
void XUA_Buffer_Ep(chanend c_aud_out,
|
||||
#if (NUM_USB_CHAN_IN > 0)
|
||||
#if (NUM_USB_CHAN_IN > 0) || defined(__DOXYGEN__)
|
||||
chanend c_aud_in,
|
||||
#endif
|
||||
#if (NUM_USB_CHAN_IN == 0) || defined (UAC_FORCE_FEEDBACK_EP)
|
||||
@@ -77,34 +74,29 @@ void XUA_Buffer_Ep(chanend c_aud_out,
|
||||
chanend c_midi_to_host,
|
||||
chanend c_midi,
|
||||
#endif
|
||||
#ifdef IAP
|
||||
chanend c_iap_from_host,
|
||||
chanend c_iap_to_host,
|
||||
#ifdef IAP_INT_EP
|
||||
chanend c_iap_to_host_int,
|
||||
#endif
|
||||
chanend c_iap,
|
||||
#ifdef IAP_EA_NATIVE_TRANS
|
||||
chanend c_iap_ea_native_out,
|
||||
chanend c_iap_ea_native_in,
|
||||
chanend c_iap_ea_native_ctrl,
|
||||
chanend c_iap_ea_native_data,
|
||||
#endif
|
||||
#endif
|
||||
#if (SPDIF_RX) || (ADAT_RX)
|
||||
#if (XUA_SPDIF_RX_EN) || (XUA_ADAT_RX_EN)
|
||||
chanend ?c_int,
|
||||
chanend ?c_clk_int,
|
||||
#endif
|
||||
chanend c_sof,
|
||||
chanend c_aud_ctl,
|
||||
in port p_off_mclk
|
||||
#if( 0 < HID_CONTROLS )
|
||||
#if (HID_CONTROLS)
|
||||
, chanend c_hid
|
||||
#endif
|
||||
#ifdef CHAN_BUFF_CTRL
|
||||
, chanend c_buff_ctrl
|
||||
#endif
|
||||
);
|
||||
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC) || defined(__DOYXGEN__)
|
||||
#if (!XUA_USE_APP_PLL) || defined(__DOXYGEN__)
|
||||
, client interface pll_ref_if i_pll_ref
|
||||
#endif
|
||||
#if (XUA_USE_APP_PLL) || defined(__DOXYGEN__)
|
||||
, chanend c_swpll_update
|
||||
#endif
|
||||
#endif
|
||||
);
|
||||
|
||||
|
||||
/** Manage the data transfer between the USB audio buffer and the
|
||||
* Audio I/O driver.
|
||||
@@ -116,7 +108,5 @@ void XUA_Buffer_Decouple(chanend c_audio_out
|
||||
, chanend c_buff_ctrl
|
||||
#endif
|
||||
);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
74
lib_xua/api/xua_clocking.h
Normal file
74
lib_xua/api/xua_clocking.h
Normal file
@@ -0,0 +1,74 @@
|
||||
// Copyright 2011-2023 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
|
||||
#ifndef _CLOCKING_H_
|
||||
#define _CLOCKING_H_
|
||||
|
||||
#include <xs1.h>
|
||||
#include "xua.h"
|
||||
|
||||
interface pll_ref_if
|
||||
{
|
||||
void toggle();
|
||||
void init();
|
||||
void toggle_timed(int relative);
|
||||
};
|
||||
|
||||
[[distributable]]
|
||||
void PllRefPinTask(server interface pll_ref_if i_pll_ref, out port p_sync);
|
||||
|
||||
/** Clock generation and digital audio I/O handling.
|
||||
*
|
||||
* \param c_spdif_rx channel connected to S/PDIF receive thread
|
||||
* \param c_adat_rx channel connect to ADAT receive thread
|
||||
* \param i_pll_ref interface to taslk that outputs clock signal to drive external frequency synthesizer
|
||||
* \param c_audio channel connected to the audio() thread
|
||||
* \param c_clk_ctl channel connected to Endpoint0() for configuration of the
|
||||
* clock
|
||||
* \param c_clk_int channel connected to the decouple() thread for clock
|
||||
interrupts
|
||||
*/
|
||||
void clockGen(streaming chanend ?c_spdif_rx, chanend ?c_adat_rx, client interface pll_ref_if i_pll_ref, chanend c_audio, chanend c_clk_ctl, chanend c_clk_int);
|
||||
|
||||
#if (XUA_USE_APP_PLL)
|
||||
struct SoftPllState
|
||||
{
|
||||
// Count we expect on MCLK port timer at SW PLL check point.
|
||||
// Note, we expect wrapping so this is essentiually a modulus
|
||||
unsigned expectedClkMod;
|
||||
unsigned initialSetting;
|
||||
unsigned initialErrorMult;
|
||||
unsigned setting;
|
||||
|
||||
int phaseError;
|
||||
|
||||
/* Integrated phase error */
|
||||
int phaseErrorInt;
|
||||
|
||||
/* IIR filter */
|
||||
int iir_y;
|
||||
|
||||
/* Delta sigma modulator */
|
||||
unsigned ds_in;
|
||||
int ds_x1;
|
||||
int ds_x2;
|
||||
int ds_x3;
|
||||
};
|
||||
|
||||
void AppPllEnable(tileref tile, int mclkFreq_hz);
|
||||
void AppPllGetSettings(int clkFreq_hz, struct SoftPllState &pllState);
|
||||
void AppPllUpdate(tileref tile, unsigned short mclk_pt, struct SoftPllState &pllState);
|
||||
|
||||
interface SoftPll_if
|
||||
{
|
||||
void init(int mclk_hz);
|
||||
};
|
||||
|
||||
#if (XUA_SYNCMODE == XUA_SYNCMODE_ASYNC)
|
||||
[[distributable]]
|
||||
#endif
|
||||
void XUA_SoftPll(tileref tile, server interface SoftPll_if i_softPll, chanend c_update);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -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.
|
||||
/*
|
||||
* @brief Defines relating to device configuration and customisation of lib_xua
|
||||
@@ -11,29 +11,22 @@
|
||||
#include "xua_conf.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Default tile arrangement */
|
||||
/*
|
||||
* Tile arrangement defines
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Location (tile) of audio I/O. Default: 0
|
||||
*/
|
||||
#ifndef AUDIO_IO_TILE
|
||||
#define AUDIO_IO_TILE 0
|
||||
#define AUDIO_IO_TILE (0)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Location (tile) of audio I/O. Default: 0
|
||||
*/
|
||||
#ifndef XUD_TILE
|
||||
#define XUD_TILE 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Location (tile) of IAP. Default: AUDIO_IO_TILE
|
||||
*/
|
||||
#ifndef IAP_TILE
|
||||
#define IAP_TILE AUDIO_IO_TILE
|
||||
#define XUD_TILE (0)
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -58,12 +51,16 @@
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Disable USB functionalty just leaving AudioHub
|
||||
* @brief Location (tile) of reference signal to CS2100. Default: AUDIO_IO_TILE
|
||||
*/
|
||||
#ifndef XUA_USB_EN
|
||||
#define XUA_USB_EN 1
|
||||
#ifndef PLL_REF_TILE
|
||||
#define PLL_REF_TILE AUDIO_IO_TILE
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Channel based defines
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Number of input channels (device to host). Default: NONE (Must be defined by app)
|
||||
*/
|
||||
@@ -81,7 +78,18 @@
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Number of DSD output channels. Default: 0 (disabled)
|
||||
* @brief Number of PDM microphones in the design.
|
||||
*
|
||||
* Default: 0
|
||||
*/
|
||||
#ifndef XUA_NUM_PDM_MICS
|
||||
#define XUA_NUM_PDM_MICS (0)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Number of DSD output channels.
|
||||
*
|
||||
* Default: 0 (disabled)
|
||||
*/
|
||||
#if defined(DSD_CHANS_DAC) && (DSD_CHANS_DAC != 0)
|
||||
#if defined(NATIVE_DSD) && (NATIVE_DSD == 0)
|
||||
@@ -93,29 +101,8 @@
|
||||
#define DSD_CHANS_DAC 0
|
||||
#endif
|
||||
|
||||
|
||||
/* TODO not required */
|
||||
#ifndef I2S_MODE_TDM
|
||||
#define I2S_MODE_TDM 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Channels per I2S frame. *
|
||||
*
|
||||
* Default: 2 i.e standard stereo I2S (8 if using TDM i.e. I2S_MODE_TDM).
|
||||
*
|
||||
**/
|
||||
#ifndef I2S_CHANS_PER_FRAME
|
||||
#if (I2S_MODE_TDM == 1)
|
||||
#define I2S_CHANS_PER_FRAME 8
|
||||
#else
|
||||
#define I2S_CHANS_PER_FRAME 2
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* @brief Number of IS2 channesl to DAC/CODEC. Must be a multiple of 2.
|
||||
* @brief Number of I2S channesl to DAC/CODEC. Must be a multiple of 2.
|
||||
*
|
||||
* Default: NONE (Must be defined by app)
|
||||
*/
|
||||
@@ -126,7 +113,6 @@
|
||||
#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.
|
||||
*
|
||||
@@ -139,6 +125,52 @@
|
||||
#define I2S_WIRES_ADC (I2S_CHANS_ADC / I2S_CHANS_PER_FRAME)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Defines relating to the interface to external audio hardware i.e. DAC/ADC
|
||||
*/
|
||||
|
||||
#define XUA_PCM_FORMAT_I2S (0)
|
||||
#define XUA_PCM_FORMAT_TDM (1)
|
||||
/**
|
||||
* @brief Format of PCM audio interface. Should be set to XUA_PCM_FORMAT_I2S or XUA_PCM_FORMAT_TDM
|
||||
*
|
||||
* Default: XUA_PCM_FORMAT_I2S
|
||||
*/
|
||||
#ifdef XUA_PCM_FORMAT
|
||||
#if (XUA_PCM_FORMAT != XUA_PCM_FORMAT_I2S) && (XUA_PCM_FORMAT != XUA_PCM_FORMAT_TDM)
|
||||
#error Bad value for XUA_PCM_FORMAT
|
||||
#endif
|
||||
#else
|
||||
#define XUA_PCM_FORMAT XUA_PCM_FORMAT_I2S
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Channels per I2S frame. *
|
||||
*
|
||||
* Default: 2 i.e standard stereo I2S (8 if using TDM i.e. XUA_PCM_FORMAT_TDM).
|
||||
*
|
||||
**/
|
||||
#ifndef I2S_CHANS_PER_FRAME
|
||||
#if (XUA_PCM_FORMAT == XUA_PCM_FORMAT_TDM)
|
||||
#define I2S_CHANS_PER_FRAME 8
|
||||
#else
|
||||
#define I2S_CHANS_PER_FRAME 2
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Number of bits per channel for I2S/TDM. Supported values: 16/32-bit.
|
||||
*
|
||||
* Default: 32 bits
|
||||
*/
|
||||
#ifndef XUA_I2S_N_BITS
|
||||
#define XUA_I2S_N_BITS (32)
|
||||
#endif
|
||||
|
||||
#if (XUA_I2S_N_BITS != 16) && (XUA_I2S_N_BITS != 32)
|
||||
#error Unsupported value for XUA_I2S_N_BITS (only values 16/32 supported)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Ratio of the I2S sample rate to the USB Audio sample rate. Up and
|
||||
* down-sampling will be enabled as necessary when the rates differ.
|
||||
@@ -183,29 +215,39 @@
|
||||
*/
|
||||
#if (I2S_DOWNSAMPLE_MONO_IN == 1)
|
||||
#define I2S_DOWNSAMPLE_CHANS_IN (I2S_CHANS_ADC / 2)
|
||||
#if ((I2S_DOWNSAMPLE_FACTOR_IN > 1) && (I2S_MODE_TDM == 1))
|
||||
#if ((I2S_DOWNSAMPLE_FACTOR_IN > 1) && (XUA_PCM_FORMAT == XUA_PCM_FORMAT_TDM))
|
||||
#error Mono I2S input downsampling is not avaliable in TDM mode
|
||||
#endif
|
||||
#else
|
||||
#define I2S_DOWNSAMPLE_CHANS_IN I2S_CHANS_ADC
|
||||
#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
|
||||
#define MAX_FREQ (192000)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Min supported sample frequency for device (Hz). Default 44100
|
||||
* @brief Min supported sample frequency for device (Hz).
|
||||
*
|
||||
* Default: 44100Hz
|
||||
*/
|
||||
#ifndef MIN_FREQ
|
||||
#define MIN_FREQ (44100)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Master clock defines for 44100 rates (in Hz). Default: NONE (Must be defined by app)
|
||||
* @brief Master clock defines for 44100 rates (in Hz).
|
||||
*
|
||||
* Default: NONE (Must be defined by app)
|
||||
*/
|
||||
#ifndef MCLK_441
|
||||
#error MCLK_441 not defined
|
||||
@@ -213,7 +255,9 @@
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Master clock defines for 48000 rates (in Hz). Default: NONE (Must be defined by app)
|
||||
* @brief Master clock defines for 48000 rates (in Hz).
|
||||
*
|
||||
* Default: NONE (Must be defined by app)
|
||||
*/
|
||||
#ifndef MCLK_48
|
||||
#error MCLK_48 not defined
|
||||
@@ -221,26 +265,66 @@
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Default device sample frequency. A safe default should be used. Default: MIN_FREQ
|
||||
* @brief Enable/disable the use of the secondary/application PLL for generating master-clocks.
|
||||
* Only available on xcore.ai devices.
|
||||
*
|
||||
* Default: Enabled (for xcore.ai devices)
|
||||
*/
|
||||
#ifndef XUA_USE_APP_PLL
|
||||
#if defined(__XS3A__)
|
||||
#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
|
||||
/* Currently must use an external CS2100 device for syncing to external digital streams */
|
||||
#define XUA_USE_APP_PLL (0)
|
||||
#else
|
||||
#define XUA_USE_APP_PLL (1)
|
||||
#endif
|
||||
#else
|
||||
#define XUA_USE_APP_PLL (0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Default device sample frequency. A safe default should be used.
|
||||
*
|
||||
* Default: MIN_FREQ
|
||||
*/
|
||||
#ifndef DEFAULT_FREQ
|
||||
#define DEFAULT_FREQ (MIN_FREQ)
|
||||
#endif
|
||||
|
||||
/* Audio Class Defines */
|
||||
#define DEFAULT_MCLK (((DEFAULT_FREQ % 7350) == 0) ? MCLK_441 : MCLK_48)
|
||||
|
||||
/**
|
||||
* @brief USB Audio Class Version. Default: 2 (Audio Class version 2.0)
|
||||
* @brief Defines whether XMOS device runs as master (i.e. drives LR and Bit clocks)
|
||||
*
|
||||
* 0: XMOS is I2S master. 1: CODEC is I2s master.
|
||||
*
|
||||
* Default: 0 (XMOS is master)
|
||||
*/
|
||||
#ifndef CODEC_MASTER
|
||||
#define CODEC_MASTER (0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Audio Class defines
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief USB Audio Class Version
|
||||
*
|
||||
* Default: 2 (Audio Class version 2.0)
|
||||
*/
|
||||
#ifndef AUDIO_CLASS
|
||||
#define AUDIO_CLASS 2
|
||||
#define AUDIO_CLASS (2)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Whether or not to fall back to Audio Class 1.0 in USB Full-speed. Default: 0 (Disabled)
|
||||
* @brief Enable/disable fall back to Audio Class 1.0 in USB Full-speed.
|
||||
*
|
||||
* Default: Disabled
|
||||
*/
|
||||
#ifndef AUDIO_CLASS_FALLBACK
|
||||
#define AUDIO_CLASS_FALLBACK 0 /* Default to not falling back to UAC 1 */
|
||||
#define AUDIO_CLASS_FALLBACK (0)
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -269,14 +353,17 @@
|
||||
#error AUDIO_CLASS set to 1 and FULL_SPEED_AUDIO_2 enabled!
|
||||
#endif
|
||||
|
||||
|
||||
/* Feature defines */
|
||||
/*
|
||||
* Feature defines
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Number of PDM microphones in the design. Default: None
|
||||
* @brief Disable USB functionalty just leaving AudioHub
|
||||
*
|
||||
* Default: Enabled
|
||||
*/
|
||||
#ifndef XUA_NUM_PDM_MICS
|
||||
#define XUA_NUM_PDM_MICS (0)
|
||||
#ifndef XUA_USB_EN
|
||||
#define XUA_USB_EN (1)
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -333,13 +420,8 @@
|
||||
/**
|
||||
* @brief Enables ADAT Tx. Default: 0 (Disabled)
|
||||
*/
|
||||
#ifndef ADAT_TX
|
||||
#define ADAT_TX (0)
|
||||
#endif
|
||||
|
||||
/* Tidy up old SPDIF usage */
|
||||
#if defined(ADAT_TX) && (ADAT_TX == 0)
|
||||
#undef ADAT_TX
|
||||
#ifndef XUA_ADAT_TX_EN
|
||||
#define XUA_ADAT_TX_EN (0)
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -354,15 +436,15 @@
|
||||
/**
|
||||
* @brief Enables SPDIF Rx. Default: 0 (Disabled)
|
||||
*/
|
||||
#ifndef SPDIF_RX
|
||||
#define SPDIF_RX (0)
|
||||
#ifndef XUA_SPDIF_RX_EN
|
||||
#define XUA_SPDIF_RX_EN (0)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables ADAT Rx. Default: 0 (Disabled)
|
||||
*/
|
||||
#ifndef ADAT_RX
|
||||
#define ADAT_RX (0)
|
||||
#ifndef XUA_ADAT_RX_EN
|
||||
#define XUA_ADAT_RX_EN (0)
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -371,9 +453,9 @@
|
||||
*
|
||||
* Default: NONE (Must be defined by app when SPDIF_RX enabled)
|
||||
*/
|
||||
#if (SPDIF_RX) || defined (__DOXYGEN__)
|
||||
#if (XUA_SPDIF_RX_EN) || defined (__DOXYGEN__)
|
||||
#ifndef SPDIF_RX_INDEX
|
||||
#error SPDIF_RX_INDEX not defined and SPDIF_RX defined
|
||||
#error SPDIF_RX_INDEX not defined and XUA_SPDIF_RX_EN defined
|
||||
#define SPDIF_RX_INDEX 0 /* Default define for doxygen */
|
||||
#endif
|
||||
#endif
|
||||
@@ -382,11 +464,11 @@
|
||||
* @brief ADAT Rx first channel index. defines which channels ADAT will be input on.
|
||||
* Note, indexed from 0.
|
||||
*
|
||||
* Default: NONE (Must be defined by app when ADAT_RX enabled)
|
||||
* Default: NONE (Must be defined by app when XUA_ADAT_RX_EN is true)
|
||||
*/
|
||||
#if (ADAT_RX) || defined(__DOXYGEN__)
|
||||
#if (XUA_ADAT_RX_EN) || defined(__DOXYGEN__)
|
||||
#ifndef ADAT_RX_INDEX
|
||||
#error ADAT_RX_INDEX not defined and ADAT_RX defined
|
||||
#error ADAT_RX_INDEX not defined and XUA_ADAT_RX_EN is true
|
||||
#define ADAT_RX_INDEX (0) /* Default define for doxygen */
|
||||
#endif
|
||||
|
||||
@@ -395,7 +477,7 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if ADAT_RX
|
||||
#if (XUA_ADAT_RX_EN)
|
||||
|
||||
/* Setup input stream formats for ADAT */
|
||||
#if(MAX_FREQ > 96000)
|
||||
@@ -433,14 +515,37 @@
|
||||
#define HID_CONTROLS (0)
|
||||
#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
|
||||
#define CODEC_MASTER (0)
|
||||
#if (HID_CONTROLS) || defined (__DOXYGEN__)
|
||||
#define XUA_HID_ENABLED (1)
|
||||
#define XUA_OR_STATIC_HID_ENABLED (1)
|
||||
#endif
|
||||
|
||||
#if defined(__static_hid_report_h_exists__)
|
||||
#define XUA_OR_STATIC_HID_ENABLED (1)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enable a HID OUT endpoint. Only use this if you supply your own HID control.
|
||||
*
|
||||
* 1 for enabled, 0 for disabled.
|
||||
*
|
||||
* Default 0 (Disabled)
|
||||
*/
|
||||
#ifndef HID_OUT_REQUIRED
|
||||
#define HID_OUT_REQUIRED (0)
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -452,7 +557,6 @@
|
||||
#define SERIAL_STR ""
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* @brief Vendor String used by the device. This is also pre-pended to various strings used by the design.
|
||||
*
|
||||
@@ -959,43 +1063,32 @@
|
||||
|
||||
/* Power */
|
||||
|
||||
#define XUA_POWERMODE_SELF (0)
|
||||
#define XUA_POWERMODE_BUS (1)
|
||||
/**
|
||||
* @brief Report as self to the host when enabled, else reports as bus-powered. This affects descriptors
|
||||
* and XUD usage.
|
||||
* @brief Report as self or bus powered device. This affects descriptors
|
||||
* and XUD usage and is important for USB compliance
|
||||
*
|
||||
* Default: 0 (Disabled)
|
||||
* Default: XUA_POWERMODE_BUS
|
||||
*/
|
||||
#ifndef SELF_POWERED
|
||||
#define SELF_POWERED (0)
|
||||
#endif
|
||||
|
||||
/* Tidy-up historical ifndef usage */
|
||||
#if defined(SELF_POWERED) && (SELF_POWERED==0)
|
||||
#undef SELF_POWERED
|
||||
#ifndef XUA_POWERMODE
|
||||
#define XUA_POWERMODE XUA_POWERMODE_BUS
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Power drawn from the host (in mA x 2)
|
||||
*
|
||||
* Default: 0 when SELF_POWERED enabled else 250 (500mA)
|
||||
* Default: 0 when self-powered, else 250 (500mA)
|
||||
*/
|
||||
#ifdef SELF_POWERED
|
||||
#if (XUA_POWERMODE == XUA_POWERMODE_SELF)
|
||||
/* Default to taking no power from the bus in self-powered mode */
|
||||
#ifndef BMAX_POWER
|
||||
#define BMAX_POWER 0
|
||||
#ifndef _XUA_BMAX_POWER
|
||||
#define _XUA_BMAX_POWER (0)
|
||||
#endif
|
||||
#else
|
||||
/* Default to taking 500mA from the bus in bus-powered mode */
|
||||
#ifndef BMAX_POWER
|
||||
#define BMAX_POWER 250
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef XUD_PWR_CFG
|
||||
#ifdef SELF_POWERED
|
||||
#define XUD_PWR_CFG XUD_PWR_SELF
|
||||
#else
|
||||
#define XUD_PWR_CFG XUD_PWR_BUS
|
||||
#ifndef _XUA_BMAX_POWER
|
||||
#define _XUA_BMAX_POWER (250)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -1010,17 +1103,12 @@
|
||||
#define MIXER (0)
|
||||
#endif
|
||||
|
||||
/* Tidy up old ifndef usage */
|
||||
#if defined(MIXER) && (MIXER == 0)
|
||||
#undef MIXER
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Number of seperate mixes to perform
|
||||
*
|
||||
* Default: 8 if MIXER enabled, else 0
|
||||
*/
|
||||
#ifdef MIXER
|
||||
#if (MIXER)
|
||||
#ifndef MAX_MIX_COUNT
|
||||
#define MAX_MIX_COUNT (8)
|
||||
#endif
|
||||
@@ -1100,44 +1188,24 @@
|
||||
#define VOLUME_RES_MIXER (0x100)
|
||||
#endif
|
||||
|
||||
/* Handle out volume control in the mixer */
|
||||
#if defined(OUT_VOLUME_IN_MIXER) && (OUT_VOLUME_IN_MIXER==0)
|
||||
#undef OUT_VOLUME_IN_MIXER
|
||||
#else
|
||||
#if defined(MIXER)
|
||||
// Disabled by default
|
||||
//#define OUT_VOLUME_IN_MIXER
|
||||
#endif
|
||||
/* Handle out volume control in the mixer - enabled by default */
|
||||
#ifndef OUT_VOLUME_IN_MIXER
|
||||
#define OUT_VOLUME_IN_MIXER (1)
|
||||
#endif
|
||||
|
||||
/* Apply out volume controls after the mix */
|
||||
#if defined(OUT_VOLUME_AFTER_MIX) && (OUT_VOLUME_AFTER_MIX==0)
|
||||
#undef OUT_VOLUME_AFTER_MIX
|
||||
#else
|
||||
#if defined(MIXER) && defined(OUT_VOLUME_IN_MIXER)
|
||||
// Enabled by default
|
||||
#define OUT_VOLUME_AFTER_MIX
|
||||
#endif
|
||||
/* Apply out volume controls after the mix. Only relevant when OUT_VOLUME_IN_MIXER enabled. Enabled by default */
|
||||
#ifndef OUT_VOLUME_AFTER_MIX
|
||||
#define OUT_VOLUME_AFTER_MIX (1)
|
||||
#endif
|
||||
|
||||
/* Handle in volume control in the mixer */
|
||||
#if defined(IN_VOLUME_IN_MIXER) && (IN_VOLUME_IN_MIXER==0)
|
||||
#undef IN_VOLUME_IN_MIXER
|
||||
#else
|
||||
#if defined(MIXER)
|
||||
/* Disabled by default */
|
||||
//#define IN_VOLUME_IN_MIXER
|
||||
#endif
|
||||
/* Handle in volume control in the mixer - disabled by default */
|
||||
#ifndef IN_VOLUME_IN_MIXER
|
||||
#define IN_VOLUME_IN_MIXER (0)
|
||||
#endif
|
||||
|
||||
/* Apply in volume controls after the mix */
|
||||
#if defined(IN_VOLUME_AFTER_MIX) && (IN_VOLUME_AFTER_MIX==0)
|
||||
#undef IN_VOLUME_AFTER_MIX
|
||||
#else
|
||||
#if defined(MIXER) && defined(IN_VOLUME_IN_MIXER)
|
||||
// Enabled by default
|
||||
#define IN_VOLUME_AFTER_MIX
|
||||
#endif
|
||||
/* Apply in volume controls after the mix. Only relebant when IN_VOLUMNE_IN MIXER enabled. Enabled by default */
|
||||
#ifndef IN_VOLUME_AFTER_MIX
|
||||
#define IN_VOLUME_AFTER_MIX (1)
|
||||
#endif
|
||||
|
||||
/* Always enable explicit feedback EP, even when input stream is present */
|
||||
@@ -1149,6 +1217,26 @@
|
||||
#undef UAC_FORCE_FEEDBACK_EP
|
||||
#endif
|
||||
|
||||
/* Synchronisation defines */
|
||||
#define XUA_SYNCMODE_ASYNC (1) // USB_ENDPOINT_SYNCTYPE_ASYNC
|
||||
#define XUA_SYNCMODE_ADAPT (2) // USB_ENDPOINT_SYNCTYPE_ADAPT
|
||||
#define XUA_SYNCMODE_SYNC (3) // USB_ENDPOINT_SYNCTYPE_SYNC
|
||||
|
||||
#ifndef XUA_SYNCMODE
|
||||
#define XUA_SYNCMODE XUA_SYNCMODE_ASYNC
|
||||
#endif
|
||||
|
||||
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC)
|
||||
#if (XUA_SPDIF_RX_EN|| ADAT_RX)
|
||||
#error "Digital input streams not supported in Sync mode"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/*********************************************************/
|
||||
/*** Internal defines below here. NOT FOR MODIFICATION ***/
|
||||
/*********************************************************/
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
/* Endpoint addresses enums */
|
||||
enum USBEndpointNumber_In
|
||||
@@ -1158,13 +1246,13 @@ enum USBEndpointNumber_In
|
||||
ENDPOINT_NUMBER_IN_FEEDBACK,
|
||||
#endif
|
||||
ENDPOINT_NUMBER_IN_AUDIO,
|
||||
#if (SPDIF_RX) || (ADAT_RX)
|
||||
#if (XUA_SPDIF_RX_EN) || (XUA_ADAT_RX_EN)
|
||||
ENDPOINT_NUMBER_IN_INTERRUPT, /* Audio interrupt/status EP */
|
||||
#endif
|
||||
#ifdef MIDI
|
||||
ENDPOINT_NUMBER_IN_MIDI,
|
||||
#endif
|
||||
#if( 0 < HID_CONTROLS )
|
||||
#if XUA_OR_STATIC_HID_ENABLED
|
||||
ENDPOINT_NUMBER_IN_HID,
|
||||
#endif
|
||||
#ifdef IAP
|
||||
@@ -1191,50 +1279,51 @@ enum USBEndpointNumber_Out
|
||||
#ifdef IAP_EA_NATIVE_TRANS
|
||||
ENDPOINT_NUMBER_OUT_IAP_EA_NATIVE_TRANS,
|
||||
#endif
|
||||
#endif
|
||||
#if XUA_OR_STATIC_HID_ENABLED && HID_OUT_REQUIRED
|
||||
ENDPOINT_NUMBER_OUT_HID,
|
||||
#endif
|
||||
XUA_ENDPOINT_COUNT_OUT /* End marker */
|
||||
};
|
||||
|
||||
|
||||
#ifndef XUA_ENDPOINT_COUNT_CUSTOM_OUT
|
||||
#define XUA_ENDPOINT_COUNT_CUSTOM_OUT 0
|
||||
#define XUA_ENDPOINT_COUNT_CUSTOM_OUT (0)
|
||||
#endif
|
||||
|
||||
#ifndef XUA_ENDPOINT_COUNT_CUSTOM_IN
|
||||
#define XUA_ENDPOINT_COUNT_CUSTOM_IN 0
|
||||
#define XUA_ENDPOINT_COUNT_CUSTOM_IN (0)
|
||||
#endif
|
||||
|
||||
#define ENDPOINT_COUNT_IN (XUA_ENDPOINT_COUNT_IN + XUA_ENDPOINT_COUNT_CUSTOM_IN)
|
||||
#define ENDPOINT_COUNT_OUT (XUA_ENDPOINT_COUNT_OUT + XUA_ENDPOINT_COUNT_CUSTOM_OUT)
|
||||
#define ENDPOINT_COUNT_IN (XUA_ENDPOINT_COUNT_IN + XUA_ENDPOINT_COUNT_CUSTOM_IN)
|
||||
#define ENDPOINT_COUNT_OUT (XUA_ENDPOINT_COUNT_OUT + XUA_ENDPOINT_COUNT_CUSTOM_OUT)
|
||||
|
||||
#endif
|
||||
#endif /* __ASSEMBLER__ */
|
||||
|
||||
/*** Internal defines below here. NOT FOR MODIFICATION ***/
|
||||
#define AUDIO_STOP_FOR_DFU (0x12345678)
|
||||
#define AUDIO_START_FROM_DFU (0x87654321)
|
||||
#define AUDIO_REBOOT_FROM_DFU (0xa5a5a5a5)
|
||||
|
||||
#define AUDIO_STOP_FOR_DFU (0x12345678)
|
||||
#define AUDIO_START_FROM_DFU (0x87654321)
|
||||
#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)
|
||||
#define LEVEL_UPDATE_RATE 400000
|
||||
#define LEVEL_UPDATE_RATE (400000)
|
||||
#endif
|
||||
|
||||
/* The number of clock ticks to wait for the audio feeback to stabalise
|
||||
* Note, feedback always counts 128 SOFs (16ms @ HS, 128ms @ FS) */
|
||||
#ifndef FEEDBACK_STABILITY_DELAY_HS
|
||||
#define FEEDBACK_STABILITY_DELAY_HS (2000000)
|
||||
#define FEEDBACK_STABILITY_DELAY_HS (2000000)
|
||||
#endif
|
||||
|
||||
#ifndef FEEDBACK_STABILITY_DELAY_FS
|
||||
#define FEEDBACK_STABILITY_DELAY_FS (20000000)
|
||||
#define FEEDBACK_STABILITY_DELAY_FS (20000000)
|
||||
#endif
|
||||
|
||||
/* Length of clock unit/clock-selector units */
|
||||
#if (SPDIF_RX) && (ADAT_RX)
|
||||
#if (XUA_SPDIF_RX_EN) && (XUA_ADAT_RX_EN)
|
||||
#define NUM_CLOCKS (3)
|
||||
#elif (SPDIF_RX) || (ADAT_RX)
|
||||
#elif (XUA_SPDIF_RX_EN) || (XUA_ADAT_RX_EN)
|
||||
#define NUM_CLOCKS (2)
|
||||
#else
|
||||
#define NUM_CLOCKS (1)
|
||||
@@ -1315,9 +1404,9 @@ enum USBEndpointNumber_Out
|
||||
/* Some defines that allow us to remove unused code */
|
||||
|
||||
/* 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) || \
|
||||
(FS_STREAM_FORMAT_OUTPUT_3_RESOLUTION_BITS > 24) || (HS_STREAM_FORMAT_OUTPUT_1_RESOLUTION_BITS > 24) || \
|
||||
(HS_STREAM_FORMAT_OUTPUT_2_RESOLUTION_BITS > 24) || (HS_STREAM_FORMAT_OUTPUT_3_RESOLUTION_BITS > 24)
|
||||
#if (FS_STREAM_FORMAT_OUTPUT_1_RESOLUTION_BITS > 24) || (HS_STREAM_FORMAT_OUTPUT_2_RESOLUTION_BITS > 24) || \
|
||||
(((FS_STREAM_FORMAT_OUTPUT_2_RESOLUTION_BITS > 24) || (HS_STREAM_FORMAT_OUTPUT_2_RESOLUTION_BITS > 24)) && (OUTPUT_FORMAT_COUNT > 1)) || \
|
||||
(((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
|
||||
#else
|
||||
#define STREAM_FORMAT_OUTPUT_RESOLUTION_32BIT_USED 0
|
||||
@@ -1452,3 +1541,4 @@ enum USBEndpointNumber_Out
|
||||
#if (CODEC_MASTER == 1) && (DSD_CHANS_DAC != 0)
|
||||
#error CODEC_MASTER with DSD is currently unsupported
|
||||
#endif
|
||||
|
||||
|
||||
@@ -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.
|
||||
#ifndef __XUA_CONF_FULL_H__
|
||||
#define __XUA_CONF_FULL_H__
|
||||
#ifndef _XUA_CONF_FULL_H_
|
||||
#define _XUA_CONF_FULL_H_
|
||||
|
||||
#ifdef __xua_conf_h_exists__
|
||||
#include "xua_conf.h"
|
||||
|
||||
@@ -1,36 +1,41 @@
|
||||
// Copyright 2011-2021 XMOS LIMITED.
|
||||
// Copyright 2011-2022 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
|
||||
#ifndef _XUA_ENDPOINT0_H_
|
||||
#define _XUA_ENDPOINT0_H_
|
||||
|
||||
#include "xua.h"
|
||||
#include "dfu_interface.h"
|
||||
#include "vendorrequests.h"
|
||||
|
||||
#if __XC__
|
||||
/** Function implementing Endpoint 0 for enumeration, control and configuration
|
||||
* of USB audio devices. It uses the descriptors defined in ``descriptors_2.h``.
|
||||
*
|
||||
* \param c_ep0_out Chanend connected to the XUD_Manager() out endpoint array
|
||||
* \param c_ep0_in Chanend connected to the XUD_Manager() in endpoint array
|
||||
* \param c_audioCtrl Chanend connected to the decouple thread for control
|
||||
* audio (sample rate changes etc.). Note when nulled, the
|
||||
* audio device only supports single sample rate/format and
|
||||
* DFU is not supported either since this channel is used
|
||||
* to carry messages about format, rate and DFU state
|
||||
* \param c_mix_ctl Optional chanend to be connected to the mixer thread if
|
||||
* present
|
||||
* \param c_clk_ctl Optional chanend to be connected to the clockgen thread if
|
||||
* present.
|
||||
* \param c_usb_test Optional chanend to be connected to XUD if test modes required.
|
||||
* of USB audio devices. It uses the descriptors defined in ``xua_ep0_descriptors.h``.
|
||||
*
|
||||
* \param c_ep0_out Chanend connected to the XUD_Manager() out endpoint array
|
||||
* \param c_ep0_in Chanend connected to the XUD_Manager() in endpoint array
|
||||
* \param c_audioCtrl Chanend connected to the decouple thread for control
|
||||
* audio (sample rate changes etc.). Note when nulled, the
|
||||
* audio device only supports single sample rate/format and
|
||||
* DFU is not supported either since this channel is used
|
||||
* to carry messages about format, rate and DFU state
|
||||
* \param c_mix_ctl Optional chanend to be connected to the mixer core(s) if
|
||||
* present
|
||||
* \param c_clk_ctl Optional chanend to be connected to the clockgen core if
|
||||
* present
|
||||
* \param dfuInterface Interface to DFU task (this task must be run on a tile
|
||||
* connected to boot flash.
|
||||
* \param c_EANativeTransport_ctrl Optional chanend to be connected to EA Native
|
||||
* endpoint manager if present
|
||||
*/
|
||||
void XUA_Endpoint0(chanend c_ep0_out, chanend c_ep0_in, chanend ?c_audioCtrl,
|
||||
chanend ?c_mix_ctl,chanend ?c_clk_ctl, chanend ?c_EANativeTransport_ctr, client interface i_dfu ?dfuInterface
|
||||
VENDOR_REQUESTS_PARAMS_DEC_);
|
||||
void XUA_Endpoint0(chanend c_ep0_out,
|
||||
chanend c_ep0_in, chanend ?c_audioCtrl,
|
||||
chanend ?c_mix_ctl, chanend ?c_clk_ctl,
|
||||
chanend ?c_EANativeTransport_ctrl,
|
||||
client interface i_dfu ?dfuInterface
|
||||
#if !defined(__DOXYGEN__)
|
||||
VENDOR_REQUESTS_PARAMS_DEC_
|
||||
#endif
|
||||
);
|
||||
|
||||
/** Function to set the Vendor ID value
|
||||
*
|
||||
|
||||
@@ -1,34 +1,40 @@
|
||||
// Copyright 2011-2021 XMOS LIMITED.
|
||||
// Copyright 2011-2022 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
#ifndef __usb_midi_h__
|
||||
#define __usb_midi_h__
|
||||
#ifndef _XUA_MIDI_H_
|
||||
#define _XUA_MIDI_H_
|
||||
|
||||
#include "xua.h"
|
||||
|
||||
/** USB MIDI I/O thread.
|
||||
#ifndef MIDI_SHIFT_TX
|
||||
#define MIDI_SHIFT_TX (0)
|
||||
#endif
|
||||
|
||||
/** USB MIDI I/O task.
|
||||
*
|
||||
* This function passes MIDI data from USB to UART I/O.
|
||||
* This function passes MIDI data between XUA_Buffer and MIDI UART I/O.
|
||||
*
|
||||
* \param p_midi_in 1-bit input port for MIDI
|
||||
* \param p_midi_out 1-bit output port for MIDI
|
||||
* \param clk_midi clock block used for clockin the UART; should have
|
||||
* a rate of 100MHz
|
||||
* \param c_midi chanend connected to the decouple() thread
|
||||
* \param cable_number the cable number of the MIDI implementation.
|
||||
* \param p_midi_in 1-bit input port for MIDI
|
||||
* \param p_midi_out 1-bit output port for MIDI
|
||||
* \param clk_midi Clock block used for clockin the UART; should have
|
||||
* a rate of 100MHz
|
||||
* \param c_midi Chanend connected to the decouple() thread
|
||||
* \param cable_number The cable number of the MIDI implementation.
|
||||
* This should be set to 0.
|
||||
**/
|
||||
void usb_midi(
|
||||
#if (MIDI_RX_PORT_WIDTH == 4)
|
||||
buffered in port:4 ?p_midi_in,
|
||||
buffered in port:4 ?p_midi_in,
|
||||
#else
|
||||
buffered in port:1 ?p_midi_in,
|
||||
buffered in port:1 ?p_midi_in,
|
||||
#endif
|
||||
port ?p_midi_out,
|
||||
clock ?clk_midi,
|
||||
chanend ?c_midi,
|
||||
unsigned cable_number,
|
||||
chanend ?c_iap, chanend ?c_i2c, // iOS stuff
|
||||
unsigned cable_number
|
||||
#ifdef IAP
|
||||
, chanend ?c_iap, chanend ?c_i2c, // iOS stuff
|
||||
port ?p_scl, port ?p_sda
|
||||
#endif
|
||||
);
|
||||
|
||||
#define MAX_USB_MIDI_PACKET_SIZE 1024
|
||||
@@ -72,4 +78,4 @@ INLINE void midi_send_ack(chanend c) {
|
||||
#define MIDI_RATE (31250)
|
||||
#define MIDI_BITTIME (XS1_TIMER_MHZ * 1000000 / MIDI_RATE)
|
||||
#define MIDI_BITTIME_2 (MIDI_BITTIME>>1)
|
||||
#endif // __usb_midi_h__
|
||||
#endif // _XUA_MIDI_H_
|
||||
@@ -1,7 +1,9 @@
|
||||
// Copyright 2011-2021 XMOS LIMITED.
|
||||
// Copyright 2011-2023 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
#ifndef __mixer_h__
|
||||
#define __mixer_h__
|
||||
#ifndef _XUA_MIXER_H_
|
||||
#define _XUA_MIXER_H_
|
||||
|
||||
#include "xua.h"
|
||||
|
||||
enum mix_ctl_cmd {
|
||||
SET_SAMPLES_TO_HOST_MAP,
|
||||
@@ -31,4 +33,14 @@ enum mix_ctl_cmd {
|
||||
*/
|
||||
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
|
||||
27
lib_xua/doc/rst/add.rst
Normal file
27
lib_xua/doc/rst/add.rst
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
Additional Features
|
||||
-------------------
|
||||
|
||||
The previous sections describes only the basic core set of ``lib_xua`` details on enabling additional features e.g. S/PDIF are discussed in this section.
|
||||
|
||||
Where something must be defined, it is recommended this is done in `xua_conf.h` but could also be done in the application Makefile.
|
||||
|
||||
For each feature steps are listed for if calling ``lib_xua`` functions manually - if using the "codeless" programming model then these steps are informational only.
|
||||
Each section also includes a sub-section on enabling the feature using the "codeless" model.
|
||||
|
||||
For full details of all options please see the API section
|
||||
|
||||
|
||||
.. toctree::
|
||||
|
||||
S/PDIF Transmit <feat_spdif_tx>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
12
lib_xua/doc/rst/api.rst
Normal file
12
lib_xua/doc/rst/api.rst
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
.. _sec_api:
|
||||
|
||||
API Reference
|
||||
*************
|
||||
|
||||
.. toctree::
|
||||
|
||||
api_defines
|
||||
api_user_functions
|
||||
api_component
|
||||
|
||||
35
lib_xua/doc/rst/api_component.rst
Normal file
35
lib_xua/doc/rst/api_component.rst
Normal file
@@ -0,0 +1,35 @@
|
||||
.. _sec_api_component:
|
||||
|
||||
Component API
|
||||
=============
|
||||
|
||||
The following functions can be called from the top level main of an
|
||||
application and implement the various components described in
|
||||
:ref:`usb_audio_sec_architecture`.
|
||||
|
||||
When using the USB audio framework the ``c_ep_in`` array is always
|
||||
composed in the following order:
|
||||
|
||||
* Endpoint 0 (in)
|
||||
* Audio Feedback endpoint (if output enabled)
|
||||
* Audio IN endpoint (if input enabled)
|
||||
* MIDI IN endpoint (if MIDI enabled)
|
||||
* Clock Interrupt endpoint
|
||||
|
||||
The array ``c_ep_out`` is always composed in the following order:
|
||||
|
||||
* Endpoint 0 (out)
|
||||
* Audio OUT endpoint (if output enabled)
|
||||
* MIDI OUT endpoint (if MIDI enabled)
|
||||
|
||||
.. doxygenfunction:: XUA_Endpoint0
|
||||
|
||||
.. doxygenfunction:: XUA_Buffer
|
||||
|
||||
.. doxygenfunction:: XUA_AudioHub
|
||||
|
||||
.. doxygenfunction:: mixer
|
||||
|
||||
.. doxygenfunction:: clockGen
|
||||
|
||||
.. doxygenfunction:: usb_midi
|
||||
180
lib_xua/doc/rst/api_defines.rst
Normal file
180
lib_xua/doc/rst/api_defines.rst
Normal file
@@ -0,0 +1,180 @@
|
||||
|
||||
.. _sec_api_defines:
|
||||
|
||||
Configuration Defines
|
||||
=====================
|
||||
|
||||
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``.
|
||||
|
||||
These defines should be over-ridden in an optional header file ``xua_conf.h`` file or in the ``Makefile``
|
||||
for a relevant build configuration.
|
||||
|
||||
This section fully documents all of the settable defines and their default values (where appropriate).
|
||||
|
||||
Code Location (tile)
|
||||
--------------------
|
||||
|
||||
.. doxygendefine:: AUDIO_IO_TILE
|
||||
.. doxygendefine:: XUD_TILE
|
||||
.. doxygendefine:: MIDI_TILE
|
||||
.. doxygendefine:: SPDIF_TX_TILE
|
||||
.. doxygendefine:: PDM_TILE
|
||||
.. doxygendefine:: PLL_REF_TILE
|
||||
|
||||
Channel Counts
|
||||
--------------
|
||||
|
||||
.. doxygendefine:: NUM_USB_CHAN_OUT
|
||||
.. doxygendefine:: NUM_USB_CHAN_IN
|
||||
.. doxygendefine:: I2S_CHANS_DAC
|
||||
.. doxygendefine:: I2S_CHANS_ADC
|
||||
|
||||
Frequencies and Clocks
|
||||
----------------------
|
||||
|
||||
.. doxygendefine:: MAX_FREQ
|
||||
.. doxygendefine:: MIN_FREQ
|
||||
.. doxygendefine:: DEFAULT_FREQ
|
||||
.. doxygendefine:: MCLK_441
|
||||
.. doxygendefine:: MCLK_48
|
||||
.. doxygendefine:: XUA_USE_APP_PLL
|
||||
|
||||
Audio Class
|
||||
-----------
|
||||
|
||||
.. doxygendefine:: AUDIO_CLASS
|
||||
.. doxygendefine:: AUDIO_CLASS_FALLBACK
|
||||
.. doxygendefine:: FULL_SPEED_AUDIO_2
|
||||
|
||||
|
||||
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
|
||||
^^^^
|
||||
|
||||
.. doxygendefine:: MIDI
|
||||
.. doxygendefine:: MIDI_RX_PORT_WIDTH
|
||||
|
||||
S/PDIF
|
||||
^^^^^^
|
||||
|
||||
.. doxygendefine:: XUA_SPDIF_TX_EN
|
||||
.. doxygendefine:: SPDIF_TX_INDEX
|
||||
.. doxygendefine:: XUA_SPDIF_RX_EN
|
||||
.. doxygendefine:: SPDIF_RX_INDEX
|
||||
|
||||
ADAT
|
||||
^^^^
|
||||
|
||||
.. doxygendefine:: XUA_ADAT_RX_EN
|
||||
.. doxygendefine:: ADAT_RX_INDEX
|
||||
|
||||
PDM Microphones
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
.. doxygendefine:: XUA_NUM_PDM_MICS
|
||||
|
||||
DFU
|
||||
^^^
|
||||
|
||||
.. doxygendefine:: XUA_DFU_EN
|
||||
|
||||
.. .. doxygendefine:: DFU_FLASH_DEVICE
|
||||
|
||||
HID
|
||||
^^^
|
||||
|
||||
.. doxygendefine:: HID_CONTROLS
|
||||
|
||||
|
||||
CODEC Interface
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
.. doxygendefine:: CODEC_MASTER
|
||||
|
||||
|
||||
USB Device Configuration
|
||||
------------------------
|
||||
|
||||
.. doxygendefine:: VENDOR_STR
|
||||
.. doxygendefine:: VENDOR_ID
|
||||
.. doxygendefine:: PRODUCT_STR
|
||||
.. doxygendefine:: PRODUCT_STR_A2
|
||||
.. doxygendefine:: PRODUCT_STR_A1
|
||||
.. doxygendefine:: PID_AUDIO_1
|
||||
.. doxygendefine:: PID_AUDIO_2
|
||||
.. doxygendefine:: BCD_DEVICE
|
||||
|
||||
|
||||
Stream Formats
|
||||
--------------
|
||||
|
||||
Output/Playback
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
.. doxygendefine:: OUTPUT_FORMAT_COUNT
|
||||
|
||||
.. doxygendefine:: STREAM_FORMAT_OUTPUT_1_RESOLUTION_BITS
|
||||
.. doxygendefine:: STREAM_FORMAT_OUTPUT_2_RESOLUTION_BITS
|
||||
.. doxygendefine:: STREAM_FORMAT_OUTPUT_3_RESOLUTION_BITS
|
||||
|
||||
.. doxygendefine:: HS_STREAM_FORMAT_OUTPUT_1_SUBSLOT_BYTES
|
||||
.. doxygendefine:: HS_STREAM_FORMAT_OUTPUT_2_SUBSLOT_BYTES
|
||||
.. doxygendefine:: HS_STREAM_FORMAT_OUTPUT_3_SUBSLOT_BYTES
|
||||
|
||||
.. doxygendefine:: FS_STREAM_FORMAT_OUTPUT_1_SUBSLOT_BYTES
|
||||
.. doxygendefine:: FS_STREAM_FORMAT_OUTPUT_2_SUBSLOT_BYTES
|
||||
.. doxygendefine:: FS_STREAM_FORMAT_OUTPUT_3_SUBSLOT_BYTES
|
||||
|
||||
.. doxygendefine:: STREAM_FORMAT_OUTPUT_1_DATAFORMAT
|
||||
.. doxygendefine:: STREAM_FORMAT_OUTPUT_2_DATAFORMAT
|
||||
.. doxygendefine:: STREAM_FORMAT_OUTPUT_3_DATAFORMAT
|
||||
|
||||
Input/Recording
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
.. doxygendefine:: INPUT_FORMAT_COUNT
|
||||
|
||||
.. doxygendefine:: STREAM_FORMAT_INPUT_1_RESOLUTION_BITS
|
||||
|
||||
.. doxygendefine:: HS_STREAM_FORMAT_INPUT_1_SUBSLOT_BYTES
|
||||
|
||||
.. doxygendefine:: FS_STREAM_FORMAT_INPUT_1_SUBSLOT_BYTES
|
||||
|
||||
.. doxygendefine:: STREAM_FORMAT_INPUT_1_DATAFORMAT
|
||||
|
||||
Volume Control
|
||||
--------------
|
||||
|
||||
.. doxygendefine:: OUTPUT_VOLUME_CONTROL
|
||||
.. doxygendefine:: INPUT_VOLUME_CONTROL
|
||||
.. doxygendefine:: MIN_VOLUME
|
||||
.. doxygendefine:: MAX_VOLUME
|
||||
.. doxygendefine:: VOLUME_RES
|
||||
|
||||
Mixing
|
||||
------
|
||||
|
||||
.. doxygendefine:: MIXER
|
||||
.. doxygendefine:: MAX_MIX_COUNT
|
||||
.. doxygendefine:: MIX_INPUTS
|
||||
.. doxygendefine:: MIN_MIXER_VOLUME
|
||||
.. doxygendefine:: MAX_MIXER_VOLUME
|
||||
.. doxygendefine:: VOLUME_RES_MIXER
|
||||
|
||||
Power
|
||||
-----
|
||||
|
||||
.. doxygendefine:: XUA_POWERMODE
|
||||
|
||||
49
lib_xua/doc/rst/api_user_functions.rst
Normal file
49
lib_xua/doc/rst/api_user_functions.rst
Normal file
@@ -0,0 +1,49 @@
|
||||
|newpage|
|
||||
|
||||
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
|
||||
-----------------------------------------------
|
||||
|
||||
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.
|
||||
|
||||
.. doxygenfunction:: AudioHwInit
|
||||
.. doxygenfunction:: AudioHwConfig
|
||||
.. doxygenfunction:: AudioHwConfig_Mute
|
||||
.. doxygenfunction:: AudioHwConfig_UnMute
|
||||
|
||||
|
||||
Audio Stream Start/Stop Functions
|
||||
---------------------------------
|
||||
|
||||
The following functions can be optionally used by the design. They can be useful for mute lines etc.
|
||||
|
||||
.. doxygenfunction:: UserAudioStreamStart
|
||||
.. doxygenfunction:: UserAudioStreamStop
|
||||
.. doxygenfunction:: UserAudioInputStreamStart
|
||||
.. doxygenfunction:: UserAudioInputStreamStop
|
||||
.. doxygenfunction:: UserAudioOutputStreamStart
|
||||
.. doxygenfunction:: UserAudioOutputStreamStop
|
||||
|
||||
Host Active Functions
|
||||
---------------------
|
||||
|
||||
The following function can be used to signal that the device is connected to a valid host.
|
||||
|
||||
.. doxygenfunction:: UserHostActive
|
||||
|
||||
HID Controls
|
||||
------------
|
||||
|
||||
The following function is called when the device wishes to read physical user input (buttons etc).
|
||||
The function should write relevant HID bits into this array. The bit ordering and functionality is defined by the HID report descriptor used.
|
||||
|
||||
.. doxygenfunction:: UserHIDGetData
|
||||
92
lib_xua/doc/rst/arch.rst
Normal file
92
lib_xua/doc/rst/arch.rst
Normal file
@@ -0,0 +1,92 @@
|
||||
|
||||
.. _usb_audio_sec_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.
|
||||
|
||||
`lib_xua` provides fundamental building blocks for producing USB Audio products on XMOS devices. Every system is required to have the components from `lib_xua` listed in :ref:`usb_audio_shared_components`.
|
||||
|
||||
.. tabularcolumns:: lp{5cm}l
|
||||
.. _usb_audio_shared_components:
|
||||
.. list-table:: Required XUA Components
|
||||
:header-rows: 1
|
||||
:widths: 40 60
|
||||
|
||||
* - Component
|
||||
- Description
|
||||
* - Endpoint 0
|
||||
- Provides the logic for Endpoint 0 which handles
|
||||
enumeration and control of the device including DFU related requests.
|
||||
* - Endpoint buffer
|
||||
- Buffers endpoint data packets to and from the host. Manages delivery of audio packets between the endpoint buffer
|
||||
component and the audio components. It can also handle volume control processing. Note, this currently utilises two cores
|
||||
* - AudioHub
|
||||
- Handles audio I/O over I2S and manages audio data
|
||||
to/from other digital audio I/O components.
|
||||
|
||||
In addition low-level USB I/0 is required and is provided by the external dependency `lib_xud`
|
||||
|
||||
.. tabularcolumns:: lp{5cm}l
|
||||
.. list-table:: Additional Components Required
|
||||
:header-rows: 1
|
||||
:widths: 100 60
|
||||
|
||||
* - Component
|
||||
- Description
|
||||
* - XMOS USB Device Driver (XUD)
|
||||
- Handles the low level USB I/O.
|
||||
|
||||
In addition :ref:`usb_audio_optional_components` shows optional components that can be added/enabled from within `lib_xua`
|
||||
|
||||
.. tabularcolumns:: lp{5cm}l
|
||||
.. _usb_audio_optional_components:
|
||||
.. list-table:: Optional Components
|
||||
:header-rows: 1
|
||||
:widths: 40 60
|
||||
|
||||
* - Component
|
||||
- Description
|
||||
* - Mixer
|
||||
- Allows digital mixing of input and output channels. It can also
|
||||
handle volume control instead of the decoupler.
|
||||
* - Clockgen
|
||||
- Drives an external frequency generator (PLL) and manages
|
||||
changes between internal clocks and external clocks arising
|
||||
from digital input.
|
||||
* - MIDI
|
||||
- Outputs and inputs MIDI over a serial UART interface.
|
||||
|
||||
`lib_xua` also provides optional support for integrating with the following external dependencies listed in :ref:`usb_audio_external_components`
|
||||
|
||||
.. tabularcolumns:: lp{5cm}l
|
||||
.. _usb_audio_external_components:
|
||||
.. list-table:: External Components
|
||||
:header-rows: 1
|
||||
:widths: 40 60
|
||||
|
||||
* - Component
|
||||
- Description
|
||||
* - S/PDIF Transmitter (lib_spdif)
|
||||
- Outputs samples of an S/PDIF digital audio interface.
|
||||
* - S/PDIF Receiver (lib_spdif)
|
||||
- Inputs samples of an S/PDIF digital audio interface (requires the
|
||||
clockgen component).
|
||||
* - ADAT Receiver (lib_adat)
|
||||
- Inputs samples of an ADAT digital audio interface (requires the
|
||||
clockgen component).
|
||||
* - PDM Microphones (lib_mic_array)
|
||||
- Receives PDM data from microphones and performs PDM to PCM conversion
|
||||
|
||||
.. _usb_audio_threads:
|
||||
|
||||
.. figure:: images/threads-crop.*
|
||||
:width: 100%
|
||||
|
||||
USB Audio Core Diagram
|
||||
|
||||
:ref:`usb_audio_threads` shows how the components interact with each
|
||||
other in a typical system. The green circles represent cores with arrows indicating inter-core communications.
|
||||
|
||||
|
||||
@@ -1,117 +1,24 @@
|
||||
|
||||
Features & Options
|
||||
------------------
|
||||
Additional Features
|
||||
*******************
|
||||
|
||||
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,
|
||||
``lib_xua`` can provide S/PDIF output though the used of ``lib_spdif``
|
||||
|
||||
Where something must be defined, it is recommended this is done in `xua_conf.h` but could also be done in the application Makefile.
|
||||
|
||||
.. toctree::
|
||||
|
||||
S/PDIF Transmit <feat_spdif_tx>
|
||||
S/PDIF Receive <feat_spdif_rx>
|
||||
|
||||
|
||||
|
||||
|
||||
The previous sections describes only the basic core set of ``lib_xua`` details on enabling additional features e.g. S/PDIF are discussed in this section.
|
||||
|
||||
Where something must be defined, it is recommened this is done in `xua_conf.h` but could also be done in the application Makefile.
|
||||
|
||||
For each feature steps are listed for if calling ``lib_xua`` functions manually - if using the "codeless" programming model then these steps informational only.
|
||||
Each section also includes a sub-section on enabling the feature using the "codeless" model.
|
||||
|
||||
For full details of all options please see the API section
|
||||
|
||||
I2S/TDM
|
||||
~~~~~~~
|
||||
|
||||
I2S/TDM is typically fundamental to most products and is built into the ``XUA_AudioHub()`` core.
|
||||
|
||||
In order to enable I2S on must declare an array of ports for the data-lines (one for each direction)::
|
||||
|
||||
/* 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 in port:32 p_i2s_adc[] = {PORT_I2S_ADC0}; /* I2S Data-line(s) */
|
||||
|
||||
Ports for the sample and bit clocks are also required::
|
||||
|
||||
buffered out port:32 p_lrclk = PORT_I2S_LRCLK; /* I2S Bit-clock */
|
||||
buffered out port:32 p_bclk = PORT_I2S_BCLK; /* I2S L/R-clock */
|
||||
|
||||
.. note::
|
||||
|
||||
All of these ports must be buffered, width 32. Based on whether the xCORE is bus slave/master the ports must be declared as input/output respectively
|
||||
|
||||
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.::
|
||||
|
||||
/* Clock-block declarations */
|
||||
clock clk_audio_bclk = on tile[0]: XS1_CLKBLK_4; /* Bit clock */
|
||||
clock clk_audio_mclk = on tile[0]: XS1_CLKBLK_5; /* Master clock */
|
||||
|
||||
These hardware resources must be passed into the call to ``XUA_AudioHub()``::
|
||||
|
||||
/* AudioHub/IO core does most of the audio IO i.e. I2S (also serves as a hub for all audio) */
|
||||
on tile[0]: XUA_AudioHub(c_aud, clk_audio_mclk, clk_audio_bclk, p_mclk_in, p_lrclk, p_bclk);
|
||||
|
||||
|
||||
Codeless Programming Model
|
||||
..........................
|
||||
|
||||
All ports and hardware resources are already fully declared, one must simply set the following:
|
||||
|
||||
* `I2S_CHANS_DAC` must be set to the desired number of output channels via I2S
|
||||
* `I2S_CHANS_ADC` must be set to the desired number of input channels via I2S
|
||||
* `AUDIO_IO_TILE` must be set to the tile where the physical I2S connections reside
|
||||
|
||||
For configuration options, master vs slave, TDM etc please see the API section.
|
||||
|
||||
|
||||
|newpage|
|
||||
|
||||
S/PDIF Transmit
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
``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.
|
||||
|
||||
The S/PDIF transmitter core takes PCM audio samples via a channel and outputs them in S/PDIF format to a port.
|
||||
Samples are provided to the S/PDIF transmitter task from the ``XUA_AudioHub()`` task.
|
||||
|
||||
The channel should be declared a normal::
|
||||
|
||||
chan c_spdif_tx
|
||||
|
||||
|
||||
In order to use the S/PDIF transmmiter with ``lib_xua`` hardware resources must be declared e.g::
|
||||
|
||||
buffered out port:32 p_spdif_tx = PORT_SPDIF_OUT; /* SPDIF transmit port */
|
||||
|
||||
This port should be clocked from the master-clock, ``lib_spdif`` provides a helper function for setting up the port::
|
||||
|
||||
spdif_tx_port_config(p_spdif_tx2, clk_audio_mclk, p_mclk_in, delay);
|
||||
|
||||
.. note:: If sharing the master-clock port and clockblock with ``XUA_AudioHub()`` (or any other task) then this setup
|
||||
should be done before running the tasks in a ``par`` statement.
|
||||
|
||||
Finally the S/PDIF transmitter task must be run - passing in the port and channel for communication with ``XUA_AudioHub``.
|
||||
For example::
|
||||
|
||||
par
|
||||
{
|
||||
while(1)
|
||||
{
|
||||
/* Run the S/PDIF transmitter task */
|
||||
spdif_tx(p_spdif_tx2, c_spdif_tx);
|
||||
}
|
||||
|
||||
/* AudioHub/IO core does most of the audio IO i.e. I2S (also serves as a hub for all audio) */
|
||||
/* Note, since we are not using I2S we pass in null for LR and Bit clock ports and the I2S dataline ports */
|
||||
XUA_AudioHub(c_aud, clk_audio_mclk, null, p_mclk_in, null, null, null, null, c_spdif_tx);
|
||||
}
|
||||
|
||||
For further details please see the documentation, application notes and examples provided for ``lib_spdif``.
|
||||
|
||||
Codeless Programming Model
|
||||
..........................
|
||||
|
||||
If using the codeless programming method one must simply ensure the following:
|
||||
|
||||
* `PORT_SPDIF_OUT` is correctly defined in the XN file
|
||||
* `XUA_SPDIF_TX_EN` should be defined as non-zero
|
||||
* `SPDIF_TX_TILE` is correctly defined (note, this defaults to `AUDIO_IO_TILE`)
|
||||
|
||||
For further configuration options please see the API section.
|
||||
|
||||
|
||||
|
||||
|
||||
52
lib_xua/doc/rst/feat_spdif_rx.rst
Normal file
52
lib_xua/doc/rst/feat_spdif_rx.rst
Normal file
@@ -0,0 +1,52 @@
|
||||
|
||||
S/PDIF Receive
|
||||
==============
|
||||
|
||||
``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.
|
||||
|
||||
The S/PDIF receiver inputs data via a port and outputs samples via a channel. It requires a 1-bit port
|
||||
which must be 4-bit buffered. For example::
|
||||
|
||||
buffered in port:4 p_spdif_rx = PORT_SPDIF_IN;
|
||||
|
||||
It also requires a clock-block, for example::
|
||||
|
||||
clock clk_spd_rx = XS1_CLKBLK_1;
|
||||
|
||||
Finally, a channel for the output samples must be declared, note, this should be a streaming channel::
|
||||
|
||||
streaming chan c_spdif_rx;
|
||||
|
||||
The S/PDIF receiver should be called on the appropriate tile::
|
||||
|
||||
spdif_rx(c_spdif_rx,p_spdif_rx,clk_spd_rx,192000);
|
||||
|
||||
.. note::
|
||||
|
||||
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
|
||||
master clock must be able to synchronise to this external digital stream. Additionally, the host can be
|
||||
notified regarding changes in the validity of this stream, it's frequency etc. To synchronise to external
|
||||
streams the codebase assumes the use of an external Cirrus Logic CS2100 device.
|
||||
|
||||
The ``ClockGen()`` task from ``lib_xua`` provides the reference signal to the CS2100 device and also handles
|
||||
recording of clock validity etc. See :ref:`usb_audio_sec_clock_recovery` for full details regarding ``ClockGen()``.
|
||||
|
||||
It also provides a small FIFO for S/PDIF samples before they are forwarded to the ``AudioHub`` core.
|
||||
As such it requires to be inserted in the communication path between the S/PDIF receiver and the
|
||||
``AudioHub`` core. For example::
|
||||
|
||||
chan c_dig_rx;
|
||||
streaming chan c_spdif_rx;
|
||||
|
||||
par
|
||||
{
|
||||
SpdifReceive(..., c_spdif_rx, ...);
|
||||
|
||||
clockGen(c_spdif_rx, ..., c_dig_rx, ...);
|
||||
|
||||
XUA_AudioHub(..., c_dig_rx, ...);
|
||||
}
|
||||
|
||||
47
lib_xua/doc/rst/feat_spdif_tx.rst
Normal file
47
lib_xua/doc/rst/feat_spdif_tx.rst
Normal file
@@ -0,0 +1,47 @@
|
||||
|
||||
S/PDIF Transmit
|
||||
===============
|
||||
|
||||
``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.
|
||||
|
||||
The S/PDIF transmitter core takes PCM audio samples via a channel and outputs them in S/PDIF format to a port.
|
||||
Samples are provided to the S/PDIF transmitter task from the ``XUA_AudioHub()`` task.
|
||||
|
||||
The channel should be declared as normal::
|
||||
|
||||
chan c_spdif_tx
|
||||
|
||||
|
||||
In order to use the S/PDIF transmitter with ``lib_xua`` a 1-bit port must be declared e.g::
|
||||
|
||||
buffered out port:32 p_spdif_tx = PORT_SPDIF_OUT; /* SPDIF transmit port */
|
||||
|
||||
This port should be clocked from the master-clock, ``lib_spdif`` provides a helper function for setting up the port::
|
||||
|
||||
spdif_tx_port_config(p_spdif_tx, clk_audio_mclk, p_mclk_in, delay);
|
||||
|
||||
.. note:: If sharing the master-clock port and clockblock with ``XUA_AudioHub()`` (or any other task) then this setup
|
||||
should be done before running the tasks in a ``par`` statement.
|
||||
|
||||
Finally the S/PDIF transmitter task must be run - passing in the port and channel for communication with ``XUA_AudioHub``.
|
||||
For example::
|
||||
|
||||
par
|
||||
{
|
||||
while(1)
|
||||
{
|
||||
/* Run the S/PDIF transmitter task */
|
||||
spdif_tx(p_spdif_tx, c_spdif_tx);
|
||||
}
|
||||
|
||||
/* AudioHub/IO core does most of the audio IO i.e. I2S (also serves as
|
||||
* a hub for all audio).
|
||||
* Note, since we are not using I2S we pass in null for LR and Bit
|
||||
* clock ports and the I2S dataline ports */
|
||||
XUA_AudioHub(c_aud, clk_audio_mclk, null, p_mclk_in, null, null,
|
||||
null, null, c_spdif_tx);
|
||||
}
|
||||
|
||||
For further details please see the documentation, application notes and examples provided for ``lib_spdif``.
|
||||
|
||||
@@ -4,59 +4,118 @@ XMOS USB Audio Hardware Platforms
|
||||
|
||||
A range of hardware platforms for evaluating USB Audio on XMOS devices.
|
||||
|
||||
Specific, in depth, details for each platform/board are out of scope of this library documentation however, the features of the most popular platform are described below with the view of providing a worked example.
|
||||
Specific details for each platform/board are out of scope of this library documentation however, the features of the most popular platform are described below with the view of providing a worked example.
|
||||
|
||||
Please also see application note AN00246.
|
||||
|
||||
|
||||
xCORE-200 Multi-Channel Audio Board
|
||||
xCORE.AI Multichannel Audio Board
|
||||
...................................
|
||||
|
||||
`The XMOS xCORE-200 Multi-channel Audio board <https://www.xmos.com/support/boards?product=18334>`_
|
||||
(XK-AUDIO-216-MC) is a complete hardware and reference software platform targeted at up to 32-channel USB and networked audio applications, such as DJ decks and mixers.
|
||||
The XMOS xCORE.ai Multichannel Audio board (XK-AUDIO-316-MC) is a complete hardware and reference software platform targeted at up to 32-channel USB audio applications, such as DJ decks and mixers and other musical instrument interfaces. The board can also be used to prototype products with smaller feature sets or HiFi style products.
|
||||
|
||||
The Multichannel Audio Platform hardware is based around the XE216-512-TQ128 multicore microcontroller; an dual-tile xCORE-200 device with an integrated High Speed USB 2.0 PHY, RGMII (Gigabit Ethernet) interface and 16 logical cores delivering up to 2000MIPS of deterministic and responsive processing power.
|
||||
The Multichannel Audio Platform hardware is based around the XU316-1024-TQ128-C24 multicore microcontroller; an dual-tile xCORE.ai device with an integrated High Speed USB 2.0 PHY and 16 logical cores delivering up to 3200MIPS of deterministic and responsive processing power.
|
||||
|
||||
Exploiting the flexible programmability of the xCORE-200 architecture, the Multi-channel Audio Platform supports either USB or network audio source, streaming 8 analogue input and 8 analogue output audio channels simultaneously - at up to 192kHz.
|
||||
Exploiting the flexible programmability of the xCORE.ai architecture, the Multi-channel Audio Platform supports either USB or network audio source, streaming 8 analogue input and 8 analogue output audio channels simultaneously - at up to 192kHz.
|
||||
|
||||
For full details regarding the hardware please refer to `xCORE-200 Multichannel Audio Platform Hardware Manual <https://www.xmos.com/support/boards?product=18334&component=18687>`_.
|
||||
|
||||
The reference board has an associated firmware application that uses `lib_xua` to implemented a USB Audio Devicce. Full details of this application can be found in the USB Audio Design Guide.
|
||||
The reference board has an associated firmware application that uses `lib_xua` to implemented a USB Audio Device. Full details of this application can be found later in this document.
|
||||
|
||||
Analogue Input & Output
|
||||
+++++++++++++++++++++++
|
||||
|
||||
A total of eight single-ended analog input channels are provided via 3.5mm stereo jacks. Each is fed into a CirrusLogic CS5368 ADC.
|
||||
Similarly a total of eight single-ended analog output channels are provided. Each is fed into a CirrusLogic CS4384 DAC.
|
||||
A total of eight single-ended analog input channels are provided via 3.5mm stereo jacks. These inputs feed into a pair of quad-channel PCM1865 ADCs from Texas Instruments.
|
||||
|
||||
The four digital I2S/TDM input and output channels are mapped to the xCORE input/outputs through a header array. This jumper allows channel selection when the ADC/DAC is used in TDM mode
|
||||
A total of eight single-ended analog output channels are provided. These a fed from a for PCM5122 stereo DAC's from Texas instruments.
|
||||
|
||||
ADC's and DAC's are configured via an I2C bus.
|
||||
|
||||
The four digital I2S/TDM input and output channels are mapped to the xCORE input/outputs through a header array. These jumpers allow channel selection when the ADC/DAC is used in TDM mode
|
||||
|
||||
Digital Input & Output
|
||||
++++++++++++++++++++++
|
||||
|
||||
Optical and coaxial digital audio transmitters are used to provide digital audio input output in formats such as IEC60958 consumer mode (S/PDIF) and ADAT.
|
||||
The output data streams from the xCORE-200 are re-clocked using the external master clock to synchronise the data into the audio clock domain. This is achieved using simple external D-type flip-flops.
|
||||
The output data streams from the xCORE are re-clocked using the external master clock to synchronise the data into the audio clock domain. This is achieved using simple external D-type flip-flops.
|
||||
|
||||
MIDI
|
||||
++++
|
||||
|
||||
MIDI I/O is provided on the board via standard 5-pin DIN connectors. The signals are buffered using 5V line drivers and are then connected to 1-bit ports on the xCORE-200, via a 5V to 3.3V buffer.
|
||||
MIDI I/O is provided on the board via standard 5-pin DIN connectors. The signals are buffered using 5V line drivers and are then connected to 1-bit ports on the xCORE, via a 5V to 3.3V buffer.
|
||||
|
||||
Audio Clocking
|
||||
++++++++++++++
|
||||
|
||||
A flexible clocking scheme is provided for both audio and other system services. In order to accommodate a multitude of clocking options, the low-jitter master clock is generated locally using a frequency multiplier PLL chip. The chip used is a Phaselink PL611-01, which is pre-programmed to provide a 24MHz clock from its CLK0 output, and either 24.576 MHz or 22.5792MHz from its CLK1 output.
|
||||
In order to accommodate a multitude of clocking options a flexible clocking scheme is provided for the audio subsystem.
|
||||
|
||||
The 24MHz fixed output is provided to the xCORE-200 device as the main processor clock. It also provides the reference clock to a Cirrus Logic CS2100, which provides a very low jitter audio clock from a synchronisation signal provided from the xCORE-200.
|
||||
Three methods of generating an audio master clock are provided on the board:
|
||||
|
||||
* A Cirrus Logic CS2100-CP PLL device. The CS2100 features both a clock generator and clock multiplier/jitter reduced clock frequency synthesizer (clean up) and can generate a low jitter audio clock based on a synchronisation signal provided by the xCORE
|
||||
|
||||
* A Skyworks Si5351B PLL device. The Si5351 is an I2C configurable clock generator that is ideally suited for replacing crystals, crystal oscillators, VCXOs, phase-locked loops (PLLs), and fanout buffers.
|
||||
|
||||
* xCORE.ai devices are equipped with a secondary (or 'application') PLL which can be used to generate audio clocks
|
||||
|
||||
Selection between these methods is done via writing to bits 6 and 7 of PORT 8D on tile[0].
|
||||
|
||||
Either the locally generated clock (from the PL611) or the recovered low jitter clock (from the CS2100) may be selected to clock the audio stages; the xCORE-200, the ADC/DAC and Digital output stages. Selection is controlled via an additional I/O, bit 5 of PORT 8C, see :ref:`hw_316_ctrlport`.
|
||||
|
||||
.. _hw_316_ctrlport:
|
||||
|
||||
Control I/O
|
||||
+++++++++++
|
||||
|
||||
4 bits of PORT 8C are used to control external hardware on the board. This is described in :ref:`table_316_ctrlport`.
|
||||
|
||||
.. _table_316_ctrlport:
|
||||
|
||||
.. table:: PORT 8C functionality
|
||||
:class: horizontal-borders vertical_borders
|
||||
|
||||
+--------+-----------------------------------------+------------+------------+
|
||||
| Bit(s) | Functionality | 0 | 1 |
|
||||
+========+=========================================+============+============+
|
||||
| [0:3] | Unused | | |
|
||||
+--------+-----------------------------------------+------------+------------+
|
||||
| 4 | Enable 3v3 power for digital (inverted) | Enabled | Disabled |
|
||||
+--------+-----------------------------------------+------------+------------+
|
||||
| 5 | Enable 3v3 power for analogue | Disabled | Enabled |
|
||||
+--------+-----------------------------------------+------------+------------+
|
||||
| 6 | PLL Select | CS2100 | Si5351B |
|
||||
+--------+-----------------------------------------+------------+------------+
|
||||
| 7 | Master clock direction | Output | Input |
|
||||
+--------+-----------------------------------------+------------+------------+
|
||||
|
||||
|
||||
.. note::
|
||||
|
||||
To use the xCORE application PLL bit 7 should be set to 0. To use one of the external PLL's bit 7 should be set to 1.
|
||||
|
||||
Either the locally generated clock (from the PL611) or the recovered low jitter clock (from the CS2100) may be selected to clock the audio stages; the xCORE-200, the ADC/DAC and Digital output stages. Selection is conntrolled via an additional I/O, bit 5 of PORT 8C.
|
||||
|
||||
LEDs, Buttons and Other IO
|
||||
++++++++++++++++++++++++++
|
||||
|
||||
An array of 4*4 green LEDs, 3 buttons and a switch are provided for general purpose user interfacing. The LED array is driven by eight signals each controlling one of 4 rows and 4 columns.
|
||||
All programmable I/O on the board is configured for 3v3.
|
||||
|
||||
A standard XMOS xSYS interface is provided to allow host debug of the board via JTAG.
|
||||
For green LED's and three push buttons are provided for general purpose user interfacing.
|
||||
|
||||
|newpage|
|
||||
The LEDs are connected to PORT 4F and the buttons are connected to bits [0:2] of PORT 4E. Bit 3 of this port is connected to the (currently
|
||||
unused) ADC interrupt line.
|
||||
|
||||
The board also includes support for an AES11 format Word Clock input via 75 ohm BNC. The software does not support this currently and it is
|
||||
provided for future expansion.
|
||||
|
||||
All spare IO and Functional IO brought out on headers for easy connection of expansion boards (via 0.1” headers).
|
||||
|
||||
Power
|
||||
+++++
|
||||
|
||||
The board is capable of acting as a USB2.0 self or bus powered device. If bus powered, board takes power from ``USB DEVICE`` connector (micro-B receptacle).
|
||||
If self powered, board takes power from ``EXTERNAL POWER`` input (micro-B receptacle).
|
||||
|
||||
A Power Source Select (marked ``PWR SRC``) is used to select between bus and self-powered configuration.
|
||||
|
||||
|
||||
Debug
|
||||
+++++
|
||||
|
||||
For convenience the board includes an on-board xTAG4 for debugging via JTAG/xSCOPE. This is accessed via the USB (micro-B) receptacle marked ``DEBUG``.
|
||||
|
||||
|
||||
@@ -1,20 +1,34 @@
|
||||
|
||||
|appendix|
|
||||
|
||||
Known Issues
|
||||
------------
|
||||
************
|
||||
|
||||
- Quad-SPI DFU will corrupt the factory image with tools version < 14.0.4 due to an issue with libquadflash
|
||||
|
||||
- (#14762) When in DSD mode with S/PDIF output enabled, DSD samples are transmitted over S/PDIF if the DSD and S/PDIF channels are shared, this may or may not be desired
|
||||
- When in DSD mode with S/PDIF output enabled, DSD samples are transmitted over S/PDIF if the DSD and S/PDIF channels are shared, this may or may not be desired (#14762)
|
||||
|
||||
- (#14173) I2S input is completely disabled when DSD output is active - any input stream to the host will contain 0 samples
|
||||
- I2S input is completely disabled when DSD output is active - any input stream to the host will contain 0 samples (#14173)
|
||||
|
||||
- (#14780) Operating the design at a sample rate of less than or equal to the SOF rate (i.e. 8kHz at HS, 1kHz at FS) may expose a corner case relating to 0 length packet handling in both the driver and device and should be considered un-supported at this time.
|
||||
- Operating the design at a sample rate of less than or equal to the SOF rate (i.e. 8kHz at HS, 1kHz at FS) may expose a corner case relating to 0 length packet handling in both the driver and device and should be considered unsupported at this time (#14780)
|
||||
|
||||
- (#14883) Before DoP mode is detected a small number of DSD samples will be played out as PCM via I2S
|
||||
- Before DoP mode is detected a small number of DSD samples will be played out as PCM via I2S (lib_xua #162)
|
||||
|
||||
- (#14887) Volume control settings currently affect samples in both DSD and PCM modes. This results in invalid DSD output if volume control not set to 0
|
||||
- Volume control settings currently affect samples in both DSD and PCM modes. This results in invalid DSD output if volume control not set to 0 (#14887)
|
||||
|
||||
- Windows XP volume control very sensitive. The Audio 1.0 driver built into Windows XP (usbaudio.sys) does not properly support master volume AND channel volume controls, leading to a very sensitive control. Descriptors can be easily modified to disable master volume control if required (one byte - bmaControls(0) in Feature Unit descriptors)
|
||||
|
||||
- 88.2kHz and 176.4kHz sample frequencies are not exposed in Windows control panels. These are known OS restrictions.
|
||||
- 88.2kHz and 176.4kHz sample frequencies are not exposed in Windows control panels. These are known OS restrictions.
|
||||
|
||||
- When DFU flash access fails the device NAKS the host indefinitely (sw_usb_audio #54)
|
||||
|
||||
- Host mixer app (xmos_mixer) is currently not provided (lib_xua #279)
|
||||
|
||||
- In synchronous mode there is no nice transition of the reference signal when moving between internal and SOF clocks (lib_xua #275)
|
||||
|
||||
- Binary images exceeding FLASH_MAX_UPGRADE_SIZE fail silently on DFU download (lib_xua #165)
|
||||
|
||||
- UAC 1.0 mode assumes device always has input. A run time exception occurs if this is not the case (lib_xua #58)
|
||||
|
||||
- No support for I2S_CHANS_DAC = 0 and I2S_CHANS_ADC = 0 (lib_xua #260)
|
||||
|
||||
|
||||
@@ -1,37 +1,24 @@
|
||||
|
||||
.. include:: ../../../README.rst
|
||||
|
||||
|
||||
About This Document
|
||||
-------------------
|
||||
===================
|
||||
|
||||
This document describes the structure of the library, 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.
|
||||
|
||||
This document assumes familiarity with the XMOS xCORE architecture, the Universal Serial Bus 2.0 Specification (and related specifications),
|
||||
the XMOS tool chain and XC language.
|
||||
|
||||
|
||||
Host System Requirements
|
||||
------------------------
|
||||
|
||||
USB Audio devices built using `lib_xua` have the following host system requirements.
|
||||
|
||||
- Mac OSX version 10.6 or later
|
||||
|
||||
- Windows Vista, 7, 8 or 10 with Thesycon Audio Class 2.0 driver for Windows (Tested against version 3.20). Please contact XMOS for details.
|
||||
|
||||
- Windows Vista, 7, 8 or 10 with built-in USB Audio Class 1.0 driver.
|
||||
|
||||
Older versions of Windows are not guaranteed to operate as expected. Devices are also expected to operate with various Linux distributions including mobile variants.
|
||||
|
||||
.. toctree::
|
||||
|
||||
Overview <overview>
|
||||
Hardware Platforms <hw>
|
||||
Software Overview <sw>
|
||||
Using lib_xua <using>
|
||||
Features <feat>
|
||||
Software Detail <sw_detail>
|
||||
Software Architecture <arch>
|
||||
Basic Usage <using>
|
||||
Options <opt>
|
||||
Advanced Usage <using_adv>
|
||||
Additional Features <feat>
|
||||
Implementation Detail <sw>
|
||||
API <api>
|
||||
Known Issues <issues>
|
||||
|
||||
|
||||
|
||||
37
lib_xua/doc/rst/opt.rst
Normal file
37
lib_xua/doc/rst/opt.rst
Normal file
@@ -0,0 +1,37 @@
|
||||
|
||||
.. _sec_options:
|
||||
|
||||
Options
|
||||
*******
|
||||
|
||||
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.
|
||||
|
||||
For full details of all options please see ::ref:`sec_api`.
|
||||
|
||||
.. toctree::
|
||||
|
||||
Strings <opt_strings>
|
||||
Code Location <opt_location>
|
||||
Channel Counts and Sample Rates <opt_channels>
|
||||
USB Audio Class Support <opt_audio_class>
|
||||
Synchronisation <opt_sync>
|
||||
I2S/TDM <opt_i2s>
|
||||
S/PDIF Transmit <opt_spdif_tx>
|
||||
S/PDIF Receive <opt_spdif_rx>
|
||||
MIDI <opt_midi>
|
||||
PDM Microphones <opt_pdm>
|
||||
Mixer <opt_mixer>
|
||||
Direct Stream Digital (DSD) <opt_dsd>
|
||||
USB Audio Formats <opt_audio_formats>
|
||||
Other Options <opt_other>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,33 +1,40 @@
|
||||
USB Audio Class Version Support
|
||||
-------------------------------
|
||||
|newpage|
|
||||
|
||||
The XMOS USB Audio framework supports both USB Audio Class 1.0 and Audio Class 2.0.
|
||||
USB Audio Class Version
|
||||
=======================
|
||||
|
||||
USB Audio Class 2.0 offers many improvements over USB Audio Class 1.0, most notable is the complete support for high-speed operation. This means that Audio Class devices are no longer limited to full-speed operation allowing greater channel counts, sample frequencies and sample bit-depths. Additional improvement, amoungst others, include:
|
||||
The codebase supports USB Audio Class versions 1.0 and 2.0.
|
||||
|
||||
USB Audio Class 2.0 offers many improvements over USB Audio Class 1.0, most notable is the complete
|
||||
support for high-speed operation. This means that Audio Class devices are no longer limited to
|
||||
full-speed operation allowing greater channel counts, sample frequencies and sample bit-depths.
|
||||
Additional improvements, amongst others, include:
|
||||
|
||||
- Added support for multiple clock domains, clock description and clock control
|
||||
|
||||
- Extensive support for interrupts to inform the host about dynamic changes that occur to different entities such as Clocks etc
|
||||
|
||||
Driver Support
|
||||
~~~~~~~~~~~~~~
|
||||
--------------
|
||||
|
||||
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 2.0
|
||||
+++++++++++++++
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
Audio Class 2.0 is fully supported in Apple OSX since version 10.6.4. Audio Class 2.0 is not supported natively by Windows operating systems. It is therefore required that a driver is installed. Documentation of Windows drivers is beyond the scope of this document, please contact XMOS for further details.
|
||||
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.
|
||||
|
||||
Audio Class 1.0 Mode and Fall-back
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
----------------------------------
|
||||
|
||||
The normal 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
|
||||
allow "driver-less" operation with Windows operating systems.
|
||||
allow "driver-less" operation with older versions of Windows operating systems.
|
||||
|
||||
.. note::
|
||||
|
||||
@@ -41,7 +48,7 @@ The device will operate in full-speed Audio Class 1.0 mode if one of the followi
|
||||
to the host over a full speed link (and the Audio Class fall back is
|
||||
enabled).
|
||||
|
||||
The options to control this behavior are detailed in :ref:`usb_audio_sec_custom_defines_api`.
|
||||
The options to control this behavior are detailed in :ref:`sec_api_defines`.
|
||||
|
||||
When running in Audio Class 1.0 mode the following restrictions are applied:
|
||||
|
||||
@@ -55,3 +62,29 @@ Due to bandwidth limitations of full-speed USB the following sample-frequency re
|
||||
|
||||
- Sample rate is limited to a maximum of 96kHz if only input *or* output is enabled.
|
||||
|
||||
|
||||
Related Defines
|
||||
---------------
|
||||
|
||||
:ref:`opt_audio_class_defines` descibes the defines that effect audio class selection.
|
||||
|
||||
.. _opt_audio_class_defines:
|
||||
|
||||
.. list-table:: Audio Class defines
|
||||
:header-rows: 1
|
||||
:widths: 20 80 20
|
||||
|
||||
* - Define
|
||||
- Description
|
||||
- Default
|
||||
* - ``AUDIO_CLASS``
|
||||
- Audio Class version (1 or 2)
|
||||
- N/A (*must* be defined)
|
||||
* - ``AUDIO_CLASS_FALLBACK``
|
||||
- Enable audio class fallback functionalty
|
||||
- ``0`` (disabled)
|
||||
|
||||
.. note::
|
||||
|
||||
Enabling USB Audio Class fallback functionality may have USB Compliance implications
|
||||
|
||||
135
lib_xua/doc/rst/opt_audio_formats.rst
Normal file
135
lib_xua/doc/rst/opt_audio_formats.rst
Normal file
@@ -0,0 +1,135 @@
|
||||
|newpage|
|
||||
|
||||
.. _sec_opt_audio_formats:
|
||||
|
||||
Audio Stream Formats
|
||||
====================
|
||||
|
||||
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.
|
||||
|
||||
An Audio Streaming interface can have Alternate Settings that can be used to change certain characteristics
|
||||
of the interface and underlying endpoint. A typical use of Alternate Settings is to provide a way to
|
||||
change the subframe size and/or number of channels on an active Audio Streaming interface.
|
||||
Whenever an Audio Streaming interface requires an isochronous data endpoint, it must at least provide
|
||||
the default Alternate Setting (Alternate Setting 0) with zero bandwidth requirements (no isochronous
|
||||
data endpoint defined) and an additional Alternate Setting that contains the actual isochronous
|
||||
data endpoint. This zero bandwidth alternative setting 0 is always implemented by the design.
|
||||
|
||||
For further information refer to 3.16.2 of `USB Audio Device Class Definition for Audio Devices <http://www.usb.org/developers/devclass_docs/Audio2.0_final.zip>`_
|
||||
|
||||
Customisable parameters for the Alternate Settings provided by the design are as follows.:
|
||||
|
||||
* Audio sample resolution
|
||||
* Audio sample subslot size
|
||||
* Audio data format
|
||||
|
||||
.. note::
|
||||
|
||||
Currently only a single format is supported for the recording stream
|
||||
|
||||
By default the design exposes two sets of Alternative Settings for the playback Audio Streaming interface, one for 16-bit and another for
|
||||
24-bit playback. When DSD is enabled an additional (32-bit) alternative is exposed.
|
||||
|
||||
Audio Subslot
|
||||
-------------
|
||||
|
||||
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.
|
||||
This is represented by `bSubslotSize` in the devices descriptor set.
|
||||
|
||||
An audio subslot always contains an integer number of bytes. The specification limits the possible
|
||||
audio subslot size to 1, 2, 3 or 4 bytes per audio subslot.
|
||||
|
||||
Since the xCORE is a 32-bit machine the value 4 is typically used for `bSubSlot` - this means that
|
||||
packing/unpacking samples to/from packets is trivial. Other values can, however, be used and the design
|
||||
supports values 4, 3 and 2.
|
||||
|
||||
Values other than 4 may be used for the following reasons:
|
||||
|
||||
* Bus-bandwidth needs to be efficiently utilised. For example maximising channel-count/sample-rates in
|
||||
full-speed operation.
|
||||
|
||||
* To support restrictions with certain hosts. For example many Android based hosts support only 16bit
|
||||
samples in a 2-byte subslot.
|
||||
|
||||
`bSubSlot` size is set using the following defines:
|
||||
|
||||
* When running in high-speed:
|
||||
|
||||
* `HS_STREAM_FORMAT_OUTPUT_1_SUBSLOT_BYTES`
|
||||
|
||||
* `HS_STREAM_FORMAT_OUTPUT_2_SUBSLOT_BYTES`
|
||||
|
||||
* `HS_STREAM_FORMAT_OUTPUT_3_SUBSLOT_BYTES`
|
||||
|
||||
* When running in full-speed:
|
||||
|
||||
* `FS_STREAM_FORMAT_OUTPUT_1_SUBSLOT_BYTES`
|
||||
|
||||
* `FS_STREAM_FORMAT_OUTPUT_2_SUBSLOT_BYTES`
|
||||
|
||||
* `FS_STREAM_FORMAT_OUTPUT_3_SUBSLOT_BYTES`
|
||||
|
||||
|
||||
Audio Sample Resolution
|
||||
-----------------------
|
||||
|
||||
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
|
||||
supports values 16, 24 and 32.
|
||||
|
||||
`bBitResolution` is set using the following defines:
|
||||
|
||||
* When operating at high-speed:
|
||||
|
||||
* `HS_STREAM_FORMAT_OUTPUT_1_RESOLUTION_BITS`
|
||||
|
||||
* `HS_STREAM_FORMAT_OUTPUT_2_RESOLUTION_BITS`
|
||||
|
||||
* `HS_STREAM_FORMAT_OUTPUT_3_RESOLUTION_BITS`
|
||||
|
||||
* When operating at full-speed:
|
||||
|
||||
* `FS_STREAM_FORMAT_OUTPUT_1_RESOLUTION_BITS`
|
||||
|
||||
* `FS_STREAM_FORMAT_OUTPUT_2_RESOLUTION_BITS`
|
||||
|
||||
* `FS_STREAM_FORMAT_OUTPUT_3_RESOLUTION_BITS`
|
||||
|
||||
|
||||
Audio Format
|
||||
------------
|
||||
|
||||
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.
|
||||
|
||||
The USB Audio `Raw Data` format is used to indicate DSD data (2.3.1.7.5 of `USB Device Class
|
||||
Definition for Audio Data Formats <http://www.usb.org/developers/devclass_docs/Audio2.0_final.zip>`_).
|
||||
This use of a RAW/DSD format in an alternative setting is termed by XMOS as *Native DSD*
|
||||
|
||||
The following defines affect both full-speed and high-speed operation:
|
||||
|
||||
* STREAM_FORMAT_OUTPUT_1_DATAFORMAT
|
||||
|
||||
* STREAM_FORMAT_OUTPUT_2_DATAFORMAT
|
||||
|
||||
* STREAM_FORMAT_OUTPUT_3_DATAFORMAT
|
||||
|
||||
The following options are supported:
|
||||
|
||||
* UAC_FORMAT_TYPEI_RAW_DATA
|
||||
|
||||
* UAC_FORMAT_TYPEI_PCM
|
||||
|
||||
.. note::
|
||||
|
||||
Currently DSD is only supported on the output/playback stream
|
||||
|
||||
.. note::
|
||||
|
||||
4 byte slot size with a 32 bit resolution is required for RAW/DSD format
|
||||
|
||||
Native DSD requires driver support and is available in the Thesycon Windows driver via ASIO.
|
||||
|
||||
|
||||
73
lib_xua/doc/rst/opt_channels.rst
Normal file
73
lib_xua/doc/rst/opt_channels.rst
Normal file
@@ -0,0 +1,73 @@
|
||||
|newpage|
|
||||
|
||||
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
|
||||
availablity.
|
||||
|
||||
For example, the maximum packet size for high-speed USB is 1024 bytes, limiting the channel count
|
||||
to 10 channels for a device running at 192kHz with 32bit sample depth.
|
||||
|
||||
The defines in :ref:`opt_channel_defines` set the channel counts exposed to the USB host.
|
||||
|
||||
.. tabularcolumns:: lp{5cm}l
|
||||
.. _opt_channel_defines:
|
||||
.. list-table:: Channel count defines
|
||||
:header-rows: 1
|
||||
:widths: 20 80 20
|
||||
|
||||
* - Define
|
||||
- Description
|
||||
- Default
|
||||
* - ``NUM_USB_CHAN_OUT``
|
||||
- Number of output channels the device advertises to the USB host
|
||||
- N/A (must be defined)
|
||||
* - ``NUM_USB_CHAN_IN``
|
||||
- Number of input channels the device advertises to the USB host
|
||||
- N/A (must be defined)
|
||||
|
||||
Sample rates ranges are set by the defines in :ref:`opt_channel_sr_defines`. The codebase will
|
||||
automatically populate the device sample rate list with popular frequencies between the min and
|
||||
max values. All values are in Hz:
|
||||
|
||||
.. tabularcolumns:: lp{5cm}l
|
||||
.. _opt_channel_sr_defines:
|
||||
.. list-table:: Sample rate defines
|
||||
:header-rows: 1
|
||||
:widths: 20 80 20
|
||||
|
||||
* - Define
|
||||
- Description
|
||||
- Default
|
||||
* - ``MAX_FREQ``
|
||||
- Maximum supported sample rate (Hz)
|
||||
- ``192000``
|
||||
* - ``MIN_FREQ``
|
||||
- Minimum supported sample rate (Hz)
|
||||
- ``44100``
|
||||
* - ``DEFAULT_FREQ``
|
||||
- Starting frequency for the device after boot
|
||||
- ``MIN_FREQ``
|
||||
|
||||
|
||||
The codebase requires knowledge of the two master clock frequencies that will be present on the
|
||||
master-clock port(s). One for 44.1kHz, 88.2kHz etc and one for 48kHz, 96kHz etc. These are set
|
||||
using defines in :ref:`opt_channel_mc_defines`. All values are in Hz.
|
||||
|
||||
.. tabularcolumns:: lp{5cm}l
|
||||
.. _opt_channel_mc_defines:
|
||||
.. list-table:: Master clock rate defines
|
||||
:header-rows: 1
|
||||
:widths: 20 80 20
|
||||
|
||||
* - Define
|
||||
- Description
|
||||
- Default
|
||||
* - ``CLK_441``
|
||||
- Master clock defines for 44100 rates (Hz)
|
||||
- ``(256 * 44100)``
|
||||
* - ``MCLK_48``
|
||||
- Master clock defines for 48000 rates (Hz)
|
||||
- ``(256 * 48000)``
|
||||
104
lib_xua/doc/rst/opt_dsd.rst
Normal file
104
lib_xua/doc/rst/opt_dsd.rst
Normal file
@@ -0,0 +1,104 @@
|
||||
|newpage|
|
||||
|
||||
Direct Stream Digital (DSD)
|
||||
===========================
|
||||
|
||||
Direct Stream Digital (DSD) is used for digitally encoding audio signals on Super Audio CDs (SACD).
|
||||
It uses pulse-density modulation (PDM) encoding.
|
||||
|
||||
The codebase supports DSD playback from the host via "DSD over PCM" (DoP) and a "Native" implementation
|
||||
which is, while USB specification based, proprietary to XMOS.
|
||||
|
||||
DSD is enabled with by setting the define in :ref:`opt_dsd_defines` to a non-zero value.
|
||||
|
||||
.. _opt_dsd_defines:
|
||||
|
||||
.. list-table:: DSD defines
|
||||
:header-rows: 1
|
||||
:widths: 20 80 20
|
||||
|
||||
* - Define
|
||||
- Description
|
||||
- Default
|
||||
* - ``DSD_CHANS_DAC``
|
||||
- Number of DSD channels
|
||||
- ``0`` (Disabled)
|
||||
|
||||
Typically this would be set to ``2`` for stereo output.
|
||||
|
||||
By default both "Native" and DoP functionality are enabled when DSD is enabled. The Native DSD implementation uses
|
||||
an alternative streaming interface such that the host can inform the device that DSD data is being streamed.
|
||||
See: ::ref:`sec_opt_audio_formats` for details.
|
||||
|
||||
If only DoP functionality is desired the Native implementation can be disabled with the define in
|
||||
:ref:`opt_nativedsd_defines`.
|
||||
|
||||
.. _opt_nativedsd_defines:
|
||||
|
||||
.. list-table:: Native DSD defines
|
||||
:header-rows: 1
|
||||
:widths: 20 80 20
|
||||
|
||||
* - Define
|
||||
- Description
|
||||
- Default
|
||||
* - ``NATIVE_DSD``
|
||||
- Enable/Disable "Native" DSD implementation
|
||||
- ``1`` (Enabled)
|
||||
|
||||
|
||||
DSD over PCM (DoP)
|
||||
------------------
|
||||
|
||||
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>`_.
|
||||
|
||||
While Native DSD support is available in Windows though a driver, OSX incorporates a USB driver
|
||||
that only supports PCM, this is also true of the central audio engine, CoreAudio. It is
|
||||
therefore not possible to use the "Native" scheme defined above using the built in driver of OSX.
|
||||
|
||||
Since the Apple OS only allows a PCM path a method of transporting DSD audio data over PCM frames
|
||||
has been developed.
|
||||
|
||||
Standard DSD has a sample size of 1 bit and a sample rate of 2.8224MHz - this is 64x the speed of a
|
||||
compact disc (CD). This equates to the same data-rate as a 16 bit PCM stream at 176.4kHz.
|
||||
|
||||
In order to clearly identify when this PCM stream contains DSD and when it contains PCM some header
|
||||
bits are added to the sample. A 24-bit PCM stream is therefore used, with the most significant
|
||||
byte being used for a DSD marker (alternating 0x05 and 0xFA values).
|
||||
|
||||
When enabled, if USB audio design detects a un-interrupted run of these samples (above a defined
|
||||
threshold) it switches to DSD mode, using the lower 16-bits as DSD sample data. When this check for
|
||||
DSD headers fails the design falls back to PCM mode. DoP detection and switching is done completely
|
||||
in the Audio/I2S core (`audio.xc`). All other code handles the audio samples as PCM.
|
||||
|
||||
The design supports higher DSD/DoP rates (i.e. DSD128) by simply raising the underlying PCM sample
|
||||
rate e.g. from 176.4kHz to 352.8kHz. The marker byte scheme remains exactly the same regardless
|
||||
of rate.
|
||||
|
||||
.. note::
|
||||
|
||||
DoP requires bit-perfect transmission - therefore any audio/volume processing will break the stream.
|
||||
|
||||
"Native" vs DoP
|
||||
---------------
|
||||
|
||||
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.
|
||||
Such a property may be desired when upporting DSD128 without exposing a 352.8kHz PCM rate, for example.
|
||||
|
||||
Ports
|
||||
-----
|
||||
|
||||
The codebase expects 1-bit ports to be defined in the application XN file for the DSD data and
|
||||
clock lines for example::
|
||||
|
||||
<Port Location="XS1_PORT_1M" Name="PORT_DSD_DAC0"/>
|
||||
<port Location="XS1_PORT_1N" Name="PORT_DSD_DAC1"/>
|
||||
<Port Location="XS1_PORT_1G" Name="PORT_DSD_CLK"/>
|
||||
|
||||
.. note::
|
||||
|
||||
The DSD ports may or may not overlap the I2S ports - the codebase will reconfigure the ports as appropriate
|
||||
when switching between PCM and DSD modes.
|
||||
|
||||
60
lib_xua/doc/rst/opt_i2s.rst
Normal file
60
lib_xua/doc/rst/opt_i2s.rst
Normal file
@@ -0,0 +1,60 @@
|
||||
|newpage|
|
||||
|
||||
I2S/TDM
|
||||
=======
|
||||
|
||||
I2S/TDM is typically fundamental to most products and is built into the ``XUA_AudioHub()`` core.
|
||||
|
||||
The defines in :ref:`opt_i2s_defines` effect the I2S implementation.
|
||||
|
||||
.. tabularcolumns:: lp{5cm}l
|
||||
.. _opt_i2s_defines:
|
||||
.. list-table:: I2S defines
|
||||
:header-rows: 1
|
||||
:widths: 20 80 20
|
||||
|
||||
* - Define
|
||||
- Description
|
||||
- Default
|
||||
* - ``I2S_CHANS_DAC``
|
||||
- The desired number of output channels via I2S (0 for disabled)
|
||||
- N/A (Must be defined)
|
||||
* - ``I2S_CHANS_ADC``
|
||||
- The desired number of input channels via I2S (0 for disabled)
|
||||
- N/A (Must be defined)
|
||||
* - ``XUA_PCM_FORMAT``
|
||||
- Enables either TDM or I2S mode
|
||||
- ``XUA_PCM_FORMAT_I2S``
|
||||
* - ``CODEC_MASTER``
|
||||
- Sets if xCORE is I2S master or slave
|
||||
- ``0`` (xCORE is master)
|
||||
* - ``XUA_I2S_N_BITS``
|
||||
- I2S/TDM word length (16, 32-bit supported)
|
||||
- ``32``
|
||||
|
||||
The I2S code expects that the ports required for I2S (master clock, LR-clock, bit-clock and data lines) are be defined in the application XN file in the relevant `Tile``.
|
||||
For example::
|
||||
|
||||
<Tile Number="0" Reference="tile[0]">
|
||||
<Port Location="XS1_PORT_1A" Name="PORT_MCLK_IN"/>
|
||||
<Port Location="XS1_PORT_1B" Name="PORT_I2S_LRCLK"/>
|
||||
<Port Location="XS1_PORT_1C" Name="PORT_I2S_BCLK"/>
|
||||
<Port Location="XS1_PORT_1D" Name="PORT_I2S_DAC0"/>
|
||||
<port Location="XS1_PORT_1E" Name="PORT_I2S_DAC1"/>
|
||||
<Port Location="XS1_PORT_1F" Name="PORT_I2S_ADC0"/>
|
||||
<Port Location="XS1_PORT_1G" Name="PORT_I2S_ADC1"/>
|
||||
</Tile>
|
||||
|
||||
All of the I2S/TDM related ports must be 1-bit ports.
|
||||
|
||||
.. note::
|
||||
|
||||
TDM mode allows 8 channels (rather than 2) to be supplied on each 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.
|
||||
|
||||
44
lib_xua/doc/rst/opt_location.rst
Normal file
44
lib_xua/doc/rst/opt_location.rst
Normal file
@@ -0,0 +1,44 @@
|
||||
|newpage|
|
||||
|
||||
Code Location
|
||||
=============
|
||||
|
||||
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
|
||||
resources and associated code.
|
||||
|
||||
A series of defines are used to allow the programmer to easily move code between tiles. Arguably the
|
||||
most important of these are ``AUDIO_IO_TILE`` and ``XUD_TILE``. :ref:`opt_location_defines` shows a
|
||||
full listing of these ``TILE`` defines.
|
||||
|
||||
.. tabularcolumns:: lp{5cm}l
|
||||
.. _opt_location_defines:
|
||||
.. list-table:: Tile defines
|
||||
:header-rows: 1
|
||||
:widths: 20 80 20
|
||||
|
||||
* - Define
|
||||
- Description
|
||||
- Default
|
||||
* - ``AUDIO_IO_TILE``
|
||||
- Tile on which I2S/TDM, ADAT Rx, S/PDIF Rx & mixer resides
|
||||
- ``0``
|
||||
* - ``XUD_TILE``
|
||||
- Tile on which USB resides, including buffering for all USB interfaces/endppoints
|
||||
- ``0``
|
||||
* - ``MIDI_TILE``
|
||||
- Tile on which MIDI resides
|
||||
- Same as ``AUDIO_IO_TILE``
|
||||
* - ``SPDIF_TX_TILE``
|
||||
- Tile on which S/PDIF Tx resides
|
||||
- Same as ``AUDIO_IO_TILE``
|
||||
* - ``PDM_TILE``
|
||||
- Tile on which PDM microphones resides
|
||||
- Same as ``AUDIO_IO_TILE``
|
||||
* - ``PLL_REF_TILE``
|
||||
- Tile on which reference signal to CS2100 resides
|
||||
- Same as ``AUDIO_IO_TILE``
|
||||
|
||||
.. note::
|
||||
|
||||
It should be ensured that the relevant port defines in the application XN file match the code location defines
|
||||
54
lib_xua/doc/rst/opt_midi.rst
Normal file
54
lib_xua/doc/rst/opt_midi.rst
Normal file
@@ -0,0 +1,54 @@
|
||||
|
||||
|newpage|
|
||||
|
||||
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>`_.
|
||||
|
||||
MIDI functionality is enabled with the define in :ref:`opt_midi_defines`.
|
||||
|
||||
.. _opt_midi_defines:
|
||||
|
||||
.. list-table:: MIDI enable define
|
||||
:header-rows: 1
|
||||
:widths: 20 80 20
|
||||
|
||||
* - Define
|
||||
- Description
|
||||
- Default
|
||||
* - ``MIDI``
|
||||
- Enable MIDI functionality
|
||||
- ``0`` (Disabled)
|
||||
|
||||
|
||||
The codebase supports MIDI receive on a 4-bit or 1-bit port, defaulting to using a 1-bit port.
|
||||
MIDI transmit is supported port of any bit-width. By default the codebase assumes the transmit
|
||||
and receive I/O is connected to bit[0] of the port. This is configurable for the transmit port.
|
||||
:ref:`opt_midi_defines` provides information on the configuring these parameters.
|
||||
|
||||
.. _opt_midi_port_defines:
|
||||
|
||||
.. list-table:: MIDI port defines
|
||||
:header-rows: 1
|
||||
:widths: 20 80 20
|
||||
|
||||
* - Define
|
||||
- Description
|
||||
- Default
|
||||
* - ``MIDI_RX_PORT_WIDTH``
|
||||
- Port width of the MIDI rx port (1 or 4bit)
|
||||
- ``1`` (1-bit port)
|
||||
* - ``MIDI_SHIFT_TX``
|
||||
- MIDI tx bit
|
||||
- ``0`` (bit[0])
|
||||
|
||||
The MIDI code expects that the ports for receive and transmit are defined in the application XN file in the relevant Tile.
|
||||
The expected names for the ports are ``PORT_MIDI_IN`` and ``PORT_MIDI_OUT``, for example::
|
||||
|
||||
<Tile Number="0" Reference="tile[0]">
|
||||
<!-- MIDI -->
|
||||
<Port Location="XS1_PORT_1F" Name="PORT_MIDI_IN"/>
|
||||
<Port Location="XS1_PORT_4C" Name="PORT_MIDI_OUT"/>
|
||||
</Tile>
|
||||
|
||||
41
lib_xua/doc/rst/opt_mixer.rst
Normal file
41
lib_xua/doc/rst/opt_mixer.rst
Normal file
@@ -0,0 +1,41 @@
|
||||
|newpage|
|
||||
|
||||
Mixer
|
||||
=====
|
||||
|
||||
The codebase supports audio mixing functionality with highly flexible routing options.
|
||||
|
||||
Essentially the mixer is capable of performing 8 separate mixes with up to 18 inputs at sample rates
|
||||
up to 96kHz and 2 mixes with up to 18 inputs at higher sample rates.
|
||||
|
||||
Inputs to the mixer can be selected from any device input (USB, S/PDIF, I2S etc) and
|
||||
outputs from the mixer can be routed to any device output (USB, S/PDIF, I2S etc).
|
||||
|
||||
See :ref:`usb_audio_sec_mixer` for full details of the mixer including control.
|
||||
|
||||
Basic configuration of mixer functionality is achieved with the defines in :ref:`opt_mixer_defines`.
|
||||
|
||||
.. _opt_mixer_defines:
|
||||
|
||||
.. list-table:: Mixer defines
|
||||
:header-rows: 1
|
||||
:widths: 20 80 20
|
||||
|
||||
* - Define
|
||||
- Description
|
||||
- Default
|
||||
* - ``MIXER``
|
||||
- Enable mixer
|
||||
- ``0`` (Disabled)
|
||||
* - ``MAX_MIX_COUNT``
|
||||
- Number of separate mix outputs to perform
|
||||
- ``8``
|
||||
* - ``MIX_INPUTS``
|
||||
- Number of channels input into the mixer
|
||||
- ``18``
|
||||
|
||||
.. note::
|
||||
|
||||
The mixer cores always run on the tile defined by ``AUDIO_IO_TILE``
|
||||
|
||||
|
||||
26
lib_xua/doc/rst/opt_other.rst
Normal file
26
lib_xua/doc/rst/opt_other.rst
Normal file
@@ -0,0 +1,26 @@
|
||||
|newpage|
|
||||
|
||||
Other Options
|
||||
=============
|
||||
|
||||
There are a few other, lesser used, options available.
|
||||
|
||||
.. _opt_other_defines:
|
||||
|
||||
.. list-table:: Other defines
|
||||
:header-rows: 1
|
||||
:widths: 20 80 20
|
||||
|
||||
* - Define
|
||||
- Description
|
||||
- Default
|
||||
* - ``XUA_USB_EN``
|
||||
- Allows the use of the audio subsytem without USB
|
||||
- ``1`` (enabled)
|
||||
* - ``INPUT_VOLUME_CONTROL``
|
||||
- Enables volume control on input channels, both descriptors and processing
|
||||
- ``1`` (enabled)
|
||||
* - ``OUTPUT_VOLUME_CONTROL``
|
||||
- Enables volume control on output channels, both descriptors and processing
|
||||
- ``1`` (enabled)
|
||||
|
||||
36
lib_xua/doc/rst/opt_pdm.rst
Normal file
36
lib_xua/doc/rst/opt_pdm.rst
Normal file
@@ -0,0 +1,36 @@
|
||||
|newpage|
|
||||
|
||||
PDM Microphones
|
||||
===============
|
||||
|
||||
The codebase supports input from up to 8 PDM microphones.
|
||||
|
||||
PDM microphone support is provided via ``lib_mic_array``. Settings for PDM microphones are controlled
|
||||
via the defines in :ref:`opt_pdm_defines`.
|
||||
|
||||
.. _opt_pdm_defines:
|
||||
|
||||
.. list-table:: PDM defines
|
||||
:header-rows: 1
|
||||
:widths: 20 80 20
|
||||
|
||||
* - Define
|
||||
- Description
|
||||
- Default
|
||||
* - ``XUA_NUM_PDM_MICS``
|
||||
- The number of mics to enable (0 for disabled)
|
||||
- ``0`` (disabled)
|
||||
* - ``PDM_MIC_INDEX``
|
||||
- Defines which input channel the mics map to
|
||||
- ``0``
|
||||
|
||||
The codebase expects 1-bit ports to be defined in the application XN file for ``PORT_PDM_CLK`` and ``PORT_PDM_MCLK``.
|
||||
An 8-bit port is expected for ``PORT_PDM_DATA``. For example::
|
||||
|
||||
<Tile Number="0" Reference="tile[0]">
|
||||
<!-- Mic related ports -->
|
||||
<Port Location="XS1_PORT_1E" Name="PORT_PDM_CLK"/>
|
||||
<Port Location="XS1_PORT_8B" Name="PORT_PDM_DATA"/>
|
||||
<Port Location="XS1_PORT_1F" Name="PORT_PDM_MCLK"/>
|
||||
</Tile>
|
||||
|
||||
60
lib_xua/doc/rst/opt_spdif_rx.rst
Normal file
60
lib_xua/doc/rst/opt_spdif_rx.rst
Normal file
@@ -0,0 +1,60 @@
|
||||
|newpage|
|
||||
|
||||
S/PDIF Receive
|
||||
==============
|
||||
|
||||
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).
|
||||
|
||||
Basic configuration of S/PDIF receive functionality is achieved with the defines in :ref:`opt_spdif_rx_defines`.
|
||||
|
||||
.. _opt_spdif_rx_defines:
|
||||
|
||||
.. list-table:: S/PDIF rx defines
|
||||
:header-rows: 1
|
||||
:widths: 20 80 20
|
||||
|
||||
* - Define
|
||||
- Description
|
||||
- Default
|
||||
* - ``XUA_SPDIF_RX_EN``
|
||||
- Enable S/PDIF receive
|
||||
- ``0`` (Disabled)
|
||||
* - ``SPDIF_RX_INDEX``
|
||||
- Defines which channels S/PDIF will be input on
|
||||
- N/A (must defined)
|
||||
|
||||
.. note::
|
||||
|
||||
S/PDIF receive always runs on the tile defined by ``AUDIO_IO_TILE``
|
||||
|
||||
The codebase expects the S/PDIF receive port to be defined in the application XN file as ``PORT_SPDIF_IN``.
|
||||
This must be a 1-bit port, for example::
|
||||
|
||||
<Port Location="XS1_PORT_1A" Name="PORT_SPDIF_IN"/>
|
||||
|
||||
When S/PDIF receive is enabled the codebase expects to drive a synchronisation signal to an external
|
||||
Cirrus Logic CS2100 device for master-clock generation.
|
||||
|
||||
The programmer should ensure the define in :ref:`opt_spdif_rx_ref_defines` is set appropriately.
|
||||
|
||||
.. _opt_spdif_rx_ref_defines:
|
||||
|
||||
.. list-table:: Reference Clock Location
|
||||
:header-rows: 1
|
||||
:widths: 20 80 20
|
||||
|
||||
* - Define
|
||||
- Description
|
||||
- Default
|
||||
* - ``PLL_REF_TILE``
|
||||
- Tile location of reference to CS2100 device
|
||||
- ``AUDIO_IO_TILE``
|
||||
|
||||
The codebase expects this reference signal port to be defined in the application XN file as ``PORT_PLL_REF``.
|
||||
This may be a port of any bit-width, however, connection to bit[0] is assumed::
|
||||
|
||||
<Port Location="XS1_PORT_1A" Name="PORT_PLL_REF"/>
|
||||
|
||||
Configuration of the external CS2100 device (typically via I2C) is beyond the scope of this document.
|
||||
|
||||
46
lib_xua/doc/rst/opt_spdif_tx.rst
Normal file
46
lib_xua/doc/rst/opt_spdif_tx.rst
Normal file
@@ -0,0 +1,46 @@
|
||||
|newpage|
|
||||
|
||||
S/PDIF Transmit
|
||||
===============
|
||||
|
||||
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).
|
||||
|
||||
Basic configuration of S/PDIF transmit functionality is achieved with the defines in :ref:`opt_spdif_tx_defines`
|
||||
|
||||
.. _opt_spdif_tx_defines:
|
||||
|
||||
.. list-table:: S/PDIF tx defines
|
||||
:header-rows: 1
|
||||
:widths: 20 80 20
|
||||
|
||||
* - Define
|
||||
- Description
|
||||
- Default
|
||||
* - ``XUA_SPDIF_TX_EN``
|
||||
- Enable S/PDIF transmit
|
||||
- ``0`` (Disabled)
|
||||
* - ``SPDIF_TX_INDEX``
|
||||
- Output channel offset to use for S/PDIF transmit
|
||||
- ``0``
|
||||
|
||||
In addition, the developer may choose which tile the S/PDIF transmitter runs on, see :ref:`opt_spdif_tx_tile_defines`.
|
||||
|
||||
.. _opt_spdif_tx_tile_defines:
|
||||
|
||||
.. list-table:: S/PDIF tile define
|
||||
:header-rows: 1
|
||||
:widths: 20 80 20
|
||||
|
||||
* - Define
|
||||
- Description
|
||||
- Default
|
||||
* - ``SPDIF_TX_TILE``
|
||||
- Tile that S/PDIF tx is connected to
|
||||
- ``AUDIO_IO_TILE``
|
||||
|
||||
The codebase expects the S/PDIF transmit port to be defined in the application XN file as ``PORT_SPDIF_OUT``.
|
||||
This must be a 1-bit port, for example::
|
||||
|
||||
<Port Location="XS1_PORT_1A" Name="PORT_SPDIF_OUT"/>
|
||||
|
||||
41
lib_xua/doc/rst/opt_strings.rst
Normal file
41
lib_xua/doc/rst/opt_strings.rst
Normal file
@@ -0,0 +1,41 @@
|
||||
|
||||
Strings and ID's
|
||||
================
|
||||
|
||||
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`.
|
||||
|
||||
The Vendor ID (VID) should be acquired from the USB Implementers Forum (www.usb.org). Under no circumstances
|
||||
should the XMOS VID or any other VID be used without express permission.
|
||||
|
||||
The VID and Product ID (PID) pair must be unique to each product, otherwise driver incompatibilities may arise.
|
||||
|
||||
.. tabularcolumns:: lp{5cm}l
|
||||
|
||||
.. _opt_strings_defines:
|
||||
|
||||
.. list-table:: String & ID defines
|
||||
:header-rows: 1
|
||||
:widths: 20 80 20
|
||||
|
||||
* - Define
|
||||
- Description
|
||||
- Default
|
||||
* - ``VENDOR_STR``
|
||||
- Name of vendor/manufacturer, note the is appended to various strings.
|
||||
- ``"XMOS"``
|
||||
* - ``PRODUCT_STR_A2``
|
||||
- Name of the product when running in Audio Class 2.0 mode
|
||||
- ``"XMOS xCORE (UAC2.0)"``
|
||||
* - ``PRODUCT_STR_A1``
|
||||
- Name of the product when running in Audio Class 1.0 mode
|
||||
- ``"XMOS xCORE (UAC1.0)"``
|
||||
* - ``PID_AUDIO_2``
|
||||
- Product ID when running in Audio Class 2.0 mode
|
||||
- ``0x0002``
|
||||
* - ``PID_AUDIO_1``
|
||||
- Product ID when running in Audio Class 1.0 mode
|
||||
- ``0x0003``
|
||||
|
||||
|
||||
|
||||
96
lib_xua/doc/rst/opt_sync.rst
Normal file
96
lib_xua/doc/rst/opt_sync.rst
Normal file
@@ -0,0 +1,96 @@
|
||||
|
||||
|newpage|
|
||||
|
||||
Synchronisation & Clocking
|
||||
==========================
|
||||
|
||||
The codebase supports "Synchronous" and "Asynchronous" modes for USB transfer as defined by the
|
||||
USB specification(s).
|
||||
|
||||
Asynchronous mode (``XUA_SYNCMODE_ASYNC``) has the advantage that the device is clock-master. This means that
|
||||
a high-quality local master-clock source can be utilised. It also has the benefit that the device may
|
||||
synchronise it's master clock to an external digital input stream e.g. S/PDIF thus avoiding sample-rate
|
||||
conversion.
|
||||
|
||||
The drawback of this mode is that it burdens the host with syncing to the device which some hosts
|
||||
may not support. This is especially pertinent to embedded hosts, however, most PC's and mobile devices
|
||||
will indeed support this mode.
|
||||
|
||||
Synchronous mode (``XUA_SYNCMODE_SYNC``) is an option if the target host does not support asynchronous mode
|
||||
or if it is desirable to synchronise many devices to a single host. It should be noted, however, that input
|
||||
from digital streams, such as S/PDIF, are not currently supported in this mode.
|
||||
|
||||
.. note::
|
||||
|
||||
The selection of synchronisation mode is done at build time and cannot be changed dynamically.
|
||||
|
||||
Setting the synchronisation mode of the device is done using the define in :ref:`opt_sync_defines`
|
||||
|
||||
.. _opt_sync_defines:
|
||||
|
||||
.. list-table:: Sync Define
|
||||
:header-rows: 1
|
||||
:widths: 20 80 20
|
||||
|
||||
* - Define
|
||||
- Description
|
||||
- Default
|
||||
* - ``XUA_SYNCMODE``
|
||||
- USB synchronisation mode
|
||||
- ``XUA_SYNCMODE_ASYNC``
|
||||
|
||||
When operating in asynchronous mode xcore.ai based devices will be configured, by default, to use their internal
|
||||
"Applications" PLL to generated an appropriate master-clock signal. To disable this ``XUA_USE_APP_PLL`` should be
|
||||
set to ``0``. For all other devices the developer is expected to supply external master-clock generation circuitry.
|
||||
|
||||
When operating in synchronous mode an 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:
|
||||
|
||||
.. list-table:: Reference clock location
|
||||
:header-rows: 1
|
||||
:widths: 20 80 20
|
||||
|
||||
* - Define
|
||||
- Description
|
||||
- Default
|
||||
* - ``PLL_REF_TILE``
|
||||
- Tile location of reference to CS2100 device
|
||||
- ``AUDIO_IO_TILE``
|
||||
|
||||
The codebase expects this reference signal port to be defined in the application XN file as ``PORT_PLL_REF``.
|
||||
This may be a port of any bit-width, however, connection to bit[0] is assumed::
|
||||
|
||||
<Port Location="XS1_PORT_1A" Name="PORT_PLL_REF"/>
|
||||
|
||||
Configuration of the external CS2100 device (typically via I2C) is beyond the scope of this document.
|
||||
|
||||
Note, in all cases the master-clocks are generated (when using the xcore.ai Application PLL) or should be generated
|
||||
(if using external circuitry) to match the defines in :ref:`opt_sync_mclk_defines`.
|
||||
|
||||
.. _opt_sync_mclk_defines:
|
||||
|
||||
.. list-table:: Master clock frequencies
|
||||
:header-rows: 1
|
||||
:widths: 20 80 20
|
||||
|
||||
* - Define
|
||||
- Description
|
||||
- Default
|
||||
* - ``MCLK_48``
|
||||
- Master clock frequency (in Hz)used for sample-rates related to 48KHz
|
||||
- NOTE
|
||||
* - ``MCLK_441``
|
||||
- Master clock frequency (in Hz) used for sample-rates related to 44.1KHz
|
||||
- NONE
|
||||
|
||||
.. note::
|
||||
|
||||
The master clock defines above are critical for proper operation and default values are not provided.
|
||||
If they are not defined by the devloper a build error will be emmited.
|
||||
@@ -1,6 +1,5 @@
|
||||
USB Audio Solution Overview
|
||||
---------------------------
|
||||
|
||||
Overview
|
||||
********
|
||||
|
||||
.. table::
|
||||
:class: vertical-borders
|
||||
@@ -26,7 +25,7 @@ USB Audio Solution Overview
|
||||
| +---------------------------------------------------------------------------------------------+
|
||||
| | `USB Midi Device Class 1.0 <http://www.usb.org/developers/devclass_docs/midi10.pdf>`_ |
|
||||
+---------------------------------+---------------------------------------------------------------------------------------------+
|
||||
| Audio | I2S/TDM |
|
||||
| Audio | I2S/TDM (16/32-bit) |
|
||||
| +---------------------------------------------------------------------------------------------+
|
||||
| | S/PDIF |
|
||||
| +---------------------------------------------------------------------------------------------+
|
||||
@@ -48,19 +47,21 @@ USB Audio Solution Overview
|
||||
| **Supported Devices** |
|
||||
+-------------------------------------------------------------------------------------------------------------------------------+
|
||||
+---------------------------------+---------------------------------------------------------------------------------------------+
|
||||
| XMOS Devices | xCORE-200 Series |
|
||||
| XMOS Devices | xCORE-200 Series |
|
||||
| +---------------------------------------------------------------------------------------------+
|
||||
| | xCORE.AI Series |
|
||||
+---------------------------------+---------------------------------------------------------------------------------------------+
|
||||
+-------------------------------------------------------------------------------------------------------------------------------+
|
||||
| **Requirements** |
|
||||
+-------------------------------------------------------------------------------------------------------------------------------+
|
||||
+---------------------------------+---------------------------------------------------------------------------------------------+
|
||||
| Development Tools | xTIMEcomposer Development Tools v14 or later |
|
||||
| Development Tools | xTIMEcomposer Development Tools v15.1 or later |
|
||||
+---------------------------------+---------------------------------------------------------------------------------------------+
|
||||
| USB | xCORE-200 Series device with integrated USB Phy |
|
||||
| USB | xCORE device with integrated USB phy (external phy not supported) |
|
||||
+---------------------------------+---------------------------------------------------------------------------------------------+
|
||||
| Audio | External audio DAC/ADC/CODECs (and required supporting componentry) supporting I2S/TDM |
|
||||
| Audio | External audio DAC/ADC/CODECs (and required supporting componentry) supporting I2S/TDM |
|
||||
+---------------------------------+---------------------------------------------------------------------------------------------+
|
||||
| Boot/Storage | Compatible SPI Flash device (or xCORE-200 device with internal flash) |
|
||||
| Boot/Storage | Compatible SPI/QSPI Flash device (or xCORE device with internal flash) |
|
||||
+---------------------------------+---------------------------------------------------------------------------------------------+
|
||||
+-------------------------------------------------------------------------------------------------------------------------------+
|
||||
| **Licensing and Support** |
|
||||
@@ -73,5 +74,3 @@ USB Audio Solution Overview
|
||||
| Reference code is maintained by XMOS Limited. |
|
||||
+-------------------------------------------------------------------------------------------------------------------------------+
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,89 +1,21 @@
|
||||
|
||||
.. _usb_audio_sec_architecture:
|
||||
Implementation Detail
|
||||
*********************
|
||||
|
||||
USB Audio Software Overview
|
||||
---------------------------
|
||||
This chapter examines the implementation of the various components that make up ``lib_xua``. It also examines the integration of dependencies and supporting libraries.
|
||||
|
||||
This section describes the software architecture of a USB Audio device implemented using `lib_xua`, its dependencies and other supporting libraries.
|
||||
|
||||
`lib_xua` provides fundamental building blocks for producing USB Audio products on XMOS devices. Every system is required to have the components from `lib_xua` listed in :ref:`usb_audio_shared_components`.
|
||||
|
||||
.. _usb_audio_shared_components:
|
||||
|
||||
.. list-table:: Required XUA Components
|
||||
:header-rows: 1
|
||||
:widths: 40 60
|
||||
|
||||
* - Component
|
||||
- Description
|
||||
* - Endpoint 0
|
||||
- Provides the logic for Endpoint 0 which handles
|
||||
enumeration and control of the device including DFU related requests.
|
||||
* - Endpoint buffer
|
||||
- Buffers endpoint data packets to and from the host. Manages delivery of audio packets between the endpoint buffer
|
||||
component and the audio components. It can also handle volume control processing.Note, this currently utlises two cores
|
||||
* - AudioHub
|
||||
- Handles audio I/O over I2S and manages audio data
|
||||
to/from other digital audio I/O components.
|
||||
|
||||
In addition low-level USB I/0 is required and is provided by the external dependency `lib_xud`
|
||||
|
||||
.. list-table:: Additional Components Required
|
||||
:header-rows: 1
|
||||
:widths: 100 60
|
||||
|
||||
* - Component
|
||||
- Description
|
||||
* - XMOS USB Device Driver (XUD)
|
||||
- Handles the low level USB I/O.
|
||||
|
||||
In addition :ref:`usb_audio_optional_components` shows optional components that can be added/enabled from within `lib_xua`
|
||||
|
||||
.. _usb_audio_optional_components:
|
||||
|
||||
.. list-table:: Optional Components
|
||||
:header-rows: 1
|
||||
:widths: 40 60
|
||||
|
||||
* - Component
|
||||
- Description
|
||||
* - Mixer
|
||||
- Allows digital mixing of input and output channels. It can also
|
||||
handle volume control instead of the decoupler.
|
||||
* - Clockgen
|
||||
- Drives an external frequency generator (PLL) and manages
|
||||
changes between internal clocks and external clocks arising
|
||||
from digital input.
|
||||
* - MIDI
|
||||
- Outputs and inputs MIDI over a serial UART interface.
|
||||
|
||||
`lib_xua` also provides optional support for integrating with the following eternal dependencies:
|
||||
|
||||
.. list-table:: Optional Components
|
||||
:header-rows: 1
|
||||
:widths: 40 60
|
||||
|
||||
* - Component
|
||||
- Description
|
||||
* - S/PDIF Transmitter (lib_spdif)
|
||||
- Outputs samples of an S/PDIF digital audio interface.
|
||||
* - S/PDIF Receiver (lib_spdif)
|
||||
- Inputs samples of an S/PDIF digital audio interface (requires the
|
||||
clockgen component).
|
||||
* - ADAT Receiver (lib_adat)
|
||||
- Inputs samples of an ADAT digital audio interface (requires the
|
||||
clockgen component).
|
||||
* - PDM Microphones (lib_mic_array)
|
||||
- Receives PDM data from microphones and performs PDM to PCM conversion
|
||||
|
||||
.. _usb_audio_threads:
|
||||
|
||||
.. figure:: images/threads-crop.*
|
||||
:width: 100%
|
||||
|
||||
USB Audio Core Diagram
|
||||
|
||||
:ref:`usb_audio_threads` shows how the components interact with each
|
||||
other in a typical system. The green circles represent cores with arrows indicating inter-core communications.
|
||||
.. toctree::
|
||||
|
||||
sw_audio
|
||||
sw_ep0
|
||||
sw_xud
|
||||
sw_clocking
|
||||
sw_mixer
|
||||
sw_spdif
|
||||
sw_spdif_rx
|
||||
sw_adat_rx
|
||||
sw_midi
|
||||
sw_pdm
|
||||
sw_hid
|
||||
sw_resource
|
||||
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
ADAT Receive
|
||||
------------
|
||||
|
||||
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
|
||||
described in :ref:`usb_audio_sec_component_api`.
|
||||
|
||||
The component outputs 32 bits words split into nine word frames. The
|
||||
frames are laid out in the following manner:
|
||||
|
||||
* Control byte
|
||||
* Channel 0 sample
|
||||
* Channel 1 sample
|
||||
* Channel 2 sample
|
||||
* Channel 3 sample
|
||||
* Channel 4 sample
|
||||
* Channel 5 sample
|
||||
* Channel 6 sample
|
||||
* Channel 7 sample
|
||||
|
||||
Example of code show how to read the output of the ADAT component is shown below::
|
||||
|
||||
control = inuint(oChan);
|
||||
|
||||
for(int i = 0; i < 8; i++)
|
||||
{
|
||||
sample[i] = inuint(oChan);
|
||||
}
|
||||
|
||||
Samples are 24-bit values contained in the lower 24 bits of the word.
|
||||
|
||||
The control word comprises four control bits in bits [11..8] and the value 0b00000001 in bits [7..0].
|
||||
This control word enables synchronization at a higher level, in that on the channel a single odd
|
||||
word is always read followed by eight words of data.
|
||||
|
||||
.. Timing Requirements
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. The data samples are outputted onto the channel every 2.4 us. The
|
||||
.. control sample follows 1.7 us after the last data sample, and is
|
||||
.. followed 2.4 us later by the first data sample. Given that a channel
|
||||
.. can hold two words of data, when data appears on the channel, it
|
||||
.. should be input within 4.1 us otherwise the ADAT receiver will block,
|
||||
.. and data will be lost. Between data samples a window of 4.8 us is
|
||||
.. available.
|
||||
|
||||
Integration
|
||||
~~~~~~~~~~~
|
||||
|
||||
Since the ADAT is a digital stream the devices master clock must synchronised to it. This is
|
||||
typically achieved with an external fractional-n clock multiplier.
|
||||
|
||||
The ADAT receive function communicates with the clockGen component which passes audio data onto the
|
||||
audio driver and handles locking to the ADAT clock source if required.
|
||||
54
lib_xua/doc/rst/sw_adat_rx.rst
Normal file
54
lib_xua/doc/rst/sw_adat_rx.rst
Normal file
@@ -0,0 +1,54 @@
|
||||
|newpage|
|
||||
|
||||
ADAT Receive
|
||||
============
|
||||
|
||||
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
|
||||
described in :ref:`usb_audio_sec_component_api`.
|
||||
|
||||
The component outputs 32 bits words split into nine word frames. The
|
||||
frames are laid out in the following manner:
|
||||
|
||||
* Control byte
|
||||
* Channel 0 sample
|
||||
* Channel 1 sample
|
||||
* Channel 2 sample
|
||||
* Channel 3 sample
|
||||
* Channel 4 sample
|
||||
* Channel 5 sample
|
||||
* Channel 6 sample
|
||||
* Channel 7 sample
|
||||
|
||||
An example of how to read the output of the ADAT component is shown below::
|
||||
|
||||
control = inuint(oChan);
|
||||
|
||||
for(int i = 0; i < 8; i++)
|
||||
{
|
||||
sample[i] = inuint(oChan);
|
||||
}
|
||||
|
||||
Samples are 24-bit values contained in the lower 24 bits of the word.
|
||||
|
||||
The control word comprises four control bits in bits [11..8] and the value 0b00000001 in bits [7..0].
|
||||
This control word enables synchronization at a higher level, in that on the channel a single odd
|
||||
word is always read followed by eight words of data.
|
||||
|
||||
|
||||
Usage and Integration
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Since the ADAT is a digital stream the device's master clock must synchronised to it. The integration
|
||||
of ADAT receive is much the same as S/PDIF receive in that the ADAT receive function communicates
|
||||
with the Clock Gen core. This Clock Gen Core then passes audio data onto the Audio Hub core.
|
||||
It also handles locking to the ADAT clock source.
|
||||
|
||||
There are some small differences with the S/PDIF integration accounting for the fact that ADAT
|
||||
typically has 8 channels compared to S/DIF's two.
|
||||
|
||||
The Clock Gen core also handles SMUX II (e.g. 4 channels at 96kHz) and SMUX IV (e.g. 2 channels at
|
||||
192kHz), populating the sample FIFO as appropriate. SMUX modes are communicated to the Clock Gen
|
||||
core from Endpoint 0 via the ``c_clk_ctl`` channel. SMUX modes are exposed to the USB host using
|
||||
Alternative Interfaces, with appropriate channel counts, for the streaming input Endpoint.
|
||||
|
||||
@@ -1,26 +1,32 @@
|
||||
|newpage|
|
||||
|
||||
.. _usb_audio_sec_audio:
|
||||
|
||||
AudioHub/I2S
|
||||
............
|
||||
Audio Hub
|
||||
=========
|
||||
|
||||
The AudioHub task performs many functions. It receives and transmits samples from/to the decoupler or mixer core over an XC channel.
|
||||
The Audio Hub task performs many functions. It receives and transmits samples from/to the Decoupler
|
||||
or Mixer core over a channel.
|
||||
|
||||
It also drives several in and out I2S/TDM channels to/from a CODEC, DAC, ADC etc - from now on termed "audio hardware".
|
||||
It also drives several in and out I2S/TDM channels to/from a CODEC, DAC, ADC etc. From now on these
|
||||
external devices will be termed "audio hardware".
|
||||
|
||||
If the firmware is configured with the xCORE as I2S master the requred clock lines will also be driven out from this task also.
|
||||
If the firmware is configured with the xCORE as I2S master the required clock lines will also be
|
||||
driven from this task. It also has the task of forwarding on and receiving samples to/from other
|
||||
audio related tasks/cores such as S/PDIF tasks, ADAT etc.
|
||||
|
||||
It also has the task of formwarding on and reciving samples to/from other audio related tasks such as S/PDIF tasks, ADAT tasks etc.
|
||||
In master mode, the xCORE generates the I2S "Continuous Serial Clock (SCK)", or "Bit-Clock (BCLK)"
|
||||
and the "Word Select (WS)" or "left-right clock (LRCLK)" signals. Any CODEC or DAC/ADC combination
|
||||
that supports I2S and can be used.
|
||||
|
||||
The AudioHub task must be connected to external audio hardware that supports I2S (other modes such as "left justified" can be supported with firmware changes).
|
||||
The LR-clock, bit-clock and data are all derived from the incoming master clock (typically the
|
||||
output of the external oscillator or PLL). This is not part of the I2S standard but is commonly
|
||||
included for synchronizing the internal operation of the analog/digital converters.
|
||||
|
||||
In master mode, the XMOS device acts as the master generating the I2S "Continous Serial Clock (SCK)" typically called the Bit-Clock (BCLK) and the "Word Select (WS)" line typically called left-right clock (LRCLK) signals. Any CODEC or DAC/ADC combination that supports I2S and can be used.
|
||||
The Audio Hub task is implemented in the file ``xua_audiohub.xc``.
|
||||
|
||||
The LR-clock, bit-clock and data are all derived from the incoming master clock (typically the output of the external oscillator or PLL)
|
||||
- This is not part of the I2S standard but is commonly included for synchronizing the internal operation of the analog/digital converters.
|
||||
|
||||
The AudioHub task is implemented in the file ``xua_audiohub.xc``.
|
||||
|
||||
:ref:`usb_audio_codec_signals` shows the signals used to communicate audio between the XMOS device and the external audio hardware.
|
||||
:ref:`usb_audio_codec_signals` shows the signals used to communicate audio between the XMOS device
|
||||
and the external audio hardware.
|
||||
|
||||
.. _usb_audio_codec_signals:
|
||||
|
||||
@@ -83,13 +89,15 @@ with BCLK then being used to clock data in (SDIN) and data out (SDOUT) of the ex
|
||||
- 12.288
|
||||
- 2
|
||||
|
||||
The master clock must be supplied by an external source e.g. clock generator, fixed oscillators, PLL etc to generate the two frequencies to support
|
||||
44.1kHz and 48kHz audio frequencies (e.g. 11.2896/22.5792MHz and 12.288/24.576MHzrespectively). This master clock input is then provided to the
|
||||
external audio hardware and the xCORE device.
|
||||
For xCORE-200 devices the master clock must be supplied by an external source e.g. clock generator,
|
||||
fixed oscillators, PLL etc. xCORE.ai devices may use the integrated secondary PLL.
|
||||
|
||||
Two master clock frequencies to support 44.1kHz and 48kHz audio frequencies (e.g. 11.2896/22.5792MHz
|
||||
and 12.288/24.576MHz respectively). This master clock input is then provided to the external audio
|
||||
hardware and the xCORE device.
|
||||
|
||||
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
|
||||
|
||||
@@ -122,41 +130,19 @@ The preceding diagram shows the connectivity of ports and clock blocks.
|
||||
input in one input statement. This allows the software to input, process and output 32-bit words, whilst the ports serialize and
|
||||
deserialize to the single I/O pin connected to each port.
|
||||
|
||||
xCORE-200 series devices have the ability to divide an extenal clock in a clock-block.
|
||||
Unlike previous xCORE architectures, xCORE-200 (XS2) and xCORE.ai (XS3) series devices have the ability to divide an external clock in a clock-block.
|
||||
|
||||
However, XS1 based devices do not have this functionality. In order achieve the reqired master-clock
|
||||
to bit-clock/LR-clock divicd on XS1 devices, buffered ports with a transfer width of 32 are also
|
||||
used for ``p_bclk`` and ``p_lrclk``. The bit clock is generated by performing outputs of a particular pattern to ``p_bclk`` to toggle
|
||||
the output at the desired rate. The pattern depends on the divide between the master-clock and bit-clock.
|
||||
The following table shows the required pattern for different values of this divide:
|
||||
|
||||
.. list-table:: Output patterns
|
||||
:header-rows: 1
|
||||
|
||||
* - Divide
|
||||
- Output pattern
|
||||
- Outputs per sample
|
||||
* - 2
|
||||
- ``0xAAAAAAAA``
|
||||
- 2
|
||||
* - 4
|
||||
- ``0xCCCCCCCC``
|
||||
- 4
|
||||
* - 8
|
||||
- ``0xF0F0F0F0``
|
||||
- 8
|
||||
|
||||
In any case, the bit clock outputs 32 clock cycles per sample. In the special case where the divide is 1 (i.e. the bit clock frequency equals
|
||||
The bit clock outputs 32 clock cycles per sample. In the special case where the divide is 1 (i.e. the bit clock frequency equals
|
||||
the master clock frequency), the ``p_bclk`` port is set to a special mode where it simply outputs its clock input (i.e. ``p_mclk``).
|
||||
See ``configure_port_clock_output()`` in ``xs1.h`` for details.
|
||||
|
||||
``p_lrclk`` is clocked by ``p_bclk``. In I2S mode the port outputs the pattern ``0x7fffffff``
|
||||
followed by ``0x80000000`` repeatedly. This gives a signal that has a transition one bit-clock
|
||||
before the data (as required by the I2S standard) and alternates between high and low for the
|
||||
left and right channels of audio.
|
||||
before the data (as required by the I2S standard) and alternates between high and low for the left
|
||||
and right channels of audio.
|
||||
|
||||
Changing Audio Sample Frequency
|
||||
+++++++++++++++++++++++++++++++
|
||||
-------------------------------
|
||||
|
||||
.. _usb_audio_sec_chang-audio-sample:
|
||||
|
||||
@@ -170,7 +156,5 @@ Upon receiving the change of sample frequency request, the audio
|
||||
core stops the I2S/TDM interface and calls the CODEC/port configuration
|
||||
functions.
|
||||
|
||||
Once this is complete, the I2S/TDM interface (i.e. the main look 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.
|
||||
|
||||
|
||||
@@ -1,35 +1,60 @@
|
||||
|
||||
|newpage|
|
||||
|
||||
.. _usb_audio_sec_clock_recovery:
|
||||
|
||||
External Clock Recovery (ClockGen)
|
||||
----------------------------------
|
||||
External Clock Recovery (Clock Gen)
|
||||
===================================
|
||||
|
||||
An application can either provide fixed master clock sources via selectable oscillators, clock
|
||||
generation IC, etc, to provide the audio master or use an external PLL/Clock Multiplier to
|
||||
generate a master clock based on reference from the XMOS device.
|
||||
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
|
||||
master clock frequencies.
|
||||
|
||||
Using an external PLL/Clock Multiplier allows the design to lock to an external clock source
|
||||
from a digital stream (e.g. S/PDIF or ADAT input).
|
||||
It may also use an external PLL/Clock Multiplier to generate a master clock based on a reference from
|
||||
the xCORE.
|
||||
|
||||
The clock recovery core (clockGen) is responsible for generating the reference frequency
|
||||
to the Fractional-N Clock Generator. This, in turn, generates the master clock used over the
|
||||
whole design.
|
||||
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 codebase supports the Cirrus
|
||||
Logic CS2100 device for this purpose. Other devices may be supported via code modification.
|
||||
|
||||
.. note::
|
||||
|
||||
It is expected that in a future release the secondary PLL in xCORE.ai devices, coupled with
|
||||
associated software changes, will be capable of replacing the CS2100 part for most designs.
|
||||
|
||||
The Clock Recovery core (Clock Gen) is responsible for generating the reference frequency
|
||||
to the CS2100 device. This, in turn, generates the master clock used over the whole design.
|
||||
This core also serves as a smaller buffer between ADAT and S/PDIF receiving cores and the Audio Hub
|
||||
core.
|
||||
|
||||
When running in *Internal Clock* mode this core simply generates this clock using a local
|
||||
timer, based on the XMOS reference clock.
|
||||
|
||||
When running in an external clock mode (i.e. S/PDIF Clock" or "ADAT Clock" mode) digital
|
||||
samples are received from the S/PDIF and/or ADAT receive core.
|
||||
When running in an external clock mode (i.e. S/PDIF Clock" or "ADAT Clock" mode) samples are
|
||||
received from the S/PDIF and/or ADAT receive core. The external frequency is calculated through
|
||||
counting samples in a given period. The reference clock to the CS2100 is then generated based on
|
||||
the reception of these samples.
|
||||
|
||||
The external frequency is calculated through counting samples in a given period. The
|
||||
reference clock to the Fractional-N Clock Multiplier is then generated based on this
|
||||
external stream. If this stream becomes invalid, the timer event will fire to ensure that
|
||||
valid master clock generation continues regardless of cable unplugs etc.
|
||||
If an external stream becomes invalid, the *Internal Clock* timer event will fire to ensure that
|
||||
valid master clock generation continues regardless of cable unplugs etc. Efforts are made to
|
||||
ensure the transition between these clocks are relatively seamless. Additionally efforts are also
|
||||
made to try and keep the jitter on the reference clock as low as possibly, regardless of activity
|
||||
level of the Clock Gen core. The is achieved though the use of port times to schedule pin toggling
|
||||
rather than directly outputting to the port.
|
||||
|
||||
This core gets clock selection Get/Set commands from Endpoint 0 via the ``c_clk_ctl``
|
||||
The Clock Gen core gets clock selection Get/Set commands from Endpoint 0 via the ``c_clk_ctl``
|
||||
channel. This core also records the validity of external clocks, which is also queried
|
||||
through the same channel from Endpoint 0.
|
||||
through the same channel from Endpoint 0. Note, the *Internal Clock* is always reported as being
|
||||
valid. It should be noted that the device always reports the current device sample rate regardless
|
||||
of the clock being interrogated. This results in improved user experience for most driver/operating
|
||||
system combinations
|
||||
|
||||
To inform the host of any status change, the Clock Gen core can also cause the Decouple core to
|
||||
request an interrupt packet on change of clock validity. This functionality is based on the Audio
|
||||
Class 2.0 status/interrupt endpoint feature.
|
||||
|
||||
This core also can cause the decouple core to request an interrupt packet on change of
|
||||
clock validity. This functionality is based on the Audio Class 2.0 status/interrupt endpoint
|
||||
feature.
|
||||
.. note::
|
||||
|
||||
When running in Synchronous mode external digital input streams are currently not supported.
|
||||
Such a feature would require sample-rate conversion to covert from the S/PDIF or ADAT clock
|
||||
domain to the USB host clock domain. As such this core is not used in a Synchronous mode device.
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
Implementation Detail
|
||||
---------------------
|
||||
|
||||
This section describes the software architecture of a USB Audio device implemented using `lib_xua`, it's dependancies and other supporting libraries.
|
||||
|
||||
This section will now examine the operation of these components in further detail.
|
||||
|
||||
.. toctree::
|
||||
|
||||
sw_audio
|
||||
sw_spdif
|
||||
|
||||
|
||||
..
|
||||
sw_xud
|
||||
sw_ep0
|
||||
sw_audio
|
||||
sw_mixer
|
||||
sw_spdif_rx
|
||||
sw_adat
|
||||
sw_clocking
|
||||
sw_midi
|
||||
sw_pdm
|
||||
sw_resource
|
||||
..
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
.. _usb_audio_sec_usb:
|
||||
|
||||
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.
|
||||
|
||||
These tasks can be generally split into enumeration, audio configuration and firmware upgrade requests.
|
||||
|
||||
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.
|
||||
|
||||
@@ -19,7 +19,7 @@ During the enumeration process the host will issue various commands to the devic
|
||||
The endpoint 0 code runs in its own core and follows a similar format to that of the USB Device examples in `lib_xud` (i.e. Example HID Mouse Demo). That is, a call is made to ``USB_GetSetupPacket()`` to receive a command from the host. This populates a ``USB_SetupPacket_t`` structure, which is then parsed.
|
||||
|
||||
There are many mandatory requests that a USB Device must support as required by the USB Specification. Since these are required for all devices in order to function a
|
||||
``USB_StandardRequests()`` function is provided (see ``module_usb_device``) which implements all of these requests. This includes the following items:
|
||||
``USB_StandardRequests()`` function is provided (see ``xud_device.xc``) which implements all of these requests. This includes the following items:
|
||||
|
||||
- Requests for standard descriptors (Device descriptor, configuration descriptor etc) and string descriptors
|
||||
- USB GET/SET INTERFACE requests
|
||||
@@ -28,8 +28,8 @@ There are many mandatory requests that a USB Device must support as required by
|
||||
|
||||
For more information and full documentation, including full worked examples of simple devices, please refer to `lib_xud`.
|
||||
|
||||
The ``USB_StandardRequests()`` function takes the devices various descriptors as parameters, these are passed from data structures found in the ``descriptors.h`` file.
|
||||
These data structures are fully customised based on the how the design is configured using various defines (see :ref:`sec_custom_defines_api`).
|
||||
The ``USB_StandardRequests()`` function takes the devices various descriptors as parameters, these are passed from data structures found in the ``xud_ep0_descriptors.h`` file.
|
||||
These data structures are fully customised based on the how the design is configured using various defines.
|
||||
|
||||
The ``USB_StandardRequests()`` functions returns a ``XUD_Result_t``. ``XUD_RESULT_OKAY`` indicates that the request was fully handled without error and no further action is required
|
||||
- The device should move to receiving the next request from the host (via ``USB_GetSetupPacket()``).
|
||||
@@ -38,41 +38,42 @@ The function returns ``XUD_RES_ERR`` if the request was not recognised by the ``
|
||||
|
||||
The function may also return ``XUD_RES_RST`` if a bus-reset has been issued onto the bus by the host and communicated from XUD to Endpoint 0.
|
||||
|
||||
Since the ``USB_StandardRequests()`` function STALLs an unknown request, the endpoint 0 code must parse the ``USB_SetupPacket_t`` structure to handle device specific requests and then calling ``USB_StandardRequests()`` as required. This is described next.
|
||||
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
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
-----------------------------
|
||||
|
||||
The USB Audio design "over-rides" some of the requests handled by ``USB_StandardRequests()``, for example it uses the SET_INTERFACE request to indicate it 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 called to handle the response to the host etc.
|
||||
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
|
||||
~~~~~~~~~~~~~~
|
||||
Before making the call to ``USB_StandardRequests()`` the setup packet is parsed for Class requests. These are handled in functions such as ``AudioClasRequests_2()``, ``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.
|
||||
|
||||
Some of the common Audio Class requests and their associated behaviour will now be examined.
|
||||
|
||||
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).
|
||||
|
||||
Note, Audio Class 1.0 Sample rate changes are send to the relevant endpoint, rather than the interface - this is handled as a special case in he endpoint 0 request parsing where ``AudioEndpointRequests_1()`` is called.
|
||||
|
||||
The ``AudioClassRequests_X()`` functions parses the request further 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
|
||||
++++++++++++++++++++++++++++++
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The ``AudioClassRequests_2()`` function parses the passed ``USB_SetupPacket_t`` structure for a ``CUR`` request of type ``SAM_FREQ_CNTROL`` 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).
|
||||
|
||||
The new sample frequency is extracted and passed via channel to the rest of the design - through the buffering code and eventually to the Audio IO/I2S core. The ``AudioClassRequests_2()`` function waits for a handshake to propagate back though the system before signalling to the host that the request has completed successfully. Note, during this time the USB library is NAKing the host essentially holding off further traffic/requests until the sample-rate change is fully complete.
|
||||
The new sample frequency is extracted and passed via channel to the rest of the design - through the buffering code and eventually to the Audio Hub (I2S) core. The ``AudioClassRequests_2()`` function waits for a handshake to propagate back through the system before signalling to the host that the request has completed successfully. Note, during this time the USB library is NAKing the host essentially holding off further traffic/requests until the sample-rate change is fully complete.
|
||||
|
||||
.. _usb_audio_sec_audio-requ-volume:
|
||||
|
||||
Audio Request: Volume Control
|
||||
+++++++++++++++++++++++++++++
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
When the host requests a volume change, it
|
||||
sends an audio interface request to Endpoint 0. An array is
|
||||
@@ -83,7 +84,7 @@ When changing the volume, Endpoint 0 applies the master volume and
|
||||
channel volume, producing a single volume value for each channel.
|
||||
These are stored in the array.
|
||||
|
||||
The volume will either be handled by the ``decoupler`` core or the mixer
|
||||
The volume will either be handled by the ``decouple`` core or the mixer
|
||||
component (if the mixer component is used). Handling the volume in the
|
||||
mixer gives the decoupler more performance to handle more channels.
|
||||
|
||||
@@ -97,34 +98,35 @@ the array (ordering between writes and reads is unimportant in this
|
||||
case). Inline assembly is used by the decoupler core to access
|
||||
the array, avoiding the parallel usage checks of XC.
|
||||
|
||||
If volume control is implemented in the mixer, Endpoint 0 sends a mixer command to the mixer to change the volume. Mixer commands
|
||||
If volume control is implemented in the mixer, Endpoint 0 sends a mixer command
|
||||
to the mixer to change the volume. Mixer commands
|
||||
are described in :ref:`usb_audio_sec_mixer`.
|
||||
|
||||
Audio Endpoints (Endpoint Buffer and Decoupler)
|
||||
...............................................
|
||||
===============================================
|
||||
|
||||
Endpoint Buffer
|
||||
~~~~~~~~~~~~~~~
|
||||
---------------
|
||||
|
||||
All endpoints other that Endpoint 0 are handled in one core. This
|
||||
core is implemented in the file ``usb_buffer.xc``. This core is communicates directly with the XUD library.
|
||||
core is implemented in the file ``ep_buffer.xc``. This core communicates directly with the XUD library.
|
||||
|
||||
The USB buffer core is also responsible for feedback calculation based on USB Start Of Frame
|
||||
(SOF) notification and reads from the port counter of a port connected to the master clock.
|
||||
|
||||
Decoupler
|
||||
~~~~~~~~~
|
||||
Decouple
|
||||
--------
|
||||
|
||||
The decoupler supplies the USB buffering core with buffers to
|
||||
transmit/receive audio data to/from the host. It marshals these buffers into
|
||||
FIFOs. The data from the FIFOs are then sent over XC channels to
|
||||
other parts of the system as they need it. This core also
|
||||
other parts of the system as they need it. In asynchronous mode this core also
|
||||
determines the size of each packet of audio sent to the host (thus
|
||||
matching the audio rate to the USB packet rate). The decoupler is
|
||||
implemented in the file ``decouple.xc``.
|
||||
|
||||
Audio Buffering Scheme
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
----------------------
|
||||
|
||||
This scheme is executed by co-operation between the buffering
|
||||
core, the decouple core and the XUD library.
|
||||
@@ -132,76 +134,69 @@ core, the decouple core and the XUD library.
|
||||
For data going from the device to the host the following scheme is
|
||||
used:
|
||||
|
||||
|
||||
#. The decouple core receives samples from the audio 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
|
||||
entered into it. Packets are stored in a format consisting of their
|
||||
length in bytes followed by the data.
|
||||
|
||||
#. When the buffer cores needs a buffer to send to the XUD core
|
||||
(after sending the previous buffer), the decouple core is
|
||||
#. When the Endpoint Buffer core needs a buffer to send to the XUD core
|
||||
(after sending the previous buffer), the Decouple core is
|
||||
signalled (via a shared memory flag).
|
||||
|
||||
#. Upon this signal from the buffering core, the decouple core
|
||||
passes the next packet from the FIFO to the buffer core. It also
|
||||
signals to the XUD library that the buffer core is able to send a
|
||||
#. Upon this signal from the Endpoint Buffer core, the Decouple core
|
||||
passes the next packet from the FIFO to the Endpoint Buffer core. It also
|
||||
signals to the XUD library that the Endpoint Buffer core is able to send a
|
||||
packet.
|
||||
|
||||
#. When the buffer core has sent this buffer, it signals to the
|
||||
decouple that the buffer has been sent and the decouple core
|
||||
#. When the Endpoint Buffer core has sent this buffer, it signals to the
|
||||
Decouple core that the buffer has been sent and the Decouple core
|
||||
moves the read pointer of the FIFO.
|
||||
|
||||
|
||||
For data going from the host to the device the following scheme is
|
||||
used:
|
||||
|
||||
|
||||
#. The decouple core passes a pointer to the buffering 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
|
||||
the buffering core is ready to receive.
|
||||
the Endpoint Buffer core is ready to receive.
|
||||
|
||||
#. The buffering core then reads a USB packet into the FIFO and
|
||||
signals to the decoupler that the packet has been read.
|
||||
#. The Endpoint Buffer core then reads a USB packet into the FIFO and
|
||||
signals to the Decouple core that the packet has been read.
|
||||
|
||||
#. Upon receiving this signal the decoupler core updates the
|
||||
#. Upon receiving this signal the Decouple core updates the
|
||||
write pointer of the FIFO and provides a new pointer to the
|
||||
buffering core to fill.
|
||||
|
||||
#. Upon request from the audio core, the decoupler core sends
|
||||
samples to the audio core by reading samples out of the FIFO.
|
||||
Endpoint Buffer core to fill.
|
||||
|
||||
#. Upon request from the Audio Hub core, the Decouple core sends
|
||||
samples to the Audio Hub core by reading samples out of the FIFO.
|
||||
|
||||
Decoupler/Audio Core interaction
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
--------------------------------
|
||||
|
||||
To meet timing requirements of the audio system, 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
|
||||
send/receive samples immediately. An interrupt handler
|
||||
is set up in the decoupler core to do this. The interrupt handler
|
||||
is implemented in the function ``handle_audio_request``.
|
||||
|
||||
The audio system sends a word over a channel to the decouple core to
|
||||
request sample transfer (using the build in outuint function).
|
||||
request sample transfer (using the build in ``outuint()`` function).
|
||||
The receipt of this word in the channel
|
||||
causes the ``handle_audio_request`` interrupt to fire.
|
||||
|
||||
The first operation the interrupt handler does is to send back a word
|
||||
acknowledging the request (if there was a change of sample frequency
|
||||
The first operation the interrupt handler does (once it inputs the word that triggered the interrupt)
|
||||
is to send back a word acknowledging the request (if there was a change of sample frequency
|
||||
a control token would instead be sent---the audio system uses a testct()
|
||||
to inspect for this case).
|
||||
|
||||
Sample transfer may now take place. First the audio subsystem transfers
|
||||
samples destined for the host, then the decouple core sends
|
||||
samples from the host to device. These transfers always take place
|
||||
Sample transfer may now take place. First the Decouple core sends samples from host to device then the
|
||||
audio subsystem transfers samples destined for the host. These transfers always take place
|
||||
in channel count sized chunks (i.e. ``NUM_USB_CHAN_OUT`` and
|
||||
``NUM_USB_CHAN_IN``). That is, if the device has 10 output channels and
|
||||
8 input channels, 10 samples are sent from the decouple core and 8 received
|
||||
every interrupt.
|
||||
``NUM_USB_CHAN_IN``). That is, if the device has 10 output channels and 8 input channels,
|
||||
10 samples are sent from the decouple core and 8 received every interrupt.
|
||||
|
||||
The complete communication scheme is shown in the table below (for non sample
|
||||
frequency change case):
|
||||
|
||||
|
||||
.. table:: Decouple/Audio System Channel Communication
|
||||
|
||||
+-----------------+-----------------+-----------------------------------------+
|
||||
@@ -237,55 +232,62 @@ frequency change case):
|
||||
+-----------------+-----------------+-----------------------------------------+
|
||||
|
||||
.. note::
|
||||
The request and acknowledgement sent to/from Decouple to the Audio System is an "output underflow" sample
|
||||
The request and acknowledgement sent to/from the Decouple core to the Audio System is an "output underflow" sample
|
||||
value. If in PCM mode it will be 0, in DSD mode it will be DSD silence.
|
||||
This allows the buffering system to output a suitable underflow value without knowing the format of the stream
|
||||
(this is especially advantageous in the DSD over PCM (DoP) case)
|
||||
|
||||
Asynchronous Feedback
|
||||
+++++++++++++++++++++
|
||||
---------------------
|
||||
|
||||
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
|
||||
the *USB 2.0 Specification*.
|
||||
the *USB 2.0 Specification*. This calculated feedback value is also used to size packets to the host.
|
||||
|
||||
This asynchronous clocking scheme means that the device is the clocking master than therefore
|
||||
means a high-quality local master clock source can be used.
|
||||
This asynchronous clocking scheme means that the device is the clock master and therefore
|
||||
a high-quality local master clock or a digital input stream can be used as the clock source.
|
||||
|
||||
After each received USB SOF token, the buffering core takes a time-stamp from a port clocked off
|
||||
After each received USB Start Of Frame (SOF) token, the buffering core takes a time-stamp from a port clocked off
|
||||
the master clock. By subtracting the time-stamp taken at the previous SOF, the number of master
|
||||
clock ticks since the last SOF is calculated. From this the number of samples (as a fixed
|
||||
point number) between SOFs can be calculated.
|
||||
This count is aggregated over 128 SOFs and used as a basis for the feedback value.
|
||||
point number) between SOFs can be calculated. This count is aggregated over 128 SOFs and used as a
|
||||
basis for the feedback value.
|
||||
|
||||
The sending of feedback to the host is also handled in the USB buffering core via an explicit feedback
|
||||
IN endpoint. If both input and output is enabled then the feedback is implicit based on the audio stream
|
||||
sent to the host.
|
||||
The sending of feedback to the host is also handled in the Endpoint Buffer core via an explicit
|
||||
feedback IN endpoint.
|
||||
|
||||
If both input and output is enabled then the feedback can be implicit based on the audio stream
|
||||
sent to the host. In practice this an explicit feedback endpoint is normally used due to restrictions
|
||||
in Microsoft Windows operating systems (see ``UAC_FORCE_FEEDBACK_EP``).
|
||||
|
||||
USB Rate Control
|
||||
++++++++++++++++
|
||||
----------------
|
||||
|
||||
.. _usb_audio_sec_usb-rate-control:
|
||||
|
||||
The Audio core must consume data from USB
|
||||
and provide data to USB at the correct rate for the selected sample
|
||||
frequency. The *USB 2.0 Specification* states that the maximum
|
||||
variation on USB packets can be +/- 1 sample per USB frame. USB
|
||||
frames are sent at 8kHz, so on average for 48kHz each packet
|
||||
contains six samples per channel. The device uses Asynchronous mode,
|
||||
so the audio clock may drift and run faster or slower than the
|
||||
host. Hence, if the audio clock is slightly fast, the device may
|
||||
occasionally input/output seven samples rather than six. Alternatively,
|
||||
it may be slightly slow and input/output five samples rather than six.
|
||||
:ref:`usb_audio_samples_per_packet` shows the allowed number of samples
|
||||
per packet for each example audio frequency.
|
||||
The device must consume data from USB host and provide data to USB host at the correct rate for the
|
||||
selected sample frequency. When running in asynchronous mode the *USB 2.0 Specification* states
|
||||
that the maximum variation on USB packets can be +/- 1 sample per USB frame (Synchronous mode
|
||||
mandates no variation other than that required to match a sample rate that doesn't cleanly divide
|
||||
the USB SOF period e.g. 44.1kHz)
|
||||
|
||||
See USB Device Class Definition for Audio Data Formats v2.0 section 2.3.1.1
|
||||
for full details.
|
||||
High-speed USB frames are sent at 8kHz, so on average for 48kHz each packet contains six samples
|
||||
per channel.
|
||||
|
||||
When running in Asynchronous mode, so the audio clock may drift and run faster or slower than the
|
||||
host. Hence, if the audio clock is slightly fast, the device may occasionally input/output seven
|
||||
samples rather than six. Alternatively, it may be slightly slow and input/output five samples rather
|
||||
than six. :ref:`usb_audio_samples_per_packet` shows the allowed number of samples per packet for
|
||||
each example audio frequency in Asynchronous mode.
|
||||
|
||||
When running in Synchronous mode the audio clock is synchronised to the USB host SOF clock. Hence,
|
||||
at 48kHz the device always expects six samples from, and always sends size samples to, the host.
|
||||
|
||||
See USB Device Class Definition for Audio Data Formats v2.0 section 2.3.1.1 for full details.
|
||||
|
||||
.. _usb_audio_samples_per_packet:
|
||||
|
||||
.. table:: Allowed samples per packet
|
||||
.. table:: Allowed samples per packet in Async mode
|
||||
|
||||
+-----------------+-------------+-------------+
|
||||
| Frequency (kHz) | Min Packet | Max Packet |
|
||||
@@ -304,46 +306,11 @@ for full details.
|
||||
+-----------------+-------------+-------------+
|
||||
|
||||
|
||||
To implement this control, the decoupler core uses the feedback
|
||||
value calculated in the buffering core. This value is used to
|
||||
work out the size of the next packet it will insert into the audio
|
||||
FIFO.
|
||||
To implement this control, the Decoupler core uses the feedback value calculated in the EP Buffering
|
||||
core. This value is used to work out the size of the next packet it will insert into the audio FIFO.
|
||||
|
||||
.. note::
|
||||
|
||||
In Synchronous mode the same system is used, but the feedback value simply uses a fixed value
|
||||
rather than one derived from the master clock port.
|
||||
|
||||
.. .. _fig_usb_devices:
|
||||
|
||||
.. .. table:: USB interfaces presented to host
|
||||
.. :class: center
|
||||
..
|
||||
.. +-----------------------+----------------------------------+
|
||||
.. | **Mode** | **Interfaces** |
|
||||
.. +=======================+==================================+
|
||||
.. | Application mode | | Audio Class 2/Audio Class 1 |
|
||||
.. | | | DFU Class 1.1 |
|
||||
.. | | | MIDI Device Class 1.0 |
|
||||
.. +-----------------------+----------------------------------+
|
||||
.. | DFU mode | DFU Class 1.1 |
|
||||
.. +-----------------------+----------------------------------+
|
||||
|
||||
.. The device initially starts in Application mode.
|
||||
|
||||
|
||||
|
||||
|
||||
.. :ref:`usb_audio_sec_dfu` describes how DFU mode is used. The
|
||||
.. audio device class (1 or 2) is set at compile time---see :ref:`usb_audio_sec_custom_defines_api`.
|
||||
|
||||
|
||||
|
||||
.. Reset
|
||||
.. ~~~~~
|
||||
|
||||
.. On receiving a reset request, three steps occur:
|
||||
|
||||
.. #. Depending on the DFU state, the device may be set into DFU
|
||||
mode.
|
||||
|
||||
.. #. A XUD function is called to reset the endpoint structure and receive the new bus speed.
|
||||
|
||||
.. _usb_audio_sec_audio-requ-sett:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
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
|
||||
Interface Device Class Specification.
|
||||
@@ -45,4 +45,3 @@ On each HID report request from the host the function ``Vendor_ReadHidButtons(un
|
||||
|
||||
Since the ``Vendor_ReadHidButtons()`` function is called from the ``buffer`` logical core, care should be taken not to add to much execution time to this function since this could cause issues with servicing other endpoints.
|
||||
|
||||
For a full example please see the HID section in :ref:`usb_audio_sec_l1_audio_sw`.
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
|
||||
Apple MFi compatibility
|
||||
-----------------------
|
||||
|
||||
XMOS devices are capable of operating with Apple iPod, iPhone, and iPad devices
|
||||
that feature USB host support. Information regarding this functionality is
|
||||
protected by the Made For iPod (MFi) program and associated licensing.
|
||||
|
||||
Please contact XMOS for details and further documentation.
|
||||
@@ -1,7 +1,13 @@
|
||||
MIDI
|
||||
----
|
||||
|newpage|
|
||||
|
||||
MIDI
|
||||
====
|
||||
|
||||
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
|
||||
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``.
|
||||
|
||||
The Endpoint Buffer core implements the two Bulk endpoints (one In and one Out) as well as interacting
|
||||
with small, shared-memory, FIFOs for each endpoint.
|
||||
|
||||
The MIDI driver implements a 31250 baud UART input and output. On receiving 32-bit USB MIDI events
|
||||
from the ``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 an
|
||||
passed on to the ``buffer`` core. The MIDI core is implemented in the file ``usb_midi.xc``.
|
||||
|
||||
@@ -3,50 +3,53 @@
|
||||
Digital Mixer
|
||||
-------------
|
||||
|
||||
The mixer core(s) take outgoing audio from the decoupler core and incoming
|
||||
audio from the audio driver core. It then applies the volume to each
|
||||
channel and passes incoming audio on to the decoupler and outgoing
|
||||
audio to the audio driver. The volume update is achieved using the
|
||||
built-in 32bit to 64bit signed multiply-accumulate function
|
||||
(``macs``). The mixer is implemented in the file
|
||||
``mixer.xc``.
|
||||
The Mixer core(s) take outgoing audio from the Decouple core and incoming audio from the Audio Hub
|
||||
core. It then applies the volume to each channel and passes incoming audio on to Decouple and outgoing
|
||||
audio to Audio Hub. The volume update is achieved using the built-in 32bit to 64bit signed
|
||||
multiply-accumulate function (``macs``). The mixer is implemented in the file ``mixer.xc``.
|
||||
|
||||
The mixer takes two cores and can perform eight mixes with
|
||||
up to 18 inputs at sample rates up to 96kHz and two mixes with up to 18
|
||||
inputs at higher sample rates. The component automatically moves
|
||||
down to two mixes when switching to a higher rate.
|
||||
The mixer takes (up to) two cores and can perform eight mixes with up to 18 inputs at sample rates
|
||||
up to 96kHz and two mixes with up to 18 inputs at higher sample rates. The component automatically
|
||||
reverts to generating two mixes when running at the higher rate.
|
||||
|
||||
The mixer can take inputs from either:
|
||||
|
||||
* The USB outputs from the host---these samples come from the decoupler core.
|
||||
* The inputs from the audio interface on the device---these
|
||||
samples come from the audio driver.
|
||||
* The USB outputs from the host---these samples come from the Decouple core.
|
||||
* The inputs from the audio interfaces on the device---these samples come from the Audio Hub core
|
||||
and includes samples from digital input streams.
|
||||
|
||||
Since the sum of these inputs may be more then the 18 possible mix
|
||||
inputs to each mixer, there is a mapping from all the
|
||||
possible inputs to the mixer inputs.
|
||||
Since the sum of these inputs may be more then the 18 possible mix inputs to each mixer, there is a
|
||||
mapping from all the possible inputs to the mixer inputs.
|
||||
|
||||
After the mix occurs, the final outputs are created. There are two
|
||||
output destinations:
|
||||
After the mix occurs, the final outputs are created. There are two possible output destinations
|
||||
for each mix.
|
||||
|
||||
* The USB inputs to the host---these samples are sent to the decoupler core.
|
||||
* The USB inputs to the host---these samples are sent to the Decouple core.
|
||||
|
||||
* The outputs to the audio interface on the device---these samples
|
||||
are sent to the audio driver.
|
||||
* The outputs to the audio interface on the device---these samples are sent to the Audio Hub
|
||||
core
|
||||
|
||||
For each possible output, a mapping exists to tell the mixer what its
|
||||
source is. The possible sources are the USB outputs from the host, the
|
||||
inputs for the audio interface or the outputs from the mixer units.
|
||||
For each possible output from the device, a mapping exists to inform the mixer what it's source is.
|
||||
The possible sources are the output from the USB host, the inputs from the Audio Hub core or the
|
||||
outputs from the mixes.
|
||||
|
||||
As mentioned in :ref:`usb_audio_sec_audio-requ-volume`, the mixer can also
|
||||
handle volume setting. If the mixer is configured to handle volume but
|
||||
the number of mixes is set to zero (so the component is solely doing
|
||||
volume setting) then the component will use only one core.
|
||||
Essentially the mixer/router can be configured such that any device input can be used as an input to
|
||||
any mix or routed directly to any device output. Additionally, any device output can be derived from
|
||||
any mixer output or any device input.
|
||||
|
||||
As mentioned in :ref:`usb_audio_sec_audio-requ-volume`, the mixer can also handle processing or
|
||||
volume controls. If the mixer is configured to handle volume but the number of mixes is set to zero
|
||||
(such that the core is solely doing volume setting) then the component will use only one core. This
|
||||
is sometimes a useful configuration for large channel count devices.
|
||||
|
||||
Control
|
||||
~~~~~~~
|
||||
|
||||
The mixers can receive the following control commands from the Endpoint 0 core via a channel:
|
||||
The mixers can receive the control commands from the host via USB Control Requests to Endpoint 0.
|
||||
The Endpoint 0 core relays these to the Mixer cores(s) via a channel (``c_mix_ctl``). These commands
|
||||
are described in :ref:`table_mixer_commands`.
|
||||
|
||||
.. _table_mixer_commands:
|
||||
|
||||
.. list-table:: Mixer Component Commands
|
||||
:header-rows: 1
|
||||
@@ -79,103 +82,170 @@ Host Control
|
||||
~~~~~~~~~~~~
|
||||
|
||||
The mixer can be controlled from a host PC by sending requests to Endpoint 0. XMOS provides a simple
|
||||
command line based sample application demonstrating how the mixer can be controlled.
|
||||
command line based sample application demonstrating how the mixer can be controlled. This is
|
||||
intended as an example of how you might add mixer control to your own control application. It is not
|
||||
intended to be exposed to end users.
|
||||
|
||||
For details, consult the README file in the host_usb_mixer_control directory.
|
||||
A list of arguments can also be seen with::
|
||||
|
||||
The main requirements of this control are to
|
||||
$ ./xmos_mixer --help
|
||||
|
||||
The main requirements of this control utility are to
|
||||
|
||||
* Set the mapping of input channels into the mixer
|
||||
* Set the coefficients for each mixer output of each input
|
||||
* Set the coefficients for each mixer output for each input
|
||||
* Set the mapping for physical outputs which can either come
|
||||
directly from the inputs or via the mixer.
|
||||
|
||||
There is enough flexibility within this configuration that there will often
|
||||
be multiple ways of creating the required solution.
|
||||
.. note::
|
||||
|
||||
Whilst using the XMOS Host control example application, consider setting the
|
||||
mixer to perform a loop-back from analogue inputs 1 and 2 to analogue
|
||||
outputs 1 and 2.
|
||||
The flexibility within this configuration space us such that there is often multiple ways
|
||||
of producing the desired result. Product developers may only want to expose a subset of this
|
||||
functionality to their end users.
|
||||
|
||||
First consider the inputs to the mixer::
|
||||
Whilst using the XMOS Host control example application, consider the example of setting the
|
||||
mixer to perform a loop-back from analogue inputs 1 & 2 to analogue outputs 1 & 2.
|
||||
|
||||
./xmos_mixer --display-aud-channel-map 0
|
||||
.. note::
|
||||
|
||||
displays which channels are mapped to which mixer inputs::
|
||||
The command outputs shown are examples; the actual output will depend on the mixer configuration.
|
||||
|
||||
./xmos_mixer --display-aud-channel-map-sources 0
|
||||
The following will show the index for each device output along with which channel is currently mapped to it.
|
||||
In this example the analogue outputs 1 & 2 are 0 & 1 respectively::
|
||||
|
||||
displays which channels could possibly be mapped to mixer inputs. Notice
|
||||
that analogue inputs 1 and 2 are on mixer inputs 10 and 11.
|
||||
$ ./xmos_mixer --display-aud-channel-map
|
||||
|
||||
Now examine the audio output mapping::
|
||||
Audio Output Channel Map
|
||||
------------------------
|
||||
|
||||
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)
|
||||
$ _
|
||||
|
||||
./xmos_mixer --display-aud-channel-map 0
|
||||
The DAW Output Map can be seen with::
|
||||
|
||||
displays which channels are mapped to which outputs. By default all
|
||||
of these bypass the mixer. We can also see what all the possible
|
||||
mappings are::
|
||||
$ ./xmos_mixer --display-daw-channel-map
|
||||
|
||||
./xmos_mixer --display-aud-channel-map-sources 0
|
||||
DAW Output To Host Channel Map
|
||||
------------------------
|
||||
|
||||
0 (DEVICE IN - Analogue 1) source is 4 (DEVICE IN - Analogue 1)
|
||||
1 (DEVICE IN - Analogue 2) source is 5 (DEVICE IN - Analogue 2)
|
||||
$ _
|
||||
|
||||
So now map the first two mixer outputs to physical outputs 1 and 2::
|
||||
.. note::
|
||||
|
||||
./xmos_mixer --set-aud-channel-map 0 26
|
||||
./xmos_mixer --set-aud-channel-map 1 27
|
||||
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::
|
||||
|
||||
./xmos_mixer --display-aud-channel-map 0
|
||||
$ ./xmos_mixer --display-aud-channel-map
|
||||
|
||||
This now makes analogue outputs 1 and 2 come from the mixer, rather
|
||||
than directly from USB. However the mixer is still mapped to pass
|
||||
the USB channels through to the outputs, so there will still be no
|
||||
functional change yet.
|
||||
Audio Output Channel Map
|
||||
------------------------
|
||||
|
||||
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)
|
||||
$ _
|
||||
|
||||
The mixer nodes need to be individually set. They can be displayed
|
||||
with::
|
||||
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.
|
||||
|
||||
./xmos_mixer --display-mixer-nodes 0
|
||||
|
||||
To get the audio from the analogue inputs to outputs 1 and 2, nodes 80
|
||||
and 89 need to be set::
|
||||
.. note::
|
||||
|
||||
./xmos_mixer --set-value 0 80 0
|
||||
./xmos_mixer --set-value 0 89 0
|
||||
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::
|
||||
|
||||
$ ./xmos_mixer --display-mixer-nodes 0
|
||||
|
||||
Mixer Values (0)
|
||||
----------------
|
||||
|
||||
Mixer outputs
|
||||
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::
|
||||
|
||||
./xmos_mixer --set-value 0 0 -inf
|
||||
./xmos_mixer --set-value 0 9 -inf
|
||||
$ ./xmos_mixer --set-value 0 0 -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 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.
|
||||
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
|
||||
such that mixer outputs 1 and 2 come from the analogue inputs 1 and 2.
|
||||
|
||||
To demonstrate this, firstly undo the changes above::
|
||||
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 89 -inf
|
||||
./xmos_mixer --set-value 0 0 0
|
||||
./xmos_mixer --set-value 0 9 0
|
||||
$ ./xmos_mixer --set-value 0 8 -inf
|
||||
$ ./xmos_mixer --set-value 0 11 -inf
|
||||
$ ./xmos_mixer --set-value 0 0 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 1 11
|
||||
|
||||
If you rerun::
|
||||
|
||||
./xmos_mixer --display-mixer-nodes 0
|
||||
|
||||
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. Again, by playing audio into analogue inputs
|
||||
1/2 this can be heard looped through to analogue outputs 1/2.
|
||||
$ ./xmos_mixer --set-mixer-source 0 0 4
|
||||
|
||||
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
|
||||
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::
|
||||
|
||||
$ ./xmos_mixer --display-mixer-nodes 0
|
||||
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
|newpage|
|
||||
|
||||
PDM Microphones
|
||||
---------------
|
||||
===============
|
||||
|
||||
Overview of PDM implemention
|
||||
----------------------------
|
||||
|
||||
The design is capable of integrating PDM microphones. The PDM stream from the microphones is converted
|
||||
to PCM and output to the host via USB.
|
||||
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.
|
||||
|
||||
Interfacing to the PDM microphones is done using the XMOS microphone array library (``lib_mic_array``).
|
||||
``lib_mic_array`` is designed to allow interfacing to PDM microphones coupled with efficient decimation
|
||||
@@ -19,9 +18,6 @@ The following components of the library are used:
|
||||
* PDM interface
|
||||
* Four channel decimators
|
||||
|
||||
|newpage|
|
||||
|
||||
|
||||
Up to sixteen PDM microphones can be attached to each high channel count PDM interface (``mic_array_pdm_rx()``).
|
||||
One to four processing tasks, ``mic_array_decimate_to_pcm_4ch()``, each process up to four channels. For 1-4
|
||||
channels the library requires two logical cores:
|
||||
@@ -40,35 +36,39 @@ for 5-8 channels three logical cores are required, as shown below:
|
||||
Five to eight count PDM interface
|
||||
|
||||
The left most task, ``mic_array_pdm_rx()``, samples up to 8 microphones and filters the data to provide up to
|
||||
eight 384 KHz data streams, split in two streams of four channels. The processing thread
|
||||
decimates the signal to a user chosen sample rate (one of 48, 24, 16, 12 or 8 KHz).
|
||||
eight 384kHz data streams, split into two streams of four channels. The processing thread
|
||||
decimates the signal to a user chosen sample rate (one of 48, 24, 16, 12 or 8kHz).
|
||||
|
||||
More channels can be supported by increasing the number of cores dedicated to the PDM tasks. However, the current
|
||||
PDM mic integration into USB Audio limits itself to 8.
|
||||
PDM mic integration into ``lib_xua`` is limited to 8.
|
||||
|
||||
After the decimation to the output sample-rate various other steps take place e.g. DC offset elimination, gain correction
|
||||
and compensation etc. Please refer to ``lib_mic_array`` documention for further implementation detail and complete feature set.
|
||||
|
||||
and compensation etc. Please refer to the documentation provided with ``lib_mic_array`` for further
|
||||
implementation detail and complete feature set.
|
||||
|
||||
PDM Microphone Hardware Characteristics
|
||||
+++++++++++++++++++++++++++++++++++++++
|
||||
---------------------------------------
|
||||
|
||||
The PDM microphones need a *clock input* and provide the PDM signal on a *data output*. All PDM microphones share the same
|
||||
clock signal (buffered on the PCB as appropriate), and output onto eight data wires that are connected to a single 8-bit port:
|
||||
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
|
||||
output onto eight data wires that are connected to a single 8-bit port:
|
||||
|
||||
.. _pdm_wire_table:
|
||||
|
||||
.. list-table:: PDM microphone data and signal wires
|
||||
:class: vertical-borders horizontal-borders
|
||||
|
||||
* - *CLOCK*
|
||||
:header-rows: 1
|
||||
|
||||
* - Signal
|
||||
- Description
|
||||
* - CLOCK
|
||||
- Clock line, the PDM clock the used by the microphones to
|
||||
drive the data out.
|
||||
* - *DQ_PDM*
|
||||
* - DQ_PDM
|
||||
- The data from the PDM microphones on an 8 bit port.
|
||||
|
||||
The only port that is passed into ``lib_mic_array`` is the 8-bit data port. The library
|
||||
assumes that the input port is clocked using the PDM clock and requires no knowlege of the
|
||||
assumes that the input port is clocked using the PDM clock and requires no knowledge of the
|
||||
PDM clock source.
|
||||
|
||||
The input clock for the microphones can be generated in a multitude of
|
||||
@@ -76,14 +76,14 @@ ways. For example, a 3.072MHz clock can be generated on the board, or the xCORE
|
||||
divide down 12.288 MHz master clock. Or, if clock accuracy is not important, the internal 100 MHz
|
||||
reference can be divided down to provide an approximate clock.
|
||||
|
||||
Integration of PDM Microphones into USB Audio
|
||||
+++++++++++++++++++++++++++++++++++++++++++++
|
||||
Usage & Integration
|
||||
-------------------
|
||||
|
||||
A PDM microphone wrapper is called from ``main()`` and takes one channel argument connecting it to the rest of the system:
|
||||
|
||||
``pcm_pdm_mic(c_pdm_pcm);``
|
||||
|
||||
The implemetation of this function can be found in the file ``pcm_pdm_mics.xc``.
|
||||
The implementation of this function can be found in the file ``pcm_pdm_mics.xc``.
|
||||
|
||||
The first job of this function is to configure the ports/clocking for the microphones, this divides the external
|
||||
audio master clock input (on port ``p_mclk``) and outputs the divided clock to the microphones via the ``p_pdm_clk`` port::
|
||||
@@ -93,7 +93,7 @@ audio master clock input (on port ``p_mclk``) and outputs the divided clock to t
|
||||
configure_in_port(p_pdm_mics, pdmclk);
|
||||
start_clock(pdmclk);
|
||||
|
||||
It then runs the various cores required for the PDM interface and PDM to PCM conversion as discussed previously::
|
||||
It then runs the various cores required for the PDM interface and PDM to PCM conversion as previously discussed::
|
||||
|
||||
par
|
||||
{
|
||||
@@ -107,8 +107,9 @@ The ``pdm_process()`` task includes the main integration code, it takes audio fr
|
||||
it, performs optional local processing and outputs it to the audio driver (TDM/I2S core).
|
||||
|
||||
This function simply makes a call to ``mic_array_get_next_time_domain_frame()`` in order to get a frame of PCM audio
|
||||
from the microphones. It then waits for an request for audio samples from the audio/I2S/TDM core via a channel and
|
||||
from the microphones. It then waits for an request for audio samples from the Audio Hub core via a channel and
|
||||
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
|
||||
is required.
|
||||
|
||||
|
||||
@@ -1,24 +1,26 @@
|
||||
|newpage|
|
||||
|
||||
.. _usb_audio_sec_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.
|
||||
|
||||
.. table:: Resource Usage
|
||||
|
||||
+---------------+---------------+---------------------+-------------------------------------+
|
||||
| Component | Cores | Memory (KB) | Ports |
|
||||
+===============+===============+=====================+=====================================+
|
||||
| XUD library | 1 | 9 (6 code) | ULPI ports |
|
||||
| XUD library | 1 | 9 (6 code) | USB ports |
|
||||
| | | | |
|
||||
+---------------+---------------+---------------------+-------------------------------------+
|
||||
| Endpoint 0 | 1 | 17.5 (10.5 code) | none |
|
||||
+---------------+---------------+---------------------+-------------------------------------+
|
||||
| USB Buffering | 1 | 22.5 (1 code) | none |
|
||||
| USB Buffering | 2 | 22.5 (1 code) | 1 x n bit port |
|
||||
+---------------+---------------+---------------------+-------------------------------------+
|
||||
| Audio driver | 1 | 8.5 (6 code) | See :ref:`usb_audio_sec_audio` |
|
||||
| Audio Hub | 1 | 8.5 (6 code) | See :ref:`usb_audio_sec_audio` |
|
||||
+---------------+---------------+---------------------+-------------------------------------+
|
||||
| S/PDIF Tx | 1 | 3.5 (2 code) | 1 x 1 bit port |
|
||||
+---------------+---------------+---------------------+-------------------------------------+
|
||||
@@ -26,18 +28,18 @@ component of the reference design software.
|
||||
+---------------+---------------+---------------------+-------------------------------------+
|
||||
| ADAT Rx | 1 | 3.2 (3.2 code) | 1 x 1 bit port |
|
||||
+---------------+---------------+---------------------+-------------------------------------+
|
||||
| Midi | 1 | 6.5 (1.5 code) | 2 x 1 bit ports |
|
||||
| MIDI | 1 | 6.5 (1.5 code) | 2 x 1 bit ports |
|
||||
+---------------+---------------+---------------------+-------------------------------------+
|
||||
| Mixer | 2 | 8.7 (6.5 code) | |
|
||||
| Mixer | (up to) 2 | 8.7 (6.5 code) | |
|
||||
+---------------+---------------+---------------------+-------------------------------------+
|
||||
| ClockGen | 1 | 2.5 (2.4 code) | |
|
||||
+---------------+---------------+---------------------+-------------------------------------+
|
||||
|
||||
.. note::
|
||||
|
||||
These resource estimates are based on the multichannel reference design with
|
||||
all options of that design enabled. For fewer channels, the resource
|
||||
usage is likely to decrease.
|
||||
These resource estimates are based on the multichannel reference design with
|
||||
all options of that design enabled. For fewer channels, the resource
|
||||
usage is likely to decrease.
|
||||
|
||||
.. note::
|
||||
|
||||
@@ -46,6 +48,6 @@ component of the reference design software.
|
||||
|
||||
.. note::
|
||||
|
||||
The ULPI ports are a fixed set of ports on the L-Series
|
||||
device. When using these ports, other ports are
|
||||
unavailable when ULPI is active. See the `XS1-L Hardware Design Checklist <http://www.xmos.com/published/xs1lcheck>`_ for further details.
|
||||
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.
|
||||
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
|
||||
|newpage|
|
||||
|
||||
S/PDIF Transmit
|
||||
...............
|
||||
===============
|
||||
|
||||
``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.
|
||||
@@ -18,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
|
||||
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**
|
||||
- 44.1, 48, 88.2, 96, 176.4, 192 kHz
|
||||
@@ -28,7 +31,7 @@ clock generation (e.g. when clock source is already locked to desired audio cloc
|
||||
- ``lib_spdif``
|
||||
|
||||
Clocking
|
||||
++++++++
|
||||
--------
|
||||
|
||||
.. only:: latex
|
||||
|
||||
@@ -51,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).
|
||||
|
||||
Usage
|
||||
+++++
|
||||
-----
|
||||
|
||||
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``
|
||||
@@ -79,10 +82,10 @@ The following protocol is used on the channel:
|
||||
* - ``...``
|
||||
-
|
||||
|
||||
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
|
||||
:ref:`usb_audio_spdif_stream_structure`. The channel status bits are
|
||||
@@ -126,15 +129,15 @@ indicates sampling frequency as shown in :ref:`usb_audio_spdif_sample_bits`.
|
||||
* - Frequency (kHz)
|
||||
- n
|
||||
* - 44.1
|
||||
- 0
|
||||
- 0x0
|
||||
* - 48
|
||||
- 2
|
||||
- 0x2
|
||||
* - 88.2
|
||||
- 8
|
||||
- 0x8
|
||||
* - 96
|
||||
- A
|
||||
- 0xA
|
||||
* - 176.4
|
||||
- C
|
||||
- 0xC
|
||||
* - 192
|
||||
- E
|
||||
- 0xE
|
||||
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
|newpage|
|
||||
|
||||
S/PDIF Receive
|
||||
---------------
|
||||
==============
|
||||
|
||||
XMOS devices can support S/PDIF receive up to 192kHz.
|
||||
XMOS devices can support S/PDIF receive up to 192kHz - see ``lib_spdif`` for full specifications.
|
||||
|
||||
The S/PDIF receiver module uses a clockblock and a buffered one-bit port.
|
||||
The S/PDIF receiver module uses a clock-block and a buffered one-bit port.
|
||||
The clock-block is divided of a 100 MHz reference clock. The one bit port is buffered to 4-bits.
|
||||
The receiver code uses this clock to over sample the input data.
|
||||
|
||||
The receiver outputs audio samples over a *streaming channel end* where data can be input using the
|
||||
built-in input operator.
|
||||
built-in input operator. ``lib_spdif`` also provides API functions that wrap up this communication.
|
||||
|
||||
The S/PDIF receive function never returns. The 32-bit value from the channel
|
||||
input comprises:
|
||||
The S/PDIF receive function never returns. The 32-bit value from the channel input comprises:
|
||||
|
||||
.. list-table:: S/PDIF RX Word Structure
|
||||
:header-rows: 1
|
||||
@@ -41,16 +42,22 @@ The tag has one of three values:
|
||||
* - FRAME\_Z
|
||||
- Sample on channel 0 (Left), and the first sample of a frame; can be used if the user bits need to be reconstructed.
|
||||
|
||||
See S/PDIF 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
|
||||
+++++++++++++++++++++
|
||||
---------------------
|
||||
|
||||
Since S/PDIF is a digital steam the devices master clock must be syncronised to it. This is typically
|
||||
done with an external fractional-n multipier. See `Clock Recovery` (:ref:`usb_audio_sec_clock_recovery`)
|
||||
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`).
|
||||
|
||||
The S/PDIF receive function communicates with the ``clockGen`` component with passes audio data to the
|
||||
audio driver and handles locking to the S/PDIF clock source if required (see External Clock Recovery).
|
||||
.. note::
|
||||
|
||||
Due to the requirement for this clock recovery S/PDIF receive can only be used in Asynchronous
|
||||
mode.
|
||||
|
||||
The S/PDIF receive function communicates with the Clock Gen core, which in turn passes audio data to the
|
||||
Audio Hub core. The Clock Gen core also handles locking to the S/PDIF clock source
|
||||
(see :ref:`usb_audio_sec_clock_recovery`).
|
||||
|
||||
Ideally the parity of each word/sample received should be checked. This is done using the built in
|
||||
``crc32`` function (see ``xs1.h``):
|
||||
@@ -62,8 +69,7 @@ Ideally the parity of each word/sample received should be checked. This is done
|
||||
If bad parity is detected the word/sample is ignored, otherwise the tag is inspected for channel
|
||||
(i.e. left or right) and the sample stored.
|
||||
|
||||
The following code snippet illustrates how the output of the S/PDIF receive component could be used::
|
||||
|
||||
The following code snippet illustrates how the output of the S/PDIF receive component could is used::
|
||||
|
||||
while(1)
|
||||
{
|
||||
@@ -90,6 +96,5 @@ The following code snippet illustrates how the output of the S/PDIF receive comp
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
The Clock Gen core stores samples in a small FIFO before they are communicated to the Audio Hub core.
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
|
||||
|newpage|
|
||||
|
||||
XMOS USB Device (XUD) Library
|
||||
.............................
|
||||
=============================
|
||||
|
||||
All low level communication with the USB host is handled by the XMOS USB Device (XUD) library - `lib_xud`
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
Using lib_xud
|
||||
-------------
|
||||
|
||||
This sections describes the basic usage of `lib_xud`. It provides a guide on how to program the USB Audio Devices using `lib_xud`.
|
||||
Basic Usage
|
||||
***********
|
||||
|
||||
Reviewing application note AN00246 is highly recommended at this point.
|
||||
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.
|
||||
|
||||
@@ -18,15 +18,17 @@ The code is split into several directories.
|
||||
- MIDI I/O code
|
||||
* - dfu
|
||||
- Device Firmware Upgrade code
|
||||
* - hid
|
||||
- Human Interface Device code
|
||||
|
||||
|
||||
Note, the midi and dfu directories are potential candidates for separate libs in their own right.
|
||||
|
||||
|
||||
Including in a project
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
Using in a Project
|
||||
==================
|
||||
|
||||
All `lib_xua` functions can be accessed via the ``xua.h`` header filer::
|
||||
All `lib_xua` functions can be accessed via the ``xua.h`` header file::
|
||||
|
||||
#include <xua.h>
|
||||
|
||||
@@ -34,109 +36,51 @@ It is also required to add ``lib_xua`` to the ``USED_MODULES`` field of your app
|
||||
|
||||
USED_MODULES = .. lib_xua ...
|
||||
|
||||
.. _sec_basic_usage_codeless:
|
||||
|
||||
Core hardware resources
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
"Codeless" Programming Model
|
||||
============================
|
||||
|
||||
The user must declare and initialise relevant hardware resources (globally) and pass them to the relevant function of `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.
|
||||
|
||||
As an absolute minimum the following resources are required:
|
||||
For instance, some users may not have a large software development experience and simply want to
|
||||
customise some basic settings such as strings, sample-rates, channel-counts etc.
|
||||
Others may want to fully customise the implementation - adding additional functionality such as
|
||||
adding DSP or possibly only using a subset of the functions provided - just ``XUA_AudioHub``,
|
||||
for example.
|
||||
|
||||
- A 1-bit port for audio master clock input
|
||||
- A n-bit port for internal feedback calculation (typically a free, unused port is used e.g. `16B`)
|
||||
- A clock-block, which will be clocked from the master clock input port
|
||||
In addition, the large number of supported features can lead to a large number of tasks, hardware
|
||||
resources, communication channels etc, requiring quite a lot of code to be authored for each product.
|
||||
|
||||
Example declaration of these resources might look as follows::
|
||||
In order to cater for the former class of users, a "codeless" option is provided. Put simply, a file
|
||||
``main.xc`` is provided which includes a pre-authored ``main()`` function along with all of the
|
||||
required hardware resource declarations. Code is generated based on the options provided by the
|
||||
developer in ``xua_conf.h``
|
||||
|
||||
in port p_mclk_in = PORT_MCLK_IN;
|
||||
in port p_for_mclk_count = PORT_MCLK_COUNT; /* Extra port for counting master clock ticks */
|
||||
clock clk_audio_mclk = on tile[0]: XS1_CLKBLK_5; /* Master clock */
|
||||
Using this development model the user simply must include a ``xua_conf.h`` with their settings and
|
||||
optional implementations of any 'user functions' as desired. This, along with an XN file for their
|
||||
hardware platform, is all that is required to build a fully featured and functioning product. This
|
||||
XN file should contain definitions of the ports used for the various ``lib_xua`` functionality,
|
||||
see ::ref:`sec_options`.
|
||||
|
||||
.. note::
|
||||
This development model also provides the benefit of a full and verified codebase as a basis for a product.
|
||||
|
||||
The `PORT_MCLK_IN` and `PORT_MCLK_COUNT` defintions are derived from the projects XN file
|
||||
This behaviour described in this section is the default behaviour of `lib_xua`, to disable this please
|
||||
set ``EXCLUDE_USB_AUDIO_MAIN`` to 1 in the application makefile or ``xua_conf.h`` and see
|
||||
::ref:`sec_advanced_usage`.
|
||||
|
||||
Configuring lib_xua
|
||||
===================
|
||||
|
||||
The ``XUA_AudioHub()`` function requires an audio master clock input to clock the physical audio I/O. Less obvious is the reasoning for the ``XUA_Buffer()``
|
||||
task having the same requirement - it is used for the USB feedback system and packet sizing.
|
||||
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.
|
||||
|
||||
Due to the above, if the ``XUD_AudioHub()`` and ``XUA_Buffer()`` cores must reside on separate tiles a separate master clock input port must be provided to each, for example::
|
||||
Such build time options include audio class version, sample rates, channel counts etc. Please see
|
||||
::ref:`sec_api` for full listings.
|
||||
|
||||
/* Master clock for the audio IO tile */
|
||||
in port p_mclk_in = PORT_MCLK_IN;
|
||||
|
||||
/* Resources for USB feedback */
|
||||
in port p_mclk_in_usb = PORT_MCLK_IN_USB; /* Extra master clock input for the USB tile */
|
||||
|
||||
Whilst the hardware resources described in this section satisfy the basic requirements for the operation (or build) of `lib_xua` projects typically also needs some additional audio I/O,
|
||||
I2S or SPDIF for example.
|
||||
|
||||
These should be passed into the various cores as required - see API and Features sections.
|
||||
|
||||
Running the core components
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
In their most basic form the core components can be run as follows::
|
||||
|
||||
par
|
||||
{
|
||||
/* Endpoint 0 core from lib_xua */
|
||||
XUA_Endpoint0(c_ep_out[0], c_ep_in[0], c_aud_ctl, null, null, null, null);
|
||||
|
||||
/* Buffering cores - handles audio data to/from EP's and gives/gets data to/from the audio I/O core */
|
||||
/* Note, this spawns two cores */
|
||||
XUA_Buffer(c_ep_out[1], c_ep_in[1], c_sof, c_aud_ctl, p_for_mclk_count, c_aud);
|
||||
|
||||
/* AudioHub/IO core does most of the audio IO i.e. I2S (also serves as a hub for all audio) */
|
||||
XUA_AudioHub(c_aud, ...) ;
|
||||
}
|
||||
|
||||
``XUA_Buffer()`` expects its ``p_for_mclk_count`` argument to be clocked from the audio master clock before being passed it.
|
||||
The following code satisfies this requirement::
|
||||
|
||||
{
|
||||
/* Connect master-clock clock-block to clock-block pin */
|
||||
set_clock_src(clk_audio_mclk_usb, p_mclk_in_usb); /* Clock clock-block from mclk pin */
|
||||
set_port_clock(p_for_mclk_count, clk_audio_mclk_usb); /* Clock the "count" port from the clock block */
|
||||
start_clock(clk_audio_mclk_usb); /* Set the clock off running */
|
||||
|
||||
XUA_Buffer(c_ep_out[1], c_ep_in[1], c_sof, c_aud_ctl, p_for_mclk_count, c_aud);
|
||||
|
||||
}
|
||||
|
||||
.. note:: Keeping this configuration outside of ``XUA_Buffer()`` does not preclude the possibllty of sharing ``p_mclk_in_usb`` port with additional components
|
||||
|
||||
To produce a fully operating device a call to ``XUD_Main()`` (from ``lib_xud``) must also be made for USB connectivity::
|
||||
|
||||
/* Low level USB device layer core */
|
||||
on tile[1]: XUD_Main(c_ep_out, 2, c_ep_in, 2, c_sof, epTypeTableOut, epTypeTableIn, null, null, -1, XUD_SPEED_HS, XUD_PWR_SELF);
|
||||
|
||||
Additionally the required communication channels must also be declared::
|
||||
|
||||
/* Channel arrays for lib_xud */
|
||||
chan c_ep_out[2];
|
||||
chan c_ep_in[2];
|
||||
|
||||
/* Channel for communicating SOF notifications from XUD to the Buffering cores */
|
||||
chan c_sof;
|
||||
|
||||
/* Channel for audio data between buffering cores and AudioHub/IO core */
|
||||
chan c_aud;
|
||||
|
||||
/* Channel for communicating control messages from EP0 to the rest of the device (via the buffering cores) */
|
||||
chan c_aud_ctl;
|
||||
|
||||
|
||||
This section provides enough information to implement a skeleton program for a USB Audio device. When running the xCORE device will present itself as a USB Audio Class device on the bus.
|
||||
|
||||
|
||||
Configuring XUA
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Configuration of the various build time options of ``lib_xua`` is done via the optional header `xua_conf.h`. Such build time options include audio class version, sample rates, channel counts etc.
|
||||
Please see the API section for full listings.
|
||||
|
||||
The build system will automatically include the `xua_conf.h` header file as appropriate - the user should continue to include `xua.h` as previously directed. A simple example is shown below::
|
||||
The build system will automatically include the `xua_conf.h` header file as appropriate - the developer
|
||||
should continue to include `xua.h` as previously directed. A simple example is shown below::
|
||||
|
||||
#ifndef _XUA_CONF_H_
|
||||
#define _XUA_CONF_H_
|
||||
@@ -149,28 +93,10 @@ The build system will automatically include the `xua_conf.h` header file as appr
|
||||
|
||||
#endif
|
||||
|
||||
User Functions
|
||||
==============
|
||||
|
||||
User functions
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
To enable custom functionality, such as configuring external audio hardware, custom functionality on stream start/stop etc various user overridable functions are provided (see API section for full listings). The default implementations are empty.
|
||||
|
||||
|
||||
Codeless programming model
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Whilst it is possible to code a USB Audio device using the building blocks provided by `lib_xua` it is realised that this might not be desirable for some classes of customers or product.
|
||||
|
||||
For instance, some users may not have a large software development experience and simply want to customise some basic settings such as strings, sample-rates, channel-counts etc. Others may want to fully customise the implementation - adding additional functionality such as adding DSD or possibly only using a subset of the functions provided - just ``XUA_AudioHub``, for example.
|
||||
|
||||
In addition, the large number of supported features can lead to a large number of tasks, hardware resources, communication channels etc, requiring quite a lot of code to be authored for each product.
|
||||
|
||||
In order to cater for the former class of users, a "codeless" option is provided. Put simply, a file ``main.xc`` is provided which includes a pre-authored ``main()`` function along with all of the required hardware resource declarations. Code is generated based on the options provided in ``xua_conf.h``
|
||||
|
||||
Using this development model the user simply must include a ``xua_conf.h`` with their settings and optional implementations of any 'user functions' as desired. This, along with an XN file for their hardware platform, is all that is required to build a fully featured and functioning product.
|
||||
|
||||
This model also provides the benefit of a known-good, full codebase as a basis for a product.
|
||||
|
||||
This behaviour described in this section is the default behaviour of `lib_xua`, to disable this please set ``EXCLUDE_USB_AUDIO_MAIN`` to 1 in the application makefile or ``xua_conf.h``.
|
||||
|
||||
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
|
||||
full listings). The default implementations of these functions are empty.
|
||||
|
||||
|
||||
25
lib_xua/doc/rst/using_adv.rst
Normal file
25
lib_xua/doc/rst/using_adv.rst
Normal file
@@ -0,0 +1,25 @@
|
||||
.. _sec_advanced_usage:
|
||||
|
||||
Advanced Usage
|
||||
**************
|
||||
|
||||
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
|
||||
scratch using the building blocks provided by `lib_xua`.
|
||||
|
||||
This could be for a number of reasons, adding complex DSP, merging with some other functionality
|
||||
etc. This section describes these building blocks and their use.
|
||||
|
||||
Reviewing application note AN00246 is highly recommended at this point.
|
||||
|
||||
|
||||
.. toctree::
|
||||
|
||||
Core Hardware Resources <using_adv_core_hw>
|
||||
Running the Core Components <using_adv_core_comp>
|
||||
I2S/TDM <using_adv_i2s>
|
||||
Mixer <using_adv_mixer>
|
||||
|
||||
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user