From f3634755292ea27abf2979ff63311657c7c736ae Mon Sep 17 00:00:00 2001 From: xross Date: Mon, 8 Aug 2022 14:50:31 +0100 Subject: [PATCH] Moved AN00246 from xCORE-200 to xCORE.ai MC Audio Board --- examples/AN00246_xua_example/Makefile | 11 +- .../doc/rst/AN00246_xua_example.rst | 23 +-- .../AN00246_xua_example/src/app_xua_simple.xc | 24 ++- examples/AN00246_xua_example/src/cs4384.h | 33 ---- examples/AN00246_xua_example/src/cs5368.h | 19 -- .../src/hid_report_descriptor.h | 168 ------------------ examples/AN00246_xua_example/src/hwsupport.xc | 166 ++++------------- .../src/xk-audio-216-mc.xn | 88 --------- .../src/xk-audio-316-mc.xn | 92 ++++++++++ examples/AN00246_xua_example/src/xua_conf.h | 4 +- examples/shared/apppll.h | 108 +++++++++++ lib_xua/src/core/clocking/clockgen.xc | 5 - 12 files changed, 272 insertions(+), 469 deletions(-) delete mode 100644 examples/AN00246_xua_example/src/cs4384.h delete mode 100644 examples/AN00246_xua_example/src/cs5368.h delete mode 100644 examples/AN00246_xua_example/src/hid_report_descriptor.h delete mode 100644 examples/AN00246_xua_example/src/xk-audio-216-mc.xn create mode 100644 examples/AN00246_xua_example/src/xk-audio-316-mc.xn create mode 100644 examples/shared/apppll.h 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..170fdf16 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 ........ @@ -55,13 +51,12 @@ be included in your code to use the library. 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:: @@ -99,7 +94,7 @@ 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: @@ -162,7 +157,7 @@ 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 +To run the demo, connect a USB cable to power the xCORE.ai Multichannel Audio board and plug the xTAG to the board and connect the xTAG USB cable to your development machine. @@ -177,7 +172,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 @@ -192,7 +187,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 ................................... @@ -204,7 +199,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 ....................... diff --git a/examples/AN00246_xua_example/src/app_xua_simple.xc b/examples/AN00246_xua_example/src/app_xua_simple.xc index a4ee4b84..834ed0ec 100644 --- a/examples/AN00246_xua_example/src/app_xua_simple.xc +++ b/examples/AN00246_xua_example/src/app_xua_simple.xc @@ -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/shared/apppll.h b/examples/shared/apppll.h new file mode 100644 index 00000000..7cbfec80 --- /dev/null +++ b/examples/shared/apppll.h @@ -0,0 +1,108 @@ + +#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 cf3137c7..fa656861 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;