├── .gitignore ├── CHANGELOG.rst ├── LICENSE.txt ├── Makefile ├── README.rst ├── app_absolute ├── .cproject ├── .project ├── .xproject ├── Makefile ├── README.rst ├── config.xscope └── src │ └── main.xc ├── app_adc_example ├── .cproject ├── .project ├── .xproject ├── Makefile ├── README.rst ├── config.xscope └── src │ └── main.xc ├── app_audio_dalek ├── .cproject ├── .project ├── .xproject ├── Makefile ├── README.rst └── src │ ├── app_conf.h │ ├── app_global.h │ ├── audio_io.h │ ├── audio_io.xc │ ├── codec.h │ ├── codec.xc │ ├── dsp_biquad.h │ ├── dsp_biquad.xc │ ├── i2s_master_conf.h │ ├── lfo.h │ ├── lfo.xc │ ├── main.h │ ├── main.xc │ ├── module_dsp_biquad_conf.h │ └── xa_sk_audio_1v0.h ├── app_audio_dsp ├── .cproject ├── .project ├── .xproject ├── Makefile ├── README.rst └── src │ ├── app_conf.h │ ├── app_global.h │ ├── audio_io.h │ ├── audio_io.xc │ ├── c_utils.c │ ├── c_utils.h │ ├── codec.h │ ├── codec.xc │ ├── coeffs.h │ ├── coeffs.xc │ ├── control.h │ ├── control.xc │ ├── debug_conf.h │ ├── drc.h │ ├── drc.xc │ ├── dsp.h │ ├── dsp.xc │ ├── i2s_master_conf.h │ ├── level.h │ ├── level.xc │ ├── main.xc │ └── xa_sk_audio_1v0.h ├── app_balance ├── .cproject ├── .project ├── .xproject ├── Makefile ├── README.rst └── src │ ├── acceloremeter.xc │ ├── ball.h │ ├── debug_conf.h │ ├── i2c_conf.h │ └── main.xc ├── app_glowing_leds ├── .cproject ├── .project ├── .xproject ├── Makefile ├── README.rst └── src │ └── main.xc ├── app_noughts_and_crosses ├── .cproject ├── .project ├── .xproject ├── Makefile ├── README.rst ├── config.xscope └── src │ ├── computer_player.h │ ├── computer_player.xc │ ├── debug_conf.h │ ├── game.h │ ├── game.xc │ ├── main.xc │ ├── random.h │ ├── random.xc │ ├── scoring.h │ ├── scoring.xc │ ├── strategy.h │ ├── user_player.h │ └── user_player.xc ├── app_scanning_leds ├── .cproject ├── .project ├── .xproject ├── Makefile ├── README.rst └── src │ └── main.xc ├── app_servo ├── Makefile ├── README.rst ├── config.xscope └── main.xc ├── app_spinning_bar ├── .cproject ├── .project ├── .xproject ├── Makefile ├── README.rst └── src │ └── main.xc ├── app_spinning_dot ├── .cproject ├── .project ├── .xproject ├── Makefile ├── README.rst └── src │ └── main.xc ├── host_dsp_control ├── Makefile └── dsp_control.c ├── host_dsp_gui ├── CMakeLists.txt └── src │ ├── biquad_controls.cpp │ ├── biquad_controls.h │ ├── biquad_slider.h │ ├── biquad_sliders.cpp │ ├── drc_controls.cpp │ ├── drc_controls.h │ ├── drc_spinbox.cpp │ ├── drc_spinbox.h │ ├── main.cpp │ ├── mutex.c │ ├── mutex.h │ ├── qcustomplot.cpp │ ├── qcustomplot.h │ ├── queues.c │ ├── queues.h │ ├── sliders.pro │ ├── window.cpp │ ├── window.h │ ├── xscope_host_shared.c │ └── xscope_host_shared.h ├── module_startkit_adc ├── .cproject ├── .makefile ├── .project ├── .xproject ├── README.rst ├── module_build_info └── src │ ├── startkit_adc.h │ └── startkit_adc.xc ├── module_startkit_gpio ├── .cproject ├── .makefile ├── .project ├── .xproject ├── README.rst ├── module_build_info └── src │ ├── startkit_gpio.h │ └── startkit_gpio.xc ├── module_startkit_servo ├── README.rst ├── module_build_info └── src │ ├── .servo.xc.swp │ ├── servo.h │ └── servo.xc ├── startKIT_port_mapping.h └── xpd.xml /.gitignore: -------------------------------------------------------------------------------- 1 | */.build 2 | */bin 3 | */.settings 4 | *.xmt 5 | *.log 6 | *.zip 7 | *.xe 8 | -------------------------------------------------------------------------------- /CHANGELOG.rst: -------------------------------------------------------------------------------- 1 | startKIT Examples Change Log 2 | ============================= 3 | 4 | 1.2.0 5 | ----- 6 | * Added ADC example and module 7 | 8 | 1.1.0 9 | ----- 10 | * Added dalek example and led scan 11 | 12 | 1.0.0 13 | ----- 14 | * Initial Version 15 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | 2 | Software License Agreement 3 | 4 | Copyright (c) 2011, XMOS Ltd, All rights reserved. 5 | 6 | Additional copyright holders (each contributor holds copyright 7 | over contribution as described in the git commit logs for the repository): 8 | 9 | 10 | Copyright (c) 2011 11 | 12 | The copyright holders hereby grant to any person obtaining a copy of this software (the "Software") and/or its associated 13 | documentation files (the Documentation), the perpetual, irrevocable (except in the case of breach of this license) no-cost, 14 | royalty free, sublicensable rights to use, copy, modify, merge, publish, display, publicly perform, distribute, and/or 15 | sell copies of the Software and the Documentation, together or separately, and to permit persons to whom the Software and/or 16 | Documentation is furnished to do so, subject to the following conditions: 17 | 18 | . Redistributions of the Software in source code must retain the above copyright notice, this list of conditions and the 19 | following disclaimers. 20 | 21 | . Redistributions of the Software in binary form must reproduce the above copyright notice, this list of conditions and 22 | the following disclaimers in the documentation and/or other materials provided with the distribution. 23 | 24 | . Redistributions of the Documentation must retain the above copyright notice, this list of conditions and the following 25 | disclaimers. 26 | 27 | Neither the name of XMOS Ltd, nor the names of its contributors may be used to endorse or promote products derived from this 28 | Software or the Documentation without specific prior written permission of the copyright holder. 29 | 30 | THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 31 | LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 32 | CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 33 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR DOCUMENTATION OR THE USE OF OR OTHER 34 | DEALINGS WITH THE SOFTWARE OR DOCUMENTATION. 35 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | # This variable should contain a space separated list of all 3 | # the directories containing buildable applications (usually 4 | # prefixed with the app_ prefix) 5 | # 6 | # If the variable is set to "all" then all directories that start with app_ 7 | # are built. 8 | BUILD_SUBDIRS = all 9 | 10 | XMOS_MAKE_PATH ?= .. 11 | include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.toplevel 12 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | startKIT developer board examples 2 | ================================= 3 | 4 | :Latest release: 1.2.0rc0 5 | :Maintainer: davelxmos 6 | :Description: startKIT example programs 7 | 8 | 9 | Required software (dependencies) 10 | ================================ 11 | 12 | * sc_i2s (git@github.com:xcore/sc_i2s) 13 | * sc_i2c (git@github.com:xcore/sc_i2c) 14 | * sc_slicekit_support (https://github.com/xcore/sc_slicekit_support.git) 15 | * sw_audio_effects (git@github.com:xcore/sw_audio_effects) 16 | * sc_sdram_burst (https://github.com/xcore/sc_sdram_burst) 17 | * sc_capacitive_sensing (git@github.com:xcore/sc_capacitive_sensing) 18 | * sc_util (git://github.com/xcore/sc_util) 19 | 20 | -------------------------------------------------------------------------------- /app_absolute/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | app_absolute 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.cdt.managedbuilder.core.genmakebuilder 10 | clean,full,incremental, 11 | 12 | 13 | ?children? 14 | ?name?=outputEntries\|?children?=?name?=entry\\\\|\\|\|| 15 | 16 | 17 | ?name? 18 | 19 | 20 | 21 | org.eclipse.cdt.make.core.append_environment 22 | true 23 | 24 | 25 | org.eclipse.cdt.make.core.buildArguments 26 | CONFIG=Debug 27 | 28 | 29 | org.eclipse.cdt.make.core.buildCommand 30 | xmake 31 | 32 | 33 | org.eclipse.cdt.make.core.cleanBuildTarget 34 | clean 35 | 36 | 37 | org.eclipse.cdt.make.core.contents 38 | org.eclipse.cdt.make.core.activeConfigSettings 39 | 40 | 41 | org.eclipse.cdt.make.core.enableAutoBuild 42 | false 43 | 44 | 45 | org.eclipse.cdt.make.core.enableCleanBuild 46 | true 47 | 48 | 49 | org.eclipse.cdt.make.core.enableFullBuild 50 | true 51 | 52 | 53 | org.eclipse.cdt.make.core.stopOnError 54 | true 55 | 56 | 57 | org.eclipse.cdt.make.core.useDefaultBuildCmd 58 | false 59 | 60 | 61 | 62 | 63 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder 64 | full,incremental, 65 | 66 | 67 | 68 | 69 | 70 | org.eclipse.cdt.core.cnature 71 | org.eclipse.cdt.managedbuilder.core.managedBuildNature 72 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature 73 | com.xmos.cdt.core.XdeProjectNature 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /app_absolute/.xproject: -------------------------------------------------------------------------------- 1 | sw_startkit_examplesXM-004098-SM -------------------------------------------------------------------------------- /app_absolute/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = STARTKIT 2 | APP_NAME = 3 | XCC_FLAGS = -O3 4 | USED_MODULES = module_startkit_gpio 5 | 6 | #============================================================================= 7 | # The following part of the Makefile includes the common build infrastructure 8 | # for compiling XMOS applications. You should not need to edit below here. 9 | 10 | XMOS_MAKE_PATH ?= ../.. 11 | include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.common 12 | -------------------------------------------------------------------------------- /app_absolute/README.rst: -------------------------------------------------------------------------------- 1 | Absolute position 2 | ================= 3 | 4 | :scope: Example 5 | :description: A simple demo showing the use of slides and leds on startKIT. 6 | :keywords: capacitive, sensors, startKIT 7 | 8 | This program demonstrates that sliders can be used to read an (approximate) 9 | X and Y location. The position is highlighted by means of an (anti aliased) 10 | LED. Moving a finger along either slider will move the LED along. 11 | 12 | 13 | Implementation 14 | -------------- 15 | 16 | There are three tasks: 17 | 18 | * A task to drive the leds and capacitive sensors. This uses the 19 | driver found in ``module_starkit_gpio`` 20 | * A task that performs the output. It averages out a virtual ball position 21 | and sets the LED levels to display its position in an antialised manner. 22 | * A task that reacts to the capacitive sense events and uses them to 23 | update the ball display task. 24 | -------------------------------------------------------------------------------- /app_absolute/config.xscope: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app_absolute/src/main.xc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "startkit_gpio.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | typedef interface ball_if { 11 | void new_position(int x, int y, int z); 12 | } ball_if; 13 | 14 | 15 | #define HISTORY_LEN 32 16 | 17 | struct history { 18 | int values[HISTORY_LEN]; // A filter that holds 32 old values 19 | int w; // index of the oldest value in the array 20 | int av; // Running average of all struct 21 | }; 22 | 23 | static int filter(struct history &h, int value) { 24 | h.av += value; 25 | h.av -= h.values[h.w]; 26 | h.values[h.w] = value; 27 | h.w++; 28 | if (h.w == HISTORY_LEN) { 29 | h.w = 0; 30 | } 31 | return h.av/HISTORY_LEN; 32 | } 33 | 34 | 35 | // This is the range of the ball, i.e. the x,y,z coordinates will 36 | // be between -BALL_RANGE and +BALL_RANGE 37 | #define BALL_RANGE 700 38 | 39 | [[combinable]] 40 | void ball(server ball_if ball, client startkit_led_if leds) { 41 | struct history history_x, history_y, history_z; 42 | history_x.w = history_y.w = history_z.w = 0; 43 | history_x.av = history_y.av = history_z.av = 0; 44 | 45 | for(int i = 0; i < HISTORY_LEN; i++) { 46 | history_x.values[i] = history_y.values[i] = history_z.values[i] = 0; 47 | } 48 | 49 | while(1) { 50 | select { 51 | case ball.new_position(int new_x, int new_y, int new_z): 52 | int x, y, z; 53 | 54 | // Average the ball position over recent history 55 | x = filter(history_x, new_x); 56 | y = filter(history_y, new_y); 57 | z = filter(history_z, new_z); 58 | 59 | // Split the position into sign and magnitude 60 | // where the magnitude is between 0..LED_ON 61 | int sx = x < 0 ? -1 : 1; 62 | int sy = y < 0 ? -1 : 1; 63 | unsigned px, py; 64 | px = abs(x); 65 | px = px > BALL_RANGE ? BALL_RANGE : px; 66 | px = px * LED_ON/BALL_RANGE; 67 | 68 | py = abs(y); 69 | py = py > BALL_RANGE ? BALL_RANGE : py; 70 | py = py * LED_ON/BALL_RANGE; 71 | 72 | // Clear all led levels 73 | leds.set_multiple(0b111111111, 0); 74 | 75 | // Set the leds to show the ball position 76 | leds.set(1, 1, (LED_ON - px) * (LED_ON - py) / LED_ON); 77 | leds.set(1, 1 + sy, (LED_ON - px) * py / LED_ON); 78 | leds.set(1 + sx, 1, (px * (LED_ON - py)) / LED_ON); 79 | leds.set(1 + sx, 1 + sy, (px * py) / LED_ON); 80 | break; 81 | } 82 | } 83 | } 84 | 85 | [[combinable]] 86 | void drive_ball(client slider_if i_slider_x, 87 | client slider_if i_slider_y, 88 | client ball_if i_ball) 89 | { 90 | timer tmr; 91 | int t; 92 | int poll_period = 100000; 93 | tmr :> t; 94 | while (1) { 95 | select { 96 | case tmr when timerafter(t + poll_period) :> t: 97 | int x = i_slider_x.get_coord(); 98 | int y = i_slider_y.get_coord(); 99 | // Capsense returns in range 0..3000, adjust so 0 is centre 100 | x -= 1500; 101 | y -= 1500; 102 | xscope_int(PROBEX, x); 103 | xscope_int(PROBEY, y); 104 | i_ball.new_position(x, y, 0); 105 | t += poll_period; 106 | break; 107 | } 108 | } 109 | } 110 | 111 | /* This the port where the leds reside */ 112 | startkit_gpio_ports gpio_ports = 113 | {XS1_PORT_32A, XS1_PORT_4A, XS1_PORT_4B, XS1_CLKBLK_1}; 114 | 115 | int main(void) { 116 | // These interfaces connect the tasks below together 117 | ball_if i_ball; 118 | startkit_led_if i_led; 119 | slider_if i_slider_x, i_slider_y; 120 | par { 121 | on tile[0].core[0]: drive_ball(i_slider_x, i_slider_y, i_ball); 122 | 123 | // This task reads the ball position from the accelerometer task 124 | // when there is a change and updates the LED values based on 125 | // that position 126 | on tile[0].core[1]: ball(i_ball, i_led); 127 | 128 | // The led driver task 129 | on tile[0].core[2]: startkit_gpio_driver(i_led, null, 130 | i_slider_x, i_slider_y, 131 | gpio_ports); 132 | } 133 | return 0; 134 | } 135 | 136 | -------------------------------------------------------------------------------- /app_adc_example/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | app_adc_example 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.cdt.managedbuilder.core.genmakebuilder 10 | clean,full,incremental, 11 | 12 | 13 | ?children? 14 | ?name?=outputEntries\|?children?=?name?=entry\\\\|\\|\|| 15 | 16 | 17 | ?name? 18 | 19 | 20 | 21 | org.eclipse.cdt.make.core.append_environment 22 | true 23 | 24 | 25 | org.eclipse.cdt.make.core.buildArguments 26 | CONFIG=Debug 27 | 28 | 29 | org.eclipse.cdt.make.core.buildCommand 30 | xmake 31 | 32 | 33 | org.eclipse.cdt.make.core.cleanBuildTarget 34 | clean 35 | 36 | 37 | org.eclipse.cdt.make.core.contents 38 | org.eclipse.cdt.make.core.activeConfigSettings 39 | 40 | 41 | org.eclipse.cdt.make.core.enableAutoBuild 42 | false 43 | 44 | 45 | org.eclipse.cdt.make.core.enableCleanBuild 46 | true 47 | 48 | 49 | org.eclipse.cdt.make.core.enableFullBuild 50 | true 51 | 52 | 53 | org.eclipse.cdt.make.core.stopOnError 54 | true 55 | 56 | 57 | org.eclipse.cdt.make.core.useDefaultBuildCmd 58 | false 59 | 60 | 61 | 62 | 63 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder 64 | full,incremental, 65 | 66 | 67 | 68 | 69 | 70 | org.eclipse.cdt.core.cnature 71 | org.eclipse.cdt.managedbuilder.core.managedBuildNature 72 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature 73 | com.xmos.cdt.core.XdeProjectNature 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /app_adc_example/.xproject: -------------------------------------------------------------------------------- 1 | sw_startkit_examplesXM-004098-SM -------------------------------------------------------------------------------- /app_adc_example/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 | TARGET = STARTKIT 5 | 6 | # The APP_NAME variable determines the name of the final .xe file. It should 7 | # not include the .xe postfix. If left blank the name will default to 8 | # the project name 9 | APP_NAME = 10 | 11 | # The USED_MODULES variable lists other module used by the application. 12 | USED_MODULES = module_startkit_adc module_startkit_gpio 13 | 14 | # The flags passed to xcc when building the application 15 | # You can also set the following to override flags for a particular language: 16 | # XCC_XC_FLAGS, XCC_C_FLAGS, XCC_ASM_FLAGS, XCC_CPP_FLAGS 17 | # If the variable XCC_MAP_FLAGS is set it overrides the flags passed to 18 | # xcc for the final link (mapping) stage. 19 | XCC_FLAGS = -O3 -g -report 20 | 21 | # The XCORE_ARM_PROJECT variable, if set to 1, configures this 22 | # project to create both xCORE and ARM binaries. 23 | XCORE_ARM_PROJECT = 0 24 | 25 | # The VERBOSE variable, if set to 1, enables verbose output from the make system. 26 | VERBOSE = 0 27 | 28 | XMOS_MAKE_PATH ?= ../.. 29 | -include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.common 30 | -------------------------------------------------------------------------------- /app_adc_example/README.rst: -------------------------------------------------------------------------------- 1 | ADC Example 2 | =========== 3 | 4 | :scope: Example 5 | :description: A simple demo that lights LEDs proportionally to the ADC inputs 6 | :keywords: LEDs, startKIT, ADC 7 | 8 | 9 | Very simple example of using the ADC module. It uses the ADC in one shot mode (each time trigger is called every 200ms from a timer) and then reads the 4 values after conversion complete notification received. It also shows an example of a select (wait on multiple events) because it also listens to the button, and lights additional LEDs when that is pressed. 10 | 11 | Touch the ADC0..ADC3 pads/pins in the bottom left hand corner to light the LEDs! 12 | 13 | The values are also printed on the screen (ensure xscope i/o is enabled in the GUI, or use xrun --xscope at the command line). -------------------------------------------------------------------------------- /app_adc_example/config.xscope: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /app_adc_example/src/main.xc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "startkit_gpio.h" 7 | #include "startkit_adc.h" 8 | 9 | #define LOOP_PERIOD 20000000 //Trigger ADC and print results every 200ms 10 | 11 | startkit_gpio_ports gpio_ports = {XS1_PORT_32A, XS1_PORT_4A, XS1_PORT_4B, XS1_CLKBLK_1}; //LEDs/SW, sliders, clock 12 | 13 | 14 | void app(client startkit_led_if i_leds, client startkit_button_if i_button, client startkit_adc_if i_adc) 15 | { 16 | timer t_loop; //Loop timer 17 | int loop_time; //Loop time comparison variable 18 | 19 | unsigned short adc_val[4] = {0, 0, 0, 0};//ADC vals 20 | 21 | printstrln("App started"); 22 | 23 | t_loop :> loop_time; //Take the initial timestamp of the 100Mhz timer 24 | loop_time += LOOP_PERIOD; //Set comparison to future time 25 | while (1) { 26 | select { 27 | 28 | case i_button.changed(): //Button event 29 | if (i_button.get_value() == BUTTON_DOWN) { 30 | printstrln("Button pressed!"); 31 | i_leds.set(2, 2, LED_ON); 32 | i_leds.set(1, 2, LED_ON); 33 | i_leds.set(0, 2, LED_ON); 34 | } 35 | else { 36 | printstrln("Button released!"); 37 | i_leds.set(2, 2, LED_OFF); 38 | i_leds.set(1, 2, LED_OFF); 39 | i_leds.set(0, 2, LED_OFF); 40 | } 41 | break; 42 | //Loop timeout event 43 | case t_loop when timerafter(loop_time) :> void: 44 | i_adc.trigger(); //Fire the ADC! 45 | loop_time += LOOP_PERIOD; //Setup future time event 46 | break; 47 | 48 | case i_adc.complete(): //Notification from ADC server when aquisition complete 49 | i_adc.read(adc_val); //Get the values (and clear the notfication) 50 | for(int i = 0; i < 4; i++){ 51 | printstr("ADC chan "); 52 | printint(i); 53 | printstr(" = "); 54 | printint(adc_val[i]); 55 | if (i < 3) printstr(", "); 56 | switch (i){ //Map ADC channels to align with LEDs on startKIT 57 | case 0: 58 | i_leds.set(1, 1, adc_val[i]); 59 | break; 60 | case 1: 61 | i_leds.set(2, 0, adc_val[i]); 62 | break; 63 | case 2: 64 | i_leds.set(0, 1, adc_val[i]); 65 | break; 66 | case 3: 67 | i_leds.set(1, 0, adc_val[i]); 68 | break; 69 | } 70 | } 71 | printchar('\n'); 72 | break; 73 | }//select 74 | }//while 1 75 | } 76 | 77 | 78 | int main() 79 | { 80 | // These interface connections link the application to the GPIO task and ADC driver task 81 | startkit_led_if i_led; //For setting LEDs 82 | startkit_button_if i_button; //For reading the button 83 | startkit_adc_if i_adc; //For triggering/reading ADC 84 | chan c_adc; //Used by ADC driver to connect to ADC hardware 85 | 86 | par { 87 | on tile[0].core[0]: startkit_gpio_driver(i_led, i_button,//Run GPIO task for leds/button 88 | null, null, 89 | gpio_ports); 90 | on tile[0].core[0]: adc_task(i_adc, c_adc, 0); //Run ADC server task (on same core as GPIO!) 91 | startkit_adc(c_adc); //Declare the ADC service (this is the ADC hardware, not a task) 92 | on tile[0]: app(i_led, i_button, i_adc); //Run the app 93 | } 94 | return 0; 95 | } 96 | 97 | -------------------------------------------------------------------------------- /app_audio_dalek/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | app_audio_dalek 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.cdt.managedbuilder.core.genmakebuilder 10 | clean,full,incremental, 11 | 12 | 13 | ?children? 14 | ?name?=outputEntries\|?children?=?name?=entry\\\\|\\|\|| 15 | 16 | 17 | ?name? 18 | 19 | 20 | 21 | org.eclipse.cdt.make.core.append_environment 22 | true 23 | 24 | 25 | org.eclipse.cdt.make.core.buildArguments 26 | CONFIG=Debug 27 | 28 | 29 | org.eclipse.cdt.make.core.buildCommand 30 | xmake 31 | 32 | 33 | org.eclipse.cdt.make.core.cleanBuildTarget 34 | clean 35 | 36 | 37 | org.eclipse.cdt.make.core.contents 38 | org.eclipse.cdt.make.core.activeConfigSettings 39 | 40 | 41 | org.eclipse.cdt.make.core.enableAutoBuild 42 | false 43 | 44 | 45 | org.eclipse.cdt.make.core.enableCleanBuild 46 | true 47 | 48 | 49 | org.eclipse.cdt.make.core.enableFullBuild 50 | true 51 | 52 | 53 | org.eclipse.cdt.make.core.stopOnError 54 | true 55 | 56 | 57 | org.eclipse.cdt.make.core.useDefaultBuildCmd 58 | false 59 | 60 | 61 | 62 | 63 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder 64 | full,incremental, 65 | 66 | 67 | 68 | 69 | 70 | org.eclipse.cdt.core.cnature 71 | org.eclipse.cdt.managedbuilder.core.managedBuildNature 72 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature 73 | com.xmos.cdt.core.XdeProjectNature 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /app_audio_dalek/.xproject: -------------------------------------------------------------------------------- 1 | sw_startkit_examplesXM-004098-SM -------------------------------------------------------------------------------- /app_audio_dalek/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 = STARTKIT 6 | APP_NAME = startkit_dalek 7 | 8 | # The flags passed to xcc when building the application 9 | BUILD_FLAGS = -Wall -O3 -report -g -DSDA_HIGH=2 -DSCL_HIGH=1 10 | 11 | # The USED_MODULES variable lists other module used by the application. These 12 | # modules will extend the SOURCE_DIRS, INCLUDE_DIRS and LIB_DIRS variables. 13 | # Modules are expected to be in the directory above the BASE_DIR directory. 14 | USED_MODULES = module_capacitive_sensing module_dsp_biquad module_dsp_utils module_i2c_single_port module_i2s_master module_startkit_gpio 15 | 16 | XCC_FLAGS = $(BUILD_FLAGS) -fxscope 17 | 18 | #============================================================================= 19 | # The following part of the Makefile includes the common build infrastructure 20 | # for compiling XMOS applications. You should not need to edit below here. 21 | 22 | XMOS_MAKE_PATH ?= ../.. 23 | include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.common 24 | 25 | VERBOSE = 0 26 | -------------------------------------------------------------------------------- /app_audio_dalek/README.rst: -------------------------------------------------------------------------------- 1 | Startkit Dalek example 2 | ================================= 3 | 4 | :scope: Example 5 | :description: Does ring modulation (AM of LFO) and applies a BiQuad filter to a stereo stream on the startKIT/audio slice boards 6 | :keywords: biquad, filter, equalisation, audio, dsp, slicekit 7 | :boards: XA-SK-AUDIO 8 | 9 | The sliders control modulation depth and frequency of the triangular LFO. 10 | Button toggles between Dry and Effect signals, each time the Effect is called a different filter is used. The LED shows where you are in the cycle. 11 | The filter cycles through the following pre-defined types: Low Pass, High Pass, Band Pass, Band Stop, All Pass 12 | 13 | * The Audio_IO uses 1 logical core (aka thread). 14 | * The LFO uses 1 logical core. 15 | * The DSP BiQuad function uses 1 logical core. 16 | * The LED/Buttons/Slider interface uses 1 logical core too -------------------------------------------------------------------------------- /app_audio_dalek/src/app_conf.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************\ 2 | * Header: app_conf 3 | * File: app_conf.h 4 | * 5 | * Description: Definitions for configuration of application. 6 | * NB These definitions will be passed to all modules used in application 7 | * 8 | * Version: 0v1 9 | * Build: 10 | * 11 | * The copyrights, all other intellectual and industrial 12 | * property rights are retained by XMOS and/or its licensors. 13 | * Terms and conditions covering the use of this code can 14 | * be found in the Xmos End User License Agreement. 15 | * 16 | * Copyright XMOS Ltd 2012 17 | * 18 | * In the case where this code is a modification of existing code 19 | * under a separate license, the separate license terms are shown 20 | * below. The modifications to the code are still covered by the 21 | * copyright notice above. 22 | * 23 | \******************************************************************************/ 24 | 25 | #ifndef _APP_CONF_H_ 26 | #define _APP_CONF_H_ 27 | 28 | /** Number of audio channels used in this application */ 29 | #define NUM_APP_CHANS 2 30 | 31 | /** Number of BiQuad filters used in this application */ 32 | #define NUM_APP_BIQUADS 1 33 | 34 | #endif // _APP_CONF_H_ 35 | /******************************************************************************/ 36 | // app_conf.h 37 | -------------------------------------------------------------------------------- /app_audio_dalek/src/app_global.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************\ 2 | * Header: app_global 3 | * File: app_global.h 4 | * 5 | * Description: Global Definitions, types, and prototypes for application 6 | * 7 | * Version: 0v1 8 | * Build: 9 | * 10 | * The copyrights, all other intellectual and industrial 11 | * property rights are retained by XMOS and/or its licensors. 12 | * Terms and conditions covering the use of this code can 13 | * be found in the Xmos End User License Agreement. 14 | * 15 | * Copyright XMOS Ltd 2012 16 | * 17 | * In the case where this code is a modification of existing code 18 | * under a separate license, the separate license terms are shown 19 | * below. The modifications to the code are still covered by the 20 | * copyright notice above. 21 | * 22 | \******************************************************************************/ 23 | 24 | 25 | 26 | #ifndef _APP_GLOBAL_H_ 27 | #define _APP_GLOBAL_H_ 28 | 29 | // Comment-out if NOT using xscope 30 | #define USE_XSCOPE 1 31 | 32 | // Tile that Audio Slice is connected to 33 | #define AUDIO_IO_TILE 0 // Tile connected to Audio Slice board 34 | #define DSP_TILE 0 // Tile used by DSP functions 35 | 36 | // Audio sample frequency (Hz) 37 | #define SAMP_FREQ 48000 38 | 39 | // Audio Slice hardware version 40 | #define AUDIO_SLICE_HW_MAJOR 1 41 | #define AUDIO_SLICE_HW_MINOR 1 42 | 43 | // Audio clocking defines 44 | // Master clock defines (Hz) 45 | #define MCLK_FREQ_441 (512*44100) // 44.1, 88.2 etc 46 | #define MCLK_FREQ_48 (512*48000) // 48, 96 etc 47 | 48 | #if (SAMP_FREQ%22050==0) 49 | #define MCLK_FREQ MCLK_FREQ_441 50 | #elif (SAMP_FREQ%24000==0) 51 | #define MCLK_FREQ MCLK_FREQ_48 52 | #else 53 | #error Unsupported sample frequency 54 | #endif 55 | 56 | // Bit clock divide 57 | #define BCLK_DIV (MCLK_FREQ / (SAMP_FREQ * 64)) 58 | 59 | // Ports 60 | #if ((AUDIO_SLICE_HW_MAJOR == 1) && (AUDIO_SLICE_HW_MINOR == 1)) 61 | #define PORT_I2S_DAC0 XS1_PORT_1G 62 | #define PORT_I2S_DAC1 XS1_PORT_1H 63 | #define PORT_I2S_ADC0 XS1_PORT_1K 64 | #define PORT_I2S_ADC1 XS1_PORT_1L 65 | #define PORT_I2S_LRCLK XS1_PORT_1I 66 | #define PORT_I2S_BCLK XS1_PORT_1F 67 | #define PORT_MCLK_IN XS1_PORT_1E 68 | 69 | #define PORT_GPIO XS1_PORT_4C 70 | #define PORT_I2C XS1_PORT_4D 71 | 72 | #else 73 | #error currently not un-supported slice hw version 74 | #endif 75 | 76 | #endif // ifndef _APP_GLOBAL_H_ 77 | /*****************************************************************************/ 78 | // app_global.h 79 | -------------------------------------------------------------------------------- /app_audio_dalek/src/audio_io.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************\ 2 | * Header: audio_io 3 | * File: audio_io.h 4 | * 5 | * Description: Definitions, types, and prototypes for audio_io.xc 6 | * 7 | * Version: 0v1 8 | * Build: 9 | * 10 | * The copyrights, all other intellectual and industrial 11 | * property rights are retained by XMOS and/or its licensors. 12 | * Terms and conditions covering the use of this code can 13 | * be found in the Xmos End User License Agreement. 14 | * 15 | * Copyright XMOS Ltd 2012 16 | * 17 | * In the case where this code is a modification of existing code 18 | * under a separate license, the separate license terms are shown 19 | * below. The modifications to the code are still covered by the 20 | * copyright notice above. 21 | * 22 | \******************************************************************************/ 23 | 24 | #ifndef _AUDIO_IO_H_ 25 | #define _AUDIO_IO_H_ 26 | 27 | #include 28 | #include "i2c.h" 29 | #include "codec.h" 30 | #include "i2s_master.h" 31 | #include "app_global.h" 32 | 33 | /******************************************************************************/ 34 | void audio_io( 35 | streaming chanend c_aud // Audio end of channel between I/O and DSP coar 36 | ); 37 | /******************************************************************************/ 38 | 39 | #endif // _AUDIO_IO_H_ 40 | /******************************************************************************/ 41 | // audio_io.h 42 | -------------------------------------------------------------------------------- /app_audio_dalek/src/audio_io.xc: -------------------------------------------------------------------------------- 1 | /******************************************************************************\ 2 | * File: audio_io.xc 3 | * 4 | * Description: Audio I/O Coar 5 | * 6 | * Version: 0v1 7 | * Build: 8 | * 9 | * The copyrights, all other intellectual and industrial 10 | * property rights are retained by XMOS and/or its licensors. 11 | * Terms and conditions covering the use of this code can 12 | * be found in the Xmos End User License Agreement. 13 | * 14 | * Copyright XMOS Ltd 2012 15 | * 16 | * In the case where this code is a modification of existing code 17 | * under a separate license, the separate license terms are shown 18 | * below. The modifications to the code are still covered by the 19 | * copyright notice above. 20 | * 21 | \******************************************************************************/ 22 | 23 | #include "audio_io.h" 24 | 25 | // Global Structure for I2S resources 26 | on stdcore[AUDIO_IO_TILE] : r_i2s i2s_resource_s = 27 | { 28 | XS1_CLKBLK_1, 29 | XS1_CLKBLK_2, 30 | PORT_MCLK_IN, // Master Clock 31 | PORT_I2S_BCLK, // Bit Clock 32 | PORT_I2S_LRCLK, // LR Clock 33 | 34 | #if I2S_MASTER_NUM_CHANS_ADC == 4 35 | {PORT_I2S_ADC0, PORT_I2S_ADC1}, 36 | #elif I2S_MASTER_NUM_CHANS_ADC == 2 37 | {PORT_I2S_ADC0}, 38 | #else 39 | #error Unsupported No Of I2S_MASTER_NUM_CHANS_ADC Channels 40 | #endif 41 | 42 | #if I2S_MASTER_NUM_CHANS_DAC == 4 43 | {PORT_I2S_DAC0, PORT_I2S_DAC1} 44 | #elif I2S_MASTER_NUM_CHANS_DAC == 2 45 | {PORT_I2S_DAC0} 46 | #else 47 | #error Unsupported No Of I2S_MASTER_NUM_CHANS_DAC Channels 48 | #endif 49 | 50 | }; // r_i2s 51 | 52 | on stdcore[AUDIO_IO_TILE] : port p_i2c = PORT_I2C; 53 | on stdcore[AUDIO_IO_TILE] : out port p_gpio = PORT_GPIO; 54 | 55 | /*****************************************************************************/ 56 | void audio_hw_init() // Initialise HardWare 57 | { 58 | // Initialise the I2C bus 59 | i2c_master_init( p_i2c ); 60 | } // audio_hw_init 61 | /*****************************************************************************/ 62 | void audio_hw_config( // Setup the CODEC for use. 63 | unsigned samFreq // Sample frequency 64 | ) 65 | { 66 | // Note we do this everytime since we reset CODEC on Sample-Frequency change 67 | codec_config( samFreq ,MCLK_FREQ ); 68 | } 69 | /*****************************************************************************/ 70 | void audio_io( // Audio I/O coar 71 | streaming chanend c_aud // Audio end of channel between I/O and DSP coars 72 | ) 73 | { 74 | unsigned mclk_bclk_div = MCLK_FREQ/(SAMP_FREQ * 64); // Calculate Bit-clock frequency 75 | 76 | 77 | audio_hw_init(); // Configure the CODECs 78 | 79 | audio_hw_config( SAMP_FREQ ); // Configure the clocking 80 | 81 | i2s_master( i2s_resource_s ,c_aud ,mclk_bclk_div ); // Call I2S master loop 82 | } // audio_io 83 | /*****************************************************************************/ 84 | // audio_io.xc 85 | -------------------------------------------------------------------------------- /app_audio_dalek/src/codec.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************\ 2 | * Header: config 3 | * File: config.h 4 | * 5 | * Description: Definitions, types, and prototypes for config.xc 6 | * 7 | * Version: 0v1 8 | * Build: 9 | * 10 | * The copyrights, all other intellectual and industrial 11 | * property rights are retained by XMOS and/or its licensors. 12 | * Terms and conditions covering the use of this code can 13 | * be found in the Xmos End User License Agreement. 14 | * 15 | * Copyright XMOS Ltd 2012 16 | * 17 | * In the case where this code is a modification of existing code 18 | * under a separate license, the separate license terms are shown 19 | * below. The modifications to the code are still covered by the 20 | * copyright notice above. 21 | * 22 | \******************************************************************************/ 23 | 24 | #ifndef _CODEC_H_ 25 | #define _CODEC_H_ 26 | 27 | #include 28 | #include "i2c.h" 29 | #include "xa_sk_audio_1v0.h" 30 | 31 | extern port p_i2c; 32 | extern out port p_gpio; 33 | 34 | 35 | #define CODEC1_I2C_DEVICE_ADDR (0x90) 36 | #define CODEC2_I2C_DEVICE_ADDR (0x92) 37 | 38 | #define CODEC_DEV_ID_ADDR 0x01 39 | #define CODEC_PWR_CTRL_ADDR 0x02 40 | #define CODEC_MODE_CTRL_ADDR 0x03 41 | #define CODEC_ADC_DAC_CTRL_ADDR 0x04 42 | #define CODEC_TRAN_CTRL_ADDR 0x05 43 | #define CODEC_MUTE_CTRL_ADDR 0x06 44 | #define CODEC_DACA_VOL_ADDR 0x07 45 | #define CODEC_DACB_VOL_ADDR 0x08 46 | 47 | #define IIC_REGWRITE(reg, val) {data[0] = val; i2c_master_write_reg(CODEC1_I2C_DEVICE_ADDR, reg, data, 1, p_i2c);data[0] = val; i2c_master_write_reg(CODEC2_I2C_DEVICE_ADDR, reg, data, 1, p_i2c);} 48 | #define IIC_REGREAD(reg, val) {i2c_master_read_reg(CODEC1_I2C_DEVICE_ADDR, reg, val, 1, p_i2c);} 49 | 50 | /*****************************************************************************/ 51 | void codec_config( // Configure Codec 52 | unsigned samFreq, // Sample Frequency 53 | unsigned mClk // Master Clock 54 | ); 55 | /*****************************************************************************/ 56 | 57 | #endif // _CODEC_H_ 58 | /*****************************************************************************/ 59 | // codec.h 60 | -------------------------------------------------------------------------------- /app_audio_dalek/src/codec.xc: -------------------------------------------------------------------------------- 1 | /******************************************************************************\ 2 | * File: codec.xc 3 | * 4 | * Description: Codec Configuration 5 | * 6 | * Version: 0v1 7 | * Build: 8 | * 9 | * The copyrights, all other intellectual and industrial 10 | * property rights are retained by XMOS and/or its licensors. 11 | * Terms and conditions covering the use of this code can 12 | * be found in the Xmos End User License Agreement. 13 | * 14 | * Copyright XMOS Ltd 2012 15 | * 16 | * In the case where this code is a modification of existing code 17 | * under a separate license, the separate license terms are shown 18 | * below. The modifications to the code are still covered by the 19 | * copyright notice above. 20 | * 21 | \******************************************************************************/ 22 | 23 | #include "codec.h" 24 | 25 | #define DO_READ_STATUS 0 26 | 27 | /*****************************************************************************/ 28 | void codec_config( // Configure Codec 29 | unsigned samFreq, // Sample Frequency 30 | unsigned mClk // Master Clock 31 | ) 32 | { 33 | timer t; 34 | unsigned time; 35 | unsigned tmp; 36 | 37 | unsigned char data[1] = {0}; 38 | 39 | /* Set CODEC in reset */ 40 | tmp = P_GPIO_COD_RST_N; 41 | 42 | /* Set master clock select appropriately */ 43 | if ((samFreq % 22050) == 0) 44 | { 45 | tmp &= ~P_GPIO_MCLK_SEL; 46 | } 47 | else //if((samFreq % 24000) == 0) 48 | { 49 | tmp |= P_GPIO_MCLK_SEL; 50 | } 51 | 52 | /* Output to port */ 53 | p_gpio <: tmp; 54 | 55 | /* Hold in reset for 2ms while waiting for MCLK to stabilise */ 56 | t :> time; 57 | time += 200000; 58 | t when timerafter(time) :> int _; 59 | 60 | /* CODEC out of reset */ 61 | tmp |= P_GPIO_COD_RST_N; 62 | p_gpio <: tmp; 63 | 64 | /* Set power down bit in the CODEC over I2C */ 65 | IIC_REGWRITE(CODEC_DEV_ID_ADDR, 0x01); 66 | 67 | 68 | #if DO_READ_STATUS 69 | /* Read CODEC device ID to make sure everything is OK */ 70 | IIC_REGREAD(CODEC_DEV_ID_ADDR, data); 71 | 72 | int codec_dev_id = data[0]; 73 | if (((codec_dev_id & 0xF0) >> 4) != 0xC) 74 | { 75 | printstr("Unexpected CODEC Device ID, expected 0xC, got "); 76 | printhex(codec_dev_id); 77 | } 78 | #endif 79 | 80 | /* Now set all registers as we want them : 81 | Mode Control Reg: 82 | Set FM[1:0] as 11. This sets Slave mode. 83 | Set MCLK_FREQ[2:0] as 010. This sets MCLK to 512Fs in Single, 256Fs in Double and 128Fs in Quad Speed Modes. 84 | This means 24.576MHz for 48k and 22.5792MHz for 44.1k. 85 | Set Popguard Transient Control. 86 | So, write 0x35. */ 87 | IIC_REGWRITE(CODEC_MODE_CTRL_ADDR, 0x35); 88 | 89 | /* ADC & DAC Control Reg: 90 | Leave HPF for ADC inputs continuously running. 91 | Digital Loopback: OFF 92 | DAC Digital Interface Format: I2S 93 | ADC Digital Interface Format: I2S 94 | So, write 0x09. */ 95 | IIC_REGWRITE(CODEC_ADC_DAC_CTRL_ADDR, 0x09); 96 | 97 | /* Transition Control Reg: 98 | No De-emphasis. Don't invert any channels. Independent vol controls. Soft Ramp and Zero Cross enabled.*/ 99 | IIC_REGWRITE(CODEC_TRAN_CTRL_ADDR, 0x60); 100 | 101 | /* Mute Control Reg: Turn off AUTO_MUTE */ 102 | IIC_REGWRITE(CODEC_MUTE_CTRL_ADDR, 0x00); 103 | 104 | /* DAC Chan A Volume Reg: 105 | We don't require vol control so write 0x00 (0dB) */ 106 | IIC_REGWRITE(CODEC_DACA_VOL_ADDR, 0x00); 107 | 108 | /* DAC Chan B Volume Reg: 109 | We don't require vol control so write 0x00 (0dB) */ 110 | IIC_REGWRITE(CODEC_DACB_VOL_ADDR, 0x00); 111 | 112 | /* Clear power down bit in the CODEC over I2C */ 113 | IIC_REGWRITE(CODEC_PWR_CTRL_ADDR, 0x00); 114 | 115 | } // codec_config 116 | /*****************************************************************************/ 117 | // codec.xc 118 | -------------------------------------------------------------------------------- /app_audio_dalek/src/dsp_biquad.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************\ 2 | * Header: dsp_biquad 3 | * File: dsp_biquad.h 4 | * 5 | * Description: Definitions, types, and prototypes for dsp_biquad.xc 6 | * 7 | * Version: 0v1 8 | * Build: 9 | * 10 | * The copyrights, all other intellectual and industrial 11 | * property rights are retained by XMOS and/or its licensors. 12 | * Terms and conditions covering the use of this code can 13 | * be found in the Xmos End User License Agreement. 14 | * 15 | * Copyright XMOS Ltd 2012 16 | * 17 | * In the case where this code is a modification of existing code 18 | * under a separate license, the separate license terms are shown 19 | * below. The modifications to the code are still covered by the 20 | * copyright notice above. 21 | * 22 | \******************************************************************************/ 23 | 24 | #ifndef _DSP_BIQUAD_H_ 25 | #define _DSP_BIQUAD_H_ 26 | 27 | #include 28 | #include 29 | 30 | #include "types64bit.h" 31 | #include "app_global.h" 32 | #include "common_utils.h" 33 | #include "biquad_simple.h" 34 | #include "startkit_gpio.h" 35 | 36 | #ifdef USE_XSCOPE 37 | #include 38 | #endif // ifdef USE_XSCOPE 39 | 40 | #define FX_STR_LEN 10 // Holds Filter names 41 | 42 | typedef struct FX_STR_TAG // Structure to hold one filter name 43 | { 44 | char nam[FX_STR_LEN]; // name string 45 | } FX_STR_S; 46 | 47 | typedef struct FX_NAMES_TAG // Structure to hold all filter names 48 | { 49 | FX_STR_S names[NUM_FILT_MODES]; // array of structures containing a filter name 50 | } FX_NAMES_S; 51 | 52 | 53 | /******************************************************************************/ 54 | void dsp_biquad( // Coar that applies BiQuad filter to stream of audio samples 55 | streaming chanend c_dsp_eq, // Channel connecting to DSP-control coar (bi-directional) 56 | S32_T biquad_id, // Identifies which BiQuad to use 57 | client startkit_led_if i_led, 58 | client startkit_button_if i_button, 59 | chanend c_gain 60 | ); 61 | /******************************************************************************/ 62 | 63 | #endif // _DSP_BIQUAD_H_ 64 | /******************************************************************************/ 65 | // dsp_biquad.h 66 | -------------------------------------------------------------------------------- /app_audio_dalek/src/i2s_master_conf.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************\ 2 | * Header: i2s_master_conf 3 | * File: i2s_master_conf.h 4 | * 5 | * Description: Definitions for configuration of application. 6 | * NB These definitions will be passed to all modules used in application 7 | * 8 | * Version: 0v1 9 | * Build: 10 | * 11 | * The copyrights, all other intellectual and industrial 12 | * property rights are retained by XMOS and/or its licensors. 13 | * Terms and conditions covering the use of this code can 14 | * be found in the Xmos End User License Agreement. 15 | * 16 | * Copyright XMOS Ltd 2012 17 | * 18 | * In the case where this code is a modification of existing code 19 | * under a separate license, the separate license terms are shown 20 | * below. The modifications to the code are still covered by the 21 | * copyright notice above. 22 | * 23 | \******************************************************************************/ 24 | 25 | #ifndef _I2S_MASTER_CONF_H_ 26 | #define _I2S_MASTER_CONF_H_ 27 | 28 | #include "app_conf.h" 29 | 30 | #define I2S_MASTER_NUM_CHANS_ADC NUM_APP_CHANS 31 | #define I2S_MASTER_NUM_CHANS_DAC NUM_APP_CHANS 32 | 33 | #endif // _I2S_MASTER_CONF_H_ 34 | /******************************************************************************/ 35 | // i2s_master_conf.h 36 | -------------------------------------------------------------------------------- /app_audio_dalek/src/lfo.h: -------------------------------------------------------------------------------- 1 | /* 2 | * lfo.h 3 | * 4 | * Created on: Oct 17, 2013 5 | * Author: Ed 6 | */ 7 | 8 | #ifndef LFO_H_ 9 | #define LFO_H_ 10 | 11 | #include "startkit_gpio.h" 12 | 13 | void lfo(chanend c_lfo, client slider_if i_slider_x, client slider_if i_slider_y); 14 | 15 | #endif /* LFO_H_ */ 16 | -------------------------------------------------------------------------------- /app_audio_dalek/src/lfo.xc: -------------------------------------------------------------------------------- 1 | /* 2 | * lfo.xc 3 | * 4 | * Generates a 5 - 40 Hz Triangle waveform and sends it over a channel 5 | * Amplitude and frequency are controlled via the sliders on startKIT 6 | * 7 | * Every millisecond, it sends a new sample across 8 | * 9 | * Created on: Oct 17, 2013 10 | * Author: Ed 11 | */ 12 | 13 | #include "lfo.h" 14 | #include 15 | 16 | #define MILLISECOND 100000 17 | #define SECOND 100000000 18 | #define FSD 0x7fffffff 19 | 20 | #define SLIDER_MIN 1000 21 | #define SLIDER_MAX 2000 22 | 23 | #define LFO_MIN 5 24 | #define LFO_MAX 40 25 | 26 | void lfo(chanend c_lfo, client slider_if i_slider_x, client slider_if i_slider_y) 27 | { 28 | int gain = FSD, dir = 1, time; 29 | int hertz = 30; 30 | int depth = 0; //0 = no effect, FSD = max depth 31 | int slider_pos_x, slider_pos_y; 32 | int step = (FSD/((SECOND/MILLISECOND) / (2 * hertz))); 33 | timer tmr; 34 | tmr :> time; 35 | 36 | while(1){ 37 | 38 | time += MILLISECOND; 39 | select{ 40 | case tmr when timerafter(time) :> time: //Time for a new sample to be generated 41 | if(dir==1) gain += step; //Rising phase of triangle 42 | else gain -= step; //Falling phase of triangle 43 | if (gain >= (FSD-step)) dir = -1; 44 | if (gain <= step) dir = 1; 45 | //c_lfo <: gain; 46 | c_lfo <: FSD - (int) (((long long)depth * (long long)gain) >> 31); 47 | break; 48 | 49 | case i_slider_y.changed_state(): //CHange frequency (ie. step size) 50 | slider_pos_y = i_slider_y.get_coord(); 51 | i_slider_y.get_slider_state(); //necessary to clear notification 52 | if ((slider_pos_y > SLIDER_MIN) && (slider_pos_y < SLIDER_MAX)){ 53 | hertz = LFO_MIN + (((LFO_MAX-LFO_MIN) * (slider_pos_y-SLIDER_MIN)) / (SLIDER_MAX-SLIDER_MIN)); 54 | printint(hertz); 55 | printstrln(" hertz"); 56 | step = (FSD/((SECOND/MILLISECOND) / (2 * hertz))); 57 | } 58 | break; 59 | 60 | case i_slider_x.changed_state(): //CHange modulation depth (ie. amplitude) 61 | slider_pos_x = i_slider_x.get_coord(); 62 | i_slider_x.get_slider_state(); //necessary to clear notification 63 | if ((slider_pos_x > SLIDER_MIN) && (slider_pos_x < SLIDER_MAX)){ 64 | depth = ((FSD / (SLIDER_MAX-SLIDER_MIN)) * (slider_pos_x-SLIDER_MIN)); 65 | } 66 | if ((slider_pos_x < SLIDER_MIN) && (slider_pos_x != 0)) depth = FSD; 67 | if (slider_pos_x > SLIDER_MAX) depth = 0; 68 | printhex(depth); 69 | printstrln(" depth"); 70 | break; 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /app_audio_dalek/src/main.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************\ 2 | * Header: main 3 | * File: main.h 4 | * 5 | * Description: Definitions, types, and prototypes for main.xc 6 | * 7 | * Version: 0v1 8 | * Build: 9 | * 10 | * The copyrights, all other intellectual and industrial 11 | * property rights are retained by XMOS and/or its licensors. 12 | * Terms and conditions covering the use of this code can 13 | * be found in the Xmos End User License Agreement. 14 | * 15 | * Copyright XMOS Ltd 2012 16 | * 17 | * In the case where this code is a modification of existing code 18 | * under a separate license, the separate license terms are shown 19 | * below. The modifications to the code are still covered by the 20 | * copyright notice above. 21 | * 22 | \******************************************************************************/ 23 | 24 | #ifndef _MAIN_H_ 25 | #define _MAIN_H_ 26 | 27 | #include "audio_io.h" 28 | #include "dsp_biquad.h" 29 | 30 | #endif // _MAIN_H_ 31 | /******************************************************************************/ 32 | // main.h 33 | -------------------------------------------------------------------------------- /app_audio_dalek/src/main.xc: -------------------------------------------------------------------------------- 1 | /******************************************************************************\ 2 | * File: main.xc 3 | * 4 | * Top level app for dalek simulator app. 5 | * USes startKIT & audio slice hardware to provide various audio effects 6 | * Use button to select biquad filter type 7 | * Use sliders to control dalek effect (one does modulation depth, the other freq) 8 | * Uses sawtooth LFO to amplitude modulate audio to make dalek effect 9 | * Hint: enable xSCOPE RT to see input/output/LFO waveforms! 10 | * 11 | * Modified from project found here https://github.com/xcore/sw_audio_effects 12 | \******************************************************************************/ 13 | 14 | #include "main.h" 15 | #include "startkit_gpio.h" 16 | #include "lfo.h" 17 | #include 18 | 19 | on tile[DSP_TILE]: startkit_gpio_ports gpio_ports = 20 | {XS1_PORT_32A, XS1_PORT_4A, XS1_PORT_4B, XS1_CLKBLK_3}; 21 | 22 | #ifdef USE_XSCOPE 23 | /*****************************************************************************/ 24 | void xscope_user_init( void ) // 'C' constructor function (NB called before main) 25 | { 26 | xscope_register( 3 27 | ,XSCOPE_CONTINUOUS ,"Left in" ,XSCOPE_INT ,"n" 28 | ,XSCOPE_CONTINUOUS ,"Left out" ,XSCOPE_INT ,"n" 29 | ,XSCOPE_CONTINUOUS ,"Mod" ,XSCOPE_INT ,"n" 30 | ); // xscope_register 31 | 32 | xscope_config_io( XSCOPE_IO_BASIC ); // Enable XScope printing 33 | } // xscope_user_init 34 | #endif // ifdef USE_XSCOPE 35 | 36 | /*****************************************************************************/ 37 | int main (void) 38 | { 39 | streaming chan c_aud_dsp; // Channel between I/O and DSP core 40 | chan c_gain; // Channel between LFO (low freq osc) and DSP core 41 | startkit_led_if i_led; // Interface between DSP core and LED controller 42 | startkit_button_if i_button; // Interface between DSP core and button listner component 43 | slider_if i_slider_x, i_slider_y; //Interface between DSP core and slider component 44 | 45 | par 46 | { 47 | on tile[AUDIO_IO_TILE]: audio_io( c_aud_dsp ); // Audio I/O core aka I2S 48 | 49 | on tile[DSP_TILE]: dsp_biquad( c_aud_dsp ,0, i_led, i_button, c_gain ); // BiQuad filter core 50 | 51 | on tile[DSP_TILE]: startkit_gpio_driver(i_led, i_button, 52 | i_slider_x, 53 | i_slider_y, 54 | gpio_ports); 55 | on tile[DSP_TILE]: lfo(c_gain, i_slider_x, i_slider_y); 56 | } 57 | 58 | return 0; 59 | } // main 60 | /*****************************************************************************/ 61 | // main.xc 62 | -------------------------------------------------------------------------------- /app_audio_dalek/src/module_dsp_biquad_conf.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************\ 2 | * Header: module_dsp_biquad_conf 3 | * File: module_dsp_biquad_conf.h 4 | * 5 | * Description: Definitions for configuration of application. 6 | * NB These definitions will be passed to all modules used in application 7 | * 8 | * Version: 0v1 9 | * Build: 10 | * 11 | * The copyrights, all other intellectual and industrial 12 | * property rights are retained by XMOS and/or its licensors. 13 | * Terms and conditions covering the use of this code can 14 | * be found in the Xmos End User License Agreement. 15 | * 16 | * Copyright XMOS Ltd 2012 17 | * 18 | * In the case where this code is a modification of existing code 19 | * under a separate license, the separate license terms are shown 20 | * below. The modifications to the code are still covered by the 21 | * copyright notice above. 22 | * 23 | \******************************************************************************/ 24 | 25 | #ifndef _MODULE_DSP_BIQUAD_CONF_H_ 26 | #define _MODULE_DSP_BIQUAD_CONF_H_ 27 | 28 | #include "app_conf.h" 29 | 30 | #define NUM_BIQUAD_CHANS NUM_APP_CHANS 31 | 32 | #endif // _MODULE_DSP_BIQUAD_CONF_H_ 33 | /******************************************************************************/ 34 | // module_dsp_biquad_conf.h 35 | -------------------------------------------------------------------------------- /app_audio_dalek/src/xa_sk_audio_1v0.h: -------------------------------------------------------------------------------- 1 | 2 | /* General output port bit definitions */ 3 | //These are on port as defined by #define PORT_GPIO in app_global.h 4 | 5 | #define P_GPIO_SPDIF_EN 0x01 /* SPDIF enable*/ 6 | #define P_GPIO_MCLK_SEL 0x02 /* MCLK frequency select. 0 - 22.5792MHz, 1 - 24.576MHz. */ 7 | #define P_GPIO_COD_RST_N 0x04 /* CODEC RESET. Active low. */ 8 | #define P_GPIO_LED 0x08 /* LED. Active high. */ 9 | -------------------------------------------------------------------------------- /app_audio_dsp/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | app_audio_dsp 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.cdt.managedbuilder.core.genmakebuilder 10 | clean,full,incremental, 11 | 12 | 13 | ?children? 14 | ?name?=outputEntries\|?children?=?name?=entry\\\\|\\|\|| 15 | 16 | 17 | ?name? 18 | 19 | 20 | 21 | org.eclipse.cdt.make.core.append_environment 22 | true 23 | 24 | 25 | org.eclipse.cdt.make.core.buildArguments 26 | CONFIG=Debug 27 | 28 | 29 | org.eclipse.cdt.make.core.buildCommand 30 | xmake 31 | 32 | 33 | org.eclipse.cdt.make.core.cleanBuildTarget 34 | clean 35 | 36 | 37 | org.eclipse.cdt.make.core.contents 38 | org.eclipse.cdt.make.core.activeConfigSettings 39 | 40 | 41 | org.eclipse.cdt.make.core.enableAutoBuild 42 | false 43 | 44 | 45 | org.eclipse.cdt.make.core.enableCleanBuild 46 | true 47 | 48 | 49 | org.eclipse.cdt.make.core.enableFullBuild 50 | true 51 | 52 | 53 | org.eclipse.cdt.make.core.stopOnError 54 | true 55 | 56 | 57 | org.eclipse.cdt.make.core.useDefaultBuildCmd 58 | false 59 | 60 | 61 | 62 | 63 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder 64 | full,incremental, 65 | 66 | 67 | 68 | 69 | 70 | org.eclipse.cdt.core.cnature 71 | org.eclipse.cdt.managedbuilder.core.managedBuildNature 72 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature 73 | com.xmos.cdt.core.XdeProjectNature 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /app_audio_dsp/.xproject: -------------------------------------------------------------------------------- 1 | sw_startkit_examplesXM-004098-SM -------------------------------------------------------------------------------- /app_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 = STARTKIT 6 | APP_NAME = startkit_audio_dsp 7 | 8 | # The flags passed to xcc when building the application 9 | BUILD_FLAGS = -Wall -O3 -report -g -DSDA_HIGH=2 -DSCL_HIGH=1 10 | 11 | # The USED_MODULES variable lists other module used by the application. These 12 | # modules will extend the SOURCE_DIRS, INCLUDE_DIRS and LIB_DIRS variables. 13 | # Modules are expected to be in the directory above the BASE_DIR directory. 14 | USED_MODULES = module_capacitive_sensing module_cascading_biquad module_i2c_single_port 15 | USED_MODULES += module_i2s_master module_startkit_gpio module_logging 16 | 17 | XCC_FLAGS = $(BUILD_FLAGS) -fxscope 18 | 19 | #============================================================================= 20 | # The following part of the Makefile includes the common build infrastructure 21 | # for compiling XMOS applications. You should not need to edit below here. 22 | 23 | XMOS_MAKE_PATH ?= ../.. 24 | include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.common 25 | 26 | VERBOSE = 0 27 | -------------------------------------------------------------------------------- /app_audio_dsp/README.rst: -------------------------------------------------------------------------------- 1 | Startkit Audio DSP Example 2 | ========================== 3 | 4 | :scope: Example 5 | :description: Basic DSP evaluation application 6 | :keywords: biquad, DRC, audio, dsp, startkit 7 | :boards: XA-SK-AUDIO 8 | 9 | The button cycles through the available DSP modes: 10 | * None 11 | * Biquads 12 | * DRC 13 | * Biquads and DRC 14 | 15 | There are two host control applications, a command-line (host_dsp_control) and a GUI (host_dsp_gui) 16 | which is a QT application. 17 | 18 | In order to connect the control application the target application must be run using the xSCOPE 19 | server:: 20 | 21 | xrun --xscope-port localhost:12346 bin/startkit_audio_dsp.xe 22 | 23 | *Note*: the port (12346) is simply an example. 24 | *Note*: the application will not start until a control application is connected 25 | 26 | Command-line controller 27 | ----------------------- 28 | 29 | The command-line controller is connected using:: 30 | 31 | cd host_dsp_control 32 | ./dsp_control -p 12346 33 | 34 | *Note*: the port (-p 12346) simply has to match the one used with xrun. 35 | 36 | The usage commands available through the command-line controller are shown by simply pressing 'h+ENTER'. 37 | 38 | GUI controller 39 | -------------- 40 | 41 | The GUI controller is in the host_dsp_gui/ folder. QT will be required. It was developed with 42 | Qt Creator 5.3.0. To build it simply open the provided .pro file. Then run it and it will connect 43 | to the device. There is currently a hard-coded assumption that the port is 12346 in this 44 | controller. 45 | 46 | *Note*: it is possible to connect multiple controller at the same time. 47 | 48 | Real-time xSCOPE 49 | ---------------- 50 | 51 | In order to view the audio signals in and out, and the level detection state you can connect the 52 | real-time xSCOPE view in the xTIMEcomposer tools. 53 | 54 | *Note*: xTIMEcomposer 13.1.1 or newer is required to connect real-time xSCOPE simultaneously with 55 | a controller. 56 | 57 | -------------------------------------------------------------------------------- /app_audio_dsp/src/app_conf.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, 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 _APP_CONF_H_ 7 | #define _APP_CONF_H_ 8 | 9 | /** Number of audio channels used in this application */ 10 | #define NUM_APP_CHANS 2 11 | 12 | #define MAX_GAIN 0x7fffffff 13 | 14 | // The signal values are signed 24-bit values 15 | #define MAX_VALUE ((1 << 23) - 1) 16 | #define MIN_VALUE (-(1 << 23)) 17 | 18 | #endif // _APP_CONF_H_ 19 | -------------------------------------------------------------------------------- /app_audio_dsp/src/app_global.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, 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 _APP_GLOBAL_H_ 7 | #define _APP_GLOBAL_H_ 8 | 9 | // Comment-out if NOT using xscope 10 | #define USE_XSCOPE 1 11 | 12 | // Audio sample frequency (Hz) 13 | #define SAMP_FREQ 48000 14 | 15 | // Audio Slice hardware version 16 | #define AUDIO_SLICE_HW_MAJOR 1 17 | #define AUDIO_SLICE_HW_MINOR 1 18 | 19 | // Audio clocking defines 20 | // Master clock defines (Hz) 21 | #define MCLK_FREQ_441 (512*44100) // 44.1, 88.2 etc 22 | #define MCLK_FREQ_48 (512*48000) // 48, 96 etc 23 | 24 | #if (SAMP_FREQ%22050==0) 25 | #define MCLK_FREQ MCLK_FREQ_441 26 | #elif (SAMP_FREQ%24000==0) 27 | #define MCLK_FREQ MCLK_FREQ_48 28 | #else 29 | #error Unsupported sample frequency 30 | #endif 31 | 32 | // Bit clock divide 33 | #define BCLK_DIV (MCLK_FREQ / (SAMP_FREQ * 64)) 34 | 35 | // Ports 36 | #if ((AUDIO_SLICE_HW_MAJOR == 1) && (AUDIO_SLICE_HW_MINOR == 1)) 37 | #define PORT_I2S_DAC0 XS1_PORT_1G 38 | #define PORT_I2S_DAC1 XS1_PORT_1H 39 | #define PORT_I2S_ADC0 XS1_PORT_1K 40 | #define PORT_I2S_ADC1 XS1_PORT_1L 41 | #define PORT_I2S_LRCLK XS1_PORT_1I 42 | #define PORT_I2S_BCLK XS1_PORT_1F 43 | #define PORT_MCLK_IN XS1_PORT_1E 44 | 45 | #define PORT_GPIO XS1_PORT_4C 46 | #define PORT_I2C XS1_PORT_4D 47 | 48 | #else 49 | #error currently not un-supported slice hw version 50 | #endif 51 | 52 | #endif // _APP_GLOBAL_H_ 53 | -------------------------------------------------------------------------------- /app_audio_dsp/src/audio_io.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, 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 _AUDIO_IO_H_ 7 | #define _AUDIO_IO_H_ 8 | 9 | #include 10 | #include "i2c.h" 11 | #include "codec.h" 12 | #include "i2s_master.h" 13 | #include "app_global.h" 14 | 15 | void audio_io( 16 | streaming chanend c_aud // Audio end of channel between I/O and DSP coar 17 | ); 18 | 19 | #endif // _AUDIO_IO_H_ 20 | -------------------------------------------------------------------------------- /app_audio_dsp/src/audio_io.xc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, 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 "audio_io.h" 7 | 8 | // Global Structure for I2S resources 9 | on stdcore[0] : r_i2s i2s_resource_s = 10 | { 11 | XS1_CLKBLK_1, 12 | XS1_CLKBLK_2, 13 | PORT_MCLK_IN, // Master Clock 14 | PORT_I2S_BCLK, // Bit Clock 15 | PORT_I2S_LRCLK, // LR Clock 16 | 17 | #if I2S_MASTER_NUM_CHANS_ADC == 4 18 | {PORT_I2S_ADC0, PORT_I2S_ADC1}, 19 | #elif I2S_MASTER_NUM_CHANS_ADC == 2 20 | {PORT_I2S_ADC0}, 21 | #else 22 | #error Unsupported No Of I2S_MASTER_NUM_CHANS_ADC Channels 23 | #endif 24 | 25 | #if I2S_MASTER_NUM_CHANS_DAC == 4 26 | {PORT_I2S_DAC0, PORT_I2S_DAC1} 27 | #elif I2S_MASTER_NUM_CHANS_DAC == 2 28 | {PORT_I2S_DAC0} 29 | #else 30 | #error Unsupported No Of I2S_MASTER_NUM_CHANS_DAC Channels 31 | #endif 32 | 33 | }; // r_i2s 34 | 35 | on stdcore[0] : port p_i2c = PORT_I2C; 36 | on stdcore[0] : out port p_gpio = PORT_GPIO; 37 | 38 | void audio_hw_init() // Initialise Hardware 39 | { 40 | // Initialise the I2C bus 41 | i2c_master_init(p_i2c); 42 | } 43 | 44 | void audio_hw_config(unsigned samFreq) 45 | { 46 | // Note we do this everytime since we reset CODEC on Sample-Frequency change 47 | codec_config(samFreq, MCLK_FREQ); 48 | } 49 | 50 | void audio_io(streaming chanend c_aud) 51 | { 52 | unsigned mclk_bclk_div = MCLK_FREQ/(SAMP_FREQ * 64); // Calculate Bit-clock frequency 53 | 54 | audio_hw_init(); // Configure the CODECs 55 | audio_hw_config(SAMP_FREQ); // Configure the clocking 56 | i2s_master(i2s_resource_s, c_aud, mclk_bclk_div); // Call I2S master loop 57 | } 58 | -------------------------------------------------------------------------------- /app_audio_dsp/src/c_utils.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, 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 | #include 10 | #include 11 | #include 12 | 13 | #include "c_utils.h" 14 | #include "debug_print.h" 15 | 16 | char get_next_char(const unsigned char **buffer) 17 | { 18 | const unsigned char *ptr = *buffer; 19 | while (*ptr && isspace(*ptr)) 20 | ptr++; 21 | 22 | *buffer = ptr + 1; 23 | return *ptr; 24 | } 25 | 26 | int convert_atoi_substr(const unsigned char **buffer) 27 | { 28 | const unsigned char *ptr = *buffer; 29 | unsigned int value = 0; 30 | while (*ptr && isspace(*ptr)) 31 | ptr++; 32 | 33 | if (*ptr == '\0') 34 | return 0; 35 | 36 | value = atoi((char*)ptr); 37 | 38 | while (*ptr && !isspace(*ptr)) 39 | ptr++; 40 | 41 | *buffer = ptr; 42 | return value; 43 | } 44 | 45 | -------------------------------------------------------------------------------- /app_audio_dsp/src/c_utils.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, 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 __C_UTILS_H__ 7 | #define __C_UTILS_H__ 8 | 9 | #include 10 | 11 | #ifdef __XC__ 12 | extern "C" { 13 | #endif 14 | 15 | char get_next_char(const unsigned char **buffer); 16 | int convert_atoi_substr(const unsigned char **buffer); 17 | 18 | #ifdef __XC__ 19 | } 20 | #endif 21 | 22 | #endif // __C_UTILS_H__ 23 | -------------------------------------------------------------------------------- /app_audio_dsp/src/codec.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, 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 _CODEC_H_ 7 | #define _CODEC_H_ 8 | 9 | #include 10 | #include "i2c.h" 11 | #include "xa_sk_audio_1v0.h" 12 | 13 | extern port p_i2c; 14 | extern out port p_gpio; 15 | 16 | 17 | #define CODEC1_I2C_DEVICE_ADDR (0x90) 18 | #define CODEC2_I2C_DEVICE_ADDR (0x92) 19 | 20 | #define CODEC_DEV_ID_ADDR 0x01 21 | #define CODEC_PWR_CTRL_ADDR 0x02 22 | #define CODEC_MODE_CTRL_ADDR 0x03 23 | #define CODEC_ADC_DAC_CTRL_ADDR 0x04 24 | #define CODEC_TRAN_CTRL_ADDR 0x05 25 | #define CODEC_MUTE_CTRL_ADDR 0x06 26 | #define CODEC_DACA_VOL_ADDR 0x07 27 | #define CODEC_DACB_VOL_ADDR 0x08 28 | 29 | #define IIC_REGWRITE(reg, val) {data[0] = val; i2c_master_write_reg(CODEC1_I2C_DEVICE_ADDR, reg, data, 1, p_i2c);data[0] = val; i2c_master_write_reg(CODEC2_I2C_DEVICE_ADDR, reg, data, 1, p_i2c);} 30 | #define IIC_REGREAD(reg, val) {i2c_master_read_reg(CODEC1_I2C_DEVICE_ADDR, reg, val, 1, p_i2c);} 31 | 32 | void codec_config(unsigned sampleFrequency, unsigned mClk); 33 | 34 | #endif // _CODEC_H_ 35 | -------------------------------------------------------------------------------- /app_audio_dsp/src/codec.xc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, 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 "codec.h" 7 | #include "debug_print.h" 8 | 9 | #define DO_READ_STATUS 0 10 | 11 | void codec_config(unsigned sampleFrequency, unsigned mClk) 12 | { 13 | timer t; 14 | unsigned time; 15 | unsigned tmp; 16 | 17 | unsigned char data[1] = {0}; 18 | 19 | /* Set CODEC in reset */ 20 | tmp = P_GPIO_COD_RST_N; 21 | 22 | /* Set master clock select appropriately */ 23 | if ((sampleFrequency % 22050) == 0) 24 | { 25 | tmp &= ~P_GPIO_MCLK_SEL; 26 | } 27 | else //if((sampleFrequency % 24000) == 0) 28 | { 29 | tmp |= P_GPIO_MCLK_SEL; 30 | } 31 | 32 | /* Output to port */ 33 | p_gpio <: tmp; 34 | 35 | /* Hold in reset for 2ms while waiting for MCLK to stabilise */ 36 | t :> time; 37 | time += 200000; 38 | t when timerafter(time) :> int _; 39 | 40 | /* CODEC out of reset */ 41 | tmp |= P_GPIO_COD_RST_N; 42 | p_gpio <: tmp; 43 | 44 | /* Set power down bit in the CODEC over I2C */ 45 | IIC_REGWRITE(CODEC_DEV_ID_ADDR, 0x01); 46 | 47 | #if DO_READ_STATUS 48 | /* Read CODEC device ID to make sure everything is OK */ 49 | IIC_REGREAD(CODEC_DEV_ID_ADDR, data); 50 | 51 | int codec_dev_id = data[0]; 52 | if (((codec_dev_id & 0xF0) >> 4) != 0xC) 53 | debug_print("Unexpected CODEC Device ID, expected 0xC, got %x", codec_dev_id); 54 | #endif 55 | 56 | /* Now set all registers as we want them : 57 | Mode Control Reg: 58 | Set FM[1:0] as 11. This sets Slave mode. 59 | Set MCLK_FREQ[2:0] as 010. This sets MCLK to 512Fs in Single, 256Fs in Double and 128Fs in Quad Speed Modes. 60 | This means 24.576MHz for 48k and 22.5792MHz for 44.1k. 61 | Set Popguard Transient Control. 62 | So, write 0x35. */ 63 | IIC_REGWRITE(CODEC_MODE_CTRL_ADDR, 0x35); 64 | 65 | /* ADC & DAC Control Reg: 66 | Leave HPF for ADC inputs continuously running. 67 | Digital Loopback: OFF 68 | DAC Digital Interface Format: I2S 69 | ADC Digital Interface Format: I2S 70 | So, write 0x09. */ 71 | IIC_REGWRITE(CODEC_ADC_DAC_CTRL_ADDR, 0x09); 72 | 73 | /* Transition Control Reg: 74 | No De-emphasis. Don't invert any channels. Independent vol controls. Soft Ramp and Zero Cross enabled.*/ 75 | IIC_REGWRITE(CODEC_TRAN_CTRL_ADDR, 0x60); 76 | 77 | /* Mute Control Reg: Turn off AUTO_MUTE */ 78 | IIC_REGWRITE(CODEC_MUTE_CTRL_ADDR, 0x00); 79 | 80 | /* DAC Chan A Volume Reg: 81 | We don't require vol control so write 0x00 (0dB) */ 82 | IIC_REGWRITE(CODEC_DACA_VOL_ADDR, 0x00); 83 | 84 | /* DAC Chan B Volume Reg: 85 | We don't require vol control so write 0x00 (0dB) */ 86 | IIC_REGWRITE(CODEC_DACB_VOL_ADDR, 0x00); 87 | 88 | /* Clear power down bit in the CODEC over I2C */ 89 | IIC_REGWRITE(CODEC_PWR_CTRL_ADDR, 0x00); 90 | } 91 | -------------------------------------------------------------------------------- /app_audio_dsp/src/coeffs.h: -------------------------------------------------------------------------------- 1 | //Generated code - do not edit. 2 | 3 | #define BANKS 10 4 | #define DBS 25 5 | #define FRACTIONALBITS 27 6 | -------------------------------------------------------------------------------- /app_audio_dsp/src/control.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, 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 __CONTROL_H__ 7 | #define __CONTROL_H__ 8 | 9 | #define GET_BIQUAD_ENABLED(x) (x & 0x1) 10 | #define SET_BIQUAD_ENABLED(x, v) ((x & ~0x1) | (v & 0x1)) 11 | #define GET_DRC_ENABLED(x) (x & 0x2) 12 | #define SET_DRC_ENABLED(x, v) ((x & ~0x2) | ((v & 0x1) << 1)) 13 | 14 | #define PRE_GAIN_BITS 29 15 | #define PRE_GAIN_OFFSET ((1 << PRE_GAIN_BITS) - 1) 16 | 17 | typedef int dsp_state_t; 18 | 19 | #include "startkit_gpio.h" 20 | #include "drc.h" 21 | #include "level.h" 22 | 23 | #define LEVEL_ATTACK 1 24 | #define LEVEL_RELEASE 2 25 | #define LEVEL_THRESHOLD 4 26 | 27 | /** 28 | * The control interface between the control and DSP processes. 29 | */ 30 | typedef interface control_if { 31 | /** 32 | * Set the pre-effects gain. 33 | * 34 | * \param gain the gain value to set. Must be in the range 0-MAX_GAIN 35 | * (see app_conf.h). 36 | */ 37 | void set_pre_gain(int gain); 38 | 39 | /** 40 | * Set the post-effects gain. 41 | * 42 | * \param gain the gain value to set. Must be in the range 0-MAX_GAIN 43 | * (see app_conf.h). 44 | */ 45 | void set_gain(int gain); 46 | 47 | /** 48 | * Control which effects are on (e.g. biquads/DRC) 49 | * 50 | * \param state a bitfield indicating which effects are active. 51 | * 52 | */ 53 | void set_effect(dsp_state_t state); 54 | 55 | /** 56 | * Configure the biquad decibel level for a given biquad index. 57 | * 58 | * \param chan_index the channel number to modify. If chan_index == NUM_APP_CHANS 59 | * (see app_conf.h) then this will be applied to all channels. 60 | * 61 | * \param index the biquad bank to modify. 62 | * 63 | * \param dbs the new decibel level to set. Must be in the range 0-DBS 64 | * (see coeffs.h). 65 | */ 66 | void set_dbs(int chan_index, int index, int dbs); 67 | 68 | /** 69 | * Get the current level for a biquad bank. 70 | * 71 | * \param chan_index the channel number to modify. Must be in the range 72 | * 0-NUM_APP_CHANS (see app_conf.h). 73 | * 74 | * \param index the biquad bank to modify. 75 | * 76 | * \return the current decibel level as an index in the range 0-DBS (see coeffs.h) 77 | */ 78 | int get_dbs(int chan_index, int index); 79 | 80 | /** 81 | * Configure the specified DRC entry 82 | * 83 | * \param index the index into the DRC configuration table. Must be 84 | * in the range 0-DRC_NUM_THRESHOLDS (see drc.h). 85 | * 86 | * \param control the DRC configuration structure. 87 | */ 88 | void set_drc_entry(int index, drcControl &control); 89 | 90 | /** 91 | * Get the current configuration for the specified DRC entry 92 | * 93 | * \param index the index into the DRC configuration table. Must be 94 | * in the range 0-DRC_NUM_THRESHOLDS (see drc.h). 95 | * 96 | * \return the DRC configuration structure 97 | */ 98 | drcControl get_drc_entry(int index); 99 | 100 | /** 101 | * Configure a subset of the level state for the specifiec channel 102 | * 103 | * \param chan_index the channel number to modify. Must be in the range 104 | * 0-NUM_APP_CHANS (see app_conf.h). 105 | * 106 | * \param state the level state to apply. 107 | * 108 | * \param flags a bitfield which indicates which bits of state are valid. 109 | */ 110 | void set_level_entry(int chan_index, levelState &state, int flags); 111 | 112 | /** 113 | * Get the current level for the specifiec channel 114 | * 115 | * \param chan_index the channel number to modify. Must be in the range 116 | * 0-NUM_APP_CHANS (see app_conf.h). 117 | * 118 | * \return the level state 119 | */ 120 | levelState get_level_entry(int chan_index); 121 | 122 | } control_if; 123 | 124 | /** 125 | * A control task that listens to data being received over xscope, 126 | * interprets the commands and controls the DSP process. 127 | */ 128 | void control(chanend c_host_data, 129 | client startkit_led_if i_led, 130 | client startkit_button_if i_button, 131 | client control_if i_control); 132 | 133 | #endif // __CONTROL_H__ 134 | -------------------------------------------------------------------------------- /app_audio_dsp/src/debug_conf.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, 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 DEBUG_CONF_H_ 7 | #define DEBUG_CONF_H_ 8 | 9 | #define DEBUG_PRINT_ENABLE 1 10 | 11 | #endif /* DEBUG_CONF_H_ */ 12 | -------------------------------------------------------------------------------- /app_audio_dsp/src/drc.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, 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 __DRC_H__ 7 | #define __DRC_H__ 8 | 9 | #define DRC_NUM_THRESHOLDS 3 10 | 11 | /** 12 | * Structure for the drcControl. The _percent values are only for user readability. 13 | */ 14 | typedef struct drcControl { 15 | int threshold_percent; 16 | int threshold; 17 | int gain_percent; 18 | int gain_factor; 19 | } drcControl; 20 | 21 | extern drcControl drcTable[DRC_NUM_THRESHOLDS]; 22 | 23 | /** 24 | * This function must be called prior to using the drc function. 25 | */ 26 | extern void initDrc(); 27 | 28 | /** 29 | * This function applies the DRC filter. 30 | * 31 | * \param xn value to be filtered in fixed point format. Results that do 32 | * not fit are clipped to the maximum positive and negative 33 | * values. Input values should nominally be in the range 34 | * [-1..+1] leaving headroom for intermediate results. 35 | * 36 | * \param level current signal level which is used to influence the amount 37 | * of DRC to apply. 38 | * 39 | * \return Filtered value in fixed point format. 40 | */ 41 | extern int drc(int xn, int level); 42 | 43 | #endif // __DRC_H__ 44 | -------------------------------------------------------------------------------- /app_audio_dsp/src/drc.xc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, 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 "drc.h" 7 | #include "debug_print.h" 8 | #include "xclib.h" 9 | #include "app_conf.h" 10 | #include "level.h" 11 | 12 | static int do_gain(int sample, int gain) 13 | { 14 | long long value = (long long) sample * (long long) gain; 15 | return value >> 31; 16 | } 17 | 18 | static int merge(int a, int b, int a_not_b) 19 | { 20 | long long tmp_a = (long long) a * (long long) a_not_b; 21 | long long tmp_b = (long long) b * (long long) (MAX_GAIN - a_not_b); 22 | 23 | a = tmp_a >> 31; 24 | b = tmp_b >> 31; 25 | 26 | return a + b; 27 | } 28 | 29 | #define DRC_THRESHOLD(x) (x), ((x==100) ? MAX_VALUE : (MAX_VALUE / (long long)100 * (long long)x)) 30 | #define DRC_GAIN(x) (x), ((x==100) ? MAX_GAIN : (MAX_GAIN / (long long)100 * (long long)x)) 31 | 32 | drcControl drcTable[DRC_NUM_THRESHOLDS] = { 33 | { DRC_THRESHOLD(60), DRC_GAIN(70) }, 34 | { DRC_THRESHOLD(70), DRC_GAIN(60) }, 35 | { DRC_THRESHOLD(80), DRC_GAIN(50) } 36 | }; 37 | 38 | void initDrc() 39 | { 40 | } 41 | 42 | int drc(int xn, int level) 43 | { 44 | int drc_value = xn; 45 | int negative = 0; 46 | 47 | if (xn < 0) { 48 | drc_value = -xn; 49 | negative = 1; 50 | } 51 | 52 | for (int i = 0; i < DRC_NUM_THRESHOLDS; i++) { 53 | if (drc_value > drcTable[i].threshold) { 54 | drc_value = drcTable[i].threshold + do_gain(drc_value - drcTable[i].threshold, drcTable[i].gain_factor); 55 | } 56 | } 57 | 58 | if (negative) 59 | drc_value = -drc_value; 60 | 61 | return merge(drc_value, xn, level << LEVEL_TO_GAIN_SHIFT); 62 | } 63 | 64 | -------------------------------------------------------------------------------- /app_audio_dsp/src/dsp.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, 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 _DSP_H_ 7 | #define _DSP_H_ 8 | 9 | #include "control.h" 10 | 11 | void dsp( 12 | streaming chanend c_audio, 13 | server control_if i_control 14 | ); 15 | 16 | #endif // _DSP_H_ 17 | -------------------------------------------------------------------------------- /app_audio_dsp/src/i2s_master_conf.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, 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 _I2S_MASTER_CONF_H_ 7 | #define _I2S_MASTER_CONF_H_ 8 | 9 | #include "app_conf.h" 10 | 11 | #define I2S_MASTER_NUM_CHANS_ADC NUM_APP_CHANS 12 | #define I2S_MASTER_NUM_CHANS_DAC NUM_APP_CHANS 13 | 14 | #endif // _I2S_MASTER_CONF_H_ 15 | -------------------------------------------------------------------------------- /app_audio_dsp/src/level.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, 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 __LEVEL_H__ 7 | #define __LEVEL_H__ 8 | 9 | #include "app_global.h" 10 | 11 | #define MIRCO_SEC_PER_SAMPLE (1000000 / SAMP_FREQ) 12 | 13 | #define LEVEL_BITS 29 14 | #define MAX_LEVEL ((1 << LEVEL_BITS) - 1) 15 | #define LEVEL_TO_GAIN_SHIFT (31 - LEVEL_BITS) 16 | 17 | /** 18 | * The _percent and _ns members are only for user display 19 | */ 20 | typedef struct levelState { 21 | int level; 22 | int attack_micro_sec; 23 | int attack_rate; 24 | int release_micro_sec; 25 | int release_rate; 26 | int threshold_percent; 27 | int threshold; 28 | } levelState; 29 | 30 | extern void initLevelState(levelState &ls, int attack_micro_sec, int release_micro_sec, int threshold); 31 | 32 | extern void computeLevel(levelState &ls, int xn); 33 | 34 | #endif // __LEVEL_H__ 35 | -------------------------------------------------------------------------------- /app_audio_dsp/src/level.xc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, 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 "level.h" 7 | #include "debug_print.h" 8 | #include "app_conf.h" 9 | 10 | void initLevelState(levelState &ls, int attack_micro_sec, int release_micro_sec, int threshold_percent) 11 | { 12 | ls.level = 0; 13 | ls.attack_micro_sec = attack_micro_sec; 14 | if (attack_micro_sec == 0) 15 | ls.attack_rate = MAX_LEVEL; 16 | else 17 | ls.attack_rate = MAX_LEVEL / attack_micro_sec * MIRCO_SEC_PER_SAMPLE; 18 | 19 | ls.release_micro_sec = release_micro_sec; 20 | if (ls.release_micro_sec == 0) 21 | ls.release_rate = MAX_LEVEL; 22 | else 23 | ls.release_rate = MAX_LEVEL / release_micro_sec * MIRCO_SEC_PER_SAMPLE; 24 | 25 | ls.threshold_percent = threshold_percent; 26 | ls.threshold = (MAX_VALUE / 100) * threshold_percent; 27 | } 28 | 29 | void computeLevel(levelState &ls, int xn) 30 | { 31 | if (xn < 0) 32 | xn = -xn; 33 | 34 | if (xn > ls.threshold) { 35 | ls.level += ls.attack_rate; 36 | if (ls.level > MAX_LEVEL) 37 | ls.level = MAX_LEVEL; 38 | 39 | } else { 40 | ls.level -= ls.release_rate; 41 | if (ls.level < 0) 42 | ls.level = 0; 43 | } 44 | } 45 | 46 | -------------------------------------------------------------------------------- /app_audio_dsp/src/main.xc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, 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 | #include "app_global.h" 10 | #include "startkit_gpio.h" 11 | #include "audio_io.h" 12 | #include "dsp.h" 13 | #include "control.h" 14 | 15 | on stdcore[0]: startkit_gpio_ports gpio_ports = 16 | {XS1_PORT_32A, XS1_PORT_4A, XS1_PORT_4B, XS1_CLKBLK_3}; 17 | 18 | #ifdef USE_XSCOPE 19 | void xscope_user_init(void) // 'C' constructor function (NB called before main) 20 | { 21 | xscope_register(3, 22 | XSCOPE_CONTINUOUS, "Left in", XSCOPE_INT, "n", 23 | XSCOPE_CONTINUOUS, "Left out", XSCOPE_INT, "n", 24 | XSCOPE_CONTINUOUS, "Mod", XSCOPE_INT, "n" 25 | ); // xscope_register 26 | 27 | xscope_config_io(XSCOPE_IO_BASIC); // Enable XScope printing 28 | } 29 | #endif 30 | 31 | // A function to simply consume cycles 32 | void filler() 33 | { 34 | set_core_fast_mode_on(); 35 | while (1) { } 36 | } 37 | 38 | int main (void) 39 | { 40 | chan c_host_data; // Channel to receive control messages from the host 41 | streaming chan c_aud_dsp; // Channel for audio between I/O and DSP core 42 | startkit_led_if i_led; // Interface between control core and LED controller 43 | startkit_button_if i_button; // Interface between control core and button listener component 44 | slider_if i_slider_x, i_slider_y; // Unused slider interface 45 | control_if i_control; // Interface between the control and DSP cores 46 | 47 | par 48 | { 49 | xscope_host_data(c_host_data); 50 | 51 | on stdcore[0]: audio_io(c_aud_dsp); 52 | 53 | on stdcore[0]: dsp(c_aud_dsp, i_control); 54 | 55 | on stdcore[0]: startkit_gpio_driver(i_led, i_button, 56 | i_slider_x, i_slider_y, gpio_ports); 57 | 58 | on stdcore[0]: control(c_host_data, i_led, i_button, i_control); 59 | 60 | // Fill the unused cores to prove that the DSP works with 8 cores active 61 | on stdcore[0]: filler(); 62 | on stdcore[0]: filler(); 63 | on stdcore[0]: filler(); 64 | on stdcore[0]: filler(); 65 | } 66 | 67 | return 0; 68 | } 69 | -------------------------------------------------------------------------------- /app_audio_dsp/src/xa_sk_audio_1v0.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, 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 | /* General output port bit definitions */ 7 | //These are on port as defined by #define PORT_GPIO in app_global.h 8 | 9 | #define P_GPIO_SPDIF_EN 0x01 /* SPDIF enable*/ 10 | #define P_GPIO_MCLK_SEL 0x02 /* MCLK frequency select. 0 - 22.5792MHz, 1 - 24.576MHz. */ 11 | #define P_GPIO_COD_RST_N 0x04 /* CODEC RESET. Active low. */ 12 | #define P_GPIO_LED 0x08 /* LED. Active high. */ 13 | -------------------------------------------------------------------------------- /app_balance/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | app_balance 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.cdt.managedbuilder.core.genmakebuilder 10 | clean,full,incremental, 11 | 12 | 13 | ?children? 14 | ?name?=outputEntries\|?children?=?name?=entry\\\\|\\|\|| 15 | 16 | 17 | ?name? 18 | 19 | 20 | 21 | org.eclipse.cdt.make.core.append_environment 22 | true 23 | 24 | 25 | org.eclipse.cdt.make.core.buildArguments 26 | CONFIG=Debug 27 | 28 | 29 | org.eclipse.cdt.make.core.buildCommand 30 | xmake 31 | 32 | 33 | org.eclipse.cdt.make.core.cleanBuildTarget 34 | clean 35 | 36 | 37 | org.eclipse.cdt.make.core.contents 38 | org.eclipse.cdt.make.core.activeConfigSettings 39 | 40 | 41 | org.eclipse.cdt.make.core.enableAutoBuild 42 | false 43 | 44 | 45 | org.eclipse.cdt.make.core.enableCleanBuild 46 | true 47 | 48 | 49 | org.eclipse.cdt.make.core.enableFullBuild 50 | true 51 | 52 | 53 | org.eclipse.cdt.make.core.stopOnError 54 | true 55 | 56 | 57 | org.eclipse.cdt.make.core.useDefaultBuildCmd 58 | false 59 | 60 | 61 | 62 | 63 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder 64 | full,incremental, 65 | 66 | 67 | 68 | 69 | 70 | org.eclipse.cdt.core.cnature 71 | org.eclipse.cdt.managedbuilder.core.managedBuildNature 72 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature 73 | com.xmos.cdt.core.XdeProjectNature 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /app_balance/.xproject: -------------------------------------------------------------------------------- 1 | sw_startkit_examplesXM-004098-SM -------------------------------------------------------------------------------- /app_balance/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = STARTKIT 2 | APP_NAME = 3 | XCC_FLAGS = -g -report -save-temps -O1 4 | USED_MODULES = module_i2c_master module_startkit_gpio module_logging 5 | 6 | #============================================================================= 7 | # The following part of the Makefile includes the common build infrastructure 8 | # for compiling XMOS applications. You should not need to edit below here. 9 | 10 | #============================================================================= 11 | # The following part of the Makefile includes the common build infrastructure 12 | # for compiling XMOS applications. You should not need to edit below here. 13 | 14 | XMOS_MAKE_PATH ?= ../.. 15 | include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.common 16 | -------------------------------------------------------------------------------- /app_balance/README.rst: -------------------------------------------------------------------------------- 1 | Balance the ball (LED) 2 | ====================== 3 | 4 | :scope: Example 5 | :description: A demo of using the accelerometer slice 6 | :keywords: accelerometer, startKIT 7 | 8 | This program requires an accelerometer slice. 9 | 10 | It shows a ball (represented by a LED with some antialiasing) and when the 11 | startKIT is tilted the ball will roll to the edge. 12 | 13 | Implementation 14 | -------------- 15 | 16 | There are two tasks: 17 | 18 | * A task that performs the output. It PWMs the LEDs to show the position in 19 | an antialised manner. Values are averaged over 32 samples before being used. 20 | 21 | * A task that queries the accelerometer. It uses ``sc_i2c`` to communicate 22 | with the accelerometer. 23 | -------------------------------------------------------------------------------- /app_balance/src/acceloremeter.xc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, 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 | * acelloslice.xc 8 | * 9 | * Created on: 1 Oct 2013 10 | * Author: edward 11 | */ 12 | 13 | #include "i2c.h" 14 | #include "ball.h" 15 | #include 16 | #include 17 | #include 18 | #include "debug_print.h" 19 | 20 | /** Function that reads out an acceleration; out of two registers and makes 21 | * it two's complements. 22 | */ 23 | int read_acceleration(r_i2c &i2c, int reg) { 24 | int r; 25 | unsigned char data[1]; 26 | i2c_master_read_reg(0x1D, reg, data, 1, i2c); 27 | r = data[0] << 2; 28 | i2c_master_read_reg(0x1D, reg+1, data, 1, i2c); 29 | r |= (data[0] >> 6); 30 | if(r & 0x200) { 31 | r -= 1023; 32 | } 33 | return r; 34 | } 35 | 36 | /** Function that reads acceleration in 3 dimensions and outputs them onto a channel end 37 | */ 38 | void accelerometer(client ball_if ball, r_i2c &i2c) { 39 | unsigned char data[1]; 40 | i2c_master_init(i2c); 41 | 42 | // Set up dividers 43 | data[0] = 0x01; // Set up dividers 44 | i2c_master_write_reg(0x1D, 0x0E, data, 1, i2c); 45 | data[0] = 0x01; 46 | i2c_master_write_reg(0x1D, 0x2A, data, 1, i2c); 47 | while(1) { 48 | do { 49 | i2c_master_read_reg(0x1D, 0x00, data, 1, i2c); 50 | } while (!data[0] & 0x08); 51 | int x, y, z; 52 | x = read_acceleration(i2c, 1); 53 | y = read_acceleration(i2c, 3); 54 | z = read_acceleration(i2c, 5); 55 | 56 | // Once the position is read use it to set the ball position 57 | ball.new_position(x, y, z); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /app_balance/src/ball.h: -------------------------------------------------------------------------------- 1 | #ifndef __ball_h__ 2 | #define __ball_h__ 3 | 4 | typedef interface ball_if { 5 | void new_position(int x, int y, int z); 6 | } ball_if; 7 | 8 | #endif // __ball_h__ 9 | -------------------------------------------------------------------------------- /app_balance/src/debug_conf.h: -------------------------------------------------------------------------------- 1 | #define DEBUG_PRINT_ENABLE 1 2 | -------------------------------------------------------------------------------- /app_balance/src/i2c_conf.h: -------------------------------------------------------------------------------- 1 | #define I2C_BIT_TIME 250 2 | -------------------------------------------------------------------------------- /app_balance/src/main.xc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, 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 | #include 10 | #include 11 | #include 12 | #include "ball.h" 13 | #include "i2c.h" 14 | #include "startkit_gpio.h" 15 | 16 | extern void accelerometer(client ball_if, r_i2c &i2c); 17 | 18 | #define HISTORY_LEN 32 19 | 20 | struct history { 21 | int values[HISTORY_LEN]; // A filter that holds 32 old values 22 | int w; // index of the oldest value in the array 23 | int av; // Running average of all struct 24 | }; 25 | 26 | static int filter(struct history &h, int value) { 27 | h.av += value; 28 | h.av -= h.values[h.w]; 29 | h.values[h.w] = value; 30 | h.w++; 31 | if (h.w == HISTORY_LEN) { 32 | h.w = 0; 33 | } 34 | return h.av/HISTORY_LEN; 35 | } 36 | 37 | // This is the range of the ball, i.e. the x,y,z coordinates will 38 | // be between -BALL_RANGE and +BALL_RANGE 39 | #define BALL_RANGE 50 40 | 41 | [[combinable]] 42 | void ball(server ball_if ball, client startkit_led_if leds) { 43 | struct history history_x, history_y, history_z; 44 | history_x.w = history_y.w = history_z.w = 0; 45 | history_x.av = history_y.av = history_z.av = 0; 46 | 47 | for(int i = 0; i < HISTORY_LEN; i++) { 48 | history_x.values[i] = history_y.values[i] = history_z.values[i] = 0; 49 | } 50 | 51 | while(1) { 52 | select { 53 | case ball.new_position(int new_x, int new_y, int new_z): 54 | int x, y, z; 55 | 56 | // Average the ball position over recent history 57 | x = filter(history_x, new_x); 58 | y = filter(history_y, new_y); 59 | z = filter(history_z, new_z); 60 | 61 | // Split the position into sign and magnitude 62 | // where the magnitude is between 0..LED_ON 63 | int sx = x < 0 ? -1 : 1; 64 | int sz = z < 0 ? -1 : 1; 65 | unsigned px, pz; 66 | 67 | px = abs(x); // take absolute value 68 | px = px > BALL_RANGE ? BALL_RANGE : px; // clip at BALL_RANGE 69 | px = px * LED_ON/BALL_RANGE; // scale to LED_ON 70 | 71 | pz = abs(z); 72 | pz = pz > BALL_RANGE ? BALL_RANGE : pz; 73 | pz = pz * LED_ON/BALL_RANGE; 74 | 75 | // Clear all led levels 76 | leds.set_multiple(0b111111111, 0); 77 | 78 | // Set the leds to show the ball position 79 | leds.set(1, 1, (LED_ON - px) * (LED_ON - pz) / LED_ON); 80 | leds.set(1, 1 + sz, (LED_ON - px) * pz / LED_ON); 81 | leds.set(1 + sx, 1, (px * (LED_ON - pz)) / LED_ON); 82 | leds.set(1 + sx, 1 + sz, (px * pz) / LED_ON); 83 | break; 84 | } 85 | } 86 | } 87 | 88 | /* The ports for the I2C interface to the accelerometer */ 89 | r_i2c i2c = { XS1_PORT_1K, XS1_PORT_1I, 250 }; 90 | 91 | /* The ports for leds/button/capsense */ 92 | startkit_gpio_ports gpio_ports = 93 | {XS1_PORT_32A, XS1_PORT_4A, XS1_PORT_4B, XS1_CLKBLK_1}; 94 | 95 | int main(void) { 96 | // These interfaces connect the tasks below together 97 | ball_if i_ball; 98 | startkit_led_if i_led; 99 | 100 | // This is what the task diagram of the application is like: 101 | // 102 | // i2c_master <-- accelerometer 103 | // | 104 | // V 105 | // ball --> startkit_gpio_driver 106 | 107 | // The ball and startkit_gpio_driver tasks run on the same logical 108 | // core (using co-operative multitasking). 109 | // 110 | // The i2c_master tasks is "distributable" and connected to the 111 | // accelerometer task on the same tile so does not take up a logical 112 | // core of its own. 113 | // 114 | // Altogether the application takes up 2 logical cores. 115 | 116 | par { 117 | // This task periodically reads the position from the 118 | // accelerometer slice and feeds it to the ball task 119 | on tile[0]: accelerometer(i_ball, i2c); 120 | 121 | // This task reads the ball position from the accelerometer task 122 | // when there is a change and updates the LED values based on 123 | // that position 124 | on tile[0].core[0]: ball(i_ball, i_led); 125 | 126 | // The led driver task 127 | on tile[0].core[0]: startkit_gpio_driver(i_led, null, null, null, 128 | gpio_ports); 129 | } 130 | return 0; 131 | } 132 | -------------------------------------------------------------------------------- /app_glowing_leds/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | app_glowing_leds 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.cdt.managedbuilder.core.genmakebuilder 10 | clean,full,incremental, 11 | 12 | 13 | ?children? 14 | ?name?=outputEntries\|?children?=?name?=entry\\\\|\\|\|| 15 | 16 | 17 | ?name? 18 | 19 | 20 | 21 | org.eclipse.cdt.make.core.append_environment 22 | true 23 | 24 | 25 | org.eclipse.cdt.make.core.buildArguments 26 | CONFIG=Debug 27 | 28 | 29 | org.eclipse.cdt.make.core.buildCommand 30 | xmake 31 | 32 | 33 | org.eclipse.cdt.make.core.cleanBuildTarget 34 | clean 35 | 36 | 37 | org.eclipse.cdt.make.core.contents 38 | org.eclipse.cdt.make.core.activeConfigSettings 39 | 40 | 41 | org.eclipse.cdt.make.core.enableAutoBuild 42 | false 43 | 44 | 45 | org.eclipse.cdt.make.core.enableCleanBuild 46 | true 47 | 48 | 49 | org.eclipse.cdt.make.core.enableFullBuild 50 | true 51 | 52 | 53 | org.eclipse.cdt.make.core.stopOnError 54 | true 55 | 56 | 57 | org.eclipse.cdt.make.core.useDefaultBuildCmd 58 | false 59 | 60 | 61 | 62 | 63 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder 64 | full,incremental, 65 | 66 | 67 | 68 | 69 | 70 | org.eclipse.cdt.core.cnature 71 | org.eclipse.cdt.managedbuilder.core.managedBuildNature 72 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature 73 | com.xmos.cdt.core.XdeProjectNature 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /app_glowing_leds/.xproject: -------------------------------------------------------------------------------- 1 | sw_startkit_examplesXM-004098-SM -------------------------------------------------------------------------------- /app_glowing_leds/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 | TARGET = STARTKIT 5 | 6 | # The APP_NAME variable determines the name of the final .xe file. It should 7 | # not include the .xe postfix. If left blank the name will default to 8 | # the project name 9 | APP_NAME = app_glowing_leds 10 | 11 | # The USED_MODULES variable lists other module used by the application. 12 | USED_MODULES = module_startkit_gpio 13 | 14 | # The flags passed to xcc when building the application 15 | # You can also set the following to override flags for a particular language: 16 | # XCC_XC_FLAGS, XCC_C_FLAGS, XCC_ASM_FLAGS, XCC_CPP_FLAGS 17 | # If the variable XCC_MAP_FLAGS is set it overrides the flags passed to 18 | # xcc for the final link (mapping) stage. 19 | XCC_FLAGS = -g -report -save-temps 20 | 21 | # The VERBOSE variable, if set to 1, enables verbose output from the make system. 22 | VERBOSE = 0 23 | 24 | 25 | #============================================================================= 26 | # The following part of the Makefile includes the common build infrastructure 27 | # for compiling XMOS applications. You should not need to edit below here. 28 | 29 | XMOS_MAKE_PATH ?= ../.. 30 | include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.common 31 | -------------------------------------------------------------------------------- /app_glowing_leds/README.rst: -------------------------------------------------------------------------------- 1 | Glowing LED pattern 2 | =================== 3 | 4 | :scope: Example 5 | :description: A simple demo using LED and PWM on the startKIT 6 | :keywords: LEDs, startKIT, buttons 7 | 8 | This example shows use of the LEDs and button on the startKIT by 9 | showing a repeated glowing pattern. It uses ``module_starkit_gpio`` to 10 | access the GPIO. 11 | -------------------------------------------------------------------------------- /app_glowing_leds/src/main.xc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "startkit_gpio.h" 5 | 6 | // This function is combinable - it can share a core with other tasks 7 | [[combinable]] 8 | static void glow(client startkit_led_if leds, client startkit_button_if button) 9 | { 10 | timer tmr; 11 | int period = 1 * 1000 * 1000 * 100; // period from off to on = 1s; 12 | unsigned res = 30; // increment the brightness in this 13 | // number of steps 14 | int delay = period / res; // how long to wait between updates 15 | int level = 0; // the level of led brightness 16 | unsigned pattern = 0b010101010; // the pattern output to the leds, 17 | // alternates between an X and its 18 | // inverse 19 | int timestamp; 20 | int dir = 1; 21 | 22 | // Take the initial timestamp of the 100Mhz timer 23 | tmr :> timestamp; 24 | while (1) { 25 | select { 26 | // After 'delay' ticks do this 27 | case tmr when timerafter(timestamp + delay) :> void: 28 | // increase the output level of the led 29 | level += dir * (LED_ON / res); 30 | if (level > LED_ON) { 31 | level = LED_ON; 32 | dir = -1; 33 | } 34 | if (level < 0) { 35 | level = 0; 36 | dir = 1; 37 | } 38 | // set the leds 39 | leds.set_multiple(pattern, level); 40 | // update the timestamp for the next timeout 41 | timestamp += delay; 42 | break; 43 | 44 | case button.changed(): 45 | if (button.get_value() == BUTTON_DOWN) { 46 | // If the button has been pressed down then 47 | // invert the pattern 48 | pattern = ~pattern; 49 | } 50 | break; 51 | } 52 | } 53 | } 54 | 55 | 56 | startkit_gpio_ports gpio_ports = 57 | {XS1_PORT_32A, XS1_PORT_4A, XS1_PORT_4B, XS1_CLKBLK_1}; 58 | 59 | // 'main' sets up the system, consisting of two tasks - one to drive 60 | // the i/o and one to run the application that communicates with that 61 | // driver. 62 | int main() 63 | { 64 | // These interface connections link the application to the 65 | // gpio driver. 66 | startkit_led_if i_led; 67 | startkit_button_if i_button; 68 | par { 69 | on tile[0].core[0]: startkit_gpio_driver(i_led, i_button, 70 | null, null, 71 | gpio_ports); 72 | on tile[0].core[1]: glow(i_led, i_button); 73 | } 74 | return 0; 75 | } 76 | -------------------------------------------------------------------------------- /app_noughts_and_crosses/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | app_noughts_and_crosses 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.cdt.managedbuilder.core.genmakebuilder 10 | clean,full,incremental, 11 | 12 | 13 | ?children? 14 | ?name?=outputEntries\|?children?=?name?=entry\\\\|\\|\|| 15 | 16 | 17 | ?name? 18 | 19 | 20 | 21 | org.eclipse.cdt.make.core.append_environment 22 | true 23 | 24 | 25 | org.eclipse.cdt.make.core.buildArguments 26 | CONFIG=Debug 27 | 28 | 29 | org.eclipse.cdt.make.core.buildCommand 30 | xmake 31 | 32 | 33 | org.eclipse.cdt.make.core.cleanBuildTarget 34 | clean 35 | 36 | 37 | org.eclipse.cdt.make.core.contents 38 | org.eclipse.cdt.make.core.activeConfigSettings 39 | 40 | 41 | org.eclipse.cdt.make.core.enableAutoBuild 42 | false 43 | 44 | 45 | org.eclipse.cdt.make.core.enableCleanBuild 46 | true 47 | 48 | 49 | org.eclipse.cdt.make.core.enableFullBuild 50 | true 51 | 52 | 53 | org.eclipse.cdt.make.core.stopOnError 54 | true 55 | 56 | 57 | org.eclipse.cdt.make.core.useDefaultBuildCmd 58 | false 59 | 60 | 61 | 62 | 63 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder 64 | full,incremental, 65 | 66 | 67 | 68 | 69 | 70 | org.eclipse.cdt.core.cnature 71 | org.eclipse.cdt.managedbuilder.core.managedBuildNature 72 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature 73 | com.xmos.cdt.core.XdeProjectNature 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /app_noughts_and_crosses/.xproject: -------------------------------------------------------------------------------- 1 | sw_startkit_examplesXM-004098-SM -------------------------------------------------------------------------------- /app_noughts_and_crosses/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = STARTKIT 2 | APP_NAME = 3 | XCC_FLAGS = -g -report -Os -save-temps -fno-xta-info 4 | USED_MODULES = module_xassert module_logging module_startkit_gpio 5 | 6 | #============================================================================= 7 | # The following part of the Makefile includes the common build infrastructure 8 | # for compiling XMOS applications. You should not need to edit below here. 9 | 10 | XMOS_MAKE_PATH ?= ../.. 11 | include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.common 12 | -------------------------------------------------------------------------------- /app_noughts_and_crosses/README.rst: -------------------------------------------------------------------------------- 1 | Noughts and crosses (tic-tac-toe) 2 | ================================= 3 | 4 | :scope: Example 5 | :description: A noughts and crosses game for the startKIT 6 | :keywords: game, startKIT 7 | 8 | 9 | This is a program that plays noughts and crosses on a startKIT. 10 | The 3x3 display of LEDs shows the board status: 11 | 12 | - full LEDs: X, user 13 | - dimmed LEDs: O, computer 14 | 15 | WHen it is the user's move one of the LEDs flashes - this is a cursor and 16 | it can be moved by swiping the sliders. Pressing the button makes a move, 17 | and the XCORE will make the next move. 18 | 19 | 20 | Implementation 21 | -------------- 22 | 23 | There are three tasks: 24 | 25 | * A task that performs the output. It PWMs the LEDs, shows the blinking 26 | cursor, and awaits input on the button: ``user_output.xc`` 27 | 28 | * A task that operates the sliders: ``user_input.xc``. The repository 29 | ``sc_capacitive_sensing`` is used to implement the sliders. 30 | 31 | * A task that calculates the next move: ``strategy.xc`` 32 | 33 | -------------------------------------------------------------------------------- /app_noughts_and_crosses/config.xscope: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app_noughts_and_crosses/src/computer_player.h: -------------------------------------------------------------------------------- 1 | #ifndef __computer_player_h__ 2 | #define __computer_player_h__ 3 | #include "game.h" 4 | #include "startkit_gpio.h" 5 | 6 | [[combinable]] 7 | void computer_player(client player_if); 8 | 9 | #endif // __computer_player_h__ 10 | -------------------------------------------------------------------------------- /app_noughts_and_crosses/src/computer_player.xc: -------------------------------------------------------------------------------- 1 | #include "computer_player.h" 2 | #include "game.h" 3 | #include "random.h" 4 | #include "scoring.h" 5 | 6 | /** The computer player uses an auxiliary function to find a 7 | move for the computer to play. It fills the 8 | ``best_i`` and ``best_j`` reference parameters with the position 9 | of the best move based on an AI algorithm that searches possible 10 | future move combinations. 11 | The parameter ``board`` is the current board state and the parameter 12 | ``me`` indicates which type of piece the computer is playing. 13 | */ 14 | static void find_best_move(char board[3][3], 15 | int &best_i, 16 | int &best_j, 17 | board_val_t me); 18 | 19 | /** With this function, the computer player task is quite simple. It just 20 | waits for the game tasks to request a move, gets a copy of the 21 | board state, determines the best move to play and then communicates 22 | back with the game state playing the move. */ 23 | 24 | [[combinable]] 25 | void computer_player(client player_if game) 26 | { 27 | while (1) { 28 | select { 29 | case game.move_required(): 30 | char board[3][3]; 31 | int i, j; 32 | game.get_board(board); 33 | find_best_move(board, i, j, game.get_my_val()); 34 | game.play(i, j); 35 | break; 36 | } 37 | } 38 | } 39 | 40 | /****/ 41 | 42 | static void find_best_move(char board[3][3], 43 | int &best_i, 44 | int &best_j, 45 | board_val_t me) 46 | { 47 | board_val_t who = me; 48 | int longest = -1; 49 | struct {int x; int y;} moves[9]; 50 | int moves_left = 9; 51 | for (int i=0;i<3;i++) { 52 | for (int j=0;j<3;j++) { 53 | if (board[i][j] != BOARD_EMPTY) { 54 | moves_left--; 55 | } else { 56 | best_i = i; 57 | best_j = j; 58 | } 59 | } 60 | } 61 | 62 | if (moves_left == 9) { 63 | best_i = my_random(3); 64 | best_j = my_random(3); 65 | return; 66 | } 67 | 68 | int cur_move = 0; 69 | moves[0].x = -1; 70 | moves[0].y = 0; 71 | 72 | while (1) { 73 | int cur_x = moves[cur_move].x; 74 | int cur_y = moves[cur_move].y; 75 | int valid = 1; 76 | int end_of_game = 0; 77 | // step 78 | cur_x++; 79 | if (cur_x > 2) { 80 | cur_x = 0; 81 | cur_y++; 82 | if (cur_y > 2) { 83 | if (cur_move == 0) { 84 | return; 85 | } 86 | else { 87 | // backtrack 88 | cur_move--; 89 | who = who == BOARD_O ? BOARD_X : BOARD_O; 90 | board[moves[cur_move].x][moves[cur_move].y] = BOARD_EMPTY; 91 | continue; 92 | } 93 | } 94 | } 95 | moves[cur_move].x = cur_x; 96 | moves[cur_move].y = cur_y; 97 | 98 | //debug_printf("Move %d, trying (%d, %d)\n", cur_move, cur_x, cur_y); 99 | 100 | if (board[cur_x][cur_y] != BOARD_EMPTY) 101 | valid = 0; 102 | 103 | if (valid) { 104 | board[cur_x][cur_y] = who; 105 | // score the board 106 | int end_of_game, winner; 107 | score(board, end_of_game, winner); 108 | if (winner == me) { 109 | if (cur_move > longest) { 110 | longest = cur_move; 111 | best_i = moves[0].x; 112 | best_j = moves[0].y; 113 | //debug_printf("Found winning sequence (length=%d)\n", cur_move); 114 | } 115 | } 116 | } 117 | 118 | if (valid && !end_of_game && cur_move < moves_left - 1) { 119 | cur_move++; 120 | who = who == BOARD_O ? BOARD_X : BOARD_O; 121 | moves[cur_move].x = -1; 122 | moves[cur_move].y = 0; 123 | } 124 | else if (valid) { 125 | board[cur_x][cur_y] = BOARD_EMPTY; 126 | } 127 | } 128 | return; 129 | } 130 | -------------------------------------------------------------------------------- /app_noughts_and_crosses/src/debug_conf.h: -------------------------------------------------------------------------------- 1 | #define DEBUG_PRINT_ENABLE 1 2 | -------------------------------------------------------------------------------- /app_noughts_and_crosses/src/game.h: -------------------------------------------------------------------------------- 1 | #ifndef __game_h__ 2 | #define __game_h__ 3 | #include "startkit_gpio.h" 4 | 5 | /** The game task controls the board state and blinking cursor, displaying them 6 | via the LED connection to the GPIO driver task. The key interface is 7 | between the game task and the two player tasks. This includes functions 8 | for getting and updating the current game state. 9 | 10 | The game task uses notifications to inform the player tasks that a move is 11 | required. 12 | */ 13 | 14 | typedef enum board_val_t { 15 | BOARD_EMPTY, 16 | BOARD_X, 17 | BOARD_O, 18 | } board_val_t; 19 | 20 | typedef interface player_if { 21 | // This function will fill in the supplied board array with the 22 | // current game state. 23 | void get_board(char board[3][3]); 24 | 25 | // Set the user cursor to the specified position. 26 | void set_cursor(unsigned row, unsigned col); 27 | 28 | // Clear the user cursor from the board. 29 | void clear_cursor(); 30 | 31 | // This function can be called by players to determine whether they 32 | // are the X piece or the O piece. 33 | board_val_t get_my_val(); 34 | 35 | // This notification will be signalled by the game to the player when 36 | // a move is required from the player. 37 | [[notification]] slave void move_required(); 38 | 39 | // This function is called by the player to make a move in the specified 40 | // position. 41 | [[clears_notification]] void play(unsigned row, unsigned col); 42 | } player_if; 43 | 44 | // This task controls the game state providing two connections to the 45 | // two players of the game. 46 | [[combinable]] 47 | void game(server player_if players[2], client startkit_led_if i_led); 48 | 49 | /** Note that game task is *combinable* allowing it to share processing time 50 | with other combinable tasks in between reacting to events. 51 | **/ 52 | 53 | #endif // __game_h__ 54 | -------------------------------------------------------------------------------- /app_noughts_and_crosses/src/game.xc: -------------------------------------------------------------------------------- 1 | #include "game.h" 2 | #include "random.h" 3 | #include "scoring.h" 4 | #include 5 | #include 6 | #include 7 | 8 | static void clear_board(char board[3][3]) 9 | { 10 | for (int i = 0; i < 3; i++) 11 | for (int j = 0; j < 3; j++) 12 | board[i][j] = BOARD_EMPTY; 13 | } 14 | 15 | static int get_led_level(board_val_t val) 16 | { 17 | switch (val) { 18 | case BOARD_EMPTY: 19 | return 0; 20 | case BOARD_O: 21 | return LED_ON; 22 | case BOARD_X: 23 | return (LED_ON/16); 24 | } 25 | return 0; 26 | } 27 | 28 | static void display_board(client startkit_led_if i_led, 29 | char board[3][3]) 30 | { 31 | for (int i = 0; i < 3; i++) 32 | for (int j = 0; j < 3; j++) { 33 | i_led.set(i, j, get_led_level(board[i][j])); 34 | } 35 | } 36 | 37 | static void display_ending(client startkit_led_if i_led, 38 | char board[3][3], 39 | board_val_t winner) 40 | { 41 | // flash the winners moves for a bit 42 | int num_flashes = 4; 43 | int flash_delay = 20000000; 44 | int val = 0; 45 | for (int count = 0; count < num_flashes*2; count++) { 46 | for (int i = 0; i < 3; i++) { 47 | for (int j = 0; j < 3; j++) { 48 | int level; 49 | if (winner == BOARD_EMPTY) 50 | level == val ? LED_ON : 0; 51 | else if (board[i][j] == winner) 52 | level = val ? get_led_level(winner) : 0; 53 | else 54 | level = 0; 55 | i_led.set(i, j, level); 56 | } 57 | } 58 | timer tmr; 59 | int t; 60 | tmr :> t; 61 | tmr when timerafter(t+flash_delay) :> void; 62 | val = ~val; 63 | } 64 | } 65 | 66 | [[combinable]] 67 | void game(server player_if players[2], client startkit_led_if i_led) 68 | { 69 | char board[3][3]; 70 | int cursor_x = -1, cursor_y; 71 | timer tmr; 72 | int time; 73 | int cursor_val = 0; 74 | int flash_period = 200 * 1000 * 100; 75 | clear_board(board); 76 | int starting_player = my_random(2); 77 | players[starting_player].move_required(); 78 | while (1) { 79 | select { 80 | case players[int i].play(unsigned row, unsigned col): 81 | board_val_t mark = (i == 0 ? BOARD_O : BOARD_X); 82 | assert(row < 3 && col < 3); 83 | assert(board[row][col] == BOARD_EMPTY); 84 | board[row][col] = mark; 85 | display_board(i_led, board); 86 | int end_of_game, winner; 87 | score(board, end_of_game, winner); 88 | if (end_of_game) { 89 | display_ending(i_led, board, winner); 90 | clear_board(board); 91 | display_board(i_led, board); 92 | int starting_player = my_random(2); 93 | players[starting_player].move_required(); 94 | } 95 | else { 96 | players[1-i].move_required(); 97 | } 98 | break; 99 | 100 | case players[int i].get_board(char pboard[3][3]): 101 | memcpy(pboard, board, sizeof(board)); 102 | break; 103 | 104 | case players[int i].set_cursor(unsigned row, unsigned col): 105 | assert(row < 3 && col < 3); 106 | if (cursor_x != -1) 107 | i_led.set(cursor_x, cursor_y, 108 | get_led_level(board[cursor_x][cursor_y])); 109 | cursor_x = row; cursor_y = col; 110 | i_led.set(cursor_x, cursor_y, cursor_val); 111 | tmr :> time; 112 | cursor_val = 0; 113 | break; 114 | 115 | case players[int i].get_my_val() -> board_val_t val: 116 | val = (i == 0 ? BOARD_O : BOARD_X); 117 | break; 118 | 119 | case players[int i].clear_cursor(): 120 | if (cursor_x != -1) 121 | i_led.set(cursor_x, cursor_y, 122 | get_led_level(board[cursor_x][cursor_y])); 123 | cursor_x = -1; 124 | break; 125 | 126 | case (cursor_x != -1) => tmr when timerafter(time + flash_period) :> void: 127 | i_led.set(cursor_x, cursor_y, cursor_val); 128 | cursor_val = LED_ON - cursor_val; 129 | time += flash_period; 130 | break; 131 | } 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /app_noughts_and_crosses/src/main.xc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, 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 | #include 6 | #include 7 | #include "game.h" 8 | #include "user_player.h" 9 | #include "computer_player.h" 10 | 11 | /** 12 | The tic-tac-toe demo is a program that plays tic-tac-toe (also known as 13 | noughts and crosses) on a XMOS startKIT development board. It is provided 14 | as a demonstation program of how to program the device. 15 | The 3x3 display of LEDs shows the board status: 16 | 17 | - Full LEDs: user player (marking a O) 18 | - Dimmed LEDs: computer player (marking a 1) 19 | 20 | When it is the user's move, one of the LEDs flashes - this is a cursor and 21 | it can be moved by swiping the sliders. Pressing the button makes a move, 22 | and the computer player will make the next move. 23 | 24 | The application consists of four tasks: 25 | 26 | * The ``startkit_gpio_driver`` task drives the LEDs on the device (using 27 | PWM to make the lights glow at different levels of intensity), the 28 | capacitive sensors on the sliders and the button. It has three 29 | interface connections connected to it - one for the button, one for the 30 | LEDs and one for the slider. 31 | * The ``game`` task which controls the game state. It is connected to the 32 | two player tasks and to the gpio task to drive the LEDs to display the 33 | game state. 34 | * The ``user_player`` task which receives notifications from 35 | and sends commands to the game task. It also connects to the 36 | gpio task to read the sliders and buttons when the user player makes 37 | a move. 38 | * The ``cpu_player`` task which receives notifications from and send 39 | commands to the game task. It uses an internal AI algorithm to determine 40 | what move to make. 41 | 42 | .. aafig:: 43 | 44 | `gpio_driver` ` `user player task` `cpu player task` 45 | +--------+ +-------+ +-------+ 46 | | | `button_if` | | | | 47 | | +<-------------+ | | | 48 | I/O<--+ | `slider_if` | | | | 49 | | +<-------------+ +--+ +--+ | 50 | | | | | | | | | 51 | +--+-----+ +-------+ | | | | 52 | ^ | | +-------+ 53 | | `game task` | | 54 | | +-------+ | | 55 | | | | | | 56 | +-----------+ +<----------+ | 57 | `led_if` | | `game_if` | 58 | | +<---------------+ 59 | | | 60 | +-------+ 61 | 62 | The four tasks are spread across two logical cores. One 63 | logical core runs the gpio driver which needs to be responsive to the I/O 64 | pins. The other core runs the other three tasks which do not have real-time 65 | constraints and share the core via co-operative multitasking. 66 | 67 | **/ 68 | 69 | /** 70 | The main program consists of a ``par`` statement to run all the tasks in 71 | parallel with three tasks placed on the same core. The declarations 72 | are typedefs of interface types to connect the tasks together. 73 | */ 74 | 75 | // The port structure required for the GPIO task 76 | startkit_gpio_ports gpio_ports = 77 | {XS1_PORT_32A, XS1_PORT_4A, XS1_PORT_4B, XS1_CLKBLK_1}; 78 | 79 | int main() { 80 | startkit_button_if i_button; 81 | startkit_led_if i_led; 82 | slider_if i_slider_x, i_slider_y; 83 | player_if i_game[2]; 84 | par { 85 | on tile[0].core[0]: game(i_game, i_led); 86 | on tile[0].core[0]: user_player(i_game[0], 87 | i_slider_x, i_slider_y, i_button); 88 | on tile[0].core[0]: computer_player(i_game[1]); 89 | on tile[0]: startkit_gpio_driver(i_led, i_button, 90 | i_slider_x, i_slider_y, 91 | gpio_ports); 92 | 93 | } 94 | return 0; 95 | } 96 | -------------------------------------------------------------------------------- /app_noughts_and_crosses/src/random.h: -------------------------------------------------------------------------------- 1 | extern int my_random(int v); 2 | -------------------------------------------------------------------------------- /app_noughts_and_crosses/src/random.xc: -------------------------------------------------------------------------------- 1 | #include "random.h" 2 | #include 3 | 4 | int my_random(int v) { 5 | timer t; 6 | unsigned time, r; 7 | int r0 = 0; 8 | for(int i = 0x070b; i <= 0x0a0b; i += 0x100) { 9 | r0 = (r0 << 1) ^ getps(i); // This gets the RO values 10 | } 11 | r = r0; // The last 4 bits are xored in. 12 | setps(0x060b, 0xF); // enable RO 13 | t :> time; 14 | t when timerafter(time+5000) :> int _; // Run RO for 50 us 15 | setps(0x060b, 0); // disable RO 16 | r0 = 0; 17 | for(int i = 0x070b; i <= 0x0a0b; i += 0x100) { 18 | r0 = (r0 << 1) ^ getps(i); // XOR RO values, specifically last 4 bits 19 | } 20 | r ^= r0; // last 4 bits are random. 21 | return r % v; // this will have a bias when v is not a power of 2. 22 | } 23 | -------------------------------------------------------------------------------- /app_noughts_and_crosses/src/scoring.h: -------------------------------------------------------------------------------- 1 | #ifndef __scoring_h__ 2 | #define __scoring_h__ 3 | 4 | /** Function that scores a board - returns one of the three scores above. 5 | * 6 | * \param end_of_game set to 1 if the board position is the end of game 7 | * \param winner set to the winner or BOARD_EMPTY if no winner 8 | */ 9 | void score(char board[3][3], int &end_of_game, int &winner); 10 | 11 | #endif // __scoring_h__ 12 | -------------------------------------------------------------------------------- /app_noughts_and_crosses/src/scoring.xc: -------------------------------------------------------------------------------- 1 | #include "scoring.h" 2 | #include "game.h" 3 | 4 | /** Function that scores a board - returns one of the three scores above. 5 | */ 6 | void score(char board[3][3], int &end_of_game, int &winner) { 7 | end_of_game = 1; 8 | // check for a winning row 9 | for(int j = 0; j < 3; j++) { 10 | if (board[0][j] == BOARD_EMPTY) { 11 | continue; 12 | } 13 | int cnt = 0; 14 | for(int i = 1; i < 3; i++) { 15 | if (board[i][j] == board[0][j]) { 16 | cnt++; 17 | } 18 | } 19 | if (cnt == 2) { 20 | winner = board[0][j]; 21 | return; 22 | } 23 | } 24 | 25 | // check for a winning column 26 | for(int j = 0; j < 3; j++) { 27 | if (board[j][0] == BOARD_EMPTY) { 28 | continue; 29 | } 30 | int cnt = 0; 31 | for(int i = 1; i < 3; i++) { 32 | if (board[j][i] == board[j][0]) { 33 | cnt++; 34 | } 35 | } 36 | if (cnt == 2) { 37 | winner = board[j][0]; 38 | return; 39 | } 40 | } 41 | 42 | // check for a winning diagonal 43 | if (board[1][1] != BOARD_EMPTY) { 44 | if (board[0][0] == board[1][1] && board[1][1] == board[2][2]) { 45 | winner = board[1][1]; 46 | return; 47 | } 48 | } 49 | if (board[1][1] != BOARD_EMPTY) { 50 | if (board[2][0] == board[1][1] && board[1][1] == board[0][2]) { 51 | winner = board[1][1]; 52 | return; 53 | } 54 | } 55 | 56 | // There is no winner 57 | winner = BOARD_EMPTY; 58 | // Check if all spaces have been filled 59 | for (int i = 0; i < 3; i++) 60 | for (int j = 0; j < 3; j++) 61 | if (board[i][j] == BOARD_EMPTY) 62 | end_of_game = 0; 63 | 64 | return; 65 | } 66 | -------------------------------------------------------------------------------- /app_noughts_and_crosses/src/strategy.h: -------------------------------------------------------------------------------- 1 | void strategy(chanend to_output); 2 | -------------------------------------------------------------------------------- /app_noughts_and_crosses/src/user_player.h: -------------------------------------------------------------------------------- 1 | #ifndef __user_player_h__ 2 | #define __user_player_h__ 3 | #include "game.h" 4 | #include "startkit_gpio.h" 5 | 6 | [[combinable]] 7 | void user_player(client player_if, 8 | client slider_if i_slider_x, 9 | client slider_if i_slider_y, 10 | client startkit_button_if i_button); 11 | 12 | #endif // __user_player_h__ 13 | -------------------------------------------------------------------------------- /app_noughts_and_crosses/src/user_player.xc: -------------------------------------------------------------------------------- 1 | #include "user_player.h" 2 | #include 3 | 4 | /** The user player task connects to the game task and the gpio task. 5 | It is either in a playing state or idle state. When it gets a 6 | move request notification from the game task, it moves into the playing 7 | state and sets up the cursor in the game task. Whilst in the playing state 8 | it reacts to slider and button events to move the cursor 9 | and complete the game move. 10 | */ 11 | 12 | [[combinable]] 13 | void user_player(client player_if i_game, 14 | client slider_if i_slider_x, 15 | client slider_if i_slider_y, 16 | client startkit_button_if i_button) 17 | { 18 | /** The task has some local state - a variable to determine whether it 19 | is in a playing state or not, ``x`` and ``y`` variables to store 20 | the current position of the cursor and a local copy of the board state. 21 | */ 22 | int playing = 0; 23 | int x = 0, y = 0; 24 | char board[3][3]; 25 | 26 | /** The main body of the task consists of a ``while (1) select`` loop. */ 27 | while (1) { 28 | select { 29 | /** The first case in the select reacts when the game tasks requests 30 | a move is played. This causes the player task to enter the playing 31 | state. At this point the task takes a copy of the board state and 32 | sets up the cursor by interacting with the game task. */ 33 | case i_game.move_required(): 34 | // Get a local copy of the board state 35 | i_game.get_board(board); 36 | // Find an empty place to place the cursor 37 | int found = 0; 38 | for (int i = 0; i < 3 && !found; i++) { 39 | for (int j = 0 ; j < 3 && !found; j++) { 40 | if (board[i][j] == BOARD_EMPTY) { 41 | x = i; 42 | y = j; 43 | found = 1; 44 | } 45 | } 46 | } 47 | i_game.set_cursor(x, y); 48 | playing = 1; 49 | break; 50 | 51 | /** If the button is pressed it causes an event on the connection 52 | to the gpio driver. The following case reacts to this event and 53 | if the task is in the playing state and the cursor is at an empty 54 | space on the board, it calls the ``play`` function over 55 | the connection to the game task to play the move, and then leave the 56 | playing state. */ 57 | case i_button.changed(): 58 | button_val_t val = i_button.get_value(); 59 | if (playing && val == BUTTON_DOWN) { 60 | if (board[x][y] == BOARD_EMPTY) { 61 | // Make the move 62 | i_game.clear_cursor(); 63 | i_game.play(x, y); 64 | playing = 0; 65 | } 66 | } 67 | break; 68 | 69 | /** The task also reacts to changes in the slider. In this case it 70 | moves the cursor if the slider notifies the task of a 71 | ``LEFTING`` or ``RIGHTING`` event (indicating that the user 72 | has swiped left or right). 73 | */ 74 | case i_slider_x.changed_state(): 75 | sliderstate state = i_slider_x.get_slider_state(); 76 | if (!playing) 77 | break; 78 | if (state != LEFTING && state != RIGHTING) 79 | break; 80 | int dir = state == LEFTING ? 1 : -1; 81 | int new_x = x + dir; 82 | if (new_x >= 0 && new_x < 3) { 83 | x = new_x; 84 | i_game.set_cursor(x, y); 85 | } 86 | break; 87 | 88 | /** The case to handle the vertical slider is similar. Handling 89 | move requests, slider swipes and button presses completes the 90 | player task. 91 | **/ 92 | case i_slider_y.changed_state(): 93 | sliderstate state = i_slider_y.get_slider_state(); 94 | if (!playing) 95 | break; 96 | if (state != LEFTING && state != RIGHTING) 97 | break; 98 | int dir = state == LEFTING ? 1 : -1; 99 | int new_y = y + dir; 100 | if (new_y >= 0 && new_y < 3) { 101 | y = new_y; 102 | i_game.set_cursor(x, y); 103 | } 104 | break; 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /app_scanning_leds/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | app_scanning_leds 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.cdt.managedbuilder.core.genmakebuilder 10 | clean,full,incremental, 11 | 12 | 13 | ?children? 14 | ?name?=outputEntries\|?children?=?name?=entry\\\\|\\|\|| 15 | 16 | 17 | ?name? 18 | 19 | 20 | 21 | org.eclipse.cdt.make.core.append_environment 22 | true 23 | 24 | 25 | org.eclipse.cdt.make.core.buildArguments 26 | CONFIG=Debug 27 | 28 | 29 | org.eclipse.cdt.make.core.buildCommand 30 | xmake 31 | 32 | 33 | org.eclipse.cdt.make.core.cleanBuildTarget 34 | clean 35 | 36 | 37 | org.eclipse.cdt.make.core.contents 38 | org.eclipse.cdt.make.core.activeConfigSettings 39 | 40 | 41 | org.eclipse.cdt.make.core.enableAutoBuild 42 | false 43 | 44 | 45 | org.eclipse.cdt.make.core.enableCleanBuild 46 | true 47 | 48 | 49 | org.eclipse.cdt.make.core.enableFullBuild 50 | true 51 | 52 | 53 | org.eclipse.cdt.make.core.stopOnError 54 | true 55 | 56 | 57 | org.eclipse.cdt.make.core.useDefaultBuildCmd 58 | false 59 | 60 | 61 | 62 | 63 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder 64 | full,incremental, 65 | 66 | 67 | 68 | 69 | 70 | org.eclipse.cdt.core.cnature 71 | org.eclipse.cdt.managedbuilder.core.managedBuildNature 72 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature 73 | com.xmos.cdt.core.XdeProjectNature 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /app_scanning_leds/.xproject: -------------------------------------------------------------------------------- 1 | sw_startkit_examplesXM-004098-SM -------------------------------------------------------------------------------- /app_scanning_leds/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 | TARGET = STARTKIT 5 | 6 | # The APP_NAME variable determines the name of the final .xe file. It should 7 | # not include the .xe postfix. If left blank the name will default to 8 | # the project name 9 | APP_NAME = Blink 10 | 11 | # The USED_MODULES variable lists other module used by the application. 12 | USED_MODULES = 13 | 14 | # The flags passed to xcc when building the application 15 | # You can also set the following to override flags for a particular language: 16 | # XCC_XC_FLAGS, XCC_C_FLAGS, XCC_ASM_FLAGS, XCC_CPP_FLAGS 17 | # If the variable XCC_MAP_FLAGS is set it overrides the flags passed to 18 | # xcc for the final link (mapping) stage. 19 | XCC_FLAGS_Debug = -O0 -g 20 | XCC_FLAGS_Release = -O2 -g 21 | 22 | # The VERBOSE variable, if set to 1, enables verbose output from the make system. 23 | VERBOSE = 0 24 | 25 | XMOS_MAKE_PATH ?= ../.. 26 | -include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.common 27 | -------------------------------------------------------------------------------- /app_scanning_leds/README.rst: -------------------------------------------------------------------------------- 1 | LED scan example 2 | ================ 3 | 4 | :scope: Example 5 | :description: A simple demo blinks each LED on the board individually 6 | :keywords: LEDs, startKIT, buttons 7 | 8 | This program blinks each of the startKITs onboard LEDs individually 9 | to give new users an idea on how to address them. 10 | This is meant to be similar to the Arduinos Blink sketch. 11 | -------------------------------------------------------------------------------- /app_scanning_leds/src/main.xc: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on: Dec 21, 2013 3 | * Author: ShannonS 4 | * E-mail: strutz.shannon@gmail.com 5 | * Website: www.shannonstrutz.com 6 | * 7 | * This code is offered under the MIT 2013 License 8 | */ 9 | 10 | #include 11 | #include 12 | 13 | //As listed in the startKIT hardware manual, A1 is at port P32A19, pin X0D70 14 | //What alll that means is that it is controlled by bit 19 in the 32-bit register 15 | 16 | //Unfortunatly the hardware manual also has another error 17 | //At the bottom of page 10, it states the LED pins are active high. 18 | //When you run this program, you can clearly see that is wrong. 19 | 20 | port p32 = XS1_PORT_32A; //PORT 32A 21 | int leds[10] = { 22 | 0b01111111111111111111, //LED A1 23 | 0b10111111111111111111, //LED B1 24 | 0b11011111111111111111, //LED C1 25 | 0b11111110111111111111, //LED A2 26 | 0b11111111011111111111, //LED B2 27 | 0b11111111101111111111, //LED C2 28 | 0b11111111110111111111, //LED A3 29 | 0b11111111111011111111, //LED B3 30 | 0b11111111111101111111, //LED C3 31 | 0b11111111111111111111 //ALL OFF 32 | }; 33 | 34 | port p1 = XS1_PORT_1A; 35 | port p2 = XS1_PORT_1D; 36 | 37 | 38 | int main(void){ 39 | int delay = 500; 40 | while(1){ 41 | for(int i = 0; i < 10; i++) { 42 | p32 <: leds[i]; 43 | delay_milliseconds(delay); 44 | } 45 | p2 <: 1; 46 | delay_milliseconds(delay); 47 | p2 <: 0; 48 | p1 <: 1; 49 | delay_milliseconds(delay); 50 | p1 <: 0; 51 | } 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /app_servo/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 | TARGET = STARTKIT 5 | 6 | # The APP_NAME variable determines the name of the final .xe file. It should 7 | # not include the .xe postfix. If left blank the name will default to 8 | # the project name 9 | APP_NAME = servo 10 | 11 | # The USED_MODULES variable lists other module used by the application. 12 | USED_MODULES = module_startkit_servo 13 | 14 | # The flags passed to xcc when building the application 15 | # You can also set the following to override flags for a particular language: 16 | # XCC_XC_FLAGS, XCC_C_FLAGS, XCC_ASM_FLAGS, XCC_CPP_FLAGS 17 | # If the variable XCC_MAP_FLAGS is set it overrides the flags passed to 18 | # xcc for the final link (mapping) stage. 19 | XCC_FLAGS = -O2 -g -report 20 | 21 | # The XCORE_ARM_PROJECT variable, if set to 1, configures this 22 | # project to create both xCORE and ARM binaries. 23 | XCORE_ARM_PROJECT = 0 24 | 25 | # The VERBOSE variable, if set to 1, enables verbose output from the make system. 26 | VERBOSE = 0 27 | 28 | XMOS_MAKE_PATH ?= ../.. 29 | -include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.common 30 | -------------------------------------------------------------------------------- /app_servo/README.rst: -------------------------------------------------------------------------------- 1 | Servo test 2 | ========== 3 | 4 | :scope: Example 5 | :description: Simple demo that exercises the servo library module 6 | :keywords: servo, PWM, PPM, startKIT 7 | 8 | Simple test for the servo module. Ramps all 4 signals from min to max over a few seconds 9 | 10 | Implementation 11 | -------------- 12 | 13 | There are two tasks: 14 | 15 | * A task to drive the servo on a single wide port. This uses the 16 | driver found in ``module_strtkit_servo`` 17 | * A task that generates ramp up/down commands for the servo driver 18 | 19 | -------------------------------------------------------------------------------- /app_servo/config.xscope: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app_servo/main.xc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "servo.h" 5 | 6 | //Test program - ramps up and down all 4 channels 7 | //See servo.h for API 8 | //See servo.xc for implementation notes 9 | 10 | #define PORT_WIDTH 4 11 | 12 | on tile[0] : out port p_servo = XS1_PORT_4C; //D14, D20, D15, D21 on startKIT 13 | 14 | void demo_servo (client interface servo_if i_servo) { 15 | timer tmr; 16 | unsigned int time, delay = 5000 * MICROSECOND; 17 | unsigned int i, j; 18 | 19 | tmr :> time; 20 | while (1) { 21 | printstrln("Going up!"); 22 | for (i = SERVO_MIN_POS; i < SERVO_MAX_POS; i+= 100) { 23 | for (j = 0; j < PORT_WIDTH; j++) { 24 | i_servo.set_pos(j, i); 25 | } 26 | tmr when timerafter(time + delay) :> time; 27 | } 28 | printstrln("Going down!"); 29 | for (i = SERVO_MAX_POS; i > SERVO_MIN_POS; i-= 100) { 30 | tmr when timerafter(time + delay) :> time; 31 | for (j = 0; j < PORT_WIDTH; j++) { 32 | i_servo.set_pos(j, i); 33 | } 34 | tmr when timerafter(time + delay) :> time; 35 | } 36 | } 37 | return; 38 | } 39 | 40 | int main() { 41 | interface servo_if i_servo; 42 | par { 43 | on tile[0] : demo_servo(i_servo); 44 | on tile[0] : servo_task(i_servo, p_servo, PORT_WIDTH, SERVO_CENTRE_POS); 45 | } 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /app_spinning_bar/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | app_spinning_bar 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.cdt.managedbuilder.core.genmakebuilder 10 | clean,full,incremental, 11 | 12 | 13 | ?children? 14 | ?name?=outputEntries\|?children?=?name?=entry\\\\|\\|\|| 15 | 16 | 17 | ?name? 18 | 19 | 20 | 21 | org.eclipse.cdt.make.core.append_environment 22 | true 23 | 24 | 25 | org.eclipse.cdt.make.core.buildArguments 26 | CONFIG=Debug 27 | 28 | 29 | org.eclipse.cdt.make.core.buildCommand 30 | xmake 31 | 32 | 33 | org.eclipse.cdt.make.core.cleanBuildTarget 34 | clean 35 | 36 | 37 | org.eclipse.cdt.make.core.contents 38 | org.eclipse.cdt.make.core.activeConfigSettings 39 | 40 | 41 | org.eclipse.cdt.make.core.enableAutoBuild 42 | false 43 | 44 | 45 | org.eclipse.cdt.make.core.enableCleanBuild 46 | true 47 | 48 | 49 | org.eclipse.cdt.make.core.enableFullBuild 50 | true 51 | 52 | 53 | org.eclipse.cdt.make.core.stopOnError 54 | true 55 | 56 | 57 | org.eclipse.cdt.make.core.useDefaultBuildCmd 58 | false 59 | 60 | 61 | 62 | 63 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder 64 | full,incremental, 65 | 66 | 67 | 68 | 69 | 70 | org.eclipse.cdt.core.cnature 71 | org.eclipse.cdt.managedbuilder.core.managedBuildNature 72 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature 73 | com.xmos.cdt.core.XdeProjectNature 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /app_spinning_bar/.xproject: -------------------------------------------------------------------------------- 1 | sw_startkit_examplesXM-004098-SM -------------------------------------------------------------------------------- /app_spinning_bar/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = STARTKIT 2 | APP_NAME = 3 | XCC_FLAGS = 4 | USED_MODULES = 5 | 6 | #============================================================================= 7 | # The following part of the Makefile includes the common build infrastructure 8 | # for compiling XMOS applications. You should not need to edit below here. 9 | 10 | XMOS_MAKE_PATH ?= ../.. 11 | include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.common 12 | -------------------------------------------------------------------------------- /app_spinning_bar/README.rst: -------------------------------------------------------------------------------- 1 | The spinning bar 2 | ================ 3 | 4 | :scope: Example 5 | :description: A simple demo using LEDs on the startKIT 6 | :keywords: LEDs, startKIT 7 | 8 | 9 | This is one of the simplest examples. It spins a sequence:: 10 | 11 | | / - \ 12 | 13 | onto the 3x3 grid of LEDS. It just requires a single main program that 14 | outputs a sequence of values to the LEDs. After each value is written the 15 | program waits for a timer. The delay increases over time, slowing down the 16 | spinning bar. 17 | -------------------------------------------------------------------------------- /app_spinning_bar/src/main.xc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* 5 | * the patterns for each bit are: 6 | * 0x80000 0x40000 0x20000 7 | * 0x01000 0x00800 0x00400 8 | * 0x00200 0x00100 0x00080 9 | * 10 | * As the leds go to 3V3, 0x00000 drives all 9 leds on, and 0xE1F80 drives 11 | * all nine leds off. 12 | * The four patterns below drive a dash, backslash, pipe, and slash. 13 | */ 14 | 15 | #define MODES 4 16 | 17 | int leds[MODES] = { 18 | 0xE0380, 19 | 0x61700, 20 | 0xA1680, 21 | 0xC1580 22 | }; 23 | 24 | /* This the port where the leds reside */ 25 | port p32 = XS1_PORT_32A; 26 | 27 | int main(void) { 28 | int delay = 50; // initial delay 50 ms 29 | int led_counter = 0; // A counter to count through the leds array 30 | while(1) { 31 | delay_milliseconds(delay); // Wait 32 | delay += 1; // Gradually increase the delay 33 | p32 <: leds[led_counter]; // Drive the next led pattern 34 | led_counter++; // Pick the next pattern 35 | if (led_counter == MODES) { // If we are at the last pattern 36 | led_counter = 0; // then wrap around. 37 | } 38 | } 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /app_spinning_dot/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | app_spinning_dot 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.cdt.managedbuilder.core.genmakebuilder 10 | clean,full,incremental, 11 | 12 | 13 | ?children? 14 | ?name?=outputEntries\|?children?=?name?=entry\\\\|\\|\|| 15 | 16 | 17 | ?name? 18 | 19 | 20 | 21 | org.eclipse.cdt.make.core.append_environment 22 | true 23 | 24 | 25 | org.eclipse.cdt.make.core.buildArguments 26 | CONFIG=Debug 27 | 28 | 29 | org.eclipse.cdt.make.core.buildCommand 30 | xmake 31 | 32 | 33 | org.eclipse.cdt.make.core.cleanBuildTarget 34 | clean 35 | 36 | 37 | org.eclipse.cdt.make.core.contents 38 | org.eclipse.cdt.make.core.activeConfigSettings 39 | 40 | 41 | org.eclipse.cdt.make.core.enableAutoBuild 42 | false 43 | 44 | 45 | org.eclipse.cdt.make.core.enableCleanBuild 46 | true 47 | 48 | 49 | org.eclipse.cdt.make.core.enableFullBuild 50 | true 51 | 52 | 53 | org.eclipse.cdt.make.core.stopOnError 54 | true 55 | 56 | 57 | org.eclipse.cdt.make.core.useDefaultBuildCmd 58 | false 59 | 60 | 61 | 62 | 63 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder 64 | full,incremental, 65 | 66 | 67 | 68 | 69 | 70 | org.eclipse.cdt.core.cnature 71 | org.eclipse.cdt.managedbuilder.core.managedBuildNature 72 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature 73 | com.xmos.cdt.core.XdeProjectNature 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /app_spinning_dot/.xproject: -------------------------------------------------------------------------------- 1 | sw_startkit_examplesXM-004098-SM -------------------------------------------------------------------------------- /app_spinning_dot/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = STARTKIT 2 | APP_NAME = 3 | XCC_FLAGS = 4 | USED_MODULES = 5 | 6 | #============================================================================= 7 | # The following part of the Makefile includes the common build infrastructure 8 | # for compiling XMOS applications. You should not need to edit below here. 9 | 10 | XMOS_MAKE_PATH ?= ../.. 11 | include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.common 12 | -------------------------------------------------------------------------------- /app_spinning_dot/README.rst: -------------------------------------------------------------------------------- 1 | The spinning dot 2 | ================ 3 | 4 | :scope: Example 5 | :description: A LED demo for startKIT 6 | :keywords: LEDs, startKIT 7 | 8 | This is a slightly more complex version of the spinning bar. Rather than 9 | spinning a bar a single dit is spun around the edge of the 3x3 square, but 10 | its movement is smoothed out by antialiasing. A LED will gradually be 11 | switched on whilst the previous LED is gradually switched off. 12 | 13 | It just requires a single main program that outputs a sequence of values to 14 | the LEDs. When the dot has moved a fraction X% between two LEDs, then the 15 | next LED pattern is driven for X% of the time, and then the old pattern is 16 | driven for 100-X% of the time. The PWM periodicity is 1ms, so a 1% duty 17 | cycle results in a 10 us on and 990 us off period. 18 | 19 | As an added bonus the middle LED is flipped on every rotation. 20 | -------------------------------------------------------------------------------- /app_spinning_dot/src/main.xc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, 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 | /* 9 | * the patterns for each bit are: 10 | * 0x80000 0x40000 0x20000 11 | * 0x01000 0x00800 0x00400 12 | * 0x00200 0x00100 0x00080 13 | * 14 | * As the leds go to 3V3, 0x00000 drives all 9 leds on, and 0xE1F80 drives 15 | * all nine leds off. 16 | * The four patterns below drive a dash, backslash, pipe, and slash. 17 | */ 18 | 19 | #define MIDDLE 0x00800 20 | 21 | #define MODES 8 22 | 23 | int leds[MODES] = { 24 | 0xA1F80, 25 | 0xC1F80, 26 | 0xE1B80, 27 | 0xE1F00, 28 | 0xE1E80, 29 | 0xE1D80, 30 | 0xE0F80, 31 | 0x71F80, 32 | }; 33 | 34 | /* This the port where the leds reside */ 35 | port p32 = XS1_PORT_32A; 36 | 37 | int main(void) { 38 | timer tmr; // Create a timer to time transistions 39 | int now; // A variable to hold the current time 40 | int pwm_period = 100000; // 1 ms PWM period, 1 kHz clock 41 | int delay = 1000/MODES; // One full circle in 1000 PWM periods = 1 sec 42 | int led_counter = 0; // A counter to count through the leds array 43 | int middle = 0; // state of the middle led. Off initially 44 | 45 | tmr :> now; // Get the current time, this is maintained in now 46 | while(1) { 47 | int new_led_counter = led_counter+1; // Next pattern 48 | int new_middle = middle; // and next middle LED status 49 | if (new_led_counter == MODES) { // If we have gone around all patterns 50 | new_led_counter = 0; // Go back to the first pattern 51 | new_middle = new_middle ^ MIDDLE; // and toggle the middle led. 52 | } // To PWM we repeatedly push two LED 53 | for(int i = 0; i < delay; i ++) { // patterns, for a total of 1 ms 54 | p32 <: leds[new_led_counter] ^ new_middle; // new pattern 55 | tmr when timerafter(now+pwm_period*i/delay) :> void; // Wait for i/delay % 56 | p32 <: leds[led_counter] ^ middle; // old pattern 57 | now += pwm_period; // Wait for rest 58 | tmr when timerafter(now) :> void; // increase i for gentle 59 | } // change to brightness 60 | led_counter = new_led_counter; // Move on to the next pattern and 61 | middle = new_middle; // the next middle LED status 62 | } 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /host_dsp_control/Makefile: -------------------------------------------------------------------------------- 1 | 2 | APP_NAME = dsp_control 3 | FLAGS = -O2 -DXSCOPE_HOST_HAS_PROMPT 4 | 5 | ROOT = ../.. 6 | include $(ROOT)/sc_xscope_support/host_library/makefile.shared 7 | 8 | -------------------------------------------------------------------------------- /host_dsp_control/dsp_control.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Note that the device and listener should be run with the same port and IP. 3 | * For example: 4 | * 5 | * xrun --xscope-realtime --xscope-port 127.0.0.1:12346 ... 6 | * 7 | * ./packet_analyser -s 127.0.0.1 -p 12346 8 | * 9 | */ 10 | /* 11 | * Includes for thread support 12 | */ 13 | #ifdef _WIN32 14 | 15 | #include 16 | 17 | #else 18 | 19 | #include 20 | #include 21 | 22 | #endif 23 | 24 | 25 | #include "xscope_host_shared.h" 26 | 27 | #define MAX_FILENAME_LEN 1024 28 | 29 | const char *g_prompt = ""; 30 | 31 | void hook_registration_received(int sockfd, int xscope_probe, char *name) 32 | { 33 | // Do nothing 34 | } 35 | 36 | void hook_data_received(int sockfd, int xscope_probe, void *data, int data_len) 37 | { 38 | // Do nothing 39 | } 40 | 41 | void hook_exiting() 42 | { 43 | // Do nothing 44 | } 45 | 46 | static char get_next_char(const char **buffer) 47 | { 48 | const char *ptr = *buffer; 49 | int len = 0; 50 | while (*ptr && isspace(*ptr)) 51 | ptr++; 52 | 53 | *buffer = ptr + 1; 54 | return *ptr; 55 | } 56 | 57 | static int convert_atoi_substr(const char **buffer) 58 | { 59 | const char *ptr = *buffer; 60 | unsigned int value = 0; 61 | while (*ptr && isspace(*ptr)) 62 | ptr++; 63 | 64 | if (*ptr == '\0') 65 | return 0; 66 | 67 | value = atoi((char*)ptr); 68 | 69 | while (*ptr && !isspace(*ptr)) 70 | ptr++; 71 | 72 | *buffer = ptr; 73 | return value; 74 | } 75 | 76 | #define LINE_LENGTH 1024 77 | 78 | /* 79 | * A separate thread to handle user commands to control the target. 80 | */ 81 | #ifdef _WIN32 82 | DWORD WINAPI console_thread(void *arg) 83 | #else 84 | void *console_thread(void *arg) 85 | #endif 86 | { 87 | int sockfd = *(int *)arg; 88 | char buffer[LINE_LENGTH + 1]; 89 | do { 90 | int i = 0; 91 | int c = 0; 92 | const char *ptr = NULL; 93 | char cmd = 0; 94 | 95 | for (i = 0; (i < LINE_LENGTH) && ((c = getchar()) != EOF) && (c != '\n'); i++) 96 | buffer[i] = tolower(c); 97 | buffer[i] = '\0'; 98 | 99 | ptr = &buffer[0]; 100 | cmd = get_next_char(&ptr); 101 | switch (cmd) { 102 | case 'q': 103 | print_and_exit("Done\n"); 104 | break; 105 | 106 | default: 107 | xscope_ep_request_upload(sockfd, i + 1, (const unsigned char *)buffer); 108 | break; 109 | } 110 | } while (1); 111 | 112 | #ifdef _WIN32 113 | return 0; 114 | #else 115 | return NULL; 116 | #endif 117 | } 118 | 119 | void usage(char *argv[]) 120 | { 121 | printf("Usage: %s [-s server_ip] [-p port]\n", argv[0]); 122 | printf(" -s server_ip : The IP address of the xscope server (default %s)\n", DEFAULT_SERVER_IP); 123 | printf(" -p port : The port of the xscope server (default %s)\n", DEFAULT_PORT); 124 | exit(1); 125 | } 126 | 127 | int main(int argc, char *argv[]) 128 | { 129 | #ifdef _WIN32 130 | HANDLE thread; 131 | #else 132 | pthread_t tid; 133 | #endif 134 | char *server_ip = DEFAULT_SERVER_IP; 135 | char *port_str = DEFAULT_PORT; 136 | int err = 0; 137 | int sockfds[1] = {0}; 138 | int c = 0; 139 | 140 | #ifndef _WIN32 141 | // Ensure that stdout is not buffered for the auto-test framework 142 | setvbuf(stdout, NULL, _IOLBF, 0); 143 | #endif 144 | 145 | while ((c = getopt(argc, argv, "s:p:")) != -1) { 146 | switch (c) { 147 | case 's': 148 | server_ip = optarg; 149 | break; 150 | case 'p': 151 | port_str = optarg; 152 | break; 153 | case ':': /* -f or -o without operand */ 154 | fprintf(stderr, "Option -%c requires an operand\n", optopt); 155 | err++; 156 | break; 157 | case '?': 158 | fprintf(stderr, "Unrecognized option: '-%c'\n", optopt); 159 | err++; 160 | } 161 | } 162 | if (optind < argc) 163 | err++; 164 | 165 | if (err) 166 | usage(argv); 167 | 168 | sockfds[0] = initialise_socket(server_ip, port_str); 169 | 170 | // Now start the console 171 | #ifdef _WIN32 172 | thread = CreateThread(NULL, 0, console_thread, &sockfds[0], 0, NULL); 173 | if (thread == NULL) 174 | print_and_exit("ERROR: Failed to create console thread\n"); 175 | #else 176 | err = pthread_create(&tid, NULL, &console_thread, &sockfds[0]); 177 | if (err != 0) 178 | print_and_exit("ERROR: Failed to create console thread\n"); 179 | #endif 180 | 181 | handle_sockets(sockfds, 1); 182 | return 0; 183 | } 184 | 185 | -------------------------------------------------------------------------------- /host_dsp_gui/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.8) 2 | project (host_dsp_gui) 3 | enable_testing() 4 | 5 | set (CMAKE_PREFIX_PATH "/Users/peter/Qt5.3.0/5.3.0/clang_64") 6 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY lib) 7 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY lib) 8 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY bin) 9 | 10 | include_directories( src ) 11 | 12 | file(GLOB_RECURSE GUI_INCLUDES "src/*.h" ) 13 | 14 | file(GLOB_RECURSE GUI_SRC "src/*.cpp" ) 15 | 16 | file(GLOB_RECURSE GUI_UI "src/*.ui" ) 17 | 18 | # Find includes in corresponding build directories 19 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 20 | # Instruct CMake to run moc automatically when needed. 21 | set(CMAKE_AUTOMOC ON) 22 | 23 | # Find the QtWidgets library 24 | find_package(Qt5Widgets) 25 | 26 | qt5_wrap_ui(host_dsp_gui_FORMS_HEADERS ${GUI_UI}) 27 | 28 | message(STATUS ${host_dsp_gui_FORMS_HEADERS}) 29 | message(STATUS ${GUI_SRC}) 30 | message(STATUS ${GUI_INCLUDES}) 31 | 32 | add_executable (host_dsp_gui ${GUI_INCLUDES} ${GUI_SRC} ${host_dsp_gui_FORMS_HEADERS}) 33 | 34 | # Use the Widgets module from Qt 5. 35 | qt5_use_modules(host_dsp_gui Widgets) 36 | -------------------------------------------------------------------------------- /host_dsp_gui/src/biquad_controls.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "biquad_controls.h" 4 | #include "biquad_slider.h" 5 | 6 | const QString bank_title[NUM_BIQUADS] = { 7 | "Low Pass", 8 | "125 Hz", 9 | "250 Hz", 10 | "500 Hz", 11 | "1 kHz", 12 | "2 kHz", 13 | "4 kHz", 14 | "6 kHz", 15 | "8kHz", 16 | "High Pass", 17 | }; 18 | 19 | BiquadControls::BiquadControls(const QString &title, QWidget *parent) 20 | : QGroupBox(title, parent) 21 | { 22 | QBoxLayout *slidersLayout = new QBoxLayout(QBoxLayout::LeftToRight); 23 | for (int i = 0; i < NUM_BIQUADS; i++) { 24 | m_controls[i] = new BiquadSlider(bank_title[i], i, this); 25 | slidersLayout->addWidget(m_controls[i]); 26 | } 27 | 28 | for (int i = 0; i < NUM_BIQUADS; i++) { 29 | for (int j = 0; j < NUM_BIQUADS; j++) { 30 | if (i == j) 31 | continue; 32 | connect(m_controls[i], SIGNAL(valueChanged(int)), m_controls[j], SLOT(setValue(int))); 33 | } 34 | } 35 | 36 | for (int i = 0; i < NUM_BIQUADS; i++) { 37 | connect(m_controls[i], SIGNAL(valueChanged(int, int)), parent, SLOT(setBiquadBank(int, int))); 38 | } 39 | 40 | setLayout(slidersLayout); 41 | } 42 | 43 | void BiquadControls::selectAll() 44 | { 45 | for (int i = 0; i < NUM_BIQUADS; i++) { 46 | m_controls[i]->setSelected(true); 47 | } 48 | } 49 | 50 | void BiquadControls::selectNone() 51 | { 52 | for (int i = 0; i < NUM_BIQUADS; i++) { 53 | m_controls[i]->setSelected(false); 54 | } 55 | } 56 | 57 | void BiquadControls::invertSelection() 58 | { 59 | for (int i = 0; i < NUM_BIQUADS; i++) { 60 | if (m_controls[i]->isChecked()) 61 | m_controls[i]->setSelected(false); 62 | else 63 | m_controls[i]->setSelected(true); 64 | } 65 | } 66 | 67 | void BiquadControls::selectionChanged(bool selected) 68 | { 69 | for (int i = 0; i < NUM_BIQUADS; i++) { 70 | disconnect(m_controls[i], SIGNAL(valueChanged(int)), 0, 0); 71 | } 72 | for (int i = 0; i < NUM_BIQUADS; i++) { 73 | for (int j = 0; j < NUM_BIQUADS; j++) { 74 | if (i == j || !m_controls[j]->isChecked()) 75 | continue; 76 | 77 | connect(m_controls[i], SIGNAL(valueChanged(int)), m_controls[j], SLOT(setValue(int))); 78 | } 79 | } 80 | } 81 | 82 | bool BiquadControls::allSelected() 83 | { 84 | bool allSelected = true; 85 | for (int i = 0; i < NUM_BIQUADS && allSelected; i++) { 86 | if (!m_controls[i]->isChecked()) 87 | allSelected = false; 88 | } 89 | return allSelected; 90 | } 91 | -------------------------------------------------------------------------------- /host_dsp_gui/src/biquad_controls.h: -------------------------------------------------------------------------------- 1 | #ifndef _BIQUAD_CONTROLS_H_ 2 | #define _BIQUAD_CONTROLS_H_ 3 | 4 | #include 5 | 6 | QT_BEGIN_NAMESPACE 7 | class BiquadSlider; 8 | QT_END_NAMESPACE 9 | 10 | #define NUM_BIQUADS 10 11 | 12 | class BiquadControls : public QGroupBox 13 | { 14 | Q_OBJECT 15 | 16 | public: 17 | BiquadControls(const QString &title, QWidget *parent = 0); 18 | 19 | bool allSelected(); 20 | 21 | public slots: 22 | void selectAll(); 23 | void selectNone(); 24 | void invertSelection(); 25 | void selectionChanged(bool selected); 26 | 27 | private: 28 | BiquadSlider *m_controls[NUM_BIQUADS]; 29 | }; 30 | 31 | #endif // _BIQUAD_CONTROLS_H_ 32 | -------------------------------------------------------------------------------- /host_dsp_gui/src/biquad_slider.h: -------------------------------------------------------------------------------- 1 | #ifndef _BIQUAD_SLIDER_H_ 2 | #define _BIQUAD_SLIDER_H_ 3 | 4 | #include 5 | 6 | QT_BEGIN_NAMESPACE 7 | class QSlider; 8 | class QSpinBox; 9 | class QCheckBox; 10 | QT_END_NAMESPACE 11 | 12 | class BiquadSlider : public QGroupBox 13 | { 14 | Q_OBJECT 15 | 16 | public: 17 | BiquadSlider(const QString &title, int index, QWidget *parent = 0); 18 | 19 | virtual bool isChecked(); 20 | 21 | signals: 22 | void valueChanged(int value); 23 | void valueChanged(int index, int value); 24 | 25 | public slots: 26 | void setValue(int value); 27 | void setSelected(bool selected); 28 | 29 | private: 30 | int m_index; 31 | QSlider *m_slider; 32 | QSpinBox *m_valueSpinBox; 33 | QCheckBox *m_selected; 34 | }; 35 | 36 | #endif // _BIQUAD_SLIDER_H_ 37 | -------------------------------------------------------------------------------- /host_dsp_gui/src/biquad_sliders.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "biquad_slider.h" 4 | 5 | #define SLIDER_MIN 0 6 | #define SLIDER_MAX 24 7 | #define SLIDER_INITIAL 20 8 | 9 | BiquadSlider::BiquadSlider(const QString &title, int index, QWidget *parent) 10 | : QGroupBox(title, parent) 11 | , m_index(index) 12 | { 13 | m_slider = new QSlider(Qt::Vertical); 14 | m_slider->setFocusPolicy(Qt::StrongFocus); 15 | m_slider->setTickPosition(QSlider::TicksBothSides); 16 | m_slider->setTickInterval(10); 17 | m_slider->setSingleStep(1); 18 | m_slider->setMinimum(SLIDER_MIN); 19 | m_slider->setMaximum(SLIDER_MAX); 20 | m_slider->setValue(SLIDER_INITIAL); 21 | 22 | m_valueSpinBox = new QSpinBox; 23 | m_valueSpinBox->setRange(SLIDER_MIN, SLIDER_MAX); 24 | m_valueSpinBox->setSingleStep(1); 25 | m_valueSpinBox->setValue(SLIDER_INITIAL); 26 | 27 | m_selected = new QCheckBox; 28 | m_selected->setChecked(true); 29 | 30 | connect(m_slider, SIGNAL(valueChanged(int)), m_valueSpinBox, SLOT(setValue(int))); 31 | connect(m_valueSpinBox, SIGNAL(valueChanged(int)), m_slider, SLOT(setValue(int))); 32 | connect(m_valueSpinBox, SIGNAL(valueChanged(int)), this, SLOT(setValue(int))); 33 | 34 | connect(m_slider, SIGNAL(valueChanged(int)), this, SIGNAL(valueChanged(int))); 35 | 36 | connect(m_selected, SIGNAL(toggled(bool)), parent, SLOT(selectionChanged(bool))); 37 | 38 | QBoxLayout *sliderLayout = new QBoxLayout(QBoxLayout::TopToBottom); 39 | sliderLayout->addWidget(m_slider); 40 | sliderLayout->addWidget(m_valueSpinBox); 41 | sliderLayout->addWidget(m_selected); 42 | 43 | setLayout(sliderLayout); 44 | } 45 | 46 | void BiquadSlider::setValue(int value) 47 | { 48 | m_slider->setValue(value); 49 | m_valueSpinBox->setValue(value); 50 | valueChanged(m_index, value); 51 | } 52 | 53 | bool BiquadSlider::isChecked() 54 | { 55 | return m_selected->isChecked(); 56 | } 57 | 58 | void BiquadSlider::setSelected(bool selected) 59 | { 60 | m_selected->setChecked(selected); 61 | } 62 | -------------------------------------------------------------------------------- /host_dsp_gui/src/drc_controls.h: -------------------------------------------------------------------------------- 1 | #ifndef _DRC_CONTROLS_H_ 2 | #define _DRC_CONTROLS_H_ 3 | 4 | #include 5 | 6 | QT_BEGIN_NAMESPACE 7 | class QSlider; 8 | class QSpinBox; 9 | class QDial; 10 | class QCustomPlot; 11 | QT_END_NAMESPACE 12 | 13 | #define NUM_THRESHOLDS 3 14 | 15 | typedef struct { 16 | int threshold; 17 | int gain; 18 | } DrcTableEntry; 19 | 20 | class DrcControls : public QGroupBox 21 | { 22 | Q_OBJECT 23 | 24 | public: 25 | DrcControls(const QString &title, QWidget *parent = 0); 26 | 27 | public slots: 28 | void levelThresholdUpdated(int index, int value); 29 | 30 | private: 31 | void plotGraph(); 32 | void setDrcEntry(int index, int threshold, int gain); 33 | 34 | private: 35 | QSlider *m_attackMicroSec; 36 | QSpinBox *m_attackSpinBox; 37 | 38 | QSlider *m_releaseMicroSec; 39 | QSpinBox *m_releaseSpinBox; 40 | 41 | QDial *m_threshold; 42 | QSpinBox *m_thresholdSpinBox; 43 | 44 | QCustomPlot *m_drcGraph; 45 | 46 | DrcTableEntry m_drcTable[NUM_THRESHOLDS]; 47 | }; 48 | 49 | #endif // _DRC_CONTROLS_H_ 50 | -------------------------------------------------------------------------------- /host_dsp_gui/src/drc_spinbox.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "drc_spinbox.h" 4 | 5 | DrcSpinBox::DrcSpinBox(int index, int *valuePtr) 6 | : m_index(index) 7 | , m_valuePtr(valuePtr) 8 | { 9 | connect(this, SIGNAL(valueChanged(int)), this, SLOT(valueSet(int))); 10 | } 11 | 12 | void DrcSpinBox::valueSet(int value) 13 | { 14 | *m_valuePtr = value; 15 | valueChanged(m_index, value); 16 | } 17 | -------------------------------------------------------------------------------- /host_dsp_gui/src/drc_spinbox.h: -------------------------------------------------------------------------------- 1 | #ifndef _DRC_SPINBOX_H_ 2 | #define _DRC_SPINBOX_H_ 3 | 4 | #include 5 | 6 | class DrcSpinBox : public QSpinBox 7 | { 8 | Q_OBJECT 9 | 10 | public: 11 | /* The DRC spin box takes the index into the DRC table and a 12 | * pointer to the integer value that it is controlling. 13 | */ 14 | DrcSpinBox(int index, int *valuePtr); 15 | 16 | signals: 17 | /* The signal that provides the table index */ 18 | void valueChanged(int index, int value); 19 | 20 | public slots: 21 | void valueSet(int value); 22 | 23 | private: 24 | int m_index; 25 | int *m_valuePtr; 26 | }; 27 | 28 | #endif // _DRC_SPINBOX_H_ 29 | -------------------------------------------------------------------------------- /host_dsp_gui/src/main.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the examples of the Qt Toolkit. 7 | ** 8 | ** $QT_BEGIN_LICENSE:BSD$ 9 | ** You may use this file under the terms of the BSD license as follows: 10 | ** 11 | ** "Redistribution and use in source and binary forms, with or without 12 | ** modification, are permitted provided that the following conditions are 13 | ** met: 14 | ** * Redistributions of source code must retain the above copyright 15 | ** notice, this list of conditions and the following disclaimer. 16 | ** * Redistributions in binary form must reproduce the above copyright 17 | ** notice, this list of conditions and the following disclaimer in 18 | ** the documentation and/or other materials provided with the 19 | ** distribution. 20 | ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names 21 | ** of its contributors may be used to endorse or promote products derived 22 | ** from this software without specific prior written permission. 23 | ** 24 | ** 25 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 36 | ** 37 | ** $QT_END_LICENSE$ 38 | ** 39 | ****************************************************************************/ 40 | 41 | #include 42 | 43 | #include "window.h" 44 | 45 | /* 46 | * Includes for thread support 47 | */ 48 | #ifdef _WIN32 49 | #include 50 | #else 51 | #include 52 | #endif 53 | 54 | #include "xscope_host_shared.h" 55 | 56 | extern "C" void hook_registration_received(int sockfd, int xscope_probe, char *name) 57 | { 58 | // Ignore 59 | } 60 | 61 | extern "C" void hook_data_received(int sockfd, int xscope_probe, void *data, int data_len) 62 | { 63 | // Ignore 64 | } 65 | 66 | extern "C" void hook_exiting() 67 | { 68 | // Ignore 69 | } 70 | 71 | int g_sockfd; 72 | 73 | #ifdef _WIN32 74 | DWORD WINAPI control_thread(void *arg) 75 | #else 76 | void *control_thread(void *arg) 77 | #endif 78 | { 79 | char *server_ip = "127.0.0.1"; 80 | char *port_str = "12346"; 81 | int sockfds[1] = {0}; 82 | sockfds[0] = initialise_socket(server_ip, port_str); 83 | g_sockfd = sockfds[0]; 84 | if (sockfds[0] >= 0) 85 | handle_sockets(sockfds, 1); 86 | 87 | #ifdef _WIN32 88 | return 0; 89 | #else 90 | return NULL; 91 | #endif 92 | } 93 | 94 | int main(int argc, char *argv[]) 95 | { 96 | #ifdef _WIN32 97 | HANDLE thread; 98 | thread = CreateThread(NULL, 0, control_thread, NULL, 0, NULL); 99 | if (thread == NULL) { 100 | printf("ERROR: Failed to create console thread\n"); 101 | exit(1); 102 | } 103 | #else 104 | pthread_t tid; 105 | int err = pthread_create(&tid, NULL, &control_thread, NULL); 106 | if (err != 0) { 107 | printf("ERROR: Failed to create console thread\n"); 108 | exit(1); 109 | } 110 | #endif 111 | 112 | QApplication app(argc, argv); 113 | Window window; 114 | window.show(); 115 | return app.exec(); 116 | } 117 | -------------------------------------------------------------------------------- /host_dsp_gui/src/mutex.c: -------------------------------------------------------------------------------- 1 | #include "mutex.h" 2 | #include "xscope_host_shared.h" 3 | 4 | // A mutex to ensure that the thread interactions are safe 5 | #ifdef _WIN32 6 | 7 | #include 8 | HANDLE g_mutex; 9 | 10 | void mutex_create(mutex_t *mutex) 11 | { 12 | *mutex = CreateMutex( 13 | NULL, // default security attributes 14 | FALSE, // initially not owned 15 | NULL); // unnamed mutex 16 | 17 | if (*mutex == NULL) 18 | print_and_exit("ERROR: mutex init failed\n"); 19 | } 20 | 21 | void mutex_destroy(mutex_t *mutex) 22 | { 23 | CloseHandle(*mutex); 24 | } 25 | 26 | void mutex_acquire(mutex_t *mutex) 27 | { 28 | DWORD result = WaitForSingleObject(*mutex, INFINITE); 29 | if (result != WAIT_OBJECT_0) 30 | print_and_exit("ERROR: mutex acquire failed\n"); 31 | } 32 | 33 | void mutex_release(mutex_t *mutex) 34 | { 35 | if (! ReleaseMutex(*mutex)) 36 | print_and_exit("ERROR: mutex release failed\n"); 37 | } 38 | 39 | #else 40 | 41 | #include 42 | pthread_mutex_t g_mutex; 43 | 44 | void mutex_create(mutex_t *mutex) 45 | { 46 | if (pthread_mutex_init(mutex, NULL) != 0) 47 | print_and_exit("ERROR: mutex init failed\n"); 48 | } 49 | 50 | void mutex_destroy(mutex_t *mutex) 51 | { 52 | pthread_mutex_destroy(mutex); 53 | } 54 | 55 | void mutex_acquire(mutex_t *mutex) 56 | { 57 | if (pthread_mutex_lock(mutex)) 58 | print_and_exit("ERROR: mutex acquire failed\n"); 59 | } 60 | 61 | void mutex_release(mutex_t *mutex) 62 | { 63 | if (pthread_mutex_unlock(mutex)) 64 | print_and_exit("ERROR: mutex release failed\n"); 65 | } 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /host_dsp_gui/src/mutex.h: -------------------------------------------------------------------------------- 1 | #ifndef __mutex_h__ 2 | #define __mutex_h__ 3 | 4 | #ifdef _WIN32 5 | #include 6 | typedef HANDLE mutex_t; 7 | #else 8 | #include 9 | typedef pthread_mutex_t mutex_t; 10 | #endif 11 | 12 | void mutex_create(mutex_t *mutex); 13 | void mutex_destroy(mutex_t *mutex); 14 | void mutex_acquire(mutex_t *mutex); 15 | void mutex_release(mutex_t *mutex); 16 | 17 | #endif // __mutex_h__ 18 | -------------------------------------------------------------------------------- /host_dsp_gui/src/queues.c: -------------------------------------------------------------------------------- 1 | #include "mutex.h" 2 | #include "queues.h" 3 | #include "xscope_host_shared.h" 4 | 5 | mutex_t g_mutex; 6 | 7 | socket_data_t g_socket_data[MAX_NUM_SOCKETS]; 8 | int g_socket_data_initialised = 0; 9 | 10 | void initialize_socket_data() 11 | { 12 | // Only let this function execute once 13 | if (!g_socket_data_initialised) 14 | { 15 | int i = 0; 16 | for (i = 0; i < MAX_NUM_SOCKETS; i++) { 17 | g_socket_data[i].sockfd = -1; 18 | } 19 | mutex_create(&g_mutex); 20 | g_socket_data_initialised = 1; 21 | } 22 | } 23 | 24 | void allocate_socket_data(int sockfd) 25 | { 26 | int i; 27 | 28 | initialize_socket_data(); 29 | 30 | for (i = 0; i < MAX_NUM_SOCKETS; i++) { 31 | if (g_socket_data[i].sockfd == -1) { 32 | g_socket_data[i].sockfd = sockfd; 33 | g_socket_data[i].upload_active = 0; 34 | return; 35 | } 36 | } 37 | // Not enough entries to handle this case 38 | assert(0); 39 | } 40 | 41 | socket_data_t *get_socket_data(int sockfd) 42 | { 43 | int i; 44 | for (i = 0; i < MAX_NUM_SOCKETS; i++) { 45 | if (g_socket_data[i].sockfd == sockfd) 46 | return &g_socket_data[i]; 47 | } 48 | // Failed to allocate the entry for this socket 49 | assert(0); 50 | return NULL; 51 | } 52 | 53 | upload_queue_entry_t *new_entry(unsigned int length, const unsigned char *data) 54 | { 55 | int index = 0; 56 | upload_queue_entry_t *entry = malloc(sizeof(upload_queue_entry_t)); 57 | entry->data = (unsigned char *)malloc(sizeof(char)+sizeof(int)+length); 58 | 59 | entry->data[index] = XTRACE_SOCKET_MSG_EVENT_TARGET_DATA; 60 | index += 1; 61 | *(unsigned int *)&(entry->data[index]) = length; 62 | index += 4; 63 | memcpy(&entry->data[index], data, length); 64 | index += length; 65 | entry->length = index; 66 | entry->next = NULL; 67 | return entry; 68 | } 69 | 70 | void free_entry(upload_queue_entry_t *entry) 71 | { 72 | free(entry->data); 73 | free(entry); 74 | } 75 | 76 | static void manage_queue(socket_data_t *socket_data) 77 | { 78 | int n = 0; 79 | upload_queue_entry_t *entry = socket_data->queue.head; 80 | 81 | // Can't start sending more data until outstanding data complete 82 | if (socket_data->upload_active) 83 | return; 84 | 85 | // No more data to send 86 | if (entry == NULL) 87 | return; 88 | 89 | // Send the head 90 | n = send(socket_data->sockfd, entry->data, entry->length, 0); 91 | if (n != entry->length) 92 | print_and_exit("ERROR: send failed on socket %d\n", socket_data->sockfd); 93 | 94 | socket_data->upload_active = 1; 95 | } 96 | 97 | int queue_empty(int sockfd) 98 | { 99 | socket_data_t *socket_data = get_socket_data(sockfd); 100 | 101 | if (socket_data->queue.head == NULL) 102 | return 1; 103 | else 104 | return 0; 105 | } 106 | 107 | void queue_add(int sockfd, upload_queue_entry_t *entry) 108 | { 109 | socket_data_t *socket_data = get_socket_data(sockfd); 110 | 111 | mutex_acquire(&g_mutex); 112 | if (socket_data->queue.head == NULL) { 113 | socket_data->queue.head = entry; 114 | socket_data->queue.tail = entry; 115 | } else { 116 | socket_data->queue.tail->next = entry; 117 | socket_data->queue.tail = entry; 118 | } 119 | 120 | manage_queue(socket_data); 121 | mutex_release(&g_mutex); 122 | } 123 | 124 | void queue_complete_head(int sockfd) 125 | { 126 | socket_data_t *socket_data = get_socket_data(sockfd); 127 | upload_queue_entry_t *entry = socket_data->queue.head; 128 | assert(entry != NULL); 129 | 130 | mutex_acquire(&g_mutex); 131 | socket_data->queue.head = entry->next; 132 | if (socket_data->queue.tail == entry) 133 | socket_data->queue.tail = NULL; 134 | 135 | free_entry(entry); 136 | socket_data->upload_active = 0; 137 | 138 | manage_queue(socket_data); 139 | mutex_release(&g_mutex); 140 | } 141 | 142 | -------------------------------------------------------------------------------- /host_dsp_gui/src/queues.h: -------------------------------------------------------------------------------- 1 | #ifndef __queues_h__ 2 | #define __queues_h__ 3 | 4 | #define MAX_NUM_SOCKETS 10 5 | 6 | #if defined(__XC__) || defined(__cplusplus) 7 | extern "C" { 8 | #endif 9 | 10 | typedef struct upload_queue_entry_t { 11 | unsigned int length; 12 | unsigned char *data; 13 | struct upload_queue_entry_t *next; 14 | } upload_queue_entry_t; 15 | 16 | typedef struct upload_queue_t { 17 | upload_queue_entry_t *head; 18 | upload_queue_entry_t *tail; 19 | } upload_queue_t; 20 | 21 | typedef struct socket_data_t { 22 | int sockfd; 23 | int upload_active; 24 | upload_queue_t queue; 25 | } socket_data_t; 26 | 27 | void allocate_socket_data(int sockfd); 28 | upload_queue_entry_t *new_entry(unsigned length, const unsigned char *data); 29 | int queue_empty(int sockfd); 30 | void queue_add(int sockfd, upload_queue_entry_t *entry); 31 | void queue_complete_head(int sockfd); 32 | 33 | #if defined(__XC__) || defined(__cplusplus) 34 | } 35 | #endif 36 | 37 | #endif // __queues_h__ 38 | -------------------------------------------------------------------------------- /host_dsp_gui/src/sliders.pro: -------------------------------------------------------------------------------- 1 | QT += widgets printsupport 2 | 3 | HEADERS = \ 4 | window.h \ 5 | mutex.h \ 6 | queues.h \ 7 | xscope_host_shared.h \ 8 | biquad_slider.h \ 9 | biquad_controls.h \ 10 | drc_controls.h \ 11 | qcustomplot.h \ 12 | drc_spinbox.h 13 | SOURCES = main.cpp \ 14 | window.cpp \ 15 | mutex.c \ 16 | queues.c \ 17 | xscope_host_shared.c \ 18 | biquad_controls.cpp \ 19 | biquad_sliders.cpp \ 20 | drc_controls.cpp \ 21 | qcustomplot.cpp \ 22 | drc_spinbox.cpp 23 | 24 | # install 25 | target.path = $$[QT_INSTALL_EXAMPLES]/widgets/widgets/sliders 26 | INSTALLS += target 27 | -------------------------------------------------------------------------------- /host_dsp_gui/src/window.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the examples of the Qt Toolkit. 7 | ** 8 | ** $QT_BEGIN_LICENSE:BSD$ 9 | ** You may use this file under the terms of the BSD license as follows: 10 | ** 11 | ** "Redistribution and use in source and binary forms, with or without 12 | ** modification, are permitted provided that the following conditions are 13 | ** met: 14 | ** * Redistributions of source code must retain the above copyright 15 | ** notice, this list of conditions and the following disclaimer. 16 | ** * Redistributions in binary form must reproduce the above copyright 17 | ** notice, this list of conditions and the following disclaimer in 18 | ** the documentation and/or other materials provided with the 19 | ** distribution. 20 | ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names 21 | ** of its contributors may be used to endorse or promote products derived 22 | ** from this software without specific prior written permission. 23 | ** 24 | ** 25 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 36 | ** 37 | ** $QT_END_LICENSE$ 38 | ** 39 | ****************************************************************************/ 40 | 41 | #ifndef WINDOW_H 42 | #define WINDOW_H 43 | 44 | #include 45 | 46 | QT_BEGIN_NAMESPACE 47 | class QCheckBox; 48 | class QGroupBox; 49 | class QLabel; 50 | class QDial; 51 | class QStackedWidget; 52 | class QPushButton; 53 | class BiquadControls; 54 | class QSpinBox; 55 | QT_END_NAMESPACE 56 | 57 | #define MAX_COMMAND_LEN 100 58 | 59 | extern int g_sockfd; 60 | 61 | class Window : public QWidget 62 | { 63 | Q_OBJECT 64 | 65 | public: 66 | Window(); 67 | 68 | public slots: 69 | void enableBiquads(bool enable); 70 | void enableDrc(bool enable); 71 | 72 | void setPreGain(int value); 73 | void setGain(int value); 74 | 75 | void setBiquadBank(int index, int value); 76 | void setLevelAttack(int value); 77 | void setLevelRelease(int value); 78 | void setLevelThreshold(int value); 79 | 80 | private: 81 | void createBiquadControls(); 82 | void createDrcControls(); 83 | void createControls(); 84 | 85 | QStackedWidget *m_stackedWidget; 86 | 87 | // BIQUADS 88 | QGroupBox *m_biquadControlBox; 89 | BiquadControls *m_biquadSliders; 90 | QCheckBox *m_biquadEnable; 91 | QPushButton *m_selectAll; 92 | QPushButton *m_selectNone; 93 | QPushButton *m_selectInvert; 94 | 95 | // DRC 96 | QGroupBox *m_drcControlBox; 97 | QCheckBox *m_drcEnable; 98 | 99 | // GAIN 100 | QGroupBox *m_preGainBox; 101 | QDial *m_preGainDial; 102 | QSpinBox *m_preGainSpinBox; 103 | 104 | QGroupBox *m_gainBox; 105 | QDial *m_gainDial; 106 | QSpinBox *m_gainSpinBox; 107 | }; 108 | 109 | #endif 110 | -------------------------------------------------------------------------------- /host_dsp_gui/src/xscope_host_shared.h: -------------------------------------------------------------------------------- 1 | #ifndef __SHARED_H__ 2 | #define __SHARED_H__ 3 | 4 | /* 5 | * The required includes for any host application. 6 | */ 7 | #ifdef _WIN32 8 | #include 9 | #include 10 | #pragma comment(lib, "Ws2_32.lib") 11 | 12 | // Provided by the inet_pton.c implementation locally 13 | int inet_pton(int af, const char *src, void *dst); 14 | 15 | // Locally provided getopt.h 16 | #include "getopt.h" 17 | 18 | typedef unsigned __int8 uint8_t; 19 | typedef unsigned __int16 uint16_t; 20 | typedef unsigned __int32 uint32_t; 21 | typedef unsigned __int64 uint64_t; 22 | 23 | typedef __int8 int8_t; 24 | typedef __int16 int16_t; 25 | typedef __int32 int32_t; 26 | typedef __int64 int64_t; 27 | 28 | #else 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #endif 38 | 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | 47 | #define XSCOPE_EP_SUCCESS 0 48 | #define XSCOPE_EP_FAILURE 1 49 | 50 | // Different event types to register and handle 51 | #define XTRACE_SOCKET_MSG_EVENT_REGISTER 0x1 52 | #define XTRACE_SOCKET_MSG_EVENT_RECORD 0x2 53 | #define XTRACE_SOCKET_MSG_EVENT_TARGET_DATA 0x4 54 | #define XTRACE_SOCKET_MSG_EVENT_PRINT 0x8 55 | 56 | // Need one byte for type, then 8 bytes of time stamp and 4 bytes of length 57 | #define PRINT_EVENT_BYTES 13 58 | 59 | // Data events have 16 bytes of overhead (type[1], id[1], flag[2], length[4], timestamp[8]) 60 | #define DATA_EVENT_BYTES 16 61 | // And 8 bytes before the length can be read 62 | #define DATA_EVENT_HEADER_BYTES 8 63 | 64 | // The target completion message is (type[1], data[4]) 65 | #define TARGET_DATA_EVENT_BYTES 5 66 | 67 | // Registration events have the form: (type[1], id[4], type[4], r[4], g[4], b[4], 68 | // strlen(name)[4], name[N], 69 | // strlen("ps")[4], "ps"[3], 70 | // user_type, 71 | // strlen(user_name)[4], user_name[N]) 72 | #define REGISTER_EVENT_HEADER_BYTES 25 73 | 74 | #define MAX_RECV_BYTES 16384 75 | 76 | #define CAPTURE_LENGTH 64 77 | 78 | #define EXTRACT_UINT(buf, pos) (buf[pos] | (buf[pos+1] << 8) | (buf[pos+2] << 16) | (buf[pos+3] << 24)) 79 | 80 | #define DEFAULT_SERVER_IP "127.0.0.1" 81 | #define DEFAULT_PORT "12346" 82 | 83 | #if defined(__XC__) || defined(__cplusplus) 84 | extern "C" { 85 | #endif 86 | 87 | int initialise_socket(char *ip_addr_str, char *port_str); 88 | void interrupt_handler(int sig); 89 | void print_and_exit(const char* format, ...); 90 | 91 | /* 92 | * Function that sends data to the device over the socket. Puts the data into 93 | * a message of the correct format and sends it to the socket. It expects 94 | * there to be only one outstanding message at a time. This is not an xscope 95 | * limitation, just one for simplicity. 96 | */ 97 | int xscope_ep_request_upload(int sockfd, unsigned int length, const unsigned char *data); 98 | 99 | void handle_sockets(int *sockfd, int no_of_sockfd); 100 | 101 | #if defined(__XC__) || defined(__cplusplus) 102 | } 103 | #endif 104 | 105 | #endif // __SHARED_H__ 106 | -------------------------------------------------------------------------------- /module_startkit_adc/.makefile: -------------------------------------------------------------------------------- 1 | all: 2 | @echo "** Module only - only builds as part of application **" 3 | 4 | 5 | clean: 6 | @echo "** Module only - only builds as part of application **" 7 | 8 | 9 | -------------------------------------------------------------------------------- /module_startkit_adc/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | module_startkit_adc 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.cdt.managedbuilder.core.genmakebuilder 10 | clean,full,incremental, 11 | 12 | 13 | ?children? 14 | ?name?=outputEntries\|?children?=?name?=entry\\\\|\\|\|| 15 | 16 | 17 | ?name? 18 | 19 | 20 | 21 | org.eclipse.cdt.make.core.append_environment 22 | true 23 | 24 | 25 | org.eclipse.cdt.make.core.buildArguments 26 | CONFIG=Debug 27 | 28 | 29 | org.eclipse.cdt.make.core.buildCommand 30 | xmake 31 | 32 | 33 | org.eclipse.cdt.make.core.cleanBuildTarget 34 | clean 35 | 36 | 37 | org.eclipse.cdt.make.core.contents 38 | org.eclipse.cdt.make.core.activeConfigSettings 39 | 40 | 41 | org.eclipse.cdt.make.core.enableAutoBuild 42 | false 43 | 44 | 45 | org.eclipse.cdt.make.core.enableCleanBuild 46 | true 47 | 48 | 49 | org.eclipse.cdt.make.core.enableFullBuild 50 | true 51 | 52 | 53 | org.eclipse.cdt.make.core.stopOnError 54 | true 55 | 56 | 57 | org.eclipse.cdt.make.core.useDefaultBuildCmd 58 | false 59 | 60 | 61 | 62 | 63 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder 64 | full,incremental, 65 | 66 | 67 | 68 | 69 | 70 | org.eclipse.cdt.core.cnature 71 | org.eclipse.cdt.managedbuilder.core.managedBuildNature 72 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature 73 | com.xmos.cdt.core.XdeProjectNature 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /module_startkit_adc/.xproject: -------------------------------------------------------------------------------- 1 | sw_startkit_examplesXM-004098-SM -------------------------------------------------------------------------------- /module_startkit_adc/README.rst: -------------------------------------------------------------------------------- 1 | ADC Driver for startKIT 2 | ======================== 3 | 4 | :scope: Example 5 | :description: A module for accessing the 4ch ADC on startKIT 6 | :keywords: startKIT, ADC, analog, analogue 7 | 8 | 9 | Presents the U8A/startKIT 12b ADC in an MCU-like manner by abstracting away 10 | channels, link setup (for startKIT FLASH boot) and trigger requirements. 11 | 12 | 13 | Enables all 4 channels and provides simple API for trigger, read and conversion complete event. Practical fastest sample rate (to aquire all 4 channels) with all cores running flat-out is about 50us (to trigger, aquire, notify and read). So about 20KHz. Assumes core sharing with startkit_GPIO task (slow). 14 | Ie. This module is built for comfort rather than speed. Give it it's own core and only run 4 cores total,and this number jumps to about 6us, or about 165KHz. Much closer to max theoretical b/w of 1MHz/4 = 250KHz 15 | 16 | Runs in two modes (self triggering periodically or trigger on request). Trigger function still callable in periodic mode and conversion finished notification available in period mode if needed. Task is combinable so you can run it with other low speed tasks in the same logical core! (eg. GPIO) 17 | -------------------------------------------------------------------------------- /module_startkit_adc/module_build_info: -------------------------------------------------------------------------------- 1 | MODULE_XCC_FLAGS = $(XCC_FLAGS) -O3 -------------------------------------------------------------------------------- /module_startkit_adc/src/startkit_adc.h: -------------------------------------------------------------------------------- 1 | //adc.h for startKIT written by infiniteimprobability (xcore.com) June 2014 2 | // 3 | //Contains ADC task and ADC interface definition 4 | // 5 | //Aims to present the U8A/startKIT 12b ADC in an MCU-like manner by abstracting away 6 | //channels, link setup (for startKIT FLASH boot) and trigger requirements. 7 | 8 | // 9 | //Enables all 4 channels and provides simple API for trigger, read and conversion complete event 10 | //Practical fastest sample rate (to aquire all 4 channels) with all cores running flat-out 11 | //is about 50us (to trigger, aquire, notify and read). So about 20KHz. Assumes core sharing with GPIO (slower) 12 | //Ie. This module is built for comfort rather than speed. Give it it's own core and only run 4 cores total, 13 | //and this number jumps to about 6us, or about 165KHz. Much closer to max theoritcal b/w of 1MHz/4 = 250KHz 14 | // 15 | //Runs in two modes (self tiggering periodically or trigger on request). Trigger function still callable 16 | //in periodic mode and conversion finished notfication available in period mode if needed. Task is combinable 17 | //so you can run it with other low speed tasks in the same logical core! (eg. GPIO) 18 | // 19 | //License = do what you like with it! But please post your projects on xcore.com for others to enjoy! 20 | 21 | #ifndef ADC_H_ 22 | #define ADC_H_ 23 | #include 24 | 25 | #define ADC_TRIG_DELAY 40 //400ns minimum high/low time for ADC trigger signal 26 | #define ADC_TRIG_PORT XS1_PORT_1A //ADC trigger pin. Defined by startKIT hardware 27 | 28 | 29 | //ADC Methods 30 | typedef interface adc { 31 | //Initiates a trigger sequence. If trigger already in progress, this call is ignored 32 | [[guarded]] void trigger(void); 33 | //Reads the 4 ADC values and places them in array of unsigned shorts passed. 34 | //Value is 0 to 65520 unsigned. Actual ADC is 12b so bottom 4 bits always zero. Ie. left justified 35 | //Optionally returns the ADC state - 1 if ADC trigger/aquisition complete, or 0 if in progress 36 | [[clears_notification]] int read(unsigned short adc_val[4]); 37 | //Call to client to indicate aquisition complete. Behaves a bit like ADC finish interrupt. Optional. 38 | [[notification]] slave void complete(void); 39 | } startkit_adc_if; 40 | 41 | [[combinable]] 42 | //Runs ADC task. Very low MIPS consumption so is good candidate for combining with other low speed tasks 43 | //Pass i_adc control inteface and automatic trigger period in microseconds. 44 | //If trigger period is set to zero, ADC will only convert on trigger() call. 45 | void adc_task(server startkit_adc_if i_adc, chanend c_adc, int trigger_period); 46 | 47 | #endif /* ADC_H_ */ 48 | -------------------------------------------------------------------------------- /module_startkit_gpio/.makefile: -------------------------------------------------------------------------------- 1 | all: 2 | @echo "** Module only - only builds as part of application **" 3 | 4 | 5 | clean: 6 | @echo "** Module only - only builds as part of application **" 7 | 8 | 9 | -------------------------------------------------------------------------------- /module_startkit_gpio/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | module_startkit_gpio 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.cdt.managedbuilder.core.genmakebuilder 10 | clean,full,incremental, 11 | 12 | 13 | ?children? 14 | ?name?=outputEntries\|?children?=?name?=entry\\\\|\\|\|| 15 | 16 | 17 | ?name? 18 | 19 | 20 | 21 | org.eclipse.cdt.make.core.append_environment 22 | true 23 | 24 | 25 | org.eclipse.cdt.make.core.buildArguments 26 | CONFIG=Debug 27 | 28 | 29 | org.eclipse.cdt.make.core.buildCommand 30 | xmake 31 | 32 | 33 | org.eclipse.cdt.make.core.cleanBuildTarget 34 | clean 35 | 36 | 37 | org.eclipse.cdt.make.core.contents 38 | org.eclipse.cdt.make.core.activeConfigSettings 39 | 40 | 41 | org.eclipse.cdt.make.core.enableAutoBuild 42 | false 43 | 44 | 45 | org.eclipse.cdt.make.core.enableCleanBuild 46 | true 47 | 48 | 49 | org.eclipse.cdt.make.core.enableFullBuild 50 | true 51 | 52 | 53 | org.eclipse.cdt.make.core.stopOnError 54 | true 55 | 56 | 57 | org.eclipse.cdt.make.core.useDefaultBuildCmd 58 | false 59 | 60 | 61 | 62 | 63 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder 64 | full,incremental, 65 | 66 | 67 | 68 | 69 | 70 | org.eclipse.cdt.core.cnature 71 | org.eclipse.cdt.managedbuilder.core.managedBuildNature 72 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature 73 | com.xmos.cdt.core.XdeProjectNature 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /module_startkit_gpio/.xproject: -------------------------------------------------------------------------------- 1 | sw_startkit_examplesXM-004098-SM -------------------------------------------------------------------------------- /module_startkit_gpio/README.rst: -------------------------------------------------------------------------------- 1 | GPIO Driver for startKIT 2 | ======================== 3 | 4 | :scope: Example 5 | :description: A module for driving the LEDS, button and capsense on 6 | startKIT boards 7 | :keywords: startKIT, leds, capacitive, buttons 8 | 9 | 10 | This module provides a driver for the startKIT gpio functionality. It 11 | allows users to react to swiper events and button presses and also 12 | drive PWM output to different levels of brightness on the leds. 13 | 14 | Due to the board design of the startKIT, the LEDs and button share a 15 | single 32-bit port. Additionally, the capactive sensor wires a routed 16 | very close to the LEDs. This means that the buttons and sensors can 17 | only be sampled when the LEDs are not driving. This module handles 18 | this synchronization is a separate task. 19 | -------------------------------------------------------------------------------- /module_startkit_gpio/module_build_info: -------------------------------------------------------------------------------- 1 | MODULE_XCC_FLAGS = $(XCC_FLAGS) -O3 2 | 3 | DEPENDENT_MODULES = module_capacitive_sensing 4 | -------------------------------------------------------------------------------- /module_startkit_gpio/src/startkit_gpio.h: -------------------------------------------------------------------------------- 1 | #ifndef _startkit_gpio_h_ 2 | #define _startkit_gpio_h_ 3 | #include "slider.h" 4 | 5 | /** Enum for controlling led levels. 6 | * 7 | * Leds can be set in the range LED_OFF .. LED_ON. The exact resolution 8 | * depends on the driver. 9 | */ 10 | enum led_val { 11 | LED_OFF = 0x0, 12 | LED_ON = 0xFFFF 13 | }; 14 | 15 | /** Interface for controlling leds on the startkit. 16 | */ 17 | typedef interface startkit_led_if { 18 | /** Set an led output level. 19 | * 20 | * Use this function to set a single led in the range LED_OFF .. LED_ON 21 | */ 22 | void set(unsigned row, unsigned col, unsigned val); 23 | 24 | /** Set multiple led values. 25 | * 26 | * Use this function to set the level of several leds at once. 27 | * The first argument is a bitmask where the least signifcant nine 28 | * bits map to the led array in the following way: 29 | * 30 | * 8 7 6 31 | * 5 4 3 32 | * 2 1 0 33 | * 34 | * If the bit is set in the mask then the led is set to the second argument. 35 | * If the bit is not set then the led is set to LED_OFF. 36 | */ 37 | void set_multiple(unsigned mask, unsigned val); 38 | 39 | } startkit_led_if; 40 | 41 | /** Enum for representing button state */ 42 | typedef enum button_val { 43 | BUTTON_UP, 44 | BUTTON_DOWN 45 | } button_val_t; 46 | 47 | /** Interface for interacting with buttons */ 48 | typedef interface startkit_button_if { 49 | /** This notification occurs when the button changes state (i.e. goes 50 | * up->down or down->up). 51 | * 52 | * You can select on this in your program e.g. :: 53 | * 54 | * void f(client startkit_button_if i_button) { 55 | * ... 56 | * select { 57 | * case i_button.change(): 58 | * button_val_t val = get_value(); 59 | * .... 60 | * 61 | */ 62 | [[notification]] slave void changed(); 63 | 64 | /** Get the current value of the button. 65 | * 66 | * This returns either BUTTON_UP or BUTTON_DOWN. 67 | */ 68 | [[clears_notification]] button_val_t get_value(); 69 | 70 | } startkit_button_if; 71 | 72 | 73 | /* Simple LED driver 74 | * 75 | * This task will drive leds according to commands received via the 76 | * interface startkit_led_if. It has no resolution or pwm, so leds will either 77 | * be turned on or off depending on whether the level is greater or less 78 | * than LED_ON/2. 79 | * 80 | * The drive is distributable, so will not take up any compute on a logical core 81 | * of its own unless it is connected to clients on a different tile. 82 | */ 83 | [[distributable]] 84 | void startkit_led_driver(server startkit_led_if c_led[n], unsigned n, port p32); 85 | 86 | /** Ports/clocks for startkit GPIO, the ports 87 | * should be XS1_PORT_32A, XS1_PORT_4A, XS1_PORT_4B. 88 | * 89 | */ 90 | typedef struct startkit_gpio_ports 91 | { 92 | port p32; // 32-bit port for leds/button 93 | port capx; // 4-bit capsense port - x slider 94 | port capy; // 4-bit capsense port - y slider 95 | clock clk; // clock for capsense (if capsense required) 96 | } startkit_gpio_ports; 97 | 98 | 99 | /** startKIT gpio driver. 100 | * 101 | * This task drives pwm output on the leds to varying brightness and 102 | * also reads the button on the board. 103 | * 104 | * It requires the startKIT's 32 bit port (XS1_PORT_32A) to be passed 105 | * as the last argument. 106 | * 107 | * Clients can connect via the first two arguments. Several clients can 108 | * connect to set led levels. 109 | * 110 | * The function is combinable so can share a logical core with other combinable 111 | * tasks. If combined is will use cooperative multitasking to periodically 112 | * drive the pwm and sample the button value. 113 | */ 114 | [[combinable]] 115 | void startkit_gpio_driver(server startkit_led_if ?i_led, 116 | server startkit_button_if ?i_button, 117 | server slider_if ?i_slider_x, 118 | server slider_if ?i_slider_y, 119 | startkit_gpio_ports &ps); 120 | 121 | 122 | 123 | #endif // _startkit_gpio_h_ 124 | -------------------------------------------------------------------------------- /module_startkit_servo/README.rst: -------------------------------------------------------------------------------- 1 | Servo Driver for startKIT 2 | ========================- 3 | 4 | :scope: Example 5 | :description: A module for generating servo control signals startKIT 6 | :keywords: startKIT, servo, PWM, PPM 7 | 8 | Provides a simple example of generating multiple timed pulses from a single wide (4,8,16 or 32b) port, using a single logical. Currently set at 20ms period, 700-2300us high time, it provides an ideal way of driving multiple servos. It makes use of a tools version 13 feature of soft timers, meaning the code declares one timer per servo channel (for each pin) and one for the end of frame. Ie. N+1. It means that only one timer is consumed, regardless of channels. It also uses an interface to set set the duty. 9 | 10 | 11 | There is a price to pay for having multiple events handled by a single core - if multiple events arrive at the same time (eg. duties all set to the same value) then some transitions will be delayed. This has been calculated to be about 0.5% error (from min to max position) worst case when 8 channels are used on a single port, ot 0.15% error on a 4 channel system on a single 4b port. 12 | 13 | This has been tested on startKIT with the lines wired directly from the 3v3 I/O. It seemed to work fine, even though the servo was powered from 5V. 14 | 15 | There is more info in the code (including API) in servo.h and servo.xc. Also, see app_servo for a usage example. 16 | 17 | Happy servoing! 18 | 19 | -------------------------------------------------------------------------------- /module_startkit_servo/module_build_info: -------------------------------------------------------------------------------- 1 | MODULE_XCC_FLAGS = $(XCC_FLAGS) -O3 -------------------------------------------------------------------------------- /module_startkit_servo/src/.servo.xc.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xcore/sw_startkit_examples/39c9120904b3375fd8a9fbf2c7ba21e5666aa1d2/module_startkit_servo/src/.servo.xc.swp -------------------------------------------------------------------------------- /module_startkit_servo/src/servo.h: -------------------------------------------------------------------------------- 1 | #ifndef SERVO_H_ 2 | #define SERVO_H_ 3 | #include 4 | 5 | //Timing constants 6 | #define MICROSECOND (XS1_TIMER_HZ / 1000000) 7 | #define SERVO_MIN_POS (700 * MICROSECOND) 8 | #define SERVO_MAX_POS (2300 * MICROSECOND) 9 | #define SERVO_CENTRE_POS ((SERVO_MIN_POS + SERVO_MAX_POS) / 2) 10 | #define SERVO_PERIOD (20000 * MICROSECOND) 11 | 12 | //Interface for setting duties. 13 | //Param 1 - Channel number 0 -> (port_width - 1) 14 | //Param 2 - duration/position in 10ns timer ticks. Will be clipped to MIN/MAX range 15 | //Returns - void 16 | interface servo_if{ 17 | void set_pos(unsigned channel, int position); 18 | }; 19 | 20 | //Task for controlling outputs. While (1) task that is controlled over interface 21 | //Param 1 - Interface for calling set duty method 22 | //Param 2 - The port used for servo control 23 | //Param 3 - The width of the port used (1 - 32) 24 | //Param 4 - Initial position (pulse width) for all channels 25 | //Returns - void. While (1) so never returns 26 | void servo_task(server interface servo_if i_servo, out port p_servo, 27 | static const unsigned port_width, static const unsigned initial_position); 28 | 29 | #endif /* SERVO_H_ */ 30 | -------------------------------------------------------------------------------- /module_startkit_servo/src/servo.xc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void servo_task(server interface servo_if i_servo, out port p_servo, 7 | static const unsigned port_width, static const unsigned initial_position){ 8 | 9 | unsigned transition_table[port_width]; //length of each servo channel in 10ns ticks 10 | unsigned transition_trigger[port_width]; //Variable used to trigger each channel's timer 11 | timer t_transition[port_width]; //Timers used for setting the falling edge transition 12 | 13 | unsigned cycle_end_trigger; //Variable for triggering end of PWM frame 14 | timer t_cycle_end; //Timer used for triggering end of PWM frame 15 | unsigned port_shadow = ~0; //Port shadow, initialised to all high for beginning of cycle 16 | 17 | t_cycle_end :> cycle_end_trigger; //Grab time for start of frame 18 | cycle_end_trigger += SERVO_PERIOD; //Set trigger for end of frame 19 | 20 | p_servo <: port_shadow; //Set the initial value 21 | 22 | for(int i=0; i transition_trigger[i]; 25 | transition_trigger[i] += transition_table[i]; 26 | } 27 | 28 | 29 | while(1){ 30 | select{ 31 | //Cases for individual transitions. This expands out to individual cases - one for each channel 32 | //Note that edges that are close together may be delayed by ~750ns per channel for a 4b port, or 1100ns per channel for 8b port. 33 | //This is because each timer case has to be executed sequentially, so there may be queue 34 | //this translates to worst case error of about 0.14% error for 4 outputs on 4b port and 35 | //about 0.48% error for 8b port with 8 outputs 36 | case (int i=0; i void: 37 | port_shadow &= ~(0x1 << i); //Clear the relevant bit (set to 0) 38 | p_servo <: port_shadow; //Put it on the port 39 | transition_trigger[i] += SERVO_PERIOD;//Set up tigger far out into next cycle 40 | break; 41 | 42 | //Case that handles end of frame. Resets all channels 43 | case t_cycle_end when timerafter(cycle_end_trigger) :> void: 44 | port_shadow = ~0; //Set all outputs to 1 45 | p_servo <: port_shadow; 46 | 47 | for(int i=0; i transition_trigger[i]; 49 | transition_trigger[i] += transition_table[i]; 50 | } 51 | cycle_end_trigger += SERVO_PERIOD; //Set up next cycle end event 52 | break; 53 | 54 | //Upate case. Note that this buffers and so will noy apply until end of frame/next frame 55 | case i_servo.set_pos(unsigned channel, int position): 56 | if (position > (int)SERVO_MAX_POS) {//Clip to max 57 | position = SERVO_MAX_POS; 58 | } 59 | if (position < (int)SERVO_MIN_POS) {//Clip to min 60 | position = SERVO_MIN_POS; 61 | } 62 | transition_table[channel] = position;//Update new transition buffer 63 | break; 64 | 65 | } 66 | } 67 | } 68 | --------------------------------------------------------------------------------