diff --git a/tests/i2s_loopback/LICENSE.txt b/tests/i2s_loopback/LICENSE.txt new file mode 100644 index 00000000..3f72bf93 --- /dev/null +++ b/tests/i2s_loopback/LICENSE.txt @@ -0,0 +1,133 @@ +Software Release License Agreement + +Copyright (c) 2016, XMOS, All rights reserved. + +BY ACCESSING, USING, INSTALLING OR DOWNLOADING THE XMOS SOFTWARE, YOU AGREE TO BE BOUND BY THE FOLLOWING TERMS. IF YOU DO NOT AGREE TO THESE, DO NOT ATTEMPT TO DOWNLOAD, ACCESS OR USE THE XMOS Software. +Parties: + +(1) XMOS Limited, incorporated and registered in England and Wales with company number 5494985 whose registered office is 107 Cheapside, London, EC2V 6DN (XMOS). + +(2) An individual or legal entity exercising permissions granted by this License (Customer). + +If you are entering into this Agreement on behalf of another legal entity such as a company, partnership, university, college etc. (for example, as an employee, student or consultant), you warrant that you have authority to bind that entity. + +1. Definitions + +"License" means this Software License and any schedules or annexes to it. + +"License Fee" means the fee for the XMOS Software as detailed in any schedules or annexes to this Software License + +"Licensee Modifications" means all developments and modifications of the XMOS Software developed independently by the Customer. + +"XMOS Modifications" means all developments and modifications of the XMOS Software developed or co-developed by XMOS. + +"XMOS Hardware" means any XMOS hardware devices supplied by XMOS from time to time and/or the particular XMOS devices detailed in any schedules or annexes to this Software License. + +"XMOS Software" comprises the XMOS owned circuit designs, schematics, source code, object code, reference designs, (including related programmer comments and documentation, if any), error corrections, improvements, modifications (including XMOS Modifications) and updates. + +The headings in this License do not affect its interpretation. Save where the context otherwise requires, references to clauses and schedules are to clauses and schedules of this License. + +Unless the context otherwise requires: + +- references to XMOS and the Customer include their permitted successors and assigns; +- references to statutory provisions include those statutory provisions as amended or re-enacted; and +- references to any gender include all genders. + +Words in the singular include the plural and in the plural include the singular. + +2. License + +XMOS grants the Customer a non-exclusive license to use, develop, modify and distribute the XMOS Software in object code only with, or for the purpose of being used with, XMOS Hardware. + +Open Source Software (OSS) must be used and dealt with in accordance with any license terms under which OSS is distributed. + +3. Consideration + +In consideration of the mutual obligations contained in this License, the parties agree to its terms. + +4. Term + +Subject to clause 12 below, this License shall be perpetual. + +5. Restrictions on Use + +The Customer will adhere to all applicable import and export laws and regulations of the country in which it resides and of the United States and United Kingdom, without limitation. The Customer agrees that it is its responsibility to obtain copies of and to familiarise itself fully with these laws and regulations to avoid violation. + +6. Modifications + +The Customer will own all intellectual property rights in the Licensee Modifications but will undertake to provide XMOS with any fixes made to correct any bugs found in the XMOS Software on a non-exclusive, perpetual and royalty free license basis. + +XMOS will own all intellectual property rights in the XMOS Modifications. +The Customer may only use the Licensee Modifications and XMOS Modifications on, or in relation to, XMOS Hardware. + +7. Support + +Support of the XMOS Software may be provided by XMOS pursuant to a separate support agreement. + +8. Warranty and Disclaimer + +The XMOS Software is provided "AS IS" without a warranty of any kind. XMOS and its licensors' entire liability and Customer's exclusive remedy under this warranty to be determined in XMOS's sole and absolute discretion, will be either (a) the corrections of defects in media or replacement of the media, or (b) the refund of the license fee paid (if any). + +Whilst XMOS gives the Customer the ability to load their own software and applications onto XMOS devices, the security of such software and applications when on the XMOS devices is the Customer's own responsibility and any breach of security shall not be deemed a defect or failure of the hardware. XMOS shall have no liability whatsoever in relation to any costs, damages or other losses Customer may incur as a result of any breaches of security in relation to your software or applications. + +XMOS AND ITS LICENSORS DISCLAIM ALL OTHER WARRANTIES, EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY/ SATISFACTORY QUALITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT EXCEPT TO THE EXTENT THAT THESE DISCLAIMERS ARE HELD TO BE LEGALLY INVALID UNDER APPLICABLE LAW. + +9. High Risk Activities + +The XMOS Software is not designed or intended for use in conjunction with on-line control equipment in hazardous environments requiring fail-safe performance, including without limitation the operation of nuclear facilities, aircraft navigation or communication systems, air traffic control, life support machines, or weapons systems (collectively "High Risk Activities") in which the failure of the XMOS Software could lead directly to death, personal injury, or severe physical or environmental damage. XMOS and its licensors specifically disclaim any express or implied warranties relating to use of the XMOS Software in connection with High Risk Activities. + +10. Liability + +TO THE EXTENT NOT PROHIBITED BY APPLICABLE LAW, NEITHER XMOS NOR ITS LICENSORS SHALL BE LIABLE FOR ANY LOST REVENUE, BUSINESS, PROFIT, CONTRACTS OR DATA, ADMINISTRATIVE OR OVERHEAD EXPENSES, OR FOR SPECIAL, INDIRECT, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES HOWEVER CAUSED AND REGARDLESS OF THEORY OF LIABILITY ARISING OUT OF THIS LICENSE, EVEN IF XMOS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. In no event shall XMOS's liability to the Customer whether in contract, tort (including negligence), or otherwise exceed the License Fee. + +Customer agrees to indemnify, hold harmless, and defend XMOS and its licensors from and against any claims or lawsuits, including attorneys' fees and any other liabilities, demands, proceedings, damages, losses, costs, expenses fines and charges which are made or brought against or incurred by XMOS as a result of your use or distribution of the Licensee Modifications or your use or distribution of XMOS Software, or any development of it, other than in accordance with the terms of this License. + +11. Ownership + +The copyrights and all other intellectual and industrial property rights for the protection of information with respect to the XMOS Software (including the methods and techniques on which they are based) are retained by XMOS and/or its licensors. Nothing in this Agreement serves to transfer such rights. Customer may not sell, mortgage, underlet, sublease, sublicense, lend or transfer possession of the XMOS Software in any way whatsoever to any third party who is not bound by this Agreement. + +12. Termination + +Either party may terminate this License at any time on written notice to the other if the other: + +- is in material or persistent breach of any of the terms of this License and either that breach is incapable of remedy, or the other party fails to remedy that breach within 30 days after receiving written notice requiring it to remedy that breach; or +- is unable to pay its debts (within the meaning of section 123 of the Insolvency Act 1986), or becomes insolvent, or is subject to an order or a resolution for its liquidation, administration, winding-up or dissolution (otherwise than for the purposes of a solvent amalgamation or reconstruction), or has an administrative or other receiver, manager, trustee, liquidator, administrator or similar officer appointed over all or any substantial part of its assets, or enters into or proposes any composition or arrangement with its creditors generally, or is subject to any analogous event or proceeding in any applicable jurisdiction. + +Termination by either party in accordance with the rights contained in clause 12 shall be without prejudice to any other rights or remedies of that party accrued prior to termination. + +On termination for any reason: + +- all rights granted to the Customer under this License shall cease; +- the Customer shall cease all activities authorised by this License; +- the Customer shall immediately pay any sums due to XMOS under this License; and +- the Customer shall immediately destroy or return to the XMOS (at the XMOS's option) all copies of the XMOS Software then in its possession, custody or control and, in the case of destruction, certify to XMOS that it has done so. + +Clauses 5, 8, 9, 10 and 11 shall survive any effective termination of this Agreement. + +13. Third party rights + +No term of this License is intended to confer a benefit on, or to be enforceable by, any person who is not a party to this license. + +14. Confidentiality and publicity + +Each party shall, during the term of this License and thereafter, keep confidential all, and shall not use for its own purposes nor without the prior written consent of the other disclose to any third party any, information of a confidential nature (including, without limitation, trade secrets and information of commercial value) which may become known to such party from the other party and which relates to the other party, unless such information is public knowledge or already known to such party at the time of disclosure, or subsequently becomes public knowledge other than by breach of this license, or subsequently comes lawfully into the possession of such party from a third party. + +The terms of this license are confidential and may not be disclosed by the Customer without the prior written consent of XMOS. +The provisions of clause 14 shall remain in full force and effect notwithstanding termination of this license for any reason. + +15. Entire agreement + +This License and the documents annexed as appendices to this License or otherwise referred to herein contain the whole agreement between the parties relating to the subject matter hereof and supersede all prior agreements, arrangements and understandings between the parties relating to that subject matter. + +16. Assignment + +The Customer shall not assign this License or any of the rights granted under it without XMOS's prior written consent. + +17. Governing law and jurisdiction + +This License shall be governed by and construed in accordance with English law and each party hereby submits to the non-exclusive jurisdiction of the English courts. + +This License has been entered into on the date stated at the beginning of it. + +Schedule +XMOS Microphone array library software diff --git a/tests/i2s_loopback/Makefile b/tests/i2s_loopback/Makefile new file mode 100644 index 00000000..4f54fc80 --- /dev/null +++ b/tests/i2s_loopback/Makefile @@ -0,0 +1,99 @@ +# Copyright (c) 2016, XMOS Ltd, All rights reserved +TARGET = xk-audio-216-mc.xn +USED_MODULES = lib_xua \ + module_i2c_shared module_i2c_single_port lib_logging + +BUILD_FLAGS = -O0 -g -lflash -DXUD_SERIES_SUPPORT=4 -fxscope -save-temps -march=xs2a -DUSB_TILE=tile[1] + +BUILD_FLAGS_i2s_master_2in_2out_48khz = $(BUILD_FLAGS) \ + -D ADAT_RX=0 -D ADAT_TX=0 -D SPDIF_RX=0 -D SPDIF_TX=0 -D MIDI=0 \ + -D NUM_USB_CHAN_IN=2 -D NUM_USB_CHAN_OUT=2 -DI2S_CHANS_ADC=2 -DI2S_CHANS_DAC=2 \ + -D DEFAULT_FREQ=48000 + +BUILD_FLAGS_i2s_slave_2in_2out_48khz = $(BUILD_FLAGS) \ + -D ADAT_RX=0 -D ADAT_TX=0 -D SPDIF_RX=0 -D SPDIF_TX=0 -D MIDI=0 \ + -D NUM_USB_CHAN_IN=2 -D NUM_USB_CHAN_OUT=2 -DI2S_CHANS_ADC=2 -DI2S_CHANS_DAC=2 \ + -D DEFAULT_FREQ=48000 -DCODEC_MASTER=1 + +BUILD_FLAGS_i2s_master_2in_2out_192khz = $(BUILD_FLAGS) \ + -D ADAT_RX=0 -D ADAT_TX=0 -D SPDIF_RX=0 -D SPDIF_TX=0 -D MIDI=0 \ + -D NUM_USB_CHAN_IN=2 -D NUM_USB_CHAN_OUT=2 -D I2S_CHANS_ADC=2 -D I2S_CHANS_DAC=2 \ + -D DEFAULT_FREQ=192000 + +BUILD_FLAGS_i2s_slave_2in_2out_192khz = $(BUILD_FLAGS) \ + -D ADAT_RX=0 -D ADAT_TX=0 -D SPDIF_RX=0 -D SPDIF_TX=0 -D MIDI=0 \ + -D NUM_USB_CHAN_IN=2 -D NUM_USB_CHAN_OUT=2 -DI2S_CHANS_ADC=2 -DI2S_CHANS_DAC=2 \ + -D DEFAULT_FREQ=192000 -DCODEC_MASTER=1 + +BUILD_FLAGS_i2s_master_8in_8out_48khz = $(BUILD_FLAGS) \ + -D ADAT_RX=0 -D ADAT_TX=0 -D SPDIF_RX=0 -D SPDIF_TX=0 -D MIDI=0 \ + -D NUM_USB_CHAN_IN=8 -D NUM_USB_CHAN_OUT=8 -D I2S_CHANS_ADC=8 -D I2S_CHANS_DAC=8 \ + -D DEFAULT_FREQ=48000 + +BUILD_FLAGS_i2s_slave_8in_8out_48khz = $(BUILD_FLAGS) \ + -D ADAT_RX=0 -D ADAT_TX=0 -D SPDIF_RX=0 -D SPDIF_TX=0 -D MIDI=0 \ + -D NUM_USB_CHAN_IN=8 -D NUM_USB_CHAN_OUT=8 -D I2S_CHANS_ADC=8 -D I2S_CHANS_DAC=8 \ + -D DEFAULT_FREQ=48000 -DCODEC_MASTER=1 + +BUILD_FLAGS_i2s_master_8in_8out_192khz = $(BUILD_FLAGS) \ + -D ADAT_RX=0 -D ADAT_TX=0 -D SPDIF_RX=0 -D SPDIF_TX=0 -D MIDI=0 \ + -D NUM_USB_CHAN_IN=8 -D NUM_USB_CHAN_OUT=8 -D I2S_CHANS_ADC=8 -D I2S_CHANS_DAC=8 \ + -D DEFAULT_FREQ=192000 \ + -O2 # optimisations to meet timing + +BUILD_FLAGS_i2s_slave_8in_8out_192khz = $(BUILD_FLAGS) \ + -D ADAT_RX=0 -D ADAT_TX=0 -D SPDIF_RX=0 -D SPDIF_TX=0 -D MIDI=0 \ + -D NUM_USB_CHAN_IN=8 -D NUM_USB_CHAN_OUT=8 -D I2S_CHANS_ADC=8 -D I2S_CHANS_DAC=8 \ + -D DEFAULT_FREQ=192000 -DCODEC_MASTER=1 \ + -O2 # optimisations to meet timing + +BUILD_FLAGS_tdm_master_8in_8out_48khz = $(BUILD_FLAGS) -D I2S_MODE_TDM=1 \ + -D ADAT_RX=0 -D ADAT_TX=0 -D SPDIF_RX=0 -D SPDIF_TX=0 -D MIDI=0 \ + -D NUM_USB_CHAN_IN=8 -D NUM_USB_CHAN_OUT=8 -D I2S_CHANS_ADC=8 -D I2S_CHANS_DAC=8 \ + -D DEFAULT_FREQ=48000 \ + -O2 # optimisations to meet timing + +BUILD_FLAGS_tdm_slave_8in_8out_48khz = $(BUILD_FLAGS) -D I2S_MODE_TDM=1 \ + -D ADAT_RX=0 -D ADAT_TX=0 -D SPDIF_RX=0 -D SPDIF_TX=0 -D MIDI=0 \ + -D NUM_USB_CHAN_IN=8 -D NUM_USB_CHAN_OUT=8 -D I2S_CHANS_ADC=8 -D I2S_CHANS_DAC=8 \ + -D DEFAULT_FREQ=48000 -DCODEC_MASTER=1 \ + -O2 # optimisations to meet timing + +BUILD_FLAGS_tdm_master_16in_16out_48khz = $(BUILD_FLAGS) -D I2S_MODE_TDM=1 \ + -D ADAT_RX=0 -D ADAT_TX=0 -D SPDIF_RX=0 -D SPDIF_TX=0 -D MIDI=0 \ + -D NUM_USB_CHAN_IN=16 -D NUM_USB_CHAN_OUT=16 -D I2S_CHANS_ADC=16 -D I2S_CHANS_DAC=16 \ + -D DEFAULT_FREQ=48000 \ + -O2 # optimisations to meet timing + +BUILD_FLAGS_tdm_slave_16in_16out_48khz = $(BUILD_FLAGS) -D I2S_MODE_TDM=1 \ + -D ADAT_RX=0 -D ADAT_TX=0 -D SPDIF_RX=0 -D SPDIF_TX=0 -D MIDI=0 \ + -D NUM_USB_CHAN_IN=16 -D NUM_USB_CHAN_OUT=16 -D I2S_CHANS_ADC=16 -D I2S_CHANS_DAC=16 \ + -D DEFAULT_FREQ=48000 -DCODEC_MASTER=1 \ + -O2 # optimisations to meet timing + +#XCC_FLAGS_hardware_i2s_master_2in_2out_48khz = -D HARDWARE $(BUILD_FLAGS_i2s_master_2in_2out_48khz) +#XCC_FLAGS_hardware_i2s_master_2in_2out_192khz = -D HARDWARE $(BUILD_FLAGS_i2s_master_2in_2out_192khz) +#XCC_FLAGS_hardware_i2s_master_8in_8out_48khz = -D HARDWARE $(BUILD_FLAGS_i2s_master_8in_8out_48khz) +#XCC_FLAGS_hardware_i2s_master_8in_8out_192khz = -D HARDWARE $(BUILD_FLAGS_i2s_master_8in_8out_192khz) +#XCC_FLAGS_hardware_tdm_master_8in_8out_48khz = -D HARDWARE $(BUILD_FLAGS_tdm_master_8in_8out_48khz) + +XCC_FLAGS_simulation_i2s_master_2in_2out_48khz = -D SIMULATION $(BUILD_FLAGS_i2s_master_2in_2out_48khz) +XCC_FLAGS_simulation_i2s_slave_2in_2out_48khz = -D SIMULATION $(BUILD_FLAGS_i2s_slave_2in_2out_48khz) + +XCC_FLAGS_simulation_i2s_master_2in_2out_192khz = -D SIMULATION $(BUILD_FLAGS_i2s_master_2in_2out_192khz) +XCC_FLAGS_simulation_i2s_slave_2in_2out_192khz = -D SIMULATION $(BUILD_FLAGS_i2s_slave_2in_2out_192khz) + +XCC_FLAGS_simulation_i2s_master_8in_8out_48khz = -D SIMULATION $(BUILD_FLAGS_i2s_master_8in_8out_48khz) +XCC_FLAGS_simulation_i2s_slave_8in_8out_48khz = -D SIMULATION $(BUILD_FLAGS_i2s_slave_8in_8out_48khz) + +XCC_FLAGS_simulation_i2s_master_8in_8out_192khz = -D SIMULATION $(BUILD_FLAGS_i2s_master_8in_8out_192khz) +XCC_FLAGS_simulation_i2s_slave_8in_8out_192khz = -D SIMULATION $(BUILD_FLAGS_i2s_slave_8in_8out_192khz) + +XCC_FLAGS_simulation_tdm_master_8in_8out_48khz = -D SIMULATION $(BUILD_FLAGS_tdm_master_8in_8out_48khz) +XCC_FLAGS_simulation_tdm_slave_8in_8out_48khz = -D SIMULATION $(BUILD_FLAGS_tdm_slave_8in_8out_48khz) + +XCC_FLAGS_simulation_tdm_master_16in_16out_48khz = -D SIMULATION $(BUILD_FLAGS_tdm_master_16in_16out_48khz) +XCC_FLAGS_simulation_tdm_slave_16in_16out_48khz = -D SIMULATION $(BUILD_FLAGS_tdm_slave_16in_16out_48khz) + +XMOS_MAKE_PATH ?= ../.. +-include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.common diff --git a/tests/i2s_loopback/debug_conf.h b/tests/i2s_loopback/debug_conf.h new file mode 100644 index 00000000..676f75f0 --- /dev/null +++ b/tests/i2s_loopback/debug_conf.h @@ -0,0 +1,8 @@ +// Copyright (c) 2016, XMOS Ltd, All rights reserved +#ifndef __debug_conf_h__ +#define __debug_conf_h__ + +#define DEBUG_PRINT_ENABLE_MAIN 1 +#define DEBUG_PRINT_ENABLE_AUDIO_IO 0 + +#endif // __debug_conf_h__ diff --git a/tests/i2s_loopback/main.xc b/tests/i2s_loopback/main.xc new file mode 100644 index 00000000..73e91448 --- /dev/null +++ b/tests/i2s_loopback/main.xc @@ -0,0 +1,247 @@ +// Copyright (c) 2016, XMOS Ltd, All rights reserved +#include +#include +#include +#include +#include "xua.h" + +#define DEBUG_UNIT MAIN +#include "debug_print.h" + + +/* Port declarations. Note, the defines come from the xn file */ +#if I2S_WIRES_DAC > 0 +on tile[AUDIO_IO_TILE] : buffered out port:32 p_i2s_dac[I2S_WIRES_DAC] = + {PORT_I2S_DAC0, +#endif +#if I2S_WIRES_DAC > 1 + PORT_I2S_DAC1, +#endif +#if I2S_WIRES_DAC > 2 + PORT_I2S_DAC2, +#endif +#if I2S_WIRES_DAC > 3 + PORT_I2S_DAC3, +#endif +#if I2S_WIRES_DAC > 4 + PORT_I2S_DAC4, +#endif +#if I2S_WIRES_DAC > 5 + PORT_I2S_DAC5, +#endif +#if I2S_WIRES_DAC > 6 + PORT_I2S_DAC6, +#endif +#if I2S_WIRES_DAC > 7 +#error I2S_WIRES_DAC value is too large! +#endif +#if I2S_WIRES_DAC > 0 + }; +#endif + +#if I2S_WIRES_ADC > 0 +on tile[AUDIO_IO_TILE] : buffered in port:32 p_i2s_adc[I2S_WIRES_ADC] = + {PORT_I2S_ADC0, +#endif +#if I2S_WIRES_ADC > 1 + PORT_I2S_ADC1, +#endif +#if I2S_WIRES_ADC > 2 + PORT_I2S_ADC2, +#endif +#if I2S_WIRES_ADC > 3 + PORT_I2S_ADC3, +#endif +#if I2S_WIRES_ADC > 4 + PORT_I2S_ADC4, +#endif +#if I2S_WIRES_ADC > 5 + PORT_I2S_ADC5, +#endif +#if I2S_WIRES_ADC > 6 + PORT_I2S_ADC6, +#endif +#if I2S_WIRES_ADC > 7 +#error I2S_WIRES_ADC value is too large! +#endif +#if I2S_WIRES_ADC > 0 + }; +#endif + + +#if defined(CODEC_MASTER) && (CODEC_MASTER != 0) +buffered in port:32 p_lrclk = PORT_I2S_LRCLK; +buffered in port:32 p_bclk = PORT_I2S_BCLK; +#else +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 */ +#endif + +/* Note, declared unsafe as sometimes we want to share this port +e.g. PDM mics and I2S use same master clock IO */ +port p_mclk_in_ = PORT_MCLK_IN; + +/* Clock-block declarations */ +clock clk_audio_bclk = on tile[AUDIO_IO_TILE]: XS1_CLKBLK_1; /* Bit clock */ +clock clk_audio_mclk = on tile[AUDIO_IO_TILE]: XS1_CLKBLK_2; /* Master clock */ + +unsafe +{ + /* TODO simplify this */ + unsafe port p_mclk_in; /* Audio master clock input */ +} + +#ifdef SIMULATION +#define INITIAL_SKIP_FRAMES 10 +#define TOTAL_TEST_FRAMES 100 +#else +#define INITIAL_SKIP_FRAMES 1000 +#define TOTAL_TEST_FRAMES (5 * DEFAULT_FREQ) +#endif + +#define SAMPLE(frame_count, channel_num) (((frame_count) << 8) | ((channel_num) & 0xFF)) +#define SAMPLE_FRAME_NUM(test_word) ((test_word) >> 8) +#define SAMPLE_CHANNEL_NUM(test_word) ((test_word) & 0xFF) + +void generator(chanend c_checker, chanend c_out) +{ + unsigned frame_count; + int underflow_word; + int fail; + int i; + + frame_count = 0; + + + while (1) { + underflow_word = inuint(c_out); + +#pragma loop unroll + for (i = 0; i < NUM_USB_CHAN_OUT; i++) { + outuint(c_out, SAMPLE(frame_count, i)); + } + + fail = inuint(c_checker); + +#pragma loop unroll + for (i = 0; i < NUM_USB_CHAN_IN; i++) { + outuint(c_checker, inuint(c_out)); + } + + if (frame_count == TOTAL_TEST_FRAMES) { + if (!fail) { + debug_printf("PASS\n"); + } + outct(c_out, AUDIO_STOP_FOR_DFU); + //inuint(c_out); //This causes the DFUhandler to be called with exceptiopn in slave mode so skip this - we are out of here anyhow + exit(0); + } + + frame_count++; + } +} + +void checker(chanend c_checker, int disable) +{ + unsigned x[NUM_USB_CHAN_IN]; + int last_frame_number; + unsigned frame_count; + int fail; + int i; + + if (disable) + debug_printf("checker disabled\n"); + + /*debug_printf("%s %d/%d %d\n", + I2S_MODE_TDM ? "TDM" : "I2S", NUM_USB_CHAN_IN, NUM_USB_CHAN_OUT, DEFAULT_FREQ);*/ + + fail = 0; + frame_count = 0; + last_frame_number = -1; + + while (1) { + outuint(c_checker, fail); + +#pragma loop unroll + for (i = 0; i < NUM_USB_CHAN_IN; i++) { + x[i] = inuint(c_checker); + } + + if (frame_count > INITIAL_SKIP_FRAMES) { + // check that frame number is incrementing + if (!disable && SAMPLE_FRAME_NUM(x[0]) != last_frame_number + 1) { + debug_printf("%d: 0x%x (%d)\n", frame_count, x[0], last_frame_number); + fail = 1; + } + + for (i = 0; i < NUM_USB_CHAN_IN; i++) { + // check channel numbers are 0 to N-1 in a frame + if (!disable && SAMPLE_CHANNEL_NUM(x[i]) != i) { + debug_printf("%d,%d: 0x%x\n", frame_count, i, x[i]); + fail = 1; + } + + // check frame number doesn't change in a frame + if (!disable && SAMPLE_FRAME_NUM(x[i]) != SAMPLE_FRAME_NUM(x[0])) { + debug_printf("%d,%d: 0x%x (0x%x)\n", frame_count, i, x[i], x[0]); + fail = 1; + } + } + } + + last_frame_number = SAMPLE_FRAME_NUM(x[0]); + frame_count++; + } +} + +#ifdef SIMULATION + +out port p_mclk_gen = on tile[AUDIO_IO_TILE] : XS1_PORT_1A; +clock clk_audio_mclk_gen = on tile[AUDIO_IO_TILE] : XS1_CLKBLK_3; +void master_mode_clk_setup(void); + +#ifdef CODEC_MASTER +out port p_bclk_gen = on tile[AUDIO_IO_TILE] : XS1_PORT_1B; +clock clk_audio_bclk_gen = on tile[AUDIO_IO_TILE] : XS1_CLKBLK_4; +out port p_lrclk_gen = on tile[AUDIO_IO_TILE] : XS1_PORT_1C; +clock clk_audio_lrclk_gen = on tile[AUDIO_IO_TILE] : XS1_CLKBLK_5; +void slave_mode_clk_setup(const unsigned samFreq, const unsigned chans_per_frame); +#endif +#endif + +#if I2S_MODE_TDM +const int i2s_tdm_mode = 1; +#else +const int i2s_tdm_mode = 0; +#endif + +int main(void) +{ + chan c_checker; + chan c_out; + + par { + on tile[AUDIO_IO_TILE]: + { + unsafe + { + p_mclk_in = p_mclk_in_; + } + par + { + XUA_AudioHub(c_out); + generator(c_checker, c_out); + checker(c_checker, 0); +#ifdef SIMULATION +#ifdef CODEC_MASTER + slave_mode_clk_setup(DEFAULT_FREQ, (i2s_tdm_mode != 0) ? 8 : 2); +#else + master_mode_clk_setup(); +#endif +#endif + } + } + } + + return 0; +} diff --git a/tests/i2s_loopback/simulation.xc b/tests/i2s_loopback/simulation.xc new file mode 100644 index 00000000..2c90b7dd --- /dev/null +++ b/tests/i2s_loopback/simulation.xc @@ -0,0 +1,65 @@ +// Copyright (c) 2016, XMOS Ltd, All rights reserved +#ifdef SIMULATION + +#include +#include "audiohw.h" +#include "print.h" + +extern port p_mclk_in; + +extern port p_mclk25mhz; +extern clock clk_mclk25mhz; + +void AudioHwConfig(unsigned samFreq, unsigned mClk, unsigned dsdMode, unsigned sampRes_DAC, unsigned sampRes_ADC) +{ + // nothing +} + +void AudioHwInit() +{ + // nothing +} + + +extern clock clk_audio_mclk_gen; +extern out port p_mclk_gen; +void master_mode_clk_setup(void) +{ + configure_clock_rate(clk_audio_mclk_gen, 25, 1); // Slighly faster than typical MCLK of 24.576MHz + configure_port_clock_output(p_mclk_gen, clk_audio_mclk_gen); + start_clock(clk_audio_mclk_gen); + + //printstrln("Starting mclk"); + delay_seconds(-1); //prevent destructor ruining clock gen +} + + +#ifdef CODEC_MASTER +extern out port p_bclk_gen; +extern clock clk_audio_bclk_gen; +extern out port p_lrclk_gen; +extern clock clk_audio_lrclk_gen; + +void slave_mode_clk_setup(const unsigned samFreq, const unsigned chans_per_frame){ + const unsigned data_bits = 32; + const unsigned mclk_freq = 24576000; + + const unsigned mclk_bclk_ratio = mclk_freq / (chans_per_frame * samFreq * data_bits); + const unsigned bclk_lrclk_ratio = (chans_per_frame * data_bits); // 48.828Hz LRCLK + + //bclk + configure_clock_src_divide(clk_audio_bclk_gen, p_mclk_gen, mclk_bclk_ratio/2); + configure_port_clock_output(p_bclk_gen, clk_audio_bclk_gen); + start_clock(clk_audio_bclk_gen); + + //lrclk + configure_clock_src_divide(clk_audio_lrclk_gen, p_bclk_gen, bclk_lrclk_ratio/2); + configure_port_clock_output(p_lrclk_gen, clk_audio_lrclk_gen); + start_clock(clk_audio_lrclk_gen); + + //mclk + master_mode_clk_setup(); +} +#endif + +#endif diff --git a/tests/i2s_loopback/usb_device.h b/tests/i2s_loopback/usb_device.h new file mode 100644 index 00000000..9d09c7da --- /dev/null +++ b/tests/i2s_loopback/usb_device.h @@ -0,0 +1,24 @@ +// Copyright (c) 2016, XMOS Ltd, All rights reserved +#ifndef __usb_device_h__ +#define __usb_device_h__ + +#include +#include +#include "usb_std_requests.h" +#include "xud.h" + +XUD_Result_t USB_GetSetupPacket(XUD_ep ep_out, XUD_ep ep_in, REFERENCE_PARAM(USB_SetupPacket_t, sp)); + +XUD_Result_t USB_StandardRequests(XUD_ep ep_out, XUD_ep ep_in, + NULLABLE_ARRAY_OF(unsigned char, devDesc_hs), int devDescLength_hs, + NULLABLE_ARRAY_OF(unsigned char, cfgDesc_hs), int cfgDescLength_hs, + NULLABLE_ARRAY_OF(unsigned char, devDesc_fs), int devDescLength_fs, + NULLABLE_ARRAY_OF(unsigned char, cfgDesc_fs), int cfgDescLength_fs, +#ifdef __XC__ + char * unsafe strDescs[], +#else + char * strDescs[], +#endif + int strDescsLength, REFERENCE_PARAM(USB_SetupPacket_t, sp), XUD_BusSpeed_t usbBusSpeed); + +#endif // __usb_device_h__ diff --git a/tests/i2s_loopback/usb_device.xc b/tests/i2s_loopback/usb_device.xc new file mode 100644 index 00000000..563b3198 --- /dev/null +++ b/tests/i2s_loopback/usb_device.xc @@ -0,0 +1,32 @@ +#if 0 +// Copyright (c) 2016, XMOS Ltd, All rights reserved +#include +#include +#include "usb_std_requests.h" +#include "xud.h" +#include "usb_device.h" + +unsigned char g_currentConfig = 0; +unsigned char g_interfaceAlt[16]; + +XUD_Result_t USB_GetSetupPacket(XUD_ep ep_out, XUD_ep ep_in, REFERENCE_PARAM(USB_SetupPacket_t, sp)) +{ + return XUD_RES_OKAY; +} + +XUD_Result_t USB_StandardRequests(XUD_ep ep_out, XUD_ep ep_in, + NULLABLE_ARRAY_OF(unsigned char, devDesc_hs), int devDescLength_hs, + NULLABLE_ARRAY_OF(unsigned char, cfgDesc_hs), int cfgDescLength_hs, + NULLABLE_ARRAY_OF(unsigned char, devDesc_fs), int devDescLength_fs, + NULLABLE_ARRAY_OF(unsigned char, cfgDesc_fs), int cfgDescLength_fs, +#ifdef __XC__ + char * unsafe strDescs[], +#else + char * strDescs[], +#endif + int strDescsLength, REFERENCE_PARAM(USB_SetupPacket_t, sp), XUD_BusSpeed_t usbBusSpeed) +{ + return XUD_RES_OKAY; +} + +#endif diff --git a/tests/i2s_loopback/xk_216_mc/audiohw.xc b/tests/i2s_loopback/xk_216_mc/audiohw.xc new file mode 100644 index 00000000..55a83409 --- /dev/null +++ b/tests/i2s_loopback/xk_216_mc/audiohw.xc @@ -0,0 +1,371 @@ +// Copyright (c) 2016, XMOS Ltd, All rights reserved +#ifdef HARDWARE + +#include + +#include +#include "devicedefines.h" +#include +#include "gpio_access.h" +#include "i2c_shared.h" +#include "cs4384.h" +#include "cs5368.h" +#include "cs2100.h" +#include "print.h" +#include "dsd_support.h" + +/* The number of timer ticks to wait for the audio PLL to lock */ +/* CS2100 lists typical lock time as 100 * input period */ +#define AUDIO_PLL_LOCK_DELAY (40000000) + +#if defined(SPDIF_RX) || defined(ADAT_RX) +#define USE_FRACTIONAL_N 1 +#endif + +on tile[0] : out port p_gpio = XS1_PORT_8C; + +#ifndef IAP +/* If IAP not enabled, i2c ports not declared - still needs for DAC config */ +on tile [0] : struct r_i2c r_i2c = {XS1_PORT_4A}; +#else +extern struct r_i2c r_i2c; +#endif + +#define DAC_REGWRITE(reg, val) {data[0] = val; i2c_shared_master_write_reg(r_i2c, CS4384_I2C_ADDR, reg, data, 1);} +#define DAC_REGREAD(reg, val) {i2c_shared_master_read_reg(r_i2c, CS4384_I2C_ADDR, reg, val, 1);} +#define ADC_REGWRITE(reg, val) {data[0] = val; i2c_shared_master_write_reg(r_i2c, CS5368_I2C_ADDR, reg, data, 1);} + +#ifdef USE_FRACTIONAL_N + +#if !(defined(SPDIF_RX) || defined(ADAT_RX)) +/* Choose a frequency the xcore can easily generate internally */ +#define PLL_SYNC_FREQ 1000000 +#else +#define PLL_SYNC_FREQ 300 +#endif + +#define CS2100_REGREAD(reg, data) {data[0] = 0xAA; i2c_master_read_reg(CS2100_I2C_DEVICE_ADDR, reg, data, 1, r_i2c);} +#define CS2100_REGREAD_ASSERT(reg, data, expected) {data[0] = 0xAA; i2c_master_read_reg(CS2100_I2C_DEVICE_ADDR, reg, data, 1, r_i2c); assert(data[0] == expected);} +#define CS2100_REGWRITE(reg, val) {data[0] = val; i2c_master_write_reg(CS2100_I2C_DEVICE_ADDR, reg, data, 1, r_i2c);} + +/* Init of CS2100 */ +void PllInit(void) +{ + unsigned char data[1] = {0}; + +#if XCORE_200_MC_AUDIO_HW_VERSION < 2 + /* Enable init */ + CS2100_REGWRITE(CS2100_DEVICE_CONFIG_1, 0x05); +#else + CS2100_REGWRITE(CS2100_DEVICE_CONFIG_1, 0x07); +#endif + CS2100_REGWRITE(CS2100_GLOBAL_CONFIG, 0x01); + CS2100_REGWRITE(CS2100_FUNC_CONFIG_1, 0x08); + CS2100_REGWRITE(CS2100_FUNC_CONFIG_2, 0x00); //0x10 for always gen clock even when unlocked + + /* Read back and check */ +#if XCORE_200_MC_AUDIO_HW_VERSION < 2 + CS2100_REGREAD_ASSERT(CS2100_DEVICE_CONFIG_1, data, 0x05); +#else + CS2100_REGREAD_ASSERT(CS2100_DEVICE_CONFIG_1, data, 0x07); +#endif + CS2100_REGREAD_ASSERT(CS2100_GLOBAL_CONFIG, data, 0x01); + CS2100_REGREAD_ASSERT(CS2100_FUNC_CONFIG_1, data, 0x08); + CS2100_REGREAD_ASSERT(CS2100_FUNC_CONFIG_2, data, 0x00); +} + +/* Setup PLL multiplier */ +void PllMult(unsigned output, unsigned ref) +{ + unsigned char data[1] = {0}; + + /* PLL expects 12:20 format, convert output and ref to 12:20 */ + /* Shift up the dividend by 12 to retain format... */ + unsigned mult = (unsigned) ((((unsigned long long)output) << 32) / (((unsigned long long)ref) << 20)); + + CS2100_REGWRITE(CS2100_RATIO_1, (mult >> 24) & 0xFF); + CS2100_REGWRITE(CS2100_RATIO_2, (mult >> 16) & 0xFF); + CS2100_REGWRITE(CS2100_RATIO_3, (mult >> 8) & 0xFF); + CS2100_REGWRITE(CS2100_RATIO_4, (mult & 0xFF)); + + /* Read back and check */ + CS2100_REGREAD_ASSERT(CS2100_RATIO_1, data, ((mult >> 24) & 0xFF)); + CS2100_REGREAD_ASSERT(CS2100_RATIO_2, data, ((mult >> 16) & 0xFF)); + CS2100_REGREAD_ASSERT(CS2100_RATIO_3, data, ((mult >> 8) & 0xFF)); + CS2100_REGREAD_ASSERT(CS2100_RATIO_4, data, (mult & 0xFF)); +} +#endif + +#if !(defined(SPDIF_RX) || defined(ADAT_RX)) && defined(USE_FRACTIONAL_N) +on tile[AUDIO_IO_TILE] : out port p_pll_clk = PORT_PLL_REF; +on tile[AUDIO_IO_TILE] : clock clk_pll_sync = XS1_CLKBLK_5; +#endif + +void wait_us(int microseconds) +{ + timer t; + unsigned time; + + t :> time; + t when timerafter(time + (microseconds * 100)) :> void; +} + +void AudioHwInit(chanend ?c_codec) +{ +#if !(defined(SPDIF_RX) || defined(ADAT_RX)) && defined(USE_FRACTIONAL_N) + /* Output a fixed sync clock to the pll */ + configure_clock_rate(clk_pll_sync, 100, 100/(PLL_SYNC_FREQ/1000000)); + configure_port_clock_output(p_pll_clk, clk_pll_sync); + start_clock(clk_pll_sync); +#endif + + /* Init the i2c module */ + i2c_shared_master_init(r_i2c); + + /* Assert reset to ADC and DAC */ + set_gpio(P_GPIO_DAC_RST_N, 0); + set_gpio(P_GPIO_ADC_RST_N, 0); + + /* 0b11 : USB B */ + /* 0b01 : Lightning */ + /* 0b10 : USB A */ +#ifdef USB_SEL_A + set_gpio(P_GPIO_USB_SEL0, 0); + set_gpio(P_GPIO_USB_SEL1, 1); +#else + set_gpio(P_GPIO_USB_SEL0, 1); + set_gpio(P_GPIO_USB_SEL1, 1); +#endif + +#ifdef USE_FRACTIONAL_N + /* If we have any digital input then use the external PLL - selected via MUX */ + set_gpio(P_GPIO_PLL_SEL, 1); + + /* Initialise external PLL */ + PllInit(); +#endif + +#ifdef IAP + /* Enable VBUS output */ + set_gpio(P_GPIO_VBUS_EN, 1); +#endif +} + +/* Configures the external audio hardware for the required sample frequency. + * See gpio.h for I2C helper functions and gpio access + */ +void AudioHwConfig(unsigned samFreq, unsigned mClk, chanend ?c_codec, unsigned dsdMode, + unsigned sampRes_DAC, unsigned sampRes_ADC) +{ + unsigned char data[1] = {0}; + + /* Put ADC and DAC into reset */ + set_gpio(P_GPIO_ADC_RST_N, 0); + set_gpio(P_GPIO_DAC_RST_N, 0); + + /* Set master clock select appropriately */ +#if defined(USE_FRACTIONAL_N) + /* Configure external fractional-n clock multiplier for 300Hz -> mClkFreq */ + PllMult(mClk, PLL_SYNC_FREQ); +#endif + /* Allow some time for mclk to lock and MCLK to stabilise - this is important to avoid glitches at start of stream */ + { + timer t; + unsigned time; + t :> time; + t when timerafter(time+AUDIO_PLL_LOCK_DELAY) :> void; + } + +#if defined(USE_FRACTIONAL_N) + while(1) + { + /* Read Unlock Indicator in PLL as sanity check... */ + CS2100_REGREAD(CS2100_DEVICE_CONTROL, data); + if(!(data[0] & 0x80)) + { + break; + } + } +#else + if (mClk == MCLK_441) + { + set_gpio(P_GPIO_MCLK_FSEL, 0); + } + else + { + set_gpio(P_GPIO_MCLK_FSEL, 1); //mClk = MCLK_48 + } + + /* Allow MCLK to settle */ + wait_us(20000); +#endif + +#if 1 + if((dsdMode == DSD_MODE_NATIVE) || (dsdMode == DSD_MODE_DOP)) + { + /* Enable DSD 8ch out mode on mux */ + //set_gpio(p_adrst_cksel_dsd, P_DSD_MODE, 1); + + /* DAC out out reset, note ADC left in reset in for DSD mode */ + set_gpio(P_GPIO_DAC_RST_N, 1); + + /* Configure DAC values required for DSD mode */ + + /* 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 1 for DSD + * bit[4:1] : DAC Pair Disable (DACx_DIS) : All Dac Pairs enabled + * bit[0] : Power Down (PDN) : Powered down + */ + DAC_REGWRITE(CS4384_MODE_CTRL, 0xe1); + + if (samFreq > 3000000) + { + /* DSD128 */ + /* DSD Control (Address: 0x04) */ + /* bit[7:5] : DSD Digital Inteface Format (DSD_DIF) : 128x over samples with 4x MCLK + * bit[4] : Direct DSD Conversion: Set to 0, data sent to DSD processor + * bit[3] : Static DSD detect : 1 for enabled + * bit[2] : Invalid DSD Detect : 1 for enabled + * bit[1] : DSD Phase Modulation Mode Select + * bit[0] : DSD Phase Modulation Enable + */ + DAC_REGWRITE(CS4384_DSD_CTRL, 0b11001100); + } + else + { + /* DSD64 */ + /* DSD Control (Address: 0x04) */ + /* bit[7:5] : DSD Digital Inteface Format (DSD_DIF) : 64x over samples with 8x MCLK + * bit[4] : Direct DSD Conversion: Set to 0, data sent to DSD processor + * bit[3] : Static DSD detect : 1 for enabled + * bit[2] : Invalid DSD Detect : 1 for enabled + * bit[1] : DSD Phase Modulation Mode Select + * bit[0] : DSD Phase Modulation Enable + */ + DAC_REGWRITE(CS4384_DSD_CTRL, 0b01001100); + } + + /* 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 not freeze + * bit[5] : PCM/DSD Selection (DSD/PCM) : Set to 1 for DSD + * bit[4:1] : DAC Pair Disable (DACx_DIS) : All Dac Pairs enabled + * bit[0] : Power Down (PDN) : Power down disabled + */ + DAC_REGWRITE(CS4384_MODE_CTRL, 0xA0); + + /* Note: ADC kept in reset, no config sent. DSD mode is output only 0*/ + } + else + { + /* dsdMode == 0 */ + /* Set MUX to PCM mode (muxes ADC I2S data lines) */ + set_gpio(P_GPIO_DSD_MODE, 0); + + /* Take ADC out of reset */ + set_gpio(P_GPIO_ADC_RST_N, 1); + + { + unsigned dif = 0, mode = 0; +#ifdef I2S_MODE_TDM + dif = 0x02; /* TDM */ +#else + dif = 0x01; /* I2S */ +#endif + +#ifdef CODEC_MASTER + /* Note, only the ADC device supports being I2S master. + * Set ADC as master and run DAC as slave */ + if(samFreq < 54000) + mode = 0x00; /* Single-speed Mode Master */ + else if(samFreq < 108000) + mode = 0x01; /* Double-speed Mode Master */ + else if(samFreq < 216000) + mode = 0x02; /* Quad-speed Mode Master */ +#else + mode = 0x03; /* Slave mode all speeds */ +#endif + + /* 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); + +#ifdef CODEC_MASTER + /* Allow some time for clocks from ADC to become stable */ + wait_us(500); +#endif + + /* Configure DAC with PCM values. Note 2 writes to mode control to enable/disable freeze/power down */ + set_gpio(P_GPIO_DAC_RST_N, 1);//De-assert DAC reset + + wait_us(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); + +#ifdef I2S_MODE_TDM + /* PCM Control (Address: 0x03) */ + /* bit[7:4] : Digital Interface Format (DIF) : 0b1100 for TDM + * bit[3:2] : Reserved + * bit[1:0] : Functional Mode (FM) : 0x11 for auto-speed detect (32 to 200kHz) + */ + DAC_REGWRITE(CS4384_PCM_CTRL, 0b11000011); +#else + /* 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); +#endif + + /* 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); + } +#endif + return; +} +//: + +#endif diff --git a/tests/i2s_loopback/xk_216_mc/cs2100.h b/tests/i2s_loopback/xk_216_mc/cs2100.h new file mode 100644 index 00000000..197799ee --- /dev/null +++ b/tests/i2s_loopback/xk_216_mc/cs2100.h @@ -0,0 +1,11 @@ +#define CS2100_I2C_DEVICE_ADDR (0x9c>>1) + +#define CS2100_DEVICE_CONTROL 0x02 +#define CS2100_DEVICE_CONFIG_1 0x03 +#define CS2100_GLOBAL_CONFIG 0x05 +#define CS2100_RATIO_1 0x06 +#define CS2100_RATIO_2 0x07 +#define CS2100_RATIO_3 0x08 +#define CS2100_RATIO_4 0x09 +#define CS2100_FUNC_CONFIG_1 0x16 +#define CS2100_FUNC_CONFIG_2 0x17 diff --git a/tests/i2s_loopback/xk_216_mc/cs4384.h b/tests/i2s_loopback/xk_216_mc/cs4384.h new file mode 100644 index 00000000..bb9500d8 --- /dev/null +++ b/tests/i2s_loopback/xk_216_mc/cs4384.h @@ -0,0 +1,31 @@ +#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/tests/i2s_loopback/xk_216_mc/cs5368.h b/tests/i2s_loopback/xk_216_mc/cs5368.h new file mode 100644 index 00000000..fb1ff91d --- /dev/null +++ b/tests/i2s_loopback/xk_216_mc/cs5368.h @@ -0,0 +1,17 @@ +#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/tests/i2s_loopback/xk_216_mc/gpio_access.c b/tests/i2s_loopback/xk_216_mc/gpio_access.c new file mode 100644 index 00000000..19cc75f4 --- /dev/null +++ b/tests/i2s_loopback/xk_216_mc/gpio_access.c @@ -0,0 +1,41 @@ +// Copyright (c) 2016, XMOS Ltd, All rights reserved +#ifdef HARDWARE +#include +#include "gpio_access.h" + +void p_gpio_lock() +{ +} + +void p_gpio_unlock() +{ +} + +unsigned p_gpio_peek() +{ + unsigned portId, x; + + asm("ldw %0, dp[p_gpio]":"=r"(portId)); + asm volatile("peek %0, res[%1]":"=r"(x):"r"(portId)); + + return x; +} + +void p_gpio_out(unsigned x) +{ + unsigned portId; + + asm("ldw %0, dp[p_gpio]":"=r"(portId)); + asm volatile("out res[%0], %1"::"r"(portId),"r"(x)); +} + +void set_gpio(unsigned bit, unsigned value) +{ + unsigned port_shadow; + port_shadow = p_gpio_peek(); // Read port pin value + if (value == 0) port_shadow &= ~bit; // If writing a 0, generate mask and AND with current val + else port_shadow |= bit; // Else use mask and OR to set bit + p_gpio_out(port_shadow); // Write back to port. Will make port an output if not already +} + +#endif diff --git a/tests/i2s_loopback/xk_216_mc/gpio_access.h b/tests/i2s_loopback/xk_216_mc/gpio_access.h new file mode 100644 index 00000000..25fc5a59 --- /dev/null +++ b/tests/i2s_loopback/xk_216_mc/gpio_access.h @@ -0,0 +1,52 @@ +// Copyright (c) 2016, XMOS Ltd, All rights reserved +#ifndef __gpio_access_h__ +#define __gpio_access_h__ + +#include "customdefines.h" + +#if XCORE_200_MC_AUDIO_HW_VERSION == 2 + +/* 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.*/ + +#else + +/* 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_ADC_RST_N (1 << 2) +#define P_GPIO_USB_SEL0 (1 << 3) +#define P_GPIO_USB_SEL1 (1 << 4) +#define P_GPIO_VBUS_EN (1 << 5) +#define P_GPIO_MCLK_FSEL (1 << 6) /* Select frequency on Phaselink clock. 0 = 24.576MHz for 48k, 1 = 22.5792MHz for 44.1k.*/ +#define P_GPIO_PLL_SEL (1 << 7) /* 1 = CS2100, 0 = Phaselink clock source */ + +#endif + + +/*LED array defines*/ +#define LED_ALL_ON 0xf00f +#define LED_SQUARE_BIG 0x9009 +#define LED_SQUARE_SML 0x6006 +#define LED_ROW_1 0xf001 +#define LED_ROW_2 0xf003 +#define LED_ROW_3 0xf007 +#define ALL_OFF 0x0000 +// LED array masks +#define LED_MASK_COL_OFF 0x7fff +#define LED_MASK_DISABLE 0xffff + +void set_gpio(unsigned bit, unsigned value); +void p_gpio_lock(); +void p_gpio_unlock(); +unsigned p_gpio_peek(); +void p_gpio_out(unsigned x); + +#endif // __gpio_access_h__ diff --git a/tests/i2s_loopback/xk_216_mc/xk-audio-216-mc.xn b/tests/i2s_loopback/xk_216_mc/xk-audio-216-mc.xn new file mode 100644 index 00000000..a9f765b0 --- /dev/null +++ b/tests/i2s_loopback/xk_216_mc/xk-audio-216-mc.xn @@ -0,0 +1,96 @@ + + + Board + XS2 MC Audio + + tileref tile[2] + tileref usb_tile + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + --> + --> + + + + + + + + + + + + + + + + + + --> + --> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/i2s_loopback/xua_conf.h b/tests/i2s_loopback/xua_conf.h new file mode 100644 index 00000000..57ee8e0d --- /dev/null +++ b/tests/i2s_loopback/xua_conf.h @@ -0,0 +1,26 @@ +// Copyright (c) 2016, XMOS Ltd, All rights reserved +#ifndef __custom_defines_h__ +#define __custom_defines_h__ + +#define EXCLUDE_USB_AUDIO_MAIN +#define NUM_PDM_MICS 0 +#define XUD_TILE 1 +#define AUDIO_IO_TILE 0 +#define MIXER 0 +#define MCLK_441 (512 * 44100) +#define MCLK_48 (512 * 48000) +#define MIN_FREQ 44100 +#define MAX_FREQ 192000 +#define SPDIF_TX_INDEX 0 +#define VENDOR_STR "XMOS" +#define VENDOR_ID 0x20B1 +#define PRODUCT_STR_A2 "Test device" +#define PRODUCT_STR_A1 "Test device" +#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 // __custom_defines_h__ diff --git a/tests/pass.expect b/tests/pass.expect new file mode 100644 index 00000000..7ef22e9a --- /dev/null +++ b/tests/pass.expect @@ -0,0 +1 @@ +PASS diff --git a/tests/runtests.py b/tests/runtests.py new file mode 100755 index 00000000..36198102 --- /dev/null +++ b/tests/runtests.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python2.7 +import xmostest +import os.path + +if __name__ == "__main__": + + + xmostest.init() + + xmostest.register_group("lib_xua", + "i2s_loopback_sim_tests", + "I2S loopback simulator tests", + + """ +Tests are performed by running the audiohub code connected to a +loopback plugin +""") + + xmostest.runtests() + + xmostest.finish() diff --git a/tests/runtests.pyc b/tests/runtests.pyc new file mode 100644 index 00000000..814ee1c1 Binary files /dev/null and b/tests/runtests.pyc differ diff --git a/tests/test_i2s_loopback.py b/tests/test_i2s_loopback.py new file mode 100644 index 00000000..7b69b062 --- /dev/null +++ b/tests/test_i2s_loopback.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python +import xmostest + +def runtest_one_config(env, format, i2s_role, num_chans_in, num_chans_out, sample_rate): + testlevel = 'smoke' + resources = xmostest.request_resource('xsim') + + binary = 'i2s_loopback/bin/{env}_{format}_{i2s_role}_{num_chans_in}in_{num_chans_out}out_{sample_rate}/i2s_loopback_{env}_{format}_{i2s_role}_{num_chans_in}in_{num_chans_out}out_{sample_rate}.xe'.format(env=env, format=format, i2s_role=i2s_role, num_chans_in=num_chans_in, num_chans_out=num_chans_out, sample_rate=sample_rate) + tester = xmostest.ComparisonTester(open('pass.expect'), + 'sw_vocalfusion', + 'digital_audio_tests', + 'i2s_loopback', + {'env':env, + 'format':format, + 'i2s_role':i2s_role, + 'num_chans_in':num_chans_in, + 'num_chans_out':num_chans_out, + 'sample_rate':sample_rate}) + tester.set_min_testlevel(testlevel) + loopback_args= '-port tile[0] XS1_PORT_1M 1 0 -port tile[0] XS1_PORT_1I 1 0 ' + \ + '-port tile[0] XS1_PORT_1N 1 0 -port tile[0] XS1_PORT_1J 1 0 ' + \ + '-port tile[0] XS1_PORT_1O 1 0 -port tile[0] XS1_PORT_1K 1 0 ' + \ + '-port tile[0] XS1_PORT_1P 1 0 -port tile[0] XS1_PORT_1L 1 0 ' + \ + '-port tile[0] XS1_PORT_1A 1 0 -port tile[0] XS1_PORT_1F 1 0 ' + if i2s_role == 'slave': + loopback_args += '-port tile[0] XS1_PORT_1B 1 0 -port tile[0] XS1_PORT_1H 1 0 ' #bclk + loopback_args += '-port tile[0] XS1_PORT_1C 1 0 -port tile[0] XS1_PORT_1G 1 0 ' #lrclk + + max_cycles = 1500000 #enough to reach the 10 skip + 100 test in sim at 48kHz + xmostest.run_on_simulator(resources['xsim'], binary, tester=tester, simargs=['--max-cycles', str(max_cycles), '--plugin', 'LoopbackPort.dll', loopback_args]) + +def runtest(): + runtest_one_config('simulation', 'i2s', 'master', 2, 2, '48khz') + #runtest_one_config('simulation', 'i2s', 'slave', 2, 2, '48khz') + + #runtest_one_config('simulation', 'i2s', 'master', 2, 2, '192khz') + #runtest_one_config('simulation', 'i2s', 'slave', 2, 2, '192khz') + + #runtest_one_config('simulation', 'i2s', 'master', 8, 8, '48khz') + #runtest_one_config('simulation', 'i2s', 'slave', 8, 8, '48khz') + + #runtest_one_config('simulation', 'i2s', 'master', 8, 8, '192khz') + #runtest_one_config('simulation', 'i2s', 'slave', 8, 8, '192khz') + + #runtest_one_config('simulation', 'tdm', 'master', 8, 8, '48khz') + #runtest_one_config('simulation', 'tdm', 'slave', 8, 8, '48khz') + + #runtest_one_config('simulation', 'tdm', 'master', 16, 16, '48khz') + #runtest_one_config('simulation', 'tdm', 'slave', 16, 16, '48khz') diff --git a/tests/test_i2s_loopback.pyc b/tests/test_i2s_loopback.pyc new file mode 100644 index 00000000..a4933456 Binary files /dev/null and b/tests/test_i2s_loopback.pyc differ diff --git a/tests/test_results.csv b/tests/test_results.csv new file mode 100644 index 00000000..e69de29b