WIP Adaptive with PLL nudge (demo working)

This commit is contained in:
Ed Clarke
2018-11-05 13:46:01 +00:00
parent 3214d4ea9f
commit c662acaa3b
6 changed files with 144 additions and 26 deletions

View File

@@ -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

View File

@@ -4,7 +4,10 @@
#include <print.h>
#include <stdio.h>
#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){}

View File

@@ -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

View File

@@ -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;
}
}

View File

@@ -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

View File

@@ -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;
}