From c662acaa3b8a2f2252a006d3c4075d14de85e481 Mon Sep 17 00:00:00 2001 From: Ed Clarke Date: Mon, 5 Nov 2018 13:46:01 +0000 Subject: [PATCH] WIP Adaptive with PLL nudge (demo working) --- examples/xua_lite_example/src/AudioConfig.h | 11 +-- examples/xua_lite_example/src/AudioConfig.xc | 75 ++++++++++++++++--- examples/xua_lite_example/src/app_xua_lite.xc | 6 +- examples/xua_lite_example/src/audio_hub.xc | 12 ++- examples/xua_lite_example/src/pdm_mic.xc | 32 ++++++++ .../xua_lite_example/src/xua_buffer_lite.xc | 34 ++++++++- 6 files changed, 144 insertions(+), 26 deletions(-) diff --git a/examples/xua_lite_example/src/AudioConfig.h b/examples/xua_lite_example/src/AudioConfig.h index 9843cb1d..a4fe9270 100755 --- a/examples/xua_lite_example/src/AudioConfig.h +++ b/examples/xua_lite_example/src/AudioConfig.h @@ -1,15 +1,8 @@ #ifndef _AUDIO_CONFIG_ #define _AUDIO_CONFIG_ -void ConfigAudioPorts(unsigned divide); +void AudioHwConfigure(unsigned samFreq, client i2c_master_if i_i2c); +void pll_nudge(int nudge); -void AudioHwInit(); - -void PLL_Init(void); - -/* Configures master clock and codc for passed sample freq */ -void AudioHwConfig(unsigned samFreq); - -void ConfigCodec24576(unsigned samFeq); #endif diff --git a/examples/xua_lite_example/src/AudioConfig.xc b/examples/xua_lite_example/src/AudioConfig.xc index acf1cb9e..a1dde227 100755 --- a/examples/xua_lite_example/src/AudioConfig.xc +++ b/examples/xua_lite_example/src/AudioConfig.xc @@ -4,7 +4,10 @@ #include #include #include "i2c.h" - +#include "xua.h" +#define DEBUG_UNIT AUDIO_CFG +#define DEBUG_PRINT_ENABLE_AUDIO_CFG 1 +#include "debug_print.h" // TLV320DAC3101 Device I2C Address @@ -45,16 +48,39 @@ #define DAC3101_SPKR_DRVR 0x2B // Register 43 - Right Class-D Speaker Driver // TLV320DAC3101 easy register access defines -//#define DAC3101_REGREAD(reg, data) {data[0] = 0xAA; i2c_master_read_reg(DAC3101_I2C_DEVICE_ADDR, reg, data, 1, i2c);} -//#define DAC3101_REGWRITE(reg, val) {data[0] = val; i2c_master_write_reg(DAC3101_I2C_DEVICE_ADDR, reg, data, 1, i2c);} - -//#define DAC3101_REGWRITE(reg, val) {i_i2c[0].write_reg(DAC3101_I2C_DEVICE_ADDR, reg, val);} - -// TLV320DAC3101 easy register access defines -//#define DAC3101_REGWRITE(reg, val) {data[0] = val; i2c_master_write_reg(DAC3101_I2C_DEVICE_ADDR, reg, data, 1, i2c);} #define DAC3101_REGWRITE(reg, val) {i_i2c.write_reg(DAC3101_I2C_DEVICE_ADDR, reg, val);} + +static void set_node_pll_reg(tileref tile_ref, unsigned reg_val){ + write_sswitch_reg(get_tile_id(tile_ref), XS1_SSWITCH_PLL_CTL_NUM, reg_val); +} + +// Nominal setting is ref div = 25, fb_div = 1024, op_div = 2 +// PCF Freq 0.96MHz + +enum clock_nudge{ + PLL_SLOWER = -1, + PLL_NOMINAL = 0, + PLL_FASTER = 1 +}; + +#define PLL_LOW 0xC003FE18 // This is 3.069MHz +#define PLL_NOM 0xC003FF18 // This is 3.072MHz +#define PLL_HIGH 0xC0040018 // This is 3.075MHz + +int old_nudge = 0; +void pll_nudge(int nudge) { + if (nudge > 0){ + set_node_pll_reg(tile[0], PLL_HIGH); + } + else if (nudge < 0){ + set_node_pll_reg(tile[0], PLL_LOW); + } + set_node_pll_reg(tile[0], PLL_NOM); + if(nudge != old_nudge && nudge){debug_printf("nudge: %d\n", nudge); }old_nudge = nudge; +} + void AudioHwConfigure(unsigned samFreq, client i2c_master_if i_i2c) { @@ -101,6 +127,34 @@ void AudioHwConfigure(unsigned samFreq, client i2c_master_if i_i2c) // DAC_MOD_CLK = DAC_CLK / 4 = 5.6448MHz. // DAC_FS = DAC_MOD_CLK / 128 = 44.1kHz. +#if XUA_ADAPTIVE + //Set nominal clock speed on PLL + write_sswitch_reg(get_tile_id(tile[0]), XS1_SSWITCH_PLL_CTL_NUM, PLL_NOM); + + // We are assuming 48kHz family only and we generate MCLK + // Set PLL J Value to 7 + DAC3101_REGWRITE(DAC3101_PLL_J, 0x07); + // Set PLL D to 0 ... + // Set PLL D MSB Value to 0x00 + DAC3101_REGWRITE(DAC3101_PLL_D_MSB, 0x07); + // Set PLL D LSB Value to 0x00 + DAC3101_REGWRITE(DAC3101_PLL_D_LSB, 0x80); + + delay_milliseconds(1); + + // Set PLL_CLKIN = BCLK (device pin), CODEC_CLKIN = PLL_CLK (generated on-chip) + DAC3101_REGWRITE(DAC3101_CLK_GEN_MUX, 0x07); + + // Set PLL P and R values and power up. + DAC3101_REGWRITE(DAC3101_PLL_P_R, 0x94); + // Set NDAC clock divider to 2 and power up. + DAC3101_REGWRITE(DAC3101_NDAC_VAL, 0x82); + // Set MDAC clock divider to 7 and power up. + DAC3101_REGWRITE(DAC3101_MDAC_VAL, 0x87); + // Set OSR clock divider to 128. + DAC3101_REGWRITE(DAC3101_DOSR_VAL_LSB, 0x80); + +#else /* Sample frequency dependent register settings */ if ((samFreq % 11025) == 0) { @@ -143,7 +197,9 @@ void AudioHwConfigure(unsigned samFreq, client i2c_master_if i_i2c) DAC3101_REGWRITE(DAC3101_MDAC_VAL, 0x84); // Set OSR clock divider to 128. DAC3101_REGWRITE(DAC3101_DOSR_VAL_LSB, 0x80); - + +#endif + // Set CLKOUT Mux to DAC_CLK DAC3101_REGWRITE(DAC3101_CLKOUT_MUX, 0x04); // Set CLKOUT M divider to 1 and power up. @@ -205,6 +261,7 @@ void AudioHwConfigure(unsigned samFreq, client i2c_master_if i_i2c) i_i2c.shutdown(); } + //These are here just to silence compiler warnings void AudioHwInit(){} void AudioHwConfig(unsigned samFreq, unsigned mClk, unsigned dsdMode, unsigned sampRes_DAC, unsigned sampRes_ADC){} \ No newline at end of file diff --git a/examples/xua_lite_example/src/app_xua_lite.xc b/examples/xua_lite_example/src/app_xua_lite.xc index d33daf09..94115c54 100644 --- a/examples/xua_lite_example/src/app_xua_lite.xc +++ b/examples/xua_lite_example/src/app_xua_lite.xc @@ -64,6 +64,7 @@ void AudioHwConfigure(unsigned samFreq, client i2c_master_if i_i2c); void XUA_Endpoint0_select(chanend c_ep0_out, chanend c_ep0_in, chanend c_audioControl, chanend ?c_mix_ctl, chanend ?c_clk_ctl, chanend ?c_EANativeTransport_ctrl, CLIENT_INTERFACE(i_dfu, ?dfuInterface) VENDOR_REQUESTS_PARAMS_DEC_); void pdm_mic(streaming chanend c_ds_output, in buffered port:32 p_pdm_mics); +void mic_array_setup_ddr_xcore(clock pdmclk, clock pdmclk6, out port p_pdm_clk, buffered in port:32 p_pdm_data, int divide); void burn_normal_priority(void){ while(1); @@ -98,7 +99,8 @@ int main() c_audio :> int _; //Now wait until i2c has finished mclk setup const unsigned micDiv = MCLK_48/3072000; - mic_array_setup_ddr(pdmclk, pdmclk6, p_mclk_in, p_pdm_clk, p_pdm_mics, micDiv); + if (XUA_ADAPTIVE) mic_array_setup_ddr_xcore(pdmclk, pdmclk6, p_pdm_clk, p_pdm_mics, micDiv); + else mic_array_setup_ddr(pdmclk, pdmclk6, p_mclk_in, p_pdm_clk, p_pdm_mics, micDiv); par { i2s_frame_master(i_i2s, p_i2s_dac, 1, p_i2s_adc, 1, p_bclk, p_lrclk, p_mclk_in, clk_audio_bclk); @@ -110,7 +112,7 @@ int main() } } on tile[1]:{ - // Connect master-clock input clock-block to clock-block pin + // Connect master-clock input clock-block to clock-block pin for asnch feedback calculation set_clock_src(clk_usb_mclk, p_mclk_in_usb); // Clock clock-block from mclk pin set_port_clock(p_for_mclk_count, clk_usb_mclk); // Clock the "count" port from the clock block start_clock(clk_usb_mclk); // Set the clock off running diff --git a/examples/xua_lite_example/src/audio_hub.xc b/examples/xua_lite_example/src/audio_hub.xc index 9516c262..42c1cdd9 100644 --- a/examples/xua_lite_example/src/audio_hub.xc +++ b/examples/xua_lite_example/src/audio_hub.xc @@ -5,6 +5,7 @@ #define DEBUG_PRINT_ENABLE_XUA_AUDIO_HUB 1 #include "debug_print.h" #include "mic_array.h" +#include "AudioConfig.h" void mic_array_decimator_set_samprate(const unsigned samplerate, int mic_decimator_fir_data_array[], mic_array_decimator_conf_common_t *dcc, mic_array_decimator_config_t dc[]); @@ -31,6 +32,8 @@ void AudioHub(server i2s_frame_callback_if i2s, int32_t samples_out[NUM_USB_CHAN_OUT] = {0}; int32_t samples_in[NUM_USB_CHAN_IN] = {0}; + int32_t clock_nudge = 0; + #if XUA_NUM_PDM_MICS > 0 unsigned buffer; int raw_mics[XUA_NUM_PDM_MICS] = {0}; @@ -66,8 +69,9 @@ void AudioHub(server i2s_frame_callback_if i2s, case i2s.restart_check() -> i2s_restart_t restart: restart = I2S_NO_RESTART; // Keep on looping timer tmr; int t0, t1; tmr :> t0; - for (int i = 0; i < NUM_USB_CHAN_OUT; i++) c_audio :> samples_out[i]; - for (int i = 0; i < NUM_USB_CHAN_IN; i++) c_audio <: raw_mics[i]; + for (int i = 0; i < NUM_USB_CHAN_OUT; i++) c_audio :> samples_out[i]; + if (XUA_ADAPTIVE) c_audio :> clock_nudge; + for (int i = 0; i < NUM_USB_CHAN_IN; i++) c_audio <: raw_mics[i]; //Grab mics current = mic_array_get_next_time_domain_frame(c_ds_output, decimatorCount, buffer, mic_audio_frame, dc); @@ -75,8 +79,10 @@ void AudioHub(server i2s_frame_callback_if i2s, raw_mics[0] = current->data[0][0]; raw_mics[1] = current->data[1][0]; } + + pll_nudge(clock_nudge); //tmr :> t1; debug_printf("%d\n", t1 - t0); - delay_microseconds(15); //Test backpressure tolerance + //delay_microseconds(10); //Test backpressure tolerance break; } } diff --git a/examples/xua_lite_example/src/pdm_mic.xc b/examples/xua_lite_example/src/pdm_mic.xc index eb6227d1..bc2fd263 100644 --- a/examples/xua_lite_example/src/pdm_mic.xc +++ b/examples/xua_lite_example/src/pdm_mic.xc @@ -74,4 +74,36 @@ void pdm_mic(streaming chanend c_ds_output, in buffered port:32 p_pdm_mics) } } + +void mic_array_setup_ddr_xcore(clock pdmclk, + clock pdmclk6, + out port p_pdm_clk, + buffered in port:32 p_pdm_data, + int divide) { + configure_clock_xcore(pdmclk, 80); + //configure_clock_src_divide(pdmclk, p_mclk, divide/2); + + configure_clock_xcore(pdmclk6, 40); + //configure_clock_src_divide(pdmclk6, p_mclk, divide/4); + + configure_port_clock_output(p_pdm_clk, pdmclk); + configure_in_port(p_pdm_data, pdmclk6); + + /* start the faster capture clock */ + start_clock(pdmclk6); + /* wait for a rising edge on the capture clock */ + partin(p_pdm_data, 4); + /* start the slower output clock */ + start_clock(pdmclk); + + /* + * this results in the rising edge of the capture clock + * leading the rising edge of the output clock by one period + * of p_mclk, which is about 40.7 ns for the typical frequency + * of 24.576 megahertz. + * This should fall within the data valid window. + */ + +} + #endif diff --git a/examples/xua_lite_example/src/xua_buffer_lite.xc b/examples/xua_lite_example/src/xua_buffer_lite.xc index adda73c4..03c832e2 100644 --- a/examples/xua_lite_example/src/xua_buffer_lite.xc +++ b/examples/xua_lite_example/src/xua_buffer_lite.xc @@ -155,6 +155,27 @@ void do_feedback_calculation(unsigned &sof_count } } +void fill_level_process(int fill_level, int &clock_nudge){ + const int trigger_high_upper = 6; + const int trigger_high_lower = 8; + + const int trigger_low_upper = -6; + const int trigger_low_lower = -8; + + if (fill_level >= trigger_high_upper){ + clock_nudge = 1; + //debug_printf("Nudge down\n"); + } + else if (fill_level <= trigger_low_upper){ + //debug_printf("Nudge up\n"); + clock_nudge = -1; + } + else clock_nudge = 0; + //debug_printf("%d\n", clock_nudge); + + static unsigned counter; counter++; if (counter>SOF_FREQ_HZ){counter = 0; debug_printf("f: %d\n",fill_level);} +} + extern "C"{ void XUA_Endpoint0_lite_init(chanend c_ep0_out, chanend c_ep0_in, chanend c_audioControl, @@ -187,7 +208,10 @@ void XUA_Buffer_lite(chanend c_ep0_out, chanend c_ep0_in, chanend c_aud_out, cha const unsigned mclk_hz = MCLK_48; unsigned int fb_clocks[1] = {0}; - + //Adapative device clock control + int clock_nudge = 0; + + //Endpoints XUD_ep ep_aud_out = XUD_InitEp(c_aud_out); XUD_ep ep_aud_in = XUD_InitEp(c_aud_in); XUD_ep ep_feedback = 0; @@ -270,6 +294,9 @@ void XUA_Buffer_lite(chanend c_ep0_out, chanend c_ep0_in, chanend c_aud_out, cha if (ret != FIFO_SUCCESS) debug_printf("h2d full\n"); num_samples_to_send_to_host = num_samples_received_from_host; + int fill_level = fifo_get_fill_relative_half(host_to_device_fifo_ptr); + fill_level_process(fill_level, clock_nudge); + //Mark EP as ready for next frame from host XUD_SetReady_OutPtr(ep_aud_out, (unsigned)buffer_aud_out); //tmr :> t1; debug_printf("o%d\n", t1 - t0); @@ -314,10 +341,11 @@ void XUA_Buffer_lite(chanend c_ep0_out, chanend c_ep0_in, chanend c_aud_out, cha c_audio_hub :> samples_in[i]; } fifo_ret_t ret = fifo_block_pop(host_to_device_fifo_ptr, samples_out, NUM_USB_CHAN_OUT); - if (ret != FIFO_SUCCESS && output_interface_num) debug_printf("h2s empty\n"); + if (ret != FIFO_SUCCESS && output_interface_num != 0) debug_printf("h2d empty\n"); for (int i = 0; i < NUM_USB_CHAN_OUT; i++) c_audio_hub <: samples_out[i]; + if (XUA_ADAPTIVE) c_audio_hub <: clock_nudge; ret = fifo_block_push(device_to_host_fifo_ptr, samples_in, NUM_USB_CHAN_IN); - if (ret != FIFO_SUCCESS && input_interface_num) debug_printf("d2h full\n"); + if (ret != FIFO_SUCCESS && input_interface_num != 0) debug_printf("d2h full\n"); //tmr :> t1; debug_printf("a%d\n", t1 - t0); break; }