本文整理汇总了C++中freq_range_t::clip方法的典型用法代码示例。如果您正苦于以下问题:C++ freq_range_t::clip方法的具体用法?C++ freq_range_t::clip怎么用?C++ freq_range_t::clip使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类freq_range_t
的用法示例。
在下文中一共展示了freq_range_t::clip方法的10个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: set_bandwidth
/***********************************************************************
* Bandwidth Handling
**********************************************************************/
double dbsrx::set_bandwidth(double bandwidth){
//convert complex bandpass to lowpass bandwidth
bandwidth = bandwidth/2.0;
//clip the input
bandwidth = dbsrx_bandwidth_range.clip(bandwidth);
double ref_clock = this->get_iface()->get_clock_rate(dboard_iface::UNIT_RX);
//NOTE: _max2118_write_regs.m_divider set in set_lo_freq
//compute f_dac setting
_max2118_write_regs.f_dac = uhd::clip<int>(int((((bandwidth*_max2118_write_regs.m_divider)/ref_clock) - 4)/0.145),0,127);
//determine actual bandwidth
_bandwidth = double((ref_clock/(_max2118_write_regs.m_divider))*(4+0.145*_max2118_write_regs.f_dac));
UHD_LOGV(often) << boost::format(
"DBSRX Filter Bandwidth: %f MHz, m: %d, f_dac: %d\n"
) % (_bandwidth/1e6) % int(_max2118_write_regs.m_divider) % int(_max2118_write_regs.f_dac) << std::endl;
this->send_reg(0x3, 0x4);
//convert lowpass back to complex bandpass bandwidth
return 2.0*_bandwidth;
}
示例2:
/***********************************************************************
* Tuning
**********************************************************************/
double wbx_base::wbx_version3::set_lo_freq(dboard_iface::unit_t unit, double target_freq) {
//clip to tuning range
target_freq = wbx_v3_freq_range.clip(target_freq);
UHD_LOGGER_TRACE("WBX") << boost::format(
"WBX tune: target frequency %f MHz"
) % (target_freq/1e6) ;
/*
* If the user sets 'mode_n=integer' in the tuning args, the user wishes to
* tune in Integer-N mode, which can result in better spur
* performance on some mixers. The default is fractional tuning.
*/
property_tree::sptr subtree = (unit == dboard_iface::UNIT_RX) ? self_base->get_rx_subtree()
: self_base->get_tx_subtree();
device_addr_t tune_args = subtree->access<device_addr_t>("tune_args").get();
bool is_int_n = boost::iequals(tune_args.get("mode_n",""), "integer");
double reference_freq = self_base->get_iface()->get_clock_rate(unit);
//Select the LO
adf435x_iface::sptr& lo_iface = unit == dboard_iface::UNIT_RX ? _rxlo : _txlo;
lo_iface->set_reference_freq(reference_freq);
//The mixer has a divide-by-2 stage on the LO port so the synthesizer
//frequency must 2x the target frequency
double synth_target_freq = target_freq * 2;
//Use 8/9 prescaler for vco_freq > 3 GHz (pg.18 prescaler)
lo_iface->set_prescaler(synth_target_freq > 3e9 ?
adf435x_iface::PRESCALER_8_9 : adf435x_iface::PRESCALER_4_5);
//The feedback of the divided frequency must be disabled whenever the target frequency
//divided by the minimum PFD frequency cannot meet the minimum integer divider (N) value.
//If it is disabled, additional phase ambiguity will be introduced. With a minimum PFD
//frequency of 10 MHz, synthesizer frequencies below 230 MHz (LO frequencies below 115 MHz)
//will have too much ambiguity to synchronize.
lo_iface->set_feedback_select(
(int(synth_target_freq / 10e6) >= lo_iface->get_int_range().start() ?
adf435x_iface::FB_SEL_DIVIDED : adf435x_iface::FB_SEL_FUNDAMENTAL));
double synth_actual_freq = lo_iface->set_frequency(synth_target_freq, is_int_n);
//The mixer has a divide-by-2 stage on the LO port so the synthesizer
//actual_freq must /2 the synth_actual_freq
double actual_freq = synth_actual_freq / 2;
if (unit == dboard_iface::UNIT_RX) {
lo_iface->set_output_power((actual_freq == wbx_rx_lo_5dbm.clip(actual_freq)) ?
adf435x_iface::OUTPUT_POWER_5DBM : adf435x_iface::OUTPUT_POWER_2DBM);
} else {
lo_iface->set_output_power((actual_freq == wbx_tx_lo_5dbm.clip(actual_freq)) ?
adf435x_iface::OUTPUT_POWER_5DBM : adf435x_iface::OUTPUT_POWER_M1DBM);
}
//Write to hardware
lo_iface->commit();
return actual_freq;
}
示例3:
/***********************************************************************
* Tuning
**********************************************************************/
double wbx_base::wbx_version3::set_lo_freq(dboard_iface::unit_t unit, double target_freq) {
//clip to tuning range
target_freq = wbx_v3_freq_range.clip(target_freq);
UHD_LOGV(often) << boost::format(
"WBX tune: target frequency %f MHz"
) % (target_freq/1e6) << std::endl;
/*
* If the user sets 'mode_n=integer' in the tuning args, the user wishes to
* tune in Integer-N mode, which can result in better spur
* performance on some mixers. The default is fractional tuning.
*/
property_tree::sptr subtree = (unit == dboard_iface::UNIT_RX) ? self_base->get_rx_subtree()
: self_base->get_tx_subtree();
device_addr_t tune_args = subtree->access<device_addr_t>("tune_args").get();
bool is_int_n = boost::iequals(tune_args.get("mode_n",""), "integer");
double reference_freq = self_base->get_iface()->get_clock_rate(unit);
//Select the LO
adf435x_iface::sptr& lo_iface = unit == dboard_iface::UNIT_RX ? _rxlo : _txlo;
lo_iface->set_reference_freq(reference_freq);
//The mixer has a divide-by-2 stage on the LO port so the synthesizer
//frequency must 2x the target frequency
double synth_target_freq = target_freq * 2;
//Use 8/9 prescaler for vco_freq > 3 GHz (pg.18 prescaler)
lo_iface->set_prescaler(synth_target_freq > 3e9 ?
adf435x_iface::PRESCALER_8_9 : adf435x_iface::PRESCALER_4_5);
//When divider resync is enabled, a 180 deg phase error is introduced when syncing
//multiple WBX boards. Switching to fundamental mode works arounds this issue.
//TODO: Document why the following has to be true
lo_iface->set_feedback_select((target_freq > reference_freq) ?
adf435x_iface::FB_SEL_DIVIDED : adf435x_iface::FB_SEL_FUNDAMENTAL);
double synth_actual_freq = lo_iface->set_frequency(synth_target_freq, is_int_n);
//The mixer has a divide-by-2 stage on the LO port so the synthesizer
//actual_freq must /2 the synth_actual_freq
double actual_freq = synth_actual_freq / 2;
if (unit == dboard_iface::UNIT_RX) {
lo_iface->set_output_power((actual_freq == wbx_rx_lo_5dbm.clip(actual_freq)) ?
adf435x_iface::OUTPUT_POWER_5DBM : adf435x_iface::OUTPUT_POWER_2DBM);
} else {
lo_iface->set_output_power((actual_freq == wbx_tx_lo_5dbm.clip(actual_freq)) ?
adf435x_iface::OUTPUT_POWER_5DBM : adf435x_iface::OUTPUT_POWER_M1DBM);
}
//Write to hardware
lo_iface->commit();
return actual_freq;
}
示例4: update_atr
/***********************************************************************
* Antenna Handling
**********************************************************************/
void sbx_xcvr::update_atr(void){
//calculate atr pins
int rx_pga0_iobits = rx_pga0_gain_to_iobits(_rx_gains["PGA0"]);
int tx_pga0_iobits = tx_pga0_gain_to_iobits(_tx_gains["PGA0"]);
int rx_lo_lpf_en = (_rx_lo_freq == sbx_enable_rx_lo_filter.clip(_rx_lo_freq)) ? LO_LPF_EN : 0;
int tx_lo_lpf_en = (_tx_lo_freq == sbx_enable_tx_lo_filter.clip(_tx_lo_freq)) ? LO_LPF_EN : 0;
int rx_ld_led = get_locked(dboard_iface::UNIT_RX) ? 0 : RX_LED_LD;
int tx_ld_led = get_locked(dboard_iface::UNIT_TX) ? 0 : TX_LED_LD;
int rx_ant_led = _rx_ant == "TX/RX" ? RX_LED_RX1RX2 : 0;
int tx_ant_led = _rx_ant == "TX/RX" ? 0 : TX_LED_TXRX;
//setup the tx atr (this does not change with antenna)
this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_IDLE,
tx_pga0_iobits | tx_lo_lpf_en | tx_ld_led | tx_ant_led | TX_POWER_UP | ANT_XX | TX_MIXER_DIS);
this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_TX_ONLY,
tx_pga0_iobits | tx_lo_lpf_en | tx_ld_led | tx_ant_led | TX_POWER_UP | ANT_TX | TX_MIXER_ENB);
this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_FULL_DUPLEX,
tx_pga0_iobits | tx_lo_lpf_en | tx_ld_led | tx_ant_led | TX_POWER_UP | ANT_TX | TX_MIXER_ENB);
//setup the rx atr (this does not change with antenna)
this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_IDLE,
rx_pga0_iobits | rx_lo_lpf_en | rx_ld_led | rx_ant_led | RX_POWER_UP | ANT_XX | RX_MIXER_DIS);
this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_TX_ONLY,
rx_pga0_iobits | rx_lo_lpf_en | rx_ld_led | rx_ant_led | RX_POWER_UP | ANT_RX2 | RX_MIXER_DIS);
this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX,
rx_pga0_iobits | rx_lo_lpf_en | rx_ld_led | rx_ant_led | RX_POWER_UP | ANT_RX2 | RX_MIXER_ENB);
//set the atr regs that change with antenna setting
this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_RX_ONLY,
tx_pga0_iobits | tx_lo_lpf_en | tx_ld_led | tx_ant_led | TX_POWER_UP | TX_MIXER_DIS |
((_rx_ant == "TX/RX")? ANT_RX : ANT_TX));
this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_RX_ONLY,
rx_pga0_iobits | rx_lo_lpf_en | rx_ld_led | rx_ant_led | RX_POWER_UP | RX_MIXER_ENB |
((_rx_ant == "TX/RX")? ANT_TXRX : ANT_RX2));
UHD_LOGV(often) << boost::format(
"SBX RXONLY ATR REG: 0x%08x"
) % (rx_pga0_iobits | RX_POWER_UP | RX_MIXER_ENB | ((_rx_ant == "TX/RX")? ANT_TXRX : ANT_RX2)) << std::endl;
}
示例5: set_freq
double tvrx::set_freq(double freq) {
freq = tvrx_freq_range.clip(freq);
std::string prev_band = get_band(_lo_freq - tvrx_if_freq);
std::string new_band = get_band(freq);
double target_lo_freq = freq + tvrx_if_freq; //the desired LO freq for high-side mixing
double f_ref = reference_freq / double(reference_divider); //your tuning step size
int divisor = int((target_lo_freq + (f_ref * 4.0)) / (f_ref * 8)); //the divisor we'll use
double actual_lo_freq = (f_ref * 8 * divisor); //the LO freq we'll actually get
if((divisor & ~0x7fff)) UHD_THROW_INVALID_CODE_PATH();
//now we update the registers
_tuner_4937di5_regs.db1 = (divisor >> 8) & 0xff;
_tuner_4937di5_regs.db2 = divisor & 0xff;
if(new_band == "VHFLO") _tuner_4937di5_regs.bandsel = tuner_4937di5_regs_t::BANDSEL_VHFLO;
else if(new_band == "VHFHI") _tuner_4937di5_regs.bandsel = tuner_4937di5_regs_t::BANDSEL_VHFHI;
else if(new_band == "UHF") _tuner_4937di5_regs.bandsel = tuner_4937di5_regs_t::BANDSEL_UHF;
else UHD_THROW_INVALID_CODE_PATH();
_tuner_4937di5_regs.power = tuner_4937di5_regs_t::POWER_OFF;
update_regs();
//ok don't forget to reset RF gain here if the new band != the old band
//we do this because the gains are different for different band settings
//not FAR off, but we do this to be consistent
if(prev_band != new_band) set_gain(_gains["RF"], "RF");
UHD_LOGV(often) << boost::format("set_freq: target LO: %f f_ref: %f divisor: %i actual LO: %f") % target_lo_freq % f_ref % divisor % actual_lo_freq << std::endl;
_lo_freq = actual_lo_freq; //for rx props
//Check the the IF if larger than the dsp rate and apply a corrective adjustment
//so that the cordic will be tuned to a possible rate within its range.
const double codec_rate = this->get_iface()->get_codec_rate(dboard_iface::UNIT_RX);
if (tvrx_if_freq >= codec_rate/2){
return _lo_freq - codec_rate;
}
return _lo_freq;
}
示例6: set_lo_freq
/***********************************************************************
* Tuning
**********************************************************************/
void dbsrx::set_lo_freq(double target_freq){
target_freq = dbsrx_freq_range.clip(target_freq);
double actual_freq=0.0, pfd_freq=0.0, ref_clock=0.0;
int R=0, N=0, r=0, m=0;
bool update_filter_settings = false;
//choose refclock
std::vector<double> clock_rates = this->get_iface()->get_clock_rates(dboard_iface::UNIT_RX);
const double max_clock_rate = std::sorted(clock_rates).back();
BOOST_FOREACH(ref_clock, std::reversed(std::sorted(clock_rates))){
if (ref_clock > 27.0e6) continue;
if (size_t(max_clock_rate/ref_clock)%2 == 1) continue; //reject asymmetric clocks (odd divisors)
//choose m_divider such that filter tuning constraint is met
m = 31;
while ((ref_clock/m < 1e6 or ref_clock/m > 2.5e6) and m > 0){ m--; }
if(dbsrx_debug) std::cerr << boost::format(
"DBSRX: trying ref_clock %f and m_divider %d"
) % (ref_clock) % m << std::endl;
if (m >= 32) continue;
//choose R
for(r = 0; r <= 6; r += 1) {
//compute divider from setting
R = 1 << (r+1);
if (dbsrx_debug) std::cerr << boost::format("DBSRX R:%d\n") % R << std::endl;
//compute PFD compare frequency = ref_clock/R
pfd_freq = ref_clock / R;
//constrain the PFD frequency to specified range
if ((pfd_freq < dbsrx_pfd_freq_range.start()) or (pfd_freq > dbsrx_pfd_freq_range.stop())) continue;
//compute N
N = int(std::floor(target_freq/pfd_freq));
//constrain N to specified range
if ((N < 256) or (N > 32768)) continue;
goto done_loop;
}
}
done_loop:
//Assert because we failed to find a suitable combination of ref_clock, R and N
UHD_ASSERT_THROW(ref_clock <= 27.0e6 and ref_clock >= 0.0);
UHD_ASSERT_THROW(ref_clock/m >= 1e6 and ref_clock/m <= 2.5e6);
UHD_ASSERT_THROW((pfd_freq >= dbsrx_pfd_freq_range.start()) and (pfd_freq <= dbsrx_pfd_freq_range.stop()));
UHD_ASSERT_THROW((N >= 256) and (N <= 32768));
if(dbsrx_debug) std::cerr << boost::format(
"DBSRX: choose ref_clock (current: %f, new: %f) and m_divider %d"
) % (this->get_iface()->get_clock_rate(dboard_iface::UNIT_RX)) % ref_clock % m << std::endl;
//if ref_clock or m divider changed, we need to update the filter settings
if (ref_clock != this->get_iface()->get_clock_rate(dboard_iface::UNIT_RX) or m != _max2118_write_regs.m_divider) update_filter_settings = true;
//compute resulting output frequency
actual_freq = pfd_freq * N;
//apply ref_clock, R, and N settings
this->get_iface()->set_clock_rate(dboard_iface::UNIT_RX, ref_clock);
ref_clock = this->get_iface()->get_clock_rate(dboard_iface::UNIT_RX);
_max2118_write_regs.m_divider = m;
_max2118_write_regs.r_divider = (max2118_write_regs_t::r_divider_t) r;
_max2118_write_regs.set_n_divider(N);
_max2118_write_regs.ade_vco_ade_read = max2118_write_regs_t::ADE_VCO_ADE_READ_ENABLED;
//compute prescaler variables
int scaler = actual_freq > 1125e6 ? 2 : 4;
_max2118_write_regs.div2 = scaler == 4 ? max2118_write_regs_t::DIV2_DIV4 : max2118_write_regs_t::DIV2_DIV2;
if(dbsrx_debug) std::cerr << boost::format(
"DBSRX: scaler %d, actual_freq %f MHz, register bit: %d"
) % scaler % (actual_freq/1e6) % int(_max2118_write_regs.div2) << std::endl;
//compute vco frequency and select vco
double vco_freq = actual_freq * scaler;
if (vco_freq < 2433e6)
_max2118_write_regs.osc_band = 0;
else if (vco_freq < 2711e6)
_max2118_write_regs.osc_band = 1;
else if (vco_freq < 3025e6)
_max2118_write_regs.osc_band = 2;
else if (vco_freq < 3341e6)
_max2118_write_regs.osc_band = 3;
else if (vco_freq < 3727e6)
_max2118_write_regs.osc_band = 4;
else if (vco_freq < 4143e6)
_max2118_write_regs.osc_band = 5;
else if (vco_freq < 4493e6)
_max2118_write_regs.osc_band = 6;
else
_max2118_write_regs.osc_band = 7;
//.........这里部分代码省略.........
示例7: set_tx_lo_freq
void wbx_simple::set_tx_lo_freq(double freq){
_tx_lo_freq = set_lo_freq(dboard_iface::UNIT_TX, wbx_freq_range.clip(freq));
}
示例8: set_lo_freq
/***********************************************************************
* Tuning
**********************************************************************/
double rfx_xcvr::set_lo_freq(
dboard_iface::unit_t unit,
double target_freq
){
UHD_LOGGER_TRACE("RFX") << boost::format(
"RFX tune: target frequency %f MHz"
) % (target_freq/1e6) ;
//clip the input
target_freq = _freq_range.clip(target_freq);
if (_div2[unit]) target_freq *= 2;
//rfx400 rx is a special case with div2 in mixer, so adf4360 must output fundamental
bool is_rx_rfx400 = ((get_rx_id() == 0x0024) && unit != dboard_iface::UNIT_TX);
//map prescalers to the register enums
static const uhd::dict<int, adf4360_regs_t::prescaler_value_t> prescaler_to_enum = map_list_of
(8, adf4360_regs_t::PRESCALER_VALUE_8_9)
(16, adf4360_regs_t::PRESCALER_VALUE_16_17)
(32, adf4360_regs_t::PRESCALER_VALUE_32_33)
;
//map band select clock dividers to enums
static const uhd::dict<int, adf4360_regs_t::band_select_clock_div_t> bandsel_to_enum = map_list_of
(1, adf4360_regs_t::BAND_SELECT_CLOCK_DIV_1)
(2, adf4360_regs_t::BAND_SELECT_CLOCK_DIV_2)
(4, adf4360_regs_t::BAND_SELECT_CLOCK_DIV_4)
(8, adf4360_regs_t::BAND_SELECT_CLOCK_DIV_8)
;
double actual_freq=0, ref_freq = this->get_iface()->get_clock_rate(unit);
int R=0, BS=0, P=0, B=0, A=0;
/*
* The goal here to to loop though possible R dividers,
* band select clock dividers, and prescaler values.
* Calculate the A and B counters for each set of values.
* The loop exits when it meets all of the constraints.
* The resulting loop values are loaded into the registers.
*
* fvco = [P*B + A] * fref/R
* fvco*R/fref = P*B + A = N
*/
for(R = 2; R <= 32; R+=2){
for(auto BS: bandsel_to_enum.keys()){
if (ref_freq/R/BS > 1e6) continue; //constraint on band select clock
for(auto P: prescaler_to_enum.keys()){
//calculate B and A from N
double N = target_freq*R/ref_freq;
B = int(std::floor(N/P));
A = boost::math::iround(N - P*B);
if (B < A or B > 8191 or B < 3 or A > 31) continue; //constraints on A, B
//calculate the actual frequency
actual_freq = double(P*B + A)*ref_freq/R;
if (actual_freq/P > 300e6) continue; //constraint on prescaler output
//constraints met: exit loop
goto done_loop;
}
}
} done_loop:
UHD_LOGGER_TRACE("RFX") << boost::format(
"RFX tune: R=%d, BS=%d, P=%d, B=%d, A=%d, DIV2=%d"
) % R % BS % P % B % A % int(_div2[unit] && (!is_rx_rfx400)) ;
//load the register values
adf4360_regs_t regs;
regs.core_power_level = adf4360_regs_t::CORE_POWER_LEVEL_10MA;
regs.counter_operation = adf4360_regs_t::COUNTER_OPERATION_NORMAL;
regs.muxout_control = adf4360_regs_t::MUXOUT_CONTROL_DLD;
regs.phase_detector_polarity = adf4360_regs_t::PHASE_DETECTOR_POLARITY_POS;
regs.charge_pump_output = adf4360_regs_t::CHARGE_PUMP_OUTPUT_NORMAL;
regs.cp_gain_0 = adf4360_regs_t::CP_GAIN_0_SET1;
regs.mute_till_ld = adf4360_regs_t::MUTE_TILL_LD_ENB;
regs.output_power_level = adf4360_regs_t::OUTPUT_POWER_LEVEL_3_5MA;
regs.current_setting1 = adf4360_regs_t::CURRENT_SETTING1_0_31MA;
regs.current_setting2 = adf4360_regs_t::CURRENT_SETTING2_0_31MA;
regs.power_down = adf4360_regs_t::POWER_DOWN_NORMAL_OP;
regs.prescaler_value = prescaler_to_enum[P];
regs.a_counter = A;
regs.b_counter = B;
regs.cp_gain_1 = adf4360_regs_t::CP_GAIN_1_SET1;
regs.divide_by_2_output = (_div2[unit] && (!is_rx_rfx400)) ? // Special case RFX400 RX Mixer divides by two
adf4360_regs_t::DIVIDE_BY_2_OUTPUT_DIV2 :
adf4360_regs_t::DIVIDE_BY_2_OUTPUT_FUND ;
regs.divide_by_2_prescaler = adf4360_regs_t::DIVIDE_BY_2_PRESCALER_FUND;
regs.r_counter = R;
regs.ablpw = adf4360_regs_t::ABLPW_3_0NS;
regs.lock_detect_precision = adf4360_regs_t::LOCK_DETECT_PRECISION_5CYCLES;
regs.test_mode_bit = 0;
regs.band_select_clock_div = bandsel_to_enum[BS];
//write the registers
std::vector<adf4360_regs_t::addr_t> addrs = list_of //correct power-up sequence to write registers (R, C, N)
(adf4360_regs_t::ADDR_RCOUNTER)
(adf4360_regs_t::ADDR_CONTROL)
(adf4360_regs_t::ADDR_NCOUNTER)
//.........这里部分代码省略.........
示例9: Reg
/***********************************************************************
* Tuning
**********************************************************************/
double wbx_base::wbx_version4::set_lo_freq(dboard_iface::unit_t unit, double target_freq) {
//clip to tuning range
target_freq = wbx_v4_freq_range.clip(target_freq);
UHD_LOGV(often) << boost::format(
"WBX tune: target frequency %f Mhz"
) % (target_freq/1e6) << std::endl;
/*
* If the user sets 'mode_n=integer' in the tuning args, the user wishes to
* tune in Integer-N mode, which can result in better spur
* performance on some mixers. The default is fractional tuning.
*/
property_tree::sptr subtree = (unit == dboard_iface::UNIT_RX) ? self_base->get_rx_subtree()
: self_base->get_tx_subtree();
device_addr_t tune_args = subtree->access<device_addr_t>("tune_args").get();
bool is_int_n = boost::iequals(tune_args.get("mode_n",""), "integer");
//map prescaler setting to mininmum integer divider (N) values (pg.18 prescaler)
static const uhd::dict<int, int> prescaler_to_min_int_div = map_list_of
(0,23) //adf4351_regs_t::PRESCALER_4_5
(1,75) //adf4351_regs_t::PRESCALER_8_9
;
//map rf divider select output dividers to enums
static const uhd::dict<int, adf4351_regs_t::rf_divider_select_t> rfdivsel_to_enum = map_list_of
(1, adf4351_regs_t::RF_DIVIDER_SELECT_DIV1)
(2, adf4351_regs_t::RF_DIVIDER_SELECT_DIV2)
(4, adf4351_regs_t::RF_DIVIDER_SELECT_DIV4)
(8, adf4351_regs_t::RF_DIVIDER_SELECT_DIV8)
(16, adf4351_regs_t::RF_DIVIDER_SELECT_DIV16)
(32, adf4351_regs_t::RF_DIVIDER_SELECT_DIV32)
(64, adf4351_regs_t::RF_DIVIDER_SELECT_DIV64)
;
double reference_freq = self_base->get_iface()->get_clock_rate(unit);
//The mixer has a divide-by-2 stage on the LO port so the synthesizer
//frequency must 2x the target frequency
double synth_target_freq = target_freq * 2;
//TODO: Document why the following has to be true
bool div_resync_enabled = (target_freq > reference_freq);
adf4351_regs_t::prescaler_t prescaler =
synth_target_freq > 3e9 ? adf4351_regs_t::PRESCALER_8_9 : adf4351_regs_t::PRESCALER_4_5;
adf435x_tuning_constraints tuning_constraints;
tuning_constraints.force_frac0 = is_int_n;
tuning_constraints.band_sel_freq_max = 100e3;
tuning_constraints.ref_doubler_threshold = 12.5e6;
tuning_constraints.int_range = uhd::range_t(prescaler_to_min_int_div[prescaler], 4095);
tuning_constraints.pfd_freq_max = 25e6;
tuning_constraints.rf_divider_range = uhd::range_t(1, 64);
//When divider resync is enabled, a 180 deg phase error is introduced when syncing
//multiple WBX boards. Switching to fundamental mode works arounds this issue.
tuning_constraints.feedback_after_divider = div_resync_enabled;
double synth_actual_freq = 0;
adf435x_tuning_settings tuning_settings = tune_adf435x_synth(
synth_target_freq, reference_freq, tuning_constraints, synth_actual_freq);
//The mixer has a divide-by-2 stage on the LO port so the synthesizer
//actual_freq must /2 the synth_actual_freq
double actual_freq = synth_actual_freq / 2;
//load the register values
adf4351_regs_t regs;
if (unit == dboard_iface::UNIT_RX)
regs.output_power = (actual_freq == wbx_rx_lo_5dbm.clip(actual_freq)) ? adf4351_regs_t::OUTPUT_POWER_5DBM
: adf4351_regs_t::OUTPUT_POWER_2DBM;
else
regs.output_power = (actual_freq == wbx_tx_lo_5dbm.clip(actual_freq)) ? adf4351_regs_t::OUTPUT_POWER_5DBM
: adf4351_regs_t::OUTPUT_POWER_M1DBM;
regs.frac_12_bit = tuning_settings.frac_12_bit;
regs.int_16_bit = tuning_settings.int_16_bit;
regs.mod_12_bit = tuning_settings.mod_12_bit;
regs.clock_divider_12_bit = tuning_settings.clock_divider_12_bit;
regs.feedback_select = tuning_constraints.feedback_after_divider ?
adf4351_regs_t::FEEDBACK_SELECT_DIVIDED :
adf4351_regs_t::FEEDBACK_SELECT_FUNDAMENTAL;
regs.clock_div_mode = div_resync_enabled ?
adf4351_regs_t::CLOCK_DIV_MODE_RESYNC_ENABLE :
adf4351_regs_t::CLOCK_DIV_MODE_FAST_LOCK;
regs.prescaler = prescaler;
regs.r_counter_10_bit = tuning_settings.r_counter_10_bit;
regs.reference_divide_by_2 = tuning_settings.r_divide_by_2_en ?
adf4351_regs_t::REFERENCE_DIVIDE_BY_2_ENABLED :
adf4351_regs_t::REFERENCE_DIVIDE_BY_2_DISABLED;
regs.reference_doubler = tuning_settings.r_doubler_en ?
adf4351_regs_t::REFERENCE_DOUBLER_ENABLED :
adf4351_regs_t::REFERENCE_DOUBLER_DISABLED;
regs.band_select_clock_div = tuning_settings.band_select_clock_div;
UHD_ASSERT_THROW(rfdivsel_to_enum.has_key(tuning_settings.rf_divider));
regs.rf_divider_select = rfdivsel_to_enum[tuning_settings.rf_divider];
regs.ldf = is_int_n ?
adf4351_regs_t::LDF_INT_N :
//.........这里部分代码省略.........
示例10: while
/***********************************************************************
* Tuning
**********************************************************************/
double wbx_base::wbx_version2::set_lo_freq(dboard_iface::unit_t unit, double target_freq) {
//clip to tuning range
target_freq = wbx_v2_freq_range.clip(target_freq);
UHD_LOGV(often) << boost::format(
"WBX tune: target frequency %f Mhz"
) % (target_freq/1e6) << std::endl;
//map prescaler setting to mininmum integer divider (N) values (pg.18 prescaler)
static const uhd::dict<int, int> prescaler_to_min_int_div = map_list_of
(0,23) //adf4350_regs_t::PRESCALER_4_5
(1,75) //adf4350_regs_t::PRESCALER_8_9
;
//map rf divider select output dividers to enums
static const uhd::dict<int, adf4350_regs_t::rf_divider_select_t> rfdivsel_to_enum = map_list_of
(1, adf4350_regs_t::RF_DIVIDER_SELECT_DIV1)
(2, adf4350_regs_t::RF_DIVIDER_SELECT_DIV2)
(4, adf4350_regs_t::RF_DIVIDER_SELECT_DIV4)
(8, adf4350_regs_t::RF_DIVIDER_SELECT_DIV8)
(16, adf4350_regs_t::RF_DIVIDER_SELECT_DIV16)
;
double actual_freq, pfd_freq;
double ref_freq = self_base->get_iface()->get_clock_rate(unit);
int R=0, BS=0, N=0, FRAC=0, MOD=0;
int RFdiv = 1;
adf4350_regs_t::reference_divide_by_2_t T = adf4350_regs_t::REFERENCE_DIVIDE_BY_2_DISABLED;
adf4350_regs_t::reference_doubler_t D = adf4350_regs_t::REFERENCE_DOUBLER_DISABLED;
//Reference doubler for 50% duty cycle
// if ref_freq < 12.5MHz enable regs.reference_divide_by_2
if(ref_freq <= 12.5e6) D = adf4350_regs_t::REFERENCE_DOUBLER_ENABLED;
//increase RF divider until acceptable VCO frequency
//start with target_freq*2 because mixer has divide by 2
double vco_freq = target_freq*2;
while (vco_freq < 2.2e9) {
vco_freq *= 2;
RFdiv *= 2;
}
//use 8/9 prescaler for vco_freq > 3 GHz (pg.18 prescaler)
adf4350_regs_t::prescaler_t prescaler = vco_freq > 3e9 ? adf4350_regs_t::PRESCALER_8_9 : adf4350_regs_t::PRESCALER_4_5;
/*
* The goal here is to loop though possible R dividers,
* band select clock dividers, N (int) dividers, and FRAC
* (frac) dividers.
*
* Calculate the N and F dividers for each set of values.
* The loop exists when it meets all of the constraints.
* The resulting loop values are loaded into the registers.
*
* from pg.21
*
* f_pfd = f_ref*(1+D)/(R*(1+T))
* f_vco = (N + (FRAC/MOD))*f_pfd
* N = f_vco/f_pfd - FRAC/MOD = f_vco*((R*(T+1))/(f_ref*(1+D))) - FRAC/MOD
* f_rf = f_vco/RFdiv)
* f_actual = f_rf/2
*/
for(R = 1; R <= 1023; R+=1){
//PFD input frequency = f_ref/R ... ignoring Reference doubler/divide-by-2 (D & T)
pfd_freq = ref_freq*(1+D)/(R*(1+T));
//keep the PFD frequency at or below 25MHz (Loop Filter Bandwidth)
if (pfd_freq > 25e6) continue;
//ignore fractional part of tuning
N = int(std::floor(vco_freq/pfd_freq));
//keep N > minimum int divider requirement
if (N < prescaler_to_min_int_div[prescaler]) continue;
for(BS=1; BS <= 255; BS+=1){
//keep the band select frequency at or below 100KHz
//constraint on band select clock
if (pfd_freq/BS > 100e3) continue;
goto done_loop;
}
} done_loop:
//Fractional-N calculation
MOD = 4095; //max fractional accuracy
FRAC = int((vco_freq/pfd_freq - N)*MOD);
//Reference divide-by-2 for 50% duty cycle
// if R even, move one divide by 2 to to regs.reference_divide_by_2
if(R % 2 == 0){
T = adf4350_regs_t::REFERENCE_DIVIDE_BY_2_ENABLED;
R /= 2;
}
//actual frequency calculation
actual_freq = double((N + (double(FRAC)/double(MOD)))*ref_freq*(1+int(D))/(R*(1+int(T)))/RFdiv/2);
//.........这里部分代码省略.........