Merge pull request #1747 from martinling/si5351c-defs
Si5351C refactoring
This commit is contained in:
commit
c77e7e7358
4 changed files with 871 additions and 254 deletions
|
|
@ -111,9 +111,9 @@ void clock_gen_init(void)
|
|||
sample_rate_set(SR_FP_MHZ(10), true);
|
||||
|
||||
si5351c_configure_clock_control(&si5351c);
|
||||
si5351c_set_clock_source(&si5351c, PLL_SOURCE_XTAL);
|
||||
si5351c_change_input(&si5351c, SI5351C_INPUT_XTAL);
|
||||
// soft reset
|
||||
si5351c_reset_pll(&si5351c, SI5351C_PLL_BOTH);
|
||||
si5351c_reset_plls(&si5351c, SI5351C_PLL_MASK_BOTH);
|
||||
si5351c_enable_clock_outputs(&si5351c);
|
||||
}
|
||||
|
||||
|
|
@ -159,9 +159,10 @@ clock_source_t activate_best_clock_source(void)
|
|||
/* No external or PortaPack clock was found. Use HackRF Si5351C crystal. */
|
||||
}
|
||||
|
||||
si5351c_set_clock_source(
|
||||
&si5351c,
|
||||
(source == CLOCK_SOURCE_HACKRF) ? PLL_SOURCE_XTAL : PLL_SOURCE_CLKIN);
|
||||
si5351c_input_t input = (source == CLOCK_SOURCE_HACKRF) ? SI5351C_INPUT_XTAL :
|
||||
SI5351C_INPUT_CLKIN;
|
||||
si5351c_change_input(&si5351c, input);
|
||||
|
||||
hackrf_ui()->set_clock_source(source);
|
||||
|
||||
return source;
|
||||
|
|
@ -411,7 +412,7 @@ fp_28_36_t sample_rate_set(const fp_28_36_t sample_rate, const bool program)
|
|||
}
|
||||
|
||||
/* Reset PLL to synchronize output clock phase. */
|
||||
si5351c_reset_pll(&si5351c, SI5351C_PLL_A);
|
||||
si5351c_reset_plls(&si5351c, SI5351C_PLL_MASK_A);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2022 Great Scott Gadgets <info@greatscottgadgets.com>
|
||||
* Copyright 2012-2026 Great Scott Gadgets <info@greatscottgadgets.com>
|
||||
* Copyright 2012 Jared Boone <jared@sharebrained.com>
|
||||
*
|
||||
* This file is part of HackRF.
|
||||
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "clock_io.h"
|
||||
#include "delay.h"
|
||||
|
|
@ -36,6 +37,8 @@
|
|||
#include "platform_scu.h"
|
||||
#endif
|
||||
|
||||
#include "si5351c_regs.def"
|
||||
|
||||
/* Driver instance. */
|
||||
// const i2c_lpc_config_t i2c_config_si5351c_slow_clock = {
|
||||
// .duty_cycle_count = 15,
|
||||
|
|
@ -48,16 +51,20 @@ si5351c_driver_t si5351c = {
|
|||
.i2c_address = 0x60,
|
||||
};
|
||||
|
||||
static enum pll_sources active_clock_source = PLL_SOURCE_UNINITIALIZED;
|
||||
static bool input_initialized = false;
|
||||
static si5351c_input_t active_input;
|
||||
/* External clock output default is deactivated as it creates noise */
|
||||
static bool clkout_enabled = false;
|
||||
static uint8_t outputs_disabled = 0xff;
|
||||
|
||||
/* write to single register */
|
||||
void si5351c_write_single(si5351c_driver_t* const drv, uint8_t reg, uint8_t val)
|
||||
{
|
||||
const uint8_t data_tx[] = {reg, val};
|
||||
si5351c_write(drv, data_tx, 2);
|
||||
i2c_bus_transfer(drv->bus, drv->i2c_address, data_tx, 2, NULL, 0);
|
||||
if (reg < SI5351C_CACHED_REGS) {
|
||||
drv->regs[reg] = val;
|
||||
si5351c_reg_set_clean(drv, reg);
|
||||
}
|
||||
}
|
||||
|
||||
/* read single register */
|
||||
|
|
@ -66,72 +73,100 @@ uint8_t si5351c_read_single(si5351c_driver_t* const drv, uint8_t reg)
|
|||
const uint8_t data_tx[] = {reg};
|
||||
uint8_t data_rx[] = {0x00};
|
||||
i2c_bus_transfer(drv->bus, drv->i2c_address, data_tx, 1, data_rx, 1);
|
||||
return data_rx[0];
|
||||
uint8_t val = data_rx[0];
|
||||
if (reg < SI5351C_CACHED_REGS) {
|
||||
drv->regs[reg] = val;
|
||||
si5351c_reg_set_clean(drv, reg);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write to one or more contiguous registers. data[0] should be the first
|
||||
* register number, one or more values follow.
|
||||
*/
|
||||
void si5351c_write(
|
||||
si5351c_driver_t* const drv,
|
||||
const uint8_t* const data,
|
||||
const size_t data_count)
|
||||
/* Commit changes to register values. */
|
||||
void si5351c_regs_commit(si5351c_driver_t* drv)
|
||||
{
|
||||
i2c_bus_transfer(drv->bus, drv->i2c_address, data, data_count, NULL, 0);
|
||||
for (int start = 0; start < SI5351C_CACHED_REGS; start++) {
|
||||
if (si5351c_reg_is_dirty(drv, start)) {
|
||||
if (start == SI5351C_CACHED_REGS - 1) {
|
||||
si5351c_write_single(drv, start, drv->regs[start]);
|
||||
} else {
|
||||
int end;
|
||||
for (end = start + 1; end < 256; end++) {
|
||||
if (!si5351c_reg_is_dirty(drv, end))
|
||||
break;
|
||||
}
|
||||
size_t len = 1 + (end - start);
|
||||
uint8_t data_tx[len];
|
||||
data_tx[0] = start;
|
||||
for (int i = 0; i < (end - start); i++) {
|
||||
data_tx[1 + i] = drv->regs[start + i];
|
||||
}
|
||||
i2c_bus_transfer(
|
||||
drv->bus,
|
||||
drv->i2c_address,
|
||||
data_tx,
|
||||
len,
|
||||
NULL,
|
||||
0);
|
||||
for (int i = start; i < end; i++) {
|
||||
si5351c_reg_set_clean(drv, i);
|
||||
}
|
||||
start = end;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset bits are self-clearing. */
|
||||
drv->regs[177] = 0;
|
||||
}
|
||||
|
||||
/* Disable all CLKx outputs. */
|
||||
void si5351c_disable_all_outputs(si5351c_driver_t* const drv)
|
||||
{
|
||||
outputs_disabled = 0xff;
|
||||
uint8_t data[] = {3, outputs_disabled};
|
||||
si5351c_write(drv, data, sizeof(data));
|
||||
set_all_CLK_OEB(drv, SI5351C_OUTPUT_DISABLE);
|
||||
si5351c_regs_commit(drv);
|
||||
}
|
||||
|
||||
/* Disable all CLKx outputs using selected PLL. */
|
||||
void si5351c_disable_pll_outputs(si5351c_driver_t* const drv, si5351c_pll_t pll)
|
||||
void si5351c_disable_pll_outputs(si5351c_driver_t* const drv, si5351c_pll_mask_t mask)
|
||||
{
|
||||
/*
|
||||
* Bitmask defines outputs using PLL B. Other outputs are assumed to
|
||||
* use PLL A.
|
||||
*/
|
||||
uint8_t pllb_outputs = 0x00;
|
||||
if (detected_platform() == BOARD_ID_PRALINE) {
|
||||
pllb_outputs = 0x30;
|
||||
/* For each CLKx output, check if it is using the specified PLL. */
|
||||
for (int op = 0; op < 8; op++) {
|
||||
int ms;
|
||||
/* First check which multisynth is used by this output. */
|
||||
switch (get_CLK_SRC(drv, op)) {
|
||||
case SI5351C_SRC_MULTISYNTH_SELF:
|
||||
ms = op;
|
||||
break;
|
||||
case SI5351C_SRC_MULTISYNTH_0_4:
|
||||
ms = (op < 4) ? 0 : 4;
|
||||
break;
|
||||
default:
|
||||
/* This output is not using any PLL */
|
||||
continue;
|
||||
}
|
||||
/* Now check which PLL is used by that multisynth. */
|
||||
if (mask & (1 << get_MS_SRC(drv, ms))) {
|
||||
/* This output depends on the specified PLL; disable it. */
|
||||
set_CLK_OEB(drv, op, SI5351C_OUTPUT_DISABLE);
|
||||
}
|
||||
}
|
||||
|
||||
if (pll & SI5351C_PLL_A) {
|
||||
outputs_disabled |= ~pllb_outputs;
|
||||
}
|
||||
if (pll & SI5351C_PLL_B) {
|
||||
outputs_disabled |= pllb_outputs;
|
||||
}
|
||||
uint8_t data[] = {3, outputs_disabled};
|
||||
si5351c_write(drv, data, sizeof(data));
|
||||
si5351c_regs_commit(drv);
|
||||
}
|
||||
|
||||
/* Turn off OEB pin control for all CLKx */
|
||||
void si5351c_disable_oeb_pin_control(si5351c_driver_t* const drv)
|
||||
{
|
||||
uint8_t data[] = {9, 0xFF};
|
||||
si5351c_write(drv, data, sizeof(data));
|
||||
set_all_OEB_MASK(drv, true);
|
||||
si5351c_regs_commit(drv);
|
||||
}
|
||||
|
||||
/* Power down all CLKx */
|
||||
void si5351c_power_down_all_clocks(si5351c_driver_t* const drv)
|
||||
{
|
||||
uint8_t data[] = {
|
||||
16,
|
||||
SI5351C_CLK_POWERDOWN,
|
||||
SI5351C_CLK_POWERDOWN,
|
||||
SI5351C_CLK_POWERDOWN,
|
||||
SI5351C_CLK_POWERDOWN,
|
||||
SI5351C_CLK_POWERDOWN,
|
||||
SI5351C_CLK_POWERDOWN,
|
||||
SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE,
|
||||
SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE};
|
||||
si5351c_write(drv, data, sizeof(data));
|
||||
set_all_CLK_PDN(drv, true);
|
||||
set_FBA_INT(drv, true);
|
||||
set_FBB_INT(drv, true);
|
||||
si5351c_regs_commit(drv);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -141,8 +176,8 @@ void si5351c_power_down_all_clocks(si5351c_driver_t* const drv)
|
|||
*/
|
||||
void si5351c_set_crystal_configuration(si5351c_driver_t* const drv)
|
||||
{
|
||||
uint8_t data[] = {183, 0x80};
|
||||
si5351c_write(drv, data, sizeof(data));
|
||||
set_XTAL_CL(drv, SI5351C_XTAL_8PF);
|
||||
si5351c_regs_commit(drv);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -151,8 +186,10 @@ void si5351c_set_crystal_configuration(si5351c_driver_t* const drv)
|
|||
*/
|
||||
void si5351c_enable_xo_and_ms_fanout(si5351c_driver_t* const drv)
|
||||
{
|
||||
uint8_t data[] = {187, 0xD0};
|
||||
si5351c_write(drv, data, sizeof(data));
|
||||
set_CLKIN_FANOUT_EN(drv, true);
|
||||
set_XO_FANOUT_EN(drv, true);
|
||||
set_MS_FANOUT_EN(drv, true);
|
||||
si5351c_regs_commit(drv);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -160,50 +197,39 @@ void si5351c_enable_xo_and_ms_fanout(si5351c_driver_t* const drv)
|
|||
* CLKIN_DIV=0 (Divide by 1)
|
||||
* Set both PLLA_SRC and PLLB_SRC
|
||||
*/
|
||||
void si5351c_configure_pll_sources(
|
||||
si5351c_driver_t* const drv,
|
||||
const enum pll_sources source)
|
||||
void si5351c_configure_inputs(si5351c_driver_t* const drv, const si5351c_input_t input)
|
||||
{
|
||||
uint8_t data[] = {15, 0x00};
|
||||
|
||||
if (source == PLL_SOURCE_CLKIN) {
|
||||
data[1] = 0x0c;
|
||||
}
|
||||
si5351c_write(drv, data, sizeof(data));
|
||||
set_CLKIN_DIV(drv, SI5351C_DIV_1);
|
||||
set_PLLA_SRC(drv, input);
|
||||
set_PLLB_SRC(drv, input);
|
||||
si5351c_regs_commit(drv);
|
||||
}
|
||||
|
||||
/* MultiSynth NA (PLLA) and NB (PLLB) */
|
||||
void si5351c_configure_pll_multisynth(
|
||||
si5351c_driver_t* const drv,
|
||||
const enum pll_sources source)
|
||||
const si5351c_input_t input)
|
||||
{
|
||||
/* XTAL: 25 MHz * (0x0e00 + 512) / 128 = 800 MHz, integer mode */
|
||||
uint8_t data[] = {26, 0x00, 0x01, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00};
|
||||
if (source == PLL_SOURCE_CLKIN) {
|
||||
/* CLKIN: 10 MHz * (0x2600 + 512) / 128 = 800 MHz, integer mode */
|
||||
data[4] = 0x26;
|
||||
for (si5351c_pll_t pll = SI5351C_PLL_A; pll <= SI5351C_PLL_B; pll++) {
|
||||
if (input == SI5351C_INPUT_CLKIN) {
|
||||
/* CLKIN: 10 MHz * (0x2600 + 512) / 128 = 800 MHz, integer mode */
|
||||
set_MSN_P1(drv, pll, 0x2600);
|
||||
} else {
|
||||
/* XTAL: 25 MHz * (0x0e00 + 512) / 128 = 800 MHz, integer mode */
|
||||
set_MSN_P1(drv, pll, 0x0E00);
|
||||
}
|
||||
set_MSN_P2(drv, pll, 0);
|
||||
set_MSN_P3(drv, pll, 1);
|
||||
}
|
||||
si5351c_write(drv, data, sizeof(data));
|
||||
|
||||
/* Apply same configuration to PLL B. */
|
||||
data[0] = 34;
|
||||
si5351c_write(drv, data, sizeof(data));
|
||||
si5351c_regs_commit(drv);
|
||||
}
|
||||
|
||||
void si5351c_reset_pll(si5351c_driver_t* const drv, si5351c_pll_t pll)
|
||||
void si5351c_reset_plls(si5351c_driver_t* const drv, si5351c_pll_mask_t mask)
|
||||
{
|
||||
uint8_t value = 0;
|
||||
|
||||
if (pll & SI5351C_PLL_A) {
|
||||
value |= 0x20;
|
||||
}
|
||||
if (pll & SI5351C_PLL_B) {
|
||||
value |= 0x80;
|
||||
}
|
||||
|
||||
si5351c_disable_pll_outputs(drv, pll);
|
||||
uint8_t data[] = {177, value};
|
||||
si5351c_write(drv, data, sizeof(data));
|
||||
si5351c_disable_pll_outputs(drv, mask);
|
||||
set_PLLA_RST(drv, (mask & SI5351C_PLL_MASK_A) ? true : false);
|
||||
set_PLLB_RST(drv, (mask & SI5351C_PLL_MASK_B) ? true : false);
|
||||
si5351c_regs_commit(drv);
|
||||
delay_us_at_mhz(2000, 204);
|
||||
si5351c_enable_clock_outputs(drv);
|
||||
}
|
||||
|
|
@ -228,110 +254,166 @@ void si5351c_configure_multisynth(
|
|||
* ...
|
||||
* 7 means divide by 128
|
||||
*/
|
||||
const uint_fast8_t register_number = 42 + (ms_number * 8);
|
||||
uint8_t data[] = {
|
||||
register_number,
|
||||
(p3 >> 8) & 0xFF,
|
||||
(p3 >> 0) & 0xFF,
|
||||
(r_div << 4) | (0 << 2) | ((p1 >> 16) & 0x3),
|
||||
(p1 >> 8) & 0xFF,
|
||||
(p1 >> 0) & 0xFF,
|
||||
(((p3 >> 16) & 0xF) << 4) | (((p2 >> 16) & 0xF) << 0),
|
||||
(p2 >> 8) & 0xFF,
|
||||
(p2 >> 0) & 0xFF};
|
||||
si5351c_write(drv, data, sizeof(data));
|
||||
set_MS_P1(drv, ms_number, p1);
|
||||
set_MS_P2(drv, ms_number, p2);
|
||||
set_MS_P3(drv, ms_number, p3);
|
||||
set_R_DIV(drv, ms_number, r_div);
|
||||
si5351c_regs_commit(drv);
|
||||
}
|
||||
|
||||
void si5351c_configure_clock_control(si5351c_driver_t* const drv)
|
||||
{
|
||||
uint8_t clkout_ctrl;
|
||||
si5351c_clk_ctrl_t clkout = {
|
||||
.mode = SI5351C_MODE_INT,
|
||||
.pll = SI5351C_PLL_A,
|
||||
.source = SI5351C_SRC_MULTISYNTH_SELF,
|
||||
.drive = SI5351C_DRIVE_8MA,
|
||||
};
|
||||
|
||||
if (clkout_enabled) {
|
||||
clkout_ctrl = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) |
|
||||
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) |
|
||||
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_8MA);
|
||||
} else {
|
||||
clkout_ctrl = SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE;
|
||||
si5351c_clk_ctrl_t powered_down = {
|
||||
.power_down = true,
|
||||
.mode = SI5351C_MODE_INT,
|
||||
};
|
||||
|
||||
if (!clkout_enabled) {
|
||||
clkout = powered_down;
|
||||
}
|
||||
|
||||
si5351c_clk_ctrl_t clk[8];
|
||||
|
||||
/* Clock to CPU is deactivated as it is not used and creates noise */
|
||||
/* External clock output is kept in current state */
|
||||
uint8_t data[] = {
|
||||
16,
|
||||
SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) |
|
||||
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) |
|
||||
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_8MA),
|
||||
SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) |
|
||||
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_0_4) |
|
||||
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA) | SI5351C_CLK_INV,
|
||||
SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) |
|
||||
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_0_4) |
|
||||
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA),
|
||||
clkout_ctrl,
|
||||
SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) |
|
||||
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) |
|
||||
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_6MA) | SI5351C_CLK_INV,
|
||||
SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) |
|
||||
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) |
|
||||
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_4MA),
|
||||
SI5351C_CLK_POWERDOWN |
|
||||
SI5351C_CLK_INT_MODE, /* not connected, but: PLL A int mode */
|
||||
SI5351C_CLK_POWERDOWN |
|
||||
SI5351C_CLK_INT_MODE /* not connected, but: PLL B int mode */
|
||||
|
||||
/* CLK0: MAX5864/CPLD */
|
||||
clk[0] = (si5351c_clk_ctrl_t){
|
||||
.mode = SI5351C_MODE_FRAC,
|
||||
.pll = SI5351C_PLL_A,
|
||||
.source = SI5351C_SRC_MULTISYNTH_SELF,
|
||||
.drive = SI5351C_DRIVE_8MA,
|
||||
};
|
||||
/* CLK1: CPLD */
|
||||
clk[1] = (si5351c_clk_ctrl_t){
|
||||
.mode = SI5351C_MODE_INT,
|
||||
.pll = SI5351C_PLL_A,
|
||||
.source = SI5351C_SRC_MULTISYNTH_0_4,
|
||||
.drive = SI5351C_DRIVE_2MA,
|
||||
.invert = true,
|
||||
};
|
||||
/* CLK2: SGPIO */
|
||||
clk[2] = (si5351c_clk_ctrl_t){
|
||||
.mode = SI5351C_MODE_INT,
|
||||
.pll = SI5351C_PLL_A,
|
||||
.source = SI5351C_SRC_MULTISYNTH_0_4,
|
||||
.drive = SI5351C_DRIVE_2MA,
|
||||
};
|
||||
/* CLK3: CLKOUT */
|
||||
clk[3] = clkout;
|
||||
/* CLK4: RFFC5072 (MAX2837 on rad1o) */
|
||||
clk[4] = (si5351c_clk_ctrl_t){
|
||||
.mode = SI5351C_MODE_INT,
|
||||
.pll = SI5351C_PLL_A,
|
||||
.source = SI5351C_SRC_MULTISYNTH_SELF,
|
||||
.drive = SI5351C_DRIVE_6MA,
|
||||
.invert = true,
|
||||
};
|
||||
/* CLK5: MAX2837 (MAX2871 on rad1o) */
|
||||
clk[5] = (si5351c_clk_ctrl_t){
|
||||
.mode = SI5351C_MODE_INT,
|
||||
.pll = SI5351C_PLL_A,
|
||||
.source = SI5351C_SRC_MULTISYNTH_SELF,
|
||||
.drive = SI5351C_DRIVE_4MA,
|
||||
};
|
||||
/* CLK6: none */
|
||||
clk[6] = powered_down;
|
||||
/* CLK7: LPC43xx */
|
||||
clk[7] = powered_down;
|
||||
|
||||
#ifdef IS_H1_R9
|
||||
if (IS_H1_R9) {
|
||||
data[1] = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) |
|
||||
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) |
|
||||
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_6MA);
|
||||
data[2] = SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) |
|
||||
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) |
|
||||
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_4MA);
|
||||
data[3] = clkout_ctrl;
|
||||
data[4] = SI5351C_CLK_POWERDOWN;
|
||||
data[5] = SI5351C_CLK_POWERDOWN;
|
||||
data[6] = SI5351C_CLK_POWERDOWN;
|
||||
/* CLK0: MAX5864/CPLD/SGPIO (sample clocks) */
|
||||
clk[0] = (si5351c_clk_ctrl_t){
|
||||
.mode = SI5351C_MODE_INT,
|
||||
.pll = SI5351C_PLL_A,
|
||||
.source = SI5351C_SRC_MULTISYNTH_SELF,
|
||||
.drive = SI5351C_DRIVE_6MA,
|
||||
};
|
||||
/* CLK1: RFFC5072/MAX2839 */
|
||||
clk[1] = (si5351c_clk_ctrl_t){
|
||||
.mode = SI5351C_MODE_FRAC,
|
||||
.pll = SI5351C_PLL_A,
|
||||
.source = SI5351C_SRC_MULTISYNTH_SELF,
|
||||
.drive = SI5351C_DRIVE_4MA,
|
||||
};
|
||||
/* CLK2: CLKOUT/LPC4320 */
|
||||
clk[2] = clkout;
|
||||
/* Other outputs not present on Si5351A */
|
||||
clk[3] = powered_down;
|
||||
clk[4] = powered_down;
|
||||
clk[5] = powered_down;
|
||||
clk[6] = powered_down;
|
||||
clk[7] = powered_down;
|
||||
}
|
||||
#endif
|
||||
#ifdef IS_PRALINE
|
||||
if (IS_PRALINE) {
|
||||
/* CLK0: AFE_CLK */
|
||||
data[1] = SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) |
|
||||
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) |
|
||||
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_4MA);
|
||||
clk[0] = (si5351c_clk_ctrl_t){
|
||||
.mode = SI5351C_MODE_FRAC,
|
||||
.pll = SI5351C_PLL_A,
|
||||
.source = SI5351C_SRC_MULTISYNTH_SELF,
|
||||
.drive = SI5351C_DRIVE_4MA,
|
||||
};
|
||||
/* CLK1: SCT_CLK and FPGA_CLK */
|
||||
data[2] = SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) |
|
||||
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) |
|
||||
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA);
|
||||
clk[1] = (si5351c_clk_ctrl_t){
|
||||
.mode = SI5351C_MODE_FRAC,
|
||||
.pll = SI5351C_PLL_A,
|
||||
.source = SI5351C_SRC_MULTISYNTH_SELF,
|
||||
.drive = SI5351C_DRIVE_2MA,
|
||||
};
|
||||
/* CLK3: CLKOUT */
|
||||
clkout_ctrl = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_B) |
|
||||
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) |
|
||||
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_8MA);
|
||||
clkout.pll = SI5351C_PLL_B;
|
||||
clk[3] = clkout;
|
||||
/* CLK4: XCVR_CLK */
|
||||
data[5] = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_B) |
|
||||
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) |
|
||||
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_4MA) | SI5351C_CLK_INV;
|
||||
data[6] = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_B) |
|
||||
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) |
|
||||
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_4MA);
|
||||
clk[4] = (si5351c_clk_ctrl_t){
|
||||
.mode = SI5351C_MODE_INT,
|
||||
.pll = SI5351C_PLL_B,
|
||||
.source = SI5351C_SRC_MULTISYNTH_SELF,
|
||||
.drive = SI5351C_DRIVE_4MA,
|
||||
.invert = true,
|
||||
};
|
||||
/* CLK5: MIX_CLK */
|
||||
clk[5] = (si5351c_clk_ctrl_t){
|
||||
.mode = SI5351C_MODE_INT,
|
||||
.pll = SI5351C_PLL_B,
|
||||
.source = SI5351C_SRC_MULTISYNTH_SELF,
|
||||
.drive = SI5351C_DRIVE_4MA,
|
||||
};
|
||||
if ((detected_revision() & ~BOARD_REV_GSG) < BOARD_REV_PRALINE_R1_1) {
|
||||
/* CLK2: FPGA_CLK (not shared with SCT_CLK on older boards) */
|
||||
data[3] = SI5351C_CLK_FRAC_MODE |
|
||||
SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) |
|
||||
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) |
|
||||
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA);
|
||||
clk[2] = (si5351c_clk_ctrl_t){
|
||||
.mode = SI5351C_MODE_FRAC,
|
||||
.pll = SI5351C_PLL_A,
|
||||
.source = SI5351C_SRC_MULTISYNTH_SELF,
|
||||
.drive = SI5351C_DRIVE_2MA,
|
||||
};
|
||||
} else {
|
||||
/* CLK2: MCU_CLK */
|
||||
data[3] = SI5351C_CLK_POWERDOWN;
|
||||
clk[2] = powered_down;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
si5351c_write(drv, data, sizeof(data));
|
||||
}
|
||||
|
||||
#define SI5351C_CLK_ENABLE(x) (0 << x)
|
||||
#define SI5351C_CLK_DISABLE(x) (1 << x)
|
||||
#define SI5351C_REG_OUTPUT_EN (3)
|
||||
for (int i = 0; i < 8; i++) {
|
||||
set_CLK_PDN(drv, i, clk[i].power_down);
|
||||
set_MS_INT(drv, i, clk[i].mode);
|
||||
set_MS_SRC(drv, i, clk[i].pll);
|
||||
set_CLK_SRC(drv, i, clk[i].source);
|
||||
set_CLK_IDRV(drv, i, clk[i].drive);
|
||||
set_CLK_INV(drv, i, clk[i].invert);
|
||||
}
|
||||
|
||||
si5351c_regs_commit(drv);
|
||||
}
|
||||
|
||||
void si5351c_enable_clock_outputs(si5351c_driver_t* const drv)
|
||||
{
|
||||
|
|
@ -341,46 +423,61 @@ void si5351c_enable_clock_outputs(si5351c_driver_t* const drv)
|
|||
/* 3: External clock output is deactivated by default */
|
||||
|
||||
uint8_t clkout = 3;
|
||||
uint8_t value = 0;
|
||||
|
||||
bool enable[8];
|
||||
|
||||
#ifdef IS_PRALINE
|
||||
if (IS_PRALINE) {
|
||||
value = SI5351C_CLK_ENABLE(0) | SI5351C_CLK_ENABLE(1) |
|
||||
SI5351C_CLK_ENABLE(4) | SI5351C_CLK_ENABLE(5) |
|
||||
SI5351C_CLK_DISABLE(6) | SI5351C_CLK_DISABLE(7);
|
||||
enable[0] = true;
|
||||
enable[1] = true;
|
||||
if ((detected_revision() & ~BOARD_REV_GSG) < BOARD_REV_PRALINE_R1_1) {
|
||||
/* CLK2: FPGA_CLK (not shared with SCT_CLK on older boards) */
|
||||
value |= SI5351C_CLK_ENABLE(2);
|
||||
enable[2] = true;
|
||||
} else {
|
||||
value |= SI5351C_CLK_DISABLE(2);
|
||||
enable[2] = false;
|
||||
}
|
||||
enable[3] = false;
|
||||
enable[4] = true;
|
||||
enable[5] = true;
|
||||
enable[6] = false;
|
||||
enable[7] = false;
|
||||
}
|
||||
#endif
|
||||
#ifdef IS_NOT_PRALINE
|
||||
if (IS_NOT_PRALINE) {
|
||||
value = SI5351C_CLK_ENABLE(0) | SI5351C_CLK_ENABLE(1) |
|
||||
SI5351C_CLK_ENABLE(2) | SI5351C_CLK_ENABLE(4) |
|
||||
SI5351C_CLK_ENABLE(5) | SI5351C_CLK_DISABLE(6) |
|
||||
SI5351C_CLK_DISABLE(7);
|
||||
enable[0] = true;
|
||||
enable[1] = true;
|
||||
enable[2] = true;
|
||||
enable[3] = false;
|
||||
enable[4] = true;
|
||||
enable[5] = true;
|
||||
enable[6] = false;
|
||||
enable[7] = false;
|
||||
|
||||
/* HackRF One r9 has only three clock generator outputs. */
|
||||
#ifdef IS_H1_R9
|
||||
if (IS_H1_R9) {
|
||||
clkout = 2;
|
||||
value = SI5351C_CLK_ENABLE(0) | SI5351C_CLK_ENABLE(1) |
|
||||
SI5351C_CLK_DISABLE(3) | SI5351C_CLK_DISABLE(4) |
|
||||
SI5351C_CLK_DISABLE(5) | SI5351C_CLK_DISABLE(6) |
|
||||
SI5351C_CLK_DISABLE(7);
|
||||
enable[0] = true;
|
||||
enable[1] = true;
|
||||
enable[3] = false;
|
||||
enable[4] = false;
|
||||
enable[5] = false;
|
||||
enable[6] = false;
|
||||
enable[7] = false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
enable[clkout] = clkout_enabled;
|
||||
|
||||
value |= (clkout_enabled) ? SI5351C_CLK_ENABLE(clkout) :
|
||||
SI5351C_CLK_DISABLE(clkout);
|
||||
uint8_t data[] = {SI5351C_REG_OUTPUT_EN, value};
|
||||
si5351c_write(drv, data, sizeof(data));
|
||||
outputs_disabled = value;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
set_CLK_OEB(
|
||||
drv,
|
||||
i,
|
||||
enable[i] ? SI5351C_OUTPUT_ENABLE : SI5351C_OUTPUT_DISABLE);
|
||||
}
|
||||
si5351c_regs_commit(drv);
|
||||
|
||||
#ifdef IS_H1_R9
|
||||
if (IS_H1_R9) {
|
||||
|
|
@ -399,25 +496,13 @@ void si5351c_set_int_mode(
|
|||
const uint_fast8_t ms_number,
|
||||
const uint_fast8_t on)
|
||||
{
|
||||
uint8_t data[] = {16, 0};
|
||||
|
||||
if (ms_number < 8) {
|
||||
data[0] = 16 + ms_number;
|
||||
data[1] = si5351c_read_single(drv, data[0]);
|
||||
|
||||
if (on) {
|
||||
data[1] |= SI5351C_CLK_INT_MODE;
|
||||
} else {
|
||||
data[1] &= ~(SI5351C_CLK_INT_MODE);
|
||||
}
|
||||
|
||||
si5351c_write(drv, data, 2);
|
||||
}
|
||||
set_MS_INT(drv, ms_number, on);
|
||||
si5351c_regs_commit(drv);
|
||||
}
|
||||
|
||||
void si5351c_set_clock_source(si5351c_driver_t* const drv, const enum pll_sources source)
|
||||
void si5351c_change_input(si5351c_driver_t* const drv, si5351c_input_t input)
|
||||
{
|
||||
if (source == active_clock_source) {
|
||||
if (input_initialized && input == active_input) {
|
||||
return;
|
||||
}
|
||||
si5351c_disable_all_outputs(drv);
|
||||
|
|
@ -427,8 +512,8 @@ void si5351c_set_clock_source(si5351c_driver_t* const drv, const enum pll_source
|
|||
* HackRF One r9 always uses PLL A on the XTAL input
|
||||
* but externally switches that input to CLKIN.
|
||||
*/
|
||||
si5351c_configure_pll_sources(drv, PLL_SOURCE_XTAL);
|
||||
if (source == PLL_SOURCE_CLKIN) {
|
||||
si5351c_configure_inputs(drv, SI5351C_INPUT_XTAL);
|
||||
if (input == SI5351C_INPUT_CLKIN) {
|
||||
gpio_set(platform_gpio()->h1r9_clkin_en);
|
||||
} else {
|
||||
gpio_clear(platform_gpio()->h1r9_clkin_en);
|
||||
|
|
@ -437,12 +522,13 @@ void si5351c_set_clock_source(si5351c_driver_t* const drv, const enum pll_source
|
|||
#endif
|
||||
#ifdef IS_NOT_H1_R9
|
||||
if (IS_NOT_H1_R9) {
|
||||
si5351c_configure_pll_sources(drv, source);
|
||||
si5351c_configure_inputs(drv, input);
|
||||
}
|
||||
#endif
|
||||
si5351c_configure_pll_multisynth(drv, source);
|
||||
active_clock_source = source;
|
||||
si5351c_reset_pll(drv, SI5351C_PLL_BOTH);
|
||||
si5351c_configure_pll_multisynth(drv, input);
|
||||
active_input = input;
|
||||
input_initialized = true;
|
||||
si5351c_reset_plls(drv, SI5351C_PLL_MASK_BOTH);
|
||||
}
|
||||
|
||||
bool si5351c_clkin_signal_valid(si5351c_driver_t* const drv)
|
||||
|
|
@ -451,7 +537,9 @@ bool si5351c_clkin_signal_valid(si5351c_driver_t* const drv)
|
|||
uint32_t f = clkin_frequency();
|
||||
return (f > 9000000) && (f < 11000000);
|
||||
} else {
|
||||
return (si5351c_read_single(drv, 0) & SI5351C_LOS) == 0;
|
||||
si5351c_read_single(drv, LOS_CLKIN);
|
||||
bool los_clkin = get_LOS_CLKIN(drv);
|
||||
return !los_clkin;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -475,7 +563,8 @@ void si5351c_clkout_enable(si5351c_driver_t* const drv, uint8_t enable)
|
|||
void si5351c_init(si5351c_driver_t* const drv)
|
||||
{
|
||||
/* Read revision ID */
|
||||
selftest.si5351_rev_id = si5351c_read_single(drv, 0) & SI5351C_REVID;
|
||||
si5351c_read_single(drv, REVID);
|
||||
selftest.si5351_rev_id = get_REVID(drv);
|
||||
|
||||
/* Read back interrupt status mask register, flip the mask bits and verify. */
|
||||
uint8_t int_mask = si5351c_read_single(drv, 2);
|
||||
|
|
@ -494,6 +583,17 @@ void si5351c_init(si5351c_driver_t* const drv)
|
|||
selftest.report.pass = false;
|
||||
}
|
||||
|
||||
/* Cache all current register values. */
|
||||
uint8_t data_tx[] = {0};
|
||||
i2c_bus_transfer(
|
||||
drv->bus,
|
||||
drv->i2c_address,
|
||||
data_tx,
|
||||
1,
|
||||
drv->regs,
|
||||
sizeof(drv->regs));
|
||||
memset(drv->regs_dirty, 0, sizeof(drv->regs_dirty));
|
||||
|
||||
#ifdef IS_H1_R9
|
||||
if (IS_H1_R9) {
|
||||
const platform_gpio_t* gpio = platform_gpio();
|
||||
|
|
@ -529,8 +629,6 @@ void si5351c_set_phase(
|
|||
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);
|
||||
}
|
||||
set_CLK_PHOFF(drv, ms_number, offset);
|
||||
si5351c_regs_commit(drv);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2022 Great Scott Gadgets <info@greatscottgadgets.com>
|
||||
* Copyright 2012-2026 Great Scott Gadgets <info@greatscottgadgets.com>
|
||||
* Copyright 2012 Jared Boone <jared@sharebrained.com>
|
||||
*
|
||||
* This file is part of HackRF.
|
||||
|
|
@ -28,65 +28,93 @@ extern "C" {
|
|||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "i2c_bus.h"
|
||||
#include "i2c_lpc.h"
|
||||
|
||||
#define SI_INTDIV(x) (x * 128 - 512)
|
||||
|
||||
#define SI5351C_CLK_POWERDOWN (1 << 7)
|
||||
#define SI5351C_CLK_INT_MODE (1 << 6)
|
||||
#define SI5351C_CLK_FRAC_MODE (0 << 6)
|
||||
|
||||
#define SI5351C_CLK_INV (1 << 4)
|
||||
|
||||
#define SI5351C_CLK_SRC(x) (x << 2)
|
||||
#define SI5351C_CLK_SRC_XTAL 0
|
||||
#define SI5351C_CLK_SRC_CLKIN 1
|
||||
#define SI5351C_CLK_SRC_MULTISYNTH_0_4 2
|
||||
#define SI5351C_CLK_SRC_MULTISYNTH_SELF 3
|
||||
|
||||
#define SI5351C_CLK_IDRV(x) (x << 0)
|
||||
#define SI5351C_CLK_IDRV_2MA 0
|
||||
#define SI5351C_CLK_IDRV_4MA 1
|
||||
#define SI5351C_CLK_IDRV_6MA 2
|
||||
#define SI5351C_CLK_IDRV_8MA 3
|
||||
|
||||
#define SI5351C_LOS (1 << 4)
|
||||
#define SI5351C_REVID 0x03
|
||||
#define SI5351C_CACHED_REGS 188
|
||||
|
||||
typedef enum {
|
||||
SI5351C_PLL_A = 1,
|
||||
SI5351C_PLL_B = 2,
|
||||
SI5351C_PLL_BOTH = 3,
|
||||
SI5351C_MODE_FRAC = 0,
|
||||
SI5351C_MODE_INT = 1,
|
||||
} si5351c_mode_t;
|
||||
|
||||
typedef enum {
|
||||
SI5351C_SRC_XTAL = 0,
|
||||
SI5351C_SRC_CLKIN = 1,
|
||||
SI5351C_SRC_MULTISYNTH_0_4 = 2,
|
||||
SI5351C_SRC_MULTISYNTH_SELF = 3,
|
||||
} si5351c_src_t;
|
||||
|
||||
typedef enum {
|
||||
SI5351C_DRIVE_2MA = 0,
|
||||
SI5351C_DRIVE_4MA = 1,
|
||||
SI5351C_DRIVE_6MA = 2,
|
||||
SI5351C_DRIVE_8MA = 3,
|
||||
} si5351c_drive_t;
|
||||
|
||||
typedef enum {
|
||||
SI5351C_PLL_A = 0,
|
||||
SI5351C_PLL_B = 1,
|
||||
} si5351c_pll_t;
|
||||
|
||||
#define SI5351C_CLK_PLL_SRC(x) ((x & SI5351C_PLL_B) << 4)
|
||||
typedef enum {
|
||||
SI5351C_PLL_MASK_A = 1,
|
||||
SI5351C_PLL_MASK_B = 2,
|
||||
SI5351C_PLL_MASK_BOTH = 3,
|
||||
} si5351c_pll_mask_t;
|
||||
|
||||
enum pll_sources {
|
||||
PLL_SOURCE_UNINITIALIZED = -1,
|
||||
PLL_SOURCE_XTAL = 0,
|
||||
PLL_SOURCE_CLKIN = 1,
|
||||
};
|
||||
typedef enum {
|
||||
SI5351C_XTAL_6PF = 1,
|
||||
SI5351C_XTAL_8PF = 2,
|
||||
SI5351C_XTAL_10PF = 3,
|
||||
} si5351c_xtal_t;
|
||||
|
||||
typedef enum {
|
||||
SI5351C_OUTPUT_ENABLE = 0,
|
||||
SI5351C_OUTPUT_DISABLE = 1,
|
||||
} si5351c_output_t;
|
||||
|
||||
typedef enum {
|
||||
SI5351C_DIV_1 = 0,
|
||||
SI5351C_DIV_2 = 1,
|
||||
SI5351C_DIV_4 = 2,
|
||||
SI5351C_DIV_8 = 3,
|
||||
} si5351c_div_t;
|
||||
|
||||
typedef enum {
|
||||
SI5351C_INPUT_XTAL = 0,
|
||||
SI5351C_INPUT_CLKIN = 1,
|
||||
} si5351c_input_t;
|
||||
|
||||
typedef struct {
|
||||
i2c_bus_t* const bus;
|
||||
uint8_t i2c_address;
|
||||
uint8_t regs[SI5351C_CACHED_REGS];
|
||||
uint32_t regs_dirty[(SI5351C_CACHED_REGS + 31) / 32];
|
||||
} si5351c_driver_t;
|
||||
|
||||
typedef struct {
|
||||
bool power_down;
|
||||
si5351c_mode_t mode;
|
||||
si5351c_pll_t pll;
|
||||
si5351c_src_t source;
|
||||
si5351c_drive_t drive;
|
||||
bool invert;
|
||||
} si5351c_clk_ctrl_t;
|
||||
|
||||
void si5351c_disable_all_outputs(si5351c_driver_t* const drv);
|
||||
void si5351c_disable_oeb_pin_control(si5351c_driver_t* const drv);
|
||||
void si5351c_power_down_all_clocks(si5351c_driver_t* const drv);
|
||||
void si5351c_set_crystal_configuration(si5351c_driver_t* const drv);
|
||||
void si5351c_enable_xo_and_ms_fanout(si5351c_driver_t* const drv);
|
||||
void si5351c_configure_pll_sources(
|
||||
si5351c_driver_t* const drv,
|
||||
const enum pll_sources source);
|
||||
void si5351c_configure_inputs(si5351c_driver_t* const drv, const si5351c_input_t input);
|
||||
void si5351c_configure_pll_multisynth(
|
||||
si5351c_driver_t* const drv,
|
||||
const enum pll_sources source);
|
||||
void si5351c_reset_pll(si5351c_driver_t* const drv, si5351c_pll_t pll);
|
||||
const si5351c_input_t input);
|
||||
void si5351c_reset_plls(si5351c_driver_t* const drv, si5351c_pll_mask_t mask);
|
||||
void si5351c_configure_multisynth(
|
||||
si5351c_driver_t* const drv,
|
||||
const uint_fast8_t ms_number,
|
||||
|
|
@ -100,15 +128,11 @@ void si5351c_set_int_mode(
|
|||
si5351c_driver_t* const drv,
|
||||
const uint_fast8_t ms_number,
|
||||
const uint_fast8_t on);
|
||||
void si5351c_set_clock_source(si5351c_driver_t* const drv, const enum pll_sources source);
|
||||
void si5351c_change_input(si5351c_driver_t* const drv, const si5351c_input_t input);
|
||||
bool si5351c_clkin_signal_valid(si5351c_driver_t* const drv);
|
||||
|
||||
void si5351c_write_single(si5351c_driver_t* const drv, uint8_t reg, uint8_t val);
|
||||
uint8_t si5351c_read_single(si5351c_driver_t* const drv, uint8_t reg);
|
||||
void si5351c_write(
|
||||
si5351c_driver_t* const drv,
|
||||
const uint8_t* const data,
|
||||
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(
|
||||
|
|
|
|||
494
firmware/common/si5351c_regs.def
Normal file
494
firmware/common/si5351c_regs.def
Normal file
|
|
@ -0,0 +1,494 @@
|
|||
/*
|
||||
* Copyright 2026 Great Scott Gadgets <info@greatscottgadgets.com>
|
||||
*
|
||||
* This file is part of HackRF.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
static inline void si5351c_reg_set_clean(si5351c_driver_t* drv, int reg)
|
||||
{
|
||||
drv->regs_dirty[reg / 32] &= ~(1 << (reg % 32));
|
||||
}
|
||||
|
||||
static inline void si5351c_reg_set_dirty(si5351c_driver_t* drv, int reg)
|
||||
{
|
||||
drv->regs_dirty[reg / 32] |= (1 << (reg % 32));
|
||||
}
|
||||
|
||||
static inline bool si5351c_reg_is_dirty(si5351c_driver_t* drv, int reg)
|
||||
{
|
||||
return (drv->regs_dirty[reg / 32] & (1 << (reg % 32))) ? true : false;
|
||||
}
|
||||
|
||||
/* Generate static inline accessors that operate on the global
|
||||
* regs. Done this way to (1) allow defs to be scraped out and used
|
||||
* elsewhere, e.g. in scripts, (2) to avoid dealing with endian
|
||||
* (structs). This may be used in firmware, or on host predefined
|
||||
* register loads. */
|
||||
|
||||
/* On set_, register is always set dirty, even if nothing
|
||||
* changed. This makes sure that writes that have side effects,
|
||||
* e.g. frequency setting, are not skipped. */
|
||||
|
||||
/* n=name, r=regnum, o=offset (bits from LSB) of LSB of field,
|
||||
* l=length (bits) */
|
||||
#define __MREG__(n,r,o,l) \
|
||||
static inline uint8_t get_##n(si5351c_driver_t* const _d) { \
|
||||
return (_d->regs[r] >> o) & ((1L<<l)-1); \
|
||||
} \
|
||||
static inline void set_##n(si5351c_driver_t* const _d, uint8_t v) { \
|
||||
_d->regs[r] &= (uint8_t)(~(((1L<<l)-1)<<o)); \
|
||||
_d->regs[r] |= (uint8_t)(((v&((1L<<l)-1))<<o)); \
|
||||
si5351c_reg_set_dirty(_d, r); \
|
||||
} \
|
||||
const uint8_t n = r;
|
||||
|
||||
/* Generate accessors for numeric fields split across multiple registers */
|
||||
/* n = name */
|
||||
|
||||
#define __2PART__(n) \
|
||||
static inline uint16_t get_##n(si5351c_driver_t* const _d) { \
|
||||
return (get_##n##_TOP(_d) << 8) | get_##n##_BOT(_d); \
|
||||
} \
|
||||
static inline void set_##n(si5351c_driver_t* const _d, uint16_t v) { \
|
||||
set_##n##_TOP(_d, v >> 8); \
|
||||
set_##n##_BOT(_d, v); \
|
||||
}
|
||||
|
||||
#define __3PART__(n) \
|
||||
static inline uint32_t get_##n(si5351c_driver_t* const _d) { \
|
||||
return (get_##n##_TOP(_d) << 16) | (get_##n##_MID(_d) << 8) | get_##n##_BOT(_d); \
|
||||
} \
|
||||
static inline void set_##n(si5351c_driver_t* const _d, uint32_t v) { \
|
||||
set_##n##_TOP(_d, v >> 16); \
|
||||
set_##n##_MID(_d, v >> 8); \
|
||||
set_##n##_BOT(_d, v); \
|
||||
}
|
||||
|
||||
/* Generate accessors for per-PLL and per-multisynth registers */
|
||||
/* n=name, p=prefix, s=suffix */
|
||||
|
||||
#define __PER_PLL__(n, p, s) \
|
||||
static inline uint32_t get_##n(si5351c_driver_t* const _d, si5351c_pll_t pll) { \
|
||||
return (pll == SI5351C_PLL_A) ? get_##p##A##s(_d) : get_##p##B##s(_d); \
|
||||
} \
|
||||
static inline void set_##n(si5351c_driver_t* const _d, si5351c_pll_t pll, uint32_t v) { \
|
||||
if (pll == SI5351C_PLL_A) { \
|
||||
set_##p##A##s(_d, v); \
|
||||
} else { \
|
||||
set_##p##B##s(_d, v); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define __PER_MS__(n, p, s) \
|
||||
static inline uint32_t get_##n(si5351c_driver_t* const _d, uint8_t i) { \
|
||||
switch (i) { \
|
||||
case 0: return get_##p##0##s(_d); \
|
||||
case 1: return get_##p##1##s(_d); \
|
||||
case 2: return get_##p##2##s(_d); \
|
||||
case 3: return get_##p##3##s(_d); \
|
||||
case 4: return get_##p##4##s(_d); \
|
||||
case 5: return get_##p##5##s(_d); \
|
||||
case 6: return get_##p##6##s(_d); \
|
||||
case 7: return get_##p##7##s(_d); \
|
||||
default: return 0; \
|
||||
} \
|
||||
} \
|
||||
static inline void set_##n(si5351c_driver_t* const _d, uint8_t i, uint32_t v) { \
|
||||
switch (i) { \
|
||||
case 0: set_##p##0##s(_d, v); return; \
|
||||
case 1: set_##p##1##s(_d, v); return; \
|
||||
case 2: set_##p##2##s(_d, v); return; \
|
||||
case 3: set_##p##3##s(_d, v); return; \
|
||||
case 4: set_##p##4##s(_d, v); return; \
|
||||
case 5: set_##p##5##s(_d, v); return; \
|
||||
case 6: set_##p##6##s(_d, v); return; \
|
||||
case 7: set_##p##7##s(_d, v); return; \
|
||||
} \
|
||||
} \
|
||||
static inline void set_all_##n(si5351c_driver_t* const _d, uint32_t v) { \
|
||||
set_##p##0##s(_d, v); \
|
||||
set_##p##1##s(_d, v); \
|
||||
set_##p##2##s(_d, v); \
|
||||
set_##p##3##s(_d, v); \
|
||||
set_##p##4##s(_d, v); \
|
||||
set_##p##5##s(_d, v); \
|
||||
set_##p##6##s(_d, v); \
|
||||
set_##p##7##s(_d, v); \
|
||||
}
|
||||
|
||||
#define __PER_FRAC_MS__(n, p, s) \
|
||||
static inline void set_##n(si5351c_driver_t* const _d, uint8_t i, uint32_t v) { \
|
||||
switch (i) { \
|
||||
case 0: set_##p##0##s(_d, v); return; \
|
||||
case 1: set_##p##1##s(_d, v); return; \
|
||||
case 2: set_##p##2##s(_d, v); return; \
|
||||
case 3: set_##p##3##s(_d, v); return; \
|
||||
case 4: set_##p##4##s(_d, v); return; \
|
||||
case 5: set_##p##5##s(_d, v); return; \
|
||||
} \
|
||||
}
|
||||
|
||||
/* Register 0: Device Status */
|
||||
__MREG__(SYS_INIT, 0, 7, 1)
|
||||
__MREG__(LOL_B, 0, 6, 1)
|
||||
__MREG__(LOL_A, 0, 5, 1)
|
||||
__MREG__(LOS_CLKIN, 0, 4, 1)
|
||||
__MREG__(LOS_XTAL, 0, 3, 1)
|
||||
__MREG__(REVID, 0, 0, 2)
|
||||
|
||||
/* Register 1: Interrupt Status Sticky */
|
||||
__MREG__(SYS_INIT_STKY, 1, 7, 1)
|
||||
__MREG__(LOL_B_STKY, 1, 6, 1)
|
||||
__MREG__(LOL_A_STKY, 1, 5, 1)
|
||||
__MREG__(LOS_CLKIN_STKY, 1, 4, 1)
|
||||
__MREG__(LOS_XTAL_STKY, 1, 3, 1)
|
||||
|
||||
/* Register 2: Interrupt Status Mask */
|
||||
__MREG__(SYS_INIT_MASK, 2, 7, 1)
|
||||
__MREG__(LOL_B_MASK, 2, 6, 1)
|
||||
__MREG__(LOL_A_MASK, 2, 5, 1)
|
||||
__MREG__(LOS_CLKIN_MASK, 2, 4, 1)
|
||||
__MREG__(LOS_XTAL_MASK, 2, 3, 1)
|
||||
|
||||
/* Register 3: Output Enable Control */
|
||||
__MREG__(CLK7_OEB, 3, 7, 1)
|
||||
__MREG__(CLK6_OEB, 3, 6, 1)
|
||||
__MREG__(CLK5_OEB, 3, 5, 1)
|
||||
__MREG__(CLK4_OEB, 3, 4, 1)
|
||||
__MREG__(CLK3_OEB, 3, 3, 1)
|
||||
__MREG__(CLK2_OEB, 3, 2, 1)
|
||||
__MREG__(CLK1_OEB, 3, 1, 1)
|
||||
__MREG__(CLK0_OEB, 3, 0, 1)
|
||||
|
||||
/* Register 4: OEB Pin Enable Control */
|
||||
__MREG__(OEB_CLK7, 4, 7, 1)
|
||||
__MREG__(OEB_CLK6, 4, 6, 1)
|
||||
__MREG__(OEB_CLK5, 4, 5, 1)
|
||||
__MREG__(OEB_CLK4, 4, 4, 1)
|
||||
__MREG__(OEB_CLK3, 4, 3, 1)
|
||||
__MREG__(OEB_CLK2, 4, 2, 1)
|
||||
__MREG__(OEB_CLK1, 4, 1, 1)
|
||||
__MREG__(OEB_CLK0, 4, 0, 1)
|
||||
|
||||
/* Register 9: OEB Pin Enable Control Mask */
|
||||
__MREG__(OEB_MASK7, 9, 7, 1)
|
||||
__MREG__(OEB_MASK6, 9, 6, 1)
|
||||
__MREG__(OEB_MASK5, 9, 5, 1)
|
||||
__MREG__(OEB_MASK4, 9, 4, 1)
|
||||
__MREG__(OEB_MASK3, 9, 3, 1)
|
||||
__MREG__(OEB_MASK2, 9, 2, 1)
|
||||
__MREG__(OEB_MASK1, 9, 1, 1)
|
||||
__MREG__(OEB_MASK0, 9, 0, 1)
|
||||
|
||||
/* Register 15: PLL Input Source */
|
||||
__MREG__(CLKIN_DIV, 15, 6, 2)
|
||||
__MREG__(PLLB_SRC, 15, 3, 1)
|
||||
__MREG__(PLLA_SRC, 15, 2, 1)
|
||||
|
||||
/* Register 16: CLK0 Control */
|
||||
__MREG__(CLK0_PDN, 16, 7, 1)
|
||||
__MREG__(MS0_INT, 16, 6, 1)
|
||||
__MREG__(MS0_SRC, 16, 5, 1)
|
||||
__MREG__(CLK0_INV, 16, 4, 1)
|
||||
__MREG__(CLK0_SRC, 16, 2, 2)
|
||||
__MREG__(CLK0_IDRV, 16, 0, 2)
|
||||
|
||||
/* Register 17: CLK1 Control */
|
||||
__MREG__(CLK1_PDN, 17, 7, 1)
|
||||
__MREG__(MS1_INT, 17, 6, 1)
|
||||
__MREG__(MS1_SRC, 17, 5, 1)
|
||||
__MREG__(CLK1_INV, 17, 4, 1)
|
||||
__MREG__(CLK1_SRC, 17, 2, 2)
|
||||
__MREG__(CLK1_IDRV, 17, 0, 2)
|
||||
|
||||
/* Register 18: CLK2 Control */
|
||||
__MREG__(CLK2_PDN, 18, 7, 1)
|
||||
__MREG__(MS2_INT, 18, 6, 1)
|
||||
__MREG__(MS2_SRC, 18, 5, 1)
|
||||
__MREG__(CLK2_INV, 18, 4, 1)
|
||||
__MREG__(CLK2_SRC, 18, 2, 2)
|
||||
__MREG__(CLK2_IDRV, 18, 0, 2)
|
||||
|
||||
/* Register 19: CLK3 Control */
|
||||
__MREG__(CLK3_PDN, 19, 7, 1)
|
||||
__MREG__(MS3_INT, 19, 6, 1)
|
||||
__MREG__(MS3_SRC, 19, 5, 1)
|
||||
__MREG__(CLK3_INV, 19, 4, 1)
|
||||
__MREG__(CLK3_SRC, 19, 2, 2)
|
||||
__MREG__(CLK3_IDRV, 19, 0, 2)
|
||||
|
||||
/* Register 20: CLK4 Control */
|
||||
__MREG__(CLK4_PDN, 20, 7, 1)
|
||||
__MREG__(MS4_INT, 20, 6, 1)
|
||||
__MREG__(MS4_SRC, 20, 5, 1)
|
||||
__MREG__(CLK4_INV, 20, 4, 1)
|
||||
__MREG__(CLK4_SRC, 20, 2, 2)
|
||||
__MREG__(CLK4_IDRV, 20, 0, 2)
|
||||
|
||||
/* Register 21: CLK5 Control */
|
||||
__MREG__(CLK5_PDN, 21, 7, 1)
|
||||
__MREG__(MS5_INT, 21, 6, 1)
|
||||
__MREG__(MS5_SRC, 21, 5, 1)
|
||||
__MREG__(CLK5_INV, 21, 4, 1)
|
||||
__MREG__(CLK5_SRC, 21, 2, 2)
|
||||
__MREG__(CLK5_IDRV, 21, 0, 2)
|
||||
|
||||
/* Register 22: CLK6 Control */
|
||||
__MREG__(CLK6_PDN, 22, 7, 1)
|
||||
__MREG__(FBA_INT, 22, 6, 1)
|
||||
__MREG__(MS6_SRC, 22, 5, 1)
|
||||
__MREG__(CLK6_INV, 22, 4, 1)
|
||||
__MREG__(CLK6_SRC, 22, 2, 2)
|
||||
__MREG__(CLK6_IDRV, 22, 0, 2)
|
||||
|
||||
/* Register 23: CLK7 Control */
|
||||
__MREG__(CLK7_PDN, 23, 7, 1)
|
||||
__MREG__(FBB_INT, 23, 6, 1)
|
||||
__MREG__(MS7_SRC, 23, 5, 1)
|
||||
__MREG__(CLK7_INV, 23, 4, 1)
|
||||
__MREG__(CLK7_SRC, 23, 2, 2)
|
||||
__MREG__(CLK7_IDRV, 23, 0, 2)
|
||||
|
||||
/* Register 24: CLK0-CLK3 Disable State */
|
||||
__MREG__(CLK3_DIS_STATE, 24, 6, 2)
|
||||
__MREG__(CLK2_DIS_STATE, 24, 4, 2)
|
||||
__MREG__(CLK1_DIS_STATE, 24, 2, 2)
|
||||
__MREG__(CLK0_DIS_STATE, 24, 0, 2)
|
||||
|
||||
/* Register 25: CLK4-CLK7 Disable State */
|
||||
__MREG__(CLK7_DIS_STATE, 25, 6, 2)
|
||||
__MREG__(CLK6_DIS_STATE, 25, 4, 2)
|
||||
__MREG__(CLK5_DIS_STATE, 25, 2, 2)
|
||||
__MREG__(CLK4_DIS_STATE, 25, 0, 2)
|
||||
|
||||
/* Registers 26-33: Multisynth NA Parameters */
|
||||
__MREG__(MSNA_P3_MID, 26, 0, 8)
|
||||
__MREG__(MSNA_P3_BOT, 27, 0, 8)
|
||||
__MREG__(MSNA_P1_TOP, 28, 0, 2)
|
||||
__MREG__(MSNA_P1_MID, 29, 0, 8)
|
||||
__MREG__(MSNA_P1_BOT, 30, 0, 8)
|
||||
__MREG__(MSNA_P3_TOP, 31, 4, 4)
|
||||
__MREG__(MSNA_P2_TOP, 31, 0, 4)
|
||||
__MREG__(MSNA_P2_MID, 32, 0, 8)
|
||||
__MREG__(MSNA_P2_BOT, 33, 0, 8)
|
||||
|
||||
/* Registers 34-41: Multisynth NB Parameters */
|
||||
__MREG__(MSNB_P3_MID, 34, 0, 8)
|
||||
__MREG__(MSNB_P3_BOT, 35, 0, 8)
|
||||
__MREG__(MSNB_P1_TOP, 36, 0, 2)
|
||||
__MREG__(MSNB_P1_MID, 37, 0, 8)
|
||||
__MREG__(MSNB_P1_BOT, 38, 0, 8)
|
||||
__MREG__(MSNB_P3_TOP, 39, 4, 4)
|
||||
__MREG__(MSNB_P2_TOP, 39, 0, 4)
|
||||
__MREG__(MSNB_P2_MID, 40, 0, 8)
|
||||
__MREG__(MSNB_P2_BOT, 41, 0, 8)
|
||||
|
||||
/* Registers 42-49: Multisynth 0 Parameters */
|
||||
__MREG__(MS0_P3_MID, 42, 0, 8)
|
||||
__MREG__(MS0_P3_BOT, 43, 0, 8)
|
||||
__MREG__(R0_DIV, 44, 4, 3)
|
||||
__MREG__(MS0_DIVBY4, 44, 2, 2)
|
||||
__MREG__(MS0_P1_TOP, 44, 0, 2)
|
||||
__MREG__(MS0_P1_MID, 45, 0, 8)
|
||||
__MREG__(MS0_P1_BOT, 46, 0, 8)
|
||||
__MREG__(MS0_P3_TOP, 47, 4, 4)
|
||||
__MREG__(MS0_P2_TOP, 47, 0, 4)
|
||||
__MREG__(MS0_P2_MID, 48, 0, 8)
|
||||
__MREG__(MS0_P2_BOT, 49, 0, 8)
|
||||
|
||||
/* Registers 50-57: Multisynth 1 Parameters */
|
||||
__MREG__(MS1_P3_MID, 50, 0, 8)
|
||||
__MREG__(MS1_P3_BOT, 51, 0, 8)
|
||||
__MREG__(R1_DIV, 52, 4, 3)
|
||||
__MREG__(MS1_DIVBY4, 52, 2, 2)
|
||||
__MREG__(MS1_P1_TOP, 52, 0, 2)
|
||||
__MREG__(MS1_P1_MID, 53, 0, 8)
|
||||
__MREG__(MS1_P1_BOT, 54, 0, 8)
|
||||
__MREG__(MS1_P3_TOP, 55, 4, 4)
|
||||
__MREG__(MS1_P2_TOP, 55, 0, 4)
|
||||
__MREG__(MS1_P2_MID, 56, 0, 8)
|
||||
__MREG__(MS1_P2_BOT, 57, 0, 8)
|
||||
|
||||
/* Registers 58-65: Multisynth 2 Parameters */
|
||||
__MREG__(MS2_P3_MID, 58, 0, 8)
|
||||
__MREG__(MS2_P3_BOT, 59, 0, 8)
|
||||
__MREG__(R2_DIV, 60, 4, 3)
|
||||
__MREG__(MS2_DIVBY4, 60, 2, 2)
|
||||
__MREG__(MS2_P1_TOP, 60, 0, 2)
|
||||
__MREG__(MS2_P1_MID, 61, 0, 8)
|
||||
__MREG__(MS2_P1_BOT, 62, 0, 8)
|
||||
__MREG__(MS2_P3_TOP, 63, 4, 4)
|
||||
__MREG__(MS2_P2_TOP, 63, 0, 4)
|
||||
__MREG__(MS2_P2_MID, 64, 0, 8)
|
||||
__MREG__(MS2_P2_BOT, 65, 0, 8)
|
||||
|
||||
/* Registers 66-73: Multisynth 3 Parameters */
|
||||
__MREG__(MS3_P3_MID, 66, 0, 8)
|
||||
__MREG__(MS3_P3_BOT, 67, 0, 8)
|
||||
__MREG__(R3_DIV, 68, 4, 3)
|
||||
__MREG__(MS3_DIVBY4, 68, 2, 2)
|
||||
__MREG__(MS3_P1_TOP, 68, 0, 2)
|
||||
__MREG__(MS3_P1_MID, 69, 0, 8)
|
||||
__MREG__(MS3_P1_BOT, 70, 0, 8)
|
||||
__MREG__(MS3_P3_TOP, 71, 4, 4)
|
||||
__MREG__(MS3_P2_TOP, 71, 0, 4)
|
||||
__MREG__(MS3_P2_MID, 72, 0, 8)
|
||||
__MREG__(MS3_P2_BOT, 73, 0, 8)
|
||||
|
||||
/* Registers 74-81: Multisynth 4 Parameters */
|
||||
__MREG__(MS4_P3_MID, 74, 0, 8)
|
||||
__MREG__(MS4_P3_BOT, 75, 0, 8)
|
||||
__MREG__(R4_DIV, 76, 4, 3)
|
||||
__MREG__(MS4_DIVBY4, 76, 2, 2)
|
||||
__MREG__(MS4_P1_TOP, 76, 0, 2)
|
||||
__MREG__(MS4_P1_MID, 77, 0, 8)
|
||||
__MREG__(MS4_P1_BOT, 78, 0, 8)
|
||||
__MREG__(MS4_P3_TOP, 79, 4, 4)
|
||||
__MREG__(MS4_P2_TOP, 79, 0, 4)
|
||||
__MREG__(MS4_P2_MID, 80, 0, 8)
|
||||
__MREG__(MS4_P2_BOT, 81, 0, 8)
|
||||
|
||||
/* Registers 82-89: Multisynth 5 Parameters */
|
||||
__MREG__(MS5_P3_MID, 82, 0, 8)
|
||||
__MREG__(MS5_P3_BOT, 83, 0, 8)
|
||||
__MREG__(R5_DIV, 84, 4, 3)
|
||||
__MREG__(MS5_DIVBY4, 84, 2, 2)
|
||||
__MREG__(MS5_P1_TOP, 84, 0, 2)
|
||||
__MREG__(MS5_P1_MID, 85, 0, 8)
|
||||
__MREG__(MS5_P1_BOT, 86, 0, 8)
|
||||
__MREG__(MS5_P3_TOP, 87, 4, 4)
|
||||
__MREG__(MS5_P2_TOP, 87, 0, 4)
|
||||
__MREG__(MS5_P2_MID, 88, 0, 8)
|
||||
__MREG__(MS5_P2_BOT, 89, 0, 8)
|
||||
|
||||
/* Register 90: Multisynth 6 Parameters */
|
||||
__MREG__(MS6_P1, 90, 0, 8)
|
||||
|
||||
/* Register 91: Multisynth 7 Parameters */
|
||||
__MREG__(MS7_P1, 91, 0, 8)
|
||||
|
||||
/* Register 92: Clock 6 and 7 Output Divider */
|
||||
__MREG__(R7_DIV, 92, 4, 3)
|
||||
__MREG__(R6_DIV, 92, 0, 3)
|
||||
|
||||
/* Registers 149-161: Spread Spectrum Parameters */
|
||||
__MREG__(SSC_EN, 149, 7, 1)
|
||||
__MREG__(SSDN_P2_TOP, 149, 0, 7)
|
||||
__MREG__(SSDN_P2_BOT, 150, 0, 8)
|
||||
__MREG__(SSC_MODE, 151, 7, 1)
|
||||
__MREG__(SSDN_P3_TOP, 151, 0, 7)
|
||||
__MREG__(SSDN_P3_BOT, 152, 0, 8)
|
||||
__MREG__(SSDN_P1_BOT, 153, 0, 8)
|
||||
__MREG__(SSUDP_TOP, 154, 4, 4)
|
||||
__MREG__(SSDN_P1_TOP, 154, 0, 4)
|
||||
__MREG__(SSUDP_BOT, 155, 0, 8)
|
||||
__MREG__(SSUP_P2_TOP, 156, 0, 7)
|
||||
__MREG__(SSUP_P2_BOT, 157, 0, 8)
|
||||
__MREG__(SSUP_P3_TOP, 158, 0, 8)
|
||||
__MREG__(SSUP_P3_BOT, 159, 0, 8)
|
||||
__MREG__(SSUP_P1_BOT, 160, 0, 8)
|
||||
__MREG__(SS_NCLK, 161, 4, 4)
|
||||
__MREG__(SSUP_P1_TOP, 161, 0, 4)
|
||||
|
||||
/* Registers 162-163: VCXO Parameter */
|
||||
__MREG__(VCXO_PARAM_BOT, 162, 0, 8)
|
||||
__MREG__(VCXO_PARAM_MID, 163, 0, 8)
|
||||
__MREG__(VCXO_PARAM_TOP, 164, 0, 6)
|
||||
|
||||
/* Registers 165-170: CLK0-CLK5 Initial Phase Offsets */
|
||||
__MREG__(CLK0_PHOFF, 165, 0, 7)
|
||||
__MREG__(CLK1_PHOFF, 166, 0, 7)
|
||||
__MREG__(CLK2_PHOFF, 167, 0, 7)
|
||||
__MREG__(CLK3_PHOFF, 168, 0, 7)
|
||||
__MREG__(CLK4_PHOFF, 169, 0, 7)
|
||||
__MREG__(CLK5_PHOFF, 170, 0, 7)
|
||||
|
||||
/* Register 177: PLL Reset */
|
||||
__MREG__(PLLB_RST, 177, 7, 1)
|
||||
__MREG__(PLLA_RST, 177, 5, 1)
|
||||
|
||||
/* Register 183: Crystal Internal Load Capacitance */
|
||||
__MREG__(XTAL_CL, 183, 6, 2)
|
||||
|
||||
/* Register 187: Fanout Enable */
|
||||
__MREG__(CLKIN_FANOUT_EN, 187, 7, 1)
|
||||
__MREG__(XO_FANOUT_EN, 187, 6, 1)
|
||||
__MREG__(MS_FANOUT_EN, 187, 4, 1)
|
||||
|
||||
/* 3-part parameters */
|
||||
__3PART__(MSNA_P1)
|
||||
__3PART__(MSNA_P2)
|
||||
__3PART__(MSNA_P3)
|
||||
__3PART__(MSNB_P1)
|
||||
__3PART__(MSNB_P2)
|
||||
__3PART__(MSNB_P3)
|
||||
__3PART__(MS0_P1)
|
||||
__3PART__(MS0_P2)
|
||||
__3PART__(MS0_P3)
|
||||
__3PART__(MS1_P1)
|
||||
__3PART__(MS1_P2)
|
||||
__3PART__(MS1_P3)
|
||||
__3PART__(MS2_P1)
|
||||
__3PART__(MS2_P2)
|
||||
__3PART__(MS2_P3)
|
||||
__3PART__(MS3_P1)
|
||||
__3PART__(MS3_P2)
|
||||
__3PART__(MS3_P3)
|
||||
__3PART__(MS4_P1)
|
||||
__3PART__(MS4_P2)
|
||||
__3PART__(MS4_P3)
|
||||
__3PART__(MS5_P1)
|
||||
__3PART__(MS5_P2)
|
||||
__3PART__(MS5_P3)
|
||||
|
||||
/* 2-part parameters */
|
||||
__2PART__(SSDN_P1)
|
||||
__2PART__(SSDN_P2)
|
||||
__2PART__(SSDN_P3)
|
||||
__2PART__(SSUP_P1)
|
||||
__2PART__(SSUP_P2)
|
||||
__2PART__(SSUP_P3)
|
||||
__2PART__(SSUDP)
|
||||
|
||||
/* Per-PLL register groups */
|
||||
__PER_PLL__(LOL, LOL_, )
|
||||
__PER_PLL__(LOL_STKY, LOL_, _STKY)
|
||||
__PER_PLL__(LOL_MASK, LOL_, _MASK)
|
||||
__PER_PLL__(PLL_SRC, PLL, _SRC)
|
||||
__PER_PLL__(MSN_P1, MSN, _P1)
|
||||
__PER_PLL__(MSN_P2, MSN, _P2)
|
||||
__PER_PLL__(MSN_P3, MSN, _P3)
|
||||
__PER_PLL__(PLL_RST, PLL, _RST)
|
||||
|
||||
/* Per-multisynth register groups */
|
||||
__PER_MS__(CLK_OEB, CLK, _OEB)
|
||||
__PER_MS__(OEB_CLK, OEB_CLK, )
|
||||
__PER_MS__(OEB_MASK, OEB_MASK, )
|
||||
__PER_MS__(CLK_PDN, CLK, _PDN)
|
||||
__PER_MS__(MS_SRC, MS, _SRC)
|
||||
__PER_MS__(CLK_INV, CLK, _INV)
|
||||
__PER_MS__(CLK_SRC, CLK, _SRC)
|
||||
__PER_MS__(CLK_IDRV, CLK, _IDRV)
|
||||
__PER_MS__(CLK_DIS_STATE, CLK, _DIS_STATE)
|
||||
__PER_MS__(R_DIV, R, _DIV)
|
||||
__PER_MS__(MS_P1, MS, _P1)
|
||||
__PER_FRAC_MS__(MS_INT, MS, _INT)
|
||||
__PER_FRAC_MS__(MS_P2, MS, _P2)
|
||||
__PER_FRAC_MS__(MS_P3, MS, _P3)
|
||||
__PER_FRAC_MS__(MS_DIVBY4, MS, _DIVBY4)
|
||||
__PER_FRAC_MS__(CLK_PHOFF, CLK, _PHOFF)
|
||||
Loading…
Add table
Add a link
Reference in a new issue