diff --git a/Jenkinsfile b/Jenkinsfile index bb6f5721..bd0503cb 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -48,8 +48,6 @@ pipeline { 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") } @@ -61,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}") { @@ -105,6 +67,8 @@ pipeline { runXdoc('doc') } } + // Archive all the generated .pdf docs + archiveArtifacts artifacts: "${REPO}/**/pdf/*.pdf", fingerprint: true, allowEmptyArchive: true } } } diff --git a/examples/AN00246_xua_example/Makefile b/examples/AN00246_xua_example/Makefile index 037b1524..d4c27b94 100644 --- a/examples/AN00246_xua_example/Makefile +++ b/examples/AN00246_xua_example/Makefile @@ -1,11 +1,14 @@ 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. diff --git a/examples/AN00246_xua_example/doc/rst/AN00246_xua_example.rst b/examples/AN00246_xua_example/doc/rst/AN00246_xua_example.rst index 9627120a..a3fda049 100644 --- a/examples/AN00246_xua_example/doc/rst/AN00246_xua_example.rst +++ b/examples/AN00246_xua_example/doc/rst/AN00246_xua_example.rst @@ -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: diff --git a/examples/AN00246_xua_example/doc/rst/images/hw_setup.jpg b/examples/AN00246_xua_example/doc/rst/images/hw_setup.jpg index 8998805d..6bc1ba74 100644 Binary files a/examples/AN00246_xua_example/doc/rst/images/hw_setup.jpg and b/examples/AN00246_xua_example/doc/rst/images/hw_setup.jpg differ diff --git a/examples/AN00246_xua_example/src/app_xua_simple.xc b/examples/AN00246_xua_example/src/app_xua_simple.xc index a4ee4b84..51d55dde 100644 --- a/examples/AN00246_xua_example/src/app_xua_simple.xc +++ b/examples/AN00246_xua_example/src/app_xua_simple.xc @@ -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; diff --git a/examples/AN00246_xua_example/src/cs4384.h b/examples/AN00246_xua_example/src/cs4384.h deleted file mode 100644 index 6de83e81..00000000 --- a/examples/AN00246_xua_example/src/cs4384.h +++ /dev/null @@ -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_ */ diff --git a/examples/AN00246_xua_example/src/cs5368.h b/examples/AN00246_xua_example/src/cs5368.h deleted file mode 100644 index d2de278d..00000000 --- a/examples/AN00246_xua_example/src/cs5368.h +++ /dev/null @@ -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_ */ diff --git a/examples/AN00246_xua_example/src/hid_report_descriptor.h b/examples/AN00246_xua_example/src/hid_report_descriptor.h deleted file mode 100644 index 70e01717..00000000 --- a/examples/AN00246_xua_example/src/hid_report_descriptor.h +++ /dev/null @@ -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__ diff --git a/examples/AN00246_xua_example/src/hwsupport.xc b/examples/AN00246_xua_example/src/hwsupport.xc index 1ba6f6e6..1ca91a3f 100644 --- a/examples/AN00246_xua_example/src/hwsupport.xc +++ b/examples/AN00246_xua_example/src/hwsupport.xc @@ -1,146 +1,56 @@ -// Copyright 2016-2022 XMOS LIMITED. +// Copyright 2017-2022 XMOS LIMITED. // This Software is subject to the terms of the XMOS Public Licence: Version 1. - +#include #include -#include -#include - #include "xua.h" -#include "i2c.h" /* From lib_i2c */ +#include "../../shared/apppll.h" -#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); + + /* Use xCORE Secondary PLL to generate *fixed* master clock */ + AppPllEnable_SampleRate(DEFAULT_FREQ); + + delay_milliseconds(100); + + /* DAC setup: For basic I2S input we don't need any register setup. DACs will clock auto detect etc. + * 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 */ +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]); - } + AppPllEnable_SampleRate(samFreq); } diff --git a/examples/AN00246_xua_example/src/xk-audio-216-mc.xn b/examples/AN00246_xua_example/src/xk-audio-216-mc.xn deleted file mode 100644 index 88e6d699..00000000 --- a/examples/AN00246_xua_example/src/xk-audio-216-mc.xn +++ /dev/null @@ -1,88 +0,0 @@ - - - Board - XS2 MC Audio - - tileref tile[2] - tileref usb_tile - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - --> - - - - - - - - - - --> - --> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/AN00246_xua_example/src/xk-audio-316-mc.xn b/examples/AN00246_xua_example/src/xk-audio-316-mc.xn new file mode 100644 index 00000000..8b4334e5 --- /dev/null +++ b/examples/AN00246_xua_example/src/xk-audio-316-mc.xn @@ -0,0 +1,92 @@ + + + Board + xcore.ai MC Audio Board + + + tileref tile[2] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/AN00246_xua_example/src/xua_conf.h b/examples/AN00246_xua_example/src/xua_conf.h index 9f0b77c9..0d92b9f7 100644 --- a/examples/AN00246_xua_example/src/xua_conf.h +++ b/examples/AN00246_xua_example/src/xua_conf.h @@ -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 */ diff --git a/examples/AN00247_xua_example_spdif_tx/Makefile b/examples/AN00247_xua_example_spdif_tx/Makefile index 00fadd8d..43f0f3fe 100644 --- a/examples/AN00247_xua_example_spdif_tx/Makefile +++ b/examples/AN00247_xua_example_spdif_tx/Makefile @@ -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. diff --git a/examples/AN00247_xua_example_spdif_tx/doc/rst/AN00247_xua_example_spdif_tx.rst b/examples/AN00247_xua_example_spdif_tx/doc/rst/AN00247_xua_example_spdif_tx.rst index d36ba8e4..79f7cfcc 100644 --- a/examples/AN00247_xua_example_spdif_tx/doc/rst/AN00247_xua_example_spdif_tx.rst +++ b/examples/AN00247_xua_example_spdif_tx/doc/rst/AN00247_xua_example_spdif_tx.rst @@ -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 :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| diff --git a/examples/AN00247_xua_example_spdif_tx/doc/rst/images/hw_setup.jpg b/examples/AN00247_xua_example_spdif_tx/doc/rst/images/hw_setup.jpg index 8998805d..fe397eb8 100644 Binary files a/examples/AN00247_xua_example_spdif_tx/doc/rst/images/hw_setup.jpg and b/examples/AN00247_xua_example_spdif_tx/doc/rst/images/hw_setup.jpg differ diff --git a/examples/AN00247_xua_example_spdif_tx/src/app_xua_simple.xc b/examples/AN00247_xua_example_spdif_tx/src/app_xua_spdiftx.xc similarity index 88% rename from examples/AN00247_xua_example_spdif_tx/src/app_xua_simple.xc rename to examples/AN00247_xua_example_spdif_tx/src/app_xua_spdiftx.xc index c9c96881..9e5600ea 100644 --- a/examples/AN00247_xua_example_spdif_tx/src/app_xua_simple.xc +++ b/examples/AN00247_xua_example_spdif_tx/src/app_xua_spdiftx.xc @@ -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; diff --git a/examples/AN00247_xua_example_spdif_tx/src/hid_report_descriptor.h b/examples/AN00247_xua_example_spdif_tx/src/hid_report_descriptor.h deleted file mode 100644 index 70e01717..00000000 --- a/examples/AN00247_xua_example_spdif_tx/src/hid_report_descriptor.h +++ /dev/null @@ -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__ diff --git a/examples/AN00247_xua_example_spdif_tx/src/hwsupport.xc b/examples/AN00247_xua_example_spdif_tx/src/hwsupport.xc index 84e0464b..1ca91a3f 100644 --- a/examples/AN00247_xua_example_spdif_tx/src/hwsupport.xc +++ b/examples/AN00247_xua_example_spdif_tx/src/hwsupport.xc @@ -1,52 +1,56 @@ -// Copyright 2016-2021 XMOS LIMITED. +// Copyright 2017-2022 XMOS LIMITED. // This Software is subject to the terms of the XMOS Public Licence: Version 1. - +#include #include -#include - #include "xua.h" +#include "../../shared/apppll.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); + + /* Use xCORE Secondary PLL to generate *fixed* master clock */ + AppPllEnable_SampleRate(DEFAULT_FREQ); + + delay_milliseconds(100); + + /* DAC setup: For basic I2S input we don't need any register setup. DACs will clock auto detect etc. + * 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 */ +void AudioHwConfig(unsigned samFreq, unsigned mClk, unsigned dsdMode, unsigned sampRes_DAC, unsigned sampRes_ADC) +{ + AppPllEnable_SampleRate(samFreq); } diff --git a/examples/AN00247_xua_example_spdif_tx/src/xk-audio-216-mc.xn b/examples/AN00247_xua_example_spdif_tx/src/xk-audio-216-mc.xn deleted file mode 100644 index 88e6d699..00000000 --- a/examples/AN00247_xua_example_spdif_tx/src/xk-audio-216-mc.xn +++ /dev/null @@ -1,88 +0,0 @@ - - - Board - XS2 MC Audio - - tileref tile[2] - tileref usb_tile - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - --> - - - - - - - - - - --> - --> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/AN00247_xua_example_spdif_tx/src/xk-audio-316-mc.xn b/examples/AN00247_xua_example_spdif_tx/src/xk-audio-316-mc.xn new file mode 100644 index 00000000..9da4b479 --- /dev/null +++ b/examples/AN00247_xua_example_spdif_tx/src/xk-audio-316-mc.xn @@ -0,0 +1,92 @@ + + + Board + xcore.ai MC Audio Board + + + tileref tile[2] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/AN00247_xua_example_spdif_tx/src/xua_conf.h b/examples/AN00247_xua_example_spdif_tx/src/xua_conf.h index 1121ecdf..6459cb7f 100644 --- a/examples/AN00247_xua_example_spdif_tx/src/xua_conf.h +++ b/examples/AN00247_xua_example_spdif_tx/src/xua_conf.h @@ -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 diff --git a/examples/AN00247_xua_example_spdif_tx/src/xud_conf.h b/examples/AN00247_xua_example_spdif_tx/src/xud_conf.h deleted file mode 100644 index 3fc13baf..00000000 --- a/examples/AN00247_xua_example_spdif_tx/src/xud_conf.h +++ /dev/null @@ -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 diff --git a/examples/AN00248_xua_example_pdm_mics/doc/rst/AN00248_xua_example_pdm_mics.rst b/examples/AN00248_xua_example_pdm_mics/doc/rst/AN00248_xua_example_pdm_mics.rst index fb8b963d..2541855a 100644 --- a/examples/AN00248_xua_example_pdm_mics/doc/rst/AN00248_xua_example_pdm_mics.rst +++ b/examples/AN00248_xua_example_pdm_mics/doc/rst/AN00248_xua_example_pdm_mics.rst @@ -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 ....................... diff --git a/examples/shared/apppll.h b/examples/shared/apppll.h new file mode 100644 index 00000000..1312c0ab --- /dev/null +++ b/examples/shared/apppll.h @@ -0,0 +1,109 @@ +// Copyright 2022 XMOS LIMITED. +// This Software is subject to the terms of the XMOS Public Licence: Version 1. +#include +#include "xassert.h" + +// App PLL setup +#define APP_PLL_CTL_BYPASS (0) // 0 = no bypass, 1 = bypass. +#define APP_PLL_CTL_INPUT_SEL (0) // 0 = XTAL, 1 = sysPLL +#define APP_PLL_CTL_ENABLE (1) // 0 = disabled, 1 = enabled. + +// 24MHz in, 24.576MHz out, integer mode +// Found exact solution: IN 24000000.0, OUT 24576000.0, VCO 2457600000.0, RD 5, FD 512, OD 10, FOD 10 +#define APP_PLL_CTL_OD_48 (4) // Output divider = (OD+1) +#define APP_PLL_CTL_F_48 (511) // FB divider = (F+1)/2 +#define APP_PLL_CTL_R_48 (4) // Ref divider = (R+1) + +#define APP_PLL_CTL_48 ((APP_PLL_CTL_BYPASS << 29) | (APP_PLL_CTL_INPUT_SEL << 28) | (APP_PLL_CTL_ENABLE << 27) |\ + (APP_PLL_CTL_OD_48 << 23) | (APP_PLL_CTL_F_48 << 8) | APP_PLL_CTL_R_48) + +// Fractional divide is M/N +#define APP_PLL_FRAC_EN_48 (0) // 0 = disabled +#define APP_PLL_FRAC_NPLUS1_CYCLES_48 (0) // M value is this reg value + 1. +#define APP_PLL_FRAC_TOTAL_CYCLES_48 (0) // N value is this reg value + 1. +#define APP_PLL_FRAC_48 ((APP_PLL_FRAC_EN_48 << 31) | (APP_PLL_FRAC_NPLUS1_CYCLES_48 << 8) | APP_PLL_FRAC_TOTAL_CYCLES_48) + +// 24MHz in, 22.5792MHz out (44.1kHz * 512), frac mode +// Found exact solution: IN 24000000.0, OUT 22579200.0, VCO 2257920000.0, RD 5, FD 470.400 (m = 2, n = 5), OD 5, FOD 10 +#define APP_PLL_CTL_OD_441 (4) // Output divider = (OD+1) +#define APP_PLL_CTL_F_441 (469) // FB divider = (F+1)/2 +#define APP_PLL_CTL_R_441 (4) // Ref divider = (R+1) + +#define APP_PLL_CTL_441 ((APP_PLL_CTL_BYPASS << 29) | (APP_PLL_CTL_INPUT_SEL << 28) | (APP_PLL_CTL_ENABLE << 27) |\ + (APP_PLL_CTL_OD_441 << 23) | (APP_PLL_CTL_F_441 << 8) | APP_PLL_CTL_R_441) + +#define APP_PLL_FRAC_EN_44 (1) // 1 = enabled +#define APP_PLL_FRAC_NPLUS1_CYCLES_44 (1) // M value is this reg value + 1. +#define APP_PLL_FRAC_TOTAL_CYCLES_44 (4) // N value is this reg value + 1.define APP_PLL_CTL_R_441 (4) // Ref divider = (R+1) +#define APP_PLL_FRAC_44 ((APP_PLL_FRAC_EN_44 << 31) | (APP_PLL_FRAC_NPLUS1_CYCLES_44 << 8) | APP_PLL_FRAC_TOTAL_CYCLES_44) + +#define APP_PLL_DIV_INPUT_SEL (1) // 0 = sysPLL, 1 = app_PLL +#define APP_PLL_DIV_DISABLE (0) // 1 = disabled (pin connected to X1D11), 0 = enabled divider output to pin. +#define APP_PLL_DIV_VALUE (4) // Divide by N+1 - remember there's a /2 also afterwards for 50/50 duty cycle. +#define APP_PLL_DIV ((APP_PLL_DIV_INPUT_SEL << 31) | (APP_PLL_DIV_DISABLE << 16) | APP_PLL_DIV_VALUE) + +/* TODO support more than two freqs..*/ +void AppPllEnable(int32_t clkFreq_hz) +{ + switch(clkFreq_hz) + { + case 44100*512: + + // Disable the PLL + write_node_config_reg(tile[1], XS1_SSWITCH_SS_APP_PLL_CTL_NUM, (APP_PLL_CTL_441 & 0xF7FFFFFF)); + // Enable the PLL to invoke a reset on the appPLL. + write_node_config_reg(tile[1], XS1_SSWITCH_SS_APP_PLL_CTL_NUM, APP_PLL_CTL_441); + // Must write the CTL register twice so that the F and R divider values are captured using a running clock. + write_node_config_reg(tile[1], XS1_SSWITCH_SS_APP_PLL_CTL_NUM, APP_PLL_CTL_441); + // Now disable and re-enable the PLL so we get the full 5us reset time with the correct F and R values. + write_node_config_reg(tile[1], XS1_SSWITCH_SS_APP_PLL_CTL_NUM, (APP_PLL_CTL_441 & 0xF7FFFFFF)); + write_node_config_reg(tile[1], XS1_SSWITCH_SS_APP_PLL_CTL_NUM, APP_PLL_CTL_441); + + // Set the fractional divider if used + write_node_config_reg(tile[0], XS1_SSWITCH_SS_APP_PLL_FRAC_N_DIVIDER_NUM, APP_PLL_FRAC_44); + + break; + + case 48000*512: + + // Disable the PLL + write_node_config_reg(tile[1], XS1_SSWITCH_SS_APP_PLL_CTL_NUM, (APP_PLL_CTL_48 & 0xF7FFFFFF)); + // Enable the PLL to invoke a reset on the appPLL. + write_node_config_reg(tile[1], XS1_SSWITCH_SS_APP_PLL_CTL_NUM, APP_PLL_CTL_48); + // Must write the CTL register twice so that the F and R divider values are captured using a running clock. + write_node_config_reg(tile[1], XS1_SSWITCH_SS_APP_PLL_CTL_NUM, APP_PLL_CTL_48); + // Now disable and re-enable the PLL so we get the full 5us reset time with the correct F and R values. + write_node_config_reg(tile[1], XS1_SSWITCH_SS_APP_PLL_CTL_NUM, (APP_PLL_CTL_48 & 0xF7FFFFFF)); + write_node_config_reg(tile[1], XS1_SSWITCH_SS_APP_PLL_CTL_NUM, APP_PLL_CTL_48); + + // Set the fractional divider if used + write_node_config_reg(tile[0], XS1_SSWITCH_SS_APP_PLL_FRAC_N_DIVIDER_NUM, APP_PLL_FRAC_48); + + break; + + default: + assert(0); + break; + } + + // Wait for PLL output frequency to stabilise due to fractional divider enable + delay_microseconds(100); + + // Turn on the clock output + write_node_config_reg(tile[0], XS1_SSWITCH_SS_APP_CLK_DIVIDER_NUM, APP_PLL_DIV); +} + +void AppPllEnable_SampleRate(int32_t sampleRate_hz) +{ + assert(sampleRate_hz >= 22050); + + if(sampleRate_hz % 22050 == 0) + { + AppPllEnable(44100*512); + } + else + { + AppPllEnable(48000*512); + } +} + diff --git a/lib_xua/src/core/clocking/clockgen.xc b/lib_xua/src/core/clocking/clockgen.xc index 855ad230..793bebc9 100644 --- a/lib_xua/src/core/clocking/clockgen.xc +++ b/lib_xua/src/core/clocking/clockgen.xc @@ -250,11 +250,6 @@ void clockGen (streaming chanend ?c_spdif_rx, chanend ?c_adat_rx, client interfa { timer t_local; unsigned timeNextEdge, timeLastEdge, timeNextClockDetection; - -#if (AUDIO_IO_TILE == PLL_REF_TILE) - unsigned pinVal = 0; - unsigned short pinTime; -#endif unsigned clkMode = CLOCK_INTERNAL; /* Current clocking mode in operation */ unsigned tmp;