diff options
| -rw-r--r-- | host/examples/rx_samples_to_file.cpp | 4 | ||||
| -rw-r--r-- | host/lib/usrp/b100/b100_impl.cpp | 6 | ||||
| -rw-r--r-- | host/lib/usrp/dboard/db_dbsrx2.cpp | 6 | ||||
| -rw-r--r-- | host/lib/usrp/dboard/db_sbx_common.cpp | 132 | ||||
| -rw-r--r-- | host/lib/usrp/dboard/db_sbx_common.hpp | 28 | ||||
| -rw-r--r-- | host/lib/usrp/dboard/db_sbx_version3.cpp | 118 | ||||
| -rw-r--r-- | host/lib/usrp/dboard/db_sbx_version4.cpp | 120 | ||||
| -rw-r--r-- | host/lib/usrp/usrp1/usrp1_impl.cpp | 8 | ||||
| -rw-r--r-- | host/lib/utils/paths.cpp | 22 | ||||
| -rw-r--r-- | host/utils/uhd_images_downloader.py.in | 63 | ||||
| -rw-r--r-- | host/utils/usrp_burn_mb_eeprom.cpp | 43 | 
11 files changed, 321 insertions, 229 deletions
diff --git a/host/examples/rx_samples_to_file.cpp b/host/examples/rx_samples_to_file.cpp index b0e498125..a28d1d628 100644 --- a/host/examples/rx_samples_to_file.cpp +++ b/host/examples/rx_samples_to_file.cpp @@ -236,8 +236,8 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){          ("ref", po::value<std::string>(&ref)->default_value("internal"), "waveform type (internal, external, mimo)")          ("wirefmt", po::value<std::string>(&wirefmt)->default_value("sc16"), "wire format (sc8 or sc16)")          ("setup", po::value<double>(&setup_time)->default_value(1.0), "seconds of setup time") -        ("progress", "show average bandwidth on exit") -        ("stats", "periodically display short-term bandwidth") +        ("progress", "periodically display short-term bandwidth") +        ("stats", "show average bandwidth on exit")          ("sizemap", "track packet size and display breakdown on exit")          ("null", "run without writing to file")          ("continue", "don't abort on a bad packet") diff --git a/host/lib/usrp/b100/b100_impl.cpp b/host/lib/usrp/b100/b100_impl.cpp index 19df3d6af..305ba42a7 100644 --- a/host/lib/usrp/b100/b100_impl.cpp +++ b/host/lib/usrp/b100/b100_impl.cpp @@ -310,12 +310,14 @@ b100_impl::b100_impl(const device_addr_t &device_addr){      _tree->create<std::string>(rx_codec_path / "name").set("ad9522");      _tree->create<meta_range_t>(rx_codec_path / "gains/pga/range").set(b100_codec_ctrl::rx_pga_gain_range);      _tree->create<double>(rx_codec_path / "gains/pga/value") -        .coerce(boost::bind(&b100_impl::update_rx_codec_gain, this, _1)); +        .coerce(boost::bind(&b100_impl::update_rx_codec_gain, this, _1)) +        .set(0.0);      _tree->create<std::string>(tx_codec_path / "name").set("ad9522");      _tree->create<meta_range_t>(tx_codec_path / "gains/pga/range").set(b100_codec_ctrl::tx_pga_gain_range);      _tree->create<double>(tx_codec_path / "gains/pga/value")          .subscribe(boost::bind(&b100_codec_ctrl::set_tx_pga_gain, _codec_ctrl, _1)) -        .publish(boost::bind(&b100_codec_ctrl::get_tx_pga_gain, _codec_ctrl)); +        .publish(boost::bind(&b100_codec_ctrl::get_tx_pga_gain, _codec_ctrl)) +        .set(0.0);      ////////////////////////////////////////////////////////////////////      // and do the misc mboard sensors diff --git a/host/lib/usrp/dboard/db_dbsrx2.cpp b/host/lib/usrp/dboard/db_dbsrx2.cpp index 013f3178a..8a8f61a69 100644 --- a/host/lib/usrp/dboard/db_dbsrx2.cpp +++ b/host/lib/usrp/dboard/db_dbsrx2.cpp @@ -358,12 +358,12 @@ double dbsrx2::set_gain(double gain, const std::string &name){   * Bandwidth Handling   **********************************************************************/  double dbsrx2::set_bandwidth(double bandwidth){ -    //convert complex bandpass to lowpass bandwidth -    bandwidth = bandwidth/2.0; -      //clip the input      bandwidth = dbsrx2_bandwidth_range.clip(bandwidth); +    //convert complex bandpass to lowpass bandwidth +    bandwidth = bandwidth/2.0; +      _max2112_write_regs.lp = int((bandwidth/1e6 - 4)/0.29 + 12);      _bandwidth = double(4 + (_max2112_write_regs.lp - 12) * 0.29)*1e6; diff --git a/host/lib/usrp/dboard/db_sbx_common.cpp b/host/lib/usrp/dboard/db_sbx_common.cpp index 9db29e65a..5b713c6d7 100644 --- a/host/lib/usrp/dboard/db_sbx_common.cpp +++ b/host/lib/usrp/dboard/db_sbx_common.cpp @@ -21,6 +21,137 @@ using namespace uhd;  using namespace uhd::usrp;  using namespace boost::assign; +/*********************************************************************** + * ADF 4350/4351 Tuning Utility + **********************************************************************/ +sbx_xcvr::sbx_versionx::adf435x_tuning_settings sbx_xcvr::sbx_versionx::_tune_adf435x_synth( +    double target_freq, +    double ref_freq, +    const adf435x_tuning_constraints& constraints, +    double& actual_freq) +{ +    //Default invalid value for actual_freq +    actual_freq = 0; + +    double pfd_freq = 0; +    boost::uint16_t R = 0, BS = 0, N = 0, FRAC = 0, MOD = 0; +    boost::uint16_t RFdiv = static_cast<boost::uint16_t>(constraints.rf_divider_range.start()); +    bool D = false, T = false; + +    //Reference doubler for 50% duty cycle +    //If ref_freq < 12.5MHz enable the reference doubler +    D = (ref_freq <= constraints.ref_doubler_threshold); + +    static const double MIN_VCO_FREQ = 2.2e9; +    static const double MAX_VCO_FREQ = 4.4e9; + +    //increase RF divider until acceptable VCO frequency +    double vco_freq = target_freq; +    while (vco_freq < MIN_VCO_FREQ && RFdiv < static_cast<boost::uint16_t>(constraints.rf_divider_range.stop())) { +        vco_freq *= 2; +        RFdiv *= 2; +    } + +    /* +     * 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 exits 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*(D?2:1)/(R*(T?2:1)); + +        //keep the PFD frequency at or below 25MHz (Loop Filter Bandwidth) +        if (pfd_freq > constraints.pfd_freq_max) continue; + +        //ignore fractional part of tuning +        //N is computed from target_freq and not vco_freq because the feedback +        //mode is set to FEEDBACK_SELECT_DIVIDED +        N = boost::uint16_t(std::floor(target_freq/pfd_freq)); + +        //keep N > minimum int divider requirement +        if (N < static_cast<boost::uint16_t>(constraints.int_range.start())) continue; + +        for(BS=1; BS <= 255; BS+=1){ +            //keep the band select frequency at or below band_sel_freq_max +            //constraint on band select clock +            if (pfd_freq/BS > constraints.band_sel_freq_max) continue; +            goto done_loop; +        } +    } done_loop: + +    //Fractional-N calculation +    MOD = 4095; //max fractional accuracy +    //N is computed from target_freq and not vco_freq because the feedback +    //mode is set to FEEDBACK_SELECT_DIVIDED +    FRAC = static_cast<boost::uint16_t>((target_freq/pfd_freq - N)*MOD); +    if (constraints.force_frac0) { +        if (FRAC > (MOD / 2)) { //Round integer such that actual freq is closest to target +            N++; +        } +        FRAC = 0; +    } + +    //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 = true; +        R /= 2; +    } + +    //Typical phase resync time documented in data sheet pg.24 +    static const double PHASE_RESYNC_TIME = 400e-6; + +    //actual frequency calculation +    actual_freq = double((N + (double(FRAC)/double(MOD)))*ref_freq*(D?2:1)/(R*(T?2:1))); + +    //load the settings +    adf435x_tuning_settings settings; +    settings.frac_12_bit = FRAC; +    settings.int_16_bit = N; +    settings.mod_12_bit = MOD; +    settings.clock_divider_12_bit = std::max<boost::uint16_t>(1, std::ceil(PHASE_RESYNC_TIME*pfd_freq/MOD)); +    settings.r_counter_10_bit = R; +    settings.r_divide_by_2_en = T; +    settings.r_doubler_en = D; +    settings.band_select_clock_div = BS; +    settings.rf_divider = RFdiv; +    settings.feedback_after_divider = true; + +    UHD_LOGV(often) +        << boost::format("ADF 435X Frequencies (MHz): REQUESTED=%0.9f, ACTUAL=%0.9f" +        ) % (target_freq/1e6) % (actual_freq/1e6) << std::endl +        << boost::format("ADF 435X Intermediates (MHz): VCO=%0.2f, PFD=%0.2f, BAND=%0.2f, REF=%0.2f" +        ) % (vco_freq/1e6) % (pfd_freq/1e6) % (pfd_freq/BS/1e6) % (ref_freq/1e6) << std::endl +        << boost::format("ADF 435X Settings: R=%d, BS=%d, N=%d, FRAC=%d, MOD=%d, T=%d, D=%d, RFdiv=%d" +        ) % R % BS % N % FRAC % MOD % T % D % RFdiv << std::endl; + +    UHD_ASSERT_THROW((settings.frac_12_bit          & ((boost::uint16_t)~0xFFF)) == 0); +    UHD_ASSERT_THROW((settings.mod_12_bit           & ((boost::uint16_t)~0xFFF)) == 0); +    UHD_ASSERT_THROW((settings.clock_divider_12_bit & ((boost::uint16_t)~0xFFF)) == 0); +    UHD_ASSERT_THROW((settings.r_counter_10_bit     & ((boost::uint16_t)~0x3FF)) == 0); + +    UHD_ASSERT_THROW(vco_freq >= MIN_VCO_FREQ and vco_freq <= MAX_VCO_FREQ); +    UHD_ASSERT_THROW(settings.rf_divider >= static_cast<boost::uint16_t>(constraints.rf_divider_range.start())); +    UHD_ASSERT_THROW(settings.rf_divider <= static_cast<boost::uint16_t>(constraints.rf_divider_range.stop())); +    UHD_ASSERT_THROW(settings.int_16_bit >= static_cast<boost::uint16_t>(constraints.int_range.start())); +    UHD_ASSERT_THROW(settings.int_16_bit <= static_cast<boost::uint16_t>(constraints.int_range.stop())); + +    return settings; +} +  /***********************************************************************   * Register the SBX dboard (min freq, max freq, rx div2, tx div2) @@ -362,4 +493,3 @@ void sbx_xcvr::flash_leds(void) {      this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_TX, (TXIO_MASK|TX_LED_IO));      this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, (RXIO_MASK|RX_LED_IO));  } - diff --git a/host/lib/usrp/dboard/db_sbx_common.hpp b/host/lib/usrp/dboard/db_sbx_common.hpp index 4f3a2eeaa..e9bb2434c 100644 --- a/host/lib/usrp/dboard/db_sbx_common.hpp +++ b/host/lib/usrp/dboard/db_sbx_common.hpp @@ -181,6 +181,34 @@ protected:          ~sbx_versionx(void) {}          virtual double set_lo_freq(dboard_iface::unit_t unit, double target_freq) = 0; +    protected: +        struct adf435x_tuning_constraints { +            bool            force_frac0; +            double          ref_doubler_threshold; +            double          pfd_freq_max; +            double          band_sel_freq_max; +            uhd::range_t    rf_divider_range; +            uhd::range_t    int_range; +        }; + +        struct adf435x_tuning_settings { +            boost::uint16_t frac_12_bit; +            boost::uint16_t int_16_bit; +            boost::uint16_t mod_12_bit; +            boost::uint16_t r_counter_10_bit; +            bool            r_doubler_en; +            bool            r_divide_by_2_en; +            boost::uint16_t clock_divider_12_bit; +            boost::uint8_t  band_select_clock_div; +            boost::uint16_t rf_divider; +            bool            feedback_after_divider; +        }; + +        adf435x_tuning_settings _tune_adf435x_synth( +            double target_freq, +            double ref_freq, +            const adf435x_tuning_constraints& constraints, +            double& actual_freq);      };      /*! diff --git a/host/lib/usrp/dboard/db_sbx_version3.cpp b/host/lib/usrp/dboard/db_sbx_version3.cpp index 2765d530c..b0c9cd18f 100644 --- a/host/lib/usrp/dboard/db_sbx_version3.cpp +++ b/host/lib/usrp/dboard/db_sbx_version3.cpp @@ -63,85 +63,21 @@ double sbx_xcvr::sbx_version3::set_lo_freq(dboard_iface::unit_t unit, double tar          (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 -    double vco_freq = target_freq; -    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 = target_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 exits 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(target_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((target_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)))); +    adf435x_tuning_constraints tuning_constraints; +    tuning_constraints.force_frac0 = false; +    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);  //INT is a 12-bit field +    tuning_constraints.pfd_freq_max = 25e6; +    tuning_constraints.rf_divider_range = uhd::range_t(1, 16); -    UHD_LOGV(often) -        << boost::format("SBX Intermediates: ref=%0.2f, outdiv=%f, fbdiv=%f") % (ref_freq*(1+int(D))/(R*(1+int(T)))) % double(RFdiv*2) % double(N + double(FRAC)/double(MOD)) << std::endl -        << boost::format("SBX tune: R=%d, BS=%d, N=%d, FRAC=%d, MOD=%d, T=%d, D=%d, RFdiv=%d" -            ) % R % BS % N % FRAC % MOD % T % D % RFdiv << std::endl -        << boost::format("SBX Frequencies (MHz): REQ=%0.2f, ACT=%0.2f, VCO=%0.2f, PFD=%0.2f, BAND=%0.2f" -            ) % (target_freq/1e6) % (actual_freq/1e6) % (vco_freq/1e6) % (pfd_freq/1e6) % (pfd_freq/BS/1e6) << std::endl; +    double actual_freq; +    adf435x_tuning_settings tuning_settings = _tune_adf435x_synth( +        target_freq, self_base->get_iface()->get_clock_rate(unit), +        tuning_constraints, actual_freq);      //load the register values      adf4350_regs_t regs; @@ -151,19 +87,25 @@ double sbx_xcvr::sbx_version3::set_lo_freq(dboard_iface::unit_t unit, double tar      else          regs.output_power = adf4350_regs_t::OUTPUT_POWER_5DBM; -    regs.frac_12_bit = FRAC; -    regs.int_16_bit = N; -    regs.mod_12_bit = MOD; -    regs.clock_divider_12_bit = std::max(1, int(std::ceil(400e-6*pfd_freq/MOD))); -    regs.feedback_select = adf4350_regs_t::FEEDBACK_SELECT_DIVIDED; -    regs.clock_div_mode = adf4350_regs_t::CLOCK_DIV_MODE_RESYNC_ENABLE; -    regs.prescaler = prescaler; -    regs.r_counter_10_bit = R; -    regs.reference_divide_by_2 = T; -    regs.reference_doubler = D; -    regs.band_select_clock_div = BS; -    UHD_ASSERT_THROW(rfdivsel_to_enum.has_key(RFdiv)); -    regs.rf_divider_select = rfdivsel_to_enum[RFdiv]; +    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_settings.feedback_after_divider ? +                                    adf4350_regs_t::FEEDBACK_SELECT_DIVIDED : +                                    adf4350_regs_t::FEEDBACK_SELECT_FUNDAMENTAL; +    regs.clock_div_mode         = adf4350_regs_t::CLOCK_DIV_MODE_RESYNC_ENABLE; +    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 ? +                                    adf4350_regs_t::REFERENCE_DIVIDE_BY_2_ENABLED : +                                    adf4350_regs_t::REFERENCE_DIVIDE_BY_2_DISABLED; +    regs.reference_doubler      = tuning_settings.r_doubler_en ? +                                    adf4350_regs_t::REFERENCE_DOUBLER_ENABLED : +                                    adf4350_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];      //reset the N and R counter      regs.counter_reset = adf4350_regs_t::COUNTER_RESET_ENABLED; diff --git a/host/lib/usrp/dboard/db_sbx_version4.cpp b/host/lib/usrp/dboard/db_sbx_version4.cpp index 27fd68b05..8d95b0655 100644 --- a/host/lib/usrp/dboard/db_sbx_version4.cpp +++ b/host/lib/usrp/dboard/db_sbx_version4.cpp @@ -66,85 +66,21 @@ double sbx_xcvr::sbx_version4::set_lo_freq(dboard_iface::unit_t unit, double tar          (64, adf4351_regs_t::RF_DIVIDER_SELECT_DIV64)      ; -    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; -    adf4351_regs_t::reference_divide_by_2_t T     = adf4351_regs_t::REFERENCE_DIVIDE_BY_2_DISABLED; -    adf4351_regs_t::reference_doubler_t     D     = adf4351_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 = adf4351_regs_t::REFERENCE_DOUBLER_ENABLED; - -    //increase RF divider until acceptable VCO frequency -    double vco_freq = target_freq; -    while (vco_freq < 2.2e9) { -        vco_freq *= 2; -        RFdiv *= 2; -    } -      //use 8/9 prescaler for vco_freq > 3 GHz (pg.18 prescaler) -    adf4351_regs_t::prescaler_t prescaler = target_freq > 3e9 ? adf4351_regs_t::PRESCALER_8_9 : adf4351_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 exits 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((target_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 = adf4351_regs_t::REFERENCE_DIVIDE_BY_2_ENABLED; -        R /= 2; -    } +    adf4351_regs_t::prescaler_t prescaler = target_freq > 3.6e9 ? adf4351_regs_t::PRESCALER_8_9 : adf4351_regs_t::PRESCALER_4_5; -    //actual frequency calculation -    actual_freq = double((N + (double(FRAC)/double(MOD)))*ref_freq*(1+int(D))/(R*(1+int(T)))); +    adf435x_tuning_constraints tuning_constraints; +    tuning_constraints.force_frac0 = false; +    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);  //INT is a 12-bit field +    tuning_constraints.pfd_freq_max = 25e6; +    tuning_constraints.rf_divider_range = uhd::range_t(1, 64); -    UHD_LOGV(often) -        << boost::format("SBX Intermediates: ref=%0.2f, outdiv=%f, fbdiv=%f") % (ref_freq*(1+int(D))/(R*(1+int(T)))) % double(RFdiv*2) % double(N + double(FRAC)/double(MOD)) << std::endl -        << boost::format("SBX tune: R=%d, BS=%d, N=%d, FRAC=%d, MOD=%d, T=%d, D=%d, RFdiv=%d" -            ) % R % BS % N % FRAC % MOD % T % D % RFdiv << std::endl -        << boost::format("SBX Frequencies (MHz): REQ=%0.2f, ACT=%0.2f, VCO=%0.2f, PFD=%0.2f, BAND=%0.2f" -            ) % (target_freq/1e6) % (actual_freq/1e6) % (vco_freq/1e6) % (pfd_freq/1e6) % (pfd_freq/BS/1e6) << std::endl; +    double actual_freq; +    adf435x_tuning_settings tuning_settings = _tune_adf435x_synth( +        target_freq, self_base->get_iface()->get_clock_rate(unit), +        tuning_constraints, actual_freq);      //load the register values      adf4351_regs_t regs; @@ -154,19 +90,25 @@ double sbx_xcvr::sbx_version4::set_lo_freq(dboard_iface::unit_t unit, double tar      else          regs.output_power = adf4351_regs_t::OUTPUT_POWER_5DBM; -    regs.frac_12_bit = FRAC; -    regs.int_16_bit = N; -    regs.mod_12_bit = MOD; -    regs.clock_divider_12_bit = std::max(1, int(std::ceil(400e-6*pfd_freq/MOD))); -    regs.feedback_select = adf4351_regs_t::FEEDBACK_SELECT_DIVIDED; -    regs.clock_div_mode = adf4351_regs_t::CLOCK_DIV_MODE_RESYNC_ENABLE; -    regs.prescaler = prescaler; -    regs.r_counter_10_bit = R; -    regs.reference_divide_by_2 = T; -    regs.reference_doubler = D; -    regs.band_select_clock_div = BS; -    UHD_ASSERT_THROW(rfdivsel_to_enum.has_key(RFdiv)); -    regs.rf_divider_select = rfdivsel_to_enum[RFdiv]; +    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_settings.feedback_after_divider ? +                                    adf4351_regs_t::FEEDBACK_SELECT_DIVIDED : +                                    adf4351_regs_t::FEEDBACK_SELECT_FUNDAMENTAL; +    regs.clock_div_mode         = adf4351_regs_t::CLOCK_DIV_MODE_RESYNC_ENABLE; +    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];      //reset the N and R counter      regs.counter_reset = adf4351_regs_t::COUNTER_RESET_ENABLED; diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index 253ac1d6f..625926f36 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -258,12 +258,14 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){          _tree->create<std::string>(rx_codec_path / "name").set("ad9522");          _tree->create<meta_range_t>(rx_codec_path / "gains/pga/range").set(usrp1_codec_ctrl::rx_pga_gain_range);          _tree->create<double>(rx_codec_path / "gains/pga/value") -            .coerce(boost::bind(&usrp1_impl::update_rx_codec_gain, this, db, _1)); +            .coerce(boost::bind(&usrp1_impl::update_rx_codec_gain, this, db, _1)) +            .set(0.0);          _tree->create<std::string>(tx_codec_path / "name").set("ad9522");          _tree->create<meta_range_t>(tx_codec_path / "gains/pga/range").set(usrp1_codec_ctrl::tx_pga_gain_range);          _tree->create<double>(tx_codec_path / "gains/pga/value")              .subscribe(boost::bind(&usrp1_codec_ctrl::set_tx_pga_gain, _dbc[db].codec, _1)) -            .publish(boost::bind(&usrp1_codec_ctrl::get_tx_pga_gain, _dbc[db].codec)); +            .publish(boost::bind(&usrp1_codec_ctrl::get_tx_pga_gain, _dbc[db].codec)) +            .set(0.0);      }      //////////////////////////////////////////////////////////////////// @@ -407,7 +409,7 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){          _tree->access<subdev_spec_t>(mb_path / "rx_subdev_spec").set(_rx_subdev_spec);      if (_tree->list(mb_path / "tx_dsps").size() > 0)          _tree->access<subdev_spec_t>(mb_path / "tx_subdev_spec").set(_tx_subdev_spec); -  +  }  usrp1_impl::~usrp1_impl(void){ diff --git a/host/lib/utils/paths.cpp b/host/lib/utils/paths.cpp index 53055314b..25cade693 100644 --- a/host/lib/utils/paths.cpp +++ b/host/lib/utils/paths.cpp @@ -34,8 +34,19 @@  namespace fs = boost::filesystem;  /*********************************************************************** + * Get a list of paths for an environment variable + **********************************************************************/ +static std::string get_env_var(const std::string &var_name, const std::string &def_val = ""){ +    const char *var_value_ptr = std::getenv(var_name.c_str()); +    return (var_value_ptr == NULL)? def_val : var_value_ptr; +} + +static std::vector<fs::path> get_env_paths(const std::string &var_name){ + +/***********************************************************************   * Determine the paths separator   **********************************************************************/ +  #ifdef UHD_PLATFORM_WIN32      static const std::string env_path_sep = ";";  #else @@ -46,16 +57,6 @@ namespace fs = boost::filesystem;      boost::tokenizer<boost::char_separator<char> > \      (inp, boost::char_separator<char>(env_path_sep.c_str())) -/*********************************************************************** - * Get a list of paths for an environment variable - **********************************************************************/ -static std::string get_env_var(const std::string &var_name, const std::string &def_val = ""){ -    const char *var_value_ptr = std::getenv(var_name.c_str()); -    return (var_value_ptr == NULL)? def_val : var_value_ptr; -} - -static std::vector<fs::path> get_env_paths(const std::string &var_name){ -      std::string var_value = get_env_var(var_name);      //convert to filesystem path, filter blank paths @@ -85,6 +86,7 @@ std::vector<fs::path> get_image_paths(void){  std::vector<fs::path> get_module_paths(void){      std::vector<fs::path> paths = get_env_paths("UHD_MODULE_PATH");      paths.push_back(fs::path(uhd::get_pkg_path()) / UHD_LIB_DIR / "uhd" / "modules"); +    paths.push_back(fs::path(uhd::get_pkg_path()) / "share" / "uhd" / "modules");      return paths;  } diff --git a/host/utils/uhd_images_downloader.py.in b/host/utils/uhd_images_downloader.py.in index e7fc9e8a5..bb082190c 100644 --- a/host/utils/uhd_images_downloader.py.in +++ b/host/utils/uhd_images_downloader.py.in @@ -44,13 +44,25 @@ class temp_dir():          self.name = tempfile.mkdtemp()          return self.name      def __exit__(self, type, value, traceback): -        os.removedirs(self.name) +        try: +            shutil.rmtree(self.name) +        except OSError,e: +            #Utility should have already detected this, but this is for safety +            print str(e) +            raise Exception("Could not install images! Make sure you have write permissions.")  if __name__ == "__main__": +    print +    if os.environ.get("UHD_IMAGES_DIR") != None and os.environ.get("UHD_IMAGES_DIR") != "": +        default_images_dir = os.environ.get("UHD_IMAGES_DIR") +        print "UHD_IMAGES_DIR environment variable is set. Default install location: %s" % default_images_dir +    else: +        default_images_dir = "@CMAKE_INSTALL_PREFIX@/share/uhd/images" +      #Command line options      parser = OptionParser() -    parser.add_option("--install-location", type="string", default="", help="Set custom install location for images") +    parser.add_option("--install-location", type="string", default=default_images_dir, help="Set custom install location for images")      parser.add_option("--buffer-size", type="int", default=8192, help="Set download buffer size, [default=%default]",)      (options, args) = parser.parse_args() @@ -59,17 +71,27 @@ if __name__ == "__main__":      images_zip_md5sum = "@UHD_IMAGES_MD5SUM@"      filename = images_src.split("/")[-1] +    #Use this directory with relative paths +    current_directory = os.getcwd() +      with temp_dir() as dirname:          os.chdir(dirname) -        #Configuring image destination -        if options.install_location != "": +        if os.path.isabs(options.install_location): +            #Custom absolute path given              images_dir = options.install_location -        elif os.environ.get("UHD_IMAGES_DIR") != "" and os.environ.get("UHD_IMAGES_DIR") != None: -            images_dir = os.environ.get("UHD_IMAGES_DIR")          else: -            images_dir = "@CMAKE_INSTALL_PREFIX@/share/uhd/images" -         +            #Custom relative path given, so construct absolute path +            images_dir = os.path.abspath(os.path.join(current_directory, options.install_location)) + +        #Before doing anything, check for write permissions in parent directory +        parent_directory = os.path.dirname(images_dir) +        if os.access(parent_directory, os.W_OK): +            print "Downloading images to: %s" % images_dir +        else: +            print "You do not have write permissions at the install location!" +            sys.exit(1) +          opener = urllib2.build_opener()          opener.add_headers = [('User-Agent', 'UHD Images Downloader')]          u = opener.open(images_src) @@ -101,32 +123,37 @@ if __name__ == "__main__":          if images_zip_md5sum != downloaded_zip_md5sum:              print "\nMD5 checksum does not match!"              print "Expected %s, got %s" % (images_zip_md5sum, downloaded_zip_md5sum) +            print "Images did not install. If problem persists, please contact support@ettus.com."              os.remove(filename)              os.chdir("/".join(images_dir.split("/")[:-1])) +            sys.exit(1)          else: +            temp_path = "tempdir" +              #Extracting contents of zip file -            if os.path.exists("tempdir"): -                shutil.rmtree("tempdir") -            os.mkdir("tempdir") +            if os.path.exists(temp_path): +                shutil.rmtree(temp_path) +            os.mkdir(temp_path)              images_zip = zipfile.ZipFile(filename) -            images_zip.extractall("tempdir") +            images_zip.extractall(temp_path)              #Removing images currently in images_dir              if os.path.exists(images_dir):                  try:                      shutil.rmtree(images_dir) -                except: -                    sys.stderr.write("\nMake sure you have write permissions in the images directory.\n") -                    sys.exit(0) +                except OSError,e: +                    print str(e) +                    print "Make sure you have write permissions in the images directory." +                    sys.exit(1)              #Copying downloaded images into images_dir -            shutil.copytree("tempdir/%s/share/uhd/images" % filename[:-4],images_dir) +            shutil.copytree(os.path.join(temp_path, os.path.splitext(filename)[0], 'share', 'uhd', 'images'), images_dir)              #Removing tempdir and zip file -            shutil.rmtree("tempdir") +            shutil.rmtree(temp_path)              images_zip.close()              os.remove(filename)              os.chdir(images_dir) -            print "\nImages successfully installed to: %s" % images_dir +            print "\n\nImages successfully installed!" diff --git a/host/utils/usrp_burn_mb_eeprom.cpp b/host/utils/usrp_burn_mb_eeprom.cpp index 1b13fb615..ce0879c8e 100644 --- a/host/utils/usrp_burn_mb_eeprom.cpp +++ b/host/utils/usrp_burn_mb_eeprom.cpp @@ -1,5 +1,5 @@  // -// Copyright 2010 Ettus Research LLC +// Copyright 2010,2013 Ettus Research LLC  //  // 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 @@ -19,9 +19,11 @@  #include <uhd/device.hpp>  #include <uhd/property_tree.hpp>  #include <uhd/usrp/mboard_eeprom.hpp> +#include <boost/algorithm/string.hpp>  #include <boost/program_options.hpp>  #include <boost/format.hpp>  #include <iostream> +#include <vector>  namespace po = boost::program_options; @@ -32,8 +34,8 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){      desc.add_options()          ("help", "help message")          ("args", po::value<std::string>(&args)->default_value(""), "device address args [default = \"\"]") -        ("key", po::value<std::string>(&key), "the indentifier for a value in EEPROM") -        ("val", po::value<std::string>(&val), "the new value to set, omit for readback") +        ("key", po::value<std::string>(&key), "identifiers for new values in EEPROM, separate multiple by \",\"") +        ("val", po::value<std::string>(&val), "the new values to set, omit for readback, separate multiple by \",\"")      ;      po::variables_map vm; @@ -55,20 +57,35 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){      uhd::property_tree::sptr tree = dev->get_tree();      std::cout << std::endl; -    if (true /*always readback*/){ -        std::cout << "Fetching current settings from EEPROM..." << std::endl; -        uhd::usrp::mboard_eeprom_t mb_eeprom = tree->access<uhd::usrp::mboard_eeprom_t>("/mboards/0/eeprom").get(); -        if (not mb_eeprom.has_key(key)){ -            std::cerr << boost::format("Cannot find value for EEPROM[%s]") % key << std::endl; +    //remove whitespace, split arguments and values  +    boost::algorithm::erase_all(key, " "); +    boost::algorithm::erase_all(val, " "); + +    std::vector<std::string> keys_vec, vals_vec; +    boost::split(keys_vec, key, boost::is_any_of("\"',")); +    boost::split(vals_vec, val, boost::is_any_of("\"',")); + +    if((keys_vec.size() != vals_vec.size()) and val != "") { +        //If zero values are given, then user just wants values read to them +        throw std::runtime_error("Number of keys must match number of values!"); +    } + +    std::cout << "Fetching current settings from EEPROM..." << std::endl; +    uhd::usrp::mboard_eeprom_t mb_eeprom = tree->access<uhd::usrp::mboard_eeprom_t>("/mboards/0/eeprom").get(); +    for(size_t i = 0; i < keys_vec.size(); i++){ +        if (not mb_eeprom.has_key(keys_vec[i])){ +            std::cerr << boost::format("Cannot find value for EEPROM[%s]") % keys_vec[i] << std::endl;              return EXIT_FAILURE;          } -        std::cout << boost::format("    EEPROM [\"%s\"] is \"%s\"") % key % mb_eeprom[key] << std::endl; -        std::cout << std::endl; +        std::cout << boost::format("    EEPROM [\"%s\"] is \"%s\"") % keys_vec[i] % mb_eeprom[keys_vec[i]] << std::endl;      } +    std::cout << std::endl;      if (vm.count("val")){ -        uhd::usrp::mboard_eeprom_t mb_eeprom; mb_eeprom[key] = val; -        std::cout << boost::format("Setting EEPROM [\"%s\"] to \"%s\"...") % key % val << std::endl; -        tree->access<uhd::usrp::mboard_eeprom_t>("/mboards/0/eeprom").set(mb_eeprom); +        for(size_t i = 0; i < vals_vec.size(); i++){ +            uhd::usrp::mboard_eeprom_t mb_eeprom; mb_eeprom[keys_vec[i]] = vals_vec[i]; +            std::cout << boost::format("Setting EEPROM [\"%s\"] to \"%s\"...") % keys_vec[i] % vals_vec[i] << std::endl; +            tree->access<uhd::usrp::mboard_eeprom_t>("/mboards/0/eeprom").set(mb_eeprom); +        }          std::cout << "Power-cycle the USRP device for the changes to take effect." << std::endl;          std::cout << std::endl;      }  | 
