文章目录
AD9361示意图
典型特性
接收通路
TIA_LPF和BB_LPF属于模拟滤波器,HB3/DEC3、HB2、HB1、FIR属于数字滤波器。
发射通路
RF AND BBPLL SYNTHESIZER
经由片上的DCXO或外部晶振,再经过缓冲、2倍频、2分频、4分频之后,能够得到三个独立的Fref,分别作为BBPLL、Tx、Rx的参考频率。为了RFPLL能够有最好的性能,ADI建议将参考时钟或晶振频率在scale之后设置的越接近80MHz越好。
RF PLL
AD9361片内集成了整个PLL(包括VCO和环路滤波器),PLL运行在6~12GHz。
PLL经过divider之后,获得70MHz~6GHz的射频频率。
BBPLL
BB PLL是用来产生AD9361片内的数字时钟,包括ADC CLK、DAC CLK、所有的模拟校正时钟等,PLL运行在715MHz~1.43GHz。
REF_CLK、BBPLL_CLK、RFPLL_CLK的频率范围
摘自《AD9361_cn》
摘自《AD9361 Reference Manual》
摘自《AD9361配置软件》
ENABLE STATE MACHINE GUIDE
TDD 同一时刻只能发送或接收
FDD 可以收发同时
使能状态机(ENSM)能实时控制器件的当前状态。
Tx Power Control
发射功率的控制是通过调节发射衰减实现的,AD9361片上集成了一个hard-coded的衰减查找表,查找表的深度为360,衰减步进为0.25dB,总共可调衰减为(360-1)*0.25=89.75dB。
2R2T的收发时序
摘自《AD9361 Reference Manual》
FIR系数
SPI配置
复位期间不能进行SPI操作
复位引脚是低有效的
当一直复位时,似乎不能进行SPI操作,如SPI回读
默认先传高比特
MSB传输时,当启用多字节传输时,寄存器地址是递减的
SPI_CLK的最大频率(时钟最大50M)
官方范例代码分析
收发链路上的时钟
摘自《AD9361配置软件》
上图中的内容,可以在官方示例代码中找到对应内容,如下所示,
//摘自main.c
AD9361_InitParam default_init_param = {
//以上省略
/* Reference Clock */
40000000UL, //reference_clk_rate
//以上省略
/* Rate & BW Control */
{983040000, 245760000, 122880000, 61440000, 30720000, 30720000},// rx_path_clock_frequencies[6] *** adi,rx-path-clock-frequencies
{983040000, 122880000, 122880000, 61440000, 30720000, 30720000},// tx_path_clock_frequencies[6] *** adi,tx-path-clock-frequencies
18000000,//rf_rx_bandwidth_hz *** adi,rf-rx-bandwidth-hz
18000000,//rf_tx_bandwidth_hz *** adi,rf-tx-bandwidth-hz
//以下省略
}
//摘自ad9361.h
enum ad9361_clocks {
BB_REFCLK,
RX_REFCLK,
TX_REFCLK,
BBPLL_CLK,
ADC_CLK,
R2_CLK,
R1_CLK,
CLKRF_CLK,
RX_SAMPL_CLK,
DAC_CLK,
T2_CLK,
T1_CLK,
CLKTF_CLK,
TX_SAMPL_CLK,
RX_RFPLL_INT,
TX_RFPLL_INT,
RX_RFPLL_DUMMY,
TX_RFPLL_DUMMY,
RX_RFPLL,
TX_RFPLL,
NUM_AD9361_CLKS,
EXT_REF_CLK,
};
//用于对adi,rx-path-clock-frequencies进行索引
enum ad9361_pdata_rx_freq {
BBPLL_FREQ,
ADC_FREQ,
R2_FREQ,
R1_FREQ,
CLKRF_FREQ,
RX_SAMPL_FREQ,
NUM_RX_CLOCKS,
};
//摘自ad9361.c
int32_t ad9361_init (struct ad9361_rf_phy **ad9361_phy, AD9361_InitParam *init_param)
{
//以上省略
/* Reference Clock */
phy->clk_refin->rate = init_param->reference_clk_rate;
//以上省略
/* Rate & BW Control */
for(i = 0; i < 6; i++) {
phy->pdata->rx_path_clks[i] = init_param->rx_path_clock_frequencies[i];
}
for(i = 0; i < 6; i++) {
phy->pdata->tx_path_clks[i] = init_param->tx_path_clock_frequencies[i];
}
phy->pdata->rf_rx_bandwidth_Hz = init_param->rf_rx_bandwidth_hz;
phy->pdata->rf_tx_bandwidth_Hz = init_param->rf_tx_bandwidth_hz;
//以下省略
}
//摘自ad9361.c
/**
* Set the RX and TX path rates.
* @param phy The AD9361 state structure.
* @param rx_path_clks RX path rates buffer.
* @param tx_path_clks TX path rates buffer.
* @return 0 in case of success, negative error code otherwise.
*/
int32_t ad9361_set_trx_clock_chain(struct ad9361_rf_phy *phy,uint32_t *rx_path_clks,uint32_t *tx_path_clks)
{
//以上省略
ret = ad9361_validate_trx_clock_chain(phy, rx_path_clks);
if (ret < 0) return ret;
ret = clk_set_rate(phy, phy->ref_clk_scale[BBPLL_CLK], rx_path_clks[BBPLL_FREQ]);
if (ret < 0) return ret;
for (i = ADC_CLK, j = DAC_CLK, n = ADC_FREQ;
i <= RX_SAMPL_CLK; i++, j++, n++) {
ret = clk_set_rate(phy, phy->ref_clk_scale[i], rx_path_clks[n]);
if (ret < 0) {
dev_err(dev, "Failed to set BB ref clock rate (%"PRId32")",
ret);
return ret;
}
ret = clk_set_rate(phy, phy->ref_clk_scale[j], tx_path_clks[n]);
if (ret < 0) {
dev_err(dev, "Failed to set BB ref clock rate (%"PRId32")",
ret);
return ret;
}
}
}
/***************************************************************************//**
* @brief clk_set_rate
*******************************************************************************/
int32_t clk_set_rate(struct ad9361_rf_phy *phy,
struct refclk_scale *clk_priv,
uint32_t rate)
{
//以上省略
source = clk_priv->source;
if(phy->clks[source]->rate != rate)
{
switch (source) {
case TX_REFCLK:
case RX_REFCLK:
case BB_REFCLK:
round_rate = ad9361_clk_factor_round_rate(clk_priv, rate,
&phy->clk_refin->rate);
ad9361_clk_factor_set_rate(clk_priv, round_rate,
phy->clk_refin->rate);
phy->clks[source]->rate = ad9361_clk_factor_recalc_rate(clk_priv,
phy->clk_refin->rate);
break;
case TX_RFPLL_INT:
case RX_RFPLL_INT:
round_rate = ad9361_rfpll_int_round_rate(clk_priv, rate,
&phy->clks[clk_priv->parent_source]->rate);
ad9361_rfpll_int_set_rate(clk_priv, round_rate,
phy->clks[clk_priv->parent_source]->rate);
phy->clks[source]->rate = ad9361_rfpll_int_recalc_rate(clk_priv,
phy->clks[clk_priv->parent_source]->rate);
break;
case RX_RFPLL_DUMMY:
case TX_RFPLL_DUMMY:
ad9361_rfpll_dummy_set_rate(clk_priv, rate);
break;
case TX_RFPLL:
case RX_RFPLL:
round_rate = ad9361_rfpll_round_rate(clk_priv, rate);
ad9361_rfpll_set_rate(clk_priv, round_rate);
phy->clks[source]->rate = ad9361_rfpll_recalc_rate(clk_priv);
break;
case BBPLL_CLK:
round_rate = ad9361_bbpll_round_rate(clk_priv, rate,
&phy->clks[clk_priv->parent_source]->rate);
ad9361_bbpll_set_rate(clk_priv, round_rate,
phy->clks[clk_priv->parent_source]->rate);
phy->clks[source]->rate = ad9361_bbpll_recalc_rate(clk_priv,
phy->clks[clk_priv->parent_source]->rate);
phy->bbpll_initialized = true;
break;
case ADC_CLK:
case R2_CLK:
case R1_CLK:
case CLKRF_CLK:
case RX_SAMPL_CLK:
case DAC_CLK:
case T2_CLK:
case T1_CLK:
case CLKTF_CLK:
case TX_SAMPL_CLK:
round_rate = ad9361_clk_factor_round_rate(clk_priv, rate,
&phy->clks[clk_priv->parent_source]->rate);
ad9361_clk_factor_set_rate(clk_priv, round_rate,
phy->clks[clk_priv->parent_source]->rate);
phy->clks[source]->rate = ad9361_clk_factor_recalc_rate(clk_priv,
phy->clks[clk_priv->parent_source]->rate);
break;
default:
break;
}
//以下省略
}
//以下省略
return 0;
}
收发链路上的时钟处理相关函数的调用关系
AGC
#define REG_AGC_LOCK_LEVEL 0x101 /* AGC Lock Level */
#define REG_ADC_NOISE_CORRECTION_FACTOR 0x102 /* ADC noise Correction Factor */
#define REG_GAIN_STP_CONFIG1 0x103 /* Gain Step Config1 */
#define REG_ADC_SMALL_OVERLOAD_THRESH 0x104 /* ADC Small Overload Threshold */
#define REG_ADC_LARGE_OVERLOAD_THRESH 0x105 /* ADC Large Overload Threshold */
#define REG_GAIN_TABLE_ADDRESS 0x130 /* Gain Table Address */
#define REG_GAIN_TABLE_WRITE_DATA1 0x131 /* Gain Table Write Data1 */
#define REG_GAIN_TABLE_WRITE_DATA2 0x132 /* Gain Table Write Data2 */
#define REG_GAIN_TABLE_WRITE_DATA3 0x133 /* Gain Table Write Data 3 */
#define REG_GAIN_TABLE_READ_DATA1 0x134 /* Gain Table Read Data 1 */
#define REG_GAIN_TABLE_READ_DATA2 0x135 /* Gain Table Read Data 2 */
#define REG_GAIN_TABLE_READ_DATA3 0x136 /* Gain Table Read Data 3 */
#define REG_GAIN_TABLE_CONFIG 0x137 /* Gain Table Config */
#define REG_GM_SUB_TABLE_ADDRESS 0x138 /* Gm Sub Table Address */
#define REG_GM_SUB_TABLE_GAIN_WRITE 0x139 /* Gm Sub Table Gain Word Write */
#define REG_GM_SUB_TABLE_BIAS_WRITE 0x13A /* Gm Sub Table Bias Word Write */
#define REG_GM_SUB_TABLE_CTRL_WRITE 0x13B /* Gm Sub Table Control Word Write */
#define REG_GM_SUB_TABLE_GAIN_READ 0x13C /* Gm Sub Table Gain Word Read */
#define REG_GM_SUB_TABLE_BIAS_READ 0x13D /* Gm Sub Table Bias Word Read */
#define REG_GM_SUB_TABLE_CTRL_READ 0x13E /* Gm Sub Table Control Word Read */
#define REG_GM_SUB_TABLE_CONFIG 0x13F /* Gm Sub Table Config */
开FIR可能会影响时序
RX接收数据解析
hdl-2016-r2版本
hdl-2018-r1版本
hdl-2019-r2版本
要注意,
- 2016-r2和2018-r1的lvds_if里,解数据的方式不一样,IDDR的使用方式也不一样
- 2018-r1和2019-r2的lvds_if里,解数据的方式不一样
其他
FDD
Frequency division duplex in which transmit and receive signals can be present at the same time but use different frequencies.
是不是意味着同时进行收发的时候,收发频率不能相同?
AD9361上电后进入休眠模式(为了降低功耗),在AD9361能正常运行之前,它的时钟必须已经使能且初始化校正完成。
ADI官方论坛网友提供的AD9361初始化