diff --git a/examples/AN00246_xua_example/src/hwsupport.xc b/examples/AN00246_xua_example/src/hwsupport.xc index 5f019752..e0e671a0 100644 --- a/examples/AN00246_xua_example/src/hwsupport.xc +++ b/examples/AN00246_xua_example/src/hwsupport.xc @@ -1,9 +1,11 @@ -// Copyright 2017-2022 XMOS LIMITED. +// Copyright 2017-2024 XMOS LIMITED. // This Software is subject to the terms of the XMOS Public Licence: Version 1. #include #include #include "xua.h" -#include "../../shared/apppll.h" +extern "C"{ + #include "sw_pll.h" +} on tile[0]: out port p_ctrl = XS1_PORT_8D; @@ -38,19 +40,26 @@ void AudioHwInit() delay_milliseconds(100); /* Use xCORE Secondary PLL to generate *fixed* master clock */ - AppPllEnable_SampleRate(DEFAULT_FREQ); + if(DEFAULT_FREQ % 22050 == 0) + { + sw_pll_fixed_clock(MCLK_441); + } + else + { + sw_pll_fixed_clock(MCLK_48); + } delay_milliseconds(100); /* DAC setup: For basic I2S input we don't need any register setup. DACs will clock auto detect etc. * It holds DAC in reset until it gets clocks anyway. - * Note, this example doesn't use the ADC's + * Note, this example doesn't use the ADCs */ } /* Configures the external audio hardware for the required sample frequency */ void AudioHwConfig(unsigned samFreq, unsigned mClk, unsigned dsdMode, unsigned sampRes_DAC, unsigned sampRes_ADC) { - AppPllEnable_SampleRate(samFreq); + sw_pll_fixed_clock(mClk); } diff --git a/examples/AN00247_xua_example_spdif_tx/src/hwsupport.xc b/examples/AN00247_xua_example_spdif_tx/src/hwsupport.xc index 5f019752..1847872c 100644 --- a/examples/AN00247_xua_example_spdif_tx/src/hwsupport.xc +++ b/examples/AN00247_xua_example_spdif_tx/src/hwsupport.xc @@ -1,9 +1,12 @@ -// Copyright 2017-2022 XMOS LIMITED. +// Copyright 2017-2024 XMOS LIMITED. // This Software is subject to the terms of the XMOS Public Licence: Version 1. #include #include #include "xua.h" -#include "../../shared/apppll.h" +#include "xassert.h" +extern "C"{ + #include "sw_pll.h" +} on tile[0]: out port p_ctrl = XS1_PORT_8D; @@ -38,19 +41,26 @@ void AudioHwInit() delay_milliseconds(100); /* Use xCORE Secondary PLL to generate *fixed* master clock */ - AppPllEnable_SampleRate(DEFAULT_FREQ); + if(DEFAULT_FREQ % 22050 == 0) + { + sw_pll_fixed_clock(MCLK_441); + } + else + { + sw_pll_fixed_clock(MCLK_48); + } delay_milliseconds(100); /* DAC setup: For basic I2S input we don't need any register setup. DACs will clock auto detect etc. * It holds DAC in reset until it gets clocks anyway. - * Note, this example doesn't use the ADC's + * Note, this example doesn't use the ADCs */ } /* Configures the external audio hardware for the required sample frequency */ void AudioHwConfig(unsigned samFreq, unsigned mClk, unsigned dsdMode, unsigned sampRes_DAC, unsigned sampRes_ADC) { - AppPllEnable_SampleRate(samFreq); + sw_pll_fixed_clock(mClk); } diff --git a/examples/shared/apppll.h b/examples/shared/apppll.h deleted file mode 100644 index 1312c0ab..00000000 --- a/examples/shared/apppll.h +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright 2022 XMOS LIMITED. -// This Software is subject to the terms of the XMOS Public Licence: Version 1. -#include -#include "xassert.h" - -// App PLL setup -#define APP_PLL_CTL_BYPASS (0) // 0 = no bypass, 1 = bypass. -#define APP_PLL_CTL_INPUT_SEL (0) // 0 = XTAL, 1 = sysPLL -#define APP_PLL_CTL_ENABLE (1) // 0 = disabled, 1 = enabled. - -// 24MHz in, 24.576MHz out, integer mode -// Found exact solution: IN 24000000.0, OUT 24576000.0, VCO 2457600000.0, RD 5, FD 512, OD 10, FOD 10 -#define APP_PLL_CTL_OD_48 (4) // Output divider = (OD+1) -#define APP_PLL_CTL_F_48 (511) // FB divider = (F+1)/2 -#define APP_PLL_CTL_R_48 (4) // Ref divider = (R+1) - -#define APP_PLL_CTL_48 ((APP_PLL_CTL_BYPASS << 29) | (APP_PLL_CTL_INPUT_SEL << 28) | (APP_PLL_CTL_ENABLE << 27) |\ - (APP_PLL_CTL_OD_48 << 23) | (APP_PLL_CTL_F_48 << 8) | APP_PLL_CTL_R_48) - -// Fractional divide is M/N -#define APP_PLL_FRAC_EN_48 (0) // 0 = disabled -#define APP_PLL_FRAC_NPLUS1_CYCLES_48 (0) // M value is this reg value + 1. -#define APP_PLL_FRAC_TOTAL_CYCLES_48 (0) // N value is this reg value + 1. -#define APP_PLL_FRAC_48 ((APP_PLL_FRAC_EN_48 << 31) | (APP_PLL_FRAC_NPLUS1_CYCLES_48 << 8) | APP_PLL_FRAC_TOTAL_CYCLES_48) - -// 24MHz in, 22.5792MHz out (44.1kHz * 512), frac mode -// Found exact solution: IN 24000000.0, OUT 22579200.0, VCO 2257920000.0, RD 5, FD 470.400 (m = 2, n = 5), OD 5, FOD 10 -#define APP_PLL_CTL_OD_441 (4) // Output divider = (OD+1) -#define APP_PLL_CTL_F_441 (469) // FB divider = (F+1)/2 -#define APP_PLL_CTL_R_441 (4) // Ref divider = (R+1) - -#define APP_PLL_CTL_441 ((APP_PLL_CTL_BYPASS << 29) | (APP_PLL_CTL_INPUT_SEL << 28) | (APP_PLL_CTL_ENABLE << 27) |\ - (APP_PLL_CTL_OD_441 << 23) | (APP_PLL_CTL_F_441 << 8) | APP_PLL_CTL_R_441) - -#define APP_PLL_FRAC_EN_44 (1) // 1 = enabled -#define APP_PLL_FRAC_NPLUS1_CYCLES_44 (1) // M value is this reg value + 1. -#define APP_PLL_FRAC_TOTAL_CYCLES_44 (4) // N value is this reg value + 1.define APP_PLL_CTL_R_441 (4) // Ref divider = (R+1) -#define APP_PLL_FRAC_44 ((APP_PLL_FRAC_EN_44 << 31) | (APP_PLL_FRAC_NPLUS1_CYCLES_44 << 8) | APP_PLL_FRAC_TOTAL_CYCLES_44) - -#define APP_PLL_DIV_INPUT_SEL (1) // 0 = sysPLL, 1 = app_PLL -#define APP_PLL_DIV_DISABLE (0) // 1 = disabled (pin connected to X1D11), 0 = enabled divider output to pin. -#define APP_PLL_DIV_VALUE (4) // Divide by N+1 - remember there's a /2 also afterwards for 50/50 duty cycle. -#define APP_PLL_DIV ((APP_PLL_DIV_INPUT_SEL << 31) | (APP_PLL_DIV_DISABLE << 16) | APP_PLL_DIV_VALUE) - -/* TODO support more than two freqs..*/ -void AppPllEnable(int32_t clkFreq_hz) -{ - switch(clkFreq_hz) - { - case 44100*512: - - // Disable the PLL - write_node_config_reg(tile[1], XS1_SSWITCH_SS_APP_PLL_CTL_NUM, (APP_PLL_CTL_441 & 0xF7FFFFFF)); - // Enable the PLL to invoke a reset on the appPLL. - write_node_config_reg(tile[1], XS1_SSWITCH_SS_APP_PLL_CTL_NUM, APP_PLL_CTL_441); - // Must write the CTL register twice so that the F and R divider values are captured using a running clock. - write_node_config_reg(tile[1], XS1_SSWITCH_SS_APP_PLL_CTL_NUM, APP_PLL_CTL_441); - // Now disable and re-enable the PLL so we get the full 5us reset time with the correct F and R values. - write_node_config_reg(tile[1], XS1_SSWITCH_SS_APP_PLL_CTL_NUM, (APP_PLL_CTL_441 & 0xF7FFFFFF)); - write_node_config_reg(tile[1], XS1_SSWITCH_SS_APP_PLL_CTL_NUM, APP_PLL_CTL_441); - - // Set the fractional divider if used - write_node_config_reg(tile[0], XS1_SSWITCH_SS_APP_PLL_FRAC_N_DIVIDER_NUM, APP_PLL_FRAC_44); - - break; - - case 48000*512: - - // Disable the PLL - write_node_config_reg(tile[1], XS1_SSWITCH_SS_APP_PLL_CTL_NUM, (APP_PLL_CTL_48 & 0xF7FFFFFF)); - // Enable the PLL to invoke a reset on the appPLL. - write_node_config_reg(tile[1], XS1_SSWITCH_SS_APP_PLL_CTL_NUM, APP_PLL_CTL_48); - // Must write the CTL register twice so that the F and R divider values are captured using a running clock. - write_node_config_reg(tile[1], XS1_SSWITCH_SS_APP_PLL_CTL_NUM, APP_PLL_CTL_48); - // Now disable and re-enable the PLL so we get the full 5us reset time with the correct F and R values. - write_node_config_reg(tile[1], XS1_SSWITCH_SS_APP_PLL_CTL_NUM, (APP_PLL_CTL_48 & 0xF7FFFFFF)); - write_node_config_reg(tile[1], XS1_SSWITCH_SS_APP_PLL_CTL_NUM, APP_PLL_CTL_48); - - // Set the fractional divider if used - write_node_config_reg(tile[0], XS1_SSWITCH_SS_APP_PLL_FRAC_N_DIVIDER_NUM, APP_PLL_FRAC_48); - - break; - - default: - assert(0); - break; - } - - // Wait for PLL output frequency to stabilise due to fractional divider enable - delay_microseconds(100); - - // Turn on the clock output - write_node_config_reg(tile[0], XS1_SSWITCH_SS_APP_CLK_DIVIDER_NUM, APP_PLL_DIV); -} - -void AppPllEnable_SampleRate(int32_t sampleRate_hz) -{ - assert(sampleRate_hz >= 22050); - - if(sampleRate_hz % 22050 == 0) - { - AppPllEnable(44100*512); - } - else - { - AppPllEnable(48000*512); - } -} -