diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index 383e5540..27435050 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -512,6 +512,7 @@ fp_40_24_t sample_rate_set(const fp_40_24_t sample_rate, const bool program) sgpio_cpld_stream_disable(&sgpio_config); } +#ifndef PRALINE /* Integer mode can be enabled if p1 is even and p2 is zero. */ if (p1 & 0x1 || p2) { si5351c_set_int_mode(&clock_gen, 0, 0); @@ -519,7 +520,6 @@ fp_40_24_t sample_rate_set(const fp_40_24_t sample_rate, const bool program) si5351c_set_int_mode(&clock_gen, 0, 1); } -#ifndef PRALINE if (detected_platform() == BOARD_ID_HACKRF1_R9) { /* * On HackRF One r9 all sample clocks are externally derived @@ -541,8 +541,21 @@ fp_40_24_t sample_rate_set(const fp_40_24_t sample_rate, const bool program) si5351c_configure_multisynth(&clock_gen, 2, 0, 0, 0, 0); //p1 doesn't matter } #else - /* MS0/CLK0 is the source for the MAX5864/FPGA (AFE_CLK). */ + /* MS0/CLK0 is the source for the MAX5864 (AFE_CLK). */ si5351c_configure_multisynth(&clock_gen, 0, p1, p2, p3, 1); + + /* MS1/CLK1 is the source for the FPGA (FPGA_CLK and SCT_CLK). */ + si5351c_configure_multisynth(&clock_gen, 1, p1, p2, p3, 1); + + /* Delay FPGA_CLK relative to AFE_CLK. */ + uint8_t phase_offset = 0; + if (p1 < 2100) { + phase_offset = (p1 >> 4) - 6; + } + si5351c_set_phase(&clock_gen, 1, phase_offset); + + /* Reset PLL to synchronize output clock phase. */ + si5351c_reset_pll(&clock_gen); #endif if (streaming) { diff --git a/firmware/common/radio.c b/firmware/common/radio.c index bae631f7..40519720 100644 --- a/firmware/common/radio.c +++ b/firmware/common/radio.c @@ -188,6 +188,7 @@ static bool radio_update_sample_rate(radio_t* const radio, uint64_t* bank) switch (opmode) { case TRANSCEIVER_MODE_TX: case TRANSCEIVER_MODE_SS: + n = compute_resample_log(rate / FP_ONE_HZ, requested_n); if (n != radio->config[RADIO_BANK_APPLIED][RADIO_RESAMPLE_TX]) { #ifdef PRALINE fpga_set_tx_interpolation_ratio(&fpga, n); @@ -196,10 +197,6 @@ static bool radio_update_sample_rate(radio_t* const radio, uint64_t* bank) } break; default: - /* - * Resampling is enabled only in RX mode to work around a - * spectrum inversion bug with TX interpolation. - */ n = compute_resample_log(rate / FP_ONE_HZ, requested_n); if (n != radio->config[RADIO_BANK_APPLIED][RADIO_RESAMPLE_RX]) { #ifdef PRALINE diff --git a/firmware/common/si5351c.c b/firmware/common/si5351c.c index d9d9ef37..37176529 100644 --- a/firmware/common/si5351c.c +++ b/firmware/common/si5351c.c @@ -269,6 +269,9 @@ void si5351c_configure_clock_control( data[1] = SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(pll) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_4MA); + data[2] = SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(pll) | + SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | + SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA); data[3] = clkout_ctrl; data[5] = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | @@ -427,3 +430,21 @@ void si5351c_init(si5351c_driver_t* const drv) } (void) drv; } + +/* + * Set initial phase offset of output multisynth. AN619 associates this setting + * with outputs, but it seems to really be a multisynth setting. + * + * After changing this setting, you must call si5351c_reset_pll() to + * synchronize outputs with the new phase offset. + */ +void si5351c_set_phase( + si5351c_driver_t* const drv, + const uint8_t ms_number, + const uint8_t offset) +{ + const uint8_t address = 165 + ms_number; + if (ms_number < 8) { + si5351c_write_single(drv, address, offset & 0x7f); + } +} diff --git a/firmware/common/si5351c.h b/firmware/common/si5351c.h index 4c91bfba..6b49b8a8 100644 --- a/firmware/common/si5351c.h +++ b/firmware/common/si5351c.h @@ -104,6 +104,10 @@ void si5351c_write( const size_t data_count); void si5351c_clkout_enable(si5351c_driver_t* const drv, uint8_t enable); void si5351c_init(si5351c_driver_t* const drv); +void si5351c_set_phase( + si5351c_driver_t* const drv, + const uint8_t ms_number, + const uint8_t offset); #ifdef __cplusplus }