Skip to content

Commit 1e9991e

Browse files
authored
Merge pull request #1718 from greatscottgadgets/fix-pll-reset
Reset only sample clock outputs when changing rate
2 parents d1b3739 + 1c29079 commit 1e9991e

3 files changed

Lines changed: 69 additions & 26 deletions

File tree

firmware/common/hackrf_core.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ fp_40_24_t sample_rate_set(const fp_40_24_t sample_rate, const bool program)
325325
}
326326

327327
/* Reset PLL to synchronize output clock phase. */
328-
si5351c_reset_pll(&clock_gen);
328+
si5351c_reset_pll(&clock_gen, SI5351C_PLL_A);
329329
#endif
330330

331331
if (streaming) {
@@ -622,7 +622,7 @@ void clock_gen_init(void)
622622
si5351c_configure_clock_control(&clock_gen);
623623
si5351c_set_clock_source(&clock_gen, PLL_SOURCE_XTAL);
624624
// soft reset
625-
si5351c_reset_pll(&clock_gen);
625+
si5351c_reset_pll(&clock_gen, SI5351C_PLL_BOTH);
626626
si5351c_enable_clock_outputs(&clock_gen);
627627
}
628628

firmware/common/si5351c.c

Lines changed: 58 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
static enum pll_sources active_clock_source = PLL_SOURCE_UNINITIALIZED;
4242
/* External clock output default is deactivated as it creates noise */
4343
static bool clkout_enabled = false;
44+
static uint8_t outputs_disabled = 0xff;
4445

