From 5adbe0c4a68ae5a7ab5203e393fd3370c173bc07 Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Tue, 28 May 2013 17:24:40 +0100 Subject: [PATCH] Working to add generic DSD support --- module_usb_audio/audio.xc | 60 +++++++++++--- module_usb_audio/main.xc | 46 +++++------ module_usb_audio/ports/audioports.h | 100 +++++++++++++++++++++++- module_usb_audio/ports/audioports.xc | 112 ++++++++++++++++++++++----- 4 files changed, 264 insertions(+), 54 deletions(-) diff --git a/module_usb_audio/audio.xc b/module_usb_audio/audio.xc index 2d03746d..d56e08db 100755 --- a/module_usb_audio/audio.xc +++ b/module_usb_audio/audio.xc @@ -14,9 +14,9 @@ #include #include +#include "devicedefines.h" #include "audioports.h" #include "audiohw.h" -#include "devicedefines.h" #include "SpdifTransmit.h" //#define DSD_OUTPUT 1 @@ -52,9 +52,8 @@ extern in port p_bclk; unsigned dsdMode = 0; #ifdef DSD_OUTPUT -#define p_dsd_clk p_bclk -#define p_dsd_left p_i2s_dac[0] -#define p_dsd_right p_lrclk + + #define DSD_MARKER_1 0xFA #define DSD_MARKER_2 0x05 #define DSD_MARKER_XOR 0xFF @@ -76,6 +75,9 @@ extern clock clk_mst_spd; extern void device_reboot(void); + + + /* I2S delivery thread */ #pragma unsafe arrays unsigned deliver(chanend c_out, chanend ?c_spd_out, unsigned divide, chanend ?c_dig_rx, chanend ?c_adc) @@ -100,7 +102,7 @@ unsigned deliver(chanend c_out, chanend ?c_spd_out, unsigned divide, chanend ?c_ #ifdef DSD_OUTPUT unsigned dsdMarker = DSD_MARKER_2; /* This alternates between DSD_MARKER_1 and DSD_MARKER_2 */ int dsdCount = 0; - int everyOther = 0; + int everyOther = 1; unsigned dsdSample_l = 0; unsigned dsdSample_r = 0; #endif @@ -162,6 +164,9 @@ unsigned deliver(chanend c_out, chanend ?c_spd_out, unsigned divide, chanend ?c_ } #ifndef CODEC_MASTER + + if(!dsdMode) + { /* Clear I2S port buffers */ clearbuf(p_lrclk); @@ -219,6 +224,7 @@ unsigned deliver(chanend c_out, chanend ?c_spd_out, unsigned divide, chanend ?c_ } #endif + p_lrclk <: 0x7FFFFFFF; switch (divide) { @@ -246,6 +252,7 @@ unsigned deliver(chanend c_out, chanend ?c_spd_out, unsigned divide, chanend ?c_ break; } } + } #else /* CODEC is master */ /* Wait for LRCLK edge */ @@ -754,14 +761,40 @@ void audio(chanend c_mix_out, chanend ?c_dig_rx, chanend ?c_config, chanend ?c) /* Calculate divide required for bit clock e.g. 11.289600 / (176400 * 64) = 1 */ divide = mClk / ( curSamFreq * 64 ); - /* Configure clocking for required master clock */ - //ClockingConfig(mClk, c_config); - - /* Configure CODEC/DAC/ADC for SampleFreq/MClk */ + /* Configure Clocking/CODEC/DAC/ADC for SampleFreq/MClk */ AudioHwConfig(curSamFreq, mClk, c_config, dsdMode); /* Configure audio ports */ - ConfigAudioPorts(divide); + if(dsdMode) + { + /* re-arrange ports */ + + //ConfigAudioPorts_dsd(divide); + //unsigned dsdDataPorts[I2S_CHANS_DAC]; + + //dsdDataPorts = p_dsd_left; + + } + else + { + ConfigAudioPortsWrapper( +#if (I2S_CHANS_DAC != 0) + p_i2s_dac, +#endif +#if (I2S_CHANS_ADC != 0) + p_i2s_adc, +#endif +#if (I2S_CHANS_DAC != 0) || (I2S_CHANS_ADC != 0) +#ifndef CODEC_MASTER + p_lrclk, + p_bclk, +#else + p_lrclk, + p_bclk, +#endif +#endif + divide, dsdMode); + } if(!firstRun) { @@ -806,6 +839,13 @@ void audio(chanend c_mix_out, chanend ?c_dig_rx, chanend ?c_config, chanend ?c) null, #endif divide, c_dig_rx, c); + + + // TODO TIDY THIS! + //if(dsdMode) + //p_dsd_clk <: 0; + //else + //p_bclk <: 0; #ifdef DSD_OUTPUT if(retVal == 0) diff --git a/module_usb_audio/main.xc b/module_usb_audio/main.xc index 881c682e..8f982804 100755 --- a/module_usb_audio/main.xc +++ b/module_usb_audio/main.xc @@ -30,7 +30,7 @@ /* Audio I/O */ #if I2S_WIRES_DAC > 0 -on stdcore[0] : buffered out port:32 p_i2s_dac[I2S_WIRES_DAC] = +on tile[0] : buffered out port:32 p_i2s_dac[I2S_WIRES_DAC] = {PORT_I2S_DAC0, #endif #if I2S_WIRES_DAC > 1 @@ -59,7 +59,7 @@ on stdcore[0] : buffered out port:32 p_i2s_dac[I2S_WIRES_DAC] = #endif #if I2S_WIRES_ADC > 0 -on stdcore[0] : buffered in port:32 p_i2s_adc[I2S_WIRES_ADC] = +on tile[0] : buffered in port:32 p_i2s_adc[I2S_WIRES_ADC] = {PORT_I2S_ADC0, #endif #if I2S_WIRES_ADC > 1 @@ -92,40 +92,40 @@ on stdcore[0] : buffered in port:32 p_i2s_adc[I2S_WIRES_ADC] = #endif #ifndef CODEC_MASTER -on stdcore[AUDIO_IO_CORE] : buffered out port:32 p_lrclk = PORT_I2S_LRCLK; -on stdcore[AUDIO_IO_CORE] : buffered out port:32 p_bclk = PORT_I2S_BCLK; +on tile[AUDIO_IO_CORE] : buffered out port:32 p_lrclk = PORT_I2S_LRCLK; +on tile[AUDIO_IO_CORE] : buffered out port:32 p_bclk = PORT_I2S_BCLK; #else -on stdcore[AUDIO_IO_CORE] : in port p_lrclk = PORT_I2S_LRCLK; -on stdcore[AUDIO_IO_CORE] : in port p_bclk = PORT_I2S_BCLK; +on tile[AUDIO_IO_CORE] : in port p_lrclk = PORT_I2S_LRCLK; +on tile[AUDIO_IO_CORE] : in port p_bclk = PORT_I2S_BCLK; #endif -on stdcore[AUDIO_IO_CORE] : port p_mclk = PORT_MCLK_IN; -on stdcore[0] : in port p_for_mclk_count = PORT_MCLK_COUNT; +on tile[AUDIO_IO_CORE] : port p_mclk = PORT_MCLK_IN; +on tile[0] : in port p_for_mclk_count = PORT_MCLK_COUNT; #ifdef SPDIF -on stdcore[AUDIO_IO_CORE] : buffered out port:32 p_spdif_tx = PORT_SPDIF_OUT; +on tile[AUDIO_IO_CORE] : buffered out port:32 p_spdif_tx = PORT_SPDIF_OUT; #endif #ifdef MIDI -on stdcore[AUDIO_IO_CORE] : port p_midi_tx = PORT_MIDI_OUT; -on stdcore[AUDIO_IO_CORE] : port p_midi_rx = PORT_MIDI_IN; +on tile[AUDIO_IO_CORE] : port p_midi_tx = PORT_MIDI_OUT; +on tile[AUDIO_IO_CORE] : port p_midi_rx = PORT_MIDI_IN; #endif /* Clock blocks */ #ifdef MIDI -on stdcore[AUDIO_IO_CORE] : clock clk_midi = XS1_CLKBLK_REF; +on tile[AUDIO_IO_CORE] : clock clk_midi = XS1_CLKBLK_REF; #endif -on stdcore[AUDIO_IO_CORE] : clock clk_audio_mclk = XS1_CLKBLK_2; /* Master clock */ -on stdcore[AUDIO_IO_CORE] : clock clk_audio_bclk = XS1_CLKBLK_3; /* Bit clock */ +on tile[AUDIO_IO_CORE] : clock clk_audio_mclk = XS1_CLKBLK_2; /* Master clock */ +on tile[AUDIO_IO_CORE] : clock clk_audio_bclk = XS1_CLKBLK_3; /* Bit clock */ #ifdef SPDIF -on stdcore[AUDIO_IO_CORE] : clock clk_mst_spd = XS1_CLKBLK_1; +on tile[AUDIO_IO_CORE] : clock clk_mst_spd = XS1_CLKBLK_1; #endif /* L Series needs a port to use for USB reset */ #ifdef ARCH_L #ifdef PORT_USB_RESET /* This define is checked since it could be on a shift reg or similar */ -on stdcore[0] : out port p_usb_rst = PORT_USB_RESET; +on tile[0] : out port p_usb_rst = PORT_USB_RESET; #endif /* L Series also needs a clock for this port */ clock clk = XS1_CLKBLK_4; @@ -216,22 +216,22 @@ int main() /* USB Interface */ #if (AUDIO_CLASS==2) - on stdcore[0]: XUD_Manager(c_xud_out, EP_CNT_OUT, c_xud_in, EP_CNT_IN, + on tile[0]: XUD_Manager(c_xud_out, EP_CNT_OUT, c_xud_in, EP_CNT_IN, c_sof, epTypeTableOut, epTypeTableIn, p_usb_rst, clk, 1, XUD_SPEED_HS, c_usb_test); #else - on stdcore[0]:XUD_Manager(c_xud_out, EP_CNT_OUT, c_xud_in, EP_CNT_IN, + on tile[0]:XUD_Manager(c_xud_out, EP_CNT_OUT, c_xud_in, EP_CNT_IN, c_sof, epTypeTableOut, epTypeTableIn, p_usb_rst, clk, 1, XUD_SPEED_FS, c_usb_test); #endif /* Endpoint 0 */ - on stdcore[0]:{ + on tile[0]:{ thread_speed(); Endpoint0( c_xud_out[0], c_xud_in[0], c_aud_ctl, null, null, c_usb_test); } - on stdcore[0]: + on tile[0]: { thread_speed(); @@ -266,14 +266,14 @@ int main() } - on stdcore[0]: + on tile[0]: { thread_speed(); decouple(c_mix_out, null ); } - on stdcore[AUDIO_IO_CORE]: + on tile[AUDIO_IO_CORE]: { thread_speed(); @@ -282,7 +282,7 @@ int main() } #if defined (MIDI) || defined IAP - on stdcore[AUDIO_IO_CORE]: + on tile[AUDIO_IO_CORE]: { thread_speed(); #ifdef MIDI diff --git a/module_usb_audio/ports/audioports.h b/module_usb_audio/ports/audioports.h index 2e19b039..84ab1725 100644 --- a/module_usb_audio/ports/audioports.h +++ b/module_usb_audio/ports/audioports.h @@ -1,6 +1,104 @@ #ifndef _AUDIOPORTS_H_ #define _AUDIOPORTS_H_ -void ConfigAudioPorts(unsigned int divide); +#include +#include "devicedefines.h" +void ConfigAudioPorts_dsd(unsigned int divide); + + +#ifdef __XC__ +void ConfigAudioPorts( +#if (I2S_CHANS_DAC != 0) + buffered out port:32 p_i2s_dac[I2S_WIRES_DAC], #endif + +#if (I2S_CHANS_ADC != 0) + buffered in port:32 p_i2s_adc[I2S_WIRES_ADC], +#endif + +#if (I2S_CHANS_DAC != 0) || (I2S_CHANS_ADC != 0) +#ifndef CODEC_MASTER + buffered out port:32 p_lrclk, + buffered out port:32 p_bclk, +#else + in port p_lrclk, + in port p_bclk, +#endif +#endif + unsigned int divide); +#else + +void ConfigAudioPorts( +#if (I2S_CHANS_DAC != 0) + port p_i2s_dac[I2S_WIRES_DAC], +#endif + +#if (I2S_CHANS_ADC != 0) + port p_i2s_adc[I2S_WIRES_ADC], +#endif + +#if (I2S_CHANS_DAC != 0) || (I2S_CHANS_ADC != 0) +#ifndef CODEC_MASTER + port p_lrclk, + port p_bclk, +#else + port p_lrclk, + port p_bclk, +#endif +#endif + unsigned int divide); + + +#endif /* __XC__*/ + + +#ifdef __XC__ +void ConfigAudioPortsWrapper( +#if (I2S_CHANS_DAC != 0) + buffered out port:32 p_i2s_dac[I2S_WIRES_DAC], +#endif + +#if (I2S_CHANS_ADC != 0) + buffered in port:32 p_i2s_adc[I2S_WIRES_ADC], +#endif + +#if (I2S_CHANS_DAC != 0) || (I2S_CHANS_ADC != 0) +#ifndef CODEC_MASTER + buffered out port:32 p_lrclk, + buffered out port:32 p_bclk, +#else + in port p_lrclk, + in port p_bclk, +#endif +#endif + unsigned int divide, unsigned int dsdMode); +#else + +void ConfigAudioPortsWrapper( +#if (I2S_CHANS_DAC != 0) + port p_i2s_dac[I2S_WIRES_DAC], +#endif + +#if (I2S_CHANS_ADC != 0) + port p_i2s_adc[I2S_WIRES_ADC], +#endif + +#if (I2S_CHANS_DAC != 0) || (I2S_CHANS_ADC != 0) +#ifndef CODEC_MASTER + port p_lrclk, + port p_bclk, +#else + port p_lrclk, + port p_bclk, +#endif +#endif + unsigned int divide, unsigned int dsdMode); + + +#endif /* __XC__*/ + + + + +#endif /* _AUDIOPORTS_H_ */ diff --git a/module_usb_audio/ports/audioports.xc b/module_usb_audio/ports/audioports.xc index b7aa7d8e..3ca1eae1 100644 --- a/module_usb_audio/ports/audioports.xc +++ b/module_usb_audio/ports/audioports.xc @@ -1,33 +1,42 @@ #include +#include #include "devicedefines.h" #include "audioports.h" -/* Audio IOs */ +/* Configure audio ports. This is in C such that can we can mess around with arrays of ports */ -#if (I2S_CHANS_DAC != 0) -extern buffered out port:32 p_i2s_dac[I2S_WIRES_DAC]; -#endif - -#if (I2S_CHANS_ADC != 0) -extern buffered in port:32 p_i2s_adc[I2S_WIRES_ADC]; -#endif - -#if (I2S_CHANS_DAC != 0) || (I2S_CHANS_ADC != 0) -#ifndef CODEC_MASTER -extern buffered out port:32 p_lrclk; -extern buffered out port:32 p_bclk; -#else -extern in port p_lrclk; -extern in port p_bclk; -#endif -#endif +//extern void configure_in_port_no_ready(port p, const clock clk); +//extern void configure_out_port_no_ready(port p, const clock clk, unsigned initial); +//extern void configure_clock_src(clock clk, port p); extern port p_mclk; extern clock clk_audio_mclk; extern clock clk_audio_bclk; -void ConfigAudioPorts(unsigned int divide) +void ConfigAudioPorts( +#if (I2S_CHANS_DAC != 0) + buffered out port:32 p_i2s_dac[I2S_WIRES_DAC], + // port p_i2s_dac[I2S_WIRES_DAC], +#endif + +#if (I2S_CHANS_ADC != 0) + buffered in port:32 p_i2s_adc[I2S_WIRES_ADC], + // port p_i2s_adc[I2S_WIRES_ADC], +#endif + +#if (I2S_CHANS_DAC != 0) || (I2S_CHANS_ADC != 0) +#ifndef CODEC_MASTER + buffered out port:32 p_lrclk, + buffered out port:32 p_bclk, + //port p_lrclk, + //port p_bclk, +#else + in port p_lrclk, + in port p_bclk, +#endif +#endif +unsigned int divide) { #ifndef CODEC_MASTER @@ -105,7 +114,7 @@ void ConfigAudioPorts(unsigned int divide) start_clock(clk_audio_bclk); /* bclk initial state needs to be high */ - p_bclk <: 0xFFFFFFFF; + //p_bclk <: 0xFFFFFFFF; /* Pause until output completes */ sync(p_bclk); @@ -142,3 +151,66 @@ void ConfigAudioPorts(unsigned int divide) #endif } + +#if 0 +void ConfigAudioPorts_dsd(unsigned int divide) +{ + +#ifndef CODEC_MASTER + /* Output 0 on BCLK to ensure clock is low + * Required as stop_clock will only complete when the clock is low + */ + //configure_out_port_no_ready(p_dsd_clk, clk_audio_bclk, 0); + //configure_clock_src(clk_audio_mclk, p_mclk); + configure_out_port_no_ready(p_dsd_clk, clk_audio_mclk, 0); + p_dsd_clk <: 0; + + /* Stop bit and master clock blocks and clear port buffers */ + stop_clock(clk_audio_bclk); + stop_clock(clk_audio_mclk); + + clearbuf(p_dsd_clk); + clearbuf(p_dsd_left); + clearbuf(p_dsd_right); + + /* Clock master clock-block from master-clock port */ + configure_clock_src(clk_audio_mclk, p_mclk); + + /* For a divide of one (i.e. bitclock == master-clock) BClk is set to clock_output mode. + * In this mode it outputs an edge clock on every tick of itsassociated clock_block. + * + * For all other divides, BClk is clocked by the master clock and data + * will be output to p_bclk to generate the bit clock. + */ + if (divide == 1) /* e.g. 176.4KHz from 11.2896 */ + { + configure_port_clock_output(p_dsd_clk, clk_audio_mclk); + } + else + { + /* bit clock port from master clock clock-clock block */ + configure_out_port_no_ready(p_dsd_clk, clk_audio_mclk, 0); + } + + /* bclk clock-blocked clocked by dsd_clk pin */ + configure_clock_src(clk_audio_bclk, p_dsd_clk); + + + configure_out_port_no_ready(p_dsd_left, clk_audio_bclk, 0); + configure_out_port_no_ready(p_dsd_right, clk_audio_bclk, 0); + + /* Start clock blocks ticking */ + start_clock(clk_audio_mclk); + start_clock(clk_audio_bclk); + + /* bclk initial state needs to be high */ + p_dsd_clk<: 0xFFFFFFFF; + + /* Pause until output completes */ + sync(p_dsd_clk); + +#else /* CODEC_MASTER */ +#error CODEC MASTER for DSD not currently implemented +#endif +} +#endif