├── .cproject ├── .project ├── LICENSE.txt ├── Makefile ├── README.rst ├── app_par_audio_dsp ├── Makefile ├── bin │ └── XR-USB-AUDIO-2.0-MC │ │ └── app_par_audio_DSP.xe ├── src │ ├── XR-USB-AUDIO-2.0-MC.xn │ ├── biquad_cascade_eq.xc │ ├── biquad_cascade_eq_asm.S │ ├── biquad_coeffs.h │ ├── biquad_crossover.xc │ ├── biquad_crossover_asm.S │ ├── codec.xc │ ├── coeffs.xc │ ├── commands.h │ ├── crossover.h │ ├── defines.h │ ├── delays.xc │ ├── eq_client.h │ ├── eq_client.xc │ ├── eq_dsp_wrapper.xc │ ├── equaliser.h │ ├── equaliser_coeffs.h │ ├── i2c.xc │ ├── iis.h │ ├── iis.xc │ ├── main.xc │ ├── pll.xc │ ├── signal_overrides.h │ ├── signal_overrides.xc │ ├── sine.xc │ └── xai2_ports.h └── timing_checks.xta └── doc └── CHANGELOG /.cproject: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | xmake 151 | -f .makefile 152 | all 153 | true 154 | false 155 | true 156 | 157 | 158 | xmake 159 | -f Makefile 160 | app_uart_test.all 161 | true 162 | true 163 | true 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | ap_par_audio_dsp 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.cdt.managedbuilder.core.genmakebuilder 10 | clean,full,incremental, 11 | 12 | 13 | ?name? 14 | 15 | 16 | 17 | org.eclipse.cdt.make.core.append_environment 18 | true 19 | 20 | 21 | org.eclipse.cdt.make.core.autoBuildTarget 22 | all 23 | 24 | 25 | org.eclipse.cdt.make.core.buildArguments 26 | -f Makefile 27 | 28 | 29 | org.eclipse.cdt.make.core.buildCommand 30 | xmake 31 | 32 | 33 | org.eclipse.cdt.make.core.buildLocation 34 | ${workspace_loc:/ap_par_audio_dsp} 35 | 36 | 37 | org.eclipse.cdt.make.core.cleanBuildTarget 38 | clean 39 | 40 | 41 | org.eclipse.cdt.make.core.contents 42 | org.eclipse.cdt.make.core.activeConfigSettings 43 | 44 | 45 | org.eclipse.cdt.make.core.enableAutoBuild 46 | false 47 | 48 | 49 | org.eclipse.cdt.make.core.enableCleanBuild 50 | true 51 | 52 | 53 | org.eclipse.cdt.make.core.enableFullBuild 54 | true 55 | 56 | 57 | org.eclipse.cdt.make.core.fullBuildTarget 58 | all 59 | 60 | 61 | org.eclipse.cdt.make.core.stopOnError 62 | true 63 | 64 | 65 | org.eclipse.cdt.make.core.useDefaultBuildCmd 66 | false 67 | 68 | 69 | 70 | 71 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder 72 | 73 | 74 | 75 | 76 | 77 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature 78 | org.eclipse.cdt.managedbuilder.core.managedBuildNature 79 | org.eclipse.cdt.core.cnature 80 | 81 | 82 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Software License Agreement 2 | 3 | Copyright (c) 2011, , All rights reserved. 4 | 5 | The copyright holders hereby grant to any person obtaining a copy of this software (the "Software") and/or its associated 6 | documentation files (the Documentation), the perpetual, irrevocable (except in the case of breach of this license) no-cost, 7 | royalty free, sublicensable rights to use, copy, modify, merge, publish, display, publicly perform, distribute, and/or 8 | sell copies of the Software and the Documentation, together or separately, and to permit persons to whom the Software and/or 9 | Documentation is furnished to do so, subject to the following conditions: 10 | 11 | . Redistributions of the Software in source code must retain the above copyright notice, this list of conditions and the 12 | following disclaimers. 13 | 14 | . Redistributions of the Software in binary form must reproduce the above copyright notice, this list of conditions and 15 | the following disclaimers in the documentation and/or other materials provided with the distribution. 16 | 17 | . Redistributions of the Documentation must retain the above copyright notice, this list of conditions and the following 18 | disclaimers. 19 | 20 | Neither the name of XMOS, nor the names of its contributors may be used to endorse or promote products derived from this 21 | Software or the Documentation without specific prior written permission of the copyright holder. 22 | 23 | THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 24 | LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 26 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR DOCUMENTATION OR THE USE OF OR OTHER 27 | DEALINGS WITH THE SOFTWARE OR DOCUMENTATION. 28 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # This Makefile acts as a composite builder for all the elements 2 | # of this repository. 3 | 4 | # It has target patterns for all, clean and test for sub-directories of the 5 | # form dir.target e.g. calling: 6 | # 7 | # xmake app_uart_demo.all 8 | # 9 | # will execute 'xmake all' in the app_uart_demo sub-directory. 10 | # 11 | # In addition the following targets are defined: 12 | # 13 | # all: 14 | # 15 | # This target will build all the applications listed in the BUILD_SUBDIRS 16 | # variable. 17 | # 18 | # plugins: 19 | # 20 | # This target will build all the plugins listed in the PLUGIN_SUBDIRS 21 | # variable 22 | # 23 | # clean: 24 | # 25 | # This target will clean all the applications listed in the BUILD_SUBDIRS 26 | # variable. 27 | # 28 | # clean_plugins: 29 | # 30 | # This target will clean all the plugins listed in the PLUGIN_SUBDIRS 31 | # variable. 32 | # 33 | # test: 34 | # 35 | # This target will make the test make target in all the directories 36 | # listed in TEST_SUBDIRS. 37 | # 38 | 39 | 40 | # This variable should contain a space separated list of all 41 | # the directories containing buildable applications (usually 42 | # prefixed with the app_ prefix) 43 | BUILD_SUBDIRS = app_par_audio_dsp 44 | 45 | # This variable should contain a space separated list of all 46 | # the directories containing buildable plugins (usually 47 | # prefixed with the plugin_ prefix) 48 | PLUGIN_SUBDIRS = 49 | 50 | # This variable should contain a space separated list of all 51 | # the directories containing applications with a 'test' make target 52 | TEST_SUBDIRS = 53 | 54 | # Provided that the above variables are set you shouldn't need to modify 55 | # the targets below here. 56 | 57 | %.all: 58 | cd $* && xmake all 59 | 60 | %.clean: 61 | cd $* && xmake clean 62 | 63 | %.test: 64 | cd $* && xmake test 65 | 66 | all: $(foreach x, $(BUILD_SUBDIRS), $x.all) 67 | plugins: $(foreach x, $(PLUGIN_SUBDIRS), $x.all) 68 | clean: $(foreach x, $(BUILD_SUBDIRS), $x.clean) 69 | clean_plugins: $(foreach x, $(PLUGIN_SUBDIRS), $x.clean) 70 | test: $(foreach x, $(TEST_SUBDIRS), $x.test) 71 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | XMOS Parallel Audio DSP example 2 | 3 | :Stable release: 0.6.0 `versioning `_) 4 | 5 | :Status: Alpha 6 | 7 | :Maintainer: ThomasGmeinder 8 | 9 | :Description: Configurable Application example for parallel DSP processing of several audio channels 10 | 11 | Key Features 12 | ============ 13 | 14 | * Up to 6 channels in, 8 channels out 15 | IN 1/2 : processed by eq_wrapper (see below), OUT 1/2 16 | IN 2/3 : processed by crossover thread (see below), OUT 2/3 (below 500Hz), OUT 4/5 (above 500Hz) 17 | Note: OUT 6/7 are the same as OUT 4/5 on the HW. 18 | Note: delays is a thread that can be plugged instead of crossover or eq_wrapper 19 | * Audio DSP using concurrent threads. 2 Threads processing 4 channels each in this example. 20 | * Two configurations of Biquad filter (derived from https://github.com/xcore/sc_dsp_filters) 21 | biquad_cascade_eq.xc : Cascade of 5 Biquads used for the 5-band equaliser 22 | biquad_crossover.xc. Single Biquad configured as either highshelf or lowshelf filter 23 | * Audio samples are communicated to a configurable set of DSP threads using streaming channels 24 | * Delay buffer example (see delay_bufs and shared_mem_dsp.c) 25 | * Configurability. See User Guide Section 26 | * Wealth of Debug Features (See Debug section) 27 | 28 | To Do 29 | ===== 30 | 31 | * 32 | 33 | Firmware Overview 34 | ================= 35 | * HW Platform: XR-USB-AUDIO-2.0-MC 36 | 37 | * DSP Threads 38 | 39 | - eq_wrapper : 5-Band Equaliser processing 2 channels using peak EQ filters. Receives control commands to change EQ settings. Can send level metering data 40 | 41 | - crossover : Using highshelf filter to suppress frequs above 500Hz, lowshelf filter to suppress freqs below 500Hz 42 | Note: crossover_proc produces 2 output channels (low and high freqs) from 1 input channel 43 | 44 | - delays : Using a delay buffer, delays audio of left channel by 5000 samples (0.1 seconds at 48kHz) 45 | 46 | - eq_client : Periodically Changes Equaliser setup on the fly by switching between different Equaliser Presets. 47 | 48 | * Other Threads 49 | 50 | - iis 51 | I2S interface to codec. up to 6 channels in, 8 channels out 52 | See Audio Data Flow 53 | 54 | - mswait : wait a number of milliseconds 55 | 56 | - clkgen : generates PLL input clock 57 | 58 | * Audio Data Flow (per channel) 59 | 60 | - iis thread 61 | ouputs samples of NUM_IN stereo channels over NUM_IN streaming channels 62 | inputs samples of NUM_OUT stereo channels over NUM_IN streaming channels 63 | 64 | - DSP threads 65 | input samples over streaming channel(s) 66 | process the stream on a per-sample basis 67 | output samples over streaming channel(s). 68 | 69 | * Input-Output latency: <= one sample period 70 | 71 | * Coefficient Generation 72 | 73 | - All coefficients were created with https://github.com/xcore/sc_dsp_filters 74 | 75 | - The Makefile configurations can be found in in the source code next to the coefficients 76 | 77 | Debug Support 78 | ================= 79 | * XScope Probes for Equaliser input and output (Oscilloscope view of sample streams from HW in realtime) 80 | * Ability to override ADC audio input with custom reference signals. 81 | * Option to run on simulator (for development/debug without HW) 82 | * Audio Loopback (to test iis interface) 83 | * XTA timing checks 84 | The checks are run at compile time (see timing_checks.xta script) 85 | To analyse the routes it in the GUI, Click "Timing->Time" and then run the .xta script 86 | The script is automatically run at compile time, does the xta check and prints a summary: 87 | 88 | User Guide 89 | ================= 90 | * DSP threads can be plugged in to process selected channels on core0 as shown in main() 91 | * Configuration Options 92 | 93 | - Number of input and output channels (NUM_IN, NUM_OUT) 94 | 95 | - Set of DSP threads (see main()) 96 | 97 | - EQ Bands (EQ_BANKS) 98 | 99 | - Optimised assembly Biquad (ASM_BIQUAD_EQ) 100 | 101 | - Debug Switches (see Debug Switches in defines.h). 102 | Note: To use XScope XDE 11.2 tools are required. Add xscope library to compile. 103 | Note: Make sure NUM_IN and NUM_OUT matches the set of DSP threads connected to the streaming channels 104 | 105 | * Tool aspects 106 | - Device options (Simulator or Hardware) can be selected in "Run Configurations" and "Debug Configurations" 107 | - For more information see Tools User Guide. 108 | 109 | Known Issues 110 | ============ 111 | * Level metering output from Equaliser not activated 112 | * Limited testing of configuration space. E.g. only at 48kHz 113 | * biquadAsmXover not operational. Must be changed to take coefficient object as argument 114 | * Unexpected data type errors from XScope 115 | 116 | 117 | Required Repositories 118 | ================ 119 | 120 | * xcommon git\@github.com:xcore/xcommon.git 121 | 122 | Support 123 | ======= 124 | 125 | Issues may be submitted via the Issues tab in this github repo. Response to any issues submitted as at the discretion of the maintainer for this line. -------------------------------------------------------------------------------- /app_par_audio_dsp/Makefile: -------------------------------------------------------------------------------- 1 | # The TARGET variable determines what target system the application is 2 | # compiled for. It either refers to an XN file in the source directories 3 | # or a valid argument for the --target option when compiling. 4 | 5 | TARGET = XR-USB-AUDIO-2.0-MC 6 | 7 | # The APP_NAME variable determines the name of the final .xe file. It should 8 | # not include the .xe postfix. If left blank the name will default to 9 | # the project name 10 | 11 | APP_NAME = app_par_audio_DSP 12 | 13 | # The flags passed to xcc when building the application 14 | # You can also set the following to override flags for a particular language: 15 | # 16 | # XCC_XC_FLAGS, XCC_C_FLAGS, XCC_ASM_FLAGS, XCC_CPP_FLAGS 17 | # 18 | # If the variable XCC_MAP_FLAGS is set it overrides the flags passed to 19 | # xcc for the final link (mapping) stage. 20 | 21 | XCC_FLAGS = -O2 -Xmapper --map -Xmapper MAPFILE -lxscope -g 22 | 23 | # The USED_MODULES variable lists other module used by the application. 24 | 25 | USED_MODULES = 26 | 27 | #============================================================================= 28 | # The following part of the Makefile includes the common build infrastructure 29 | # for compiling XMOS applications. You should not need to edit below here. 30 | 31 | 32 | # Use the main Makefile from module_xmos_common 33 | include ../../xcommon/module_xcommon/build/Makefile.common 34 | 35 | # The final target of the build. This is usually dependent on a binary file 36 | # in the $(BIN_DIR) directory e.g. 37 | # 38 | # all : $(BIN_DIR)/my_app.xe 39 | 40 | all: $(BIN_DIR)/$(APP_NAME).xe 41 | @echo Build Complete 42 | 43 | 44 | clean: clean_common 45 | -------------------------------------------------------------------------------- /app_par_audio_dsp/bin/XR-USB-AUDIO-2.0-MC/app_par_audio_DSP.xe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xcore/ap_par_audio_dsp/32c8a2c5de3595dde109d9ba1b9e44867c95c490/app_par_audio_dsp/bin/XR-USB-AUDIO-2.0-MC/app_par_audio_DSP.xe -------------------------------------------------------------------------------- /app_par_audio_dsp/src/XR-USB-AUDIO-2.0-MC.xn: -------------------------------------------------------------------------------- 1 | 2 | 5 | Device 6 | XS1-L2A-QF124 7 | 8 | 9 | core stdcore[2] 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /app_par_audio_dsp/src/biquad_cascade_eq.xc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011, XMOS Ltd, All rights reserved 2 | // This software is freely distributable under a derivative of the 3 | // University of Illinois/NCSA Open Source License posted in 4 | // LICENSE.txt and at 5 | 6 | #include 7 | #include "equaliser.h" 8 | #include "equaliser_coeffs.h" 9 | #include "defines.h" 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | void init_equaliser(biquad_cascade_state_eq_s &state, int zeroDb) { 16 | for(int i = 0; i <= EQ_BANKS; i++) { 17 | state.b[i].xn1 = 0; 18 | state.b[i].xn2 = 0; 19 | } 20 | for(int i = 0; i < EQ_BANKS; i++) { 21 | state.b[i].db = zeroDb; 22 | state.desiredDb[i] = zeroDb; 23 | } 24 | state.adjustCounter = EQ_BANKS; 25 | state.adjustDelay = 0; 26 | } 27 | 28 | extern int biquadAsmEQ(int xn, biquad_cascade_state_eq_s &state); 29 | 30 | #pragma unsafe arrays 31 | int biquad_cascade_eq(biquad_cascade_state_eq_s &state, int xn, int power[]) { 32 | 33 | // difference equation 34 | //y(n) = b_0 * x(n) + b_1 * x(n-1) + b_2 * x(n-2) - a_1 * y(n-1) - a_2 * y(n-2) 35 | 36 | #ifdef ASM_BIQUAD_EQ 37 | //#error "biquadAsmEQ integration not working yet" 38 | #pragma xta call "call_0" 39 | xn = biquadAsmEQ(xn, state); 40 | #else 41 | unsigned int ynl; 42 | int ynh; 43 | #pragma loop unroll (5) 44 | for(int j=0; j> FRACTIONALBITS); 54 | } else if (ynh < 0) { 55 | ynh = 0x80000000; 56 | } else { 57 | ynh = 0x7fffffff; 58 | } 59 | state.b[j].xn2 = state.b[j].xn1; 60 | state.b[j].xn1 = xn; 61 | 62 | xn = ynh; 63 | 64 | power[j] += (ynh * ynh) >> 10; //for graphic equaliser display 65 | } 66 | state.b[EQ_BANKS].xn2 = state.b[EQ_BANKS].xn1; 67 | state.b[EQ_BANKS].xn1 = ynh; 68 | if (state.adjustDelay > 0) { 69 | state.adjustDelay--; 70 | } else { 71 | state.adjustCounter--; 72 | if (state.b[state.adjustCounter].db > state.desiredDb[state.adjustCounter]) { 73 | state.b[state.adjustCounter].db--; 74 | } 75 | if (state.b[state.adjustCounter].db < state.desiredDb[state.adjustCounter]) { 76 | state.b[state.adjustCounter].db++; 77 | } 78 | if (state.adjustCounter == 0) { 79 | state.adjustCounter = EQ_BANKS; 80 | } 81 | state.adjustDelay = 40; 82 | } 83 | #endif 84 | 85 | return xn; 86 | }; 87 | 88 | void update_eq_gain(int bank, int gain, biquad_cascade_state_eq_s &state) 89 | { 90 | state.desiredDb[bank] = gain; 91 | } 92 | -------------------------------------------------------------------------------- /app_par_audio_dsp/src/biquad_cascade_eq_asm.S: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011, XMOS Ltd, All rights reserved 2 | // This software is freely distributable under a derivative of the 3 | // University of Illinois/NCSA Open Source License posted in 4 | // LICENSE.txt and at 5 | 6 | 7 | #include 8 | #include "defines.h" 9 | 10 | #define NWORDS 8 11 | 12 | // .cc_top biquadAsm, biquadAsm.func 13 | 14 | .globl biquadAsmEQ 15 | .globl biquadAsmEQ.nstackwords 16 | .linkset biquadAsmEQ.nstackwords,NWORDS 17 | 18 | biquadAsmEQ: 19 | entsp NWORDS 20 | stw r4, sp[0] 21 | stw r5, sp[1] 22 | stw r6, sp[2] 23 | stw r7, sp[3] 24 | stw r8, sp[4] 25 | stw r9, sp[5] 26 | stw r10, sp[6] 27 | 28 | // r0: xn 29 | // r1: &state.xn12dbs[j] 30 | // r2: state.xn1[j] 31 | // r3: state.xn2[j] 32 | // r4: tmp 33 | // r5: FRACTIONALBITS 34 | // r6: 1<<(FRACTIONALBITS-1) 35 | // r7: &coeffs[0][j] 36 | // r8: j 37 | // r9: &coeffs[state.dbs[j]][j] 38 | // r10: ynl 39 | // r11: ynh 40 | 41 | ldc r5, FRACTIONALBITS 42 | ldaw r7, dp[eq_coeffs] 43 | ldc r8, 0 44 | 45 | ldw r2, r1[0] 46 | ldw r3, r1[1] 47 | 48 | ldc r11, 0 49 | 50 | ldc r6, 1 51 | shl r6, r6, r5 52 | shr r6, r6, 1 53 | 54 | 55 | loop: 56 | ldc r4, 5*EQ_BANKS // words per filter * BANKS 57 | ldw r9, r1[2] 58 | or r10, r6, r6 59 | mul r4, r4, r9 60 | ldaw r9, r7[r4] 61 | 62 | ldw r4, r9[2] 63 | maccs r11, r10, r4, r0 64 | ldw r4, r9[3] 65 | maccs r11, r10, r4, r2 66 | ldw r4, r9[4] 67 | maccs r11, r10, r4, r3 68 | 69 | stw r2, r1[1] // xn2 = xn1 70 | stw r0, r1[0] // xn1 = xn 71 | ldaw r1, r1[3] 72 | 73 | ldw r4, r9[0] 74 | ldw r2, r1[0] 75 | maccs r11, r10, r4, r2 76 | ldw r4, r9[1] 77 | ldw r3, r1[1] 78 | maccs r11, r10, r4, r3 79 | 80 | ldaw r7, r7[5] // Words per filter 81 | 82 | or r4, r11, r11 83 | sext r4, r5 84 | eq r4, r11, r4 85 | bt r4, resultFits 86 | ldc r0, 0x80 87 | shl r0, r0, 24 88 | lsu r4, r11, r4 89 | sub r0, r0, r4 90 | bu resultDone 91 | 92 | resultFits: 93 | ldc r4, 32-FRACTIONALBITS 94 | shl r11, r11, r4 95 | shr r10, r10, r5 96 | or r0, r11, r10 97 | 98 | resultDone: 99 | add r8, r8, 1 100 | eq r11, r8, EQ_BANKS 101 | bf r11, loop // clears r11 102 | 103 | stw r2, r1[1] 104 | stw r0, r1[0] 105 | 106 | ldc r11, 3*EQ_BANKS 107 | ldaw r9, r1[-r11] 108 | ldc r11, 3 109 | ldaw r1, r1[r11] 110 | ldw r11, r1[0] 111 | bt r11, decrementDelay 112 | ldc r11, 40 113 | stw r11, r1[0] 114 | ldw r11, r1[1] 115 | sub r11, r11, 1 116 | stw r11, r1[1] 117 | bt r11, checkdB 118 | ldc r4, EQ_BANKS 119 | stw r4, r1[1] 120 | checkdB: 121 | ldc r10, 3 //r9 poinst to db/xn1/xn2, r1 points to adjustdelay, counter, desdb[] 122 | mul r10, r11, r10 123 | ldaw r9, r9[r10] 124 | ldw r10, r9[2] 125 | add r11, r11, 2 126 | ldw r8, r1[r11] 127 | magicLabel: 128 | lsu r7, r8, r10 129 | bt r7, decrement 130 | lsu r7, r10, r8 131 | bf r7, allDone 132 | add r10, r10, 1 133 | stw r10, r9[2] 134 | bu allDone 135 | decrement: 136 | sub r10, r10, 1 137 | stw r10, r9[2] 138 | bu allDone 139 | 140 | decrementDelay: 141 | sub r11, r11, 1 142 | stw r11, r1[0] 143 | allDone: 144 | 145 | ldw r4, sp[0] 146 | ldw r5, sp[1] 147 | ldw r6, sp[2] 148 | ldw r7, sp[3] 149 | ldw r8, sp[4] 150 | ldw r9, sp[5] 151 | ldw r10, sp[6] 152 | retsp NWORDS 153 | 154 | // .cc_bottom biquadAsmEQ.func 155 | -------------------------------------------------------------------------------- /app_par_audio_dsp/src/biquad_coeffs.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011, XMOS Ltd, All rights reserved 2 | // This software is freely distributable under a derivative of the 3 | // University of Illinois/NCSA Open Source License posted in 4 | // LICENSE.txt and at 5 | 6 | #ifndef BIQUAD_COEFFS_H_ 7 | #define BIQUAD_COEFFS_H_ 8 | 9 | typedef struct {int a1, a2, b0, b1, b2;} 10 | coeffs_s; 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /app_par_audio_dsp/src/biquad_crossover.xc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011, XMOS Ltd, All rights reserved 2 | // This software is freely distributable under a derivative of the 3 | // University of Illinois/NCSA Open Source License posted in 4 | // LICENSE.txt and at 5 | 6 | #include 7 | #include 8 | #include "biquad_coeffs.h" 9 | #include "crossover.h" 10 | #include "defines.h" 11 | 12 | 13 | void init_xover(biquad_state_xover_s &state, int zeroDb) { 14 | for(int i = 0; i <= XOVER_BANKS; i++) { 15 | state.b[i].xn1 = 0; 16 | state.b[i].xn2 = 0; 17 | } 18 | for(int i = 0; i < XOVER_BANKS; i++) { 19 | state.b[i].db = zeroDb; 20 | state.desiredDb[i] = zeroDb; 21 | } 22 | state.adjustCounter = XOVER_BANKS; 23 | state.adjustDelay = 0; 24 | } 25 | 26 | extern int biquadAsmXover(int xn, biquad_state_xover_s &state); 27 | 28 | #pragma unsafe arrays 29 | int biquad_xover(biquad_state_xover_s &state, coeffs_s &coeffs, int xn) { 30 | // difference equation 31 | //y(n) = b_0 * x(n) + b_1 * x(n-1) + b_2 * x(n-2) - a_1 * y(n-1) - a_2 * y(n-2) 32 | 33 | #ifdef ASM_BIQUAD_XOVER 34 | #error "biquadAsmXover not operational yet, Must be changed to take coefficient object as argument" 35 | //xn = biquadAsmXover(xn, state); 36 | #else 37 | unsigned int ynl; 38 | int ynh; 39 | #pragma loop unroll(1) 40 | for(int j=0; j> FRACTIONALBITS); 50 | } else if (ynh < 0) { 51 | ynh = 0x80000000; 52 | } else { 53 | ynh = 0x7fffffff; 54 | } 55 | state.b[j].xn2 = state.b[j].xn1; 56 | state.b[j].xn1 = xn; 57 | 58 | xn = ynh; 59 | } 60 | state.b[XOVER_BANKS].xn2 = state.b[XOVER_BANKS].xn1; 61 | state.b[XOVER_BANKS].xn1 = ynh; 62 | #endif 63 | 64 | return xn; 65 | } 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /app_par_audio_dsp/src/biquad_crossover_asm.S: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011, XMOS Ltd, All rights reserved 2 | // This software is freely distributable under a derivative of the 3 | // University of Illinois/NCSA Open Source License posted in 4 | // LICENSE.txt and at 5 | 6 | 7 | #include 8 | #include "defines.h" 9 | 10 | #define NWORDS 8 11 | 12 | // .cc_top biquadAsm, biquadAsm.func 13 | 14 | .globl biquadAsmXover 15 | .globl biquadAsmXover.nstackwords 16 | .linkset biquadAsmXover.nstackwords,NWORDS 17 | 18 | biquadAsmXover: 19 | entsp NWORDS 20 | stw r4, sp[0] 21 | stw r5, sp[1] 22 | stw r6, sp[2] 23 | stw r7, sp[3] 24 | stw r8, sp[4] 25 | stw r9, sp[5] 26 | stw r10, sp[6] 27 | 28 | // r0: xn 29 | // r1: &state.xn12dbs[j] 30 | // r2: state.xn1[j] 31 | // r3: state.xn2[j] 32 | // r4: tmp 33 | // r5: FRACTIONALBITS 34 | // r6: 1<<(FRACTIONALBITS-1) 35 | // r7: &coeffs[0][j] 36 | // r8: j 37 | // r9: &coeffs[state.dbs[j]][j] 38 | // r10: ynl 39 | // r11: ynh 40 | 41 | ldc r5, FRACTIONALBITS 42 | ldaw r7, dp[eq_coeffs] 43 | ldc r8, 0 44 | 45 | ldw r2, r1[0] 46 | ldw r3, r1[1] 47 | 48 | ldc r11, 0 49 | ldc r6, 1 50 | shl r6, r6, r5 51 | shr r6, r6, 1 52 | 53 | loop: 54 | ldc r4, 5*XOVER_BANKS // words per filter * BANKS 55 | ldw r9, r1[2] 56 | or r10, r6, r6 57 | mul r4, r4, r9 58 | ldaw r9, r7[r4] 59 | 60 | ldw r4, r9[0] 61 | maccs r11, r10, r4, r0 62 | ldw r4, r9[1] 63 | maccs r11, r10, r4, r2 64 | ldw r4, r9[2] 65 | maccs r11, r10, r4, r3 66 | 67 | stw r2, r1[1] 68 | stw r0, r1[0] 69 | ldaw r1, r1[3] 70 | 71 | ldw r4, r9[3] 72 | ldw r2, r1[0] 73 | maccs r11, r10, r4, r2 74 | ldw r4, r9[4] 75 | ldw r3, r1[1] 76 | maccs r11, r10, r4, r3 77 | 78 | ldaw r7, r7[5] // Words per filter 79 | 80 | or r4, r11, r11 81 | sext r4, r5 82 | eq r4, r11, r4 83 | bt r4, resultFits 84 | ldc r0, 0x80 85 | shl r0, r0, 24 86 | lsu r4, r11, r4 87 | sub r0, r0, r4 88 | bu resultDone 89 | 90 | resultFits: 91 | ldc r4, 32-FRACTIONALBITS 92 | shl r11, r11, r4 93 | shr r10, r10, r5 94 | or r0, r11, r10 95 | 96 | resultDone: 97 | add r8, r8, 1 98 | eq r11, r8, XOVER_BANKS 99 | bf r11, loop // clears r11 100 | 101 | stw r2, r1[1] 102 | stw r0, r1[0] 103 | 104 | ldc r11, 3*XOVER_BANKS 105 | ldaw r9, r1[-r11] 106 | ldc r11, 3 107 | ldaw r1, r1[r11] 108 | ldw r11, r1[0] 109 | bt r11, decrementDelay 110 | ldc r11, 40 111 | stw r11, r1[0] 112 | ldw r11, r1[1] 113 | sub r11, r11, 1 114 | stw r11, r1[1] 115 | bt r11, checkdB 116 | stw r4, r1[1] 117 | checkdB: 118 | ldc r10, 3 //r9 poinst to db/xn1/xn2, r1 points to adjustdelay, counter, desdb[] 119 | mul r10, r11, r10 120 | ldaw r9, r9[r10] 121 | ldw r10, r9[2] 122 | add r11, r11, 2 123 | ldw r8, r1[r11] 124 | magicLabel: 125 | lsu r7, r8, r10 126 | bt r7, decrement 127 | lsu r7, r10, r8 128 | bf r7, allDone 129 | add r10, r10, 1 130 | stw r10, r9[2] 131 | bu allDone 132 | decrement: 133 | sub r10, r10, 1 134 | stw r10, r9[2] 135 | bu allDone 136 | 137 | decrementDelay: 138 | sub r11, r11, 1 139 | stw r11, r1[0] 140 | allDone: 141 | 142 | ldw r4, sp[0] 143 | ldw r5, sp[1] 144 | ldw r6, sp[2] 145 | ldw r7, sp[3] 146 | ldw r8, sp[4] 147 | ldw r9, sp[5] 148 | ldw r10, sp[6] 149 | retsp NWORDS 150 | 151 | // .cc_bottom biquadAsmXover.func 152 | -------------------------------------------------------------------------------- /app_par_audio_dsp/src/codec.xc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011, XMOS Ltd, All rights reserved 2 | // This software is freely distributable under a derivative of the 3 | // University of Illinois/NCSA Open Source License posted in 4 | // LICENSE.txt and at 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | int regrd(int addr, int device, out port scl, port sda); 11 | void regwr(int addr, int data, int device, out port scl, port sda); 12 | 13 | #define REGRD_CODEC(reg) regrd(reg, 0x90, scl, sda) 14 | #define REGWR_CODEC(reg, val) regwr(reg, val, 0x90, scl, sda) 15 | 16 | void reset_codec(out port rst) 17 | { 18 | int mode = 0x2; // clocks disconnected 19 | int sel = 0x0; // XCore sync rather than BNC input 20 | timer tmr; 21 | unsigned t; 22 | tmr :> t; 23 | 24 | rst <: 0x8 | mode | sel; 25 | t += 10000; 26 | tmr when timerafter(t) :> void; 27 | 28 | rst <: 0x0 | mode | sel; 29 | t += 10000; 30 | tmr when timerafter(t) :> void; 31 | 32 | rst <: 0x8 | mode | sel; 33 | t += 10000; 34 | tmr when timerafter(t) :> void; 35 | } 36 | 37 | void init_codec(out port scl, port sda, int codec_is_master, int mic_input, int instr_input) 38 | { 39 | // Interface Formats Register (Address 04h) 40 | // 7 Freeze Controls (FREEZE) = 0 41 | // 6 Auxiliary Digital Interface Format (AUX_DIF) = 0 42 | // 5:3 DAC Digital Interface Format (DAC_DIF) = 001 (I2S, 24bit) 43 | // 2:0 ADC Digital Interface Format (ADC_DIF) = 001 (I2S, 24bit) 44 | REGWR_CODEC(0x04, 0b00001001); 45 | assert(REGRD_CODEC(0x04) == 0b00001001); 46 | 47 | // ADC Control & DAC De-Emphasis (Address 05h) 48 | // 7 ADC1-2_HPF FREEZE = 0 49 | // 6 ADC3_HPF FREEZE = 0 50 | // 5 DAC_DEM = 0 51 | // 4 ADC1_SINGLE = 1(single ended) 52 | // 3 ADC2_SINGLE = 1 53 | // 2 ADC3_SINGLE = 1 54 | // 1 AIN5_MUX = microphone input 55 | // 0 AIN6_MUX = instrument input 56 | REGWR_CODEC(0x05, 0b00011100 | (mic_input << 1) | instr_input); 57 | assert(REGRD_CODEC(0x05) == (0b00011100 | (mic_input << 1) | instr_input)); 58 | 59 | // Functional Mode (Address 03h) 60 | if (codec_is_master) { 61 | // 7:6 DAC Functional Mode (single speed master) = 00 62 | // 5:4 ADC Functional Mode (single speed master) = 00 63 | // 3:1 MCLK Frequency (2.048-25.6MHz, MCK=512WCK) = 010 64 | // 0 Reserved 65 | REGWR_CODEC(0x03, 0b00000100); 66 | assert(REGRD_CODEC(0x03) == 0b00000100); 67 | } 68 | else { 69 | // 7:6 DAC Functional Mode (slave auto detect) = 11 70 | // 5:4 ADC Functional Mode (slave auto detect) = 11 71 | // 3:1 MCLK Frequency (2.048-25.6MHz, MCK=512WCK) = 010 72 | // 0 Reserved 73 | REGWR_CODEC(0x03, 0b11110100); 74 | assert(REGRD_CODEC(0x03) == 0b11110100); 75 | } 76 | 77 | #ifndef SHARED_SILENT 78 | printstr("CODEC present and configured as "); 79 | if (codec_is_master) 80 | printstrln("master"); 81 | else 82 | printstrln("slave"); 83 | 84 | if (mic_input) { 85 | printstrln("microphone input enabled"); 86 | } 87 | if (instr_input) { 88 | printstrln("instrument input enabled"); 89 | } 90 | #endif 91 | } 92 | -------------------------------------------------------------------------------- /app_par_audio_dsp/src/coeffs.xc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011, XMOS Ltd, All rights reserved 2 | // This software is freely distributable under a derivative of the 3 | // University of Illinois/NCSA Open Source License posted in 4 | // LICENSE.txt and at 5 | 6 | //Generated code - do not edit. 7 | 8 | // First index is the dbLevel, in steps of 1.000000 db, first entry is -20.000000 db 9 | // Second index is the filter number - this filter has 1 banks 10 | // Each structure instantiation contains the five coefficients for each biquad: 11 | // -a1/a0, -a2/a0, b0/a0, b1/a0, b2/a0; all numbers are stored in 8.24 fixed point 12 | #include "biquad_coeffs.h" 13 | 14 | #if 0 15 | 16 | 17 | // Lowshelf filter, 500Hz cutoff 18 | coeffs_s lowshelf[DBS][BANKS] = { 19 | { //Db: -20.000000 20 | { 30800578, -14232837, 15860196, -30894842, 15055593}, 21 | }, 22 | { //Db: -19.000000 23 | { 30878261, -14299262, 15909259, -30966249, 15079230}, 24 | }, 25 | { //Db: -18.000000 26 | { 30953775, -14364112, 15957779, -31035745, 15101578}, 27 | }, 28 | { //Db: -17.000000 29 | { 31027179, -14427415, 16005790, -31103372, 15122647}, 30 | }, 31 | { //Db: -16.000000 32 | { 31098531, -14489199, 16053327, -31169169, 15142451}, 33 | }, 34 | { //Db: -15.000000 35 | { 31167887, -14549493, 16100421, -31233177, 15160998}, 36 | }, 37 | { //Db: -14.000000 38 | { 31235301, -14608326, 16147109, -31295433, 15178301}, 39 | }, 40 | { //Db: -13.000000 41 | { 31300826, -14665725, 16193423, -31355976, 15194368}, 42 | }, 43 | { //Db: -12.000000 44 | { 31364514, -14721719, 16239398, -31414842, 15209209}, 45 | }, 46 | { //Db: -11.000000 47 | { 31426415, -14776336, 16285068, -31472067, 15222832}, 48 | }, 49 | { //Db: -10.000000 50 | { 31486579, -14829603, 16330467, -31527687, 15235244}, 51 | }, 52 | { //Db: -9.000000 53 | { 31545052, -14881549, 16375630, -31581735, 15246453}, 54 | }, 55 | { //Db: -8.000000 56 | { 31601882, -14932201, 16420590, -31634244, 15256464}, 57 | }, 58 | { //Db: -7.000000 59 | { 31657114, -14981585, 16465384, -31685247, 15265285}, 60 | }, 61 | { //Db: -6.000000 62 | { 31710793, -15029730, 16510045, -31734774, 15272920}, 63 | }, 64 | { //Db: -5.000000 65 | { 31762961, -15076661, 16554609, -31782856, 15279372}, 66 | }, 67 | { //Db: -4.000000 68 | { 31813660, -15122404, 16599111, -31829521, 15284647}, 69 | }, 70 | { //Db: -3.000000 71 | { 31862931, -15166986, 16643587, -31874799, 15288747}, 72 | }, 73 | { //Db: -2.000000 74 | { 31910813, -15210432, 16688072, -31918715, 15291675}, 75 | }, 76 | { //Db: -1.000000 77 | { 31957346, -15252768, 16732603, -31961296, 15293431}, 78 | }, 79 | { //Db: 0.000000 80 | { 32002567, -15294018, 16777216, -32002567, 15294018}, 81 | }, 82 | }; 83 | 84 | // Lowshelf filter, 500Hz cutoff 85 | coeffs_s highshelf[DBS][BANKS] = { 86 | { //Db: -20.000000 87 | { 32681149, -15926091, 1774726, -3258144, 1505576}, 88 | }, 89 | { //Db: -19.000000 90 | { 32655666, -15901903, 1985134, -3653615, 1691935}, 91 | }, 92 | { //Db: -18.000000 93 | { 32629440, -15877048, 2220585, -4096954, 1901193}, 94 | }, 95 | { //Db: -17.000000 96 | { 32602450, -15851508, 2484063, -4593937, 2136148}, 97 | }, 98 | { //Db: -16.000000 99 | { 32574674, -15825266, 2778912, -5151038, 2399934}, 100 | }, 101 | { //Db: -15.000000 102 | { 32546089, -15798304, 3108870, -5775506, 2696066}, 103 | }, 104 | { //Db: -14.000000 105 | { 32516672, -15770603, 3478124, -6475463, 3028486}, 106 | }, 107 | { //Db: -13.000000 108 | { 32486398, -15742144, 3891358, -7260007, 3401612}, 109 | }, 110 | { //Db: -12.000000 111 | { 32455242, -15712909, 4353814, -8139328, 3820397}, 112 | }, 113 | { //Db: -11.000000 114 | { 32423179, -15682878, 4871360, -9124838, 4290393}, 115 | }, 116 | { //Db: -10.000000 117 | { 32390183, -15652031, 5450561, -10229320, 4817823}, 118 | }, 119 | { //Db: -9.000000 120 | { 32356227, -15620348, 6098763, -11467088, 5409661}, 121 | }, 122 | { //Db: -8.000000 123 | { 32321283, -15587807, 6824189, -12854171, 6073723}, 124 | }, 125 | { //Db: -7.000000 126 | { 32285323, -15554389, 7636035, -14408520, 6818766}, 127 | }, 128 | { //Db: -6.000000 129 | { 32248317, -15520071, 8544596, -16150231, 7654605}, 130 | }, 131 | { //Db: -5.000000 132 | { 32210234, -15484831, 9561386, -18101808, 8592235}, 133 | }, 134 | { //Db: -4.000000 135 | { 32171045, -15448648, 10699290, -20288442, 9643971}, 136 | }, 137 | { //Db: -3.000000 138 | { 32130717, -15411498, 11972721, -22738336, 10823613}, 139 | }, 140 | { //Db: -2.000000 141 | { 32089217, -15373359, 13397804, -25483061, 12146615}, 142 | }, 143 | { //Db: -1.000000 144 | { 32046512, -15334207, 14992577, -28557954, 13630288}, 145 | }, 146 | { //Db: 0.000000 147 | { 32002567, -15294018, 16777216, -32002567, 15294018}, 148 | }, 149 | }; 150 | 151 | #endif 152 | -------------------------------------------------------------------------------- /app_par_audio_dsp/src/commands.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011, XMOS Ltd, All rights reserved 2 | // This software is freely distributable under a derivative of the 3 | // University of Illinois/NCSA Open Source License posted in 4 | // LICENSE.txt and at 5 | 6 | #ifndef commands_H_ 7 | #define commands_H_ 8 | 9 | /* 10 | * com.xmos.simplegfxeq protocol demo 11 | */ 12 | #define COMMAND_XMOS_SIMPLEGFXEQ_RequestBandFreqs 0x01 13 | #define COMMAND_XMOS_SIMPLEGFXEQ_SetBandFreqs 0x02 14 | #define COMMAND_XMOS_SIMPLEGFXEQ_SetBandBoost 0x03 15 | #define COMMAND_XMOS_SIMPLEGFXEQ_BandPowerOutput 0x04 16 | 17 | #define COMMAND_XMOS_SIMPLEGFXEQ_RequestBandFreqs_messageSize 1 18 | #define COMMAND_XMOS_SIMPLEGFXEQ_SetBandFreqs_messageSize 2 + (5 * 4) //2 + number of bands * size of int 19 | #define COMMAND_XMOS_SIMPLEGFXEQ_SetBandBoost_messageSize 3 20 | #define COMMAND_XMOS_SIMPLEGFXEQ_BandPowerOutput_messageSize 1 + (5 * 2) //2 + (number of bands * number of channels) 21 | 22 | #define COMMAND_XMOS_SIMPLEGFXEQ_SetBandFreqs_DataOffset_messageType 0 23 | #define COMMAND_XMOS_SIMPLEGFXEQ_SetBandFreqs_DataOffset_NumberOfBands 1 24 | #define COMMAND_XMOS_SIMPLEGFXEQ_SetBandFreqs_DataOffset_BandFreqsStart 2 25 | 26 | #define COMMAND_XMOS_SIMPLEGFXEQ_SetBandBoost_DataOffset_messageType 0 27 | #define COMMAND_XMOS_SIMPLEGFXEQ_SetBandBoost_DataOffset_bandNumber 1 28 | #define COMMAND_XMOS_SIMPLEGFXEQ_SetBandBoost_DataOffset_boostValue 2 29 | 30 | #define COMMAND_XMOS_SIMPLEGFXEQ_BandPowerOutput_DataOffset_messageType 0 31 | #define COMMAND_XMOS_SIMPLEGFXEQ_BandPowerOutput_DataOffset_PowerOutputStart 1 32 | 33 | #define MAX_PENDING_MESSAGE_SIZE 8 34 | #define COMMANDS_TO_SEND_OFFSET 0 35 | #define DSP_CONTROL_STATE_OFFSET 1 36 | #define UPDATE_BOOST_SETTINGS_START_OFFSET 2 37 | 38 | #define DSP_CONTROL_STATE_MASK 0x01 39 | #define SEND_BAND_FREQS_MASK 0x02 40 | #define UPDATE_BOOST_SETTINGS_MASK 0x04 41 | #define PROTOCOL_INIT_COMPLETE_MASK 0x08 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /app_par_audio_dsp/src/crossover.h: -------------------------------------------------------------------------------- 1 | /* 2 | * xover.h 3 | * 4 | * Created on: Mar 28, 2011 5 | * Author: thomas_mac 6 | */ 7 | 8 | #include "defines.h" 9 | #include "biquad_coeffs.h" 10 | 11 | #ifndef XOVER_H_ 12 | #define XOVER_H_ 13 | 14 | typedef struct { 15 | struct {int xn1; int xn2; int db;} b[XOVER_BANKS+1]; 16 | int adjustDelay; 17 | int adjustCounter; 18 | int desiredDb[XOVER_BANKS]; 19 | } biquad_state_xover_s; 20 | 21 | void init_xover(biquad_state_xover_s &state, int zeroDb); 22 | 23 | int biquad_xover(biquad_state_xover_s &state, coeffs_s &coeffs, int xn); 24 | 25 | #endif /* XOVER_H_ */ 26 | -------------------------------------------------------------------------------- /app_par_audio_dsp/src/defines.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011, XMOS Ltd, All rights reserved 2 | // This software is freely distributable under a derivative of the 3 | // University of Illinois/NCSA Open Source License posted in 4 | // LICENSE.txt and at 5 | 6 | 7 | #ifndef DEFINES_H_ 8 | #define DEFINES_H_ 9 | 10 | /********* Debug Switches: ********/ 11 | //#define DEBUG // debug tracing 12 | //#define INPUT_OVERRIDE 13 | //#define USE_XSCOPE 14 | //#define AUDIO_LOOPBACK 15 | //#define XSIM // run on simulator 16 | 17 | /********* Config Switches: ********/ 18 | #define EQ_BANKS 5 19 | #define EQ_UPDATE_PERIOD 1000000; //thread cycles 20 | #define XOVER_BANKS 1 21 | 22 | #define ASM_BIQUAD_EQ 23 | //#define ASM_BIQUAD_XOVER 24 | 25 | #define NUM_EQ_THREADS 1 26 | 27 | #define NUM_IN 2 // input stereo channels 28 | #define NUM_OUT 3 // output stereo channels 29 | #define NUM_INP_ACHANS NUM_IN*2 30 | #define NUM_OUTP_ACHANS NUM_OUT*2 31 | 32 | #define DELAY_SAMPLES 5120 33 | 34 | #define NUM_DELAY_BUFS 2 35 | 36 | #define DELAY_BUF_SIZE DELAY_SAMPLES 37 | 38 | #define MCK_BCK_RATIO 8 39 | // With MCK 24.576MHz and MCK_BCK_RATIO 8 40 | // sample rate = 24.576MHz / 8 / 64 = 48kHz 41 | 42 | #define DSP_COMMAND_CONTROL_STATE 0x10 43 | #define DSP_COMMAND_XMOS_SIMPLEGFXEQ_MESSAGE 0x11 44 | 45 | #define FRACTIONALBITS 24 46 | 47 | #endif /* DEFINES_H_ */ 48 | -------------------------------------------------------------------------------- /app_par_audio_dsp/src/delays.xc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011, XMOS Ltd, All rights reserved 2 | // This software is freely distributable under a derivative of the 3 | // University of Illinois/NCSA Open Source License posted in 4 | // LICENSE.txt and at 5 | 6 | 7 | #include 8 | #include "defines.h" 9 | 10 | signed delay_bufs[NUM_DELAY_BUFS][DELAY_BUF_SIZE]; 11 | unsigned delay_buf_wr_idx[NUM_DELAY_BUFS] = {0,0}; 12 | 13 | int delay_proc(unsigned achan_idx, signed in_sample, unsigned delay_buf_idx, unsigned delay) { 14 | signed out_sample; 15 | 16 | int delay_buf_rd_idx; 17 | 18 | delay_bufs[delay_buf_idx][delay_buf_wr_idx[delay_buf_idx]] = in_sample; 19 | //from_dsp_bufs[1][prev_sel_from_buf][i] = to_dsp_bufs[1][prev_sel_to_buf][i]; 20 | 21 | delay_buf_rd_idx = delay_buf_wr_idx[delay_buf_idx] - delay; 22 | 23 | if(delay_buf_rd_idx < 0) { 24 | // wrap read index 25 | delay_buf_rd_idx = DELAY_SAMPLES + delay_buf_rd_idx; // add negative number 26 | } 27 | 28 | out_sample = delay_bufs[delay_buf_idx][delay_buf_rd_idx]; 29 | 30 | // Update Write Index 31 | delay_buf_wr_idx[delay_buf_idx]++; 32 | if(delay_buf_wr_idx[delay_buf_idx] >= DELAY_SAMPLES) { 33 | // wrap write index 34 | delay_buf_wr_idx[delay_buf_idx] = 0; 35 | } 36 | 37 | return out_sample; 38 | } 39 | -------------------------------------------------------------------------------- /app_par_audio_dsp/src/eq_client.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011, XMOS Ltd, All rights reserved 2 | // This software is freely distributable under a derivative of the 3 | // University of Illinois/NCSA Open Source License posted in 4 | // LICENSE.txt and at 5 | 6 | 7 | #ifndef EQ_CLIENT_H_ 8 | #define EQ_CLIENT_H_ 9 | 10 | 11 | #endif /* EQ_CLIENT_H_ */ 12 | /** eq_client 13 | * 14 | * Client to control Equaliser Settings 15 | * 16 | * \param c_ctrl[] : array of control channels 17 | * \param c_DSP_activity[] : array of DSP monitoring channels 18 | **/ 19 | void eq_client(chanend c_ctrl[], streaming chanend c_DSP_activity[]); 20 | 21 | 22 | /** eq_client 23 | * 24 | * Set new desiredDb index for a chosen frequency band 25 | * See eq_dsp_wrapper.xc for the complementary side of the communication protocol. 26 | * 27 | * \param c_ctrl : control channel 28 | * \param band : filter bank index [0..EQ_BANKS-1] 29 | * \param db_idx : Db index [0..20] ([0dB..-20dB]) 30 | **/ 31 | void eq_client_set_band_db(chanend c_ctrl, char band, char db_idx); 32 | -------------------------------------------------------------------------------- /app_par_audio_dsp/src/eq_client.xc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011, XMOS Ltd, All rights reserved 2 | // This software is freely distributable under a derivative of the 3 | // University of Illinois/NCSA Open Source License posted in 4 | // LICENSE.txt and at 5 | 6 | #include 7 | #include "eq_client.h" 8 | #include "defines.h" 9 | #include "commands.h" 10 | 11 | #define NUM_PRESETS 3 12 | char equaliser_presets[NUM_PRESETS][EQ_BANKS] = { 13 | {20, 20, 20, 20, 20}, // all 0 dB 14 | {0, 5, 10, 15, 20}, // ramp: -20dB, -15dB, -10dB, -dB, 0dB 15 | {20, 15, 5, 15, 20}, // reduce mid ranges: -0dB, -5, -15dB, -5dB, 0dB 16 | }; 17 | unsigned preset = 0; 18 | 19 | void eq_client(chanend c_ctrl[], streaming chanend c_DSP_activity[]) { 20 | timer tmr; 21 | unsigned time; 22 | unsigned update_cnt; 23 | tmr :> time; 24 | 25 | while(1) { 26 | time += EQ_UPDATE_PERIOD; 27 | tmr when timerafter(time) :> void; 28 | 29 | // Example: Periodically change DB settings for frequency bands 30 | // of equaliser connected to c_ctrl[0] 31 | for(int i=0; i 5 | 6 | #include 7 | #include 8 | #include "equaliser.h" 9 | #include "commands.h" 10 | #include 11 | #include 12 | 13 | typedef struct 14 | { 15 | char namestring[20]; 16 | int value; 17 | } eqStruct; 18 | 19 | // Equalizer options. 20 | int numEqs = 2; 21 | eqStruct eqNames[2] = { 22 | {"Off", 0}, 23 | {"On", 1}, 24 | }; 25 | 26 | // Date received on the audio channels is always "streaming" 27 | #ifdef USE_STREAMING_CHANNELS 28 | #define AUDIO_STREAMING_INPUT(c,v) c :> v 29 | #define AUDIO_STREAMING_OUTPUT(c,v) c <: v 30 | #else 31 | #define AUDIO_STREAMING_INPUT(c,v) inuint_byref(c, v) 32 | #define AUDIO_STREAMING_OUTPUT(c,v) outuint(c, v) 33 | #endif 34 | 35 | #define iOS_REFRESH_DELAY 1000000 36 | 37 | void eq_block_proc(int power[], biquad_cascade_state_eq_s &eq_stat, unsigned achan_idx); 38 | void dsp_bypass(unsigned achan_idx); 39 | 40 | #pragma unsafe arrays 41 | void eq_wrapper(unsigned idx, chanend cCtrl, streaming chanend cDSPActivityOutput, streaming chanend c_in, streaming chanend c_out) 42 | { 43 | char command; 44 | //char controlState = 0; 45 | char controlState = 1; 46 | 47 | signed sample; 48 | unsigned sample_count = 0; 49 | 50 | biquad_cascade_state_eq_s r, l; 51 | 52 | int leftPower[EQ_BANKS], rightPower[EQ_BANKS]; 53 | 54 | #ifdef USE_XSCOPE 55 | int si, so; // just for xscope 56 | xscope_register (2, 57 | XSCOPE_CONTINUOUS , " Equaliser input (left)", XSCOPE_INT , "int", 58 | XSCOPE_CONTINUOUS , " Equaliser output (left) ", XSCOPE_INT , "int" 59 | ); 60 | #endif 61 | 62 | #ifdef ENFORCE_FAST_MODE 63 | set_thread_fast_mode_on(); 64 | #endif 65 | 66 | // Do any required DSP initialisation here 67 | init_equaliser(l, 20); // index 20 is 0 dB 68 | init_equaliser(r, 20); 69 | 70 | c_out <: 0; // output happens first in iis thread 71 | 72 | while (1) 73 | { 74 | select 75 | { 76 | case c_in :> sample : 77 | { 78 | 79 | for(int i =0; i < EQ_BANKS; i++) 80 | { 81 | leftPower[i] = 0; 82 | rightPower[i] = 0; 83 | } 84 | if(sample_count & 1) { 85 | 86 | #ifdef USE_XSCOPE 87 | si = sample; // signed not accepted by XScope ? 88 | xscope_probe_data_pred(0, sample); 89 | #endif 90 | #ifdef DEBUG 91 | printf("EQ input: 0x%x\n",sample); 92 | #endif 93 | 94 | sample = biquad_cascade_eq( 95 | r, 96 | sample, 97 | rightPower 98 | ); 99 | #ifdef USE_XSCOPE 100 | so = sample; // signed not accepted by XScope ? 101 | xscope_probe_data_pred(1, sample); 102 | #endif 103 | #ifdef DEBUG 104 | printf("EQ output: 0x%x\n",sample); 105 | #endif 106 | c_out <: sample; 107 | } else { 108 | c_out <: biquad_cascade_eq( 109 | l, 110 | sample, 111 | leftPower 112 | ); 113 | } 114 | sample_count++; 115 | } 116 | break; 117 | case cCtrl :> command: 118 | switch (command) 119 | { 120 | case DSP_COMMAND_CONTROL_STATE: 121 | cCtrl :> controlState; 122 | // Control information, as defined by eqNames 123 | break; 124 | case DSP_COMMAND_XMOS_SIMPLEGFXEQ_MESSAGE: 125 | { 126 | char message, band, boost; 127 | cCtrl :> message; 128 | if (message == COMMAND_XMOS_SIMPLEGFXEQ_SetBandBoost) 129 | { 130 | cCtrl :> band; 131 | cCtrl :> boost; 132 | update_eq_gain(band, boost, l); 133 | update_eq_gain(band, boost, r); 134 | } 135 | } 136 | break; 137 | default: 138 | break; 139 | } 140 | break; 141 | 142 | case cDSPActivityOutput :> int _: 143 | cDSPActivityOutput <: EQ_BANKS * 2; 144 | for (int i = 0; i < EQ_BANKS; i++) 145 | { 146 | cDSPActivityOutput <: (char)(32 - clz(leftPower[i])); //32 - clz(x) = log_2(x) 147 | cDSPActivityOutput <: (char)(32 - clz(rightPower[i])); 148 | } 149 | break; 150 | 151 | } 152 | 153 | } 154 | } 155 | 156 | -------------------------------------------------------------------------------- /app_par_audio_dsp/src/equaliser.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Module: module_ipod_support 3 | * Version: 1v35alpha1 4 | * Build: e51ffa39ccfdf0ef71ad86838df99eb5ed8916a5 5 | * File: blockBiquad.h 6 | * 7 | * The copyrights, all other intellectual and industrial 8 | * property rights are retained by XMOS and/or its licensors. 9 | * Terms and conditions covering the use of this code can 10 | * be found in the Xmos End User License Agreement. 11 | * 12 | * Copyright XMOS Ltd 2010 13 | * 14 | * In the case where this code is a modification of existing code 15 | * under a separate license, the separate license terms are shown 16 | * below. The modifications to the code are still covered by the 17 | * copyright notice above. 18 | * 19 | **/ 20 | // Copyright (c) 2011, XMOS Ltd, All rights reserved 21 | // This software is freely distributable under a derivative of the 22 | // University of Illinois/NCSA Open Source License posted in 23 | // LICENSE.txt and at 24 | 25 | #include "defines.h" 26 | 27 | #ifndef EQUALISER_H_ 28 | #define EQUALISER_H_ 29 | 30 | #define EQ_DBS 21 31 | 32 | typedef struct { 33 | struct {int xn1; int xn2; int db;} b[EQ_BANKS+1]; 34 | int adjustDelay; 35 | int adjustCounter; 36 | int desiredDb[EQ_BANKS]; 37 | 38 | } biquad_cascade_state_eq_s; 39 | 40 | void init_equaliser(biquad_cascade_state_eq_s &state, int zeroDb); 41 | 42 | int biquad_cascade_eq(biquad_cascade_state_eq_s &state, int xn, int power[]); 43 | 44 | void update_eq_gain(int bank, int gain, biquad_cascade_state_eq_s &state); 45 | 46 | #endif /* EQUALISER_H_ */ 47 | -------------------------------------------------------------------------------- /app_par_audio_dsp/src/equaliser_coeffs.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011, XMOS Ltd, All rights reserved 2 | // This software is freely distributable under a derivative of the 3 | // University of Illinois/NCSA Open Source License posted in 4 | // LICENSE.txt and at 5 | 6 | // Coefficients for a 5-band equaliser 7 | 8 | // Generated with the swc_cascaded_biquad package 9 | // swc_cascaded_biquad Makefile config: Todo 10 | 11 | #include "biquad_coeffs.h" 12 | #include "equaliser.h" 13 | 14 | coeffs_s eq_coeffs[EQ_DBS][EQ_BANKS] = { 15 | { //Db: -20.000000 16 | { 32082704, -15367382, 16182669, -32112672, 15931961}, 17 | { 31655308, -14921534, 15942159, -31655308, 15756591}, 18 | { 29872843, -13260175, 15194548, -29872843, 14842843}, 19 | { 26592459, -10409335, 13911669, -26592459, 13274881}, 20 | { 29331115, -13029027, 919570, -697480, 253038}, 21 | }, 22 | { //Db: -19.000000 23 | { 32144786, -15424449, 16218274, -32172157, 15956020}, 24 | { 31753542, -15019902, 15997146, -31753542, 15799972}, 25 | { 30049030, -13437332, 15294645, -30049030, 14919904}, 26 | { 26877794, -10701044, 14080009, -26877794, 13398251}, 27 | { 29147432, -12885326, 1058603, -847594, 304101}, 28 | }, 29 | { //Db: -18.000000 30 | { 32204257, -15479308, 16252935, -32229223, 15978623}, 31 | { 31846841, -15113330, 16050009, -31846841, 15840538}, 32 | { 30217279, -13606508, 15391446, -30217279, 14992278}, 33 | { 27152844, -10982238, 14244499, -27152844, 13514955}, 34 | { 28955986, -12737091, 1219461, -1026725, 365585}, 35 | }, 36 | { //Db: -17.000000 37 | { 32261227, -15532035, 16286708, -32283964, 15999806}, 38 | { 31935427, -15202037, 16100877, -31935427, 15878377}, 39 | { 30377854, -13767968, 15485126, -30377854, 15060058}, 40 | { 27417723, -11253036, 14405281, -27417723, 13624970}, 41 | { 28756475, -12584264, 1405647, -1240193, 439552}, 42 | }, 43 | { //Db: -16.000000 44 | { 32315799, -15582706, 16319650, -32336469, 16019603}, 45 | { 32019510, -15286236, 16149878, -32019510, 15913574}, 46 | { 30531021, -13921979, 15575860, -30531021, 15123335}, 47 | { 27672573, -11513578, 14562512, -27672573, 13728282}, 48 | { 28548592, -12426797, 1621229, -1494261, 528453}, 49 | }, 50 | { //Db: -15.000000 51 | { 32368074, -15631394, 16351818, -32386822, 16038044}, 52 | { 32099297, -15366133, 16197139, -32099297, 15946209}, 53 | { 30677044, -14068806, 15663827, -30677044, 15182196}, 54 | { 27917552, -11764030, 14716365, -27917552, 13824881}, 55 | { 28332019, -12264648, 1870935, -1796295, 635204}, 56 | }, 57 | { //Db: -14.000000 58 | { 32418147, -15678170, 16383267, -32435107, 16055159}, 59 | { 32174987, -15441926, 16242784, -32174987, 15976359}, 60 | { 30816187, -14208715, 15749207, -30816187, 15236724}, 61 | { 28152841, -12004576, 14867029, -28152841, 13914763}, 62 | { 28106434, -12097786, 2160255, -2154954, 763267}, 63 | }, 64 | { //Db: -13.000000 65 | { 32466111, -15723102, 16414050, -32481403, 16070976}, 66 | { 32246771, -15513809, 16286933, -32246771, 16004092}, 67 | { 30948709, -14341967, 15832184, -30948709, 15286999}, 68 | { 28378637, -12235416, 15014707, -28378637, 13997925}, 69 | { 27871505, -11926192, 2495567, -2580408, 916744}, 70 | }, 71 | { //Db: -12.000000 72 | { 32512055, -15766259, 16444222, -32525787, 16085521}, 73 | { 32314834, -15581965, 16329707, -32314834, 16029474}, 74 | { 31074868, -14468821, 15912940, -31074868, 15333097}, 75 | { 28595151, -12456767, 15159616, -28595151, 14074368}, 76 | { 27626892, -11749856, 2884274, -3084593, 1100499}, 77 | }, 78 | { //Db: -11.000000 79 | { 32556062, -15807705, 16473835, -32568332, 16098816}, 80 | { 32379354, -15646574, 16371224, -32379354, 16052566}, 81 | { 31194917, -14589531, 15991660, -31194917, 15375087}, 82 | { 28802607, -12668858, 15301983, -28802607, 14144091}, 83 | { 27372252, -11568784, 3334970, -3681508, 1320286}, 84 | }, 85 | { //Db: -10.000000 86 | { 32598214, -15847503, 16502940, -32609110, 16110883}, 87 | { 32440501, -15707805, 16411599, -32440501, 16073422}, 88 | { 31309105, -14704349, 16068531, -31309105, 15413033}, 89 | { 29001240, -12871929, 15442052, -29001240, 14207092}, 90 | { 27107233, -11382993, 3857630, -4387560, 1582905}, 91 | }, 92 | { //Db: -9.000000 93 | { 32638590, -15885715, 16531590, -32648188, 16121743}, 94 | { 32498441, -15765824, 16450948, -32498441, 16092092}, 95 | { 31417676, -14813517, 16143740, -31417676, 15446993}, 96 | { 29191291, -13066226, 15580076, -29191291, 14263367}, 97 | { 26831480, -11192518, 4463826, -5221961, 1896389}, 98 | }, 99 | { //Db: -8.000000 100 | { 32677262, -15922400, 16559835, -32685632, 16131412}, 101 | { 32553329, -15820787, 16489382, -32553329, 16108621}, 102 | { 31520866, -14917276, 16217474, -31520866, 15477018}, 103 | { 29373012, -13252007, 15716317, -29373012, 14312906}, 104 | { 26544631, -10997409, 5166976, -6207193, 2270211}, 105 | }, 106 | { //Db: -7.000000 107 | { 32714304, -15957615, 16587725, -32721504, 16139906}, 108 | { 32605317, -15872847, 16527015, -32605317, 16123048}, 109 | { 31618908, -15015858, 16289922, -31618908, 15503152}, 110 | { 29546656, -13429530, 15851051, -29546656, 14355694}, 111 | { 26246324, -10797735, 5982638, -7369542, 2715530}, 112 | }, 113 | { //Db: -6.000000 114 | { 32749783, -15991416, 16615311, -32755864, 16147240}, 115 | { 32654550, -15922148, 16563957, -32654550, 16135407}, 116 | { 31712027, -15109489, 16361274, -31712027, 15525431}, 117 | { 29712480, -13599059, 15984563, -29712480, 14391712}, 118 | { 25936191, -10593583, 6928838, -8739713, 3245483}, 119 | }, 120 | { //Db: -5.000000 121 | { 32783766, -16023857, 16642643, -32788770, 16153426}, 122 | { 32701166, -15968827, 16600317, -32701166, 16145726}, 123 | { 31800441, -15198391, 16431723, -31800441, 15543884}, 124 | { 29870746, -13760861, 16117149, -29870746, 14420928}, 125 | { 25613866, -10385063, 8026456, -10353552, 3875509}, 126 | }, 127 | { //Db: -4.000000 128 | { 32816315, -16054990, 16669770, -32820278, 16158473}, 129 | { 32745296, -16013018, 16636205, -32745296, 16154029}, 130 | { 31884364, -15282776, 16501460, -31884364, 15558532}, 131 | { 30021714, -13915201, 16249113, -30021714, 14443304}, 132 | { 25278981, -10172303, 9299659, -12252859, 4623739}, 133 | }, 134 | { //Db: -3.000000 135 | { 32847490, -16084864, 16696741, -32850439, 16162389}, 136 | { 32787067, -16054846, 16671730, -32787067, 16160332}, 137 | { 31963999, -15362849, 16570680, -31963999, 15569385}, 138 | { 30165644, -14062346, 16380771, -30165644, 14458791}, 139 | { 24931169, - 9955459, 10776413, -14486345, 5511439}, 140 | }, 141 | { //Db: -2.000000 142 | { 32877349, -16113528, 16723606, -32879305, 16165182}, 143 | { 32826599, -16094433, 16707001, -32826599, 16164647}, 144 | { 32039545, -15438812, 16639580, -32039545, 15576448}, 145 | { 30302794, -14202561, 16512449, -30302794, 14467327}, 146 | { 24570069, - 9734708, 12489050, -17110713, 6563518}, 147 | }, 148 | { //Db: -1.000000 149 | { 32905949, -16141030, 16750414, -32906924, 16166856}, 150 | { 32864007, -16131892, 16742127, -32864007, 16166981}, 151 | { 32111194, -15510856, 16708358, -32111194, 15579713}, 152 | { 30433422, -14336107, 16644482, -30433422, 14468841}, 153 | { 24195322, - 9510254, 14474936, -20191914, 7809126}, 154 | }, 155 | { //Db: 0.000000 156 | { 32933341, -16167414, 16777216, -32933341, 16167414}, 157 | { 32899402, -16167335, 16777216, -32899402, 16167335}, 158 | { 32179130, -15579165, 16777216, -32179130, 15579165}, 159 | { 30557780, -14463243, 16777216, -30557780, 14463243}, 160 | { 23806578, - 9282328, 16777216, -23806578, 9282328}, 161 | }, 162 | 163 | }; 164 | -------------------------------------------------------------------------------- /app_par_audio_dsp/src/i2c.xc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011, XMOS Ltd, All rights reserved 2 | // This software is freely distributable under a derivative of the 3 | // University of Illinois/NCSA Open Source License posted in 4 | // LICENSE.txt and at 5 | 6 | #include 7 | #include 8 | 9 | int regrd(int addr, int device, out port scl, port sda) 10 | { 11 | //int Result; 12 | timer gt; 13 | unsigned time; 14 | int Temp, CtlAdrsData, i; 15 | // three device ACK 16 | int ack[3]; 17 | int rdData; 18 | 19 | // initial values. 20 | scl <: 1; 21 | sda <: 1; 22 | sync(sda); 23 | gt :> time; 24 | time += 1000 + 1000; 25 | gt when timerafter(time) :> int _; 26 | // start bit on SDI 27 | scl <: 1; 28 | sda <: 0; 29 | gt :> time; 30 | time += 1000; 31 | gt when timerafter(time) :> int _; 32 | scl <: 0; 33 | // shift 7bits of address and 1bit R/W (fixed to write). 34 | // WARNING: Assume MSB first. 35 | for (i = 0; i < 8; i += 1) 36 | { 37 | Temp = (device >> (7 - i)) & 0x1; 38 | sda <: Temp; 39 | gt :> time; 40 | time += 1000; 41 | gt when timerafter(time) :> int _; 42 | scl <: 1; 43 | gt :> time; 44 | time += 1000; 45 | gt when timerafter(time) :> int _; 46 | scl <: 0; 47 | } 48 | // turn the data to input 49 | sda :> Temp; 50 | gt :> time; 51 | time += 1000; 52 | gt when timerafter(time) :> int _; 53 | scl <: 1; 54 | // sample first ACK. 55 | sda :> ack[0]; 56 | gt :> time; 57 | time += 1000; 58 | gt when timerafter(time) :> int _; 59 | scl <: 0; 60 | 61 | CtlAdrsData = (addr & 0xFF); 62 | // shift first 8 bits. 63 | for (i = 0; i < 8; i += 1) 64 | { 65 | Temp = (CtlAdrsData >> (7 - i)) & 0x1; 66 | sda <: Temp; 67 | gt :> time; 68 | time += 1000; 69 | gt when timerafter(time) :> int _; 70 | scl <: 1; 71 | gt :> time; 72 | time += 1000; 73 | gt when timerafter(time) :> int _; 74 | scl <: 0; 75 | } 76 | // turn the data to input 77 | sda :> Temp; 78 | gt :> time; 79 | time += 1000; 80 | gt when timerafter(time) :> int _; 81 | scl <: 1; 82 | // sample second ACK. 83 | sda :> ack[1]; 84 | gt :> time; 85 | time += 1000; 86 | gt when timerafter(time) :> int _; 87 | scl <: 0; 88 | 89 | 90 | // stop bit 91 | gt :> time; 92 | time += 1000 + 1000; 93 | gt when timerafter(time) :> int _; 94 | // start bit on SDI 95 | scl <: 1; 96 | sda <: 1; 97 | time += 1000 + 1000; 98 | gt when timerafter(time) :> int _; 99 | scl <: 0; 100 | time += 1000 + 1000; 101 | gt when timerafter(time) :> int _; 102 | 103 | 104 | // send address and read 105 | scl <: 1; 106 | sda <: 1; 107 | sync(sda); 108 | gt :> time; 109 | time += 1000 + 1000; 110 | gt when timerafter(time) :> int _; 111 | // start bit on SDI 112 | scl <: 1; 113 | sda <: 0; 114 | gt :> time; 115 | time += 1000; 116 | gt when timerafter(time) :> int _; 117 | scl <: 0; 118 | // shift 7bits of address and 1bit R/W (fixed to write). 119 | // WARNING: Assume MSB first. 120 | for (i = 0; i < 8; i += 1) 121 | { 122 | int deviceAddr = device | 1; 123 | Temp = (deviceAddr >> (7 - i)) & 0x1; 124 | sda <: Temp; 125 | gt :> time; 126 | time += 1000; 127 | gt when timerafter(time) :> int _; 128 | scl <: 1; 129 | gt :> time; 130 | time += 1000; 131 | gt when timerafter(time) :> int _; 132 | scl <: 0; 133 | } 134 | // turn the data to input 135 | sda :> Temp; 136 | gt :> time; 137 | time += 1000; 138 | gt when timerafter(time) :> int _; 139 | scl <: 1; 140 | // sample first ACK. 141 | sda :> ack[0]; 142 | gt :> time; 143 | time += 1000; 144 | gt when timerafter(time) :> int _; 145 | scl <: 0; 146 | 147 | 148 | rdData = 0; 149 | // shift second 8 bits. 150 | for (i = 0; i < 8; i += 1) 151 | { 152 | 153 | gt :> time; 154 | time += 1000; 155 | gt when timerafter(time) :> int _; 156 | scl <: 1; 157 | 158 | sda :> Temp; 159 | rdData = (rdData << 1) | (Temp & 1); 160 | 161 | gt :> time; 162 | time += 1000; 163 | gt when timerafter(time) :> int _; 164 | scl <: 0; 165 | } 166 | 167 | // turn the data to input 168 | sda :> Temp; 169 | gt :> time; 170 | time += 1000; 171 | gt when timerafter(time) :> int _; 172 | scl <: 1; 173 | // sample second ACK. 174 | sda :> ack[2]; 175 | gt :> time; 176 | time += 1000; 177 | gt when timerafter(time) :> int _; 178 | scl <: 0; 179 | gt :> time; 180 | time += 1000; 181 | gt when timerafter(time) :> int _; 182 | scl <: 1; 183 | // put the data to a good value for next round. 184 | sda <: 1; 185 | // validate all items are ACK properly. 186 | //Result = 0; 187 | //for (i = 0; i < 3; i += 1) 188 | //{ 189 | //if ((ack[i]&1) != 0) 190 | //{ 191 | //Result = Result | (1 << i); 192 | //} 193 | //} 194 | 195 | return rdData; 196 | } 197 | 198 | void regwr(int addr, int data, int device, out port scl, port sda) 199 | { 200 | //int Result; 201 | timer gt; 202 | unsigned time; 203 | int Temp, CtlAdrsData, i; 204 | // three device ACK 205 | int ack[3]; 206 | 207 | // initial values. 208 | scl <: 1; 209 | sda <: 1; 210 | sync(sda); 211 | 212 | gt :> time; 213 | time += 1000 + 1000; 214 | gt when timerafter(time) :> void; 215 | 216 | // start bit on SDI 217 | scl <: 1; 218 | sda <: 0; 219 | gt :> time; 220 | time += 1000; 221 | gt when timerafter(time) :> void; 222 | scl <: 0; 223 | 224 | // shift 7bits of address and 1bit R/W (fixed to write). 225 | // WARNING: Assume MSB first. 226 | for (i = 0; i < 8; i += 1) 227 | { 228 | Temp = (device >> (7 - i)) & 0x1; 229 | sda <: Temp; 230 | gt :> time; 231 | time += 1000; 232 | gt when timerafter(time) :> void; 233 | scl <: 1; 234 | gt :> time; 235 | time += 1000; 236 | gt when timerafter(time) :> void; 237 | scl <: 0; 238 | } 239 | 240 | // turn the data to input 241 | sda :> Temp; 242 | gt :> time; 243 | time += 1000; 244 | gt when timerafter(time) :> void; 245 | scl <: 1; 246 | 247 | // sample first ACK. 248 | sda :> ack[0]; 249 | gt :> time; 250 | time += 1000; 251 | gt when timerafter(time) :> void; 252 | scl <: 0; 253 | 254 | CtlAdrsData = (addr & 0xFF); 255 | 256 | // shift first 8 bits. 257 | for (i = 0; i < 8; i += 1) 258 | { 259 | Temp = (CtlAdrsData >> (7 - i)) & 0x1; 260 | sda <: Temp; 261 | gt :> time; 262 | time += 1000; 263 | gt when timerafter(time) :> void; 264 | scl <: 1; 265 | gt :> time; 266 | time += 1000; 267 | gt when timerafter(time) :> void; 268 | scl <: 0; 269 | } 270 | // turn the data to input 271 | sda :> Temp; 272 | gt :> time; 273 | time += 1000; 274 | gt when timerafter(time) :> void; 275 | scl <: 1; 276 | // sample second ACK. 277 | sda :> ack[1]; 278 | gt :> time; 279 | time += 1000; 280 | gt when timerafter(time) :> void; 281 | scl <: 0; 282 | 283 | CtlAdrsData = (data & 0xFF); 284 | // shift second 8 bits. 285 | for (i = 0; i < 8; i += 1) 286 | { 287 | Temp = (CtlAdrsData >> (7 - i)) & 0x1; 288 | sda <: Temp; 289 | gt :> time; 290 | time += 1000; 291 | gt when timerafter(time) :> void; 292 | scl <: 1; 293 | gt :> time; 294 | time += 1000; 295 | gt when timerafter(time) :> void; 296 | scl <: 0; 297 | } 298 | // turn the data to input 299 | sda :> Temp; 300 | gt :> time; 301 | time += 1000; 302 | gt when timerafter(time) :> void; 303 | scl <: 1; 304 | // sample second ACK. 305 | sda :> ack[2]; 306 | gt :> time; 307 | time += 1000; 308 | gt when timerafter(time) :> void; 309 | scl <: 0; 310 | gt :> time; 311 | time += 1000; 312 | gt when timerafter(time) :> void; 313 | scl <: 1; 314 | // put the data to a good value for next round. 315 | sda <: 1; 316 | // validate all items are ACK properly. 317 | //Result = 0; 318 | //for (i = 0; i < 3; i += 1) 319 | //{ 320 | //if ((ack[i]&1) != 0) 321 | //{ 322 | //Result = Result | (1 << i); 323 | //} 324 | //} 325 | //return(Result); 326 | } 327 | -------------------------------------------------------------------------------- /app_par_audio_dsp/src/iis.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011, XMOS Ltd, All rights reserved 2 | // This software is freely distributable under a derivative of the 3 | // University of Illinois/NCSA Open Source License posted in 4 | // LICENSE.txt and at 5 | 6 | /////////////////////////////////////////////////////////////////////////////// 7 | // 8 | // Multichannel IIS master receiver-transmitter 9 | // 10 | // Version 1.0 11 | // 9 Dec 2009 12 | // 13 | // iis.h 14 | // 15 | 16 | 17 | #include "defines.h" 18 | 19 | #ifndef _iis_h_ 20 | #define _iis_h_ 21 | 22 | // BCK is soft divided off MCK 23 | // MCK frequency is MCK_BCK_RATIO times BCK frequency 24 | #ifndef MCK_BCK_RATIO 25 | #define MCK_BCK_RATIO 8 26 | #endif 27 | 28 | // resources for IIS 29 | struct iis { 30 | // clock blocks 31 | // one for MCK, one for BCK 32 | clock cb1, cb2; 33 | 34 | // clock ports 35 | in port mck; 36 | out buffered port:32 bck; 37 | out buffered port:32 wck; 38 | 39 | // data ports 40 | in buffered port:32 din[NUM_IN]; 41 | out buffered port:32 dout[NUM_OUT]; 42 | }; 43 | 44 | // samples are returned left-aligned 45 | // e.g. 24-bit audio will look like 0x12345600 (positive) or 0xFF123400 (negative) 46 | // termination: send a control token down c_out, will be pinged back via c_in 47 | void iis(struct iis &r_iis, streaming chanend c_in[], streaming chanend c_out[]); 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /app_par_audio_dsp/src/iis.xc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011, XMOS Ltd, All rights reserved 2 | // This software is freely distributable under a derivative of the 3 | // University of Illinois/NCSA Open Source License posted in 4 | // LICENSE.txt and at 5 | 6 | /////////////////////////////////////////////////////////////////////////////// 7 | // 8 | // Multichannel IIS master receiver-transmitter 9 | // 10 | // Version 1.0 11 | // 9 Dec 2009 12 | // 13 | // iis.xc 14 | // 15 | // Works with tools version: 9.9.1 16 | // Tested with compiler optimisations O2 17 | // 18 | // Copyright (C) 2009, XMOS Ltd 19 | // All rights reserved. 20 | // 21 | 22 | #include 23 | #include 24 | #include "iis.h" 25 | #include "stdio.h" 26 | #include "defines.h" 27 | #include "signal_overrides.h" 28 | 29 | #ifdef USE_XSCOPE 30 | #include "xscope.h" 31 | #endif 32 | 33 | // soft divide BCK off MCK 34 | static inline void bck_32_ticks(out buffered port:32 bck) 35 | { 36 | #if MCK_BCK_RATIO == 2 37 | bck <: 0x55555555; 38 | bck <: 0x55555555; 39 | #elif MCK_BCK_RATIO == 4 40 | bck <: 0x33333333; 41 | bck <: 0x33333333; 42 | bck <: 0x33333333; 43 | bck <: 0x33333333; 44 | #elif MCK_BCK_RATIO == 8 45 | bck <: 0x0F0F0F0F; 46 | bck <: 0x0F0F0F0F; 47 | bck <: 0x0F0F0F0F; 48 | bck <: 0x0F0F0F0F; 49 | bck <: 0x0F0F0F0F; 50 | bck <: 0x0F0F0F0F; 51 | bck <: 0x0F0F0F0F; 52 | bck <: 0x0F0F0F0F; 53 | #else 54 | #error "MCK/BCK ratio must be 2, 4 or 8" 55 | #endif 56 | } 57 | 58 | static inline int termination(streaming chanend c_out, streaming chanend c_in) 59 | { 60 | int ct; 61 | asm("testct %0, res[%1]" : "=r"(ct) : "r"(c_out)); 62 | if (ct) { 63 | asm("inct %0, res[%1]" : "=r"(ct) : "r"(c_out)); 64 | asm("outct res[%0], %1" :: "r"(c_in), "r"(ct)); 65 | return 1; 66 | } 67 | else { 68 | return 0; 69 | } 70 | } 71 | 72 | #pragma unsafe arrays 73 | void iis_loop(in buffered port:32 din[], out buffered port:32 dout[], streaming chanend c_in[], streaming chanend c_out[], out buffered port:32 wck, out buffered port:32 bck) 74 | { 75 | int lr = 0; 76 | unsigned frame_counter = 0; 77 | 78 | #ifdef INPUT_OVERRIDE 79 | signed input_override[NUM_INP_ACHANS]; 80 | unsigned first_idx; 81 | unsigned j; 82 | #endif 83 | 84 | // inputs and outputs are 32 bits at a time 85 | // assuming clock block is reset - initial time is 0 86 | // split SETPT from IN using asm - basically a split transaction with BCK generation in between 87 | // input is always "up to" given time, output is always "starting from" given time 88 | // outputs will be aligned to WCK + 1 (first output at time 32, WCK at time 31) 89 | // inputs will also be aligned to WCK + 1 (first input up to time 63, WCK up to time 62) 90 | for (int i = 0; i < NUM_OUT; i++) { 91 | dout[i] @ 32 <: 0; 92 | } 93 | for (int i = 0; i < NUM_IN; i++) { 94 | asm("setpt res[%0], %1" :: "r"(din[i]), "r"(63)); 95 | } 96 | wck @ 31 <: 0; 97 | 98 | // clocks for previous outputs / inputs 99 | bck_32_ticks(bck); 100 | bck_32_ticks(bck); 101 | 102 | while(1) { 103 | // output audio data 104 | // expected to come from channel end as left-aligned 105 | #pragma loop unroll 106 | for (int i = 0; i < NUM_OUT; i++) { 107 | signed x = 0; 108 | c_out[i] :> x; 109 | dout[i] <: bitrev(x); 110 | } 111 | 112 | // drive word clock 113 | wck <: lr; 114 | lr = ~lr; 115 | 116 | // input audio data 117 | // will be output to channel end as left-aligned 118 | // compiler would insert SETC FULL on DIN input, because it doesn't know about inline SETPT above 119 | // hence we need inline IN too 120 | #pragma loop unroll 121 | for (int i = 0; i < NUM_IN; i++) { 122 | signed x; 123 | asm("in %0, res[%1]" : "=r"(x) : "r"(din[i])); 124 | #ifndef INPUT_OVERRIDE 125 | c_in[i] <: bitrev(x); 126 | #else 127 | c_in[i] <: input_override[i]; 128 | #endif 129 | } 130 | 131 | // drive bit clock 132 | bck_32_ticks(bck); 133 | 134 | #ifdef INPUT_OVERRIDE 135 | if(lr==0) {first_idx = 0;} else {first_idx=1;}; 136 | j=0; 137 | // generate input signal override 138 | for(int i=first_idx; i 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "xai2_ports.h" 12 | #include "iis.h" 13 | 14 | #include "defines.h" 15 | #include "biquad_coeffs.h" 16 | #include "crossover.h" 17 | #include "equaliser.h" 18 | #include "eq_client.h" 19 | 20 | 21 | // XMOS Parallel DSP example 22 | // See README.rst for details 23 | 24 | 25 | struct iis r_iis = { 26 | on stdcore[1] : XS1_CLKBLK_1, 27 | on stdcore[1] : XS1_CLKBLK_2, 28 | MCK_1, BCK, WCK, 29 | { ADC0, ADC1, ADC2 }, 30 | { DAC0, DAC1, DAC2, DAC3 } 31 | }; 32 | 33 | out port scl = I2C_SCL; 34 | port sda = I2C_SDA; 35 | 36 | out port sync_out = SYNC_OUT_4BIT; 37 | out port rst = SEL_MOD_RST; 38 | 39 | void init_pll(unsigned mult, out port scl, port sda); 40 | void reset_codec(out port rst); 41 | void init_codec(out port scl, port sda, int codec_is_master, int mic_input, int instr_input); 42 | 43 | void clkgen(int freq, out port p, chanend stop); 44 | 45 | extern void dsp_bypass(unsigned achan_idx); 46 | extern void sine_out(unsigned achan_idx); 47 | extern void init_states(); 48 | extern void init_xover(biquad_state_xover_s &state, int zeroDb); 49 | extern int sine(int x); 50 | 51 | extern int delay_proc(unsigned achan_idx, signed in_sample, unsigned delay_buf_idx, unsigned delay); 52 | extern int biquad_xover(biquad_state_xover_s &state, coeffs_s &coeffs, int xn); 53 | 54 | void mswait(int ms) 55 | { 56 | timer tmr; 57 | unsigned t; 58 | tmr :> t; 59 | for (int i = 0; i < ms; i++) { 60 | t += 100000; 61 | tmr when timerafter(t) :> void; 62 | } 63 | } 64 | 65 | void crossover(unsigned idx, streaming chanend c_in, streaming chanend c_out_a, streaming chanend c_out_b) { 66 | signed in_sample=0; 67 | unsigned sample_count=0; 68 | 69 | // HPF: -50 DB below 500Hz 70 | // swc_cascaded_biquad Makefile config: FILTER= -min -50 -max 0 -low 500 -step 10 71 | coeffs_s lowshelf = { 27106380, -11382399, 13969018, -27631332, 13665645}; 72 | 73 | // LPF: -50 DB above 500Hz 74 | // swc_cascaded_biquad Makefile config: FILTER= -min -50 -max 0 -high 500 -step 10 75 | coeffs_s highshelf = { 32681149, -15926091, 1774726, -3258144, 1505576}; 76 | 77 | biquad_state_xover_s state_hs_0; 78 | biquad_state_xover_s state_hs_1; 79 | biquad_state_xover_s state_ls_0; 80 | biquad_state_xover_s state_ls_1; 81 | 82 | init_xover(state_hs_0,0); 83 | init_xover(state_hs_1,0); 84 | init_xover(state_ls_0,0); 85 | init_xover(state_ls_1,0); 86 | 87 | while(1) { 88 | //sync means input buffer contains block ready for processing 89 | //c_sync :> unsigned; 90 | // filters operate on input and output buffers (shared memory) 91 | // Process a number of channels per thread 92 | 93 | if(sample_count & 1) { 94 | // right sample 95 | c_out_a <: biquad_xover( 96 | state_hs_1, 97 | highshelf, 98 | in_sample 99 | ); 100 | c_out_b <: biquad_xover( 101 | state_ls_1, 102 | lowshelf, 103 | in_sample 104 | ); 105 | } else { 106 | // left sample 107 | c_out_a <: biquad_xover( 108 | state_hs_0, 109 | highshelf, 110 | in_sample 111 | ); 112 | c_out_b <: biquad_xover( 113 | state_ls_0, 114 | lowshelf, 115 | in_sample 116 | ); 117 | } 118 | 119 | // input happens after output in iis thread! 120 | c_in :> in_sample; 121 | 122 | sample_count++; 123 | } 124 | 125 | } 126 | 127 | void loopback(unsigned idx, streaming chanend c_in[], streaming chanend c_out[]) { 128 | signed in_sample[NUM_OUT]; //more out than in 129 | 130 | while(1) { 131 | for(int i=0; i in_sample[i]; 136 | } 137 | //printf("samples looped back\n"); 138 | } 139 | } 140 | 141 | void delays(unsigned idx, streaming chanend c_in, streaming chanend c_out) { 142 | signed sample=0; //more out than in 143 | unsigned sample_count=0; 144 | while(1) { 145 | c_out <: sample; 146 | 147 | c_in :> sample; 148 | if(sample_count & 1) { 149 | // right sample 150 | sample = delay_proc(1, sample, 1, 5000); // delay by 5000 samples 151 | } else { 152 | sample = delay_proc(1, sample, 0, 0); 153 | } 154 | sample_count++; 155 | //printf("delays: sample processed\n"); 156 | } 157 | } 158 | 159 | 160 | void busy_thread() { 161 | set_thread_fast_mode_on(); 162 | while (1); 163 | } 164 | 165 | void eq_wrapper(unsigned idx, chanend cCtrl, streaming chanend cDSPActivityOutput, streaming chanend c_in, streaming chanend c_out); 166 | 167 | int main() 168 | { 169 | 170 | streaming chan c_in[NUM_IN], c_out[NUM_OUT]; 171 | streaming chan c_DSP_activity[NUM_EQ_THREADS]; 172 | chan c_ctrl[NUM_EQ_THREADS]; 173 | 174 | par { 175 | 176 | 177 | #ifdef AUDIO_LOOPBACK 178 | on stdcore[0] : loopback(0, c_in, c_out); 179 | #else 180 | on stdcore[0] : eq_wrapper(0, c_ctrl[0], c_DSP_activity[0], c_in[0], c_out[0]); 181 | 182 | #ifndef XSIM // reduce the "noise" in the simulator trace 183 | // good practise to keep other threads busy 184 | on stdcore[0] : busy_thread(); 185 | on stdcore[0] : busy_thread(); 186 | on stdcore[0] : busy_thread(); 187 | on stdcore[0] : busy_thread(); 188 | on stdcore[0] : busy_thread(); 189 | on stdcore[0] : busy_thread(); 190 | #endif 191 | 192 | // on core1 because there's a limit of 4 streaming channels across cores. 193 | on stdcore[1] : crossover(1, c_in[1], c_out[1], c_out[2]); 194 | //on stdcore[1] : delays(1, c_in[1], c_out[1]); 195 | on stdcore[0] : eq_client(c_ctrl, c_DSP_activity); 196 | #endif 197 | 198 | // Init PLL, Codec, start I2S tread 199 | on stdcore[1] : { 200 | chan stop; 201 | char name[3][4] = { "1/2", "3/4", "5/6" }; 202 | int mode = 0x0; // clocks connected together 203 | int sel = 0x0; // XCore sync rather than BNC input 204 | 205 | #ifndef XSIM 206 | // 1kHz -> 24.576MHz 207 | init_pll(24576000 / 1000, scl, sda); 208 | reset_codec(rst); 209 | rst <: 0x8 | mode | sel; 210 | init_codec(scl, sda, 0, 0, 0); 211 | #else 212 | printf("Running on Simulator\n"); 213 | #endif 214 | 215 | par { 216 | clkgen(1000, sync_out, stop); 217 | { 218 | #ifndef XSIM // don't wait 300ms when simulating 219 | mswait(300); 220 | #endif 221 | iis(r_iis, c_in, c_out); 222 | } 223 | } 224 | } 225 | } 226 | return 0; 227 | } 228 | -------------------------------------------------------------------------------- /app_par_audio_dsp/src/pll.xc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011, XMOS Ltd, All rights reserved 2 | // This software is freely distributable under a derivative of the 3 | // University of Illinois/NCSA Open Source License posted in 4 | // LICENSE.txt and at 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | int regrd(int addr, int device, out port scl, port sda); 11 | void regwr(int addr, int data, int device, out port scl, port sda); 12 | 13 | #define REGRD_PLL(reg) regrd(reg, 0x9C, scl, sda) 14 | #define REGWR_PLL(reg, val) regwr(reg, val, 0x9C, scl, sda) 15 | 16 | void init_pll(unsigned mult, out port scl, port sda) 17 | { 18 | REGWR_PLL(0x03, 0x03); 19 | REGWR_PLL(0x05, 0x01); 20 | REGWR_PLL(0x16, 0x00); 21 | 22 | // check 23 | assert(REGRD_PLL(0x03) == 0x03); 24 | assert(REGRD_PLL(0x05) == 0x01); 25 | assert(REGRD_PLL(0x16) == 0x00); // PLL lock active low 26 | 27 | // multiplier is translated to 20.12 format by shifting left by 12 28 | REGWR_PLL(0x06, (mult >> 12) & 0xFF); 29 | REGWR_PLL(0x07, (mult >> 4) & 0xFF); 30 | REGWR_PLL(0x08, (mult << 4) & 0xFF); 31 | REGWR_PLL(0x09, 0x00); 32 | 33 | // check 34 | assert(REGRD_PLL(0x06) == ((mult >> 12) & 0xFF)); 35 | assert(REGRD_PLL(0x07) == ((mult >> 4) & 0xFF)); 36 | assert(REGRD_PLL(0x08) == ((mult << 4) & 0xFF)); 37 | assert(REGRD_PLL(0x09) == 0x00); 38 | 39 | #ifndef SHARED_SILENT 40 | printstrln("CS2300 present and configured"); 41 | #endif 42 | } 43 | 44 | void clkgen(int freq, out port p, chanend stop) 45 | { 46 | timer tmr; 47 | int period = XS1_TIMER_MHZ * 1000000 / freq / 2; 48 | unsigned t; 49 | int x = 0; 50 | tmr :> t; 51 | while (1) { 52 | t += period; 53 | select { 54 | case tmr when timerafter(t) :> void: break; 55 | case stop :> int: return; 56 | } 57 | p <: x; 58 | x = !x; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /app_par_audio_dsp/src/signal_overrides.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011, XMOS Ltd, All rights reserved 2 | // This software is freely distributable under a derivative of the 3 | // University of Illinois/NCSA Open Source License posted in 4 | // LICENSE.txt and at */ 5 | 6 | #ifndef SIGNAL_OVERRIDES_H_ 7 | #define SIGNAL_OVERRIDES_H_ 8 | 9 | signed override_input(unsigned achan_idx); 10 | signed override_output(unsigned achan_idx); 11 | 12 | #endif /* SIGNAL_OVERRIDES_H_ */ 13 | -------------------------------------------------------------------------------- /app_par_audio_dsp/src/signal_overrides.xc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011, XMOS Ltd, All rights reserved 2 | // This software is freely distributable under a derivative of the 3 | // University of Illinois/NCSA Open Source License posted in 4 | // LICENSE.txt and at 5 | 6 | 7 | #include 8 | #include "signal_overrides.h" 9 | #include "defines.h" 10 | 11 | unsigned out_x[NUM_OUTP_ACHANS] = {0,0,0,0,0,0,0,0}; 12 | unsigned in_x[NUM_INP_ACHANS] = {0,0,0,0,0,0}; 13 | 14 | extern int sine(int x); 15 | 16 | // change this for custom input signal generators 17 | signed override_input(unsigned achan_idx) { 18 | signed sample; 19 | 20 | sample = sine(in_x[achan_idx]); 21 | sample += sine(in_x[achan_idx]*10); // add 10x harmonic 22 | 23 | in_x[achan_idx]+= 5; // sine freq will be: 10 * (48000Hz / 2048) ~ 234 Hz 24 | return sample >> 1; 25 | } 26 | 27 | // change this for custom input signal generators 28 | signed override_output(unsigned achan_idx) { 29 | signed sample; 30 | 31 | sample = sine(out_x[achan_idx]); 32 | sample += sine(out_x[achan_idx]*10); // add 10x harmonic 33 | out_x[achan_idx]+= 5 ; // sine freq will be: 10 * (48000Hz / 2048) ~ 234 Hz 34 | 35 | return sample >> 1; 36 | } 37 | 38 | -------------------------------------------------------------------------------- /app_par_audio_dsp/src/sine.xc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011, XMOS Ltd, All rights reserved 2 | // This software is freely distributable under a derivative of the 3 | // University of Illinois/NCSA Open Source License posted in 4 | // LICENSE.txt and at 5 | 6 | 7 | /* 8 | * One quarter of a sine wave is stored in an array called sineWave. 513 9 | * values are stored representing the data in 512 steps from 0 to pi/2. 10 | * 11 | * The data in sineWave is stored multiplied by 2^23-1, so the numbers are 12 | * between 13 | * 14 | * 0 = sineWave[0] = (sin(0)*(2^23-1)) and 15 | * 8388607 = sineWave[512] = (sin(pi/2)*(2^23-1)). 16 | * 17 | * This table can be used to lookup a complete sine or cosine by negating 18 | * and or flipping the quarter sine wave. 19 | */ 20 | 21 | int sineWave[513] = { 22 | 0, 25735, 51471, 77206, 102941, 128674, 154406, 180137, 205866, 23 | 231593, 257318, 283041, 308761, 334478, 360192, 385902, 411609, 24 | 437312, 463011, 488705, 514395, 540080, 565760, 591435, 617104, 25 | 642767, 668424, 694075, 719719, 745357, 770988, 796611, 822227, 26 | 847835, 873435, 899027, 924610, 950185, 975751, 1001307, 1026855, 27 | 1052392, 1077920, 1103437, 1128944, 1154441, 1179926, 1205401, 28 | 1230864, 1256315, 1281755, 1307183, 1332598, 1358001, 1383391, 29 | 1408768, 1434132, 1459482, 1484818, 1510141, 1535449, 1560743, 30 | 1586022, 1611286, 1636536, 1661769, 1686987, 1712189, 1737375, 31 | 1762545, 1787698, 1812834, 1837954, 1863056, 1888140, 1913207, 32 | 1938255, 1963286, 1988297, 2013291, 2038265, 2063220, 2088155, 33 | 2113071, 2137967, 2162843, 2187699, 2212534, 2237348, 2262141, 34 | 2286913, 2311663, 2336392, 2361098, 2385783, 2410444, 2435084, 35 | 2459700, 2484293, 2508863, 2533409, 2557931, 2582429, 2606903, 36 | 2631352, 2655777, 2680176, 2704551, 2728900, 2753223, 2777520, 37 | 2801791, 2826036, 2850254, 2874446, 2898610, 2922747, 2946856, 38 | 2970938, 2994992, 3019018, 3043015, 3066983, 3090923, 3114834, 39 | 3138715, 3162567, 3186388, 3210180, 3233942, 3257673, 3281374, 40 | 3305044, 3328683, 3352290, 3375866, 3399410, 3422922, 3446401, 41 | 3469849, 3493263, 3516645, 3539994, 3563309, 3586591, 3609839, 42 | 3633053, 3656233, 3679379, 3702490, 3725566, 3748607, 3771612, 43 | 3794582, 3817517, 3840415, 3863278, 3886104, 3908893, 3931646, 44 | 3954361, 3977040, 3999681, 4022284, 4044850, 4067377, 4089866, 45 | 4112317, 4134729, 4157102, 4179436, 4201730, 4223985, 4246200, 46 | 4268376, 4290511, 4312605, 4334659, 4356673, 4378645, 4400576, 47 | 4422466, 4444314, 4466120, 4487884, 4509606, 4531286, 4552923, 48 | 4574517, 4596067, 4617575, 4639039, 4660460, 4681837, 4703169, 49 | 4724457, 4745701, 4766901, 4788055, 4809164, 4830228, 4851247, 50 | 4872220, 4893147, 4914028, 4934862, 4955650, 4976392, 4997087, 51 | 5017735, 5038335, 5058888, 5079394, 5099851, 5120261, 5140622, 52 | 5160936, 5181200, 5201416, 5221583, 5241700, 5261768, 5281787, 53 | 5301756, 5321675, 5341545, 5361363, 5381132, 5400849, 5420516, 54 | 5440132, 5459697, 5479210, 5498671, 5518081, 5537439, 5556745, 55 | 5575999, 5595200, 5614348, 5633444, 5652486, 5671475, 5690411, 56 | 5709294, 5728122, 5746897, 5765618, 5784284, 5802896, 5821453, 57 | 5839956, 5858403, 5876796, 5895133, 5913414, 5931640, 5949810, 58 | 5967925, 5985983, 6003984, 6021929, 6039818, 6057649, 6075424, 59 | 6093141, 6110801, 6128403, 6145948, 6163435, 6180864, 6198235, 60 | 6215547, 6232801, 6249996, 6267133, 6284210, 6301229, 6318188, 61 | 6335087, 6351927, 6368707, 6385427, 6402087, 6418687, 6435226, 62 | 6451705, 6468123, 6484480, 6500777, 6517012, 6533185, 6549297, 63 | 6565348, 6581336, 6597263, 6613128, 6628930, 6644670, 6660348, 64 | 6675963, 6691514, 6707003, 6722429, 6737792, 6753091, 6768327, 65 | 6783498, 6798606, 6813650, 6828630, 6843546, 6858397, 6873184, 66 | 6887906, 6902563, 6917155, 6931682, 6946144, 6960540, 6974871, 67 | 6989137, 7003336, 7017470, 7031537, 7045538, 7059473, 7073342, 68 | 7087144, 7100879, 7114548, 7128149, 7141684, 7155151, 7168551, 69 | 7181883, 7195148, 7208345, 7221474, 7234535, 7247528, 7260453, 70 | 7273310, 7286098, 7298817, 7311468, 7324050, 7336563, 7349007, 71 | 7361382, 7373688, 7385924, 7398090, 7410187, 7422215, 7434172, 72 | 7446059, 7457877, 7469624, 7481301, 7492907, 7504443, 7515908, 73 | 7527303, 7538626, 7549879, 7561061, 7572171, 7583210, 7594178, 74 | 7605075, 7615899, 7626652, 7637334, 7647943, 7658481, 7668946, 75 | 7679339, 7689660, 7699908, 7710084, 7720188, 7730219, 7740177, 76 | 7750062, 7759874, 7769613, 7779279, 7788872, 7798392, 7807838, 77 | 7817210, 7826509, 7835735, 7844886, 7853964, 7862968, 7871898, 78 | 7880754, 7889535, 7898243, 7906876, 7915434, 7923918, 7932328, 79 | 7940663, 7948923, 7957108, 7965218, 7973254, 7981214, 7989099, 80 | 7996909, 8004644, 8012303, 8019887, 8027396, 8034829, 8042186, 81 | 8049468, 8056674, 8063804, 8070858, 8077836, 8084738, 8091564, 82 | 8098314, 8104988, 8111585, 8118106, 8124551, 8130919, 8137210, 83 | 8143425, 8149564, 8155625, 8161610, 8167518, 8173350, 8179104, 84 | 8184781, 8190381, 8195905, 8201351, 8206719, 8212011, 8217225, 85 | 8222362, 8227422, 8232404, 8237308, 8242136, 8246885, 8251557, 86 | 8256151, 8260668, 8265106, 8269467, 8273751, 8277956, 8282083, 87 | 8286132, 8290104, 8293997, 8297812, 8301550, 8305209, 8308790, 88 | 8312292, 8315717, 8319063, 8322331, 8325520, 8328631, 8331664, 89 | 8334619, 8337494, 8340292, 8343011, 8345651, 8348213, 8350696, 90 | 8353101, 8355427, 8357674, 8359843, 8361933, 8363945, 8365877, 91 | 8367731, 8369506, 8371203, 8372820, 8374359, 8375819, 8377200, 92 | 8378502, 8379725, 8380870, 8381936, 8382922, 8383830, 8384659, 93 | 8385409, 8386080, 8386672, 8387185, 8387620, 8387975, 8388251, 94 | 8388449, 8388567, 8388607 95 | }; 96 | 97 | /* 98 | * The sine function computes a sine assuming its first argument is an 99 | * angle measued in units of pi/1024 radians. Because there are 2048 100 | * integral steps in a sinewave, the function first computes the argument 101 | * modulo 2048, and then it looks up the sine value for each of the four 102 | * quadrants of the winsewave. 103 | */ 104 | int sine(int x) { 105 | x = x & 2047; 106 | switch (x >> 9) { 107 | case 0: return sineWave[x]; 108 | case 1: return sineWave[1024-x]; 109 | case 2: return -sineWave[x-1024]; 110 | case 3: return -sineWave[2048-x]; 111 | } 112 | return 0; 113 | } 114 | 115 | 116 | -------------------------------------------------------------------------------- /app_par_audio_dsp/src/xai2_ports.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011, XMOS Ltd, All rights reserved 2 | // This software is freely distributable under a derivative of the 3 | // University of Illinois/NCSA Open Source License posted in 4 | // LICENSE.txt and at 5 | 6 | #include 7 | 8 | // 1V1 board 9 | 10 | // SPI 11 | #define SPI_MISO on stdcore[0] : XS1_PORT_1A 12 | #define SPI_SS on stdcore[0] : XS1_PORT_1B 13 | #define SPI_SCK on stdcore[0] : XS1_PORT_1C 14 | #define SPI_MOSI on stdcore[0] : XS1_PORT_1D 15 | 16 | // clocking 17 | // also WCK_BNC on 4B 18 | #define WCK_BNC on stdcore[0] : XS1_PORT_1I 19 | #define SYNC_OUT_4BIT on stdcore[1] : XS1_PORT_4E 20 | #define MCK_0 on stdcore[0] : XS1_PORT_1L 21 | #define MCK_1 on stdcore[1] : XS1_PORT_1L 22 | 23 | // I2S 24 | #define BCK on stdcore[1] : XS1_PORT_1I 25 | #define WCK on stdcore[1] : XS1_PORT_1E 26 | #define DAC0 on stdcore[1] : XS1_PORT_1M 27 | #define DAC1 on stdcore[1] : XS1_PORT_1F 28 | #define DAC2 on stdcore[1] : XS1_PORT_1H 29 | #define DAC3 on stdcore[1] : XS1_PORT_1N 30 | #define ADC0 on stdcore[1] : XS1_PORT_1G 31 | #define ADC1 on stdcore[1] : XS1_PORT_1A 32 | #define ADC2 on stdcore[1] : XS1_PORT_1B 33 | 34 | // S/PDIF 35 | #define COAXIAL_RX on stdcore[0] : XS1_PORT_1K 36 | #define COAXIAL_TX on stdcore[1] : XS1_PORT_1K 37 | #define OPTICAL_RX on stdcore[0] : XS1_PORT_1J 38 | #define OPTICAL_TX on stdcore[1] : XS1_PORT_1J 39 | 40 | // MIDI 41 | #define MIDI_OUT on stdcore[1] : XS1_PORT_1O 42 | #define MIDI_IN on stdcore[1] : XS1_PORT_1P 43 | 44 | // control 45 | // SEL_MOD_RST bit 0: SYNC SEL, bit 1: CODEC MODE, bit 3: CODEC RST (active low) 46 | // PLL_BNC_INT bit 1: PLL LOCK, bit 2: WCK BNC, bit 3: CODEC INT 47 | #define PHY_RST on stdcore[0] : XS1_PORT_1M 48 | #define I2C_SDA on stdcore[1] : XS1_PORT_1C 49 | #define I2C_SCL on stdcore[1] : XS1_PORT_1D 50 | #define LEDS on stdcore[1] : XS1_PORT_8B 51 | #define GPIO on stdcore[1] : XS1_PORT_4F 52 | #define PLL_BNC_INT on stdcore[1] : XS1_PORT_4B 53 | #define SEL_MOD_RST on stdcore[1] : XS1_PORT_4A 54 | 55 | // UIFM 56 | #define UIFM_TXD on stdcore[0] : XS1_PORT_8A 57 | #define UIFM_RXD on stdcore[0] : XS1_PORT_8B 58 | #define UIFM_STP_SUS on stdcore[0] : XS1_PORT_1E 59 | #define UIFM_USB_CLK on stdcore[0] : XS1_PORT_1H 60 | #define UIFM_REG_WR on stdcore[0] : XS1_PORT_8C 61 | #define UIFM_REG_RD on stdcore[0] : XS1_PORT_8D 62 | #define UIFM_FLAG_0 on stdcore[0] : XS1_PORT_1N 63 | #define UIFM_FLAG_1 on stdcore[0] : XS1_PORT_1O 64 | #define UIFM_FLAG_2 on stdcore[0] : XS1_PORT_1P 65 | 66 | // ULPI (internal) 67 | #define ULPI_STP on stdcore[0] : XS1_PORT_1E 68 | #define ULPI_NXT on stdcore[0] : XS1_PORT_1F 69 | #define ULPI_DATA on stdcore[0] : XS1_PORT_8B 70 | #define ULPI_DIR on stdcore[0] : XS1_PORT_1G 71 | #define ULPI_CLK on stdcore[0] : XS1_PORT_1H 72 | 73 | // XSYS / link A (internal) 74 | #define XSYS on stdcore[0] : XS1_PORT_4B 75 | #define LINK_A on stdcore[0] : XS1_PORT_4B 76 | 77 | // 1V0 board 78 | #if 0 79 | 80 | // SPI 81 | #define SPI_MISO on stdcore[0] : XS1_PORT_1A 82 | #define SPI_SS on stdcore[0] : XS1_PORT_1B 83 | #define SPI_SCK on stdcore[0] : XS1_PORT_1C 84 | #define SPI_MOSI on stdcore[0] : XS1_PORT_1D 85 | 86 | // clocking 87 | #define WCK_BNC on stdcore[0] : XS1_PORT_1I 88 | #define SYNC_0 on stdcore[0] : XS1_PORT_1J 89 | #define SYNC_1 on stdcore[1] : XS1_PORT_1K 90 | #define MCK_0 on stdcore[0] : XS1_PORT_1L 91 | #define MCK_1 on stdcore[1] : XS1_PORT_1L 92 | 93 | // I2S 94 | #define BCK on stdcore[1] : XS1_PORT_1I 95 | #define WCK on stdcore[1] : XS1_PORT_1E 96 | #define DAC0 on stdcore[1] : XS1_PORT_1M 97 | #define DAC1 on stdcore[1] : XS1_PORT_1F 98 | #define DAC2 on stdcore[1] : XS1_PORT_1H 99 | #define DAC3 on stdcore[1] : XS1_PORT_1N 100 | #define ADC0 on stdcore[1] : XS1_PORT_1G 101 | #define ADC1 on stdcore[1] : XS1_PORT_1A 102 | #define ADC2 on stdcore[1] : XS1_PORT_1B 103 | 104 | // S/PDIF 105 | #define SPDIF_RX on stdcore[0] : XS1_PORT_1K 106 | #define SPDIF_TX on stdcore[1] : XS1_PORT_1J 107 | 108 | // MIDI 109 | #define MIDI_OUT on stdcore[1] : XS1_PORT_1O 110 | #define MIDI_IN on stdcore[1] : XS1_PORT_1P 111 | 112 | // control 113 | // RST_MCK_BUF bit 0: MCK SEL, bit 1: CODEC MODE, bit 3: CODEC RST (active low) 114 | // INT_LOCK bit 1: PLL LOCK, bit 3: CODEC INT 115 | #define PHY_RST on stdcore[0] : XS1_PORT_1M 116 | #define I2C_SDA on stdcore[1] : XS1_PORT_1C 117 | #define I2C_SCL on stdcore[1] : XS1_PORT_1D 118 | #define LEDS on stdcore[1] : XS1_PORT_8B 119 | #define INT_LOCK on stdcore[1] : XS1_PORT_4B 120 | #define RST_MCK_BUF on stdcore[1] : XS1_PORT_4A 121 | 122 | // UIFM 123 | #define UIFM_TXD on stdcore[0] : XS1_PORT_8A 124 | #define UIFM_RXD on stdcore[0] : XS1_PORT_8B 125 | #define UIFM_STP_SUS on stdcore[0] : XS1_PORT_1E 126 | #define UIFM_USB_CLK on stdcore[0] : XS1_PORT_1H 127 | #define UIFM_REG_WR on stdcore[0] : XS1_PORT_8C 128 | #define UIFM_REG_RD on stdcore[0] : XS1_PORT_8D 129 | #define UIFM_FLAG_0 on stdcore[0] : XS1_PORT_1N 130 | #define UIFM_FLAG_1 on stdcore[0] : XS1_PORT_1O 131 | #define UIFM_FLAG_2 on stdcore[0] : XS1_PORT_1P 132 | 133 | // ULPI (internal) 134 | #define ULPI_STP on stdcore[0] : XS1_PORT_1E 135 | #define ULPI_NXT on stdcore[0] : XS1_PORT_1F 136 | #define ULPI_DATA on stdcore[0] : XS1_PORT_8B 137 | #define ULPI_DIR on stdcore[0] : XS1_PORT_1G 138 | #define ULPI_CLK on stdcore[0] : XS1_PORT_1H 139 | 140 | // XSYS / link A (internal) 141 | #define XSYS on stdcore[0] : XS1_PORT_4B 142 | #define LINK_A on stdcore[0] : XS1_PORT_4B 143 | 144 | #endif 145 | -------------------------------------------------------------------------------- /app_par_audio_dsp/timing_checks.xta: -------------------------------------------------------------------------------- 1 | # load "/Users/thomas_mac/Dropbox/git/external/xcore_github/ap_par_audio_DSP/app_par_audio_DSP/bin/XR-USB-AUDIO-2.0-MC/app_par_audio_DSP.xe" 2 | 3 | # 4 | # Route: function: biquad_cascade_eq 5 | # 6 | analyze function biquad_cascade_eq 7 | # Warning: '0x103a0' is a non-portable reference. 8 | set loop - call_0,0x103a0 5 9 | set required - 21.0 us 10 | 11 | print summary -------------------------------------------------------------------------------- /doc/CHANGELOG: -------------------------------------------------------------------------------- 1 | XMOS Audio DSP example using shared memory and parallel processing. 2 | =================================================================== 3 | 4 | Release version: 0.6 5 | 6 | Firmware 7 | ======== 8 | * 0.6 9 | Fixed bug (coefficients loaded in wrong order) in assembly version of biquad. 10 | Added Simulator mode for development/debug without HW. 11 | XTA script run during compilation. 12 | Improved structure for github 13 | 14 | * 0.5 15 | Replaced Shared memory buffering scheme with communication over streaming channels. 16 | Block processing is not necessary for Biquad. 17 | Channels are more efficient for per-sample processing of the stream (saves memory and instructions per sample) 18 | Note: For shared memory version contact: thomas@xmos.com 19 | Integrated the latest Biquad Package from https://github.com/xcore/sc_dsp_filters: 20 | Optimised Assembly Biquad implementation, Saturation 21 | 22 | * 0.4 23 | Improved Equaliser (now using Peak EQ filters) 24 | Increased attenuation of crossover shelf filters 25 | Fixed delay buffers and delays example. 26 | XTA timing checks. 27 | Refactoring and cleanup 28 | Improved README.txt 29 | Added swc_cascaded_biquad package for generating coefficients for lowshelf, highshelf and peak EQ filters 30 | 31 | * 0.3 32 | Override Input and output signals with custom signal generators 33 | XScope Probes (real-time oscilloscope-style analysis) in IIC interface code. 34 | 35 | * 0.2 36 | Added Crossover using Low Shelf and High Shelf Filters. Crossover frequency 500 Hz 37 | 38 | * 0.1 39 | Added xta timing checks. See README.txt 40 | Increased Biquad BANKS to 5 41 | Activated Cascaded Biquads (they were accidentally disabled in 0.0) 42 | 43 | 44 | 45 | --------------------------------------------------------------------------------