From 8a34d2eaff2b87aae9d36b309dc552e430fd46fc Mon Sep 17 00:00:00 2001 From: Henk Muller Date: Tue, 24 Sep 2024 14:02:36 +0100 Subject: [PATCH 01/15] Added PWM functionality as an output target, some interplay with other targets is to be added --- lib_xua/api/xua_audiohub.h | 8 +++- lib_xua/api/xua_conf_default.h | 30 +++++++++++++++ lib_xua/src/core/audiohub/xua_audiohub.xc | 45 +++++++++++++++++++++-- lib_xua/src/core/main.xc | 45 ++++++++++++++++++++++- lib_xua/src/core/ports/audioports.c | 17 ++++++++- lib_xua/src/core/ports/audioports.h | 9 +++++ lib_xua/src/core/ports/audioports.xc | 4 ++ lib_xua/src/core/pwm_thread.c | 38 +++++++++++++++++++ lib_xua/src/core/pwm_thread.h | 18 +++++++++ lib_xua/src/core/uac_hwresources.h | 1 + 10 files changed, 207 insertions(+), 8 deletions(-) create mode 100644 lib_xua/src/core/pwm_thread.c create mode 100644 lib_xua/src/core/pwm_thread.h diff --git a/lib_xua/api/xua_audiohub.h b/lib_xua/api/xua_audiohub.h index 6552167fe..fb2b7d4c6 100644 --- a/lib_xua/api/xua_audiohub.h +++ b/lib_xua/api/xua_audiohub.h @@ -55,11 +55,14 @@ void XUA_AudioHub( NULLABLE_RESOURCE(chanend, c_aud), NULLABLE_RESOURCE(clock, clk_audio_mclk), - NULLABLE_RESOURCE(clock, clk_audio_bclk), NULLABLE_RESOURCE(in_port_t, p_mclk_in) + NULLABLE_RESOURCE(clock, clk_audio_bclk) +#if (XUA_I2S_EN) + , NULLABLE_RESOURCE(in_port_t, p_mclk_in) , NULLABLE_RESOURCE(i2s_clk_port_type, p_lrclk) , NULLABLE_RESOURCE(i2s_clk_port_type, p_bclk) , NULLABLE_ARRAY_OF_SIZE(out_buffered_port_32_t, p_i2s_dac, I2S_WIRES_DAC) , NULLABLE_ARRAY_OF_SIZE(in_buffered_port_32_t, p_i2s_adc, I2S_WIRES_ADC) +#endif #if (XUA_SPDIF_TX_EN) || defined(__DOXYGEN__) , chanend c_spdif_tx #endif @@ -75,6 +78,9 @@ void XUA_AudioHub( #if (XUA_NUM_PDM_MICS > 0 || defined(__DOXYGEN__)) , chanend c_pdm_in #endif +#if (XUA_PWM_CHANNELS > 0) || defined(__DOXYGEN__) + , chanend c_pwm_channels +#endif ); void SpdifTxWrapper(chanend c_spdif_tx); diff --git a/lib_xua/api/xua_conf_default.h b/lib_xua/api/xua_conf_default.h index 4142f55ea..fd489e404 100644 --- a/lib_xua/api/xua_conf_default.h +++ b/lib_xua/api/xua_conf_default.h @@ -42,6 +42,13 @@ #define SPDIF_TX_TILE AUDIO_IO_TILE #endif +/** + * @brief Location (tile) of SPDIF Tx. Default: XUD_TILE + */ +#ifndef PWM_CHANNELS_TILE +#define PWM_CHANNELS_TILE XUD_TILE +#endif + /** * @brief Location (tile) of PDM Rx. Default: AUDIO_IO_TILE */ @@ -85,6 +92,27 @@ #define XUA_NUM_PDM_MICS (0) #endif +/** + * @brief Number of PWM output channels in the design. Must be 2 or 0. + * + * Default: 0 + */ +#ifndef XUA_NUM_PWM_CHANNELS +#define XUA_NUM_PWM_CHANNELS (0) +#endif +#if (XUA_NUM_PWM_CHANNELS != 0 && XUA_NUM_PWM_CHANNELS != 2) +#error "Only none or two PWM channels supported at present" +#endif + +/** + * @brief Defines which output channels (stereo) should be output on PWM. Note, Output channels indexed from 0. + * + * Default: 0 (i.e. channels 0 & 1) + * */ +#ifndef PWM_CHANNELS_INDEX +#define PWM_CHANNELS_INDEX (0) +#endif + /** * @brief Number of DSD output channels. * @@ -124,6 +152,8 @@ #define I2S_WIRES_ADC (I2S_CHANS_ADC / I2S_CHANS_PER_FRAME) #endif +#define XUA_I2S_EN ((I2S_WIRES_ADC) > 0 || (I2S_WIRES_DAC) > 0) + /* * Defines relating to the interface to external audio hardware i.e. DAC/ADC */ diff --git a/lib_xua/src/core/audiohub/xua_audiohub.xc b/lib_xua/src/core/audiohub/xua_audiohub.xc index 3b6a8fffb..6396a939b 100755 --- a/lib_xua/src/core/audiohub/xua_audiohub.xc +++ b/lib_xua/src/core/audiohub/xua_audiohub.xc @@ -161,6 +161,9 @@ static inline int HandleSampleClock(int frameCount, buffered _XUA_CLK_DIR port:3 #pragma unsafe arrays unsigned static AudioHub_MainLoop(chanend ?c_out, chanend ?c_spd_out +#if (XUA_PWM_CHANNELS > 0) + , chanend c_pwm_channels +#endif #if (XUA_ADAT_TX_EN) , chanend c_adat_out , unsigned adatSmuxMode @@ -172,10 +175,12 @@ unsigned static AudioHub_MainLoop(chanend ?c_out, chanend ?c_spd_out #if (XUA_NUM_PDM_MICS > 0) , chanend c_pdm_pcm #endif +#if (XUA_I2S_EN) , buffered _XUA_CLK_DIR port:32 ?p_lrclk, buffered _XUA_CLK_DIR port:32 ?p_bclk, buffered out port:32 (&?p_i2s_dac)[I2S_WIRES_DAC], buffered in port:32 (&?p_i2s_adc)[I2S_WIRES_ADC] +#endif ) { /* Since DAC and ADC buffered ports off by one sample we buffer previous ADC frame */ @@ -266,10 +271,12 @@ unsigned static AudioHub_MainLoop(chanend ?c_out, chanend ?c_spd_out if ((I2S_CHANS_DAC > 0 || I2S_CHANS_ADC > 0)) { +#if (XUA_I2S_EN) #if CODEC_MASTER InitPorts_slave(p_lrclk, p_bclk, p_i2s_dac, p_i2s_adc); #else InitPorts_master(p_lrclk, p_bclk, p_i2s_dac, p_i2s_adc); +#endif #endif } @@ -407,6 +414,10 @@ unsigned static AudioHub_MainLoop(chanend ?c_out, chanend ?c_spd_out outuint(c_spd_out, samplesOut[SPDIF_TX_INDEX]); /* Forward samples to S/PDIF Tx thread */ outuint(c_spd_out, samplesOut[SPDIF_TX_INDEX + 1]); #endif +#if (XUA_PWM_CHANNELS > 0) && (NUM_USB_CHAN_OUT > 0) + outuint(c_pwm_channels, samplesOut[PWM_CHANNELS_INDEX]); /* Forward samples to PWM generator threads */ + outuint(c_pwm_channels, samplesOut[PWM_CHANNELS_INDEX + 1]); +#endif #if (XUA_NUM_PDM_MICS > 0) if ((AUD_TO_MICS_RATIO - 1) == audioToMicsRatioCounter) @@ -626,12 +637,14 @@ static void dummy_deliver(chanend ?c_out, unsigned &command) void DFUHandler(server interface i_dfu i, chanend ?c_user_cmd); #endif -void XUA_AudioHub(chanend ?c_aud, clock ?clk_audio_mclk, clock ?clk_audio_bclk, - in port ?p_mclk_in, +void XUA_AudioHub(chanend ?c_aud, clock ?clk_audio_mclk, clock ?clk_audio_bclk +#if (XUA_I2S_EN) + , in port ?p_mclk_in, buffered _XUA_CLK_DIR port:32 ?p_lrclk, buffered _XUA_CLK_DIR port:32 ?p_bclk, buffered out port:32 (&?p_i2s_dac)[I2S_WIRES_DAC], buffered in port:32 (&?p_i2s_adc)[I2S_WIRES_ADC] +#endif #if (XUA_SPDIF_TX_EN) //&& (SPDIF_TX_TILE != AUDIO_IO_TILE) , chanend c_spdif_out #endif @@ -647,6 +660,9 @@ void XUA_AudioHub(chanend ?c_aud, clock ?clk_audio_mclk, clock ?clk_audio_bclk, #if (XUA_NUM_PDM_MICS > 0) , chanend c_pdm_in #endif +#if (XUA_PWM_CHANNELS > 0) || defined(__DOXYGEN__) + , chanend c_pwm_channels +#endif ) { #if (XUA_ADAT_TX_EN) @@ -662,6 +678,12 @@ void XUA_AudioHub(chanend ?c_aud, clock ?clk_audio_mclk, clock ?clk_audio_bclk, unsigned divide; unsigned firstRun = 1; + /* Clock master clock-block from master-clock port */ + /* Note, marked unsafe since other cores may be using this mclk port */ +#if (XUA_I2S_EN) + configure_clock_src(clk_audio_mclk, p_mclk_in); +#endif + #if (DSD_CHANS_DAC > 0) /* Make sure the DSD ports are on and buffered - just in case they are not shared with I2S */ EnableBufferedPort(p_dsd_clk, 32); @@ -771,7 +793,10 @@ void XUA_AudioHub(chanend ?c_aud, clock ?clk_audio_mclk, clock ?clk_audio_bclk, #endif // (I2S_CHANS_ADC != 0) p_lrclk, p_bclk, - p_mclk_in, clk_audio_bclk, divide, curSamFreq); +#if (XUA_I2S_EN) + p_mclk_in, +#endif + clk_audio_bclk, divide, curSamFreq); } #endif // (I2S_CHANS_DAC != 0) || (I2S_CHANS_ADC != 0) @@ -849,6 +874,12 @@ void XUA_AudioHub(chanend ?c_aud, clock ?clk_audio_mclk, clock ?clk_audio_bclk, outuint(c_spdif_out, mClk); #endif +#if (XUA_PWM_CHANNELS > 0) + /* Communicate master clock and sample freq to PWM thread */ + outct(c_pwm_channels, XS1_CT_END); + outuint(c_pwm_channels, curSamFreq); +#endif + #if (XUA_NUM_PDM_MICS > 0) /* Send decimation factor to PDM task(s) */ user_pdm_init(); @@ -875,6 +906,9 @@ void XUA_AudioHub(chanend ?c_aud, clock ?clk_audio_mclk, clock ?clk_audio_bclk, #else , null #endif +#if (XUA_PWM_CHANNELS > 0) + , c_pwm_channels +#endif #if (XUA_ADAT_TX_EN) , c_adat_out , adatSmuxMode @@ -886,7 +920,10 @@ void XUA_AudioHub(chanend ?c_aud, clock ?clk_audio_mclk, clock ?clk_audio_bclk, #if (XUA_NUM_PDM_MICS > 0) , c_pdm_in #endif - , p_lrclk, p_bclk, p_i2s_dac, p_i2s_adc); +#if (XUA_I2S_EN) + , p_lrclk, p_bclk, p_i2s_dac, p_i2s_adc +#endif + ); #if (XUA_USB_EN) if(command == SET_SAMPLE_FREQ) diff --git a/lib_xua/src/core/main.xc b/lib_xua/src/core/main.xc index 9d9c6c6d3..a5018dea7 100644 --- a/lib_xua/src/core/main.xc +++ b/lib_xua/src/core/main.xc @@ -34,6 +34,10 @@ #include "spdif.h" /* From lib_spdif */ #endif +#if (XUA_PWM_CHANNELS > 0) +#include "pwm_thread.h" +#endif + #if (XUA_ADAT_RX_EN) #include "adat_rx.h" #endif @@ -110,6 +114,7 @@ on tile[AUDIO_IO_TILE] : buffered in port:32 p_i2s_adc[I2S_WIRES_ADC] = #define p_i2s_adc null #endif +#if XUA_I2S_EN #if CODEC_MASTER on tile[AUDIO_IO_TILE] : buffered in port:32 p_lrclk = PORT_I2S_LRCLK; @@ -119,6 +124,8 @@ on tile[AUDIO_IO_TILE] : buffered out port:32 p_lrclk = PORT_I2S_LRCLK; on tile[AUDIO_IO_TILE] : buffered out port:32 p_bclk = PORT_I2S_BCLK; #endif +#endif + #if (!CODEC_MASTER) || XUA_SPDIF_TX_EN || XUA_ADAT_TX_EN || ((AUDIO_IO_TILE == XUD_TILE) && XUA_USB_EN) /* Audio master clock input */ on tile[AUDIO_IO_TILE] : in port p_mclk_in = PORT_MCLK_IN; @@ -295,6 +302,9 @@ void usb_audio_io(chanend ?c_aud_in, #if (XUA_SPDIF_TX_EN) && (SPDIF_TX_TILE != AUDIO_IO_TILE) chanend c_spdif_tx, #endif +#if (XUA_PWM_CHANNELS > 0) && (PWM_CHANNELS_TILE != XUD_TILE) + chanend c_pwm_channels, +#endif #if (MIXER) chanend c_mix_ctl, #endif @@ -343,6 +353,10 @@ void usb_audio_io(chanend ?c_aud_in, spdif_tx_port_config(p_spdif_tx, clk_audio_mclk, p_mclk_in, 7); #endif +#if (XUA_PWM_CHANNELS > 0) && (PWM_CHANNELS_TILE == XUD_TILE) + chan c_pwm_channels; +#endif + par { #if (MIXER && XUA_USB_EN) @@ -360,6 +374,14 @@ void usb_audio_io(chanend ?c_aud_in, } #endif +#if (XUA_PWM_CHANNELS > 0) && (PWM_CHANNELS_TILE == XUD_TILE) +#if (AUDIO_IO_TILE == XUD_TILE) + pwm_thread(c_pwm_channels, p_mclk_in); +#else + pwm_thread(c_pwm_channels, p_mclk_in_usb); +#endif +#endif + /* Audio I/O core (pars additional S/PDIF TX Core) */ { thread_speed(); @@ -368,7 +390,10 @@ void usb_audio_io(chanend ?c_aud_in, #else #define AUDIO_CHANNEL c_aud_in #endif - XUA_AudioHub(AUDIO_CHANNEL, clk_audio_mclk, clk_audio_bclk, p_mclk_in, p_lrclk, p_bclk, p_i2s_dac, p_i2s_adc + XUA_AudioHub(AUDIO_CHANNEL, clk_audio_mclk, clk_audio_bclk +#if (XUA_I2S_EN) + , p_mclk_in, p_lrclk, p_bclk, p_i2s_dac, p_i2s_adc +#endif #if (XUA_SPDIF_TX_EN) //&& (SPDIF_TX_TILE != AUDIO_IO_TILE) , c_spdif_tx #endif @@ -383,6 +408,9 @@ void usb_audio_io(chanend ?c_aud_in, #endif #if (XUA_NUM_PDM_MICS > 0) , c_pdm_pcm +#endif +#if (XUA_PWM_CHANNELS > 0) //&& (PWM_CHANNELS_TILE != XUD_TILE) + , c_pwm_channels #endif ); } @@ -459,6 +487,10 @@ int main() chan c_spdif_tx; #endif +#if (XUA_PWM_CHANNELS > 0) && (PWM_CHANNELS_TILE != XUD_TILE) + chan c_pwm_channels; +#endif + #if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN) chan c_clk_ctl; chan c_clk_int; @@ -623,6 +655,9 @@ int main() #if (XUA_SPDIF_TX_EN) && (SPDIF_TX_TILE != AUDIO_IO_TILE) , c_spdif_tx #endif +#if (XUA_PWM_CHANNELS > 0) && (PWM_CHANNELS_TILE != XUD_TILE) + , c_pwm_channels +#endif #if (MIXER) , c_mix_ctl #endif @@ -655,6 +690,14 @@ int main() } #endif +#if (XUA_PWM_CHANNELS > 0) && (PWM_CHANNELS_TILE != XUD_TILE) + on tile[PWM_CHANNELS_TILE]: + { + thread_speed(); + pwm_thread(c_pwm_channels, p_mclk_in); + } +#endif + #if defined(MIDI) && defined(IAP) && (IAP_TILE == MIDI_TILE) /* MIDI and IAP share a core */ on tile[IAP_TILE]: diff --git a/lib_xua/src/core/ports/audioports.c b/lib_xua/src/core/ports/audioports.c index 6f018998e..63c555713 100644 --- a/lib_xua/src/core/ports/audioports.c +++ b/lib_xua/src/core/ports/audioports.c @@ -41,9 +41,17 @@ void ConfigAudioPortsWrapper( port p_adc[], int numPortsAdc, #endif - port p_lrclk, +#if (I2S_CHANS_DAC != 0) || (I2S_CHANS_ADC != 0) +#if (CODEC_MASTER == 0) + NULLABLE_RESOURCE(out_port_t p_lrclk), +#else + NULLABLE_RESOURCE(in_port_t p_lrclk), +#endif port p_bclk, +#endif +#if (XUA_I2S_EN) NULLABLE_RESOURCE(in_port_t, p_mclk_in), +#endif clock clk_audio_bclk, unsigned int divide, unsigned curSamFreq) { ConfigAudioPorts( @@ -55,8 +63,13 @@ void ConfigAudioPortsWrapper( p_adc, numPortsAdc, #endif +#if (I2S_CHANS_DAC != 0) || (I2S_CHANS_ADC != 0) p_lrclk, p_bclk, - p_mclk_in, clk_audio_bclk, divide, curSamFreq); +#endif +#if (XUA_I2S_EN) + p_mclk_in, +#endif + clk_audio_bclk, divide, curSamFreq); } diff --git a/lib_xua/src/core/ports/audioports.h b/lib_xua/src/core/ports/audioports.h index a83c53569..24dd69f85 100644 --- a/lib_xua/src/core/ports/audioports.h +++ b/lib_xua/src/core/ports/audioports.h @@ -17,6 +17,7 @@ void ConfigAudioPorts( in_buffered_port_32_t p_i2s_adc[], int numAdcPorts, #endif +#if (I2S_CHANS_DAC != 0) || (I2S_CHANS_ADC != 0) #if (CODEC_MASTER == 0) NULLABLE_RESOURCE(out_buffered_port_32_t, p_lrclk), out_buffered_port_32_t p_bclk, @@ -24,8 +25,12 @@ void ConfigAudioPorts( NULLABLE_RESOURCE(in_port_t, p_lrclk), in_port_t p_bclk, #endif +#endif +#if (XUA_I2S_EN) NULLABLE_RESOURCE(in_port_t, p_mclk_in), +#endif clock clk_audio_bclk, unsigned int divide, unsigned int curSamFreq); +//#else // Delete??? void ConfigAudioPortsWrapper( @@ -37,6 +42,7 @@ void ConfigAudioPortsWrapper( in_buffered_port_32_t p_i2s_adc[], int numPortsADC, #endif +#if (I2S_CHANS_DAC != 0) || (I2S_CHANS_ADC != 0) #if (CODEC_MASTER == 0) NULLABLE_RESOURCE(out_buffered_port_32_t, p_lrclk), out_buffered_port_32_t p_bclk, @@ -44,7 +50,10 @@ void ConfigAudioPortsWrapper( NULLABLE_RESOURCE(in_buffered_port_32_t, p_lrclk), in_buffered_port_32_t p_bclk, #endif +#endif +#if (XUA_I2S_EN) NULLABLE_RESOURCE(in_port_t, p_mclk_in), +#endif clock clk_audio_bclk, unsigned int divide, unsigned curSamFreq); #ifdef __XC__ diff --git a/lib_xua/src/core/ports/audioports.xc b/lib_xua/src/core/ports/audioports.xc index e5f1112c7..f7b51fdc4 100644 --- a/lib_xua/src/core/ports/audioports.xc +++ b/lib_xua/src/core/ports/audioports.xc @@ -17,6 +17,7 @@ void ConfigAudioPorts( int numPortsAdc, #endif +#if (I2S_CHANS_DAC != 0) || (I2S_CHANS_ADC != 0) #if (CODEC_MASTER == 0) buffered out port:32 ?p_lrclk, buffered out port:32 p_bclk, @@ -24,7 +25,10 @@ void ConfigAudioPorts( in port ?p_lrclk, in port p_bclk, #endif +#endif +#if (XUA_I2S_EN) in port ?p_mclk_in, +#endif clock clk_audio_bclk, unsigned int divide, unsigned curSamFreq) { #if (I2S_CHANS_DAC != 0) || (I2S_CHANS_ADC != 0) diff --git a/lib_xua/src/core/pwm_thread.c b/lib_xua/src/core/pwm_thread.c new file mode 100644 index 000000000..6f69222d3 --- /dev/null +++ b/lib_xua/src/core/pwm_thread.c @@ -0,0 +1,38 @@ +/** + * @file pwm_thread.c + * @brief Fork the threads to run a PWM engine + * @author Henk Muller, XMOS Semiconductor Ltd + */ +#include "xua_conf_default.h" // Settings +#if (XUA_PWM_CHANNELS > 0) +#include +#include +#include +#include +#include "software_dac_hp.h" +#include "uac_hwresources.h" + +void setup_master_clock(port_t clk_in) __attribute__ ((weak)); +void setup_master_clock(port_t clk_in) { +} + +void pwm_thread(chanend_t c_data, port_t clk_in) +{ + software_dac_hp_t sd; + xclock_t clk = CLKBLK_PWM; + port_t ports[2] = {PORT_PWM_OUT_LEFT, PORT_PWM_OUT_RIGHT}; + port_t clk_out = PORT_PWM_CLK_OUT; + port_enable(clk_in); + setup_master_clock(clk_in); + port_set_invert(clk_in); + clock_enable(clk); + clock_set_source_port(clk, clk_in); + + software_dac_hp_init(&sd, ports, clk, clk_out, 8, sd_coeffs_o6_f1_5_n8); + + software_dac_hp(&sd, c_data); +} +#endif + + + diff --git a/lib_xua/src/core/pwm_thread.h b/lib_xua/src/core/pwm_thread.h new file mode 100644 index 000000000..07396e664 --- /dev/null +++ b/lib_xua/src/core/pwm_thread.h @@ -0,0 +1,18 @@ +#ifndef __pwm_thread__h_ +#define __pwm_thread__h_ + +#include "xua_conf_default.h" // Settings + +#if (XUA_PWM_CHANNELS > 0) + #ifdef __XC__ +void pwm_thread(chanend c_data, in port p_mclk); + #else + #include +void pwm_thread(chanend_t c_data, port_t p_mclk); + #endif +#endif + +#endif + + + diff --git a/lib_xua/src/core/uac_hwresources.h b/lib_xua/src/core/uac_hwresources.h index 4cd6cdf7d..db6799ba5 100644 --- a/lib_xua/src/core/uac_hwresources.h +++ b/lib_xua/src/core/uac_hwresources.h @@ -11,5 +11,6 @@ #define CLKBLK_FLASHLIB XS1_CLKBLK_3 /* Clock block for use by flash lib */ #define CLKBLK_ADAT_RX XS1_CLKBLK_REF /* Use REF for ADAT_RX on x200/AI series */ #define CLKBLK_I2S_BIT XS1_CLKBLK_3 +#define CLKBLK_PWM XS1_CLKBLK_1 #endif /* _UAC_HWRESOURCES_H_ */ From 29134fba5675a712486228de3d058ec5101a092c Mon Sep 17 00:00:00 2001 From: Henk Muller Date: Wed, 25 Sep 2024 14:24:20 +0100 Subject: [PATCH 02/15] Simplified the PWM side and removed lots of ifdefs --- lib_xua/api/xua_audiohub.h | 2 - lib_xua/src/core/audiohub/xua_audiohub.xc | 15 +------ lib_xua/src/core/main.xc | 53 +++++++++++++---------- lib_xua/src/core/ports/audioports.c | 4 -- lib_xua/src/core/ports/audioports.h | 6 --- lib_xua/src/core/ports/audioports.xc | 2 - lib_xua/src/core/pwm_thread.c | 15 ++++--- lib_xua/src/core/pwm_thread.h | 6 ++- 8 files changed, 44 insertions(+), 59 deletions(-) diff --git a/lib_xua/api/xua_audiohub.h b/lib_xua/api/xua_audiohub.h index fb2b7d4c6..d10e15fa7 100644 --- a/lib_xua/api/xua_audiohub.h +++ b/lib_xua/api/xua_audiohub.h @@ -56,13 +56,11 @@ void XUA_AudioHub( NULLABLE_RESOURCE(chanend, c_aud), NULLABLE_RESOURCE(clock, clk_audio_mclk), NULLABLE_RESOURCE(clock, clk_audio_bclk) -#if (XUA_I2S_EN) , NULLABLE_RESOURCE(in_port_t, p_mclk_in) , NULLABLE_RESOURCE(i2s_clk_port_type, p_lrclk) , NULLABLE_RESOURCE(i2s_clk_port_type, p_bclk) , NULLABLE_ARRAY_OF_SIZE(out_buffered_port_32_t, p_i2s_dac, I2S_WIRES_DAC) , NULLABLE_ARRAY_OF_SIZE(in_buffered_port_32_t, p_i2s_adc, I2S_WIRES_ADC) -#endif #if (XUA_SPDIF_TX_EN) || defined(__DOXYGEN__) , chanend c_spdif_tx #endif diff --git a/lib_xua/src/core/audiohub/xua_audiohub.xc b/lib_xua/src/core/audiohub/xua_audiohub.xc index 6396a939b..4d8bd99ef 100755 --- a/lib_xua/src/core/audiohub/xua_audiohub.xc +++ b/lib_xua/src/core/audiohub/xua_audiohub.xc @@ -175,12 +175,10 @@ unsigned static AudioHub_MainLoop(chanend ?c_out, chanend ?c_spd_out #if (XUA_NUM_PDM_MICS > 0) , chanend c_pdm_pcm #endif -#if (XUA_I2S_EN) , buffered _XUA_CLK_DIR port:32 ?p_lrclk, buffered _XUA_CLK_DIR port:32 ?p_bclk, buffered out port:32 (&?p_i2s_dac)[I2S_WIRES_DAC], buffered in port:32 (&?p_i2s_adc)[I2S_WIRES_ADC] -#endif ) { /* Since DAC and ADC buffered ports off by one sample we buffer previous ADC frame */ @@ -271,12 +269,10 @@ unsigned static AudioHub_MainLoop(chanend ?c_out, chanend ?c_spd_out if ((I2S_CHANS_DAC > 0 || I2S_CHANS_ADC > 0)) { -#if (XUA_I2S_EN) #if CODEC_MASTER InitPorts_slave(p_lrclk, p_bclk, p_i2s_dac, p_i2s_adc); #else InitPorts_master(p_lrclk, p_bclk, p_i2s_dac, p_i2s_adc); -#endif #endif } @@ -638,13 +634,11 @@ static void dummy_deliver(chanend ?c_out, unsigned &command) #endif void XUA_AudioHub(chanend ?c_aud, clock ?clk_audio_mclk, clock ?clk_audio_bclk -#if (XUA_I2S_EN) , in port ?p_mclk_in, buffered _XUA_CLK_DIR port:32 ?p_lrclk, buffered _XUA_CLK_DIR port:32 ?p_bclk, buffered out port:32 (&?p_i2s_dac)[I2S_WIRES_DAC], buffered in port:32 (&?p_i2s_adc)[I2S_WIRES_ADC] -#endif #if (XUA_SPDIF_TX_EN) //&& (SPDIF_TX_TILE != AUDIO_IO_TILE) , chanend c_spdif_out #endif @@ -680,9 +674,7 @@ void XUA_AudioHub(chanend ?c_aud, clock ?clk_audio_mclk, clock ?clk_audio_bclk /* Clock master clock-block from master-clock port */ /* Note, marked unsafe since other cores may be using this mclk port */ -#if (XUA_I2S_EN) configure_clock_src(clk_audio_mclk, p_mclk_in); -#endif #if (DSD_CHANS_DAC > 0) /* Make sure the DSD ports are on and buffered - just in case they are not shared with I2S */ @@ -793,9 +785,7 @@ void XUA_AudioHub(chanend ?c_aud, clock ?clk_audio_mclk, clock ?clk_audio_bclk #endif // (I2S_CHANS_ADC != 0) p_lrclk, p_bclk, -#if (XUA_I2S_EN) p_mclk_in, -#endif clk_audio_bclk, divide, curSamFreq); } #endif // (I2S_CHANS_DAC != 0) || (I2S_CHANS_ADC != 0) @@ -920,10 +910,7 @@ void XUA_AudioHub(chanend ?c_aud, clock ?clk_audio_mclk, clock ?clk_audio_bclk #if (XUA_NUM_PDM_MICS > 0) , c_pdm_in #endif -#if (XUA_I2S_EN) - , p_lrclk, p_bclk, p_i2s_dac, p_i2s_adc -#endif - ); + , p_lrclk, p_bclk, p_i2s_dac, p_i2s_adc); #if (XUA_USB_EN) if(command == SET_SAMPLE_FREQ) diff --git a/lib_xua/src/core/main.xc b/lib_xua/src/core/main.xc index a5018dea7..da3f78b25 100644 --- a/lib_xua/src/core/main.xc +++ b/lib_xua/src/core/main.xc @@ -13,6 +13,7 @@ #include #include #include +#include #include #ifdef XSCOPE #include @@ -123,7 +124,9 @@ on tile[AUDIO_IO_TILE] : buffered in port:32 p_bclk = PORT_I2S_BCLK; on tile[AUDIO_IO_TILE] : buffered out port:32 p_lrclk = PORT_I2S_LRCLK; on tile[AUDIO_IO_TILE] : buffered out port:32 p_bclk = PORT_I2S_BCLK; #endif - +#else +#define p_lrclk null +#define p_bclk null #endif #if (!CODEC_MASTER) || XUA_SPDIF_TX_EN || XUA_ADAT_TX_EN || ((AUDIO_IO_TILE == XUD_TILE) && XUA_USB_EN) @@ -180,6 +183,10 @@ on tile[MIDI_TILE] : buffered in port:1 p_midi_rx = PORT_MIDI_IN; #endif +#if (XUA_PWM_CHANNELS > 0) +clock clk_pwm_channels = on tile[PWM_CHANNELS_TILE]: CLKBLK_PWM; +#endif + #ifdef MIDI on tile[MIDI_TILE] : clock clk_midi = CLKBLK_MIDI; #endif @@ -302,7 +309,7 @@ void usb_audio_io(chanend ?c_aud_in, #if (XUA_SPDIF_TX_EN) && (SPDIF_TX_TILE != AUDIO_IO_TILE) chanend c_spdif_tx, #endif -#if (XUA_PWM_CHANNELS > 0) && (PWM_CHANNELS_TILE != XUD_TILE) +#if (XUA_PWM_CHANNELS > 0) chanend c_pwm_channels, #endif #if (MIXER) @@ -346,6 +353,10 @@ void usb_audio_io(chanend ?c_aud_in, #endif /* (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN) */ +#if (XUA_PWM_CHANNELS > 0) && (PWM_CHANNELS_TILE == AUDIO_IO_TILE) + pwm_init(p_mclk_in); +#endif + #if (XUA_SPDIF_TX_EN) && (SPDIF_TX_TILE == AUDIO_IO_TILE) chan c_spdif_tx; @@ -353,10 +364,6 @@ void usb_audio_io(chanend ?c_aud_in, spdif_tx_port_config(p_spdif_tx, clk_audio_mclk, p_mclk_in, 7); #endif -#if (XUA_PWM_CHANNELS > 0) && (PWM_CHANNELS_TILE == XUD_TILE) - chan c_pwm_channels; -#endif - par { #if (MIXER && XUA_USB_EN) @@ -374,14 +381,6 @@ void usb_audio_io(chanend ?c_aud_in, } #endif -#if (XUA_PWM_CHANNELS > 0) && (PWM_CHANNELS_TILE == XUD_TILE) -#if (AUDIO_IO_TILE == XUD_TILE) - pwm_thread(c_pwm_channels, p_mclk_in); -#else - pwm_thread(c_pwm_channels, p_mclk_in_usb); -#endif -#endif - /* Audio I/O core (pars additional S/PDIF TX Core) */ { thread_speed(); @@ -390,10 +389,7 @@ void usb_audio_io(chanend ?c_aud_in, #else #define AUDIO_CHANNEL c_aud_in #endif - XUA_AudioHub(AUDIO_CHANNEL, clk_audio_mclk, clk_audio_bclk -#if (XUA_I2S_EN) - , p_mclk_in, p_lrclk, p_bclk, p_i2s_dac, p_i2s_adc -#endif + XUA_AudioHub(AUDIO_CHANNEL, clk_audio_mclk, clk_audio_bclk, p_mclk_in, p_lrclk, p_bclk, p_i2s_dac, p_i2s_adc #if (XUA_SPDIF_TX_EN) //&& (SPDIF_TX_TILE != AUDIO_IO_TILE) , c_spdif_tx #endif @@ -409,7 +405,7 @@ void usb_audio_io(chanend ?c_aud_in, #if (XUA_NUM_PDM_MICS > 0) , c_pdm_pcm #endif -#if (XUA_PWM_CHANNELS > 0) //&& (PWM_CHANNELS_TILE != XUD_TILE) +#if (XUA_PWM_CHANNELS > 0) , c_pwm_channels #endif ); @@ -487,7 +483,7 @@ int main() chan c_spdif_tx; #endif -#if (XUA_PWM_CHANNELS > 0) && (PWM_CHANNELS_TILE != XUD_TILE) +#if (XUA_PWM_CHANNELS > 0) chan c_pwm_channels; #endif @@ -579,6 +575,10 @@ int main() /* Attach mclk count port to mclk clock-block (for feedback) */ //set_port_clock(p_for_mclk_count, clk_audio_mclk); +#if (XUA_PWM_CHANNELS > 0) && (PWM_CHANNELS_TILE != AUDIO_IO_TILE) + pwm_init(p_mclk_in); +#endif + #if(AUDIO_IO_TILE != XUD_TILE) set_clock_src(clk_audio_mclk_usb, p_mclk_in_usb); set_port_clock(p_for_mclk_count, clk_audio_mclk_usb); @@ -655,7 +655,7 @@ int main() #if (XUA_SPDIF_TX_EN) && (SPDIF_TX_TILE != AUDIO_IO_TILE) , c_spdif_tx #endif -#if (XUA_PWM_CHANNELS > 0) && (PWM_CHANNELS_TILE != XUD_TILE) +#if (XUA_PWM_CHANNELS > 0) , c_pwm_channels #endif #if (MIXER) @@ -690,11 +690,18 @@ int main() } #endif -#if (XUA_PWM_CHANNELS > 0) && (PWM_CHANNELS_TILE != XUD_TILE) +#if (XUA_PWM_CHANNELS > 0) on tile[PWM_CHANNELS_TILE]: { thread_speed(); - pwm_thread(c_pwm_channels, p_mclk_in); + timer tmr; + int tt; + tmr :> tt; + // Nasty - wait for clock block to be inited + // Ideally, this happens before the PAR. + // But it is inside the IO thread + tmr when timerafter(tt + 1000000) :> void; + pwm_thread(c_pwm_channels); } #endif diff --git a/lib_xua/src/core/ports/audioports.c b/lib_xua/src/core/ports/audioports.c index 63c555713..35c581d1b 100644 --- a/lib_xua/src/core/ports/audioports.c +++ b/lib_xua/src/core/ports/audioports.c @@ -49,9 +49,7 @@ void ConfigAudioPortsWrapper( #endif port p_bclk, #endif -#if (XUA_I2S_EN) NULLABLE_RESOURCE(in_port_t, p_mclk_in), -#endif clock clk_audio_bclk, unsigned int divide, unsigned curSamFreq) { ConfigAudioPorts( @@ -67,9 +65,7 @@ void ConfigAudioPortsWrapper( p_lrclk, p_bclk, #endif -#if (XUA_I2S_EN) p_mclk_in, -#endif clk_audio_bclk, divide, curSamFreq); } diff --git a/lib_xua/src/core/ports/audioports.h b/lib_xua/src/core/ports/audioports.h index 24dd69f85..270ebe3bd 100644 --- a/lib_xua/src/core/ports/audioports.h +++ b/lib_xua/src/core/ports/audioports.h @@ -26,12 +26,8 @@ void ConfigAudioPorts( in_port_t p_bclk, #endif #endif -#if (XUA_I2S_EN) NULLABLE_RESOURCE(in_port_t, p_mclk_in), -#endif clock clk_audio_bclk, unsigned int divide, unsigned int curSamFreq); -//#else // Delete??? - void ConfigAudioPortsWrapper( #if (I2S_CHANS_DAC != 0) || (DSD_CHANS_DAC != 0) @@ -51,9 +47,7 @@ void ConfigAudioPortsWrapper( in_buffered_port_32_t p_bclk, #endif #endif -#if (XUA_I2S_EN) NULLABLE_RESOURCE(in_port_t, p_mclk_in), -#endif clock clk_audio_bclk, unsigned int divide, unsigned curSamFreq); #ifdef __XC__ diff --git a/lib_xua/src/core/ports/audioports.xc b/lib_xua/src/core/ports/audioports.xc index f7b51fdc4..1399a3ff0 100644 --- a/lib_xua/src/core/ports/audioports.xc +++ b/lib_xua/src/core/ports/audioports.xc @@ -26,9 +26,7 @@ void ConfigAudioPorts( in port p_bclk, #endif #endif -#if (XUA_I2S_EN) in port ?p_mclk_in, -#endif clock clk_audio_bclk, unsigned int divide, unsigned curSamFreq) { #if (I2S_CHANS_DAC != 0) || (I2S_CHANS_ADC != 0) diff --git a/lib_xua/src/core/pwm_thread.c b/lib_xua/src/core/pwm_thread.c index 6f69222d3..60a96cb8c 100644 --- a/lib_xua/src/core/pwm_thread.c +++ b/lib_xua/src/core/pwm_thread.c @@ -16,17 +16,20 @@ void setup_master_clock(port_t clk_in) __attribute__ ((weak)); void setup_master_clock(port_t clk_in) { } -void pwm_thread(chanend_t c_data, port_t clk_in) -{ - software_dac_hp_t sd; +void pwm_init(port_t clk_in) { xclock_t clk = CLKBLK_PWM; - port_t ports[2] = {PORT_PWM_OUT_LEFT, PORT_PWM_OUT_RIGHT}; - port_t clk_out = PORT_PWM_CLK_OUT; - port_enable(clk_in); setup_master_clock(clk_in); port_set_invert(clk_in); clock_enable(clk); clock_set_source_port(clk, clk_in); +} + +void pwm_thread(chanend_t c_data) +{ + software_dac_hp_t sd; + xclock_t clk = CLKBLK_PWM; + port_t ports[2] = {PORT_PWM_OUT_LEFT, PORT_PWM_OUT_RIGHT}; + port_t clk_out = PORT_PWM_CLK_OUT; software_dac_hp_init(&sd, ports, clk, clk_out, 8, sd_coeffs_o6_f1_5_n8); diff --git a/lib_xua/src/core/pwm_thread.h b/lib_xua/src/core/pwm_thread.h index 07396e664..2a49a992e 100644 --- a/lib_xua/src/core/pwm_thread.h +++ b/lib_xua/src/core/pwm_thread.h @@ -5,10 +5,12 @@ #if (XUA_PWM_CHANNELS > 0) #ifdef __XC__ -void pwm_thread(chanend c_data, in port p_mclk); + void pwm_init(in port clk_in); + void pwm_thread(chanend c_data); #else #include -void pwm_thread(chanend_t c_data, port_t p_mclk); + void pwm_init(port_t clk_in); + void pwm_thread(chanend_t c_data); #endif #endif From a7bf631b6449dd561f3b7c583f5aa7ec63a83a3c Mon Sep 17 00:00:00 2001 From: Henk Muller Date: Tue, 1 Apr 2025 13:23:35 +0100 Subject: [PATCH 03/15] New interface for modulator --- lib_xua/src/core/pwm_thread.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib_xua/src/core/pwm_thread.c b/lib_xua/src/core/pwm_thread.c index 60a96cb8c..cecf3ce33 100644 --- a/lib_xua/src/core/pwm_thread.c +++ b/lib_xua/src/core/pwm_thread.c @@ -10,6 +10,7 @@ #include #include #include "software_dac_hp.h" +#include "sigma_delta_modulators.h" #include "uac_hwresources.h" void setup_master_clock(port_t clk_in) __attribute__ ((weak)); From a013f31e1429b4dcf2d5a746e316e910bc3ea340 Mon Sep 17 00:00:00 2001 From: Henk Muller Date: Thu, 10 Apr 2025 15:01:54 +0100 Subject: [PATCH 04/15] New parameters for sigma_delta --- lib_xua/src/core/pwm_thread.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib_xua/src/core/pwm_thread.c b/lib_xua/src/core/pwm_thread.c index cecf3ce33..d1e1c14b4 100644 --- a/lib_xua/src/core/pwm_thread.c +++ b/lib_xua/src/core/pwm_thread.c @@ -32,7 +32,12 @@ void pwm_thread(chanend_t c_data) port_t ports[2] = {PORT_PWM_OUT_LEFT, PORT_PWM_OUT_RIGHT}; port_t clk_out = PORT_PWM_CLK_OUT; - software_dac_hp_init(&sd, ports, clk, clk_out, 8, sd_coeffs_o6_f1_5_n8); + software_dac_hp_init(&sd, ports, clk, clk_out, 8, + sd_coeffs_o6_f1_5_n8, + 2.8544, 2.8684735298, // scale, limit + 1.0/120000, -1.0/250000, // flat_comp_x2, x3 + 3.0/157, 0.63/157, // pwm comp x2, x3 + 0); // negate software_dac_hp(&sd, c_data); } From 5d2878bd4caf6b2f36bd0764eda3d74ecaab3b48 Mon Sep 17 00:00:00 2001 From: Henk Muller Date: Thu, 10 Apr 2025 15:05:24 +0100 Subject: [PATCH 05/15] Default to negate --- lib_xua/src/core/pwm_thread.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_xua/src/core/pwm_thread.c b/lib_xua/src/core/pwm_thread.c index d1e1c14b4..2bf51ca89 100644 --- a/lib_xua/src/core/pwm_thread.c +++ b/lib_xua/src/core/pwm_thread.c @@ -37,7 +37,7 @@ void pwm_thread(chanend_t c_data) 2.8544, 2.8684735298, // scale, limit 1.0/120000, -1.0/250000, // flat_comp_x2, x3 3.0/157, 0.63/157, // pwm comp x2, x3 - 0); // negate + 1); // negate software_dac_hp(&sd, c_data); } From 79d780bc216a462f58e6a5e482f149a61bfe3af4 Mon Sep 17 00:00:00 2001 From: Henk Muller Date: Thu, 10 Apr 2025 17:18:20 +0100 Subject: [PATCH 06/15] New pre distortion coefficients --- lib_xua/src/core/pwm_thread.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib_xua/src/core/pwm_thread.c b/lib_xua/src/core/pwm_thread.c index 2bf51ca89..058c2132a 100644 --- a/lib_xua/src/core/pwm_thread.c +++ b/lib_xua/src/core/pwm_thread.c @@ -35,8 +35,8 @@ void pwm_thread(chanend_t c_data) software_dac_hp_init(&sd, ports, clk, clk_out, 8, sd_coeffs_o6_f1_5_n8, 2.8544, 2.8684735298, // scale, limit - 1.0/120000, -1.0/250000, // flat_comp_x2, x3 - 3.0/157, 0.63/157, // pwm comp x2, x3 + -1.0/29000, 1.0/120000, // flat_comp_x2, x3 + -3.0/190, 0.63/80, // pwm comp x2, x3 1); // negate software_dac_hp(&sd, c_data); From 1ba9eefd0b9de69ccceaeade4228a6efb2441818 Mon Sep 17 00:00:00 2001 From: Henk Muller Date: Wed, 23 Apr 2025 11:19:30 +0100 Subject: [PATCH 07/15] Modified PWM configuration to use a conf.h file --- lib_xua/api/xua_pwm_conf_default.h | 40 ++++++++++++++++++++++++++++++ lib_xua/lib_build_info.cmake | 2 +- lib_xua/src/core/pwm_thread.c | 15 ++++++----- 3 files changed, 50 insertions(+), 7 deletions(-) create mode 100644 lib_xua/api/xua_pwm_conf_default.h diff --git a/lib_xua/api/xua_pwm_conf_default.h b/lib_xua/api/xua_pwm_conf_default.h new file mode 100644 index 000000000..92eda27ea --- /dev/null +++ b/lib_xua/api/xua_pwm_conf_default.h @@ -0,0 +1,40 @@ +#ifndef _xua_pwm_conf_default_h_ +#define _xua_pwm_conf_default_h_ + +#ifdef __xua_pwm_conf_h_exists__ + #include "xua_pwm_conf.h" +#endif + +#ifndef XUA_PWM_SD_COEFFS +#define XUA_PWM_SD_COEFFS sd_coeffs_o6_f1_5_n8 +#endif + +#ifndef XUA_PWM_SCALE +#define XUA_PWM_SCALE 2.8544 +#endif + +#ifndef XUA_PWM_LIMIT +#define XUA_PWM_LIMIT 2.8684735298 +#endif + +#ifndef XUA_PWM_FLAT_COMP_X2 +#define XUA_PWM_FLAT_COMP_X2 (-1.0/29000) +#endif + +#ifndef XUA_PWM_FLAT_COMP_X3 +#define XUA_PWM_FLAT_COMP_X3 (1.0/120000) +#endif + +#ifndef XUA_PWM_PWM_COMP_X2 +#define XUA_PWM_PWM_COMP_X2 (-3.0/190) +#endif + +#ifndef XUA_PWM_PWM_COMP_X3 +#define XUA_PWM_PWM_COMP_X3 (0.63/80) +#endif + +#ifndef XUA_PWM_NEGATE +#define XUA_PWM_NEGATE 1 +#endif + +#endif diff --git a/lib_xua/lib_build_info.cmake b/lib_xua/lib_build_info.cmake index 992638a78..07ce56919 100644 --- a/lib_xua/lib_build_info.cmake +++ b/lib_xua/lib_build_info.cmake @@ -19,7 +19,7 @@ set(LIB_INCLUDES api src/core/user/hostactive src/hid src/midi) -set(LIB_OPTIONAL_HEADERS xua_conf.h static_hid_report.h) +set(LIB_OPTIONAL_HEADERS xua_conf.h static_hid_report.h xua_pwm_conf.h) set(LIB_DEPENDENT_MODULES "lib_adat(2.0.1)" "lib_locks(2.3.1)" "lib_logging(3.3.1)" diff --git a/lib_xua/src/core/pwm_thread.c b/lib_xua/src/core/pwm_thread.c index 058c2132a..fa86ac4ee 100644 --- a/lib_xua/src/core/pwm_thread.c +++ b/lib_xua/src/core/pwm_thread.c @@ -5,6 +5,7 @@ */ #include "xua_conf_default.h" // Settings #if (XUA_PWM_CHANNELS > 0) +#include "xua_pwm_conf_default.h" // PWM Settings #include #include #include @@ -33,12 +34,14 @@ void pwm_thread(chanend_t c_data) port_t clk_out = PORT_PWM_CLK_OUT; software_dac_hp_init(&sd, ports, clk, clk_out, 8, - sd_coeffs_o6_f1_5_n8, - 2.8544, 2.8684735298, // scale, limit - -1.0/29000, 1.0/120000, // flat_comp_x2, x3 - -3.0/190, 0.63/80, // pwm comp x2, x3 - 1); // negate - + XUA_PWM_SD_COEFFS, + XUA_PWM_SCALE, + XUA_PWM_LIMIT, + XUA_PWM_FLAT_COMP_X2, + XUA_PWM_FLAT_COMP_X3, + XUA_PWM_PWM_COMP_X2, + XUA_PWM_PWM_COMP_X3, + XUA_PWM_NEGATE); software_dac_hp(&sd, c_data); } #endif From 9c624d9ca2fcc6f9ca069a9c528d321b1c2f58b4 Mon Sep 17 00:00:00 2001 From: Henk Muller Date: Wed, 7 May 2025 14:59:20 +0100 Subject: [PATCH 08/15] Added stream stop on DFU --- lib_xua/src/core/endpoint0/xua_endpoint0.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib_xua/src/core/endpoint0/xua_endpoint0.c b/lib_xua/src/core/endpoint0/xua_endpoint0.c index 868f24f7c..4140c1dc7 100755 --- a/lib_xua/src/core/endpoint0/xua_endpoint0.c +++ b/lib_xua/src/core/endpoint0/xua_endpoint0.c @@ -931,6 +931,7 @@ void XUA_Endpoint0_loop(XUD_Result_t result, USB_SetupPacket_t sp, chanend c_ep0 if(reset) { + UserAudioStreamStop(); DFUDelay(DELAY_BEFORE_REBOOT_TO_DFU_MS * 100000); device_reboot(); } @@ -1037,6 +1038,7 @@ void XUA_Endpoint0_loop(XUD_Result_t result, USB_SetupPacket_t sp, chanend c_ep0 result = DFUDeviceRequests(ep0_out, &ep0_in, &sp, null, 0 /*this is unused in DFUDeviceRequests()??*/, dfuInterface, &reset); if(reset) { + UserAudioStreamStop(); DFUDelay(DELAY_BEFORE_REBOOT_TO_DFU_MS * 100000); device_reboot(); } @@ -1245,6 +1247,7 @@ void XUA_Endpoint0_loop(XUD_Result_t result, USB_SetupPacket_t sp, chanend c_ep0 #else g_curUsbSpeed = XUD_ResetEndpoint(ep0_out, &ep0_in); #endif + UserAudioStreamStop(); g_currentConfig = 0; g_curStreamAlt_Out = 0; g_curStreamAlt_In = 0; From 8262b5e9c11e31497354b9c0ea8979763b200b47 Mon Sep 17 00:00:00 2001 From: Henk Muller Date: Wed, 7 May 2025 17:09:10 +0100 Subject: [PATCH 09/15] Avoiding pop --- lib_xua/src/core/audiohub/xua_audiohub.xc | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/lib_xua/src/core/audiohub/xua_audiohub.xc b/lib_xua/src/core/audiohub/xua_audiohub.xc index 4d8bd99ef..013511449 100755 --- a/lib_xua/src/core/audiohub/xua_audiohub.xc +++ b/lib_xua/src/core/audiohub/xua_audiohub.xc @@ -574,11 +574,15 @@ void testct_byref(chanend c, int &returnVal) returnVal = 1; } -#if (XUA_DFU_EN == 1) && ((NUM_USB_CHAN_OUT > 0) || (NUM_USB_CHAN_IN > 0)) +#if (XUA_DFU_EN == 1) && ((NUM_USB_CHAN_OUT > 0) || (NUM_USB_CHAN_IN > 0) || (XUA_PWM_CHANNELS > 0)) /* This function is a dummy version of the deliver thread that does not connect to the codec ports. It is used during DFU reset. */ [[combinable]] -static void dummy_deliver(chanend ?c_out, unsigned &command) +static void dummy_deliver(chanend ?c_out, +#if XUA_PWM_CHANNELS > 0 + chanend c_pwm, +#endif + unsigned &command) { int ct; @@ -613,6 +617,13 @@ static void dummy_deliver(chanend ?c_out, unsigned &command) { outuint(c_out, 0); } +#endif +#if XUA_PWM_CHANNELS > 0 +#pragma loop unroll + for(int i = 0; i < XUA_PWM_CHANNELS; i++) + { + outuint(c_pwm, 0); + } #endif } const int wait_ticks = XS1_TIMER_HZ/48000; @@ -945,8 +956,12 @@ void XUA_AudioHub(chanend ?c_aud, clock ?clk_audio_mclk, clock ?clk_audio_bclk #if (XUD_TILE != 0) && (AUDIO_IO_TILE == 0) DFUHandler(dfuInterface, null); #endif -#if (NUM_USB_CHAN_OUT > 0) || (NUM_USB_CHAN_IN > 0) - dummy_deliver(c_aud, command); +#if (NUM_USB_CHAN_OUT > 0) || (NUM_USB_CHAN_IN > 0) || (XUA_PWM_CHANNELS > 0) + dummy_deliver(c_aud, +#if XUA_PWM_CHANNELS > 0 + c_pwm_channels, +#endif + command); #endif } /* Note, we shouldn't reach here. Audio, once stopped for DFU, cannot be resumed */ From eddbd7e9db165d65e9c532b2cf9e86d35595c69d Mon Sep 17 00:00:00 2001 From: Ed Date: Tue, 19 Aug 2025 18:57:42 +0100 Subject: [PATCH 10/15] typo --- lib_xua/src/core/endpoint0/xua_ep0_descriptors.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_xua/src/core/endpoint0/xua_ep0_descriptors.h b/lib_xua/src/core/endpoint0/xua_ep0_descriptors.h index 34a98a3e0..24717e420 100644 --- a/lib_xua/src/core/endpoint0/xua_ep0_descriptors.h +++ b/lib_xua/src/core/endpoint0/xua_ep0_descriptors.h @@ -571,7 +571,7 @@ unsigned char devQualDesc_Null[] = // OUTPUT /* Endpoint descriptor wMaxPacketSize */ -dd + #define HS_STREAM_FORMAT_OUTPUT_1_EP_DESC_WMAXPACKETSIZE (HS_STREAM_FORMAT_OUTPUT_1_MAXPACKETSIZE) #define HS_STREAM_FORMAT_OUTPUT_2_EP_DESC_WMAXPACKETSIZE (HS_STREAM_FORMAT_OUTPUT_2_MAXPACKETSIZE) #define HS_STREAM_FORMAT_OUTPUT_3_EP_DESC_WMAXPACKETSIZE (HS_STREAM_FORMAT_OUTPUT_3_MAXPACKETSIZE) From 39264837e23142bc66bdd14e2cb9aa47fb6f0ed1 Mon Sep 17 00:00:00 2001 From: Ed Date: Tue, 19 Aug 2025 19:01:42 +0100 Subject: [PATCH 11/15] Remove UserAudioStreamStop/UserAudioStreamStop in DFU --- lib_xua/src/core/endpoint0/xua_endpoint0.c | 2 -- lib_xua/src/core/endpoint0/xua_ep0_descriptors.h | 1 - 2 files changed, 3 deletions(-) diff --git a/lib_xua/src/core/endpoint0/xua_endpoint0.c b/lib_xua/src/core/endpoint0/xua_endpoint0.c index 8c3479869..c3aa3e7cb 100755 --- a/lib_xua/src/core/endpoint0/xua_endpoint0.c +++ b/lib_xua/src/core/endpoint0/xua_endpoint0.c @@ -867,7 +867,6 @@ void XUA_Endpoint0_loop(XUD_Result_t result, USB_SetupPacket_t sp, chanend c_ep0 if(reset) { - UserAudioStreamStop(); DFUDelay(DELAY_BEFORE_REBOOT_TO_DFU_MS * 100000); device_reboot(); } @@ -976,7 +975,6 @@ void XUA_Endpoint0_loop(XUD_Result_t result, USB_SetupPacket_t sp, chanend c_ep0 result = DFUDeviceRequests(ep0_out, &ep0_in, &sp, null, 0 /*this is unused in DFUDeviceRequests()??*/, dfuInterface, &reset); if(reset) { - UserAudioStreamStop(); DFUDelay(DELAY_BEFORE_REBOOT_TO_DFU_MS * 100000); device_reboot(); } diff --git a/lib_xua/src/core/endpoint0/xua_ep0_descriptors.h b/lib_xua/src/core/endpoint0/xua_ep0_descriptors.h index 24717e420..ca5879f79 100644 --- a/lib_xua/src/core/endpoint0/xua_ep0_descriptors.h +++ b/lib_xua/src/core/endpoint0/xua_ep0_descriptors.h @@ -571,7 +571,6 @@ unsigned char devQualDesc_Null[] = // OUTPUT /* Endpoint descriptor wMaxPacketSize */ - #define HS_STREAM_FORMAT_OUTPUT_1_EP_DESC_WMAXPACKETSIZE (HS_STREAM_FORMAT_OUTPUT_1_MAXPACKETSIZE) #define HS_STREAM_FORMAT_OUTPUT_2_EP_DESC_WMAXPACKETSIZE (HS_STREAM_FORMAT_OUTPUT_2_MAXPACKETSIZE) #define HS_STREAM_FORMAT_OUTPUT_3_EP_DESC_WMAXPACKETSIZE (HS_STREAM_FORMAT_OUTPUT_3_MAXPACKETSIZE) From 57f27aa9c12a51e097571c8892ef541ee93927fc Mon Sep 17 00:00:00 2001 From: Ed Date: Tue, 19 Aug 2025 19:14:49 +0100 Subject: [PATCH 12/15] Fix missing define --- lib_xua/src/core/endpoint0/xua_ep0_descriptors.h | 1 + 1 file changed, 1 insertion(+) diff --git a/lib_xua/src/core/endpoint0/xua_ep0_descriptors.h b/lib_xua/src/core/endpoint0/xua_ep0_descriptors.h index ca5879f79..fa02c43be 100644 --- a/lib_xua/src/core/endpoint0/xua_ep0_descriptors.h +++ b/lib_xua/src/core/endpoint0/xua_ep0_descriptors.h @@ -14,6 +14,7 @@ #include "descriptor_defs.h" #include "usbaudio20.h" /* Defines from the USB Audio 2.0 Specifications */ #include "usbaudiocommon.h" +#include "packet_sizes.h" #include "xud_device.h" #include "xua_hid_descriptor.h" #include "xua_ep0_midi_descriptors.h" From 89e7563a0cfc32c6015bea4e3814b3d3e4e076ba Mon Sep 17 00:00:00 2001 From: Ed Date: Thu, 21 Aug 2025 10:24:05 +0100 Subject: [PATCH 13/15] Changelog entry for sigma_delta --- CHANGELOG.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 2b0dd1bdc..2496ee28a 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -8,6 +8,8 @@ UNRELEASED same functionality as `xua_conf_cores.h` i.e. to allow insertion of tasks into the `main()` function (`xua_conf_cores.h` to be deprecated in a future release) + * ADDED: Support for lib_sigma_delta to provide high-quality PWM audio + outputs via GPIO pins ADDED: Support for define `USER_MAIN_TASKS` with the same functionalty as `USER_MAIN_CORES` i.e. to allow insertion of tasks into the `main()` function (`USER_MAIN_CORES` to be deprecated in a future release) From b43e932963dc340f7476041bf3f0fe2208c8d0cc Mon Sep 17 00:00:00 2001 From: Ed Date: Thu, 21 Aug 2025 16:04:19 +0100 Subject: [PATCH 14/15] Fix merge issues --- lib_xua/src/core/audiohub/xua_audiohub.xc | 10 ---------- lib_xua/src/core/clocking/sw_pll_wrapper.xc | 2 +- lib_xua/src/core/ports/audioports.c | 7 ++++--- 3 files changed, 5 insertions(+), 14 deletions(-) diff --git a/lib_xua/src/core/audiohub/xua_audiohub.xc b/lib_xua/src/core/audiohub/xua_audiohub.xc index 1374d9fc2..a2276de39 100755 --- a/lib_xua/src/core/audiohub/xua_audiohub.xc +++ b/lib_xua/src/core/audiohub/xua_audiohub.xc @@ -609,15 +609,6 @@ void DFUHandler(server interface i_dfu i, chanend ?c_user_cmd); #endif -#pragma select handler -void testct_byref(chanend c, int &returnVal) -{ - returnVal = 0; - if(testct(c)) - returnVal = 1; -} - -#if (XUA_DFU_EN == 1) && ((NUM_USB_CHAN_OUT > 0) || (NUM_USB_CHAN_IN > 0) || (XUA_PWM_CHANNELS > 0)) /* This function is a dummy version of the deliver thread that does not connect to the codec ports. It is used during DFU reset and during idle non-streaming mode, if enabled. Note there are two paths through depending on dfuMode.*/ @@ -683,7 +674,6 @@ static void dummy_deliver(chanend ?c_aud, chanend ?c_pwm, unsigned sampFreq, uns } } } -#endif #if XUA_DFU_EN /* External DFU handler task */ diff --git a/lib_xua/src/core/clocking/sw_pll_wrapper.xc b/lib_xua/src/core/clocking/sw_pll_wrapper.xc index 168ef66e5..c9fa9cedb 100644 --- a/lib_xua/src/core/clocking/sw_pll_wrapper.xc +++ b/lib_xua/src/core/clocking/sw_pll_wrapper.xc @@ -120,7 +120,7 @@ void sw_pll_task(chanend c_sw_pll){ the first control value has been received. This avoids issues with channel lockup if two tasks (eg. init and SDM) try to write at the same time. */ - unsigned command = inuint(c_sw_pll); + inuint(c_sw_pll); inct(c_sw_pll); while(1) { diff --git a/lib_xua/src/core/ports/audioports.c b/lib_xua/src/core/ports/audioports.c index 35c581d1b..59312708a 100644 --- a/lib_xua/src/core/ports/audioports.c +++ b/lib_xua/src/core/ports/audioports.c @@ -43,11 +43,12 @@ void ConfigAudioPortsWrapper( #if (I2S_CHANS_DAC != 0) || (I2S_CHANS_ADC != 0) #if (CODEC_MASTER == 0) - NULLABLE_RESOURCE(out_port_t p_lrclk), + NULLABLE_RESOURCE(out_buffered_port_32_t, p_lrclk), + out_buffered_port_32_t p_bclk, #else - NULLABLE_RESOURCE(in_port_t p_lrclk), + NULLABLE_RESOURCE(in_buffered_port_32_t, p_lrclk), + in_buffered_port_32_t p_bclk, #endif - port p_bclk, #endif NULLABLE_RESOURCE(in_port_t, p_mclk_in), clock clk_audio_bclk, unsigned int divide, unsigned curSamFreq) From 01394ac7af0d3b32755381d8ee2f78a919a1d7ef Mon Sep 17 00:00:00 2001 From: Ed Date: Thu, 21 Aug 2025 16:08:54 +0100 Subject: [PATCH 15/15] Source check --- lib_xua/api/xua_pwm_conf_default.h | 2 ++ lib_xua/src/core/pwm_thread.c | 2 ++ lib_xua/src/core/pwm_thread.h | 2 ++ 3 files changed, 6 insertions(+) diff --git a/lib_xua/api/xua_pwm_conf_default.h b/lib_xua/api/xua_pwm_conf_default.h index 92eda27ea..9af82b933 100644 --- a/lib_xua/api/xua_pwm_conf_default.h +++ b/lib_xua/api/xua_pwm_conf_default.h @@ -1,3 +1,5 @@ +// Copyright 2025 XMOS LIMITED. +// This Software is subject to the terms of the XMOS Public Licence: Version 1. #ifndef _xua_pwm_conf_default_h_ #define _xua_pwm_conf_default_h_ diff --git a/lib_xua/src/core/pwm_thread.c b/lib_xua/src/core/pwm_thread.c index fa86ac4ee..6106fb588 100644 --- a/lib_xua/src/core/pwm_thread.c +++ b/lib_xua/src/core/pwm_thread.c @@ -1,3 +1,5 @@ +// Copyright 2024-2025 XMOS LIMITED. +// This Software is subject to the terms of the XMOS Public Licence: Version 1. /** * @file pwm_thread.c * @brief Fork the threads to run a PWM engine diff --git a/lib_xua/src/core/pwm_thread.h b/lib_xua/src/core/pwm_thread.h index 2a49a992e..037596da3 100644 --- a/lib_xua/src/core/pwm_thread.h +++ b/lib_xua/src/core/pwm_thread.h @@ -1,3 +1,5 @@ +// Copyright 2024-2025 XMOS LIMITED. +// This Software is subject to the terms of the XMOS Public Licence: Version 1. #ifndef __pwm_thread__h_ #define __pwm_thread__h_