4546
/* write to single register */
4647
void si5351c_write_single(si5351c_driver_t* const drv, uint8_t reg, uint8_t val)
@@ -73,7 +74,30 @@ void si5351c_write(
7374
/* Disable all CLKx outputs. */
7475
void si5351c_disable_all_outputs(si5351c_driver_t* const drv)
7576
{
76-
uint8_t data[] = {3, 0xFF};
77+
outputs_disabled = 0xff;
78+
uint8_t data[] = {3, outputs_disabled};
79+
si5351c_write(drv, data, sizeof(data));
80+
}
81+
82+
/* Disable all CLKx outputs using selected PLL. */
83+
void si5351c_disable_pll_outputs(si5351c_driver_t* const drv, si5351c_pll_t pll)
84+
{
85+
/*
86+
* Bitmask defines outputs using PLL B. Other outputs are assumed to
87+
* use PLL A.
88+
*/
89+
uint8_t pllb_outputs = 0x00;
90+
if (detected_platform() == BOARD_ID_PRALINE) {
91+
pllb_outputs = 0x30;
92+
}
93+
94+
if (pll & SI5351C_PLL_A) {
95+
outputs_disabled |= ~pllb_outputs;
96+
}
97+
if (pll & SI5351C_PLL_B) {
98+
outputs_disabled |= pllb_outputs;
99+
}
100+
uint8_t data[] = {3, outputs_disabled};
77101
si5351c_write(drv, data, sizeof(data));
78102
}
79103

@@ -156,11 +180,19 @@ void si5351c_configure_pll_multisynth(
156180
si5351c_write(drv, data, sizeof(data));
157181
}
158182

159-
void si5351c_reset_pll(si5351c_driver_t* const drv)
183+
void si5351c_reset_pll(si5351c_driver_t* const drv, si5351c_pll_t pll)
160184
{
161-
si5351c_disable_all_outputs(drv);
162-
/* reset PLLA and PLLB */
163-
uint8_t data[] = {177, 0xA0};
185+
uint8_t value = 0;
186+
187+
if (pll & SI5351C_PLL_A) {
188+
value |= 0x20;
189+
}
190+
if (pll & SI5351C_PLL_B) {
191+
value |= 0x80;
192+
}
193+
194+
si5351c_disable_pll_outputs(drv, pll);
195+
uint8_t data[] = {177, value};
164196
si5351c_write(drv, data, sizeof(data));
165197
delay_us_at_mhz(2000, 204);
166198
si5351c_enable_clock_outputs(drv);
@@ -202,11 +234,10 @@ void si5351c_configure_multisynth(
202234

203235
void si5351c_configure_clock_control(si5351c_driver_t* const drv)
204236
{
205-
const uint8_t pll = SI5351C_CLK_PLL_SRC_A;
206237
uint8_t clkout_ctrl;
207238

208239
if (clkout_enabled) {
209-
clkout_ctrl = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) |
240+
clkout_ctrl = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) |
210241
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) |
211242
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_8MA);
212243
} else {
@@ -217,20 +248,20 @@ void si5351c_configure_clock_control(si5351c_driver_t* const drv)
217248
/* External clock output is kept in current state */
218249
uint8_t data[] = {
219250
16,
220-
SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(pll) |
251+
SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) |
221252
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) |
222253
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_8MA),
223-
SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) |
254+
SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) |
224255
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_0_4) |
225256
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA) | SI5351C_CLK_INV,
226-
SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) |
257+
SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) |
227258
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_0_4) |
228259
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA),
229260
clkout_ctrl,
230-
SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) |
261+
SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) |
231262
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) |
232263
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_6MA) | SI5351C_CLK_INV,
233-
SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) |
264+
SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) |
234265
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) |
235266
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_4MA),
236267
SI5351C_CLK_POWERDOWN |
@@ -239,10 +270,10 @@ void si5351c_configure_clock_control(si5351c_driver_t* const drv)
239270
SI5351C_CLK_INT_MODE /* not connected, but: PLL B int mode */
240271
};
241272
if (detected_platform() == BOARD_ID_HACKRF1_R9) {
242-
data[1] = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC_A |
273+
data[1] = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) |
243274
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) |
244275
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_6MA);
245-
data[2] = SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC_A |
276+
data[2] = SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) |
246277
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) |
247278
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_4MA);
248279
data[3] = clkout_ctrl;
@@ -252,20 +283,27 @@ void si5351c_configure_clock_control(si5351c_driver_t* const drv)
252283
}
253284
#ifdef PRALINE
254285
/* CLK0: AFE_CLK */
255-
data[1] = SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(pll) |
286+
data[1] = SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) |
256287
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) |
257288
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_4MA);
258289
/* CLK1: SCT_CLK and FPGA_CLK */
259-
data[2] = SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(pll) |
290+
data[2] = SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) |
260291
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) |
261292
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA);
293+
/* CLK3: CLKOUT */
294+
clkout_ctrl = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_B) |
295+
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) |
296+
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_8MA);
262297
/* CLK4: XCVR_CLK */
263-
data[5] = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) |
298+
data[5] = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_B) |
264299
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) |
265300
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_4MA) | SI5351C_CLK_INV;
301+
data[6] = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_B) |
302+
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) |
303+
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_4MA);
266304
if ((detected_revision() & ~BOARD_REV_GSG) < BOARD_REV_PRALINE_R1_1) {
267305
/* CLK2: FPGA_CLK (not shared with SCT_CLK on older boards) */
268-
data[3] = SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(pll) |
306+
data[3] = SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) |
269307
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) |
270308
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA);
271309
} else {
@@ -317,6 +355,7 @@ void si5351c_enable_clock_outputs(si5351c_driver_t* const drv)
317355
SI5351C_CLK_DISABLE(clkout);
318356
uint8_t data[] = {SI5351C_REG_OUTPUT_EN, value};
319357
si5351c_write(drv, data, sizeof(data));
358+
outputs_disabled = value;
320359

321360
#if defined(HACKRF_ONE)
322361
if (detected_platform() == BOARD_ID_HACKRF1_R9) {
@@ -375,7 +414,7 @@ void si5351c_set_clock_source(si5351c_driver_t* const drv, const enum pll_source
375414
}
376415
si5351c_configure_pll_multisynth(drv, source);
377416
active_clock_source = source;
378-
si5351c_reset_pll(drv);
417+
si5351c_reset_pll(drv, SI5351C_PLL_BOTH);
379418
}
380419

381420
bool si5351c_clkin_signal_valid(si5351c_driver_t* const drv)

firmware/common/si5351c.h

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,6 @@ extern "C" {
3838
#define SI5351C_CLK_INT_MODE (1 << 6)
3939
#define SI5351C_CLK_FRAC_MODE (0 << 6)
4040

41-
#define SI5351C_CLK_PLL_SRC(x) (x << 5)
42-
#define SI5351C_CLK_PLL_SRC_A 0
43-
#define SI5351C_CLK_PLL_SRC_B 1
44-
4541
#define SI5351C_CLK_INV (1 << 4)
4642

4743
#define SI5351C_CLK_SRC(x) (x << 2)
@@ -59,6 +55,14 @@ extern "C" {
5955
#define SI5351C_LOS (1 << 4)
6056
#define SI5351C_REVID 0x03
6157

58+
typedef enum {
59+
SI5351C_PLL_A = 1,
60+
SI5351C_PLL_B = 2,
61+
SI5351C_PLL_BOTH = 3,
62+
} si5351c_pll_t;
63+
64+
#define SI5351C_CLK_PLL_SRC(x) ((x & SI5351C_PLL_B) << 4)
65+
6266
enum pll_sources {
6367
PLL_SOURCE_UNINITIALIZED = -1,
6468
PLL_SOURCE_XTAL = 0,
@@ -81,7 +85,7 @@ void si5351c_configure_pll_sources(
8185
void si5351c_configure_pll_multisynth(
8286
si5351c_driver_t* const drv,
8387
const enum pll_sources source);
84-
void si5351c_reset_pll(si5351c_driver_t* const drv);
88+
void si5351c_reset_pll(si5351c_driver_t* const drv, si5351c_pll_t pll);
8589
void si5351c_configure_multisynth(
8690
si5351c_driver_t* const drv,
8791
const uint_fast8_t ms_number,

0 commit comments

Comments
 (0)