├── .gitignore
├── firmware
├── libxud.a
├── xscope.xmt
├── dsp.h
├── pll.h
├── audioports.h
├── i2c.h
├── get_adc_counts.c
├── clocking.xc
├── codec.h
├── audiostream.h
├── audiostream.xc
├── decouple.h
├── audio.h
├── xc_ptr.h
├── dbcalc.h
├── endpoint0.h
├── clockcmds.h
├── mixer.h
├── Makefile
├── SpdifReceive.h
├── clocking.h
├── usb_buffer.h
├── pll.xc
├── DescriptorRequests.h
├── XUD_UIFM_Ports.xc
├── fastmix.S
├── biquad.S
├── dsp_router.xc
├── dsp.xc
├── customdefines.h
├── codec.xc
├── audioports.xc
├── audio.xn
├── dbcalc.xc
├── mixer.xc
├── XUD_EpFunctions.xc
├── usb.h
├── interrupt.h
├── usbaudio20.h
├── DescriptorRequests.xc
├── devicedefines.h
├── i2c.xc
├── main.xc
├── repeat.h
├── usb_buffer.xc
├── XUD_EpFuncs.S
├── mkdescriptors.py
└── endpoint0.xc
├── EULA
├── README
└── client
└── setdsp.py
/.gitignore:
--------------------------------------------------------------------------------
1 | *.o
2 | *.bin
3 | tt
4 | auto_descriptors.h
5 | map.txt
6 |
--------------------------------------------------------------------------------
/firmware/libxud.a:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcan/xmos-speaker-dsp/HEAD/firmware/libxud.a
--------------------------------------------------------------------------------
/firmware/xscope.xmt:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/firmware/dsp.h:
--------------------------------------------------------------------------------
1 | #ifndef DSP_H
2 | #define DSP_H
3 |
4 | #define FRACTIONALBITS 28
5 | #define HEADROOMBITS 4
6 | #define LFE_HEADROOMBITS 0
7 |
8 | #ifdef __XC__
9 |
10 | #define DSP_CH 6
11 | #define DSP_EXT_CH 5
12 | #define DSP_FILTERS 15
13 |
14 | #define DELAY_BITS 10
15 | #define DELAY_BUF ((1< mClkFreq */
33 | PllMult(mClkFreq/300);
34 | }
35 |
--------------------------------------------------------------------------------
/firmware/codec.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Module: module_usb_aud_shared
3 | * Version: 2v0
4 | * Build: a5a29cb961dbeda79384d1319b2a9dc4f8f6efca
5 | * File: codec.h
6 | *
7 | * The copyrights, all other intellectual and industrial
8 | * property rights are retained by XMOS and/or its licensors.
9 | * Terms and conditions covering the use of this code can
10 | * be found in the Xmos End User License Agreement.
11 | *
12 | * Copyright XMOS Ltd 2010
13 | *
14 | * In the case where this code is a modification of existing code
15 | * under a separate license, the separate license terms are shown
16 | * below. The modifications to the code are still covered by the
17 | * copyright notice above.
18 | *
19 | **/
20 | #ifndef _CODEC_H_
21 | #define _CODEC_H_
22 |
23 | /* These functions must be implemented for the CODEC/ADC/DAC arrangement of a specific design */
24 |
25 | /* TODO Are the channel args required? */
26 |
27 | /* Any required CODEC initialisation - run once at start up */
28 | void CodecInit(chanend ?c_codec);
29 |
30 | /* Configure condec for a specific mClk/Sample frquency - run on every sample frequency change */
31 | void CodecConfig(unsigned samFreq, unsigned mClk, chanend ?c_codec);
32 |
33 | #endif
34 |
--------------------------------------------------------------------------------
/firmware/audiostream.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Module: module_usb_aud_shared
3 | * Version: 2v1
4 | * Build: c94813789b307c33f0bdf39ef72362df7ec27ce3
5 | * File: audiostream.h
6 | *
7 | * The copyrights, all other intellectual and industrial
8 | * property rights are retained by XMOS and/or its licensors.
9 | * Terms and conditions covering the use of this code can
10 | * be found in the Xmos End User License Agreement.
11 | *
12 | * Copyright XMOS Ltd 2010
13 | *
14 | * In the case where this code is a modification of existing code
15 | * under a separate license, the separate license terms are shown
16 | * below. The modifications to the code are still covered by the
17 | * copyright notice above.
18 | *
19 | **/
20 | #ifndef _AUDIOSTREAM_H_
21 | #define _AUDIOSTREAM_H_
22 |
23 | /* Functions that handle functions that must occur on stream start/stop e.g. DAC mute/un-mute
24 | *
25 | * THESE NEED IMPLEMENTING FOR A SPECIFIC DESIGN
26 | *
27 | * */
28 |
29 | /* Any actions required for stream start e.g. DAC un-mute - run every stream start */
30 | void AudioStreamStart(void);
31 |
32 | /* Any actions required on stream stop e.g. DAC mute - run every steam stop */
33 | void AudioStreamStop(void);
34 |
35 | #endif
36 |
37 |
--------------------------------------------------------------------------------
/firmware/audiostream.xc:
--------------------------------------------------------------------------------
1 | /**
2 | * Module: app_usb_aud_l2
3 | * Version: 5v00
4 | * Build: bdb0bad2e22d60206c570bfea8758095c46d1519
5 | * File: audiostream.xc
6 | *
7 | * The copyrights, all other intellectual and industrial
8 | * property rights are retained by XMOS and/or its licensors.
9 | * Terms and conditions covering the use of this code can
10 | * be found in the Xmos End User License Agreement.
11 | *
12 | * Copyright XMOS Ltd 2010
13 | *
14 | * In the case where this code is a modification of existing code
15 | * under a separate license, the separate license terms are shown
16 | * below. The modifications to the code are still covered by the
17 | * copyright notice above.
18 | *
19 | **/
20 | #ifndef _AUDIOSTREAM_H_
21 | #define _AUDIOSTREAM_H_
22 |
23 | /* Functions that handle functions that must occur on stream start/stop e.g. DAC mute/un-mute
24 | * These need implementing for a specific design.
25 | *
26 | * Implementations for the L2 USB Audio Reference Design
27 | */
28 |
29 | /* Any actions required for stream start e.g. DAC un-mute - run every stream start
30 | */
31 | void AudioStreamStart(void)
32 | {
33 | // Do nothing...
34 | }
35 |
36 | /* Any actions required on stream stop e.g. DAC mute - run every steam stop
37 | */
38 | void AudioStreamStop(void)
39 | {
40 | // Do nothing...
41 | }
42 | #endif
43 |
44 |
--------------------------------------------------------------------------------
/firmware/decouple.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Module: module_usb_aud_shared
3 | * Version: 2v3
4 | * Build: e7a385b28d1c8c508ddaa0746176088124c18651
5 | * File: decouple.h
6 | *
7 | * The copyrights, all other intellectual and industrial
8 | * property rights are retained by XMOS and/or its licensors.
9 | * Terms and conditions covering the use of this code can
10 | * be found in the Xmos End User License Agreement.
11 | *
12 | * Copyright XMOS Ltd 2010
13 | *
14 | * In the case where this code is a modification of existing code
15 | * under a separate license, the separate license terms are shown
16 | * below. The modifications to the code are still covered by the
17 | * copyright notice above.
18 | *
19 | **/
20 | #ifndef __decouple_h__
21 | #define __decouple_h__
22 |
23 |
24 | /** Manage the data transfer between the USB audio buffer and the
25 | * Audio I/O driver.
26 | *
27 | * \param c_audio_out Channel connected to the audio() or mixer() threads
28 | * \param c_led Optional chanend connected to an led driver thread for
29 | * debugging purposes
30 | * \param c_midi Optional chanend connect to usb_midi() thread if present
31 | * \param c_clk_int Optional chanend connected to the clockGen() thread if present
32 | */
33 | void decouple(chanend c_audio_out,
34 | chanend ?c_clk_int, chanend ?c_led);
35 |
36 | #endif // __decouple_h__
37 |
--------------------------------------------------------------------------------
/firmware/audio.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Module: module_usb_aud_shared
3 | * Version: 2v2beta14
4 | * Build: 396662e655a947309bcc1f260c601ec64836abc1
5 | * File: audio.h
6 | *
7 | * The copyrights, all other intellectual and industrial
8 | * property rights are retained by XMOS and/or its licensors.
9 | * Terms and conditions covering the use of this code can
10 | * be found in the Xmos End User License Agreement.
11 | *
12 | * Copyright XMOS Ltd 2010
13 | *
14 | * In the case where this code is a modification of existing code
15 | * under a separate license, the separate license terms are shown
16 | * below. The modifications to the code are still covered by the
17 | * copyright notice above.
18 | *
19 | **/
20 | #ifndef __audio_h__
21 | #define __audio_h__
22 |
23 | /** The audio driver thread.
24 | *
25 | * This function drives I2S ports and handles samples to/from other digital
26 | * I/O threads.
27 | *
28 | * \param c_in Audio sample channel connected to the mixer() thread or the
29 | * decouple() thread
30 | * \param c_dig channel connected to the clockGen() thread for
31 | * receiving/transmitting samples
32 | * \param c_config An optional channel that will be passed on to the
33 | * CODEC configuration functions.
34 | */
35 | void audio(chanend c_in, chanend ?c_dig, chanend ?c_config, chanend ?c_peaks);
36 |
37 | #endif // __audio_h__
38 |
--------------------------------------------------------------------------------
/firmware/xc_ptr.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Module: module_usb_aud_shared
3 | * Version: 2v0
4 | * Build: c0b2e34218aec54736ad1259d95377c59ed03dd3
5 | * File: xc_ptr.h
6 | *
7 | * The copyrights, all other intellectual and industrial
8 | * property rights are retained by XMOS and/or its licensors.
9 | * Terms and conditions covering the use of this code can
10 | * be found in the Xmos End User License Agreement.
11 | *
12 | * Copyright XMOS Ltd 2010
13 | *
14 | * In the case where this code is a modification of existing code
15 | * under a separate license, the separate license terms are shown
16 | * below. The modifications to the code are still covered by the
17 | * copyright notice above.
18 | *
19 | **/
20 | #ifndef __xc_ptr__
21 | #define __xc_ptr__
22 |
23 | typedef unsigned int xc_ptr;
24 |
25 | inline xc_ptr array_to_xc_ptr(unsigned a[]) {
26 | xc_ptr x;
27 | asm("mov %0, %1":"=r"(x):"r"(a));
28 | return x;
29 | }
30 |
31 | #define write_via_xc_ptr(p,x) asm("stw %0, %1[0]"::"r"(x),"r"(p))
32 |
33 | #define write_via_xc_ptr_indexed(p,i,x) asm("stw %0, %1[%2]"::"r"(x),"r"(p),"r"(i))
34 |
35 | #define read_via_xc_ptr(x,p) asm("ldw %0, %1[0]":"=r"(x):"r"(p));
36 |
37 | #define read_via_xc_ptr_indexed(x,p,i) asm("ldw %0, %1[%2]":"=r"(x):"r"(p),"r"(i));
38 |
39 | #define GET_SHARED_GLOBAL(x, g) asm("ldw %0, dp[" #g "]":"=r"(x))
40 | #define SET_SHARED_GLOBAL(g, v) asm("stw %0, dp[" #g "]"::"r"(v))
41 |
42 | #endif
43 |
--------------------------------------------------------------------------------
/firmware/dbcalc.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Module: module_usb_aud_shared
3 | * Version: 2v2beta10
4 | * Build: f542ddaaa188ea8357dea7b588dca0ca2bdb2343
5 | * File: dbcalc.h
6 | *
7 | * The copyrights, all other intellectual and industrial
8 | * property rights are retained by XMOS and/or its licensors.
9 | * Terms and conditions covering the use of this code can
10 | * be found in the Xmos End User License Agreement.
11 | *
12 | * Copyright XMOS Ltd 2010
13 | *
14 | * In the case where this code is a modification of existing code
15 | * under a separate license, the separate license terms are shown
16 | * below. The modifications to the code are still covered by the
17 | * copyright notice above.
18 | *
19 | **/
20 | #ifndef __dbcalc_h__
21 | #define __dbcalc_h__
22 |
23 | /* Function: db_to_mult
24 |
25 | This function converts decibels into a volume multiplier. It uses a fixed-point polynomial approximation
26 | to 10^(db/10).
27 |
28 | Parameters:
29 | db - The db value to convert.
30 | db_frac_bits - The number of binary fractional bits in the supplied decibel value
31 | result_frac_bits - The number of required fractional bits in the result.
32 |
33 | Returns:
34 | The multiplier value as a fixed point value with the number of fractional bits as specified by
35 | the result_frac_bits parameter.
36 | */
37 | unsigned db_to_mult(int db, int db_frac_bits, int result_frac_bits);
38 |
39 | #endif // __dbcalc_h__
40 |
--------------------------------------------------------------------------------
/EULA:
--------------------------------------------------------------------------------
1 | Software License
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of
4 | this software and associated documentation files (the "Software"), to deal with
5 | the Software without restriction, including without limitation the rights to
6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7 | of the Software, and to permit persons to whom the Software is furnished to do
8 | so, subject to the following conditions:
9 |
10 | • Redistributions of source code must retain the above copyright notice, this
11 | list of conditions and the following disclaimers.
12 |
13 | • Redistributions in binary form must reproduce the above copyright notice,
14 | this list of conditions and the following disclaimers in the documentation
15 | and/or other materials provided with the distribution.
16 |
17 | • Neither the name of XMOS, nor the names of its contributors may be used to
18 | endorse or promote products derived from this Software without specific
19 | prior written permission.
20 |
21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 | CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
27 | SOFTWARE.
28 |
--------------------------------------------------------------------------------
/firmware/endpoint0.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Module: module_usb_aud_shared
3 | * Version: 2v2beta12
4 | * Build: 51aff4f427c5b2c11624d86ac8ca955d8976bfb2
5 | * File: endpoint0.h
6 | *
7 | * The copyrights, all other intellectual and industrial
8 | * property rights are retained by XMOS and/or its licensors.
9 | * Terms and conditions covering the use of this code can
10 | * be found in the Xmos End User License Agreement.
11 | *
12 | * Copyright XMOS Ltd 2010
13 | *
14 | * In the case where this code is a modification of existing code
15 | * under a separate license, the separate license terms are shown
16 | * below. The modifications to the code are still covered by the
17 | * copyright notice above.
18 | *
19 | **/
20 |
21 | #ifndef _ENDPOINT0_H_
22 | #define _ENDPOINT0_H_
23 |
24 | /** Function implementing Endpoint 0 for enumeration, control and configuration
25 | * of USB audio devices. It uses the descriptors defined in ``descriptors_2.h``.
26 | *
27 | * \param c_ep0_out Chanend connected to the XUD_Manager() out endpoint array
28 | * \param c_ep0_in Chanend connected to the XUD_Manager() in endpoint array
29 | * \param c_audioCtrl Chanend connected to the decouple thread for control
30 | * audio (sample rate changes etc.)
31 | * \param c_mix_ctl Optional chanend to be connected to the mixer thread if
32 | * present
33 | * \param c_clk_ctl Optional chanend to be connected to the clockgen thread if
34 | * present.
35 | */
36 | void Endpoint0( chanend c_ep0_out, chanend c_ep0_in, chanend c_audioCtrl, chanend ?c_mix_ctl,chanend ?c_clk_ctl, chanend c_dsp_ctl
37 | );
38 |
39 | #endif
40 |
--------------------------------------------------------------------------------
/firmware/clockcmds.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Module: module_usb_aud_shared
3 | * Version: 2v1
4 | * Build: 46c8812cb5039bfd815b3bdf58043aab3d251b83
5 | * File: clockcmds.h
6 | *
7 | * The copyrights, all other intellectual and industrial
8 | * property rights are retained by XMOS and/or its licensors.
9 | * Terms and conditions covering the use of this code can
10 | * be found in the Xmos End User License Agreement.
11 | *
12 | * Copyright XMOS Ltd 2010
13 | *
14 | * In the case where this code is a modification of existing code
15 | * under a separate license, the separate license terms are shown
16 | * below. The modifications to the code are still covered by the
17 | * copyright notice above.
18 | *
19 | **/
20 |
21 | #include "devicedefines.h"
22 |
23 | /* Clocking commands - c_clk_ctl */
24 | #define GET_SEL 0 /* Get value of clock selector */
25 | #define SET_SEL 1 /* Set value of clock selector */
26 | #define GET_FREQ 2 /* Get current freq */
27 | #define GET_VALID 3 /* Get current validity */
28 |
29 | #define CLOCK_INTERNAL 1
30 | #define CLOCK_SPDIF 2
31 | #ifdef SPDIF_RX
32 | #define CLOCK_ADAT 3
33 | #else
34 | #define CLOCK_ADAT 2
35 | #endif
36 |
37 | #define CLOCK_INTERNAL_INDEX (CLOCK_INTERNAL - 1)
38 | #define CLOCK_ADAT_INDEX (CLOCK_ADAT - 1)
39 | #define CLOCK_SPDIF_INDEX (CLOCK_SPDIF - 1)
40 |
41 | #define SET_SMUX 7
42 |
43 | /* c_audioControl */
44 | #define SET_SAMPLE_FREQ 4
45 | #define SET_CHAN_COUNT_IN 5
46 | #define SET_CHAN_COUNT_OUT 6
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/firmware/mixer.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Module: module_usb_aud_shared
3 | * Version: 2v2beta12
4 | * Build: 782797bf7a66eb5078d3ad6655b9f2ce768f1274
5 | * File: mixer.h
6 | *
7 | * The copyrights, all other intellectual and industrial
8 | * property rights are retained by XMOS and/or its licensors.
9 | * Terms and conditions covering the use of this code can
10 | * be found in the Xmos End User License Agreement.
11 | *
12 | * Copyright XMOS Ltd 2010
13 | *
14 | * In the case where this code is a modification of existing code
15 | * under a separate license, the separate license terms are shown
16 | * below. The modifications to the code are still covered by the
17 | * copyright notice above.
18 | *
19 | **/
20 | #ifndef __mixer_h__
21 | #define __mixer_h__
22 |
23 | enum mix_ctl_cmd {
24 | SET_SAMPLES_TO_HOST_MAP,
25 | SET_SAMPLES_TO_DEVICE_MAP,
26 | SET_MIX_MULT,
27 | SET_MIX_MAP,
28 | SET_MIX_IN_VOL,
29 | SET_MIX_OUT_VOL,
30 | GET_INPUT_LEVELS,
31 | GET_STREAM_LEVELS,
32 | GET_OUTPUT_LEVELS
33 | };
34 |
35 |
36 | /** Digital sample mixer.
37 | *
38 | * This thread mixes audio streams between the decouple() thread and
39 | * the audio() thread.
40 | *
41 | * \param c_to_host a chanend connected to the decouple() thread for
42 | * receiving/transmitting samples
43 | * \param c_to_audio a chanend connected to the audio() thread for
44 | * receiving/transmitting samples
45 | * \param c_mix_ctl a chanend connected to the Endpoint0() thread for
46 | * receiving control commands
47 | *
48 | */
49 | void mixer(chanend c_to_host, chanend c_to_audio, chanend c_mix_ctl);
50 |
51 | #endif
52 |
--------------------------------------------------------------------------------
/firmware/Makefile:
--------------------------------------------------------------------------------
1 | XCC := xcc
2 | XCFLAGS := -Wall -W -O2 audio.xn -Wno-switch-fallthrough -report -Wno-timing
3 | LD := xmap
4 | LDFLAGS :=
5 |
6 |
7 | # Build with "V=1" to see the commands executed; be quiet otherwise.
8 |
9 | ifeq ($(V),1)
10 | Q :=
11 | else
12 | Q := @
13 | endif
14 |
15 |
16 | OBJS := main.o
17 | OBJS += endpoint0.o DescriptorRequests.o audiorequests.o audiostream.o
18 | OBJS += decouple.o audio.o clocking.o usb_buffer.o clockgen.o codec.o
19 | OBJS += mixer.o fastmix.o i2c.o codec.o pll.o audioports.o get_adc_counts.o
20 | OBJS += XUD_EpFunctions.o XUD_UIFM_Ports.o XUD_EpFuncs.o dbcalc.o dsp.o
21 | OBJS += dsp_router.o biquad.o SpdifReceive.o
22 |
23 | LIBS := libxud.a
24 |
25 | .PHONY: all
26 | all: tt
27 |
28 |
29 |
30 | tt: $(OBJS)
31 | @echo " LINK $@"
32 | $(Q)$(XCC) $(XCFLAGS) -o $@ $^ $(LIBS) -Wm,--map,map.txt
33 |
34 | %.o: %.xc *.h auto_descriptors.h Makefile audio.xn
35 | @echo " COMPILE $@"
36 | $(Q)$(XCC) $(XCFLAGS) -o $@ -c $<
37 |
38 | %.o: %.c *.h auto_descriptors.h Makefile audio.xn
39 | @echo " COMPILE $@"
40 | $(Q)$(XCC) $(XCFLAGS) -o $@ -c $<
41 |
42 | %.s: %.c *.h auto_descriptors.h Makefile audio.xn
43 | @echo " COMPILE $@"
44 | $(Q)$(XCC) $(XCFLAGS) -o $@ -S $<
45 |
46 | %.o: %.S *.h auto_descriptors.h Makefile audio.xn
47 | @echo " ASSEMBLE $@"
48 | $(Q)$(XCC) $(XCFLAGS) -o $@ -c $<
49 |
50 | auto_descriptors.h: mkdescriptors.py
51 | @echo " GEN $@"
52 | $(Q)python $< > $@
53 |
54 | .version: FORCE
55 | $(Q)./describe.sh > .$@-tmp
56 | $(Q)cmp -s $@ .$@-tmp || cp .$@-tmp $@
57 | $(Q)rm .$@-tmp
58 |
59 | version.c: .version
60 | @echo " VERSION $@"
61 | $(Q)echo "const char version[] = \"`cat $^` (`whoami`@`hostname -s`)\";" > $@
62 |
63 | FORCE:
64 |
65 | .PHONY: clean
66 | clean:
67 | -rm -f tt $(OBJS) .version version.c auto_descriptors.h
68 |
--------------------------------------------------------------------------------
/firmware/SpdifReceive.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Module: module_spdif_rx
3 | * Version: 1v25
4 | * Build: 99e666ad7d70a85054d0d489ebc2917b9b90ed04
5 | * File: SpdifReceive.h
6 | *
7 | * The copyrights, all other intellectual and industrial
8 | * property rights are retained by XMOS and/or its licensors.
9 | * Terms and conditions covering the use of this code can
10 | * be found in the Xmos End User License Agreement.
11 | *
12 | * Copyright XMOS Ltd 2010
13 | *
14 | * In the case where this code is a modification of existing code
15 | * under a separate license, the separate license terms are shown
16 | * below. The modifications to the code are still covered by the
17 | * copyright notice above.
18 | *
19 | **/
20 | #ifndef _SpdifReceive_h_
21 | #define _SpdifReceive_h_
22 | #include
23 |
24 | #define FRAME_X 9 // Left
25 | #define FRAME_Y 5 // Right
26 | #define FRAME_Z 3 // Left (start of frame)
27 |
28 |
29 | /** S/PDIF receiver.
30 | *
31 | * This function needs 1 thread and no memory other
32 | * than ~2800 bytes of program code. It can do 11025, 12000, 22050, 24000,
33 | * 44100, 48000, 88200, 96000, and 192000 kHz.w
34 | *
35 | * For a 100MHz reference clock, use a divider
36 | * of 1 for 192000, 2 for 96000/88200, 4 for 48000/44100 on clock b.
37 | * When the decoder
38 | * encounters a long series of zeros it will lower the divider; when it
39 | * encounters a short series of 0-1 transitions it will increase the divider.
40 | *
41 | * Output: whole word with bits 0-3 set to preamble.
42 | *
43 | * \param p S/PDIF output port
44 | * \param c channel to output samples to
45 | * \param initial_divider initial divide for initial estimate of sample rate
46 | * \param b clock block set to 100MHz
47 | **/
48 | void SpdifReceive(in buffered port:4 p, streaming chanend c, int initial_divider, clock b);
49 |
50 | #endif // _SpdifReceive_h_
51 |
--------------------------------------------------------------------------------
/firmware/clocking.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Module: module_usb_aud_shared
3 | * Version: 2v2beta14
4 | * Build: 396662e655a947309bcc1f260c601ec64836abc1
5 | * File: clocking.h
6 | *
7 | * The copyrights, all other intellectual and industrial
8 | * property rights are retained by XMOS and/or its licensors.
9 | * Terms and conditions covering the use of this code can
10 | * be found in the Xmos End User License Agreement.
11 | *
12 | * Copyright XMOS Ltd 2010
13 | *
14 | * In the case where this code is a modification of existing code
15 | * under a separate license, the separate license terms are shown
16 | * below. The modifications to the code are still covered by the
17 | * copyright notice above.
18 | *
19 | **/
20 |
21 | #ifndef _CLOCKING_H_
22 | #define _CLOCKING_H_
23 |
24 | /* Functions that handle master clock generation. These need modifying for an existing design */
25 |
26 | /* Any initialisation required for master clock generation - run once at start up */
27 | void ClockingInit(void);
28 |
29 | /* Configuration for a specific master clock frequency - run every sample frequency change */
30 | void ClockingConfig(unsigned mClkFreq);
31 |
32 |
33 | /** Clock generation and digital audio I/O handling.
34 | *
35 | * \param c_spdif_rx channel connected to S/PDIF receive thread
36 | * \param c_adat_rx channel connect to ADAT receive thread
37 | * \param p port to output clock signal to drive external frequency synthesizer
38 | * \param c_audio channel connected to the audio() thread
39 | * \param c_clk_ctl channel connected to Endpoint0() for configuration of the
40 | * clock
41 | * \param c_clk_int channel connected to the decouple() thread for clock
42 | interrupts
43 | */
44 | void clockGen (streaming chanend c_spdif_rx, chanend c_adat_rx, out port p, chanend c_audio, chanend c_clk_ctl, chanend c_clk_int);
45 | #endif
46 |
47 |
--------------------------------------------------------------------------------
/firmware/usb_buffer.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Module: module_usb_aud_shared
3 | * Version: 2v2beta12
4 | * Build: a3e26005ac327c50f978224d03666749aea1c70a
5 | * File: usb_buffer.h
6 | *
7 | * The copyrights, all other intellectual and industrial
8 | * property rights are retained by XMOS and/or its licensors.
9 | * Terms and conditions covering the use of this code can
10 | * be found in the Xmos End User License Agreement.
11 | *
12 | * Copyright XMOS Ltd 2010
13 | *
14 | * In the case where this code is a modification of existing code
15 | * under a separate license, the separate license terms are shown
16 | * below. The modifications to the code are still covered by the
17 | * copyright notice above.
18 | *
19 | **/
20 | #ifndef __usb_buffer_h__
21 | #define __usb_buffer_h__
22 | /** USB Audio Buffering Thread.
23 | *
24 | * This function buffers USB audio data between the XUD layer and the decouple
25 | * thread. Most of the chanend parameters to the function should be connected to
26 | * XUD_Manager()
27 | *
28 | * \param c_aud_out Audio OUT endpoint channel connected to the XUD
29 | * \param c_aud_in Audio IN endpoint channel connected to the XUD
30 | * \param c_aud_fb Audio feedback endpoint channel connected to the XUD
31 | * \param c_midi_from_host MIDI OUT endpoint channel connected to the XUD
32 | * \param c_midi_to_host MIDI IN endpoint channel connected to the XUD
33 | * \param c_int Audio clocking interrupt endpoint channel connected to the XUD
34 | * \param c_sof Start of frame channel connected to the XUD
35 | * \param c_aud_ctl Audio control channel connected to Endpoint0()
36 | * \param p_off_mclk A port that is clocked of the MCLK input (not the MCLK input itself)
37 | */
38 | void buffer(chanend c_aud_out, chanend c_aud_in, chanend c_aud_fb,
39 | chanend c_int,
40 | chanend c_sof,
41 | chanend c_aud_ctl,
42 | in port p_off_mclk);
43 |
44 |
45 | #endif
46 |
--------------------------------------------------------------------------------
/README:
--------------------------------------------------------------------------------
1 | This is my own firmware for the XMOS USB 2.0 Multichannel Reference Design
2 | board, which I use to drive my 5.1 speakers (Logitech Z-680 with the crappy
3 | original DSP frontend box removed). It is based on the original reference
4 | firmware by XMOS, but with a lot of horribleness removed (and a lot left -
5 | here be dragons, and don't blame me for it).
6 |
7 | I had to ask to get a copy of the original reference firmware, but it was
8 | provided to me with the EULA file that is in this repo, which I interpret to
9 | mean that the whole thing is licensed under the permissive BSD-like license
10 | which it contains, and therefore I am allowed to redistribute it.
11 |
12 | You need the aforementioned XMOS USB 2.0 MC Reference board, and also an XK-1A
13 | (or modified XK-1 to fix the xlink pinout) plugged into the JTAG/XLink port.
14 | You'll either have to power the XK-1A externally or modify the main board to
15 | back-feed power to it. The XK-1 provides additional DSP power.
16 |
17 | This firmware implements a fairly flexible mixer (tested and designed to
18 | work well with the Linux ALSA sound drivers; no idea how other OSes will
19 | interpret the mixer controls available) plus a fully configurable 15 biquad DSP
20 | filters for each of the 6 output channels for equalization, all running at
21 | (hardcoded) 96kHz sample rate and 24 bit depth (with a 32-bit processing path).
22 | Notable features include the ability to use stereo inputs as soft-differential
23 | (subtraction in software), and also rotate the mapping between stereo inputs
24 | and the 5.1ch output (so that, for example, the left channel can be mapped to
25 | the front speakers and the right to the rear speakers, creating a 90° rotation).
26 | The first stereo output is a headphones output that carries a downmixed version
27 | of the final 5.1ch mix, while the next 3 are the 5.1ch outputs. There is
28 | built-in downmixing of the 5ch into the .1 subwoofer channel - no hardcoded
29 | crossover (by default it's full range), but you can trivially configure one
30 | with the biquad filters. The input LFE channel is mixed at +10dB relative to
31 | the other channels into the .1 output, per the Dolby Digital spec.
32 |
33 | I think USB audio capture is broken but I've been too lazy to debug it.
34 |
--------------------------------------------------------------------------------
/firmware/pll.xc:
--------------------------------------------------------------------------------
1 | /**
2 | * Module: app_usb_aud_l2
3 | * Version: 5v00
4 | * Build: 4ecd7ef5e1e14be120ba7c10316070b643809339
5 | * File: pll.xc
6 | *
7 | * The copyrights, all other intellectual and industrial
8 | * property rights are retained by XMOS and/or its licensors.
9 | * Terms and conditions covering the use of this code can
10 | * be found in the Xmos End User License Agreement.
11 | *
12 | * Copyright XMOS Ltd 2010
13 | *
14 | * In the case where this code is a modification of existing code
15 | * under a separate license, the separate license terms are shown
16 | * below. The modifications to the code are still covered by the
17 | * copyright notice above.
18 | *
19 | **/
20 | #include
21 | #include
22 |
23 | #include "i2c.h"
24 |
25 | #define DEV_ADR 0x9C
26 |
27 | #define PLL_REGRD(reg) I2cRegRead(DEV_ADR, reg, p_i2c_scl, p_i2c_sda)
28 | #define PLL_REGWR(reg, val) I2cRegWrite(DEV_ADR, reg, val, p_i2c_scl, p_i2c_sda)
29 |
30 | /* I2C ports */
31 | extern port p_i2c_sda;
32 | extern port p_i2c_scl;
33 |
34 | /* Init of CS2300 */
35 | void PllInit(void)
36 | {
37 | /* Enable init */
38 | //PLL_REGWR(0x1e, 0b01110000); // increase pll bandwidth to reduce lock time
39 | PLL_REGWR(0x03, 0x07);
40 | PLL_REGWR(0x05, 0x01);
41 | PLL_REGWR(0x16, 0x10);
42 | // PLL_REGWR(0x17, 0x10); //0x10 for always gen clock even when unlocked
43 | PLL_REGWR(0x17, 0x00); //0x10 for always gen clock even when unlocked
44 |
45 |
46 | /* Check */
47 | assert(PLL_REGRD(0x03) == 0x07);
48 | assert(PLL_REGRD(0x05) == 0x01);
49 | assert(PLL_REGRD(0x16) == 0x10);
50 | assert(PLL_REGRD(0x17) == 0x00);
51 | //assert(PLL_REGRD(0x1e) == 0b01110000);
52 | }
53 |
54 | /* Setup PLL multiplier */
55 | void PllMult(unsigned mult)
56 | {
57 | /* Multiplier is translated to 20.12 format by shifting left by 12 */
58 | PLL_REGWR(0x06, (mult >> 12) & 0xFF);
59 | PLL_REGWR(0x07, (mult >> 4) & 0xFF);
60 | PLL_REGWR(0x08, (mult << 4) & 0xFF);
61 | PLL_REGWR(0x09, 0x00);
62 |
63 | /* Check */
64 | assert(PLL_REGRD(0x06) == ((mult >> 12) & 0xFF));
65 | assert(PLL_REGRD(0x07) == ((mult >> 4) & 0xFF));
66 | assert(PLL_REGRD(0x08) == ((mult << 4) & 0xFF));
67 | assert(PLL_REGRD(0x09) == 0x00);
68 | }
69 |
70 |
71 |
--------------------------------------------------------------------------------
/firmware/DescriptorRequests.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Module: module_usb_shared
3 | * Version: 1v14
4 | * Build: 2653f22a66739162bd368f5c7d50da8bd7417fd7
5 | * File: DescriptorRequests.h
6 | *
7 | * The copyrights, all other intellectual and industrial
8 | * property rights are retained by XMOS and/or its licensors.
9 | * Terms and conditions covering the use of this code can
10 | * be found in the Xmos End User License Agreement.
11 | *
12 | * Copyright XMOS Ltd 2010
13 | *
14 | * In the case where this code is a modification of existing code
15 | * under a separate license, the separate license terms are shown
16 | * below. The modifications to the code are still covered by the
17 | * copyright notice above.
18 | *
19 | **/
20 | /**
21 | * @file DescriptorRequests.h
22 | * @brief DescriptorRequestsi() prototype
23 | * @author Ross Owen, XMOS Limited
24 | * @version 1.0
25 | */
26 |
27 |
28 | /** DescriptorRequests()
29 | * @brief This function performs some of the common USB standard descriptor requests.
30 | *
31 | * @param c_out Channel to XUD (ep 0)
32 | * @param c_in Channel from XUD (ep 0)
33 | * @param devDesc Device descriptor
34 | * @param devDescLength Length of device descriptor in bytes
35 | * @param cfgDesc Configuration descriptor
36 | * @param cfgDescLength Length of config descriptor in bytes
37 | * @param devQualDesc Device Qualification Descriptor
38 | * @param sp SetupPacket (passed by ref) in which the setup data is returned
39 | * @return 1 if dealt with else
40 | *
41 | * This function handles the following standard requests appropriately using values passed to it:
42 | *
43 | * - Get Device Descriptor (Using devDesc argument)
44 | * - Get Configuration Descriptor (Using cfgDesc argument)
45 | * - String requests (using strDesc argument)
46 | * - Get Micro$oft OS String Descriptor (Usings product ID string)
47 | * - Get Device_Qualifier Descriptor
48 | * - Get Other-Speed Configuration Descriptor (using oSpeedCfgDesc argument)
49 | *
50 | * This function returns 1 if the request has been dealt with successfully, 0 if not. The SetupPacket
51 | * structure should then be examined for device specific requests.
52 |
53 | */
54 | int DescriptorRequests(XUD_ep c, XUD_ep c_in, uint8 devDesc[], int devDescLength, uint8 cfgDesc[], int cfgDescLength,
55 | uint8 devQualDesc[], int devQualDescLength, uint8 oSpeedCfgDesc[], int oSpeedCfgDescLength, uint8 strDescs[][40], SetupPacket &sp);
56 |
--------------------------------------------------------------------------------
/firmware/XUD_UIFM_Ports.xc:
--------------------------------------------------------------------------------
1 | /**
2 | * Module: module_xud
3 | * Version: 0v60
4 | * Build: 5749c99b7821363ba858462b29442d52f62eafe2
5 | * File: XUD_UIFM_Ports.xc
6 | *
7 | * The copyrights, all other intellectual and industrial
8 | * property rights are retained by XMOS and/or its licensors.
9 | * Terms and conditions covering the use of this code can
10 | * be found in the Xmos End User License Agreement.
11 | *
12 | * Copyright XMOS Ltd 2010
13 | *
14 | * In the case where this code is a modification of existing code
15 | * under a separate license, the separate license terms are shown
16 | * below. The modifications to the code are still covered by the
17 | * copyright notice above.
18 | *
19 | **/
20 | #include
21 | #include
22 |
23 | #ifdef UIFM_USB_CLK_PORT
24 | // Port defines already made (probably in XN file)
25 | in port p_usb_clk = UIFM_USB_CLK_PORT;
26 | out port reg_write_port = UIFM_REG_WRITE_PORT;
27 | in port reg_read_port = UIFM_REG_READ_PORT;
28 | in port flag0_port = UIFM_FLAG_0_PORT;
29 | in port flag1_port = UIFM_FLAG_1_PORT;
30 | in port flag2_port = UIFM_FLAG_2_PORT;
31 | out port p_usb_txd = UIFM_TX_DATA_PORT;
32 | port p_usb_rxd = UIFM_RX_DATA_PORT;
33 | #else
34 |
35 | // We need to know what core the USB ports are on
36 |
37 | #ifndef USB_CORE
38 | //#error "Must define USB_CORE to core number with USB interface"
39 | #else
40 |
41 | #define UIFM_USB_CLK_PORT XS1_PORT_1H
42 |
43 | #define UIFM_REG_WRITE_PORT XS1_PORT_8C
44 | #define UIFM_REG_READ_PORT XS1_PORT_8D
45 | #define UIFM_FLAG_0_PORT XS1_PORT_1N
46 | #define UIFM_FLAG_1_PORT XS1_PORT_1O
47 | #define UIFM_FLAG_2_PORT XS1_PORT_1P
48 | #define UIFM_TX_DATA_PORT XS1_PORT_8A
49 | #define UIFM_RX_DATA_PORT XS1_PORT_8B
50 | #define UIFM_STP_SUS_PORT XS1_PORT_1E
51 | #define UIFM_LS_PORT XS1_PORT_4D
52 |
53 | #endif
54 |
55 | on stdcore[USB_CORE]:in port p_usb_clk = UIFM_USB_CLK_PORT;
56 | on stdcore[USB_CORE]:out port reg_write_port = UIFM_REG_WRITE_PORT;
57 | on stdcore[USB_CORE]:in port reg_read_port = UIFM_REG_READ_PORT;
58 | on stdcore[USB_CORE]:in port flag0_port = UIFM_FLAG_0_PORT;
59 | on stdcore[USB_CORE]:in port flag1_port = UIFM_FLAG_1_PORT;
60 | on stdcore[USB_CORE]:in port flag2_port = UIFM_FLAG_2_PORT;
61 | on stdcore[USB_CORE]:out port p_usb_txd = UIFM_TX_DATA_PORT;
62 | on stdcore[USB_CORE]: port p_usb_rxd = UIFM_RX_DATA_PORT;
63 |
64 | #endif
65 |
--------------------------------------------------------------------------------
/firmware/fastmix.S:
--------------------------------------------------------------------------------
1 | /**
2 | * Module: module_usb_aud_shared
3 | * Version: 2v2beta14
4 | * Build: 828cd13ccba5efa7d63ff5d0c967357ccd0c8ad4
5 | * File: fastmix.S
6 | *
7 | * The copyrights, all other intellectual and industrial
8 | * property rights are retained by XMOS and/or its licensors.
9 | * Terms and conditions covering the use of this code can
10 | * be found in the Xmos End User License Agreement.
11 | *
12 | * Copyright XMOS Ltd 2010
13 | *
14 | * In the case where this code is a modification of existing code
15 | * under a separate license, the separate license terms are shown
16 | * below. The modifications to the code are still covered by the
17 | * copyright notice above.
18 | *
19 | **/
20 |
21 | #include "devicedefines.h"
22 |
23 | #define DOMIX_TOP(i) \
24 | .cc_top doMix##i.function,doMix##i; \
25 | .align 4 ;\
26 | .globl doMix##i ;\
27 | .globl doMix##i##.nstackwords ;\
28 | .globl doMix##i##.maxthreads ; \
29 | .globl doMix##i##.maxtimers ; \
30 | .globl doMix##i##.maxchanends ; \
31 | .globl doMix##i##.maxsync ;\
32 | .linkset doMix##i##.locnoside, 1; \
33 | .linkset doMix##i##.locnochandec, 1;\
34 | .linkset doMix##i##.nstackwords, 0 ;\
35 | .linkset doMix##i##.maxchanends, 0 ;\
36 | .linkset doMix##i##.maxtimers, 0 ;\
37 | .linkset doMix##i##.maxthreads, 1; \
38 | doMix##i##: ;\
39 | set cp, r0; \
40 | set dp, r1; \
41 | lsub r0, r1, r0, r0, r0;\
42 |
43 | #define DOMIX_BOT(i) \
44 | ldap r11, _dp; \
45 | set dp, r11;\
46 | ldap r11, _cp;\
47 | set cp, r11;\
48 | \
49 | mov r0, r1;\
50 | ldc r2, 0x19;\
51 | sext r0, r2;\
52 | eq r0, r0, r1;\
53 | bf r0, .L20; \
54 | \
55 | shl r0, r1, 0x7;\
56 | retsp 0x0;\
57 | \
58 | \
59 | .cc_bottom doMix##i##.function;
60 |
61 | #define BODY(i) \
62 | ldw r2, cp[i]; \
63 | ldw r11, dp[i]; \
64 | maccs r1, r0, r2, r11;
65 |
66 |
67 | .text
68 |
69 | .L20:\
70 | lss r0, r1, r3;\
71 | bt r0, .L16; \
72 | ldw r0, cp[.LC0];\
73 | retsp 0x0; \
74 | .L16:\
75 | ldw r0, cp[.LC1];\
76 | retsp 0x0; \
77 |
78 |
79 |
80 |
81 | #define N MIX_INPUTS
82 | DOMIX_TOP(_out)
83 | #include "repeat.h"
84 | DOMIX_BOT(_out)
85 |
86 | #undef N
87 | #define N AUX_COUNT
88 | DOMIX_TOP(_in)
89 | #include "repeat.h"
90 | DOMIX_BOT(_in)
91 |
92 | .section .cp.const4, "acM", @progbits, 4
93 | .LC0:
94 | .align 4
95 | .int 0x7fffff00
96 | .LC1:
97 | .int 0x80000000
98 |
99 | #undef N
100 | #undef BODY
101 |
102 |
103 |
104 |
--------------------------------------------------------------------------------
/firmware/biquad.S:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2011, XMOS Ltd, All rights reserved
2 | // This software is freely distributable under a derivative of the
3 | // University of Illinois/NCSA Open Source License posted in
4 | // LICENSE.txt and at
5 |
6 | #include "dsp.h"
7 |
8 | #define NWORDS 7
9 |
10 | .globl biquad_cascade
11 | .globl biquad_cascade.nstackwords
12 | .linkset biquad_cascade.nstackwords,NWORDS
13 | .align 4
14 | biquad_cascade:
15 | entsp NWORDS
16 | stw r4, sp[0]
17 | stw r5, sp[1]
18 | stw r6, sp[2]
19 | stw r7, sp[3]
20 | stw r8, sp[4]
21 | stw r9, sp[5]
22 | stw r10, sp[6]
23 |
24 | mov r10, r3
25 |
26 | // r0: xn
27 | // r1: count
28 | // r2: biquads
29 | // r3: xn1
30 | // r4: xn2
31 | // r5: tmp
32 | // r6: FRACTIONALBITS
33 | // r7: 1<<(FRACTIONALBITS-1)
34 | // r8: accl
35 | // r9: acch
36 | // r10: headroombits
37 |
38 | ldc r6, FRACTIONALBITS
39 |
40 | ldw r3, r2[0]
41 |
42 | ashr r0, r0, r10
43 |
44 | ldc r9, 0
45 | ldc r7, 1
46 | ldw r4, r2[1]
47 | shl r7, r7, r6
48 | shr r7, r7, 1
49 |
50 | loop:
51 | mov r8, r7
52 | ldw r5, r2[2] // Coefficient b0
53 | maccs r9, r8, r5, r0 // Multiply by xn
54 | ldw r5, r2[3] // Coefficient b1
55 | maccs r9, r8, r5, r3 // Multiply by xn1
56 | ldw r5, r2[4] // Coefficient b2
57 | maccs r9, r8, r5, r4 // Multiply by xn2
58 |
59 | stw r0, r2[0] // Save xn into xn1
60 | stw r3, r2[1] // Save xn1 into xn2
61 |
62 | ldw r5, r2[5] // Coefficient a1
63 | ldw r3, r2[7] // Load yn1 (next filter xn1)
64 | maccs r9, r8, r5, r3
65 | ldw r5, r2[6] // Coefficient a2
66 | ldw r4, r2[8] // Load yn2 (next filter xn2)
67 | maccs r9, r8, r5, r4
68 |
69 | ldaw r2, r2[7] // Advance to next biquad
70 |
71 | mov r5, r9 // copy r9 into r5, to check for overflow
72 | sext r5, r6 // because sext sign extends in place
73 | eq r5, r9, r5 // If sext makes no change, result is ok
74 | bt r5, resultFits
75 | ldc r0, 0x80 // not ok, create MININT or MAXINT
76 | shl r0, r0, 24
77 | lss r5, r5, r9
78 | sub r0, r0, r5
79 | bu resultDone
80 |
81 | resultFits:
82 | ldc r5, 32-FRACTIONALBITS // Merge two halves
83 | shl r9, r9, r5 // By shifting both halves and oring them together.
84 | shr r8, r8, r6
85 | or r0, r9, r8
86 |
87 | resultDone:
88 | sub r1, r1, 1 // Dec counter
89 | eq r9, r1, 0 // Last bank?
90 | bf r9, loop // If not, jump, this clears r9
91 |
92 | stw r0, r2[0] // store yn1
93 | stw r3, r2[1] // store yn2
94 |
95 | ldc r1, 32
96 | sub r1, r1, r10
97 | mov r2, r0
98 | sext r2, r1
99 | eq r2, r0, r2 // If sext makes no change, result is ok
100 | bt r2, finalResultFits
101 | ldc r1, 0x80 // not ok, create MININT or MAXINT
102 | shl r1, r1, 24
103 | lss r2, r2, r0
104 | sub r0, r1, r2
105 | bu allDone
106 |
107 | finalResultFits:
108 | shl r0, r0, r10
109 |
110 | allDone: // Now just restore all registers.
111 |
112 | ldw r4, sp[0]
113 | ldw r5, sp[1]
114 | ldw r6, sp[2]
115 | ldw r7, sp[3]
116 | ldw r8, sp[4]
117 | ldw r9, sp[5]
118 | ldw r10, sp[6]
119 | retsp NWORDS
120 |
--------------------------------------------------------------------------------
/firmware/dsp_router.xc:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include "mixer.h"
5 | #include "devicedefines.h"
6 | #include "dsp.h"
7 |
8 | #define LDW(dest, array, index) asm("ldw %0, %1[%2]":"=r"(dest):"r"(array),"r"(index))
9 | #define STW(array, index, value) asm("stw %0, %1[%2]"::"r"(value),"r"(array),"r"(index))
10 |
11 | static int dsp_in_samples[I2S_CHANS_DAC];
12 | static int dsp_out_samples[I2S_CHANS_DAC];
13 | static int in_samples[IN_CHANNELS];
14 |
15 | static struct biquad lfe_biquads[DSP_FILTERS+1] = {
16 | {0,0,DB10,0,0,0,0},{0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},
17 | {0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},
18 | {0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},
19 | {0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},{0,0,0,0,0,0,0},
20 | };
21 |
22 | static int audiobuf[DELAY_BUF];
23 | static int p_write;
24 | static int lfe_delay;
25 |
26 | #pragma unsafe arrays
27 | static void giveSamplesToDevice(chanend c)
28 | {
29 | outuint(c, dsp_in_samples[0]);
30 | outuint(c, dsp_in_samples[1]);
31 | outuint(c, dsp_out_samples[2]);
32 | outuint(c, dsp_out_samples[3]);
33 | outuint(c, dsp_out_samples[4]);
34 | outuint(c, dsp_out_samples[5]);
35 | outuint(c, dsp_out_samples[6]);
36 | outuint(c, dsp_out_samples[7]);
37 | }
38 |
39 | #pragma unsafe arrays
40 | static void getSamplesFromDevice(chanend c)
41 | {
42 | #pragma loop unroll
43 | for (int i = 0; i < IN_CHANNELS; i++)
44 | STW(in_samples, i, inuint(c));
45 | }
46 |
47 | #pragma unsafe arrays
48 | static void giveSamplesToMixer(chanend c)
49 | {
50 | #pragma loop unroll
51 | for (int i = 0; i < IN_CHANNELS; i++)
52 | outuint(c, in_samples[i]);
53 | }
54 |
55 | #pragma unsafe arrays
56 | static void getSamplesFromMixer(chanend c)
57 | {
58 | #pragma loop unroll
59 | for (int i = 0; i < I2S_CHANS_DAC; i++)
60 | STW(dsp_in_samples, i, inuint(c));
61 | }
62 |
63 | #pragma unsafe arrays
64 | static void giveSamplesToDSP(chanend c)
65 | {
66 | #pragma loop unroll
67 | for (int i = 0; i < DSP_EXT_CH; i++)
68 | outuint(c, dsp_in_samples[2+i]);
69 | }
70 |
71 | #pragma unsafe arrays
72 | static void getSamplesFromDSP(chanend c)
73 | {
74 | #pragma loop unroll
75 | for (int i = 0; i < DSP_EXT_CH; i++)
76 | STW(dsp_out_samples, 2+i, inuint(c));
77 | }
78 |
79 | #pragma unsafe arrays
80 | void dsp_router(chanend c_mixer, chanend c_audio, chanend c_dsp, chanend c_dsp_ctl)
81 | {
82 | int result = 0;
83 | unsigned char ct;
84 | while(1) {
85 | inuint(c_audio);
86 | giveSamplesToDevice(c_audio);
87 | getSamplesFromDevice(c_audio);
88 | outuint(c_mixer, 0);
89 | getSamplesFromMixer(c_mixer);
90 | giveSamplesToMixer(c_mixer);
91 |
92 | select {
93 | case inct_byref(c_dsp_ctl, ct): {
94 | int ch, i;
95 | switch (ct) {
96 | case SET_DSP_BIQUAD:
97 | ch = inuint(c_dsp_ctl);
98 | if (ch == DSP_EXT_CH) {
99 | i = inuint(c_dsp_ctl);
100 | lfe_biquads[i].xn1 = 0;
101 | lfe_biquads[i].xn2 = 0;
102 | lfe_biquads[i].b0 = inuint(c_dsp_ctl);
103 | lfe_biquads[i].b1 = inuint(c_dsp_ctl);
104 | lfe_biquads[i].b2 = inuint(c_dsp_ctl);
105 | lfe_biquads[i].a1 = inuint(c_dsp_ctl);
106 | lfe_biquads[i].a2 = inuint(c_dsp_ctl);
107 | } else {
108 | outct(c_dsp, SET_DSP_BIQUAD);
109 | outuint(c_dsp, ch);
110 | outuint(c_dsp, inuint(c_dsp_ctl));
111 | outuint(c_dsp, inuint(c_dsp_ctl));
112 | outuint(c_dsp, inuint(c_dsp_ctl));
113 | outuint(c_dsp, inuint(c_dsp_ctl));
114 | outuint(c_dsp, inuint(c_dsp_ctl));
115 | outuint(c_dsp, inuint(c_dsp_ctl));
116 | }
117 | break;
118 | case SET_DSP_DELAY:
119 | ch = inuint(c_dsp_ctl);
120 | if (ch == DSP_EXT_CH) {
121 | lfe_delay = inuint(c_dsp_ctl);
122 | } else {
123 | outct(c_dsp, SET_DSP_DELAY);
124 | outuint(c_dsp, ch);
125 | outuint(c_dsp, inuint(c_dsp_ctl));
126 | }
127 | break;
128 | }
129 | chkct(c_dsp_ctl, XS1_CT_END);
130 | break;
131 | }
132 | default:
133 | break;
134 | }
135 | outuint(c_dsp, 0);
136 | getSamplesFromDSP(c_dsp);
137 | STW(dsp_out_samples, 2+DSP_EXT_CH, result);
138 | giveSamplesToDSP(c_dsp);
139 | p_write = (p_write + 1) & MAX_DELAY;
140 | result = biquad_cascade(dsp_in_samples[2+DSP_EXT_CH], DSP_FILTERS, lfe_biquads, LFE_HEADROOMBITS);
141 | STW(audiobuf, p_write, result);
142 | result = audiobuf[(p_write - lfe_delay) & MAX_DELAY];
143 |
144 | }
145 | }
146 |
--------------------------------------------------------------------------------
/firmware/dsp.xc:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include "mixer.h"
5 | #include "devicedefines.h"
6 | #include "dsp.h"
7 |
8 | #define LDW(dest, array, index) asm("ldw %0, %1[%2]":"=r"(dest):"r"(array),"r"(index))
9 | #define STW(array, index, value) asm("stw %0, %1[%2]"::"r"(value),"r"(array),"r"(index))
10 |
11 | static struct biquad biquads[DSP_EXT_CH][DSP_FILTERS+1] = {
12 | {
13 | {0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},
14 | {0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},
15 | {0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},
16 | {0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},{0,0,0,0,0,0,0},
17 | },
18 | {
19 | {0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},
20 | {0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},
21 | {0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},
22 | {0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},{0,0,0,0,0,0,0},
23 | },
24 | {
25 | {0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},
26 | {0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},
27 | {0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},
28 | {0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},{0,0,0,0,0,0,0},
29 | },
30 | {
31 | {0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},
32 | {0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},
33 | {0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},
34 | {0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},{0,0,0,0,0,0,0},
35 | },
36 | {
37 | {0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},
38 | {0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},
39 | {0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},
40 | {0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},{0,0,ONE,0,0,0,0},{0,0,0,0,0,0,0},
41 | },
42 | };
43 |
44 | static int audiobuf[DSP_EXT_CH][DELAY_BUF];
45 | static int delay[DSP_EXT_CH];
46 | static int p_write[DSP_EXT_CH];
47 |
48 | static int dsp_out_samples[DSP_EXT_CH];
49 |
50 | #pragma unsafe arrays
51 | static void giveSamplesToDevice(chanend c)
52 | {
53 | #pragma loop unroll
54 | for (int i = 0; i < DSP_EXT_CH; i++)
55 | outuint(c, dsp_out_samples[i]);
56 | }
57 | #pragma unsafe arrays
58 | static void getSamplesFromMixer(chanend c)
59 | {
60 | #pragma loop unroll
61 | for (int i = 0; i < DSP_EXT_CH; i++)
62 | STW(dsp_out_samples, i, inuint(c));
63 | }
64 |
65 | void dsp_sub(int ch, chanend c, const struct biquad bq[])
66 | {
67 | int result;
68 | while(1) {
69 | int p;
70 | inuint(c);
71 | p = (p_write[ch] + 1) & MAX_DELAY;
72 | STW(p_write, ch, p);
73 | result = biquad_cascade(dsp_out_samples[ch], DSP_FILTERS, bq, HEADROOMBITS);
74 | STW(audiobuf[ch], p, result);
75 | result = audiobuf[ch][(p - delay[ch]) & MAX_DELAY];
76 | STW(dsp_out_samples, ch, result);
77 | outuint(c, 0);
78 | }
79 | }
80 |
81 | void dsp_main(chanend c_dsp, chanend c1, chanend c2, chanend c3, chanend c4)
82 | {
83 | int result;
84 | set_thread_fast_mode_on();
85 | while (1) {
86 | int p;
87 | if (testct(c_dsp)) {
88 | int ch, i, cmd;
89 | cmd = inct(c_dsp);
90 | switch (cmd) {
91 | case SET_DSP_BIQUAD:
92 | ch = inuint(c_dsp);
93 | i = inuint(c_dsp);
94 | biquads[ch][i].xn1 = 0;
95 | biquads[ch][i].xn2 = 0;
96 | biquads[ch][i].b0 = inuint(c_dsp);
97 | biquads[ch][i].b1 = inuint(c_dsp);
98 | biquads[ch][i].b2 = inuint(c_dsp);
99 | biquads[ch][i].a1 = inuint(c_dsp);
100 | biquads[ch][i].a2 = inuint(c_dsp);
101 | break;
102 | case SET_DSP_DELAY:
103 | ch = inuint(c_dsp);
104 | STW(delay, ch, inuint(c_dsp));
105 | break;
106 | }
107 | }
108 | inuint(c_dsp);
109 | giveSamplesToDevice(c_dsp);
110 | getSamplesFromMixer(c_dsp);
111 | p = (p_write[0] + 1) & MAX_DELAY;
112 | STW(p_write, 0, p);
113 | outuint(c1, 0);
114 | outuint(c2, 0);
115 | outuint(c3, 0);
116 | outuint(c4, 0);
117 | result = biquad_cascade(dsp_out_samples[0], DSP_FILTERS, biquads[0], HEADROOMBITS);
118 | STW(audiobuf[0], p, result);
119 | result = audiobuf[0][(p - delay[0]) & MAX_DELAY];
120 | STW(dsp_out_samples, 0, result);
121 | inuint(c1);
122 | inuint(c2);
123 | inuint(c3);
124 | inuint(c4);
125 | }
126 | }
127 |
128 | #pragma unsafe arrays
129 | void dsp(chanend c_dsp)
130 | {
131 | chan c1, c2, c3, c4;
132 | par {
133 | dsp_main(c_dsp, c1, c2, c3, c4);
134 | dsp_sub(1, c1, biquads[1]);
135 | dsp_sub(2, c2, biquads[2]);
136 | dsp_sub(3, c3, biquads[3]);
137 | dsp_sub(4, c4, biquads[4]);
138 | }
139 | }
140 |
--------------------------------------------------------------------------------
/firmware/customdefines.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Module: app_usb_aud_l2
3 | * Version: 5v3rc0
4 | * Build: c653036bf3addcd9dae8deb06615fc62ae14ac93
5 | * File: customdefines.h
6 | *
7 | * The copyrights, all other intellectual and industrial
8 | * property rights are retained by XMOS and/or its licensors.
9 | * Terms and conditions covering the use of this code can
10 | * be found in the Xmos End User License Agreement.
11 | *
12 | * Copyright XMOS Ltd 2010
13 | *
14 | * In the case where this code is a modification of existing code
15 | * under a separate license, the separate license terms are shown
16 | * below. The modifications to the code are still covered by the
17 | * copyright notice above.
18 | *
19 | **/
20 | /**
21 | * @file customdefines.h
22 | * @brief Defines relating to device configuration and customisation.
23 | * @author Ross Owen, XMOS Limited
24 | */
25 | #ifndef _CUSTOMDEFINES_H_
26 | #define _CUSTOMDEFINES_H_
27 |
28 | //#define XUD_DEBUG_VERSION
29 | //#define DEBUG
30 |
31 | #ifdef DEBUG
32 | #define dprintf printf
33 | #else
34 | #define dprintf(...) while(0)
35 | #endif
36 |
37 | #define DEBUG_LEDS
38 |
39 | /***** Device configuration option defines. Build can be customised but changing these defines *****/
40 |
41 | /* Audio Class Version */
42 | #define AUDIO_CLASS 2
43 |
44 | /* Defines relating to channel count and channel arrangement (0 for disable) */
45 | /* Number of USB streaming channels */
46 | #define NUM_USB_CHAN_IN (2) /* Device to Host */
47 | #define NUM_USB_CHAN_OUT (6) /* Host to Device */
48 |
49 | #define OUT_VOLUME_IN_MIXER 0
50 | #define IN_VOLUME_IN_MIXER 0
51 | #define OUT_VOLUME_AFTER_MIX 0
52 | #define IN_VOLUME_AFTER_MIX 0
53 |
54 | #define MAX_MIX_COUNT 8
55 |
56 | /* Define to enable S/PDIF Rx. Note, this also effects glock gen thread and clock unit descriptors */
57 | #if defined(SPDIF_RX) && (SPDIF_RX==0)
58 | #undef SPDIF_RX
59 | #else
60 | // Enabled by default
61 | #define SPDIF_RX 1
62 | #endif
63 |
64 | #define SELF_POWERED 1
65 |
66 | /* Define for CODEC operation mode (i.e. slave/master)*/
67 | #if defined(CODEC_SLAVE) && (CODEC_SLAVE==0)
68 | #undef CODEC_SLAVE
69 | #else
70 | // Enabled by default
71 | #define CODEC_SLAVE 1
72 | #endif
73 |
74 | /* Define for enabling mixer interface */
75 | #if defined(MIXER) && (MIXER==0)
76 | #undef MIXER
77 | #else
78 | // Enabled by default
79 | #define MIXER
80 | #endif
81 |
82 | /* Number of IS2 chans to DAC..*/
83 | #define I2S_CHANS_DAC (8)
84 |
85 | /* Number of I2S chans from ADC */
86 | #define I2S_CHANS_ADC (6)
87 |
88 | /* Master clock defines (in Hz) */
89 | #define MCLK_441 (256*44100) /* 44.1, 88.2 etc */
90 | #define MCLK_48 (256*48000) /* 48, 96 etc */
91 |
92 | /* Maximum frequency device runs at */
93 | #define MAX_FREQ (96000)
94 |
95 | /* Default frequency device reports as running at */
96 | #define DEFAULT_FREQ (MAX_FREQ)
97 |
98 | /***** Defines relating to USB descriptors etc *****/
99 | #define VENDOR_STR "XMOS "
100 | #define VENDOR_ID (0x20B1) /* XMOS VID */
101 | #define PID_AUDIO_1 (0x0005)
102 | #define PID_AUDIO_2 (0x0004)
103 | #ifndef BCD_DEVICE
104 | #define BCD_DEVICE (0x0530) /* Device release number in BCD: 0xJJMN
105 | * JJ: Major, M: Minor, N: Sub-minor */
106 | #endif
107 |
108 | //#define LEVEL_METER_PROCESSING 1
109 | //#define LEVEL_METER_LEDS 1 /* Enables call to VendorLedRefresh() */
110 | //#define CLOCK_VALIDITY_CALL 1 /* Enables calls to VendorClockValidity(int valid) */
111 | #define HOST_ACTIVE_CALL 1 /* Enabled call to VendorHostActive(int active); */
112 |
113 | #ifdef HOST_ACTIVE_CALL /* L2 ref design board uses audio core reqs for host active */
114 | /*
115 | #ifndef VENDOR_AUDCORE_REQS
116 | #define VENDOR_AUDCORE_REQS 1
117 | #endif
118 |
119 | #ifndef VENDOR_AUDIO_REQS
120 | #define VENDOR_AUDIO_REQS 1
121 | #endif
122 | */
123 | #endif
124 |
125 | //#define MAX_MIX_OUTPUTS 0
126 |
127 |
128 | #ifdef SPDIF_RX
129 | # define SPDIF_RX_INDEX 6
130 | # define SPDIF_CHANS 2
131 | # define SPDIF_CLOCKS 1
132 | #else
133 | # define SPDIF_CHANS 0
134 | # define SPDIF_CLOCKS 0
135 | #endif
136 |
137 | #define MIX_INPUTS (NUM_USB_CHAN_OUT + I2S_CHANS_ADC + SPDIF_CHANS)
138 | #define IN_CHANNELS (I2S_CHANS_ADC + SPDIF_CHANS)
139 | #define AUX_COUNT (IN_CHANNELS / 2)
140 | #define NUM_CLOCKS (1 + SPDIF_CLOCKS)
141 |
142 | #endif
143 |
--------------------------------------------------------------------------------
/firmware/codec.xc:
--------------------------------------------------------------------------------
1 | /**
2 | * Module: app_usb_aud_l2
3 | * Version: 3v00
4 | * Build: 89ae0a5f3b92ea061d7202203563a40eef315ca4
5 | * File: codec.xc
6 | *
7 | * The copyrights, all other intellectual and industrial
8 | * property rights are retained by XMOS and/or its licensors.
9 | * Terms and conditions covering the use of this code can
10 | * be found in the Xmos End User License Agreement.
11 | *
12 | * Copyright XMOS Ltd 2010
13 | *
14 | * In the case where this code is a modification of existing code
15 | * under a separate license, the separate license terms are shown
16 | * below. The modifications to the code are still covered by the
17 | * copyright notice above.
18 | *
19 | **/
20 | #include "devicedefines.h"
21 | #include "i2c.h"
22 | #include
23 |
24 | /* I2C ports */
25 | extern port p_i2c_sda;
26 | extern port p_i2c_scl;
27 |
28 | extern out port p_aud_cfg;
29 |
30 | #define COD_DEV_ADRS 0x90
31 | #define SYNC_DEV_ADRS 0x9C
32 |
33 | /* CODEC initialisation for Cirrus Logic CS42448 */
34 | void CodecInit(chanend ?c_codec)
35 | {
36 | unsigned tmp;
37 |
38 | /* Clock buffers and CODEC out of reset */
39 | #ifdef CODEC_SLAVE
40 | p_aud_cfg <: 0b0000 @ tmp;
41 | tmp += 1000;
42 | p_aud_cfg @ tmp <: 0b1000;
43 | #else
44 | p_aud_cfg <: 0b0010 @ tmp;
45 | tmp += 1000;
46 | p_aud_cfg @ tmp <: 0b1010;
47 | #endif
48 |
49 | /* Power Control Register (Address 02h) */
50 | /* 0 Power Down (PDN) = 1 Enable, 0 Disable */
51 | /* 1:4 Power Down DAC Pairs (PDN_DACX) = 1 Enable, 0 Disable */
52 | /* 5:7 Power Down ADC Pairs (PDN_ADCX) = 1 Enable, 0 Disable */
53 | tmp = 0x01;
54 | I2cRegWrite(COD_DEV_ADRS, 0x2, tmp, p_i2c_scl, p_i2c_sda);
55 |
56 | /* Interface Formats Register (Address 04h) */
57 | /* 0 Freeze Controls (FREEZE) = 0, */
58 | /* 1 Auxiliary Digital Interface Format (AUX_DIF) = 0, */
59 | /* 2:4 DAC Digital Interface Format (DAC_DIF) = 001 (I2S) */
60 | /* 5:7 ADC Digital Interface Format (ADC_DIF) = 001 (I2S) */
61 | tmp = 0x09;
62 | I2cRegWrite(COD_DEV_ADRS, 0x4, tmp, p_i2c_scl, p_i2c_sda);
63 |
64 | tmp = (-12) & 0xff;
65 | I2cRegWrite(COD_DEV_ADRS, 0x11, tmp, p_i2c_scl, p_i2c_sda);
66 | I2cRegWrite(COD_DEV_ADRS, 0x12, tmp, p_i2c_scl, p_i2c_sda);
67 | I2cRegWrite(COD_DEV_ADRS, 0x13, tmp, p_i2c_scl, p_i2c_sda);
68 | I2cRegWrite(COD_DEV_ADRS, 0x14, tmp, p_i2c_scl, p_i2c_sda);
69 | I2cRegWrite(COD_DEV_ADRS, 0x15, tmp, p_i2c_scl, p_i2c_sda);
70 | I2cRegWrite(COD_DEV_ADRS, 0x16, tmp, p_i2c_scl, p_i2c_sda);
71 |
72 | /* ADC Control & DAC De-Emphasis (Address 05h) */
73 | /* 0 ADC1-2_HPF FREEZE = 0, */
74 | /* 1 ADC3_HPF FREEZE = 0, */
75 | /* 2 DAC_DEM = 0, */
76 | /* 3 ADC1_SINGLE = 1(single ended), */
77 | /* 4 ADC2_SINGLE = 1, */
78 | /* 5 ADC3_SINGLE = 1, */
79 | /* 6 AIN5_MUX = 0, */
80 | /* 7 AIN6_MUX = 0 */
81 | tmp = 0x1C;
82 | I2cRegWrite(COD_DEV_ADRS, 0x5, tmp, p_i2c_scl, p_i2c_sda);
83 |
84 | /* Power Control Register (Address 02h) - PDN disable */
85 | tmp = 0x00;
86 | I2cRegWrite(COD_DEV_ADRS, 0x2, tmp, p_i2c_scl, p_i2c_sda);
87 |
88 | }
89 |
90 | /* CODEC configuration for sample frequency change for Cirrus Logic CS42448 */
91 | void CodecConfig(unsigned samFreq, unsigned mClk, chanend ?c_codec)
92 | {
93 | unsigned tmp;
94 |
95 | /* Functional Mode (Address 03h) */
96 | /* 0:1 DAC Functional Mode Slave:Auto-detect samp rate 11 */
97 | /* 2:3 ADC Functional Mode Slave:Auto -detect samp rate 11 */
98 | /* Master: Single 00 */
99 | /* Master: Double 01 */
100 | /* Master: Quad 10 */
101 | /* 4:6 MCLK Frequency 256/128/64 : 000 */
102 | /* 512/256/128: 010 */
103 | /* 7 Reserved */
104 | #ifdef CODEC_SLAVE
105 | tmp = 0b11110000; /* Autodetect */
106 | #else
107 | if(samFreq < 50000)
108 | {
109 | tmp = 0b00000000;
110 | }
111 | else if(samFreq < 100000)
112 | {
113 | tmp = 0b01010000;
114 | }
115 | else
116 | {
117 | tmp = 0b10100000;
118 | }
119 | #endif
120 | if(mClk < 15000000)
121 | {
122 | tmp |= 0; // 256/128/64
123 | }
124 | else if(mClk < 25000000)
125 | {
126 | tmp |= 0b00000100; // 512/256/128
127 | }
128 | else
129 | {
130 | printstrln("Err: MCLK currently not supported");
131 | }
132 |
133 | I2cRegWrite(COD_DEV_ADRS, 0x3, tmp, p_i2c_scl, p_i2c_sda);
134 | }
135 |
136 |
--------------------------------------------------------------------------------
/firmware/audioports.xc:
--------------------------------------------------------------------------------
1 | /**
2 | * Module: module_usb_aud_shared
3 | * Version: 2v1
4 | * Build: 16d27b9745fbee4dd7f17ad8d31813326cea9187
5 | * File: audioports.xc
6 | *
7 | * The copyrights, all other intellectual and industrial
8 | * property rights are retained by XMOS and/or its licensors.
9 | * Terms and conditions covering the use of this code can
10 | * be found in the Xmos End User License Agreement.
11 | *
12 | * Copyright XMOS Ltd 2010
13 | *
14 | * In the case where this code is a modification of existing code
15 | * under a separate license, the separate license terms are shown
16 | * below. The modifications to the code are still covered by the
17 | * copyright notice above.
18 | *
19 | **/
20 | #include
21 | #include "devicedefines.h"
22 | #include "audioports.h"
23 |
24 | /* Audio IOs */
25 |
26 | #if (I2S_CHANS_DAC != 0)
27 | extern buffered out port:32 p_i2s_dac[I2S_WIRES_DAC];
28 | #endif
29 |
30 | #if (I2S_CHANS_ADC != 0)
31 | extern buffered in port:32 p_i2s_adc[I2S_WIRES_ADC];
32 | #endif
33 |
34 | #if (I2S_CHANS_DAC != 0) || (I2S_CHANS_ADC != 0)
35 | #ifdef CODEC_SLAVE
36 | extern buffered out port:32 p_lrclk;
37 | extern buffered out port:32 p_bclk;
38 | #else
39 | extern in port p_lrclk;
40 | extern in port p_bclk;
41 | #endif
42 | #endif
43 |
44 | extern port p_mclk;
45 |
46 | extern clock clk_audio_mclk;
47 | extern clock clk_audio_bclk;
48 |
49 | void ConfigAudioPorts(unsigned int divide)
50 | {
51 |
52 | #ifdef CODEC_SLAVE
53 | /* Output 0 on BCLK to ensure clock is low
54 | * Required as stop_clock will only complete when the clock is low
55 | */
56 | configure_out_port_no_ready(p_bclk, clk_audio_mclk, 0);
57 | p_bclk <: 0;
58 |
59 | /* Stop bit and master clock blocks and clear port buffers */
60 | stop_clock(clk_audio_bclk);
61 | stop_clock(clk_audio_mclk);
62 |
63 | clearbuf(p_lrclk);
64 | clearbuf(p_bclk);
65 |
66 | #if (I2S_CHANS_ADC != 0)
67 | for(int i = 0; i < I2S_WIRES_ADC; i++)
68 | {
69 | clearbuf(p_i2s_adc[i]);
70 | }
71 | #endif
72 |
73 | #if (I2S_CHANS_DAC != 0)
74 | for(int i = 0; i < I2S_WIRES_DAC; i++)
75 | {
76 | clearbuf(p_i2s_dac[i]);
77 | }
78 | #endif
79 |
80 | /* Clock master clock-block from master-clock port */
81 | configure_clock_src(clk_audio_mclk, p_mclk);
82 |
83 | /* For a divide of one (i.e. bitclock == master-clock) BClk is set to clock_output mode.
84 | * In this mode it outputs an edge clock on every tick of itsassociated clock_block.
85 | *
86 | * For all other divides, BClk is clocked by the master clock and data
87 | * will be output to p_bclk to generate the bit clock.
88 | */
89 | if (divide == 1) /* e.g. 176.4KHz from 11.2896 */
90 | {
91 | configure_port_clock_output(p_bclk, clk_audio_mclk);
92 | }
93 | else
94 | {
95 | /* bit clock port from master clock clock-clock block */
96 | configure_out_port_no_ready(p_bclk, clk_audio_mclk, 0);
97 | }
98 |
99 | /* Generate bit clock block from pin */
100 | configure_clock_src(clk_audio_bclk, p_bclk);
101 |
102 |
103 | #if (I2S_CHANS_DAC != 0)
104 | /* Clock I2S output data ports from clock block */
105 | for(int i = 0; i < I2S_WIRES_DAC; i++)
106 | {
107 | configure_out_port_no_ready(p_i2s_dac[i], clk_audio_bclk, 0);
108 | }
109 | #endif
110 |
111 | #if (I2S_CHANS_ADC != 0)
112 | /* Clock I2S input data ports from clock block */
113 | for(int i = 0; i < I2S_WIRES_ADC; i++)
114 | {
115 | configure_in_port_no_ready(p_i2s_adc[i], clk_audio_bclk);
116 | }
117 | #endif
118 |
119 | /* Clock LR clock from bit clock-block */
120 | configure_out_port_no_ready(p_lrclk, clk_audio_bclk, 0);
121 |
122 | /* Start clock blocks ticking */
123 | start_clock(clk_audio_mclk);
124 | start_clock(clk_audio_bclk);
125 |
126 | /* bclk initial state needs to be high */
127 | p_bclk <: 0xFFFFFFFF;
128 |
129 | /* Pause until output completes */
130 | sync(p_bclk);
131 |
132 | #else
133 | /* Stop bit and master clock blocks and clear port buffers */
134 | stop_clock(clk_audio_bclk);
135 | stop_clock(clk_audio_mclk);
136 |
137 | /* Clock bclk clock-block from bclk pin */
138 | configure_clock_src(clk_audio_bclk, p_bclk);
139 |
140 | /* Clock I2S output data ports from b-clock clock block */
141 | for(int i = 0; i < I2S_WIRES_DAC; i++)
142 | {
143 | configure_out_port_no_ready(p_i2s_dac[i], clk_audio_bclk, 0);
144 | }
145 |
146 | /* Clock I2S input data ports from clock block */
147 | for(int i = 0; i < I2S_WIRES_ADC; i++)
148 | {
149 | configure_in_port_no_ready(p_i2s_adc[i], clk_audio_bclk);
150 | }
151 |
152 | configure_in_port_no_ready(p_lrclk, clk_audio_bclk);
153 |
154 | start_clock(clk_audio_bclk);
155 |
156 | #endif
157 | }
158 |
--------------------------------------------------------------------------------
/firmware/audio.xn:
--------------------------------------------------------------------------------
1 |
2 |
5 | Board
6 | USB 2.0 MC + DSP
7 |
8 |
9 | core stdcore[3]
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
--------------------------------------------------------------------------------
/firmware/dbcalc.xc:
--------------------------------------------------------------------------------
1 | /**
2 | * Module: module_usb_aud_shared
3 | * Version: 2v2beta10
4 | * Build: d009d5bec140a80ab4e4bcbdb79b157bd8f6a4ea
5 | * File: dbcalc.xc
6 | *
7 | * The copyrights, all other intellectual and industrial
8 | * property rights are retained by XMOS and/or its licensors.
9 | * Terms and conditions covering the use of this code can
10 | * be found in the Xmos End User License Agreement.
11 | *
12 | * Copyright XMOS Ltd 2010
13 | *
14 | * In the case where this code is a modification of existing code
15 | * under a separate license, the separate license terms are shown
16 | * below. The modifications to the code are still covered by the
17 | * copyright notice above.
18 | *
19 | **/
20 | #include
21 | #include
22 | /* The coefficients of the chebychev polynomial to approximate 10^x in the interval [-1,1].
23 | This polynomial was calculated using the mpmath library in Python:
24 |
25 | from mpmath import *
26 | mp.dps = 15
27 | mp.pretty = True
28 | poly, err = chebyfit(lambda x: pow(10,x), [-1,1], 14, error=True)
29 | nprint([int(x * pow(2,28)) for x in poly])
30 | */
31 | #define COEF_PREC 28
32 | static unsigned coef[14] = {2407, 13778, 64588, 308051, 1346110, 5261991, 18277531, 55564576, 144789513, 314406484, 546179875, 711608713, 618095479, 268435456};
33 |
34 | #define DB_CALC_PREC 28
35 |
36 | /* Function: db_to_mult
37 |
38 | This function converts decibels into a volume multiplier. It uses a fixed-point polynomial approximation
39 | to 10^(db/10).
40 |
41 | Parameters:
42 | db - The db value to convert.
43 | db_frac_bits - The number of binary fractional bits in the supplied decibel value
44 | result_frac_bits - The number of required fractional bits in the result.
45 |
46 | Returns:
47 | The multiplier value as a fixed point value with the number of fractional bits as specified by
48 | the result_frac_bits parameter.
49 | */
50 | unsigned db_to_mult(int db, int db_frac_bits, int result_frac_bits)
51 | {
52 | int intpart;
53 | int val = 0;
54 | int val0=0;
55 | unsigned ret;
56 | unsigned mask = ~((1<> DB_CALC_PREC;
78 |
79 | if (intpart) {
80 | val0 = 1 << DB_CALC_PREC;
81 | for (int i=0;i> DB_CALC_PREC;
89 | if (intpart) {
90 | val0 = 1 << DB_CALC_PREC;
91 | for (int i=0;i> DB_CALC_PREC);
106 | val += coef[i] >> (COEF_PREC - DB_CALC_PREC);
107 | }
108 |
109 | /* Finally multiply by the integer power (if there was an integer part) */
110 | if (val0) {
111 | int hi=0;
112 | unsigned lo=0;
113 |
114 | {hi, lo} = macs(val0,val,hi,lo);
115 | val = (hi << (32-DB_CALC_PREC)) | (lo >> DB_CALC_PREC);
116 | }
117 |
118 |
119 | /* We now have the result, just need to scale it to the required precision */
120 | ret = val;
121 |
122 | if (result_frac_bits > DB_CALC_PREC) {
123 | return ret<<(result_frac_bits-DB_CALC_PREC);
124 | }
125 | else {
126 | return ret>>(DB_CALC_PREC-result_frac_bits);
127 | }
128 | }
129 |
130 | #ifdef TEST_DBCALC
131 | #include
132 |
133 | int main() {
134 |
135 | /* Check that we don't overflow up to 9db
136 | Should give a value just under 0x80000 */
137 | printhexln(db_to_mult(9,0,16));
138 |
139 | /* This test recreates the old db lookup table */
140 | printuintln(0xffffffff);
141 | for (int i=1;i<128;i++) {
142 | printuintln(db_to_mult(-i,0,32));
143 | }
144 | return 0;
145 | }
146 | #endif
147 |
--------------------------------------------------------------------------------
/firmware/mixer.xc:
--------------------------------------------------------------------------------
1 | /**
2 | * Module: module_usb_aud_shared
3 | * Version: 2v3
4 | * Build: b8b701010296296860417a33c03ee283d2b4ad97
5 | * File: mixer.xc
6 | *
7 | * The copyrights, all other intellectual and industrial
8 | * property rights are retained by XMOS and/or its licensors.
9 | * Terms and conditions covering the use of this code can
10 | * be found in the Xmos End User License Agreement.
11 | *
12 | * Copyright XMOS Ltd 2010
13 | *
14 | * In the case where this code is a modification of existing code
15 | * under a separate license, the separate license terms are shown
16 | * below. The modifications to the code are still covered by the
17 | * copyright notice above.
18 | *
19 | **/
20 |
21 |
22 | #include
23 | #include
24 | #include
25 | #include "mixer.h"
26 | #include "devicedefines.h"
27 |
28 | #define LDW(dest, array, index) asm("ldw %0, %1[%2]":"=r"(dest):"r"(array),"r"(index))
29 | #define STW(array, index, value) asm("stw %0, %1[%2]"::"r"(value),"r"(array),"r"(index))
30 |
31 | #ifdef MIXER
32 |
33 | #define FAST_MIXER 1
34 |
35 | static int mix_in_samples[MIX_INPUTS];
36 | static int mix_out_samples[MAX_MIX_COUNT];
37 | static int aux_in_samples[2][AUX_COUNT];
38 | static int usb_in_samples[NUM_USB_CHAN_IN];
39 |
40 | static int mix_mult[MAX_MIX_COUNT][MIX_INPUTS];
41 | static int in_mix_mult[2][AUX_COUNT];
42 | static int aux_balanced[AUX_COUNT];
43 |
44 | static int input_map[NUM_USB_CHAN_OUT] = {
45 | 0, 1, 4, 5, 2, 3,
46 | };
47 |
48 | static int output_map[MAX_MIX_COUNT] = {
49 | 6, 7, 0, 1, 2, 3, 4, 5,
50 | };
51 |
52 | int doMix_out(const int samples[], int mult[]);
53 | int doMix_in(const int samples[], int mult[]);
54 |
55 | #pragma unsafe arrays
56 | void giveSamplesToHost(chanend c)
57 | {
58 | #pragma loop unroll
59 | for (int i = 0; i < NUM_USB_CHAN_IN; i++)
60 | outuint(c, usb_in_samples[i]);
61 | }
62 |
63 | #pragma unsafe arrays
64 | static void getSamplesFromHost(chanend c)
65 | {
66 | #pragma loop unroll
67 | for (int i = 0; i < NUM_USB_CHAN_OUT; i++)
68 | STW(mix_in_samples, input_map[i], inuint(c));
69 | }
70 |
71 | #pragma unsafe arrays
72 | static void giveSamplesToDevice(chanend c)
73 | {
74 | #pragma loop unroll
75 | for (int i = 0; i < MAX_MIX_COUNT; i++)
76 | outuint(c, mix_out_samples[output_map[i]]);
77 | }
78 |
79 | #pragma unsafe arrays
80 | static void getSamplesFromDevice(chanend c)
81 | {
82 | #pragma loop unroll
83 | for (int i = 0; i < IN_CHANNELS; i++)
84 | STW(mix_in_samples, i + NUM_USB_CHAN_OUT, inuint(c));
85 | }
86 |
87 | #pragma unsafe arrays
88 | void mixer1(chanend c_host, chanend c_mix_ctl, chanend c_mixer2)
89 | {
90 | int mixed;
91 | unsigned cmd;
92 |
93 | while (1) {
94 | inuint(c_mixer2);
95 |
96 | /* Request data from decouple thread */
97 | outuint(c_host, 0);
98 |
99 | /* Between request to decouple and respose ~ 400nS latency for interrupt to fire */
100 | select
101 | {
102 | case inuint_byref(c_mix_ctl, cmd):
103 | {
104 | int mix, index, val;
105 | switch (cmd)
106 | {
107 | case SET_MIX_MULT:
108 | for (int i = 0; i < MAX_MIX_COUNT; i++) {
109 | for (int j = 0; j < MIX_INPUTS; j++) {
110 | STW(mix_mult[i], j, inuint(c_mix_ctl));
111 | }
112 | }
113 | for (int i = 0; i < 2; i++) {
114 | for (int j = 0; j < AUX_COUNT; j++) {
115 | STW(in_mix_mult[i], j, inuint(c_mix_ctl));
116 | }
117 | }
118 | for (int i = 0; i < AUX_COUNT; i++) {
119 | STW(aux_balanced, i, inuint(c_mix_ctl));
120 | }
121 | inct(c_mix_ctl);
122 | break;
123 | }
124 | break;
125 | }
126 | default:
127 | /* Select default */
128 | break;
129 | }
130 |
131 | inuint(c_host);
132 | outuint(c_mixer2, 0);
133 | giveSamplesToHost(c_host);
134 |
135 | outuint(c_mixer2, 0);
136 | inuint(c_mixer2);
137 | getSamplesFromHost(c_host);
138 | outuint(c_mixer2, 0);
139 | inuint(c_mixer2);
140 |
141 | mixed = doMix_out(mix_in_samples, mix_mult[0]);
142 | STW(mix_out_samples, 0, mixed);
143 | #if MAX_MIX_COUNT > 2
144 | mixed = doMix_out(mix_in_samples, mix_mult[2]);
145 | STW(mix_out_samples, 2, mixed);
146 | #endif
147 | #if MAX_MIX_COUNT > 4
148 | mixed = doMix_out(mix_in_samples, mix_mult[4]);
149 | STW(mix_out_samples, 4, mixed);
150 | #endif
151 | #if MAX_MIX_COUNT > 6
152 | mixed = doMix_out(mix_in_samples, mix_mult[6]);
153 | STW(mix_out_samples, 6, mixed);
154 | #endif
155 | for (int i = 0; i < AUX_COUNT; i++)
156 | STW(aux_in_samples[0], i, mix_in_samples[6 + i * 2]);
157 | mixed = doMix_in(aux_in_samples[0], in_mix_mult[0]);
158 | STW(usb_in_samples, 0, mixed);
159 | }
160 | }
161 |
162 | #pragma unsafe arrays
163 | void mixer2(chanend c_mixer1, chanend c_audio)
164 | {
165 | int mixed;
166 |
167 | while (1) {
168 | outuint(c_mixer1, 0);
169 | inuint(c_audio);
170 | (void) inuint(c_mixer1);
171 | giveSamplesToDevice(c_audio);
172 | inuint(c_mixer1);
173 | outuint(c_mixer1, 0);
174 | getSamplesFromDevice(c_audio);
175 | #pragma loop unroll
176 | for (int i = 0; i < AUX_COUNT; i++) {
177 | int off = i*2 + NUM_USB_CHAN_OUT;
178 | if (aux_balanced[i]) {
179 | int p = mix_in_samples[off] >> 1;
180 | int m = mix_in_samples[off+1] >> 1;
181 | int r = p - m;
182 | STW(mix_in_samples, off, r);
183 | STW(mix_in_samples, off+1, r);
184 | }
185 | }
186 | inuint(c_mixer1);
187 | outuint(c_mixer1, 0);
188 |
189 | #if MAX_MIX_COUNT > 1
190 | mixed = doMix_out(mix_in_samples, mix_mult[1]);
191 | STW(mix_out_samples, 1, mixed);
192 | #endif
193 | #if MAX_MIX_COUNT > 3
194 | mixed = doMix_out(mix_in_samples, mix_mult[3]);
195 | STW(mix_out_samples, 3, mixed);
196 | #endif
197 | #if MAX_MIX_COUNT > 5
198 | mixed = doMix_out(mix_in_samples, mix_mult[5]);
199 | STW(mix_out_samples, 5, mixed);
200 | #endif
201 | #if MAX_MIX_COUNT > 7
202 | mixed = doMix_out(mix_in_samples, mix_mult[7]);
203 | STW(mix_out_samples, 7, mixed);
204 | #endif
205 | for (int i = 0; i < AUX_COUNT; i++)
206 | STW(aux_in_samples[1], i, mix_in_samples[7 + i * 2]);
207 | mixed = doMix_in(aux_in_samples[1], in_mix_mult[1]);
208 | STW(usb_in_samples, 1, mixed);
209 | }
210 | }
211 |
212 | void mixer(chanend c_mix_in, chanend c_mix_out, chanend c_mix_ctl)
213 | {
214 | chan c;
215 | for (int i = 0; i < MIX_INPUTS; i++)
216 | mix_in_samples[i] = 0;
217 | for (int i = 0; i < MAX_MIX_COUNT; i++)
218 | mix_out_samples[i] = 0;
219 | for (int i = 0; i < NUM_USB_CHAN_IN; i++)
220 | usb_in_samples[i] = 0;
221 |
222 | for (int i = 0; i < MAX_MIX_COUNT; i++) {
223 | for (int j = 0;j < MIX_INPUTS; j++) {
224 | mix_mult[i][j] = 0;
225 | }
226 | }
227 | for (int i = 0; i < 2; i++) {
228 | for (int j = 0; j < AUX_COUNT; j++) {
229 | in_mix_mult[i][j] = 0;
230 | }
231 | }
232 | for (int i = 0; i < AUX_COUNT; i++)
233 | aux_balanced[i] = 0;
234 | par {
235 | mixer1(c_mix_in, c_mix_ctl, c);
236 | mixer2(c, c_mix_out);
237 | }
238 | }
239 |
240 | #endif
241 |
--------------------------------------------------------------------------------
/firmware/XUD_EpFunctions.xc:
--------------------------------------------------------------------------------
1 | /**
2 | * Module: module_xud
3 | * Version: 0v28
4 | * Build: 82d90eaec387c8d8d70f373b60f30ed4792d7bbd
5 | * File: XUD_EpFunctions.xc
6 | *
7 | * The copyrights, all other intellectual and industrial
8 | * property rights are retained by XMOS and/or its licensors.
9 | * Terms and conditions covering the use of this code can
10 | * be found in the Xmos End User License Agreement.
11 | *
12 | * Copyright XMOS Ltd 2010
13 | *
14 | * In the case where this code is a modification of existing code
15 | * under a separate license, the separate license terms are shown
16 | * below. The modifications to the code are still covered by the
17 | * copyright notice above.
18 | *
19 | **/
20 | /** @file XUD_EPFunctions.xc
21 | * @brief Implementation of user API fuctions. See xud.h for documentation.
22 | * @author Ross Owen, XMOS Limited
23 | * @version 0.9
24 | **/
25 |
26 | #include
27 | #include
28 |
29 | #include "xud.h"
30 | #include "usb.h"
31 |
32 | #if 0
33 | #pragma xta command "analyse path XUD_SetData_DataRdy XUD_SetData_OutputLoop_Out"
34 | #pragma xta command "set required - 266 ns"
35 |
36 | #endif
37 |
38 |
39 | static int min(int x, int y)
40 | {
41 | if (x < y)
42 | return x;
43 | return y;
44 | }
45 |
46 | void XUD_ParseSetupPacket(unsigned char b[], SetupPacket &p)
47 | {
48 | // Byte 0: bmRequestType.
49 | p.bmRequestType.Recipient = b[0] & 0x1f;
50 | p.bmRequestType.Type = (b[0] & 0x60) >> 5;
51 | p.bmRequestType.Direction = b[0] >> 7;
52 |
53 | // Byte 1: bRequest
54 | p.bRequest = b[1];
55 |
56 | // Bytes [2:3] wValue
57 | p.wValue = (b[3] << 8) | (b[2]);
58 |
59 | // Bytes [4:5] wIndex
60 | p.wIndex = (b[5] << 8) | (b[4]);
61 |
62 | // Bytes [6:7] wLength
63 | p.wLength = (b[7] << 8) | (b[6]);
64 |
65 | }
66 |
67 | void XUD_PrintSetupPacket(SetupPacket sp)
68 | {
69 | printstr("Setup data\n");
70 | printstr("bmRequestType.Recipient: ");
71 | printhexln(sp.bmRequestType.Recipient);
72 | printstr("bmRequestType.Type: ");
73 | printhexln(sp.bmRequestType.Type);
74 | printstr("bmRequestType.Direction: ");
75 | printhexln(sp.bmRequestType.Direction);
76 | printstr("bRequest: ");
77 | printhexln(sp.bRequest);
78 | printstr("bmRequestType.wValue: ");
79 | printhexln(sp.wValue);
80 | printstr("bmRequestType.wIndex: ");
81 | printhexln(sp.wIndex);
82 | printstr("bmRequestType.wLength: ");
83 | printhexln(sp.wLength);
84 | }
85 |
86 | /** XUD_GetBuffer_()
87 | * @brief Requests data from the endpoint related to the passed channel
88 | * @param c Channel to USB I/O thread for this endpoint
89 | * @param buffer Buffer for returned data
90 | * @return datalength of received data in bytes
91 | **/
92 | int XUD_GetBuffer(XUD_ep c, unsigned char buffer[])
93 | {
94 | return XUD_GetData(c, buffer);
95 | }
96 |
97 |
98 | /** XUD_GetSetupBuffer()
99 | * @brief Request setup data from usb buffer for a specific EP, pauses until data is available.
100 | * @param c Data channel to/from XUD
101 | * @param c_ctl Control channel from XUD
102 | * @param epNum EP number
103 | * @param buffer char buffer passed by ref into which data is returned
104 | * @return datalength in bytes (always 8), -1 if kill received
105 | **/
106 | int XUD_GetSetupBuffer(XUD_ep c_out, unsigned char buffer[])
107 | {
108 | return XUD_GetSetupData(c_out, buffer);
109 | }
110 |
111 |
112 |
113 |
114 | /** XUD_SetBuffer_ResetPid(()
115 | * @brief Sends USB data with PID reset to specified
116 | * @param c
117 | * @param epNum
118 | * @param buffer
119 | * @param datalengh in bytes!
120 | **/
121 | int XUD_SetBuffer_ResetPid(XUD_ep c, unsigned char buffer[], unsigned datalength, unsigned char pid)
122 | {
123 | return XUD_SetData(c, buffer, datalength, 0, pid);
124 | }
125 |
126 | int XUD_SetBuffer(XUD_ep c, unsigned char buffer[], unsigned datalength)
127 | {
128 | /* No PID reset, 0 start index */
129 | return XUD_SetData(c, buffer, datalength, 0, 0);
130 | }
131 |
132 |
133 |
134 |
135 | /* Datalength in bytes */
136 | int XUD_SetBuffer_ResetPid_EpMax(XUD_ep c, unsigned epNum, unsigned char buffer[],
137 | unsigned datalength, unsigned epMax, unsigned char pid)
138 | {
139 | int i = 0;
140 |
141 | /* Note: We could encompass this in the SetData function */
142 | if(datalength <= epMax)
143 | {
144 | /* Datalength is less than the maximum per transaction of the EP, so just send */
145 | return XUD_SetData(c, buffer, datalength, 0, pid);
146 | }
147 | else
148 | {
149 | /* Send first packet out and reset PID */
150 | if (XUD_SetData(c, buffer, epMax, 0, pid) < 0) return -1;
151 | i+= epMax;
152 | datalength-=epMax;
153 |
154 | while(1)
155 | {
156 |
157 | if(datalength > epMax)
158 | {
159 | /* PID Automatically toggled */
160 | if (XUD_SetData(c, buffer, epMax, i, 0) < 0) return -1;
161 |
162 | datalength-=epMax;
163 | i += epMax;
164 | }
165 | else
166 | {
167 | /* PID automatically toggled */
168 | if (XUD_SetData(c, buffer, datalength, i, 0) < 0) return -1;
169 |
170 | break; //out of while loop
171 | }
172 | }
173 | }
174 |
175 | return 0;
176 | }
177 |
178 |
179 |
180 | /* TODO Should take ep max length as a param - currently hardcoded as 64 */
181 | int XUD_DoGetRequest(XUD_ep c, XUD_ep c_in, uint8 buffer[], unsigned length, unsigned requested)
182 | {
183 | unsigned char tmpBuffer[1024];
184 |
185 | if (XUD_SetBuffer_ResetPid_EpMax(c_in, 0, buffer, min(length, requested), 64, PIDn_DATA1) < 0)
186 | {
187 | return -1;
188 | }
189 |
190 | /* USB 2.0 8.5.3.2 */
191 | if((requested > length) && (length % 64) == 0)
192 | {
193 | XUD_SetBuffer(c_in, tmpBuffer, 0);
194 | }
195 |
196 | /* Status stage */
197 | return XUD_GetData(c, tmpBuffer);
198 | }
199 |
200 |
201 | /* Send 0 length status
202 | * Simply sends a 0 length packet */
203 | //TODO dont need epNum
204 | int XUD_DoSetRequestStatus(XUD_ep c, unsigned epNum)
205 | {
206 | unsigned char tmp[8];
207 |
208 | return XUD_SetData(c, tmp, 0, 0, PIDn_DATA1);
209 | }
210 |
211 | #ifdef XUD_DEBUG_VERSION
212 | void XUD_Error(char errString[])
213 | {
214 | printstr("XUD Err: ");
215 | printstr(errString);
216 | }
217 |
218 | void XUD_Error_hex(char errString[], int i_err)
219 | {
220 | printstr("XUD Err: ");
221 | printstr(errString);
222 | printhexln(i_err);
223 | }
224 | #endif
225 |
226 |
227 | //???
228 | int XUD_ResetEndpoint0(chanend one, chanend ?two)
229 | {
230 | int busStateCt;
231 | int busSpeed;
232 |
233 |
234 |
235 | outct(one, XS1_CT_END);
236 | busStateCt = inct(one);
237 |
238 | if (!isnull(two))
239 | {
240 | outct(two, XS1_CT_END);
241 | inct(two);
242 | }
243 |
244 | /* Inspect for reset, if so we expect a CT with speed */
245 | if(busStateCt == USB_RESET_TOKEN)
246 | {
247 | busSpeed = inuint(one);
248 | if(!isnull(two))
249 | {
250 | inuint(two);
251 | }
252 |
253 | return busSpeed;
254 | }
255 | else
256 | {
257 | /* Suspend cond */
258 | /* TODO Currently suspend condition is never communicated */
259 | return XUD_SUSPEND;
260 | }
261 | }
262 |
263 | XUD_ep XUD_Init_Ep(chanend c)
264 | {
265 | XUD_ep ep = inuint(c);
266 | return ep;
267 | }
268 |
269 |
270 |
--------------------------------------------------------------------------------
/firmware/usb.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Module: module_usb_shared
3 | * Version: 1v15
4 | * Build: ba2d74b0702e5e78a497515f08dfb1ebe601cd36
5 | * File: usb.h
6 | *
7 | * The copyrights, all other intellectual and industrial
8 | * property rights are retained by XMOS and/or its licensors.
9 | * Terms and conditions covering the use of this code can
10 | * be found in the Xmos End User License Agreement.
11 | *
12 | * Copyright XMOS Ltd 2010
13 | *
14 | * In the case where this code is a modification of existing code
15 | * under a separate license, the separate license terms are shown
16 | * below. The modifications to the code are still covered by the
17 | * copyright notice above.
18 | *
19 | **/
20 | /** @file usb.h
21 | * @brief Defines from the Universal Serial Bus Specification Revision 2.0
22 | * @author Ross Owen, XMOS Limited
23 | * @version 1.0
24 | **/
25 |
26 | /* USB Class Codes (from usb.org) */
27 | #define USE_CLASS 0x00 /* Use class information in the interface descriptors */
28 | #define AUDIO 0x01
29 | #define COMMUNICATIONS 0x02
30 | #define HID 0x03
31 | #define PHYSICAL 0x05
32 | #define IMAGE 0x06
33 | #define PRINTER 0x07
34 | #define MASS_STORAGE 0x08
35 | #define HUB 0x09
36 | #define CDC_DATA 0x0A
37 | #define SMART_CARD 0x0B
38 | #define CONTENT_SECURITY 0x0D
39 | #define VIDEO 0x0E
40 | //...
41 | #define VENDOR_SPECIFIC 0x00
42 |
43 |
44 | /* Table 8-1. PID Types */
45 | #define OUT 0x1 /* Tokens */
46 | #define IN 0x9
47 | #define SOF 0x5
48 | #define SETUP 0xD
49 | #define DATA0 0x3 /* Data packet PID even */
50 | #define DATA1 0xB /* Data packet PID odd */
51 | #define DATA2 0x7 /* Data packet PID high-speed, high bandwidth isoc transaction in a microframe */
52 | #define MDATA 0xF /* Data packet PID high-speed and high bandwidth isoc transactions */
53 | #define ACK 0x2 /* Receiver accepts error-free data packet */
54 | #define NAK 0xA /* Receiving device cannot accept data of transmitting device cannot send data */
55 | #define STALL 0xE /* Endpoint is halted or a control pipe request is not supported */
56 | #define PRE 0xC
57 | #define ERR 0xC
58 | #define SPLIT 0x8
59 | #define PING 0x4 /* Hign-speed flow control probe for bulk/control endpoint */
60 |
61 |
62 | /* 9.3 USB Device Requests: Table 9-2 Format of Setup Data */
63 | /* bmRequestType: */
64 | #define BM_REQTYPE_DIRECTION_OUT 0 /* Host to device */
65 | #define BM_REQTYPE_DIRECTION_IN 1 /* Device to host */
66 |
67 | #define BM_REQTYPE_TYPE_STANDARD 0x00
68 | #define BM_REQTYPE_TYPE_CLASS 0x01
69 | #define BM_REQTYPE_TYPE_VENDOR 0x02
70 |
71 | #define BM_REQTYPE_RECIP_DEV 0x00
72 | #define BM_REQTYPE_RECIP_INTER 0x01
73 | #define BM_REQTYPE_RECIP_EP 0x02
74 | #define BM_REQTYPE_RECIP_OTHER 0x03
75 |
76 |
77 | /* Table 9-4. Standard Request Codes */
78 | /* bRequest */
79 | #define GET_STATUS 0x00
80 | #define CLEAR_FEATURE 0x01
81 | #define SET_FEATURE 0x03
82 | #define SET_ADDRESS 0x05
83 | #define GET_DESCRIPTOR 0x06
84 | #define SET_DESCRIPTOR 0x07
85 | #define GET_CONFIGURATION 0x08
86 | #define SET_CONFIGURATION 0x09
87 | #define GET_INTERFACE 0x0A
88 | #define SET_INTERFACE 0x0B
89 | #define SYNCH_FRAME 0x0C
90 |
91 |
92 | /* Table 9-5. Descriptor Types */
93 | #define DEVICE 0x01
94 | #define CONFIGURATION 0x02
95 | #define STRING 0x03
96 | #define INTERFACE 0x04
97 | #define ENDPOINT 0x05
98 | #define DEVICE_QUALIFIER 0x06
99 | #define OTHER_SPEED_CONFIGURATION 0x07
100 | #define INTERFACE_POWER 0x08
101 |
102 |
103 | /* Table 9-6. Standard Feature Selectors */
104 | #define DEVICE_REMOTE_WAKEUP 0x01 /* Recipient: Device */
105 | #define ENDPOINT_HALT 0x00 /* Recipient: Endpoint */
106 | #define TEST_MODE 0x02 /* Recipient: Device */
107 |
108 | #define STANDARD_DEVICE_REQUEST 0x00
109 | #define STANDARD_INTERFACE_REQUEST 0x01
110 | #define STANDARD_ENDPOINT_REQUEST 0x02
111 | #define VENDOR_DEVICE_REQUEST 0x40
112 | #define VENDOR_ENDPOINT_REQUEST 0x42
113 | #define CLASS_INTERFACE_REQUEST 0x21
114 | #define CLASS_ENDPOINT_REQUEST 0x22
115 |
116 |
117 |
118 | #define WVAL_EP_HALT 0
119 |
120 |
121 |
122 | // Audio
123 | #define B_REQ_SET_CUR 0x01
124 | #define B_REQ_GET_CUR 0x81
125 | #define B_REQ_GET_MIN 0x82
126 | #define B_REQ_GET_MAX 0x83
127 | #define B_REQ_GET_RES 0x84
128 |
129 | /* wValue for Get Descriptor (indicates required descriptor)
130 | * Note: top byte used only
131 | */
132 | #define WVALUE_GETDESC_DEV (DEVICE << 8)
133 | #define WVALUE_GETDESC_CONFIG (CONFIGURATION << 8)
134 | #define WVALUE_GETDESC_STRING (STRING << 8)
135 | #define WVALUE_GETDESC_INTER (INTERFACE << 8)
136 | #define WVALUE_GETDESC_DEVQUAL (DEVICE_QUALIFIER << 8)
137 | #define WVALUE_GETDESC_OSPEED_CFG (OTHER_SPEED_CONFIGURATION << 8)
138 |
139 | // Low byte values:
140 | #define WVALUE_GETDESC_STRING_LANGIDS 0x0
141 | #define WVALUE_GETDESC_STRING_IPRODUCT 0x2
142 |
143 | //bDeviceClass
144 | #define XUD_DESC_DEV_B_DEVCLASS_INTER 0x0 // Interface descriptor speicifies class
145 | #define XUD_DESC_DEV_B_DEVCLASS_COMMS 0x2 // Communications
146 |
147 | // Defines for Test mode
148 | #define WINDEX_TEST_J 0x1
149 | #define WINDEX_TEST_K 0x2
150 | #define WINDEX_TEST_SE0_NAK 0x3
151 | #define WINDEX_TEST_PACKET 0x4
152 | #define WINDEX_TEST_FORCE_ENABLE 0x5
153 |
154 | //* DEPRECATED DEFINES:
155 | // TODO rm these defines
156 | // Raw PIDs
157 | #define PID_OUT 0x01
158 | #define PID_ACK 0x02
159 | #define PID_IN 0x09
160 | #define PID_SOF 0x05
161 | #define PID_SETUP 0x0d
162 | #define PID_PING 0x04
163 |
164 | // PIDs with error check
165 | // Token
166 | #define PIDn_OUT 0xe1
167 | #define PIDn_IN 0x69
168 | #define PIDn_SOF 0xa5
169 | #define PIDn_SETUP 0x2d
170 |
171 | // Data PIDs
172 | #define PIDn_DATA0 0xc3
173 | #define PIDn_DATA1 0x4b
174 | #define PID_DATA0 0x3
175 | #define PID_DATA1 0xb
176 |
177 | #define PIDn_ACK 0xd2
178 | #define PIDn_NAK 0x5a
179 | #define PIDn_STALL 0x1e
180 |
181 | #if 0
182 | //bRequest
183 | #define B_REQ_GETSTATUS 0x00
184 | #define B_REQ_SETFEATURE 0x03
185 | #define B_REQ_CLEARFEATURE 0x01
186 | #define B_REQ_GETDESC 0x06
187 | #define B_REQ_SETADDR 0x05
188 | #define B_REQ_GETCONFIG 0x08
189 | #define B_REQ_SETCONFIG 0x09
190 | #define B_REQ_GETINTER 0x0a
191 | #define B_REQ_SETINTER 0x0b
192 | #endif
193 |
194 | #if 0
195 | //////////
196 | // Descriptor types:
197 | #define XUD_DESC_DEV_B_DESCTYPE_DEVICE 0x1
198 | #define XUD_DESC_DEV_B_DESCTYPE_CONFIG 0x2
199 | #define XUD_DESC_DEV_B_DESCTYPE_STRING 0x3
200 | #define XUD_DESC_DEV_B_DESCTYPE_INTER 0x4
201 | #define XUD_DESC_DEV_B_DESCTYPE_EP 0x5
202 | #define XUD_DESC_DEV_B_DESCTYPE_DEVQUAL 0x6
203 | #define XUD_DESC_DEV_B_DESCTYPE_OSPEED_CFG 0x7
204 |
205 | #define XUD_DESC_DEV_B_DESCTYPE_HID 0x21
206 | #endif
207 |
--------------------------------------------------------------------------------
/client/setdsp.py:
--------------------------------------------------------------------------------
1 | import sys
2 | from math import cos, sin, pi, sqrt
3 | import struct
4 | import usb.core
5 | import usb.util
6 |
7 | CHANNELS = 6
8 | FRACTIONALBITS = 28
9 | SET_DSP_BIQUAD = 1
10 | SET_DSP_DELAY = 2
11 | DSP_FILTERS = 15
12 | FS = 96000.0
13 |
14 | class Biquad(object):
15 | def __init__(self, b0, b1, b2, a0, a1, a2):
16 | self.b0 = b0 / a0
17 | self.b1 = b1 / a0
18 | self.b2 = b2 / a0
19 | self.a1 = a1 / a0
20 | self.a2 = a2 / a0
21 | @property
22 | def coefs(self):
23 | return (self.b0, self.b1, self.b2, -self.a1, -self.a2)
24 | def apply_gain(self, gain):
25 | v = 10 ** (gain / 20.0)
26 | self.b0 *= v
27 | self.b1 *= v
28 | self.b2 *= v
29 | def __str__(self):
30 | return 'Biquad<%.03f %.03f %.03f %.03f %.03f>' % self.coefs
31 |
32 | class SimpleBiquad(Biquad):
33 | def __init__(self, f0, Q):
34 | self.f0 = f0
35 | self.Q = Q
36 | self.build()
37 | Biquad.__init__(self, self.b0, self.b1, self.b2, self.a0, self.a1, self.a2)
38 | @property
39 | def w0(self):
40 | return 2 * pi * self.f0 / FS
41 | @property
42 | def alpha(self):
43 | return sin(self.w0) / (2.0 * self.Q)
44 | def __str__(self):
45 | return '%s(f0=%.03f, Q=%.03f)' % (self.__class__.__name__, self.f0, self.Q)
46 |
47 | class GainBiquad(SimpleBiquad):
48 | def __init__(self, f0, Q, gain):
49 | self.gain = gain
50 | SimpleBiquad.__init__(self, f0, Q)
51 | @property
52 | def A(self):
53 | return 10 ** (self.gain / 40.0)
54 | def __str__(self):
55 | return '%s(f0=%.03f, Q=%.03f, gain=%.02f)' % (self.__class__.__name__, self.f0, self.Q, self.gain)
56 |
57 | class LPF(SimpleBiquad):
58 | def build(self):
59 | self.b0 = (1 - cos(self.w0))/2
60 | self.b1 = 1 - cos(self.w0)
61 | self.b2 = (1 - cos(self.w0))/2
62 | self.a0 = 1 + self.alpha
63 | self.a1 = -2*cos(self.w0)
64 | self.a2 = 1 - self.alpha
65 |
66 | class HPF(SimpleBiquad):
67 | def build(self):
68 | self.b0 = (1 + cos(self.w0))/2
69 | self.b1 = -(1 + cos(self.w0))
70 | self.b2 = (1 + cos(self.w0))/2
71 | self.a0 = 1 + self.alpha
72 | self.a1 = -2*cos(self.w0)
73 | self.a2 = 1 - self.alpha
74 |
75 | class BPFSkirt(SimpleBiquad):
76 | def build(self):
77 | self.b0 = sin(self.w0)/2
78 | self.b1 = 0
79 | self.b2 = -sin(self.w0)/2
80 | self.a0 = 1 + self.alpha
81 | self.a1 = -2*cos(self.w0)
82 | self.a2 = 1 - self.alpha
83 |
84 | class BPFPeak(SimpleBiquad):
85 | def build(self):
86 | self.b0 = self.alpha
87 | self.b1 = 0
88 | self.b2 = -self.alpha
89 | self.a0 = 1 + self.alpha
90 | self.a1 = -2*cos(self.w0)
91 | self.a2 = 1 - self.alpha
92 |
93 | class notch(SimpleBiquad):
94 | def build(self):
95 | self.b0 = 1
96 | self.b1 = -2*cos(self.w0)
97 | self.b2 = 1
98 | self.a0 = 1 + self.alpha
99 | self.a1 = -2*cos(self.w0)
100 | self.a2 = 1 - self.alpha
101 |
102 | class APF(SimpleBiquad):
103 | def build(self):
104 | self.b0 = 1 - self.alpha
105 | self.b1 = -2*cos(self.w0)
106 | self.b2 = 1 + self.alpha
107 | self.a0 = 1 + self.alpha
108 | self.a1 = -2*cos(self.w0)
109 | self.a2 = 1 - self.alpha
110 |
111 | class PeakingEQ(GainBiquad):
112 | def build(self):
113 | self.b0 = 1 + self.alpha*self.A
114 | self.b1 = -2*cos(self.w0)
115 | self.b2 = 1 - self.alpha*self.A
116 | self.a0 = 1 + self.alpha/self.A
117 | self.a1 = -2*cos(self.w0)
118 | self.a2 = 1 - self.alpha/self.A
119 |
120 | class LowShelf(GainBiquad):
121 | def build(self):
122 | A = self.A
123 | self.b0 = A*( (A+1) - (A-1)*cos(self.w0) + 2*sqrt(A)*self.alpha )
124 | self.b1 = 2*A*( (A-1) - (A+1)*cos(self.w0) )
125 | self.b2 = A*( (A+1) - (A-1)*cos(self.w0) - 2*sqrt(A)*self.alpha )
126 | self.a0 = (A+1) + (A-1)*cos(self.w0) + 2*sqrt(A)*self.alpha
127 | self.a1 = -2*( (A-1) + (A+1)*cos(self.w0) )
128 | self.a2 = (A+1) + (A-1)*cos(self.w0) - 2*sqrt(A)*self.alpha
129 |
130 | class HighShelf(GainBiquad):
131 | def build(self):
132 | A = self.A
133 | self.b0 = A*( (A+1) + (A-1)*cos(self.w0) + 2*sqrt(A)*self.alpha )
134 | self.b1 = -2*A*( (A-1) + (A+1)*cos(self.w0) )
135 | self.b2 = A*( (A+1) + (A-1)*cos(self.w0) - 2*sqrt(A)*self.alpha )
136 | self.a0 = (A+1) - (A-1)*cos(self.w0) + 2*sqrt(A)*self.alpha
137 | self.a1 = 2*( (A-1) - (A+1)*cos(self.w0) )
138 | self.a2 = (A+1) - (A-1)*cos(self.w0) - 2*sqrt(A)*self.alpha
139 |
140 | class LowShelfS(LowShelf):
141 | def __init__(self, f0, S, gain):
142 | self.gain = gain
143 | Q = 1.0/sqrt((self.A + 1.0/self.A)*(1.0/S - 1.0) + 2.0)
144 | LowShelf.__init__(self, f0, Q, gain)
145 |
146 | class HighShelfS(HighShelf):
147 | def __init__(self, f0, S, gain):
148 | self.gain = gain
149 | Q = 1.0/sqrt((self.A + 1.0/self.A)*(1.0/S - 1.0) + 2.0)
150 | HighShelf.__init__(self, f0, Q, gain)
151 |
152 | class AudioInterface(object):
153 | def __init__(self):
154 | self.dev = usb.core.find(idVendor=0x20b1, idProduct=0x0004)
155 | if self.dev is None:
156 | raise Exception('Device not found')
157 |
158 | def set_biquad(self, channel, index, biquad):
159 | params = [int(i*(1< 4:
227 | gain = float(sys.argv[4])
228 | data.biquads[-1].apply_gain(gain)
229 | dev.reset_channel(channel)
230 | for i,biquad in enumerate(data.biquads):
231 | print '%d: %s' % (i, biquad)
232 | dev.set_biquad(channel, i, biquad)
233 | elif cmd == 'reset':
234 | if len(sys.argv) > 2:
235 | dev.reset_channel(int(sys.argv[2]))
236 | else:
237 | dev.reset()
238 | elif cmd == 'set':
239 | channel = int(sys.argv[2])
240 | idx = int(sys.argv[3])
241 | args = map(float, sys.argv[4:])
242 | dev.set_biquad(channel, idx, Biquad(*args))
243 | elif cmd == 'delay':
244 | channel = int(sys.argv[2])
245 | delay = float(sys.argv[3])
246 | dev.set_delay(channel, delay)
247 | else:
248 | print "Unknown command"
249 |
--------------------------------------------------------------------------------
/firmware/interrupt.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Module: module_usb_aud_shared
3 | * Version: 2v0
4 | * Build: c0b2e34218aec54736ad1259d95377c59ed03dd3
5 | * File: interrupt.h
6 | *
7 | * The copyrights, all other intellectual and industrial
8 | * property rights are retained by XMOS and/or its licensors.
9 | * Terms and conditions covering the use of this code can
10 | * be found in the Xmos End User License Agreement.
11 | *
12 | * Copyright XMOS Ltd 2010
13 | *
14 | * In the case where this code is a modification of existing code
15 | * under a separate license, the separate license terms are shown
16 | * below. The modifications to the code are still covered by the
17 | * copyright notice above.
18 | *
19 | **/
20 | #ifndef __interrupt_h__
21 | #define __interrupt_h__
22 |
23 | #define store_args0(c) \
24 | asm("kentsp 19; stw %0, sp[1]; krestsp 19"::"r"(c));
25 |
26 | #define store_args1(c,x) \
27 | asm("kentsp 20; stw %0, sp[1]; stw %1, sp[2]; krestsp 20"::"r"(c),"r"(x));
28 |
29 | #define store_args2(c,x0,x1) \
30 | asm("kentsp 21; stw %0, sp[1];" \
31 | "stw %1, sp[2];" \
32 | "stw %2, sp[3];" \
33 | " krestsp 21"::"r"(c),"r"(x0),"r"(x1));
34 |
35 | #define store_args3(c,x0,x1,x2) \
36 | asm("kentsp 22; stw %0, sp[1];" \
37 | "stw %1, sp[2];" \
38 | "stw %2, sp[3];" \
39 | "stw %3, sp[4];" \
40 | " krestsp 22"::"r"(c),"r"(x0),"r"(x1),"r"(x2));
41 |
42 | #define store_args4(c,x0,x1,x2,x3) \
43 | asm("kentsp 23; stw %4, sp[1];" \
44 | "stw %0, sp[2];" \
45 | "stw %1, sp[3];" \
46 | "stw %2, sp[4];" \
47 | "stw %3, sp[5];" \
48 | " krestsp 23"::"r"(c),"r"(x0),"r"(x1),"r"(x2),"r"(x3));
49 |
50 | #define store_args5(c,x0,x1,x2,x3,x4) \
51 | asm("kentsp 24;" \
52 | "stw %4, sp[1];" \
53 | "stw %5, sp[2];" \
54 | "stw %0, sp[3];" \
55 | "stw %1, sp[4];" \
56 | "stw %2, sp[5];" \
57 | "stw %3, sp[6];" \
58 | " krestsp 24"::"r"(c),"r"(x0),"r"(x1),"r"(x2),"r"(x3),"r"(x4));
59 |
60 | #define store_args6(c,x0,x1,x2,x3,x4,x5) \
61 | asm("kentsp 25;" \
62 | "stw %4, sp[1];" \
63 | "stw %5, sp[2];" \
64 | "stw %6, sp[3];" \
65 | "stw %0, sp[4];" \
66 | "stw %1, sp[5];" \
67 | "stw %2, sp[6];" \
68 | "stw %3, sp[7];" \
69 | " krestsp 25"::"r"(c),"r"(x0),"r"(x1),"r"(x2),"r"(x3),"r"(x4),"r"(x5));
70 |
71 | #define store_args7(c,x0,x1,x2,x3,x4,x5,x6) \
72 | asm("kentsp 26;" \
73 | "stw %4, sp[1];" \
74 | "stw %5, sp[2];" \
75 | "stw %6, sp[3];" \
76 | "stw %7, sp[4];" \
77 | "stw %0, sp[5];" \
78 | "stw %1, sp[6];" \
79 | "stw %2, sp[7];" \
80 | "stw %3, sp[8];" \
81 | " krestsp 26"::"r"(c),"r"(x0),"r"(x1),"r"(x2),"r"(x3),"r"(x4),"r"(x5),"r"(x6));
82 |
83 | #define store_args8(c,x0,x1,x2,x3,x4,x5,x6,x7) \
84 | asm("kentsp 27;" \
85 | "stw %4, sp[1];" \
86 | "stw %5, sp[2];" \
87 | "stw %6, sp[3];" \
88 | "stw %7, sp[4];" \
89 | "stw %8, sp[5];" \
90 | "stw %0, sp[6];" \
91 | "stw %1, sp[7];" \
92 | "stw %2, sp[8];" \
93 | "stw %3, sp[9];" \
94 | " krestsp 27"::"r"(c),"r"(x0),"r"(x1),"r"(x2),"r"(x3),"r"(x4),"r"(x5),"r"(x6),"r"(x7));
95 |
96 |
97 |
98 |
99 | #define load_args0(f) \
100 | "ldw r0, sp[1]\n"
101 |
102 | #define load_args1(f)\
103 | "ldw r0, sp[1]\n" \
104 | "ldw r1, sp[2]\n"
105 |
106 | #define load_args2(f)\
107 | "ldw r0, sp[1]\n" \
108 | "ldw r1, sp[2]\n" \
109 | "ldw r2, sp[3]\n"
110 |
111 | #define load_args3(f)\
112 | "ldw r0, sp[1]\n" \
113 | "ldw r1, sp[2]\n" \
114 | "ldw r2, sp[3]\n" \
115 | "ldw r3, sp[4]\n"
116 |
117 | #define load_argsn(f, args) \
118 | ".linkset __"#f"_handler_arg0, "#args"-2\n"\
119 | "ldw r0, sp[" "__"#f"_handler_arg0" "]\n" \
120 | ".linkset __"#f"_handler_arg1, "#args"-1\n"\
121 | "ldw r1, sp[" "__"#f"_handler_arg1" "]\n" \
122 | ".linkset __"#f"_handler_arg2, "#args"-0\n"\
123 | "ldw r2, sp[" "__"#f"_handler_arg2" "]\n" \
124 | ".linkset __"#f"_handler_arg3, "#args"+1\n"\
125 | "ldw r3, sp[" "__"#f"_handler_arg3" "]\n"
126 |
127 | #define load_args4(f) load_argsn(f,4)
128 | #define load_args5(f) load_argsn(f,5)
129 | #define load_args6(f) load_argsn(f,6)
130 | #define load_args7(f) load_argsn(f,7)
131 | #define load_args8(f) load_argsn(f,8)
132 |
133 | #define save_state(f,args) \
134 | ".linkset __"#f"_handler_r0_save, "#args"+12\n" \
135 | "stw r0, sp[" "__"#f"_handler_r0_save" "]\n" \
136 | ".linkset __"#f"_handler_r1_save, "#args"+13\n" \
137 | "stw r1, sp[" "__"#f"_handler_r1_save" "]\n" \
138 | ".linkset __"#f"_handler_r2_save, "#args"+2\n" \
139 | "stw r2, sp[" "__"#f"_handler_r2_save" "]\n" \
140 | ".linkset __"#f"_handler_r3_save, "#args"+3\n" \
141 | "stw r3, sp[" "__"#f"_handler_r3_save" "]\n" \
142 | ".linkset __"#f"_handler_r4_save, "#args"+4\n" \
143 | "stw r4, sp[" "__"#f"_handler_r4_save" "]\n" \
144 | ".linkset __"#f"_handler_r5_save, "#args"+5\n" \
145 | "stw r5, sp[" "__"#f"_handler_r5_save" "]\n" \
146 | ".linkset __"#f"_handler_r6_save, "#args"+6\n" \
147 | "stw r6, sp[" "__"#f"_handler_r6_save" "]\n" \
148 | ".linkset __"#f"_handler_r7_save, "#args"+7\n" \
149 | "stw r7, sp[" "__"#f"_handler_r7_save" "]\n" \
150 | ".linkset __"#f"_handler_r8_save, "#args"+8\n" \
151 | "stw r8, sp[" "__"#f"_handler_r8_save" "]\n" \
152 | ".linkset __"#f"_handler_r9_save, "#args"+9\n" \
153 | "stw r9, sp[" "__"#f"_handler_r9_save" "]\n" \
154 | ".linkset __"#f"_handler_r10_save, "#args"+10\n" \
155 | "stw r10, sp[" "__"#f"_handler_r10_save" "]\n" \
156 | ".linkset __"#f"_handler_r11_save, "#args"+11\n" \
157 | "stw r11, sp[" "__"#f"_handler_r11_save" "]\n" \
158 | ".linkset __"#f"_handler_lr_save, "#args"+14\n" \
159 | "stw lr, sp[" "__"#f"_handler_lr_save" "]\n"
160 |
161 | #define restore_state(f,args) \
162 | "ldw r0, sp[" "__"#f"_handler_r0_save" "]\n" \
163 | "ldw r1, sp[" "__"#f"_handler_r1_save" "]\n" \
164 | "ldw r2, sp[" "__"#f"_handler_r2_save" "]\n" \
165 | "ldw r3, sp[" "__"#f"_handler_r3_save" "]\n" \
166 | "ldw r4, sp[" "__"#f"_handler_r4_save" "]\n" \
167 | "ldw r5, sp[" "__"#f"_handler_r5_save" "]\n" \
168 | "ldw r6, sp[" "__"#f"_handler_r6_save" "]\n" \
169 | "ldw r7, sp[" "__"#f"_handler_r7_save" "]\n" \
170 | "ldw r8, sp[" "__"#f"_handler_r8_save" "]\n" \
171 | "ldw r9, sp[" "__"#f"_handler_r9_save" "]\n" \
172 | "ldw r10, sp[" "__"#f"_handler_r10_save" "]\n" \
173 | "ldw r11, sp[" "__"#f"_handler_r11_save" "]\n" \
174 | "ldw lr, sp[" "__"#f"_handler_lr_save" "]\n"
175 |
176 |
177 | #define STRINGIFY0(x) #x
178 | #define STRINGIFY(x) STRINGIFY0(x)
179 |
180 | #define ENABLE_INTERRUPTS() asm("setsr " STRINGIFY(XS1_SR_IEBLE_SET(0, 1)))
181 |
182 | #define DISABLE_INTERRUPTS() asm("clrsr " STRINGIFY(XS1_SR_IEBLE_SET(0, 1)))
183 |
184 | //int ksp_enter, ksp_exit, r11_store;
185 |
186 | #define do_interrupt_handler(f,args) \
187 | asm("bu .L__" #f "_handler_skip;\n" \
188 | "__" #f "_handler:\n" \
189 | "kentsp " #args " + 19\n" \
190 | "__kent:" \
191 | save_state(f,args) \
192 | load_args ## args (f) \
193 | "bl " #f "\n" \
194 | restore_state(f,args) \
195 | "krestsp " #args " + 19 \n" \
196 | "__kret:\n" \
197 | "kret\n" \
198 | ".L__" #f "_handler_skip:\n");
199 |
200 | #define set_interrupt_handler(f, nstackwords, args, c, ...) \
201 | asm (" .section .dp.data, \"adw\", @progbits\n" \
202 | " .align 4\n" \
203 | "__" #f "_kernel_stack:\n" \
204 | " .space " #nstackwords ", 0\n" \
205 | " .text\n"); \
206 | asm("mov r10, %0; ldaw r11, dp[__" #f "_kernel_stack];add r11, r11, r10;ldaw r10, sp[0]; "\
207 | "set sp,r11;stw r10, sp[0]; krestsp 0"::"r"(nstackwords-8):"r10","r11"); \
208 | store_args ## args(c, __VA_ARGS__) \
209 | do_interrupt_handler(f, args) \
210 | asm("ldap r11, __" #f "_handler; setv res[%0],r11"::"r"(c):"r11"); \
211 | asm("setc res[%0], 0xa; eeu res[%0]"::"r"(c)); \
212 | asm("setsr (((0) & ~(((1 << 0x1) - 1) << 0x1)) | (((1) << 0x1) & (((1 << 0x1) - 1) << 0x1)))");
213 |
214 |
215 |
216 | #endif
217 |
218 |
--------------------------------------------------------------------------------
/firmware/usbaudio20.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Module: module_usb_shared
3 | * Version: 1v15
4 | * Build: 5f54bab9944b48e1ccf265e572562e2be9746401
5 | * File: usbaudio20.h
6 | *
7 | * The copyrights, all other intellectual and industrial
8 | * property rights are retained by XMOS and/or its licensors.
9 | * Terms and conditions covering the use of this code can
10 | * be found in the Xmos End User License Agreement.
11 | *
12 | * Copyright XMOS Ltd 2010
13 | *
14 | * In the case where this code is a modification of existing code
15 | * under a separate license, the separate license terms are shown
16 | * below. The modifications to the code are still covered by the
17 | * copyright notice above.
18 | *
19 | **/
20 | /**
21 | * @file usbaudio20.h
22 | * @brief Defines from the USB Audio 2.0 Specifications
23 | * @author Ross Owen, XMOS Limited
24 | * @version 0.9
25 | */
26 |
27 | #include "usb.h"
28 |
29 | /***********************************************************************/
30 | /* USB Audio 2.0 Class Specification */
31 |
32 | /* A.1 Audio Function Class Code */
33 | #define AUDIO_FUNCTION AUDIO
34 |
35 | /* A.2 Audio Function Subclass Codes */
36 | #define FUNCTION_SUBCLASS_UNDEFINED 0x00
37 |
38 | /* A.3 Audio Function Protocol Codes */
39 | #define FUNCTION_PROTOCOL_UNDEFINED 0x00
40 | #define AF_VERSION_02_00 IP_VERSION_02_00
41 |
42 | /* A.4 Audio Interface Class Code */
43 | #define AUDIO 0x01
44 |
45 | /* A.5 Audio Interface Subclass Codes */
46 | #define AUDIOCONTROL 0x01
47 | #define AUDIOSTREAMING 0x02
48 | #define MIDISTREAMING 0x03
49 |
50 | /* A.6 Audo Interface Protocol Codes */
51 | #define IP_VERSION_02_00 0x20
52 |
53 | /* A.7 Audio Function Category Codes */
54 | #define FUNCTION_SUBCLASS_UNDEFINED 0x00
55 | #define DESKTOP_SPEAKER 0x01
56 | #define HOME_THEATER 0x02
57 | #define MICROPHONE 0x03
58 | #define HEADSET 0x04
59 | #define TELEPHONE 0x05
60 | #define CONVERTER 0x06
61 | #define VOICE_SOUND_RECORDER 0x07
62 | #define IO_BOX 0x08
63 | #define MUSICAL_INTRUMENT 0x09
64 | #define PRO_AUDIO 0x0A
65 | #define AUDIO_VIDEO 0x0B
66 | #define CONTROL_PANEL 0x0C
67 | #define OTHER 0xFF
68 |
69 | /* A.8 Audio Class-Specific Descriptor Types */
70 | #define CS_UNDEFINED 0x20
71 | #define CS_DEVICE 0x21
72 | #define CS_CONFIGURATION 0x22
73 | #define CS_STRING 0x23
74 | #define CS_INTERFACE 0x24
75 | #define CS_ENDPOINT 0x25
76 |
77 | /* A.9 Audio Class-Specific AC Interface Descriptor Subtypes */
78 | #define AC_DESCRIPTOR_UNDEFINED 0x00
79 | #define HEADER 0x01
80 | #define INPUT_TERMINAL 0x02
81 | #define OUTPUT_TERMINAL 0x03
82 | #define MIXER_UNIT 0x04
83 | #define SELECTOR_UNIT 0x05
84 | #define FEATURE_UNIT 0x06
85 | #define EFFECT_UNIT 0x07
86 | #define PROCESSING_UNIT 0x08
87 | #define EXTENSION_UNIT 0x09
88 | #define CLOCK_SOURCE 0x0A
89 | #define CLOCK_SELECTOR 0x0B
90 | #define CLOCK_MULTIPLIER 0x0C
91 | #define SAMPLE_RATE_CONVERTER 0x0D
92 |
93 | /* A.10 Audio Class Specific AS Interface Descriptor Subtypes */
94 | #define AS_DESCRIPTOR_UNDEFINED 0x00
95 | #define AS_GENERAL 0x01
96 | #define FORMAT_TYPE 0x02
97 | #define ENCODER 0x03
98 | #define DECODER 0x04
99 |
100 | /* A.11 Effect Unit Effect Types */
101 | #define EFFECT_UNDEFINED 0x00
102 | #define PARAM_EQ_SECTION_EFFECT 0x01
103 | #define REVERBERATION_EFFECT 0x02
104 | #define MOD_DELAY_EFFECT 0x03
105 | #define DYN_RANGE_COMP_EFFECT 0x04
106 |
107 | /* A.12 Processing Unit Process Types */
108 | #define PROCESS_UNDEFINED 0x00
109 | #define UP_DOWNMIX_PROCESS 0x01
110 | #define DOLBY_PROLOGIC_PROCESS 0x02
111 | #define STEREO_EXTENDER_PROCESS 0x03
112 |
113 | /* A.13 Audio Class-Specific Endpoint Descriptor Subtypes */
114 | #define DESCRIPTOR_UNDEFINED 0x00
115 | #define EP_GENERAL 0x01
116 |
117 | /* A.14 Audio Class-Specific Request Codes */
118 | #define REQUEST_CODE_UNDEFINED 0x00
119 | #define CUR 0x01
120 | #define RANGE 0x02
121 | #define MEM 0x03
122 |
123 | /* A.15 Encoder Type Codes */
124 | #define ENCODER_UNDEFINED 0x00
125 | #define OTHER_ENCODER 0x01
126 | #define MPEG_ENCODER 0x02
127 | #define AC_3_ENCODER 0x03
128 | #define WMA_ENCODER 0x04
129 | #define DTS_ENCODER 0x05
130 |
131 | /* A.17 Control Selector Codes */
132 | /* A.17.1 Clock Source Control Selectors */
133 | #define CS_CONTROL_UNDEFINED 0x00
134 | #define CS_SAM_FREQ_CONTROL 0x01
135 | #define CS_CLOCK_VALID_CONTROL 0x02
136 |
137 | /* A.17.2 Clock Selector Control Selectors */
138 | #define CX_CONTROL_UNDEFINED 0x00
139 | #define CX_CLOCK_SELECTOR_CONTROL 0x01
140 |
141 | /* A.17.7 Feature Unit Control Selectors */
142 | #define FU_CONTROL_UNDEFINED 0x00
143 | #define FU_MUTE_CONTROL 0x01
144 | #define FU_VOLUME_CONTROL 0x02
145 |
146 | /* A.17.6 Feature Unit Control Selectors */
147 | #define SU_CONTROL_UNDEFINED 0x00
148 | #define SU_SELECTOR_CONTROL 0x01
149 |
150 | /* Audio Class-Specific Descriptor Types */
151 | #define CS_INTERFACE 0x24
152 | #define CS_ENDPOINT 0x25
153 |
154 |
155 | /* Audio Class-Specific AS Interface Descriptor Subtypes */
156 | #define FORMAT_TYPE 0x02
157 |
158 |
159 | /***********************************************************************/
160 | /* Universal Serial Bus Device Class Definition for Audio Data Formats */
161 |
162 | /* A.1 Format Type Codes */
163 | #define FORMAT_TYPE_UNDEFINED 0x00
164 | #define FORMAT_TYPE_I 0x01
165 | #define FORMAT_TYPE_II 0x02
166 | #define FORMAT_TYPE_III 0x03
167 | #define FORMAT_TYPE_IV 0x04
168 | #define EXT_FORMAT_TYPE_I 0x81
169 | #define EXT_FORMAT_TYPE_II 0x82
170 | #define EXT_FORMAT_TYPE_III 0x83
171 |
172 | /* A.3 Side Band Protocol Codes */
173 | #define PROTOCOL_UNDEFINED 0x00
174 | #define PRESS_TIMESTAMP_PROTOCOL 0x01
175 |
176 |
177 | /***********************************************************************/
178 | /* Univeral Serial Bus Device Class Definition for Terminal Types */
179 |
180 | /* 2.1 USB Terminal Types */
181 | /* Terminal Types that describe Terminals that handle signals carried over USB */
182 | #define USB_UNDEFINED 0x0100
183 | #define USB_STREAMING 0x0101
184 | #define USB_VENDOR_SPECIFIC 0x01FF
185 |
186 | /* 2.2 Input Terminal Types */
187 | /* Terminal Types that describe Terminals that are designed to record sounds */
188 | #define INPUT_UDEFINED 0x0200
189 | #define MICROPHONE_ 0x0201
190 | #define DESKTOP_MICROPHONE 0x0202
191 | #define PERSONAL_MICROPHONE 0x0203
192 | #define OMNIDIRECTIONAL_MICROPHONE 0x0204
193 | #define MICROPHONE_ARRAY 0x0205
194 | #define PROCESSING_MICROPHONE_ARRAY 0x0206
195 |
196 | /* 2.3 Output Terminal Types */
197 | /* These Terminal Types describe Terminals that produce audible signals that are intended to
198 | * be heard by the user of the audio function */
199 | #define SPEAKER 0x0301
200 | #define HEADPHONES 0x0302
201 | #define HEAD_MOUNTED_DISPLAY 0x0303
202 | #define DESKTOPSPEAKER 0x0304
203 | #define ROOM_SPEAKER 0x0305
204 | #define COMMUNICATION_SPEAKER 0x0306
205 | #define LOW_FREQ_EFFECTS_SPEAKER 0x0307
206 |
207 |
208 | #define FORMAT_TYPE_I 0x01
209 |
210 | /* A.2 AudioData Format Bit Allocation in the bmFormats field */
211 | /* A.2.1 Audio Data Format Type I Bit Allocations */
212 | #define PCM 0x01
213 | #define PCM8 0x02
214 | #define IEEE_FLOAT 0x04
215 |
--------------------------------------------------------------------------------
/firmware/DescriptorRequests.xc:
--------------------------------------------------------------------------------
1 | /**
2 | * Module: module_usb_shared
3 | * Version: 1v2
4 | * Build: bb814601fea4422bae7e88cb0fd65289443c217c
5 | * File: DescriptorRequests.xc
6 | *
7 | * The copyrights, all other intellectual and industrial
8 | * property rights are retained by XMOS and/or its licensors.
9 | * Terms and conditions covering the use of this code can
10 | * be found in the Xmos End User License Agreement.
11 | *
12 | * Copyright XMOS Ltd 2010
13 | *
14 | * In the case where this code is a modification of existing code
15 | * under a separate license, the separate license terms are shown
16 | * below. The modifications to the code are still covered by the
17 | * copyright notice above.
18 | *
19 | **/
20 | /**
21 | * @file DescriptorRequests.xc
22 | * @brief DescriptorRequests implementation
23 | * @author Ross Owen, XMOS Limited
24 | * @version 1.0
25 | */
26 |
27 | #include
28 | #include
29 | #include
30 |
31 | #include "xud.h" /* XUD Functions and defines */
32 | #include "usb.h" /* Defines related to the USB 2.0 Spec */
33 |
34 | #if 0
35 | /** @brief Returns min of two values
36 | * @param a int
37 | * @param b int
38 | * @return min of the two passed int values
39 | */
40 | int min(int a, int b)
41 | {
42 | if (a > b)
43 | return b;
44 | else
45 | return a;
46 | }
47 | #endif
48 |
49 | extern int min(int a, int b);
50 |
51 |
52 | /* See DescriptorRequests.h for documentation */
53 | #pragma unsafe arrays
54 | int DescriptorRequests(XUD_ep c, XUD_ep c_in, uint8 devDesc[], int devDescLength, uint8 cfgDesc[], int cfgDescLength,
55 | uint8 devQualDesc[], int devQualDescLength, uint8 oSpeedCfgDesc[], int oSpeedCfgDescLength, uint8 strDescs[][40], SetupPacket &sp)
56 | {
57 | /* Return value */
58 | int datalength;
59 | int stringID = 0;
60 |
61 | /* Buffer for Setup data */
62 | uint8 buffer[120];
63 |
64 | /* Wait for Setup data */
65 | if (XUD_GetSetupBuffer(c, buffer) < 0)
66 | {
67 | return -1;
68 | } else {
69 |
70 | /* Parse data buffer end populate SetupPacket struct */
71 | XUD_ParseSetupPacket(buffer, sp);
72 |
73 | /* Inspect for recipent */
74 | switch(sp.bmRequestType.Recipient)
75 | {
76 | /* Recipient: Device */
77 | case BM_REQTYPE_RECIP_DEV:
78 |
79 | /* Inspect for request type */
80 | switch(sp.bmRequestType.Type)
81 | {
82 | /* Request Type: Standard Request */
83 | case BM_REQTYPE_TYPE_STANDARD:
84 |
85 | /* Inspect for actual request */
86 | switch(sp.bRequest)
87 | {
88 |
89 | /* Request: Get Descriptor */
90 | case GET_DESCRIPTOR:
91 |
92 | /* Inspect for which descriptor is required (high byte of wValue) */
93 | switch(sp.wValue & 0xff00)
94 | {
95 | /* Device descriptor */
96 | case WVALUE_GETDESC_DEV:
97 |
98 | /* Do get request (send descriptor then 0 length status stage) */
99 | return XUD_DoGetRequest(c, c_in, devDesc, devDescLength, sp.wLength);
100 | break;
101 |
102 | /* Configuration Descriptor */
103 | case WVALUE_GETDESC_CONFIG:
104 |
105 | /* Do get request (send descriptor then 0 length status stage) */
106 | return XUD_DoGetRequest(c, c_in, cfgDesc, cfgDescLength, sp.wLength);
107 | break;
108 |
109 | /* Device qualifier descriptor */
110 | case WVALUE_GETDESC_DEVQUAL:
111 |
112 | /* Do get request (send descriptor then 0 length status stage) */
113 | return XUD_DoGetRequest(c, c_in, devQualDesc, devQualDescLength, sp.wLength);
114 | break;
115 |
116 | /* Other Speed Configiration Descriptor */
117 | case WVALUE_GETDESC_OSPEED_CFG:
118 | return XUD_DoGetRequest(c, c_in, oSpeedCfgDesc, oSpeedCfgDescLength, sp.wLength);
119 | break;
120 |
121 |
122 | /* String Descriptor */
123 | case WVALUE_GETDESC_STRING:
124 |
125 | /* Set descriptor type */
126 | buffer[1] = STRING;
127 |
128 | /* Send the string that was requested (low byte of wValue) */
129 | /* First, generate valid descriptor from string */
130 | /* TODO Bounds check */
131 | stringID = sp.wValue & 0xff;
132 |
133 | /* Microsoft OS String special case, send product ID string */
134 | if ( sp.wValue == 0x03ee)
135 | {
136 | stringID = 2;
137 | }
138 |
139 | datalength = safestrlen(strDescs[ stringID ] );
140 |
141 | /* String 0 (LangIDs) is a special case*/
142 | if( stringID == 0 )
143 | {
144 | buffer[0] = datalength + 2;
145 | if( sp.wLength < datalength + 2 )
146 | datalength = sp.wLength - 2;
147 |
148 | for(int i = 0; i < datalength; i += 1 )
149 | {
150 | buffer[i+2] = strDescs[stringID][i];
151 | }
152 | }
153 | else
154 | {
155 | /* Datalength *= 2 due to unicode */
156 | datalength <<= 1;
157 |
158 | /* Set data length in descriptor (+2 due to 2 byte datalength)*/
159 | buffer[0] = datalength + 2;
160 |
161 | if(sp.wLength < datalength + 2)
162 | datalength = sp.wLength - 2;
163 |
164 | /* Add zero bytes for unicode.. */
165 | for(int i = 0; i < datalength; i+=2)
166 | {
167 | buffer[i+2] = strDescs[ stringID ][i>>1];
168 | buffer[i+3] = 0;
169 | }
170 |
171 | }
172 |
173 | /* Send back string */
174 |
175 | return XUD_DoGetRequest(c, c_in, buffer, datalength + 2, sp.wLength);
176 | break;
177 | default:
178 | break;
179 |
180 | }
181 | break;
182 |
183 | default:
184 | break;
185 |
186 | }
187 | break;
188 |
189 | default:
190 | break;
191 | }
192 | break;
193 |
194 | default:
195 | break;
196 | }
197 | }
198 | return 1;
199 | }
200 |
--------------------------------------------------------------------------------
/firmware/devicedefines.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Module: module_usb_aud_shared
3 | * Version: 2v4
4 | * Build: 0d7477798fc2c4749eec66c9d1555b9dd2c3fe8a
5 | * File: devicedefines.h
6 | *
7 | * The copyrights, all other intellectual and industrial
8 | * property rights are retained by XMOS and/or its licensors.
9 | * Terms and conditions covering the use of this code can
10 | * be found in the Xmos End User License Agreement.
11 | *
12 | * Copyright XMOS Ltd 2010
13 | *
14 | * In the case where this code is a modification of existing code
15 | * under a separate license, the separate license terms are shown
16 | * below. The modifications to the code are still covered by the
17 | * copyright notice above.
18 | *
19 | **/
20 | /**
21 | * @file internaldefines.h
22 | * @brief Defines relating to device configuration and customisation.
23 | * @author Ross Owen, XMOS Limited
24 | */
25 |
26 | #ifndef _DEVICEDEFINES_H_
27 | #define _DEVICEDEFINES_H_
28 |
29 | #include "customdefines.h"
30 |
31 | /* Tidy up historical INPUT/OUTPUT defines. INPUT/OUTPUT now enabled based on channel count defines */
32 | #if !defined(NUM_USB_CHAN_IN)
33 | #error NUM_USB_CHAN_IN must be defined!
34 | #else
35 | #if (NUM_USB_CHAN_IN == 0)
36 | #undef INPUT
37 | #else
38 | #define INPUT 1
39 | #endif
40 | #endif
41 |
42 | #if !defined(NUM_USB_CHAN_OUT)
43 | #error NUM_USB_CHAN_OUT must be defined!
44 | #else
45 | #if (NUM_USB_CHAN_OUT == 0)
46 | #undef OUTPUT
47 | #else
48 | #define OUTPUT 1
49 | #endif
50 | #endif
51 |
52 | #if defined(INPUT) && (INPUT == 0)
53 | #undef INPUT
54 | #endif
55 |
56 | #if defined(OUTPUT) && (OUTPUT == 0)
57 | #undef OUTPUT
58 | #endif
59 |
60 | #if defined(CODEC_SLAVE) && (CODEC_SLAVE == 0)
61 | #undef CODEC_SLAVE
62 | #endif
63 |
64 | #if defined(LEVEL_METER_LEDS) && !defined(LEVEL_UPDATE_RATE)
65 | #define LEVEL_UPDATE_RATE 400000
66 | #endif
67 |
68 | #define AUDIO_CLASS 2
69 |
70 | /* Number of IS2 chans to DAC */
71 | #ifndef I2S_CHANS_DAC
72 | #error I2S_CHANS_DAC not defined
73 | #else
74 | #define I2S_WIRES_DAC (I2S_CHANS_DAC >> 1)
75 | #endif
76 |
77 | /* Number of I2S chans from ADC */
78 | #ifndef I2S_CHANS_ADC
79 | #error I2S_CHANS_ADC not defined
80 | #else
81 | #define I2S_WIRES_ADC (I2S_CHANS_ADC >> 1)
82 | #endif
83 |
84 | /* Max supported freq for device */
85 | #ifndef MAX_FREQ
86 | #warning MAX_FREQ not defined! Using 48000
87 | #define MAX_FREQ (48000)
88 | #endif
89 |
90 | /* Default device freq */
91 | #ifndef DEFAULT_FREQ
92 | #warning DEFAULT not defined! Using MAX_FREQ
93 | #define DEFAULT_FREQ (MAX_FREQ)
94 | #endif
95 |
96 | /* Master clock defines (in Hz) */
97 | #ifndef MCLK_441
98 | #error MCLK_441 not defined
99 | #endif
100 |
101 | #ifndef MCLK_48
102 | #error MCLK_441 not defined
103 | #endif
104 |
105 | /* The number of clock ticks to wait for the audio PLL to lock */
106 | #define AUDIO_PLL_LOCK_DELAY (40000000)
107 |
108 | /* Vendor/Product strings */
109 | #ifndef VENDOR_STR
110 | #define VENDOR_STR "XMOS "
111 | //#warning VENDOR_STR not defined. Using XMOS
112 | #endif
113 |
114 | #ifndef VENDOR_ID
115 | #warning VENDOR_ID not defined. Using XMOS vendor ID
116 | #define VENDOR_ID (0x20B1) /* XMOS VID */
117 | #endif
118 |
119 | #ifndef PID_AUDIO_1
120 | #define PID_AUDIO_1 (0x0001)
121 | #warning PRODUCT_ID not defined. Using 0x0001
122 | #endif
123 |
124 | #ifndef PID_AUDIO_2
125 | #define PID_AUDIO_2 (0x0001)
126 | #warning PRODUCT_ID not defined. Using 0x0001
127 | #endif
128 |
129 | /* Device release number in BCD: 0xJJMNi */
130 | #ifndef BCD_DEVICE
131 | #define BCD_DEVICE (0x0000)
132 | #warning BCD_DEVICE not defined. Using 0x0000
133 | #endif
134 |
135 | /* Addition interfaces based on defines */
136 | #if defined(DFU) && DFU != 0
137 | #define DFU_INTERFACES (1) /* DFU interface count */
138 | #else
139 | #define DFU_INTERFACES (0)
140 | #endif
141 |
142 | #ifdef INPUT
143 | #define INPUT_INTERFACES (1)
144 | #else
145 | #define INPUT_INTERFACES (0)
146 | #endif
147 |
148 | #if defined(OUTPUT) && OUTPUT != 0
149 | #define OUTPUT_INTERFACES (1)
150 | #else
151 | #define OUTPUT_INTERFACES (0)
152 | #endif
153 |
154 |
155 | #if defined(MIDI)
156 | #define MIDI_INTERFACES (2)
157 | #else
158 | #define MIDI_INTERFACES (0)
159 | #endif
160 |
161 | #define AUDIO_STOP_FOR_DFU (0x12345678)
162 | #define AUDIO_START_FROM_DFU (0x87654321)
163 | #define AUDIO_REBOOT_FROM_DFU (0xa5a5a5a5)
164 |
165 |
166 | #define MAX_VOL (0x20000000)
167 |
168 | #define NUM_EP_OUT 2 /* Max number of device endpoints used */
169 | #define NUM_EP_IN 4
170 | /* Length of clock unit/clock-selector units */
171 |
172 |
173 | /* Total number of USB interfaces this device implements (+1 for required control interface) */
174 | #define NUM_INTERFACES INPUT_INTERFACES + OUTPUT_INTERFACES + DFU_INTERFACES + MIDI_INTERFACES + 1
175 |
176 | #ifndef SERIAL_STR
177 | #define SERIAL_STR "0000" /* Serial number string */
178 | #endif
179 |
180 | #define SERIAL_STR_INDEX 0x03
181 | #define MANUFACTURER_STR_INDEX 0x01
182 | #define PRODUCT_STR_INDEX 0x02
183 |
184 | /* Mixer defines */
185 | #ifndef MIX_INPUTS
186 | #define MIX_INPUTS 18
187 | #endif
188 |
189 | #ifndef MAX_MIX_COUNT
190 | #define MAX_MIX_COUNT 8
191 | #endif
192 |
193 |
194 | /* Volume defines */
195 |
196 | #ifndef MIN_VOLUME
197 | /* The minimum volume setting above -inf. This is a signed 8.8 fixed point
198 | number that must be strictly greater than -128 (0x8000) */
199 | /* Default min volume is -127db */
200 | #define MIN_VOLUME (0x8100)
201 | #endif
202 |
203 | #ifndef MAX_VOLUME
204 | /* The maximum volume setting. This is a signed 8.8 fixed point number. */
205 | /* Default max volume is 0db */
206 | #define MAX_VOLUME (0x0000)
207 | #endif
208 |
209 | #ifndef VOLUME_RES
210 | /* The resolution of the volume control in db as a 8.8 fixed point number */
211 | /* Default volume resolution 1db */
212 | #define VOLUME_RES (0x100)
213 | #endif
214 |
215 |
216 | #ifndef MIN_MIXER_VOLUME
217 | /* The minimum volume setting for the mixer unit above -inf.
218 | This is a signed 8.8 fixed point
219 | number that must be strictly greater than -128 (0x8000) */
220 | /* Default min volume is -127db */
221 | #define MIN_MIXER_VOLUME (0x8100)
222 | #endif
223 |
224 | #ifndef MAX_MIXER_VOLUME
225 | /* The maximum volume setting for the mixer.
226 | This is a signed 8.8 fixed point number. */
227 | /* Default max volume is 0db */
228 | #define MAX_MIXER_VOLUME (0x0000)
229 | #endif
230 |
231 | #ifndef VOLUME_RES_MIXER
232 | /* The resolution of the volume control in db as a 8.8 fixed point number */
233 | /* Default volume resolution 1db */
234 | #define VOLUME_RES_MIXER (0x100)
235 | #endif
236 |
237 | /* Handle out volume control in the mixer */
238 | #if defined(OUT_VOLUME_IN_MIXER) && (OUT_VOLUME_IN_MIXER==0)
239 | #undef OUT_VOLUME_IN_MIXER
240 | #else
241 | #if defined(MIXER)
242 | // Enabled by default
243 | #define OUT_VOLUME_IN_MIXER
244 | #endif
245 | #endif
246 |
247 | /* Apply out volume controls after the mix */
248 | #if defined(OUT_VOLUME_AFTER_MIX) && (OUT_VOLUME_AFTER_MIX==0)
249 | #undef OUT_VOLUME_AFTER_MIX
250 | #else
251 | #if defined(MIXER) && defined(OUT_VOLUME_IN_MIXER)
252 | // Enabled by default
253 | #define OUT_VOLUME_AFTER_MIX
254 | #endif
255 | #endif
256 |
257 | /* Define for reporting as self or bus-powered to the host */
258 | #if defined(SELF_POWERED) && (SELF_POWERED==0)
259 | #undef SELF_POWERED
260 | #endif
261 |
262 | /* Handle in volume control in the mixer */
263 | #if defined(IN_VOLUME_IN_MIXER) && (IN_VOLUME_IN_MIXER==0)
264 | #undef IN_VOLUME_IN_MIXER
265 | #else
266 | #if defined(MIXER)
267 | /* Enabled by default */
268 | #define IN_VOLUME_IN_MIXER
269 | #endif
270 | #endif
271 |
272 | /* Apply in volume controls after the mix */
273 | #if defined(IN_VOLUME_AFTER_MIX) && (IN_VOLUME_AFTER_MIX==0)
274 | #undef IN_VOLUME_AFTER_MIX
275 | #else
276 | #if defined(MIXER) && defined(IN_VOLUME_IN_MIXER)
277 | // Enabled by default
278 | #define IN_VOLUME_AFTER_MIX
279 | #endif
280 | #endif
281 |
282 | #if defined(AUDIO_CLASS_FALLBACK) && (AUDIO_CLASS_FALLBACK==0)
283 | #undef AUDIO_CLASS_FALLBACK
284 | #endif
285 |
286 | /* Defines for DFU */
287 | #ifndef PID_DFU
288 | #define PID_DFU PID_AUDIO_2
289 | #endif
290 |
291 | #define DFU_VENDOR_ID VENDOR_ID
292 | #define DFU_BCD_DEVICE BCD_DEVICE
293 | #define DFU_SERIAL_STR_INDEX SERIAL_STR_INDEX
294 | #define DFU_MANUFACTURER_INDEX MANUFACTURER_STR_INDEX
295 | #define DFU_PRODUCT_INDEX PRODUCT_STR_INDEX
296 | #endif
297 |
--------------------------------------------------------------------------------
/firmware/i2c.xc:
--------------------------------------------------------------------------------
1 | /**
2 | * Module: module_usb_aud_shared
3 | * Version: 2v0
4 | * Build: 334eaf5834c010b803eaca46139f6c8c8412879c
5 | * File: i2c.xc
6 | *
7 | * The copyrights, all other intellectual and industrial
8 | * property rights are retained by XMOS and/or its licensors.
9 | * Terms and conditions covering the use of this code can
10 | * be found in the Xmos End User License Agreement.
11 | *
12 | * Copyright XMOS Ltd 2010
13 | *
14 | * In the case where this code is a modification of existing code
15 | * under a separate license, the separate license terms are shown
16 | * below. The modifications to the code are still covered by the
17 | * copyright notice above.
18 | *
19 | **/
20 | #include
21 | #include
22 |
23 | int I2cRegRead(int device, int addr, port scl, port sda)
24 | {
25 | //int Result;
26 | timer gt;
27 | unsigned time;
28 | int Temp, CtlAdrsData, i;
29 | // three device ACK
30 | int ack[3];
31 | int rdData;
32 |
33 | // initial values.
34 | scl <: 1;
35 | sda <: 1;
36 | sync(sda);
37 | gt :> time;
38 | time += 1000 + 1000;
39 | gt when timerafter(time) :> int _;
40 | // start bit on SDI
41 | scl <: 1;
42 | sda <: 0;
43 | gt :> time;
44 | time += 1000;
45 | gt when timerafter(time) :> int _;
46 | scl <: 0;
47 | // shift 7bits of address and 1bit R/W (fixed to write).
48 | // WARNING: Assume MSB first.
49 | for (i = 0; i < 8; i += 1)
50 | {
51 | Temp = (device >> (7 - i)) & 0x1;
52 | sda <: Temp;
53 | gt :> time;
54 | time += 1000;
55 | gt when timerafter(time) :> int _;
56 | scl <: 1;
57 | gt :> time;
58 | time += 1000;
59 | gt when timerafter(time) :> int _;
60 | scl <: 0;
61 | }
62 | // turn the data to input
63 | sda :> Temp;
64 | gt :> time;
65 | time += 1000;
66 | gt when timerafter(time) :> int _;
67 | scl <: 1;
68 | // sample first ACK.
69 | sda :> ack[0];
70 | gt :> time;
71 | time += 1000;
72 | gt when timerafter(time) :> int _;
73 | scl <: 0;
74 |
75 | CtlAdrsData = (addr & 0xFF);
76 | // shift first 8 bits.
77 | for (i = 0; i < 8; i += 1)
78 | {
79 | Temp = (CtlAdrsData >> (7 - i)) & 0x1;
80 | sda <: Temp;
81 | gt :> time;
82 | time += 1000;
83 | gt when timerafter(time) :> int _;
84 | scl <: 1;
85 | gt :> time;
86 | time += 1000;
87 | gt when timerafter(time) :> int _;
88 | scl <: 0;
89 | }
90 | // turn the data to input
91 | sda :> Temp;
92 | gt :> time;
93 | time += 1000;
94 | gt when timerafter(time) :> int _;
95 | scl <: 1;
96 | // sample second ACK.
97 | sda :> ack[1];
98 | gt :> time;
99 | time += 1000;
100 | gt when timerafter(time) :> int _;
101 | scl <: 0;
102 |
103 |
104 | // stop bit
105 | gt :> time;
106 | time += 1000 + 1000;
107 | gt when timerafter(time) :> int _;
108 | // start bit on SDI
109 | scl <: 1;
110 | sda <: 1;
111 | time += 1000 + 1000;
112 | gt when timerafter(time) :> int _;
113 | scl <: 0;
114 | time += 1000 + 1000;
115 | gt when timerafter(time) :> int _;
116 |
117 |
118 | // send address and read
119 | scl <: 1;
120 | sda <: 1;
121 | sync(sda);
122 | gt :> time;
123 | time += 1000 + 1000;
124 | gt when timerafter(time) :> int _;
125 | // start bit on SDI
126 | scl <: 1;
127 | sda <: 0;
128 | gt :> time;
129 | time += 1000;
130 | gt when timerafter(time) :> int _;
131 | scl <: 0;
132 | // shift 7bits of address and 1bit R/W (fixed to write).
133 | // WARNING: Assume MSB first.
134 | for (i = 0; i < 8; i += 1)
135 | {
136 | int deviceAddr = device | 1;
137 | Temp = (deviceAddr >> (7 - i)) & 0x1;
138 | sda <: Temp;
139 | gt :> time;
140 | time += 1000;
141 | gt when timerafter(time) :> int _;
142 | scl <: 1;
143 | gt :> time;
144 | time += 1000;
145 | gt when timerafter(time) :> int _;
146 | scl <: 0;
147 | }
148 | // turn the data to input
149 | sda :> Temp;
150 | gt :> time;
151 | time += 1000;
152 | gt when timerafter(time) :> int _;
153 | scl <: 1;
154 | // sample first ACK.
155 | sda :> ack[0];
156 | gt :> time;
157 | time += 1000;
158 | gt when timerafter(time) :> int _;
159 | scl <: 0;
160 |
161 |
162 | rdData = 0;
163 | // shift second 8 bits.
164 | for (i = 0; i < 8; i += 1)
165 | {
166 |
167 | gt :> time;
168 | time += 1000;
169 | gt when timerafter(time) :> int _;
170 | scl <: 1;
171 |
172 | sda :> Temp;
173 | rdData = (rdData << 1) | (Temp & 1);
174 |
175 | gt :> time;
176 | time += 1000;
177 | gt when timerafter(time) :> int _;
178 | scl <: 0;
179 | }
180 |
181 | // turn the data to input
182 | sda :> Temp;
183 | gt :> time;
184 | time += 1000;
185 | gt when timerafter(time) :> int _;
186 | scl <: 1;
187 | // sample second ACK.
188 | sda :> ack[2];
189 | gt :> time;
190 | time += 1000;
191 | gt when timerafter(time) :> int _;
192 | scl <: 0;
193 | gt :> time;
194 | time += 1000;
195 | gt when timerafter(time) :> int _;
196 | scl <: 1;
197 | // put the data to a good value for next round.
198 | sda <: 1;
199 | // validate all items are ACK properly.
200 | //Result = 0;
201 | //for (i = 0; i < 3; i += 1)
202 | //{
203 | //if ((ack[i]&1) != 0)
204 | //{
205 | //Result = Result | (1 << i);
206 | //}
207 | //}
208 |
209 | return rdData;
210 | }
211 |
212 | void I2cRegWrite(int device, int addr, int data, port scl, port sda)
213 | {
214 | //int Result;
215 | timer gt;
216 | unsigned time;
217 | int Temp, CtlAdrsData, i;
218 | // three device ACK
219 | int ack[3];
220 |
221 | // initial values.
222 | scl <: 1;
223 | sda <: 1;
224 | sync(sda);
225 |
226 | gt :> time;
227 | time += 1000 + 1000;
228 | gt when timerafter(time) :> void;
229 |
230 | // start bit on SDI
231 | scl <: 1;
232 | sda <: 0;
233 | gt :> time;
234 | time += 1000;
235 | gt when timerafter(time) :> void;
236 | scl <: 0;
237 |
238 | // shift 7bits of address and 1bit R/W (fixed to write).
239 | // WARNING: Assume MSB first.
240 | for (i = 0; i < 8; i += 1)
241 | {
242 | Temp = (device >> (7 - i)) & 0x1;
243 | sda <: Temp;
244 | gt :> time;
245 | time += 1000;
246 | gt when timerafter(time) :> void;
247 | scl <: 1;
248 | gt :> time;
249 | time += 1000;
250 | gt when timerafter(time) :> void;
251 | scl <: 0;
252 | }
253 |
254 | // turn the data to input
255 | sda :> Temp;
256 | gt :> time;
257 | time += 1000;
258 | gt when timerafter(time) :> void;
259 | scl <: 1;
260 |
261 | // sample first ACK.
262 | sda :> ack[0];
263 | gt :> time;
264 | time += 1000;
265 | gt when timerafter(time) :> void;
266 | scl <: 0;
267 |
268 | CtlAdrsData = (addr & 0xFF);
269 |
270 | // shift first 8 bits.
271 | for (i = 0; i < 8; i += 1)
272 | {
273 | Temp = (CtlAdrsData >> (7 - i)) & 0x1;
274 | sda <: Temp;
275 | gt :> time;
276 | time += 1000;
277 | gt when timerafter(time) :> void;
278 | scl <: 1;
279 | gt :> time;
280 | time += 1000;
281 | gt when timerafter(time) :> void;
282 | scl <: 0;
283 | }
284 | // turn the data to input
285 | sda :> Temp;
286 | gt :> time;
287 | time += 1000;
288 | gt when timerafter(time) :> void;
289 | scl <: 1;
290 | // sample second ACK.
291 | sda :> ack[1];
292 | gt :> time;
293 | time += 1000;
294 | gt when timerafter(time) :> void;
295 | scl <: 0;
296 |
297 | CtlAdrsData = (data & 0xFF);
298 | // shift second 8 bits.
299 | for (i = 0; i < 8; i += 1)
300 | {
301 | Temp = (CtlAdrsData >> (7 - i)) & 0x1;
302 | sda <: Temp;
303 | gt :> time;
304 | time += 1000;
305 | gt when timerafter(time) :> void;
306 | scl <: 1;
307 | gt :> time;
308 | time += 1000;
309 | gt when timerafter(time) :> void;
310 | scl <: 0;
311 | }
312 | // turn the data to input
313 | sda :> Temp;
314 | gt :> time;
315 | time += 1000;
316 | gt when timerafter(time) :> void;
317 | scl <: 1;
318 | // sample second ACK.
319 | sda :> ack[2];
320 | gt :> time;
321 | time += 1000;
322 | gt when timerafter(time) :> void;
323 | scl <: 0;
324 | gt :> time;
325 | time += 1000;
326 | gt when timerafter(time) :> void;
327 | scl <: 1;
328 | // put the data to a good value for next round.
329 | sda <: 1;
330 | // validate all items are ACK properly.
331 | //Result = 0;
332 | //for (i = 0; i < 3; i += 1)
333 | //{
334 | //if ((ack[i]&1) != 0)
335 | //{
336 | //Result = Result | (1 << i);
337 | //}
338 | //}
339 | //return(Result);
340 | }
341 |
--------------------------------------------------------------------------------
/firmware/main.xc:
--------------------------------------------------------------------------------
1 | /**
2 | * Module: app_usb_aud_l2
3 | * Version: 5v3rc0
4 | * Build: ac6a4e693026146f3f2e1eb14f33e54ebc385068
5 | * File: main.xc
6 | *
7 | * The copyrights, all other intellectual and industrial
8 | * property rights are retained by XMOS and/or its licensors.
9 | * Terms and conditions covering the use of this code can
10 | * be found in the Xmos End User License Agreement.
11 | *
12 | * Copyright XMOS Ltd 2010
13 | *
14 | * In the case where this code is a modification of existing code
15 | * under a separate license, the separate license terms are shown
16 | * below. The modifications to the code are still covered by the
17 | * copyright notice above.
18 | *
19 | **/
20 | /**
21 | * @file main.xc
22 | * @brief XMOS L2 USB 2.0 Audio 2.0 Reference Design. Top level.
23 | * @author Ross Owen, XMOS Semiconductor Ltd
24 | * @version 1.4
25 | */
26 |
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 | #include
33 | #include
34 |
35 | #include "xud.h" /* XMOS USB Device Layer defines and functions */
36 | #include "usb.h" /* Defines from the USB 2.0 Specification */
37 |
38 |
39 | #include "customdefines.h"
40 | #include "devicedefines.h" /* Device specific defines */
41 | #include "endpoint0.h"
42 | #include "usb_buffer.h"
43 | #include "decouple.h"
44 | #include "audio.h"
45 | #ifdef SPDIF_RX
46 | # include "SpdifReceive.h"
47 | #endif
48 |
49 | void clockGen (streaming chanend c_spdif_rx, chanend c_adat_rx, out port p, chanend, chanend, chanend);
50 | void mixer(chanend, chanend, chanend);
51 | void dsp(chanend);
52 | void dsp_router(chanend, chanend, chanend, chanend);
53 |
54 | /* Cores */
55 | #define CORE_USB 0
56 | #define CORE_AUD 1
57 | #define CORE_DSP 2
58 |
59 | /* Core 0 */
60 | #define PORT_USB_RST XS1_PORT_1M
61 | #define PORT_PLL_CLK XS1_PORT_4E /* Clk Output to PLL */
62 |
63 | /* Core 1 */
64 | #define PORT_COD_CLK_BIT XS1_PORT_1I /* Bit clock */
65 | #define PORT_COD_CLK_LR XS1_PORT_1E /* LR clock */
66 | #define PORT_I2C_SCL XS1_PORT_1D
67 | #define PORT_I2C_SDA XS1_PORT_1C
68 |
69 | #define PORT_COD_DAC_0 XS1_PORT_1M
70 | #define PORT_COD_DAC_1 XS1_PORT_1F
71 | #define PORT_COD_DAC_2 XS1_PORT_1H
72 | #define PORT_COD_DAC_3 XS1_PORT_1N
73 |
74 | #define PORT_COD_ADC_0 XS1_PORT_1G
75 | #define PORT_COD_ADC_1 XS1_PORT_1A
76 | #define PORT_COD_ADC_2 XS1_PORT_1B
77 |
78 | #define PORT_COD_CLK_MAS XS1_PORT_1L
79 |
80 | on stdcore[CORE_USB] : buffered in port:4 p_spdif_rx = XS1_PORT_1K; /* K: coax, J: optical */
81 | on stdcore[CORE_USB] : out port p_usb_rst = PORT_USB_RST;
82 | on stdcore[CORE_USB] : in port p_for_mclk_count = XS1_PORT_32A;
83 | on stdcore[CORE_USB] : in port p_mclk_too = XS1_PORT_1L;
84 | on stdcore[CORE_AUD] : out port p_pll_clk = PORT_PLL_CLK;
85 | #ifdef CODEC_SLAVE
86 | on stdcore[CORE_AUD] : buffered out port:32 p_lrclk = PORT_COD_CLK_LR;
87 | on stdcore[CORE_AUD] : buffered out port:32 p_bclk = PORT_COD_CLK_BIT;
88 | #else
89 | on stdcore[CORE_AUD] : in port p_lrclk = PORT_COD_CLK_LR;
90 | on stdcore[CORE_AUD] : in port p_bclk = PORT_COD_CLK_BIT;
91 | #endif
92 | on stdcore[CORE_AUD] : port p_mclk = PORT_COD_CLK_MAS;
93 | on stdcore[CORE_AUD] : out port p_aud_cfg = XS1_PORT_4A;
94 | on stdcore[CORE_AUD] : port p_i2c_scl = PORT_I2C_SCL; // 2-wire configuration interface.
95 | on stdcore[CORE_AUD] : port p_i2c_sda = PORT_I2C_SDA;
96 | on stdcore[CORE_AUD] : buffered out port:32 p_spdif_tx = XS1_PORT_1J; // K: coax, J: optical
97 | on stdcore[CORE_AUD] : out port p_midi_tx = XS1_PORT_1O;
98 | on stdcore[CORE_AUD] : port p_midi_rx = XS1_PORT_1P;
99 | on stdcore[CORE_AUD] : buffered out port:32 p_i2s_dac[I2S_WIRES_DAC] = {PORT_COD_DAC_0, PORT_COD_DAC_1, PORT_COD_DAC_2, PORT_COD_DAC_3};
100 | on stdcore[CORE_AUD] : buffered in port:32 p_i2s_adc[I2S_WIRES_ADC] = {PORT_COD_ADC_0, PORT_COD_ADC_1, PORT_COD_ADC_2};
101 |
102 | /* Clock blocks */
103 | on stdcore[CORE_USB] : clock clk_adat_rx = XS1_CLKBLK_1;
104 | on stdcore[CORE_USB] : clock clk_spi = XS1_CLKBLK_2;
105 | on stdcore[CORE_USB] : clock clk = XS1_CLKBLK_3; /* USB clock */
106 | on stdcore[CORE_USB] : clock clk_spd_rx = XS1_CLKBLK_4;
107 | on stdcore[CORE_USB] : clock clk_master_too = XS1_CLKBLK_5; /* Master clock on USB core */
108 |
109 | on stdcore[CORE_AUD] : clock clk_audio_mclk = XS1_CLKBLK_1; /* Master clock */
110 | on stdcore[CORE_AUD] : clock clk_audio_bclk = XS1_CLKBLK_2; /* Bit clock */
111 | on stdcore[CORE_AUD] : clock clk_midi = XS1_CLKBLK_3;
112 | on stdcore[CORE_AUD] : clock clk_mst_spd = XS1_CLKBLK_4;
113 |
114 | on stdcore[CORE_AUD] : out port p_led = XS1_PORT_8B;
115 | on stdcore[CORE_AUD] : out port p_gpio = XS1_PORT_4F;
116 |
117 | /* Endpoint type tables for XUD */
118 | XUD_EpType epTypeTableOut[NUM_EP_OUT] = { XUD_EPTYPE_CTL | XUD_STATUS_ENABLE,
119 | XUD_EPTYPE_ISO};
120 |
121 | XUD_EpType epTypeTableIn[NUM_EP_IN] = { XUD_EPTYPE_CTL | XUD_STATUS_ENABLE,
122 | XUD_EPTYPE_ISO,
123 | XUD_EPTYPE_ISO,
124 | XUD_EPTYPE_BUL};
125 |
126 | void InitMixers(chanend c_mix_ctl);
127 |
128 | int main()
129 | {
130 | chan c_sof;
131 |
132 | chan c_xud_out[NUM_EP_OUT]; /* Endpoint channels for XUD */
133 | chan c_xud_in[NUM_EP_IN];
134 |
135 | chan c_aud_ctl;
136 | chan c_mix_ctl;
137 | chan c_clk_ctl;
138 |
139 | #ifdef MIXER
140 | chan c_mix_out;
141 | #endif
142 |
143 | chan c_dig_rx;
144 | chan c_del_out;
145 | chan c_dsp_out;
146 | #ifdef DEBUG_LEDS
147 | chan c_led;
148 | #endif
149 | streaming chan c_spdif_rx;
150 | chan c_adat_rx; // CT_END after each sample
151 | chan c_clk_int;
152 | chan c_dsp;
153 | chan c_dsp_ctl;
154 | chan c_peaks;
155 |
156 | par
157 | {
158 | /* Core 0 */
159 | /* USB Interface */
160 | on stdcore[0] :
161 | {
162 | #ifdef DEBUG
163 | xscope_register(0);
164 | xscope_config_io(XSCOPE_IO_BASIC);
165 | #endif
166 | puts("Hello, world from mgr!");
167 | XUD_Manager(c_xud_out, NUM_EP_OUT, c_xud_in, NUM_EP_IN,
168 | c_sof, epTypeTableOut, epTypeTableIn, p_usb_rst, clk, 1, XUD_SPEED_HS, null);
169 | }
170 |
171 | /* Endpoint 0 */
172 | on stdcore[0] :
173 | {
174 | puts("Hello, world from ep0!");
175 | InitMixers(c_mix_ctl);
176 | Endpoint0( c_xud_out[0], c_xud_in[0], c_aud_ctl, c_mix_ctl, c_clk_ctl, c_dsp_ctl);
177 | }
178 |
179 | /* Buffer / EP Man */
180 | on stdcore[0] :
181 | {
182 | set_thread_fast_mode_on();
183 | configure_clock_src(clk_master_too, p_mclk_too);
184 | set_port_clock(p_for_mclk_count, clk_master_too);
185 | start_clock(clk_master_too);
186 |
187 | puts("Hello, world from buffer!");
188 | buffer(c_xud_out[1], c_xud_in[2], c_xud_in[1],
189 | c_xud_in[3],
190 | c_sof, c_aud_ctl,
191 | p_for_mclk_count);
192 | }
193 |
194 | on stdcore[0] :
195 | {
196 | unsigned int i;
197 | puts("Hello, world from decouple!");
198 | decouple(c_mix_out, c_clk_int, c_led);
199 | }
200 | #ifdef SPDIF_RX
201 | on stdcore[0] :
202 | {
203 | puts("Hello, world from SpdifReceive!");
204 | set_thread_fast_mode_on();
205 | SpdifReceive(p_spdif_rx, c_spdif_rx, 2, clk_spd_rx);
206 | }
207 | #endif
208 |
209 | #define FULL 0x40000000
210 | #define HALF 0x16a09e66
211 |
212 | #define IDLE_TIME 30 * 600
213 |
214 | on stdcore[1] :
215 | {
216 | unsigned int i;
217 | int active;
218 | int tmr = IDLE_TIME;
219 | puts("Hello, world from LED!");
220 | while(1) {
221 | active = 1;
222 | i = inuint(c_peaks);
223 | if (i > (FULL>>0)) {
224 | p_led <: 0xff;
225 | } else if (i > (HALF>>0)) {
226 | p_led <: 0x7f;
227 | } else if (i > (FULL>>3)) {
228 | p_led <: 0x3f;
229 | } else if (i > (HALF>>3)) {
230 | p_led <: 0x1f;
231 | } else if (i > (FULL>>6)) {
232 | p_led <: 0x0f;
233 | } else if (i > (HALF>>6)) {
234 | p_led <: 0x07;
235 | } else if (i > (FULL>>9)) {
236 | p_led <: 0x03;
237 | } else if (i > (HALF>>9)) {
238 | p_led <: 0x01;
239 | } else {
240 | active = 0;
241 | }
242 | if (active) {
243 | tmr = 0;
244 | p_gpio <: 0x03;
245 | } else if (tmr < IDLE_TIME) {
246 | p_led <: 0x00;
247 | p_gpio <: 0x03;
248 | tmr++;
249 | } else {
250 | p_led <: 0x18;
251 | p_gpio <: 0x0c;
252 | }
253 | }
254 | }
255 |
256 | /* Core 1 */
257 | on stdcore[1] :
258 | {
259 | puts("Hello, world from mixer!");
260 | mixer(c_mix_out, c_dsp_out, c_mix_ctl);
261 | }
262 |
263 | /* Audio I/O (pars additional S/PDIF TX thread) */
264 | on stdcore[1] :
265 | {
266 | puts("Hello, world from AudioIO!");
267 | audio(c_del_out, c_dig_rx, null, c_peaks) ;
268 | }
269 |
270 | on stdcore[1] :
271 | {
272 | puts("Hello, world from clockGen!");
273 | clockGen(c_spdif_rx, c_adat_rx, p_pll_clk, c_dig_rx, c_clk_ctl, c_clk_int);
274 | }
275 |
276 | on stdcore[1] :
277 | {
278 | puts("Hello, world from DSP Router!");
279 | dsp_router(c_dsp_out, c_del_out, c_dsp, c_dsp_ctl);
280 | }
281 | on stdcore[2] :
282 | {
283 | puts("Hello, world from DSP!");
284 | dsp(c_dsp);
285 | }
286 | }
287 |
288 | return 0;
289 | }
290 |
291 |
--------------------------------------------------------------------------------
/firmware/repeat.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Module: module_usb_aud_shared
3 | * Version: 2v2beta14
4 | * Build: 828cd13ccba5efa7d63ff5d0c967357ccd0c8ad4
5 | * File: repeat.h
6 | *
7 | * The copyrights, all other intellectual and industrial
8 | * property rights are retained by XMOS and/or its licensors.
9 | * Terms and conditions covering the use of this code can
10 | * be found in the Xmos End User License Agreement.
11 | *
12 | * Copyright XMOS Ltd 2010
13 | *
14 | * In the case where this code is a modification of existing code
15 | * under a separate license, the separate license terms are shown
16 | * below. The modifications to the code are still covered by the
17 | * copyright notice above.
18 | *
19 | **/
20 | #ifndef N
21 | #error "N must be defined before including repeat.h"
22 | #endif
23 | #if N > 256
24 | #error "N cannot be larger than 256"
25 | #endif
26 | #ifndef BODY
27 | #error "BODY must be defined before including repeat.h"
28 | #endif
29 | #if N > 0
30 | BODY(0)
31 | #endif
32 | #if N > 1
33 | BODY(1)
34 | #endif
35 | #if N > 2
36 | BODY(2)
37 | #endif
38 | #if N > 3
39 | BODY(3)
40 | #endif
41 | #if N > 4
42 | BODY(4)
43 | #endif
44 | #if N > 5
45 | BODY(5)
46 | #endif
47 | #if N > 6
48 | BODY(6)
49 | #endif
50 | #if N > 7
51 | BODY(7)
52 | #endif
53 | #if N > 8
54 | BODY(8)
55 | #endif
56 | #if N > 9
57 | BODY(9)
58 | #endif
59 | #if N > 10
60 | BODY(10)
61 | #endif
62 | #if N > 11
63 | BODY(11)
64 | #endif
65 | #if N > 12
66 | BODY(12)
67 | #endif
68 | #if N > 13
69 | BODY(13)
70 | #endif
71 | #if N > 14
72 | BODY(14)
73 | #endif
74 | #if N > 15
75 | BODY(15)
76 | #endif
77 | #if N > 16
78 | BODY(16)
79 | #endif
80 | #if N > 17
81 | BODY(17)
82 | #endif
83 | #if N > 18
84 | BODY(18)
85 | #endif
86 | #if N > 19
87 | BODY(19)
88 | #endif
89 | #if N > 20
90 | BODY(20)
91 | #endif
92 | #if N > 21
93 | BODY(21)
94 | #endif
95 | #if N > 22
96 | BODY(22)
97 | #endif
98 | #if N > 23
99 | BODY(23)
100 | #endif
101 | #if N > 24
102 | BODY(24)
103 | #endif
104 | #if N > 25
105 | BODY(25)
106 | #endif
107 | #if N > 26
108 | BODY(26)
109 | #endif
110 | #if N > 27
111 | BODY(27)
112 | #endif
113 | #if N > 28
114 | BODY(28)
115 | #endif
116 | #if N > 29
117 | BODY(29)
118 | #endif
119 | #if N > 30
120 | BODY(30)
121 | #endif
122 | #if N > 31
123 | BODY(31)
124 | #endif
125 | #if N > 32
126 | BODY(32)
127 | #endif
128 | #if N > 33
129 | BODY(33)
130 | #endif
131 | #if N > 34
132 | BODY(34)
133 | #endif
134 | #if N > 35
135 | BODY(35)
136 | #endif
137 | #if N > 36
138 | BODY(36)
139 | #endif
140 | #if N > 37
141 | BODY(37)
142 | #endif
143 | #if N > 38
144 | BODY(38)
145 | #endif
146 | #if N > 39
147 | BODY(39)
148 | #endif
149 | #if N > 40
150 | BODY(40)
151 | #endif
152 | #if N > 41
153 | BODY(41)
154 | #endif
155 | #if N > 42
156 | BODY(42)
157 | #endif
158 | #if N > 43
159 | BODY(43)
160 | #endif
161 | #if N > 44
162 | BODY(44)
163 | #endif
164 | #if N > 45
165 | BODY(45)
166 | #endif
167 | #if N > 46
168 | BODY(46)
169 | #endif
170 | #if N > 47
171 | BODY(47)
172 | #endif
173 | #if N > 48
174 | BODY(48)
175 | #endif
176 | #if N > 49
177 | BODY(49)
178 | #endif
179 | #if N > 50
180 | BODY(50)
181 | #endif
182 | #if N > 51
183 | BODY(51)
184 | #endif
185 | #if N > 52
186 | BODY(52)
187 | #endif
188 | #if N > 53
189 | BODY(53)
190 | #endif
191 | #if N > 54
192 | BODY(54)
193 | #endif
194 | #if N > 55
195 | BODY(55)
196 | #endif
197 | #if N > 56
198 | BODY(56)
199 | #endif
200 | #if N > 57
201 | BODY(57)
202 | #endif
203 | #if N > 58
204 | BODY(58)
205 | #endif
206 | #if N > 59
207 | BODY(59)
208 | #endif
209 | #if N > 60
210 | BODY(60)
211 | #endif
212 | #if N > 61
213 | BODY(61)
214 | #endif
215 | #if N > 62
216 | BODY(62)
217 | #endif
218 | #if N > 63
219 | BODY(63)
220 | #endif
221 | #if N > 64
222 | BODY(64)
223 | #endif
224 | #if N > 65
225 | BODY(65)
226 | #endif
227 | #if N > 66
228 | BODY(66)
229 | #endif
230 | #if N > 67
231 | BODY(67)
232 | #endif
233 | #if N > 68
234 | BODY(68)
235 | #endif
236 | #if N > 69
237 | BODY(69)
238 | #endif
239 | #if N > 70
240 | BODY(70)
241 | #endif
242 | #if N > 71
243 | BODY(71)
244 | #endif
245 | #if N > 72
246 | BODY(72)
247 | #endif
248 | #if N > 73
249 | BODY(73)
250 | #endif
251 | #if N > 74
252 | BODY(74)
253 | #endif
254 | #if N > 75
255 | BODY(75)
256 | #endif
257 | #if N > 76
258 | BODY(76)
259 | #endif
260 | #if N > 77
261 | BODY(77)
262 | #endif
263 | #if N > 78
264 | BODY(78)
265 | #endif
266 | #if N > 79
267 | BODY(79)
268 | #endif
269 | #if N > 80
270 | BODY(80)
271 | #endif
272 | #if N > 81
273 | BODY(81)
274 | #endif
275 | #if N > 82
276 | BODY(82)
277 | #endif
278 | #if N > 83
279 | BODY(83)
280 | #endif
281 | #if N > 84
282 | BODY(84)
283 | #endif
284 | #if N > 85
285 | BODY(85)
286 | #endif
287 | #if N > 86
288 | BODY(86)
289 | #endif
290 | #if N > 87
291 | BODY(87)
292 | #endif
293 | #if N > 88
294 | BODY(88)
295 | #endif
296 | #if N > 89
297 | BODY(89)
298 | #endif
299 | #if N > 90
300 | BODY(90)
301 | #endif
302 | #if N > 91
303 | BODY(91)
304 | #endif
305 | #if N > 92
306 | BODY(92)
307 | #endif
308 | #if N > 93
309 | BODY(93)
310 | #endif
311 | #if N > 94
312 | BODY(94)
313 | #endif
314 | #if N > 95
315 | BODY(95)
316 | #endif
317 | #if N > 96
318 | BODY(96)
319 | #endif
320 | #if N > 97
321 | BODY(97)
322 | #endif
323 | #if N > 98
324 | BODY(98)
325 | #endif
326 | #if N > 99
327 | BODY(99)
328 | #endif
329 | #if N > 100
330 | BODY(100)
331 | #endif
332 | #if N > 101
333 | BODY(101)
334 | #endif
335 | #if N > 102
336 | BODY(102)
337 | #endif
338 | #if N > 103
339 | BODY(103)
340 | #endif
341 | #if N > 104
342 | BODY(104)
343 | #endif
344 | #if N > 105
345 | BODY(105)
346 | #endif
347 | #if N > 106
348 | BODY(106)
349 | #endif
350 | #if N > 107
351 | BODY(107)
352 | #endif
353 | #if N > 108
354 | BODY(108)
355 | #endif
356 | #if N > 109
357 | BODY(109)
358 | #endif
359 | #if N > 110
360 | BODY(110)
361 | #endif
362 | #if N > 111
363 | BODY(111)
364 | #endif
365 | #if N > 112
366 | BODY(112)
367 | #endif
368 | #if N > 113
369 | BODY(113)
370 | #endif
371 | #if N > 114
372 | BODY(114)
373 | #endif
374 | #if N > 115
375 | BODY(115)
376 | #endif
377 | #if N > 116
378 | BODY(116)
379 | #endif
380 | #if N > 117
381 | BODY(117)
382 | #endif
383 | #if N > 118
384 | BODY(118)
385 | #endif
386 | #if N > 119
387 | BODY(119)
388 | #endif
389 | #if N > 120
390 | BODY(120)
391 | #endif
392 | #if N > 121
393 | BODY(121)
394 | #endif
395 | #if N > 122
396 | BODY(122)
397 | #endif
398 | #if N > 123
399 | BODY(123)
400 | #endif
401 | #if N > 124
402 | BODY(124)
403 | #endif
404 | #if N > 125
405 | BODY(125)
406 | #endif
407 | #if N > 126
408 | BODY(126)
409 | #endif
410 | #if N > 127
411 | BODY(127)
412 | #endif
413 | #if N > 128
414 | BODY(128)
415 | #endif
416 | #if N > 129
417 | BODY(129)
418 | #endif
419 | #if N > 130
420 | BODY(130)
421 | #endif
422 | #if N > 131
423 | BODY(131)
424 | #endif
425 | #if N > 132
426 | BODY(132)
427 | #endif
428 | #if N > 133
429 | BODY(133)
430 | #endif
431 | #if N > 134
432 | BODY(134)
433 | #endif
434 | #if N > 135
435 | BODY(135)
436 | #endif
437 | #if N > 136
438 | BODY(136)
439 | #endif
440 | #if N > 137
441 | BODY(137)
442 | #endif
443 | #if N > 138
444 | BODY(138)
445 | #endif
446 | #if N > 139
447 | BODY(139)
448 | #endif
449 | #if N > 140
450 | BODY(140)
451 | #endif
452 | #if N > 141
453 | BODY(141)
454 | #endif
455 | #if N > 142
456 | BODY(142)
457 | #endif
458 | #if N > 143
459 | BODY(143)
460 | #endif
461 | #if N > 144
462 | BODY(144)
463 | #endif
464 | #if N > 145
465 | BODY(145)
466 | #endif
467 | #if N > 146
468 | BODY(146)
469 | #endif
470 | #if N > 147
471 | BODY(147)
472 | #endif
473 | #if N > 148
474 | BODY(148)
475 | #endif
476 | #if N > 149
477 | BODY(149)
478 | #endif
479 | #if N > 150
480 | BODY(150)
481 | #endif
482 | #if N > 151
483 | BODY(151)
484 | #endif
485 | #if N > 152
486 | BODY(152)
487 | #endif
488 | #if N > 153
489 | BODY(153)
490 | #endif
491 | #if N > 154
492 | BODY(154)
493 | #endif
494 | #if N > 155
495 | BODY(155)
496 | #endif
497 | #if N > 156
498 | BODY(156)
499 | #endif
500 | #if N > 157
501 | BODY(157)
502 | #endif
503 | #if N > 158
504 | BODY(158)
505 | #endif
506 | #if N > 159
507 | BODY(159)
508 | #endif
509 | #if N > 160
510 | BODY(160)
511 | #endif
512 | #if N > 161
513 | BODY(161)
514 | #endif
515 | #if N > 162
516 | BODY(162)
517 | #endif
518 | #if N > 163
519 | BODY(163)
520 | #endif
521 | #if N > 164
522 | BODY(164)
523 | #endif
524 | #if N > 165
525 | BODY(165)
526 | #endif
527 | #if N > 166
528 | BODY(166)
529 | #endif
530 | #if N > 167
531 | BODY(167)
532 | #endif
533 | #if N > 168
534 | BODY(168)
535 | #endif
536 | #if N > 169
537 | BODY(169)
538 | #endif
539 | #if N > 170
540 | BODY(170)
541 | #endif
542 | #if N > 171
543 | BODY(171)
544 | #endif
545 | #if N > 172
546 | BODY(172)
547 | #endif
548 | #if N > 173
549 | BODY(173)
550 | #endif
551 | #if N > 174
552 | BODY(174)
553 | #endif
554 | #if N > 175
555 | BODY(175)
556 | #endif
557 | #if N > 176
558 | BODY(176)
559 | #endif
560 | #if N > 177
561 | BODY(177)
562 | #endif
563 | #if N > 178
564 | BODY(178)
565 | #endif
566 | #if N > 179
567 | BODY(179)
568 | #endif
569 | #if N > 180
570 | BODY(180)
571 | #endif
572 | #if N > 181
573 | BODY(181)
574 | #endif
575 | #if N > 182
576 | BODY(182)
577 | #endif
578 | #if N > 183
579 | BODY(183)
580 | #endif
581 | #if N > 184
582 | BODY(184)
583 | #endif
584 | #if N > 185
585 | BODY(185)
586 | #endif
587 | #if N > 186
588 | BODY(186)
589 | #endif
590 | #if N > 187
591 | BODY(187)
592 | #endif
593 | #if N > 188
594 | BODY(188)
595 | #endif
596 | #if N > 189
597 | BODY(189)
598 | #endif
599 | #if N > 190
600 | BODY(190)
601 | #endif
602 | #if N > 191
603 | BODY(191)
604 | #endif
605 | #if N > 192
606 | BODY(192)
607 | #endif
608 | #if N > 193
609 | BODY(193)
610 | #endif
611 | #if N > 194
612 | BODY(194)
613 | #endif
614 | #if N > 195
615 | BODY(195)
616 | #endif
617 | #if N > 196
618 | BODY(196)
619 | #endif
620 | #if N > 197
621 | BODY(197)
622 | #endif
623 | #if N > 198
624 | BODY(198)
625 | #endif
626 | #if N > 199
627 | BODY(199)
628 | #endif
629 | #if N > 200
630 | BODY(200)
631 | #endif
632 | #if N > 201
633 | BODY(201)
634 | #endif
635 | #if N > 202
636 | BODY(202)
637 | #endif
638 | #if N > 203
639 | BODY(203)
640 | #endif
641 | #if N > 204
642 | BODY(204)
643 | #endif
644 | #if N > 205
645 | BODY(205)
646 | #endif
647 | #if N > 206
648 | BODY(206)
649 | #endif
650 | #if N > 207
651 | BODY(207)
652 | #endif
653 | #if N > 208
654 | BODY(208)
655 | #endif
656 | #if N > 209
657 | BODY(209)
658 | #endif
659 | #if N > 210
660 | BODY(210)
661 | #endif
662 | #if N > 211
663 | BODY(211)
664 | #endif
665 | #if N > 212
666 | BODY(212)
667 | #endif
668 | #if N > 213
669 | BODY(213)
670 | #endif
671 | #if N > 214
672 | BODY(214)
673 | #endif
674 | #if N > 215
675 | BODY(215)
676 | #endif
677 | #if N > 216
678 | BODY(216)
679 | #endif
680 | #if N > 217
681 | BODY(217)
682 | #endif
683 | #if N > 218
684 | BODY(218)
685 | #endif
686 | #if N > 219
687 | BODY(219)
688 | #endif
689 | #if N > 220
690 | BODY(220)
691 | #endif
692 | #if N > 221
693 | BODY(221)
694 | #endif
695 | #if N > 222
696 | BODY(222)
697 | #endif
698 | #if N > 223
699 | BODY(223)
700 | #endif
701 | #if N > 224
702 | BODY(224)
703 | #endif
704 | #if N > 225
705 | BODY(225)
706 | #endif
707 | #if N > 226
708 | BODY(226)
709 | #endif
710 | #if N > 227
711 | BODY(227)
712 | #endif
713 | #if N > 228
714 | BODY(228)
715 | #endif
716 | #if N > 229
717 | BODY(229)
718 | #endif
719 | #if N > 230
720 | BODY(230)
721 | #endif
722 | #if N > 231
723 | BODY(231)
724 | #endif
725 | #if N > 232
726 | BODY(232)
727 | #endif
728 | #if N > 233
729 | BODY(233)
730 | #endif
731 | #if N > 234
732 | BODY(234)
733 | #endif
734 | #if N > 235
735 | BODY(235)
736 | #endif
737 | #if N > 236
738 | BODY(236)
739 | #endif
740 | #if N > 237
741 | BODY(237)
742 | #endif
743 | #if N > 238
744 | BODY(238)
745 | #endif
746 | #if N > 239
747 | BODY(239)
748 | #endif
749 | #if N > 240
750 | BODY(240)
751 | #endif
752 | #if N > 241
753 | BODY(241)
754 | #endif
755 | #if N > 242
756 | BODY(242)
757 | #endif
758 | #if N > 243
759 | BODY(243)
760 | #endif
761 | #if N > 244
762 | BODY(244)
763 | #endif
764 | #if N > 245
765 | BODY(245)
766 | #endif
767 | #if N > 246
768 | BODY(246)
769 | #endif
770 | #if N > 247
771 | BODY(247)
772 | #endif
773 | #if N > 248
774 | BODY(248)
775 | #endif
776 | #if N > 249
777 | BODY(249)
778 | #endif
779 | #if N > 250
780 | BODY(250)
781 | #endif
782 | #if N > 251
783 | BODY(251)
784 | #endif
785 | #if N > 252
786 | BODY(252)
787 | #endif
788 | #if N > 253
789 | BODY(253)
790 | #endif
791 | #if N > 254
792 | BODY(254)
793 | #endif
794 | #if N > 255
795 | BODY(255)
796 | #endif
797 |
--------------------------------------------------------------------------------
/firmware/usb_buffer.xc:
--------------------------------------------------------------------------------
1 | /**
2 | * Module: module_usb_aud_shared
3 | * Version: 2v3
4 | * Build: 1f458299986de727de7ac8f49b72f8d29ea1ffab
5 | * File: usb_buffer.xc
6 | *
7 | * The copyrights, all other intellectual and industrial
8 | * property rights are retained by XMOS and/or its licensors.
9 | * Terms and conditions covering the use of this code can
10 | * be found in the Xmos End User License Agreement.
11 | *
12 | * Copyright XMOS Ltd 2010
13 | *
14 | * In the case where this code is a modification of existing code
15 | * under a separate license, the separate license terms are shown
16 | * below. The modifications to the code are still covered by the
17 | * copyright notice above.
18 | *
19 | **/
20 |
21 | #include
22 | #include
23 | #include
24 |
25 | //In this file xud.h is not included since we are interpreting the
26 | //assembly functions GetData/SetData as taking xc_ptrs
27 | //#include "xud.h"
28 |
29 | #define XUD_SPEED_HS 2
30 |
31 | #include "usb.h"
32 | #include "devicedefines.h"
33 | #include "xc_ptr.h"
34 | #include "clockcmds.h"
35 | #include "xud.h"
36 |
37 |
38 | //typedef unsigned int XUD_ep;
39 |
40 | //int XUD_GetData_NoReq(chanend c, xc_ptr buffer);
41 | //int XUD_SetData_NoReq(chanend c, xc_ptr buffer, unsigned datalength, unsigned startIndex);
42 | XUD_ep XUD_Init_Ep(chanend c_ep);
43 |
44 | inline void XUD_SetNotReady(XUD_ep e)
45 | {
46 | int chan_array_ptr;
47 | asm ("ldw %0, %1[0]":"=r"(chan_array_ptr):"r"(e));
48 | asm ("stw %0, %1[0]"::"r"(0),"r"(chan_array_ptr));
49 | }
50 |
51 | void GetADCCounts(unsigned samFreq, int &min, int &mid, int &max);
52 | #define BUFFER_SIZE_OUT (1028 >> 2)
53 | #define BUFFER_SIZE_IN (1028 >> 2)
54 |
55 | /* Packet buffers for audio data */
56 |
57 | extern unsigned int g_curSamFreqMultiplier;
58 |
59 |
60 | /* Global var for speed. Related to feedback. Used by input stream to determine IN packet size */
61 | unsigned g_speed;
62 | unsigned g_freqChange = 0;
63 |
64 | /* Interrupt EP data */
65 | unsigned char g_intData[8];
66 |
67 | unsigned char fb_clocks[16];
68 |
69 | //#define FB_TOLERANCE_TEST
70 | #define FB_TOLERANCE 0x100
71 |
72 | extern unsigned inZeroBuff[];
73 | extern unsigned g_numUsbChanIn;
74 | /**
75 | * Buffers data from audio endpoints
76 | * @param c_aud_out chanend for audio from xud
77 | * @param c_aud_in chanend for audio to xud
78 | * @param c_aud_fb chanend for feeback to xud
79 | * @return void
80 | */
81 | void buffer(register chanend c_aud_out, register chanend c_aud_in, chanend c_aud_fb,
82 | chanend c_int, chanend c_sof,
83 | chanend c_aud_ctl,
84 | in port p_off_mclk
85 | )
86 | {
87 | XUD_ep ep_aud_out = XUD_Init_Ep(c_aud_out);
88 | XUD_ep ep_aud_in = XUD_Init_Ep(c_aud_in);
89 | XUD_ep ep_aud_fb = XUD_Init_Ep(c_aud_fb);
90 | XUD_ep ep_int = XUD_Init_Ep(c_int);
91 |
92 | unsigned datalength;
93 | unsigned tmp;
94 | unsigned sampleFreq = 0;
95 | unsigned lastClock;
96 |
97 | unsigned clocks = 0;
98 |
99 |
100 | unsigned bufferIn = 1;
101 | unsigned remnant = 0, cycles;
102 | unsigned sofCount = 0;
103 | unsigned freqChange = 0;
104 | //unsigned expected = (DEFAULT_FREQ/8000)<<16;
105 |
106 | unsigned expected_fb = 0;
107 |
108 | xc_ptr aud_from_host_buffer = 0;
109 |
110 |
111 |
112 | set_thread_fast_mode_on();
113 |
114 | asm("stw %0, dp[int_usb_ep]"::"r"(ep_int));
115 | asm("stw %0, dp[aud_from_host_usb_ep]"::"r"(ep_aud_out));
116 | asm("stw %0, dp[aud_to_host_usb_ep]"::"r"(ep_aud_in));
117 | asm("stw %0, dp[buffer_aud_ctl_chan]"::"r"(c_aud_ctl));
118 |
119 | /* Wait for USB connect then setup our first packet */
120 | {
121 | int min, mid, max;
122 | int usb_speed = 0;
123 | int frameTime;
124 |
125 | while(usb_speed == 0)
126 | asm("ldw %0, dp[g_curUsbSpeed]" : "=r" (usb_speed) :);
127 |
128 | GetADCCounts(DEFAULT_FREQ, min, mid, max);
129 | asm("stw %0, dp[g_speed]"::"r"(mid << 16));
130 | if (usb_speed == XUD_SPEED_HS)
131 | mid*=NUM_USB_CHAN_IN*4;
132 | else
133 | mid*=NUM_USB_CHAN_IN*3;
134 | asm("stw %0, %1[0]"::"r"(mid),"r"(inZeroBuff));
135 |
136 | expected_fb = ((DEFAULT_FREQ * 0x2000) / 1000);
137 |
138 | }
139 |
140 | #ifdef OUTPUT
141 | SET_SHARED_GLOBAL(g_aud_from_host_flag, 1);
142 | #endif
143 |
144 | #ifdef INPUT
145 | SET_SHARED_GLOBAL(g_aud_to_host_flag, 1);
146 | #endif
147 |
148 | (fb_clocks, unsigned[])[0] = 0;
149 |
150 |
151 | {
152 | int usb_speed;
153 | int x;
154 |
155 | asm("ldaw %0, dp[fb_clocks]":"=r"(x));
156 | asm("ldw %0, dp[g_curUsbSpeed]" : "=r" (usb_speed) :);
157 |
158 | if (usb_speed == XUD_SPEED_HS)
159 | {
160 |
161 | XUD_SetReady_In(ep_aud_fb, PIDn_DATA0, x, 4);
162 |
163 | }
164 | else
165 | {
166 |
167 | XUD_SetReady_In(ep_aud_fb, PIDn_DATA0, x, 3);
168 | }
169 | }
170 |
171 | while(1)
172 | {
173 | /* Wait for response from XUD and service relevant EP */
174 | select
175 | {
176 | /* Interrupt EP, send back interrupt data. Note, request made from decouple */
177 | case inuint_byref(c_int, tmp):
178 | {
179 | int sent_ok = 0;
180 | /* Start XUD_SetData */
181 |
182 | XUD_SetData_Inline(ep_int, c_int);
183 |
184 | #if 0
185 | while (!sent_ok)
186 | {
187 | outct(c_int, 64);
188 | asm("ldw %0, dp[g_intData]":"=r"(tmp));
189 | outuint(c_int, tmp);
190 | asm("ldw %0, dp[g_intData+4]":"=r"(tmp));
191 | outct(c_int, 64);
192 | outuint(c_int, tmp);
193 | sent_ok = inuint(c_int);
194 | /* End XUD_SetData */
195 | }
196 | #endif
197 |
198 | asm("stw %0, dp[g_intFlag]" :: "r" (0) );
199 | XUD_SetNotReady(ep_int);
200 | break;
201 | }
202 |
203 | /* Sample Freq our chan count update from ep 0 */
204 | case inuint_byref(c_aud_ctl, tmp):
205 | {
206 | int min, mid, max;
207 | int usb_speed;
208 | int frameTime;
209 | asm("ldw %0, dp[g_curUsbSpeed]" : "=r" (usb_speed) :);
210 |
211 | if(tmp == SET_SAMPLE_FREQ)
212 | {
213 | sampleFreq = inuint(c_aud_ctl);
214 |
215 | /* Tidy up double buffer, note we can do better than this for 44.1 etc but better
216 | * than sending two packets at old speed! */
217 | if (usb_speed == XUD_SPEED_HS)
218 | frameTime = 8000;
219 | else
220 | frameTime = 1000;
221 |
222 | min = sampleFreq / frameTime;
223 |
224 | max = min + 1;
225 |
226 | mid = min;
227 |
228 | /* Check for INT(SampFreq/8000) == SampFreq/8000 */
229 | if((sampleFreq % frameTime) == 0)
230 | {
231 | min -= 1;
232 | }
233 | expected_fb = ((sampleFreq * 0x2000) / frameTime);
234 |
235 | asm("stw %0, dp[g_speed]"::"r"(mid << 16));
236 |
237 | if (usb_speed == XUD_SPEED_HS)
238 | mid *= NUM_USB_CHAN_IN*4;
239 | else
240 | mid *= NUM_USB_CHAN_IN*3;
241 |
242 | asm("stw %0, %1[0]"::"r"(mid),"r"(inZeroBuff));
243 |
244 | /* Reset FB */
245 | /* Note, Endpoint 0 will hold off host for a sufficient period to allow out feedback
246 | * to stabilise (i.e. sofCount == 128 to fire) */
247 | sofCount = 0;
248 | clocks = 0;
249 | remnant = 0;
250 |
251 | /* Ideally we want to wait for handshake (and pass back up) here. But we cannot keep this
252 | * thread locked, it must stay responsive to packets/SOFs. So, set a flag and check for
253 | * handshake elsewhere */
254 | /* Pass on sample freq change to decouple */
255 | SET_SHARED_GLOBAL(g_freqChange, SET_SAMPLE_FREQ);
256 | SET_SHARED_GLOBAL(g_freqChange_sampFreq, sampleFreq);
257 | SET_SHARED_GLOBAL(g_freqChange_flag, SET_SAMPLE_FREQ);
258 | }
259 | else
260 | {
261 | sampleFreq = inuint(c_aud_ctl);
262 | SET_SHARED_GLOBAL(g_freqChange, tmp); /* Set command */
263 | SET_SHARED_GLOBAL(g_freqChange_sampFreq, sampleFreq); /* Set flag */
264 | SET_SHARED_GLOBAL(g_freqChange_flag, tmp);
265 | }
266 |
267 |
268 |
269 | break;
270 | }
271 |
272 | #define MASK_16_13 (7) // Bits that should not be transmitted as part of feedback.
273 | #define MASK_16_10 (127) //(63) /* For Audio 1.0 we use a mask 1 bit longer than expected to avoid Windows LSB isses */
274 |
275 | case inuint_byref(c_sof, tmp):
276 |
277 | /* NOTE our feedback will be wrong for a couple of SOF's after a SF change due to
278 | * lastClock being incorrect */
279 | asm("#sof");
280 |
281 | /* Get MCLK count */
282 | asm (" getts %0, res[%1]" : "=r" (tmp) : "r" (p_off_mclk));
283 |
284 | GET_SHARED_GLOBAL(freqChange, g_freqChange);
285 | if(freqChange == SET_SAMPLE_FREQ)
286 | {
287 | /* Keep getting MCLK counts */
288 | lastClock = tmp;
289 | }
290 | else
291 | {
292 | unsigned mask = MASK_16_13, usb_speed;
293 |
294 | asm("ldw %0, dp[g_curUsbSpeed]" : "=r" (usb_speed) :);
295 |
296 | if(usb_speed != XUD_SPEED_HS)
297 | mask = MASK_16_10;
298 |
299 | /* Number of MCLKS this SOF, approx 125 * 24 (3000), sample by sample rate */
300 | asm("ldw %0, dp[g_curSamFreqMultiplier]":"=r"(cycles));
301 | cycles = ((int)((short)(tmp - lastClock))) * cycles;
302 |
303 | /* Any odd bits (lower than 16.23) have to be kept seperate */
304 | remnant += cycles & mask;
305 |
306 | /* Add 16.13 bits into clock count */
307 | clocks += (cycles & ~mask) + (remnant & ~mask);
308 |
309 | /* and overflow from odd bits. Remove overflow from odd bits. */
310 | remnant &= mask;
311 |
312 | /* Store MCLK for next time around... */
313 | lastClock = tmp;
314 |
315 | /* Reset counts based on SOF counting. Expect 16ms (128 HS SOFs/16 FS SOFS) per feedback poll
316 | * We always could 128 sofs, so 16ms @ HS, 128ms @ FS */
317 | if(sofCount == 128)
318 | {
319 | sofCount = 0;
320 | #ifdef FB_TOLERANCE_TEST
321 | if (clocks > (expected_fb - FB_TOLERANCE) &&
322 | clocks < (expected_fb + FB_TOLERANCE))
323 | #endif
324 | {
325 | int usb_speed;
326 | asm("stw %0, dp[g_speed]"::"r"(clocks)); // g_speed = clocks
327 | //fb_clocks = clocks;
328 |
329 | asm("ldw %0, dp[g_curUsbSpeed]" : "=r" (usb_speed) :);
330 |
331 | if (usb_speed == XUD_SPEED_HS)
332 | {
333 | (fb_clocks, unsigned[])[0] = clocks;
334 | }
335 | else
336 | {
337 | (fb_clocks, unsigned[])[0] = clocks>>2;
338 | }
339 | }
340 | #ifdef FB_TOLERANCE_TEST
341 | else {
342 | }
343 | #endif
344 | clocks = 0;
345 | }
346 |
347 | sofCount++;
348 | }
349 | break;
350 |
351 | #ifdef OUTPUT
352 | /* Audio HOST -> DEVICE */
353 | case inuint_byref(c_aud_out, tmp):
354 |
355 | asm("#h->d aud data");
356 | GET_SHARED_GLOBAL(aud_from_host_buffer, g_aud_from_host_buffer);
357 |
358 | // XUD_GetData
359 | {
360 | xc_ptr p = aud_from_host_buffer+4;
361 | xc_ptr p0 = p;
362 | int tail;
363 | while (!testct(c_aud_out))
364 | {
365 | unsigned int datum = inuint(c_aud_out);
366 | write_via_xc_ptr(p, datum);
367 | p += 4;
368 | }
369 | tail = inct(c_aud_out);
370 | datalength = p - p0 - 4;
371 | switch (tail)
372 | {
373 | case 10:
374 | // the tail is 0 which means
375 | datalength -= 2;
376 | break;
377 | default:
378 | // the tail is 2 which means the input was word aligned
379 | break;
380 | }
381 | }
382 |
383 | XUD_SetNotReady(ep_aud_out);
384 | write_via_xc_ptr(aud_from_host_buffer, datalength);
385 | /* Sync with audio thread */
386 | SET_SHARED_GLOBAL(g_aud_from_host_flag, 1);
387 |
388 | break;
389 | #endif
390 |
391 | #ifdef INPUT
392 | /* DEVICE -> HOST */
393 | case inuint_byref(c_aud_in, tmp):
394 | {
395 | XUD_SetData_Inline(ep_aud_in, c_aud_in);
396 |
397 | XUD_SetNotReady(ep_aud_in);
398 |
399 | /* Inform stream that buffer sent */
400 | SET_SHARED_GLOBAL(g_aud_to_host_flag, bufferIn+1);
401 | }
402 | break;
403 |
404 | #endif
405 |
406 | #ifdef OUTPUT
407 | /* Feedback Pipe */
408 | case inuint_byref(c_aud_fb, tmp):
409 | {
410 |
411 | int usb_speed;
412 | int x;
413 |
414 | asm("#aud fb");
415 |
416 | XUD_SetData_Inline(ep_aud_fb, c_aud_fb);
417 |
418 | asm("ldaw %0, dp[fb_clocks]":"=r"(x));
419 | asm("ldw %0, dp[g_curUsbSpeed]" : "=r" (usb_speed) :);
420 |
421 | if (usb_speed == XUD_SPEED_HS)
422 | {
423 | XUD_SetReady_In(ep_aud_fb, PIDn_DATA0, x, 4);
424 | }
425 | else
426 | {
427 | XUD_SetReady_In(ep_aud_fb, PIDn_DATA0, x, 3);
428 | }
429 | }
430 | break;
431 | #endif
432 | }
433 |
434 | }
435 |
436 | set_thread_fast_mode_off();
437 | }
438 |
--------------------------------------------------------------------------------
/firmware/XUD_EpFuncs.S:
--------------------------------------------------------------------------------
1 | /**
2 | * Module: module_xud
3 | * Version: 0v60
4 | * Build: 5749c99b7821363ba858462b29442d52f62eafe2
5 | * File: XUD_EpFuncs.S
6 | *
7 | * The copyrights, all other intellectual and industrial
8 | * property rights are retained by XMOS and/or its licensors.
9 | * Terms and conditions covering the use of this code can
10 | * be found in the Xmos End User License Agreement.
11 | *
12 | * Copyright XMOS Ltd 2010
13 | *
14 | * In the case where this code is a modification of existing code
15 | * under a separate license, the separate license terms are shown
16 | * below. The modifications to the code are still covered by the
17 | * copyright notice above.
18 | *
19 | **/
20 | /** XUD_EpFuncs.S
21 | * @brief Functions for data transfer to/from XUD
22 | * @author Ross Owen, XMOS Limited
23 | * @version 0v9
24 | */
25 | #include "usb.h"
26 |
27 | #define SR_EEBLE_BIT 0x1
28 | //int XUD_GetSetupData(chanend c, unsigned buffer[]);
29 | // r0 r1
30 | // TODO just use GetData
31 | .globl XUD_GetSetupData
32 | .globl XUD_GetSetupData.nstackwords
33 | .linkset XUD_GetSetupData.nstackwords, 0
34 | .text
35 |
36 | .cc_top XUD_GetSetupData.func, XUD_GetSetupData
37 | XUD_GetSetupData:
38 | ldw r2, r0[0]
39 | ldw r11, r0[1]
40 | stw r11, r2[0]
41 | ldw r0, r0[2]
42 |
43 | XUD_GetSetupData_Retry:
44 | out res[r0], r1 // TODO Should only need CT
45 |
46 |
47 | testct r11, res[r0] // Test whether there is a RESET/SUSPEND exception
48 | bt r11, ResetSuspend
49 |
50 | in r11, res[r0]
51 | SetupDataLoop:
52 | testct r11, res[r0]
53 | bt r11, XUD_GetSetupData_Retry
54 | in r11, res[r0] // r2: 0
55 | stw r11, r1[0]
56 | testct r11, res[r0]
57 | bt r11, XUD_GetSetupData_Retry
58 | in r11, res[r0] // r2: 0
59 | stw r11, r1[1]
60 | inct r11, res[r0] // tail or 9 for crc error
61 | sub r11, r11, 9
62 | bf r11, XUD_GetSetupData_Retry
63 | ldc r11, 0
64 | stw r11, r2[0] // Zero ready entry
65 | ldc r0, 8
66 |
67 | retsp 0
68 | .cc_bottom XUD_GetSetupData.func
69 |
70 |
71 | .globl XUD_GetData_NoReq
72 | .globl XUD_GetData_NoReq.nstackwords
73 | .linkset XUD_GetData_NoReq.nstackwords, 0
74 |
75 | //int XUD_GetData(chanend c, unsigned buffer[]);
76 | // r0 r1
77 |
78 | .globl XUD_GetData
79 | .globl XUD_GetData.nstackwords
80 | .linkset XUD_GetData.nstackwords, 0
81 | .text
82 |
83 | .cc_top XUD_GetData.func, XUD_GetData
84 | XUD_GetData:
85 | ldw r2, r0[0]
86 | ldw r11, r0[1]
87 | stw r11, r2[0] // Mark EP as ready
88 | ldw r0, r0[2]
89 | XUD_GetDataRetry:
90 | out res[r0], r1 // TODO Should only need CT
91 |
92 | testct r11, res[r0] // Test whether there is a RESET/SUSPEND exception
93 | bt r11, ResetSuspend
94 |
95 | in r11, res[r0] // Wait for XUD response
96 |
97 | XUD_GetData_NoReq: // Entry for _NoReq
98 | testct r3, res[r0] // Wait for data (or end)
99 | bt r3, DataEnd
100 |
101 | DataLoop:
102 | in r11, res[r0] // r2: 0
103 | stw r11, r1[r3]
104 | add r3, r3, 1
105 | testct r11, res[r0]
106 | bf r11, DataLoop
107 |
108 | DataEnd:
109 | inct r11, res[r0] // r11 is tail length (bytes + 10)
110 | // or 9 for crc error
111 | sub r11, r11, 10
112 |
113 | CalcdataLength:
114 | shl r3, r3, 2 // Num received words to bytes
115 | add r3, r11, r3 // r11: Total bytes received (Note this includes 2 byte crc)
116 |
117 | add r11, r11, 1
118 | bf r11, XUD_GetDataBadCRC // CRC error, restart
119 |
120 | ldc r11, 0
121 | stw r11, r2[0] // Zero ready entry
122 |
123 | sub r0, r3, 6 // CRC correction and extra increment
124 |
125 | retsp 0
126 |
127 | ResetSuspend:
128 | ldc r11, 0
129 | stw r11, r2[0] // Zero ready entry
130 |
131 | mkmsk r0, 32
132 | Return:
133 | retsp 0
134 |
135 | XUD_GetDataBadCRC:
136 | bu XUD_GetDataRetry
137 | .cc_bottom XUD_GetData.func
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 | // Note: Assumes startIndex is word aligned
151 | //int XUD_SetData_indexed(chanend c, unsigned buffer[], unsigned datasize, unsigned startIndex unsigned pid);
152 | // r0 r1 r2 r3
153 |
154 | .globl XUD_SetData_NoReq
155 | .globl XUD_SetData_NoReq.nstackwords
156 | .linkset XUD_SetData_NoReq.nstackwords, 0
157 |
158 | .globl XUD_SetData
159 | .globl XUD_SetData.nstackwords
160 | .linkset XUD_SetData.nstackwords, 7
161 | .text
162 |
163 | .cc_top XUD_SetData.func, XUD_SetData
164 | XUD_SetData:
165 | entsp 7
166 | stw r0, sp[1] // Reg save (for retry)
167 | stw r1, sp[2]
168 | stw r2, sp[3]
169 | stw r3, sp[4]
170 | stw r5, sp[5]
171 |
172 | XUD_SetDataRetry:
173 | stw r4, sp[0]
174 |
175 | ldw r11, sp[8] // Load PID toggle param from stack
176 | bt r11, XUD_SetData_PidReset
177 |
178 | XUD_SetData_PidToggle:
179 | ldw r11, r0[4] // Load EP PID from structure
180 | ldc r4, 0x88
181 | xor r11, r11, r4
182 | stw r11, r0[4]
183 |
184 | XUD_SetData_PidReset:
185 | stw r11, r0[4] // Store back Reset PID
186 |
187 |
188 | XUD_SetData_NoReq:
189 | add r1, r1, r3 // Add start index to buffer address
190 |
191 | CalcTailLength:
192 | shl r3, r2, 5 // Taillength: bytes to bits * 2
193 | zext r3, 7
194 |
195 | SetupLoopTerm:
196 | shr r2, r2, 2 // r2: datalength (bytes) ---> r2: datalength (words)
197 |
198 | AdjustBufferPointer:
199 | shl r5, r2, 2 // Get end off buffer address
200 | add r1, r1, r5
201 |
202 | NegativeIndex: // Produce negtive offset from end of buffer
203 | neg r2, r2
204 |
205 | LoadFirstWord:
206 | ldw r5, r1[r2] // Load first word.. (done to save branching to load)
207 |
208 | ldw r4, r0[2] // Load channel
209 | out res[r4], r11 // Send PID
210 |
211 | ldw r4, r0[0]
212 | ldw r11, r0[1] // Load chan
213 | ldw r0, r0[2]
214 |
215 | outct res[r0], r3 // Out tail length
216 | bf r2, XUD_SetData_ShortPacket
217 |
218 | XUD_SetData_DataRdy:
219 | stw r11, r4[0] // Mark EP as ready to go
220 |
221 | testct r11, res[r0] // Test whether there is a RESET/SUSPEND exception
222 | bt r11, ResetSuspend2
223 | in r11, res[r0] // Wait for response to request to send
224 |
225 | XUD_SetData_OutputLoop_Out:
226 | OutputLoop:
227 | out res[r0], r5
228 | add r2, r2, 1
229 | ldw r5, r1[r2]
230 | bt r2, OutputLoop // NOTE: We have a instruction spare here
231 |
232 | XUD_SetData_OutputLoop_End:
233 | outct res[r0], r3 // Send out tail length, note: safe as only CT 1 and 2 are reserved (END and PAUSE)
234 |
235 | SendTail:
236 | out res[r0], r5
237 | in r1, res[r0]
238 | ldc r0, 0
239 | bf r1, Return2
240 |
241 | ldw r0, sp[1]
242 | ldw r1, sp[2]
243 | ldw r2, sp[3]
244 | ldw r3, sp[4]
245 | ldw r5, sp[5]
246 |
247 | bu XUD_SetDataRetry
248 |
249 | Return2:
250 | ldc r11, 0
251 | stw r11, r4[0] // Zero ready entry
252 | ldw r4, sp[0]
253 | ldw r5, sp[5]
254 | retsp 7
255 |
256 | ResetSuspend2:
257 |
258 | mkmsk r0, 32
259 | bu Return2
260 |
261 | .cc_bottom XUD_SetData.func
262 |
263 | XUD_SetData_ShortPacket:
264 |
265 | stw r11, r4[0]
266 |
267 | testct r11, res[r0] // Test whether there is a RESET/SUSPEND exception
268 | bt r11, ResetSuspend2
269 | in r11, res[r0] // Wait for response to request to send
270 |
271 | //outct res[r0], r3 // Out tail length
272 |
273 | XUD_SetData_OutTail_Short:
274 | outct res[r0], r3 // Send out tail length, note: safe as only CT 1 and 2 are reserved (END and PAUSE)
275 |
276 | out res[r0], r5
277 | in r1, res[r0]
278 | ldc r0, 0
279 | bf r1, Return2
280 |
281 | ldw r0, sp[1]
282 | ldw r1, sp[2]
283 | ldw r2, sp[3]
284 | ldw r3, sp[4]
285 | ldw r5, sp[5]
286 |
287 | bu XUD_SetDataRetry
288 |
289 |
290 | .globl XUD_ResetEndpoint
291 | .globl XUD_ResetEndpoint.nstackwords
292 | .linkset XUD_ResetEndpoint.nstackwords, 1
293 |
294 | .cc_top XUD_ResetEndpoint.func, XUD_ResetEndpoint
295 | XUD_ResetEndpoint:
296 | entsp 1
297 | ldw r0, r0[2]
298 | bf r1, .L0
299 | ldw r1, r1[0]
300 | ldw r1, r1[2]
301 | .L0:
302 | bl XUD_ResetEndpoint0
303 | retsp 1
304 | .cc_bottom XUD_ResetEndpoint.func
305 |
306 | .globl XUD_SetReady.nstackwords
307 | .linkset XUD_SetReady.nstackwords, 0
308 |
309 | .cc_top XUD_SetReady.func, XUD_SetReady
310 | XUD_SetReady:
311 | ldw r0, r0[2]
312 | out res[r0], r1
313 | ldw r11, r0[0]
314 | ldw r2, r0[1]
315 | stw r2, r11[0]
316 | retsp 0
317 | .cc_bottom XUD_SetReady.func
318 |
319 |
320 | .globl XUD_SetStall_Out
321 | .globl XUD_SetStall_Out.nstackwords
322 | .linkset XUD_SetStall_Out.nstackwords, 0
323 |
324 | /* R0: ep number */
325 | .cc_top XUD_SetStall_Out.func, XUD_SetStall_Out
326 | XUD_SetStall_Out:
327 | ldaw r1, dp[handshakeTable_OUT]
328 | ldc r2, PIDn_STALL
329 | stw r2, r1[r0]
330 | retsp 0
331 | .cc_bottom XUD_SetStall_Out.func
332 |
333 |
334 | .globl XUD_SetStall_In
335 | .globl XUD_SetStall_In.nstackwords
336 | .linkset XUD_SetStall_In.nstackwords, 0
337 |
338 | /* R0: ep number */
339 | .cc_top XUD_SetStall_In.func, XUD_SetStall_In
340 | XUD_SetStall_In:
341 | ldaw r1, dp[handshakeTable_IN]
342 | ldc r2, PIDn_STALL
343 | stw r2, r1[r0]
344 | retsp 0
345 | .cc_bottom XUD_SetStall_In.func
346 |
347 | .globl XUD_UnStall_Out
348 | .globl XUD_UnStall_Out.nstackwords
349 | .linkset XUD_UnStall_Out.nstackwords, 0
350 |
351 | /* R0: ep number */
352 | .cc_top XUD_UnStall_Out.func, XUD_UnStall_Out
353 | XUD_UnStall_Out:
354 | ldaw r1, dp[handshakeTable_OUT]
355 | ldc r2, PIDn_NAK
356 | stw r2, r1[r0]
357 | retsp 0
358 | .cc_bottom XUD_UnStall_Out.func
359 |
360 |
361 | .globl XUD_UnStall_In
362 | .globl XUD_UnStall_In.nstackwords
363 | .linkset XUD_UnStall_In.nstackwords, 0
364 |
365 | /* R0: ep number */
366 | .cc_top XUD_UnStall_In.func, XUD_UnStall_In
367 | XUD_UnStall_In:
368 | ldaw r1, dp[handshakeTable_IN]
369 | ldc r2, PIDn_NAK
370 | stw r2, r1[r0]
371 | retsp 0
372 | .cc_bottom XUD_UnStall_In.func
373 |
--------------------------------------------------------------------------------
/firmware/mkdescriptors.py:
--------------------------------------------------------------------------------
1 | import struct
2 |
3 | CS_INTERFACE = 0x24
4 | HEADER = 0x01
5 | INPUT_TERMINAL = 0x02
6 | OUTPUT_TERMINAL = 0x03
7 | MIXER_UNIT = 0x04
8 | SELECTOR_UNIT = 0x05
9 | FEATURE_UNIT = 0x06
10 | EFFECT_UNIT = 0x07
11 | PROCESSING_UNIT = 0x08
12 | EXTENSION_UNIT = 0x09
13 | CLOCK_SOURCE = 0x0a
14 | CLOCK_SELECTOR = 0x0b
15 | CLOCK_MULTIPLIER = 0x0c
16 | SAMPLE_RATE_CONVERTER = 0x0d
17 |
18 | #channels = "FL FR FC LFE BL BR"
19 | channels = "FL FR BL BR FC LFE"
20 | for i,c in enumerate(channels.split()):
21 | globals()["C_%s" % c] = 1 << i
22 | for i,c in enumerate(channels.split()):
23 | globals()["%s" % c] = i + 1
24 |
25 | CHAN_STEREO = (2, C_FL | C_FR)
26 | CHAN_6CH = (6, C_FL | C_FR | C_FC | C_LFE | C_BL | C_BR)
27 | MASTER = 0
28 |
29 | RO = 0x01
30 | RW = 0x03
31 |
32 | USB_STREAMING = 0x0101
33 | LINE_CONNECTOR = 0x0603
34 | SPDIF_INTERFACE = 0x0605
35 |
36 | UP_DOWNMIX_PROCESS = 0x01
37 |
38 | CLOCK_EXTERNAL = 0x00
39 | CLOCK_INT_FIXED = 0x01
40 |
41 | HOME_THEATER = 0x02
42 |
43 | string_offset = 6
44 | strings = []
45 | audio_descriptors = []
46 |
47 | def mkstring(s):
48 | if s is None:
49 | return 0
50 | if s in strings:
51 | return strings.index(s) + string_offset
52 | else:
53 | strings.append(s)
54 | return len(strings) - 1 + string_offset
55 |
56 | class Descriptor(object):
57 | def __init__(self, type):
58 | self.type = type
59 |
60 | def build(self, data):
61 | data = struct.pack("
27 | #include
28 | #include
29 |
30 | #include "xud.h" /* XUD user defines and functions */
31 | #include "usb.h" /* Defines from USB 2.0 Spec */
32 | #include "usbaudio20.h" /* Defines from USB Audio 2.0 spec */
33 |
34 | #include "devicedefines.h"
35 | #include "DescriptorRequests.h" /* This device's descriptors */
36 | #include "descriptors_2.h" /* Descriptors */
37 | #include "clockcmds.h"
38 | #include "audiostream.h"
39 |
40 | /* Handles Audio Class requests */
41 | int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, SetupPacket &sp, chanend c_audioControl, chanend ?c_mix_ctl, chanend ?c_clk_ctl);
42 | int VendorRequests(XUD_ep ep0_out, XUD_ep ep0_in, SetupPacket &sp, chanend c_dsp_ctl);
43 |
44 | /* Global var for current frequency, set to default freq */
45 | unsigned int g_curSamFreq = DEFAULT_FREQ;
46 | unsigned int g_curSamFreq48000Family = DEFAULT_FREQ % 48000 == 0;
47 | unsigned int g_curSamFreqMultiplier = DEFAULT_FREQ / 48000;
48 |
49 | int min(int x, int y);
50 |
51 | /* Records alt setting for each interface */
52 | int interfaceAlt[NUM_INTERFACES] = {0};
53 |
54 | /* Global current device config var*/
55 | unsigned g_config = 0;
56 |
57 | /* Global endpoint status arrays */
58 | unsigned g_epStatusOut[NUM_EP_OUT];
59 | unsigned g_epStatusIn[NUM_EP_IN];
60 |
61 | /* Global variable for current USB bus speed (i.e. FS/HS) */
62 | unsigned g_curUsbSpeed = 0;
63 |
64 | /* Used when setting/clearing EP halt */
65 | void SetEndpointStatus(unsigned epNum, unsigned status)
66 | {
67 | /* Inspect for IN bit */
68 | if( epNum & 0x80 )
69 | {
70 | epNum &= 0x7f;
71 |
72 | /* Range check */
73 | if(epNum < NUM_EP_IN)
74 | {
75 | g_epStatusIn[ epNum & 0x7F ] = status;
76 | }
77 | }
78 | else
79 | {
80 | if(epNum < NUM_EP_OUT)
81 | {
82 | g_epStatusOut[ epNum ] = status;
83 | }
84 | }
85 | }
86 |
87 | #define STR_USENG 0x0409
88 |
89 | #define DESC_STR_LANGIDS \
90 | { \
91 | STR_USENG & 0xff, /* 2 wLangID[0] */ \
92 | STR_USENG>>8, /* 3 wLangID[0] */ \
93 | '\0' \
94 | }
95 |
96 | /* String descriptors */
97 | static unsigned char strDesc_langIDs[] = DESC_STR_LANGIDS;
98 |
99 | /* Endpoint 0 function. Handles all requests to the device */
100 | void Endpoint0( chanend c_ep0_out, chanend c_ep0_in, chanend c_audioControl, chanend ?c_mix_ctl, chanend ?c_clk_ctl, chanend c_dsp_ctl)
101 | {
102 | unsigned char buffer[512];
103 | SetupPacket sp;
104 | XUD_ep ep0_out = XUD_Init_Ep(c_ep0_out);
105 | XUD_ep ep0_in = XUD_Init_Ep(c_ep0_in);
106 |
107 | /* Init endpoint status tables */
108 | for (int i = 0; i++; i < NUM_EP_OUT)
109 | g_epStatusOut[i] = 0;
110 |
111 | for (int i = 0; i++; i < NUM_EP_IN)
112 | g_epStatusIn[i] = 0;
113 |
114 | /* Copy langIDs string desc into string[0] */
115 | safememcpy(strDescs_Audio2[0], strDesc_langIDs, sizeof(strDesc_langIDs));
116 |
117 | while(1)
118 | {
119 | int retVal = 1;
120 |
121 | /* Do standard enumeration requests */
122 | if(g_curUsbSpeed == XUD_SPEED_HS)
123 | {
124 |
125 | /* Return Audio 2.0 Descriptors */
126 | cfgDesc_Audio2[1] = CONFIGURATION;
127 | cfgDesc_Null[1] = OTHER_SPEED_CONFIGURATION;
128 |
129 | retVal = DescriptorRequests(ep0_out, ep0_in,
130 | devDesc_Audio2, sizeof(devDesc_Audio2),
131 | cfgDesc_Audio2, sizeof(cfgDesc_Audio2),
132 | devQualDesc_Null, sizeof(devQualDesc_Null),
133 | cfgDesc_Null, sizeof(cfgDesc_Null),
134 | strDescs_Audio2, sp);
135 | }
136 | else
137 | {
138 | /* Return descriptors for full-speed - NULL */
139 | cfgDesc_Null[1] = CONFIGURATION;
140 | cfgDesc_Audio2[1] = OTHER_SPEED_CONFIGURATION;
141 |
142 | retVal = DescriptorRequests(ep0_out, ep0_in,
143 | devDesc_Null, sizeof(devDesc_Null),
144 | cfgDesc_Null, sizeof(cfgDesc_Null),
145 | devQualDesc_Audio2, sizeof(devQualDesc_Audio2),
146 | cfgDesc_Audio2, sizeof(cfgDesc_Audio2),
147 | strDescs_Audio2, sp);
148 | }
149 |
150 | if (retVal == 1)
151 | {
152 | /* Request not covered by XUD_DoEnumReqs() so decode ourselves */
153 | /* Inspect Request type and Receipient */
154 | switch( (sp.bmRequestType.Recipient ) | (sp.bmRequestType.Type << 5) )
155 | {
156 | case STANDARD_INTERFACE_REQUEST:
157 |
158 | switch(sp.bRequest)
159 | {
160 | /* Set Interface */
161 | case SET_INTERFACE:
162 |
163 |
164 | #if defined(OUTPUT) && defined(INPUT)
165 | /* Check for stream start stop on output and input audio interfaces */
166 | if(sp.wValue && !interfaceAlt[1] && !interfaceAlt[2])
167 | {
168 | /* If start and input AND output not currently running */
169 | AudioStreamStart();
170 | }
171 | else if(((sp.wIndex == 1)&& (!sp.wValue)) && interfaceAlt[1] && (!interfaceAlt[2]))
172 | {
173 | /* if output stop and output running and input not running */
174 | AudioStreamStop();
175 | }
176 | else if(((sp.wIndex == 2) && (!sp.wValue)) && interfaceAlt[2] && (!interfaceAlt[1]))
177 | {
178 | /* if input stop and input running and output not running */
179 | AudioStreamStop();
180 | }
181 | #elif defined(OUTPUT) || defined(INPUT)
182 | if(sp.wValue && (!interfaceAlt[1]))
183 | {
184 | /* if start and not currently running */
185 | AudioStreamStart();
186 | }
187 | else if (!sp.wValue && interfaceAlt[1])
188 | {
189 | /* if stop and currently running */
190 | AudioStreamStop();
191 | }
192 |
193 | #endif
194 | /* Record interface change */
195 | if( sp.wIndex < NUM_INTERFACES )
196 | interfaceAlt[sp.wIndex] = sp.wValue;
197 | #if 1
198 | /* Check for audio stream from host start/stop */
199 | if(sp.wIndex == 2) // Input interface
200 | {
201 | switch(sp.wValue)
202 | {
203 | case 0:
204 |
205 | break;
206 |
207 | case 1:
208 | /* Stream active + 0 chans */
209 | outuint(c_audioControl, SET_CHAN_COUNT_IN);
210 | outuint(c_audioControl, NUM_USB_CHAN_IN);
211 |
212 | #ifdef ADAT_RX
213 | outuint(c_clk_ctl, SET_SMUX);
214 | outuint(c_clk_ctl, 0);
215 | outct(c_clk_ctl, XS1_CT_END);
216 | #endif
217 |
218 | break;
219 |
220 | #ifdef ADAT_RX
221 | case 2:
222 |
223 | /* Stream active + 8 chans */
224 | outuint(c_audioControl, SET_CHAN_COUNT_IN);
225 | outuint(c_audioControl, NUM_USB_CHAN_IN-4);
226 |
227 | outuint(c_clk_ctl, SET_SMUX);
228 | outuint(c_clk_ctl, 1);
229 | outct(c_clk_ctl, XS1_CT_END);
230 | break;
231 |
232 | case 3:
233 | outuint(c_audioControl, SET_CHAN_COUNT_IN);
234 | outuint(c_audioControl, NUM_USB_CHAN_IN-6);
235 |
236 |
237 | outuint(c_clk_ctl, SET_SMUX);
238 | outuint(c_clk_ctl, 1);
239 | outct(c_clk_ctl, XS1_CT_END);
240 | /* Stream active + 8 chans */
241 | //outuint(c_audioControl, 8);
242 | // Handshake
243 | //chkct(c_audioControl, XS1_CT_END);
244 |
245 | break;
246 |
247 | #endif
248 |
249 | }
250 | }
251 | #endif
252 | /* No data stage for this request, just do data stage */
253 | retVal = XUD_DoSetRequestStatus(ep0_in, 0);
254 | break;
255 |
256 | /* A device must support the GetInterface request if it has alternate setting for that interface */
257 | case GET_INTERFACE:
258 |
259 | buffer[0] = 0;
260 |
261 | /* Bounds check */
262 | if( sp.wIndex < NUM_INTERFACES )
263 | buffer[0] = interfaceAlt[sp.wIndex];
264 |
265 | retVal = XUD_DoGetRequest(ep0_out, ep0_in, buffer, 1, sp.wLength);
266 | break;
267 |
268 |
269 | default:
270 | printstr("Unknown Standard Interface Request: ");
271 | printhexln(sp.bRequest);
272 | printhexln(sp.bmRequestType.Type);
273 | printhexln(sp.bmRequestType.Recipient);
274 | printhexln(sp.bmRequestType.Recipient | (sp.bmRequestType.Type << 5));
275 | break;
276 | }
277 | break;
278 |
279 | /* Recipient: Device */
280 | case STANDARD_DEVICE_REQUEST:
281 |
282 | /* Standard Device requests (8) */
283 | switch( sp.bRequest )
284 | {
285 |
286 | /* Set Device Address: This is a unique set request. */
287 | case SET_ADDRESS:
288 |
289 | /* Status stage: Send a zero length packet */
290 | retVal = XUD_SetBuffer_ResetPid(ep0_in, buffer, 0, PIDn_DATA1);
291 |
292 | /* TODO We should wait until ACK is received for status stage before changing address */
293 | //XUD_Sup_Delay(50000);
294 | {
295 | timer t;
296 | unsigned time;
297 | t :> time;
298 | t when timerafter(time+50000) :> void;
299 | }
300 |
301 | /* Set device address in XUD */
302 | XUD_SetDevAddr(sp.wValue);
303 |
304 | break;
305 |
306 |
307 | /* TODO Check direction */
308 | /* Standard request: SetConfiguration */
309 | case SET_CONFIGURATION:
310 |
311 | g_config = sp.wValue;
312 |
313 | /* No data stage for this request, just do status stage */
314 | retVal = XUD_DoSetRequestStatus(ep0_in, 0);
315 | break;
316 |
317 | case GET_CONFIGURATION:
318 | buffer[0] = g_config;
319 | retVal = XUD_DoGetRequest(ep0_out, ep0_in, buffer, 1, sp.wLength);
320 | break;
321 |
322 | /* Get Status request */
323 | case GET_STATUS:
324 |
325 | buffer[0] = 0; // bus powered
326 | buffer[1] = 0; // remote wakeup not supported
327 |
328 | retVal = XUD_DoGetRequest(ep0_out, ep0_in, buffer, 2, sp.wLength);
329 | break;
330 |
331 |
332 | default:
333 | XUD_Error("Unknown device request");
334 | break;
335 |
336 | }
337 | break;
338 |
339 | /* Receipient: Endpoint */
340 | case STANDARD_ENDPOINT_REQUEST:
341 |
342 | /* Standard endpoint requests */
343 | switch ( sp.bRequest )
344 | {
345 |
346 | /* ClearFeature */
347 | case CLEAR_FEATURE:
348 |
349 | switch ( sp.wValue )
350 | {
351 | case ENDPOINT_HALT:
352 |
353 | /* Mark the endpoint status */
354 |
355 | SetEndpointStatus(sp.wIndex, 0);
356 |
357 | /* No data stage for this request, just do status stage */
358 | retVal = XUD_DoSetRequestStatus(ep0_in, 0);
359 |
360 | break;
361 |
362 |
363 | default:
364 | XUD_Error( "Unknown request in Endpoint ClearFeature" );
365 | break;
366 | }
367 | break; /* B_REQ_CLRFEAR */
368 |
369 | /* SetFeature */
370 | case SET_FEATURE:
371 |
372 | switch( sp.wValue )
373 | {
374 | case ENDPOINT_HALT:
375 |
376 | /* Check request is in range */
377 | SetEndpointStatus(sp.wIndex, 1);
378 |
379 | break;
380 |
381 | default:
382 | XUD_Error("Unknown feature in SetFeature Request");
383 | break;
384 | }
385 |
386 |
387 | retVal = XUD_DoSetRequestStatus(ep0_in, 0);
388 |
389 | break;
390 |
391 |
392 |
393 | /* Endpoint GetStatus Request */
394 | case GET_STATUS:
395 |
396 | buffer[0] = 0;
397 | buffer[1] = 0;
398 |
399 | if( sp.wIndex & 0x80 )
400 | {
401 | /* IN Endpoint */
402 | if((sp.wIndex&0x7f) < NUM_EP_IN)
403 | {
404 | buffer[0] = ( g_epStatusIn[ sp.wIndex & 0x7F ] & 0xff );
405 | buffer[1] = ( g_epStatusIn[ sp.wIndex & 0x7F ] >> 8 );
406 | }
407 | }
408 | else
409 | {
410 | /* OUT Endpoint */
411 | if(sp.wIndex < NUM_EP_OUT)
412 | {
413 | buffer[0] = ( g_epStatusOut[ sp.wIndex ] & 0xff );
414 | buffer[1] = ( g_epStatusOut[ sp.wIndex ] >> 8 );
415 | }
416 | }
417 |
418 | retVal = XUD_DoGetRequest(ep0_out, ep0_in, buffer, 2, sp.wLength);
419 |
420 | break;
421 |
422 | default:
423 | //printstrln("Unknown Standard Endpoint Request");
424 | break;
425 |
426 | }
427 | break;
428 |
429 | case CLASS_INTERFACE_REQUEST:
430 | case CLASS_ENDPOINT_REQUEST:
431 | {
432 | unsigned interfaceNum = sp.wIndex & 0xff;
433 | unsigned request = (sp.bmRequestType.Recipient ) | (sp.bmRequestType.Type << 5);
434 |
435 | retVal = AudioClassRequests_2(ep0_out, ep0_in, sp, c_audioControl, c_mix_ctl, c_clk_ctl);
436 |
437 | }
438 | break;
439 |
440 | case VENDOR_DEVICE_REQUEST: {
441 | retVal = VendorRequests(ep0_out, ep0_in, sp, c_dsp_ctl);
442 | break;
443 | }
444 |
445 | default:
446 | //printstr("unrecognised request\n");
447 | //printhexln(sp.bRequest);
448 | //printhexln(sp.bmRequestType.Type);
449 | //printhexln(sp.bmRequestType.Recipient);
450 | //printhexln(sp.bmRequestType.Recipient | (sp.bmRequestType.Type << 5));
451 | break;
452 |
453 |
454 | }
455 |
456 | } /* if(retVal == 0) */
457 |
458 | if(retVal == 1)
459 | {
460 | /* Did not handle request - Protocol Stall Secion 8.4.5 of USB 2.0 spec
461 | * Detailed in Section 8.5.3. Protocol stall is unique to control pipes.
462 | Protocol stall differs from functional stall in meaning and duration.
463 | A protocol STALL is returned during the Data or Status stage of a control
464 | transfer, and the STALL condition terminates at the beginning of the
465 | next control transfer (Setup). The remainder of this section refers to
466 | the general case of a functional stall */
467 |
468 | dprintf("Stall\n");
469 | XUD_SetStall_Out(0);
470 | XUD_SetStall_In(0);
471 | }
472 |
473 | if (retVal < 0)
474 | {
475 | g_curUsbSpeed = XUD_ResetEndpoint(ep0_in, ep0_out);
476 |
477 | g_config = 0;
478 | }
479 | }
480 | }
481 |
--------------------------------------------------------------------------------