aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/usrp
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib/usrp')
-rw-r--r--host/lib/usrp/CMakeLists.txt2
-rw-r--r--host/lib/usrp/dboard/db_rfx.cpp44
-rw-r--r--host/lib/usrp/dboard/db_xcvr2450.cpp13
-rw-r--r--host/lib/usrp/dboard_base.cpp2
-rw-r--r--host/lib/usrp/dsp_utils.cpp2
-rw-r--r--host/lib/usrp/gps_ctrl.cpp2
-rw-r--r--host/lib/usrp/tune_helper.cpp2
-rw-r--r--host/lib/usrp/usrp1/clock_ctrl.hpp2
-rw-r--r--host/lib/usrp/usrp1/codec_ctrl.cpp73
-rw-r--r--host/lib/usrp/usrp1/soft_time_ctrl.cpp14
-rw-r--r--host/lib/usrp/usrp1/usrp1_ctrl.cpp2
-rw-r--r--host/lib/usrp/usrp1/usrp1_ctrl.hpp2
-rw-r--r--host/lib/usrp/usrp1/usrp1_iface.cpp48
-rw-r--r--host/lib/usrp/usrp1/usrp1_iface.hpp2
-rw-r--r--host/lib/usrp/usrp1/usrp1_impl.cpp12
-rw-r--r--host/lib/usrp/usrp2/CMakeLists.txt2
-rw-r--r--host/lib/usrp/usrp2/clock_ctrl.cpp2
-rw-r--r--host/lib/usrp/usrp2/io_impl.cpp25
-rw-r--r--host/lib/usrp/usrp2/mboard_impl.cpp12
-rw-r--r--host/lib/usrp/usrp2/usrp2_iface.cpp65
-rw-r--r--host/lib/usrp/usrp2/usrp2_iface.hpp2
-rw-r--r--host/lib/usrp/usrp2/usrp2_impl.cpp41
-rw-r--r--host/lib/usrp/usrp_e100/CMakeLists.txt6
-rw-r--r--host/lib/usrp/usrp_e100/clock_ctrl.cpp19
-rw-r--r--host/lib/usrp/usrp_e100/clock_ctrl.hpp14
-rw-r--r--host/lib/usrp/usrp_e100/dboard_iface.cpp8
-rw-r--r--host/lib/usrp/usrp_e100/io_impl.cpp16
-rw-r--r--host/lib/usrp/usrp_e100/mboard_impl.cpp5
-rw-r--r--host/lib/usrp/usrp_e100/usrp_e100_iface.cpp11
-rw-r--r--host/lib/usrp/usrp_e100/usrp_e100_iface.hpp2
-rw-r--r--host/lib/usrp/usrp_e100/usrp_e100_impl.cpp10
-rw-r--r--host/lib/usrp/usrp_e100/usrp_e100_impl.hpp2
32 files changed, 284 insertions, 180 deletions
diff --git a/host/lib/usrp/CMakeLists.txt b/host/lib/usrp/CMakeLists.txt
index 59dabbd58..018beb417 100644
--- a/host/lib/usrp/CMakeLists.txt
+++ b/host/lib/usrp/CMakeLists.txt
@@ -1,5 +1,5 @@
#
-# Copyright 2010 Ettus Research LLC
+# Copyright 2010-2011 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
diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp
index 4d8222a52..f938c749a 100644
--- a/host/lib/usrp/dboard/db_rfx.cpp
+++ b/host/lib/usrp/dboard/db_rfx.cpp
@@ -294,6 +294,9 @@ double rfx_xcvr::set_lo_freq(
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)
@@ -309,7 +312,8 @@ double rfx_xcvr::set_lo_freq(
(8, adf4360_regs_t::BAND_SELECT_CLOCK_DIV_8)
;
- double actual_freq=0, ref_freq = this->get_iface()->get_clock_rate(unit);
+ std::vector<double> clock_rates = this->get_iface()->get_clock_rates(unit);
+ double actual_freq = 0, ref_freq = 0;
int R=0, BS=0, P=0, B=0, A=0;
/*
@@ -322,27 +326,31 @@ double rfx_xcvr::set_lo_freq(
* fvco = [P*B + A] * fref/R
* fvco*R/fref = P*B + A = N
*/
- for(R = 2; R <= 32; R+=2){
- BOOST_FOREACH(BS, bandsel_to_enum.keys()){
- if (ref_freq/R/BS > 1e6) continue; //constraint on band select clock
- BOOST_FOREACH(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;
+ for(R = 1; R <= 32; R+=((R==1)?1:2)){
+ BOOST_FOREACH(ref_freq, uhd::reversed(uhd::sorted(clock_rates))){
+ BOOST_FOREACH(BS, bandsel_to_enum.keys()){
+ if (ref_freq/R/BS > 1e6) continue; //constraint on band select clock
+ BOOST_FOREACH(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:
if (rfx_debug) std::cerr << boost::format(
- "RFX tune: R=%d, BS=%d, P=%d, B=%d, A=%d"
- ) % R % BS % P % B % A << std::endl;
+ "RFX tune: R=%d, BS=%d, P=%d, B=%d, A=%d, DIV2=%d, ref=%fMHz"
+ ) % R % BS % P % B % A % int(_div2[unit] && (!is_rx_rfx400)) % (ref_freq/1e6) << std::endl;
+
+ this->get_iface()->set_clock_rate(unit, ref_freq);
//load the register values
adf4360_regs_t regs;
@@ -361,7 +369,7 @@ double rfx_xcvr::set_lo_freq(
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] && (get_rx_id() != 0x0024)) ? // Special case RFX400 RX Mixer divides by two
+ 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;
diff --git a/host/lib/usrp/dboard/db_xcvr2450.cpp b/host/lib/usrp/dboard/db_xcvr2450.cpp
index 9d25b30a5..70b0bbabd 100644
--- a/host/lib/usrp/dboard/db_xcvr2450.cpp
+++ b/host/lib/usrp/dboard/db_xcvr2450.cpp
@@ -152,12 +152,21 @@ private:
* \return the rssi in dB
*/
double get_rssi(void){
+ //*FIXME* RSSI depends on LNA Gain Setting (datasheet pg 16 top middle chart)
+ double max_power;
+ switch(_max2829_regs.rx_lna_gain){
+ case 0:
+ case 1: max_power = 0; break;
+ case 2: max_power = -15; break;
+ case 3: max_power = -30.5; break;
+ }
+
//constants for the rssi calculation
static const double min_v = 0.5, max_v = 2.5;
static const double rssi_dyn_range = 60;
//calculate the rssi from the voltage
double voltage = this->get_iface()->read_aux_adc(dboard_iface::UNIT_RX, dboard_iface::AUX_ADC_B);
- return rssi_dyn_range*(voltage - min_v)/(max_v - min_v);
+ return max_power - rssi_dyn_range*(voltage - min_v)/(max_v - min_v);
}
};
@@ -621,7 +630,7 @@ void xcvr2450::rx_get(const wax::obj &key_, wax::obj &val){
if (key.name == "lo_locked")
val = sensor_value_t("LO", this->get_locked(), "locked", "unlocked");
else if (key.name == "rssi")
- val = sensor_value_t("RSSI", this->get_rssi(), "dB");
+ val = sensor_value_t("RSSI", this->get_rssi(), "dBm");
else
UHD_THROW_INVALID_CODE_PATH();
return;
diff --git a/host/lib/usrp/dboard_base.cpp b/host/lib/usrp/dboard_base.cpp
index 999dd9ffc..e14c9d144 100644
--- a/host/lib/usrp/dboard_base.cpp
+++ b/host/lib/usrp/dboard_base.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 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
diff --git a/host/lib/usrp/dsp_utils.cpp b/host/lib/usrp/dsp_utils.cpp
index a3a557060..2686e895b 100644
--- a/host/lib/usrp/dsp_utils.cpp
+++ b/host/lib/usrp/dsp_utils.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 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
diff --git a/host/lib/usrp/gps_ctrl.cpp b/host/lib/usrp/gps_ctrl.cpp
index e0ab6de90..ff8e9cee6 100644
--- a/host/lib/usrp/gps_ctrl.cpp
+++ b/host/lib/usrp/gps_ctrl.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 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
diff --git a/host/lib/usrp/tune_helper.cpp b/host/lib/usrp/tune_helper.cpp
index ced80c187..9637301ad 100644
--- a/host/lib/usrp/tune_helper.cpp
+++ b/host/lib/usrp/tune_helper.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 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
diff --git a/host/lib/usrp/usrp1/clock_ctrl.hpp b/host/lib/usrp/usrp1/clock_ctrl.hpp
index 645472f02..339d547e6 100644
--- a/host/lib/usrp/usrp1/clock_ctrl.hpp
+++ b/host/lib/usrp/usrp1/clock_ctrl.hpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 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
diff --git a/host/lib/usrp/usrp1/codec_ctrl.cpp b/host/lib/usrp/usrp1/codec_ctrl.cpp
index 1b4411002..9df29da0e 100644
--- a/host/lib/usrp/usrp1/codec_ctrl.cpp
+++ b/host/lib/usrp/usrp1/codec_ctrl.cpp
@@ -71,7 +71,6 @@ private:
usrp1_clock_ctrl::sptr _clock_ctrl;
int _spi_slave;
ad9862_regs_t _ad9862_regs;
- aux_adc_t _last_aux_adc_a, _last_aux_adc_b;
void send_reg(boost::uint8_t addr);
void recv_reg(boost::uint8_t addr);
@@ -134,6 +133,10 @@ usrp1_codec_ctrl_impl::usrp1_codec_ctrl_impl(usrp1_iface::sptr iface,
this->send_reg(addr);
}
+ //always start conversions for aux ADC
+ _ad9862_regs.start_a = 1;
+ _ad9862_regs.start_b = 1;
+
//aux adc clock
_ad9862_regs.clk_4 = ad9862_regs_t::CLK_4_1_4;
this->send_reg(34);
@@ -206,55 +209,37 @@ static double aux_adc_to_volts(boost::uint8_t high, boost::uint8_t low)
return double(((boost::uint16_t(high) << 2) | low)*3.3)/0x3ff;
}
-double usrp1_codec_ctrl_impl::read_aux_adc(aux_adc_t which)
-{
- //check to see if the switch needs to be set
- bool write_switch = false;
- switch(which) {
-
+double usrp1_codec_ctrl_impl::read_aux_adc(aux_adc_t which){
+ switch(which){
case AUX_ADC_A1:
+ _ad9862_regs.select_a = ad9862_regs_t::SELECT_A_AUX_ADC1;
+ this->send_reg(34); //start conversion and select mux
+ this->recv_reg(28); //read the value (2 bytes, 2 reads)
+ this->recv_reg(29);
+ return aux_adc_to_volts(_ad9862_regs.aux_adc_a1_9_2, _ad9862_regs.aux_adc_a1_1_0);
+
case AUX_ADC_A2:
- if (which != _last_aux_adc_a) {
- _ad9862_regs.select_a = (which == AUX_ADC_A1)?
- ad9862_regs_t::SELECT_A_AUX_ADC1: ad9862_regs_t::SELECT_A_AUX_ADC2;
- _last_aux_adc_a = which;
- write_switch = true;
- }
- break;
+ _ad9862_regs.select_a = ad9862_regs_t::SELECT_A_AUX_ADC2;
+ this->send_reg(34); //start conversion and select mux
+ this->recv_reg(26); //read the value (2 bytes, 2 reads)
+ this->recv_reg(27);
+ return aux_adc_to_volts(_ad9862_regs.aux_adc_a2_9_2, _ad9862_regs.aux_adc_a2_1_0);
case AUX_ADC_B1:
- case AUX_ADC_B2:
- if (which != _last_aux_adc_b) {
- _ad9862_regs.select_b = (which == AUX_ADC_B1)?
- ad9862_regs_t::SELECT_B_AUX_ADC1: ad9862_regs_t::SELECT_B_AUX_ADC2;
- _last_aux_adc_b = which;
- write_switch = true;
- }
- break;
+ _ad9862_regs.select_b = ad9862_regs_t::SELECT_B_AUX_ADC1;
+ this->send_reg(34); //start conversion and select mux
+ this->recv_reg(32); //read the value (2 bytes, 2 reads)
+ this->recv_reg(33);
+ return aux_adc_to_volts(_ad9862_regs.aux_adc_b1_9_2, _ad9862_regs.aux_adc_b1_1_0);
+ case AUX_ADC_B2:
+ _ad9862_regs.select_b = ad9862_regs_t::SELECT_B_AUX_ADC2;
+ this->send_reg(34); //start conversion and select mux
+ this->recv_reg(30); //read the value (2 bytes, 2 reads)
+ this->recv_reg(31);
+ return aux_adc_to_volts(_ad9862_regs.aux_adc_b2_9_2, _ad9862_regs.aux_adc_b2_1_0);
}
-
- //write the switch if it changed
- if(write_switch) this->send_reg(34);
-
- //map aux adcs to register values to read
- static const uhd::dict<aux_adc_t, boost::uint8_t> aux_dac_to_addr = boost::assign::map_list_of
- (AUX_ADC_A2, 26) (AUX_ADC_A1, 28)
- (AUX_ADC_B2, 30) (AUX_ADC_B1, 32)
- ;
-
- //read the value
- this->recv_reg(aux_dac_to_addr[which]+0);
- this->recv_reg(aux_dac_to_addr[which]+1);
-
- //return the value scaled to volts
- switch(which) {
- case AUX_ADC_A1: return aux_adc_to_volts(_ad9862_regs.aux_adc_a1_9_2, _ad9862_regs.aux_adc_a1_1_0);
- case AUX_ADC_A2: return aux_adc_to_volts(_ad9862_regs.aux_adc_a2_9_2, _ad9862_regs.aux_adc_a2_1_0);
- case AUX_ADC_B1: return aux_adc_to_volts(_ad9862_regs.aux_adc_b1_9_2, _ad9862_regs.aux_adc_b1_1_0);
- case AUX_ADC_B2: return aux_adc_to_volts(_ad9862_regs.aux_adc_b2_9_2, _ad9862_regs.aux_adc_b2_1_0);
- }
- UHD_ASSERT_THROW(false);
+ UHD_THROW_INVALID_CODE_PATH();
}
/***********************************************************************
diff --git a/host/lib/usrp/usrp1/soft_time_ctrl.cpp b/host/lib/usrp/usrp1/soft_time_ctrl.cpp
index e1b671811..1bab34e7b 100644
--- a/host/lib/usrp/usrp1/soft_time_ctrl.cpp
+++ b/host/lib/usrp/usrp1/soft_time_ctrl.cpp
@@ -19,6 +19,7 @@
#include <uhd/transport/bounded_buffer.hpp>
#include <boost/any.hpp>
#include <boost/thread/thread.hpp>
+#include <boost/thread/barrier.hpp>
#include <boost/thread/condition_variable.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <iostream>
@@ -43,10 +44,11 @@ public:
_stream_on_off(stream_on_off)
{
//synchronously spawn a new thread
- _update_mutex.lock(); //lock mutex before spawned
- _thread_group.create_thread(boost::bind(&soft_time_ctrl_impl::recv_cmd_dispatcher, this));
- _update_mutex.lock(); //lock blocks until spawned
- _update_mutex.unlock(); //unlock mutex before done
+ boost::barrier spawn_barrier(2);
+ _thread_group.create_thread(boost::bind(
+ &soft_time_ctrl_impl::recv_cmd_dispatcher, this, boost::ref(spawn_barrier))
+ );
+ spawn_barrier.wait();
//initialize the time to something
this->set_time(time_spec_t(0.0));
@@ -175,8 +177,8 @@ public:
_stream_mode = cmd.stream_mode;
}
- void recv_cmd_dispatcher(void){
- _update_mutex.unlock();
+ void recv_cmd_dispatcher(boost::barrier &spawn_barrier){
+ spawn_barrier.wait();
try{
boost::any cmd;
while (true){
diff --git a/host/lib/usrp/usrp1/usrp1_ctrl.cpp b/host/lib/usrp/usrp1/usrp1_ctrl.cpp
index 3fa6cb8b7..22e9fd1ce 100644
--- a/host/lib/usrp/usrp1/usrp1_ctrl.cpp
+++ b/host/lib/usrp/usrp1/usrp1_ctrl.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 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
diff --git a/host/lib/usrp/usrp1/usrp1_ctrl.hpp b/host/lib/usrp/usrp1/usrp1_ctrl.hpp
index ee68f8401..970ca2951 100644
--- a/host/lib/usrp/usrp1/usrp1_ctrl.hpp
+++ b/host/lib/usrp/usrp1/usrp1_ctrl.hpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 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
diff --git a/host/lib/usrp/usrp1/usrp1_iface.cpp b/host/lib/usrp/usrp1/usrp1_iface.cpp
index 0c37610ce..8f10df751 100644
--- a/host/lib/usrp/usrp1/usrp1_iface.cpp
+++ b/host/lib/usrp/usrp1/usrp1_iface.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 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
@@ -175,24 +175,31 @@ public:
UHD_ASSERT_THROW((num_bits <= 32) && !(num_bits % 8));
size_t num_bytes = num_bits / 8;
- // Byteswap on num_bytes
- unsigned char buff[4] = { 0 };
- for (size_t i = 1; i <= num_bytes; i++)
- buff[num_bytes - i] = (bits >> ((i - 1) * 8)) & 0xff;
-
if (readback) {
- boost::uint8_t w_len_h = which_slave & 0xff;
- boost::uint8_t w_len_l = num_bytes & 0xff;
-
- int ret = _ctrl_transport->usrp_control_read(
- VRQ_SPI_TRANSACT,
- (buff[0] << 8) | (buff[1] << 0),
- (buff[2] << 8) | (buff[3] << 0),
- buff,
- (w_len_h << 8) | (w_len_l << 0));
-
- if (ret < 0) throw uhd::io_error("USRP1: failed SPI readback transaction");
-
+ unsigned char buff[4] = {
+ (bits >> 0) & 0xff, (bits >> 8) & 0xff,
+ (bits >> 16) & 0xff, (bits >> 24) & 0xff
+ };
+ //conditions where there are two header bytes
+ if (num_bytes >= 3 and buff[num_bytes-1] != 0 and buff[num_bytes-2] != 0 and buff[num_bytes-3] == 0){
+ if (int(num_bytes-2) != _ctrl_transport->usrp_control_read(
+ VRQ_SPI_READ, (buff[num_bytes-1] << 8) | (buff[num_bytes-2] << 0),
+ (which_slave << 8) | SPI_FMT_MSB | SPI_FMT_HDR_2,
+ buff, num_bytes-2
+ )) throw uhd::io_error("USRP1: failed SPI readback transaction");
+ }
+
+ //conditions where there is one header byte
+ else if (num_bytes >= 2 and buff[num_bytes-1] != 0 and buff[num_bytes-2] == 0){
+ if (int(num_bytes-1) != _ctrl_transport->usrp_control_read(
+ VRQ_SPI_READ, buff[num_bytes-1],
+ (which_slave << 8) | SPI_FMT_MSB | SPI_FMT_HDR_1,
+ buff, num_bytes-1
+ )) throw uhd::io_error("USRP1: failed SPI readback transaction");
+ }
+ else{
+ throw uhd::io_error("USRP1: invalid input data for SPI readback");
+ }
boost::uint32_t val = (((boost::uint32_t)buff[0]) << 0) |
(((boost::uint32_t)buff[1]) << 8) |
(((boost::uint32_t)buff[2]) << 16) |
@@ -200,6 +207,11 @@ public:
return val;
}
else {
+ // Byteswap on num_bytes
+ unsigned char buff[4] = { 0 };
+ for (size_t i = 1; i <= num_bytes; i++)
+ buff[num_bytes - i] = (bits >> ((i - 1) * 8)) & 0xff;
+
boost::uint8_t w_index_h = which_slave & 0xff;
boost::uint8_t w_index_l = (SPI_FMT_MSB | SPI_FMT_HDR_0) & 0xff;
diff --git a/host/lib/usrp/usrp1/usrp1_iface.hpp b/host/lib/usrp/usrp1/usrp1_iface.hpp
index fdb7464ce..2ebcdbacc 100644
--- a/host/lib/usrp/usrp1/usrp1_iface.hpp
+++ b/host/lib/usrp/usrp1/usrp1_iface.hpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 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
diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp
index 7005c59f2..a99777775 100644
--- a/host/lib/usrp/usrp1/usrp1_impl.cpp
+++ b/host/lib/usrp/usrp1/usrp1_impl.cpp
@@ -86,7 +86,11 @@ static device_addrs_t usrp1_find(const device_addr_t &hint)
}
//std::cout << "USRP1 firmware image: " << usrp1_fw_image << std::endl;
- usrp_ctrl::make(usb_control::make(handle))->usrp_load_firmware(usrp1_fw_image);
+ usb_control::sptr control;
+ try{control = usb_control::make(handle);}
+ catch(const uhd::exception &){continue;} //ignore claimed
+
+ usrp_ctrl::make(control)->usrp_load_firmware(usrp1_fw_image);
}
//get descriptors again with serial number, but using the initialized VID/PID now since we have firmware
@@ -94,7 +98,11 @@ static device_addrs_t usrp1_find(const device_addr_t &hint)
pid = USRP1_PRODUCT_ID;
BOOST_FOREACH(usb_device_handle::sptr handle, usb_device_handle::get_device_list(vid, pid)) {
- usrp1_iface::sptr iface = usrp1_iface::make(usrp_ctrl::make(usb_control::make(handle)));
+ usb_control::sptr control;
+ try{control = usb_control::make(handle);}
+ catch(const uhd::exception &){continue;} //ignore claimed
+
+ usrp1_iface::sptr iface = usrp1_iface::make(usrp_ctrl::make(control));
device_addr_t new_addr;
new_addr["type"] = "usrp1";
new_addr["name"] = iface->mb_eeprom["name"];
diff --git a/host/lib/usrp/usrp2/CMakeLists.txt b/host/lib/usrp/usrp2/CMakeLists.txt
index e8811a8fb..49be9ac7d 100644
--- a/host/lib/usrp/usrp2/CMakeLists.txt
+++ b/host/lib/usrp/usrp2/CMakeLists.txt
@@ -1,5 +1,5 @@
#
-# Copyright 2010 Ettus Research LLC
+# Copyright 2010-2011 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
diff --git a/host/lib/usrp/usrp2/clock_ctrl.cpp b/host/lib/usrp/usrp2/clock_ctrl.cpp
index abda53bf2..7572ed6b1 100644
--- a/host/lib/usrp/usrp2/clock_ctrl.cpp
+++ b/host/lib/usrp/usrp2/clock_ctrl.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 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
diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp
index 340e9d155..07cbd2432 100644
--- a/host/lib/usrp/usrp2/io_impl.cpp
+++ b/host/lib/usrp/usrp2/io_impl.cpp
@@ -25,7 +25,8 @@
#include <uhd/transport/bounded_buffer.hpp>
#include <boost/format.hpp>
#include <boost/bind.hpp>
-#include <boost/thread.hpp>
+#include <boost/thread/thread.hpp>
+#include <boost/thread/barrier.hpp>
#include <iostream>
using namespace uhd;
@@ -209,11 +210,10 @@ struct usrp2_impl::io_impl{
vrt_packet_handler::send_state packet_handler_send_state;
//methods and variables for the pirate crew
- void recv_pirate_loop(usrp2_mboard_impl::sptr, zero_copy_if::sptr, size_t);
+ void recv_pirate_loop(boost::barrier &, usrp2_mboard_impl::sptr, zero_copy_if::sptr, size_t);
boost::thread_group recv_pirate_crew;
bool recv_pirate_crew_raiding;
bounded_buffer<async_metadata_t> async_msg_fifo;
- boost::mutex spawn_mutex;
};
/***********************************************************************
@@ -223,13 +223,15 @@ struct usrp2_impl::io_impl{
* - put async message packets into queue
**********************************************************************/
void usrp2_impl::io_impl::recv_pirate_loop(
- usrp2_mboard_impl::sptr mboard, zero_copy_if::sptr err_xport, size_t index
+ boost::barrier &spawn_barrier,
+ usrp2_mboard_impl::sptr mboard,
+ zero_copy_if::sptr err_xport,
+ size_t index
){
+ spawn_barrier.wait();
set_thread_priority_safe();
recv_pirate_crew_raiding = true;
- spawn_mutex.unlock();
-
//store a reference to the flow control monitor (offset by max dsps)
flow_control_monitor &fc_mon = *(this->fc_mons[index*usrp2_mboard_impl::MAX_NUM_DSPS]);
@@ -286,19 +288,16 @@ void usrp2_impl::io_init(void){
_io_impl = UHD_PIMPL_MAKE(io_impl, (dsp_xports));
//create a new pirate thread for each zc if (yarr!!)
+ boost::barrier spawn_barrier(_mboards.size()+1);
for (size_t i = 0; i < _mboards.size(); i++){
- //lock the unlocked mutex (non-blocking)
- _io_impl->spawn_mutex.lock();
//spawn a new pirate to plunder the recv booty
_io_impl->recv_pirate_crew.create_thread(boost::bind(
&usrp2_impl::io_impl::recv_pirate_loop,
- _io_impl.get(), _mboards.at(i), err_xports.at(i), i
+ _io_impl.get(), boost::ref(spawn_barrier),
+ _mboards.at(i), err_xports.at(i), i
));
- //block here until the spawned thread unlocks
- _io_impl->spawn_mutex.lock();
- //exit loop iteration in an unlocked condition
- _io_impl->spawn_mutex.unlock();
}
+ spawn_barrier.wait();
//update mapping here since it didnt b4 when io init not called first
update_xport_channel_mapping();
diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp
index 40fc5098b..29e0535f8 100644
--- a/host/lib/usrp/usrp2/mboard_impl.cpp
+++ b/host/lib/usrp/usrp2/mboard_impl.cpp
@@ -66,6 +66,18 @@ usrp2_mboard_impl::usrp2_mboard_impl(
device_addr["addr"], BOOST_STRINGIZE(USRP2_UDP_CTRL_PORT)
)))
{
+
+ //check the fpga compatibility number
+ const boost::uint32_t fpga_compat_num = _iface->peek32(_iface->regs.compat_num_rb);
+ if (fpga_compat_num != USRP2_FPGA_COMPAT_NUM){
+ throw uhd::runtime_error(str(boost::format(
+ "\nPlease update the firmware and FPGA images for your device.\n"
+ "See the application notes for USRP2/N-Series for instructions.\n"
+ "Expected FPGA compatibility number %d, but got %d:\n"
+ "The FPGA build is not compatible with the host code build."
+ ) % int(USRP2_FPGA_COMPAT_NUM) % fpga_compat_num));
+ }
+
//construct transports for dsp and async errors
std::cout << "Making transport for DSP0..." << std::endl;
device.dsp_xports.push_back(udp_zero_copy::make(
diff --git a/host/lib/usrp/usrp2/usrp2_iface.cpp b/host/lib/usrp/usrp2/usrp2_iface.cpp
index e3827233b..d88d31765 100644
--- a/host/lib/usrp/usrp2/usrp2_iface.cpp
+++ b/host/lib/usrp/usrp2/usrp2_iface.cpp
@@ -34,14 +34,32 @@ using namespace uhd::transport;
static const double CTRL_RECV_TIMEOUT = 1.0;
+static const boost::uint32_t MIN_PROTO_COMPAT_SPI = 7;
+static const boost::uint32_t MIN_PROTO_COMPAT_I2C = 7;
+// The register compat number must reflect the protocol compatibility
+// and the compatibility of the register mapping (more likely to change).
+static const boost::uint32_t MIN_PROTO_COMPAT_REG = USRP2_FW_COMPAT_NUM;
+static const boost::uint32_t MIN_PROTO_COMPAT_UART = 7;
+
class usrp2_iface_impl : public usrp2_iface{
public:
/***********************************************************************
* Structors
**********************************************************************/
- usrp2_iface_impl(udp_simple::sptr ctrl_transport){
- _ctrl_transport = ctrl_transport;
- _ctrl_seq_num = 0;
+ usrp2_iface_impl(udp_simple::sptr ctrl_transport):
+ _ctrl_transport(ctrl_transport),
+ _ctrl_seq_num(0),
+ _protocol_compat(0) //initialized below...
+ {
+ //Obtain the firmware's compat number.
+ //Save the response compat number for communication.
+ //TODO can choose to reject certain older compat numbers
+ usrp2_ctrl_data_t ctrl_data;
+ ctrl_data.id = htonl(USRP2_CTRL_ID_WAZZUP_BRO);
+ ctrl_data = ctrl_send_and_recv(ctrl_data, 0, ~0);
+ if (ntohl(ctrl_data.id) != USRP2_CTRL_ID_WAZZUP_DUDE)
+ throw uhd::runtime_error("firmware not responding");
+ _protocol_compat = ntohl(ctrl_data.proto_ver);
mb_eeprom = mboard_eeprom_t(*this, mboard_eeprom_t::MAP_N100);
switch(this->get_rev()){
@@ -59,15 +77,6 @@ public:
regs = usrp2_get_regs(false);
break;
}
-
- //check the fpga compatibility number
- const boost::uint32_t fpga_compat_num = this->peek32(this->regs.compat_num_rb);
- if (fpga_compat_num != USRP2_FPGA_COMPAT_NUM){
- throw uhd::runtime_error(str(boost::format(
- "Expected fpga compatibility number %d, but got %d:\n"
- "The fpga build is not compatible with the host code build."
- ) % int(USRP2_FPGA_COMPAT_NUM) % fpga_compat_num));
- }
}
/***********************************************************************
@@ -115,7 +124,7 @@ public:
out_data.data.spi_args.data = htonl(data);
//send and recv
- usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data);
+ usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data, MIN_PROTO_COMPAT_SPI);
UHD_ASSERT_THROW(ntohl(in_data.id) == USRP2_CTRL_ID_OMG_TRANSACTED_SPI_DUDE);
return ntohl(in_data.data.spi_args.data);
@@ -138,7 +147,7 @@ public:
std::copy(buf.begin(), buf.end(), out_data.data.i2c_args.data);
//send and recv
- usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data);
+ usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data, MIN_PROTO_COMPAT_I2C);
UHD_ASSERT_THROW(ntohl(in_data.id) == USRP2_CTRL_ID_COOL_IM_DONE_I2C_WRITE_DUDE);
}
@@ -153,7 +162,7 @@ public:
UHD_ASSERT_THROW(num_bytes <= sizeof(out_data.data.i2c_args.data));
//send and recv
- usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data);
+ usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data, MIN_PROTO_COMPAT_I2C);
UHD_ASSERT_THROW(ntohl(in_data.id) == USRP2_CTRL_ID_HERES_THE_I2C_DATA_DUDE);
UHD_ASSERT_THROW(in_data.data.i2c_args.addr = num_bytes);
@@ -186,7 +195,7 @@ public:
std::copy(item.begin(), item.end(), out_data.data.uart_args.data);
//send and recv
- usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data);
+ usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data, MIN_PROTO_COMPAT_UART);
UHD_ASSERT_THROW(ntohl(in_data.id) == USRP2_CTRL_ID_MAN_I_TOTALLY_WROTE_THAT_UART_DUDE);
}
}
@@ -205,7 +214,7 @@ public:
//UHD_ASSERT_THROW(num_bytes <= sizeof(out_data.data.uart_args.data));
//send and recv
- usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data);
+ usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data, MIN_PROTO_COMPAT_UART);
UHD_ASSERT_THROW(ntohl(in_data.id) == USRP2_CTRL_ID_I_HELLA_READ_THAT_UART_DUDE);
readlen = in_data.data.uart_args.bytes;
@@ -226,12 +235,16 @@ public:
/***********************************************************************
* Send/Recv over control
**********************************************************************/
- usrp2_ctrl_data_t ctrl_send_and_recv(const usrp2_ctrl_data_t &out_data){
+ usrp2_ctrl_data_t ctrl_send_and_recv(
+ const usrp2_ctrl_data_t &out_data,
+ boost::uint32_t lo = USRP2_FW_COMPAT_NUM,
+ boost::uint32_t hi = USRP2_FW_COMPAT_NUM
+ ){
boost::mutex::scoped_lock lock(_ctrl_mutex);
//fill in the seq number and send
usrp2_ctrl_data_t out_copy = out_data;
- out_copy.proto_ver = htonl(USRP2_FW_COMPAT_NUM);
+ out_copy.proto_ver = htonl(_protocol_compat);
out_copy.seq = htonl(++_ctrl_seq_num);
_ctrl_transport->send(boost::asio::buffer(&out_copy, sizeof(usrp2_ctrl_data_t)));
@@ -240,11 +253,14 @@ public:
const usrp2_ctrl_data_t *ctrl_data_in = reinterpret_cast<const usrp2_ctrl_data_t *>(usrp2_ctrl_data_in_mem);
while(true){
size_t len = _ctrl_transport->recv(boost::asio::buffer(usrp2_ctrl_data_in_mem), CTRL_RECV_TIMEOUT);
- if(len >= sizeof(boost::uint32_t) and ntohl(ctrl_data_in->proto_ver) != USRP2_FW_COMPAT_NUM){
+ boost::uint32_t compat = ntohl(ctrl_data_in->proto_ver);
+ if(len >= sizeof(boost::uint32_t) and (hi < compat or lo > compat)){
throw uhd::runtime_error(str(boost::format(
- "Expected protocol compatibility number %d, but got %d:\n"
+ "\nPlease update the firmware and FPGA images for your device.\n"
+ "See the application notes for USRP2/N-Series for instructions.\n"
+ "Expected protocol compatibility number %s, but got %d:\n"
"The firmware build is not compatible with the host code build."
- ) % int(USRP2_FW_COMPAT_NUM) % ntohl(ctrl_data_in->proto_ver)));
+ ) % ((lo == hi)? (boost::format("%d") % hi) : (boost::format("[%d to %d]") % lo % hi)) % compat));
}
if (len >= sizeof(usrp2_ctrl_data_t) and ntohl(ctrl_data_in->seq) == _ctrl_seq_num){
return *ctrl_data_in;
@@ -284,6 +300,7 @@ private:
//used in send/recv
boost::mutex _ctrl_mutex;
boost::uint32_t _ctrl_seq_num;
+ boost::uint32_t _protocol_compat;
/***********************************************************************
* Private Templated Peek and Poke
@@ -297,7 +314,7 @@ private:
out_data.data.poke_args.num_bytes = sizeof(T);
//send and recv
- usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data);
+ usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data, MIN_PROTO_COMPAT_REG);
UHD_ASSERT_THROW(ntohl(in_data.id) == USRP2_CTRL_ID_OMG_POKED_REGISTER_SO_BAD_DUDE);
}
@@ -309,7 +326,7 @@ private:
out_data.data.poke_args.num_bytes = sizeof(T);
//send and recv
- usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data);
+ usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data, MIN_PROTO_COMPAT_REG);
UHD_ASSERT_THROW(ntohl(in_data.id) == USRP2_CTRL_ID_WOAH_I_DEFINITELY_PEEKED_IT_DUDE);
return T(ntohl(in_data.data.poke_args.data));
}
diff --git a/host/lib/usrp/usrp2/usrp2_iface.hpp b/host/lib/usrp/usrp2/usrp2_iface.hpp
index df53ec66a..08f3955f1 100644
--- a/host/lib/usrp/usrp2/usrp2_iface.hpp
+++ b/host/lib/usrp/usrp2/usrp2_iface.hpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 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
diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp
index 96552929a..cb92b1921 100644
--- a/host/lib/usrp/usrp2/usrp2_impl.cpp
+++ b/host/lib/usrp/usrp2/usrp2_impl.cpp
@@ -171,6 +171,15 @@ static mtu_result_t determine_mtu(const std::string &addr){
usrp2_ctrl_data_t *ctrl_data = reinterpret_cast<usrp2_ctrl_data_t *>(buffer);
static const double echo_timeout = 0.020; //20 ms
+ //test holler - check if its supported in this fw version
+ ctrl_data->id = htonl(USRP2_CTRL_ID_HOLLER_AT_ME_BRO);
+ ctrl_data->proto_ver = htonl(USRP2_FW_COMPAT_NUM);
+ ctrl_data->data.echo_args.len = htonl(sizeof(usrp2_ctrl_data_t));
+ udp_sock->send(boost::asio::buffer(buffer, sizeof(usrp2_ctrl_data_t)));
+ udp_sock->recv(boost::asio::buffer(buffer), echo_timeout);
+ if (ntohl(ctrl_data->id) != USRP2_CTRL_ID_HOLLER_BACK_DUDE)
+ throw uhd::not_implemented_error("holler protocol not implemented");
+
size_t min_recv_mtu = sizeof(usrp2_ctrl_data_t), max_recv_mtu = sizeof(buffer);
size_t min_send_mtu = sizeof(usrp2_ctrl_data_t), max_send_mtu = sizeof(buffer);
@@ -233,23 +242,31 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){
device_addrs_t device_args = separate_device_addr(device_addr);
- //calculate the minimum send and recv mtu of all devices
- mtu_result_t mtu = determine_mtu(device_args[0]["addr"]);
- for (size_t i = 1; i < device_args.size(); i++){
- mtu_result_t mtu_i = determine_mtu(device_args[i]["addr"]);
- mtu.recv_mtu = std::min(mtu.recv_mtu, mtu_i.recv_mtu);
- mtu.send_mtu = std::min(mtu.send_mtu, mtu_i.send_mtu);
- }
+ try{
+ //calculate the minimum send and recv mtu of all devices
+ mtu_result_t mtu = determine_mtu(device_args[0]["addr"]);
+ for (size_t i = 1; i < device_args.size(); i++){
+ mtu_result_t mtu_i = determine_mtu(device_args[i]["addr"]);
+ mtu.recv_mtu = std::min(mtu.recv_mtu, mtu_i.recv_mtu);
+ mtu.send_mtu = std::min(mtu.send_mtu, mtu_i.send_mtu);
+ }
- std::cout << "mtu recv bytes " << mtu.recv_mtu << std::endl;
- std::cout << "mtu send bytes " << mtu.send_mtu << std::endl;
+ //use the discovered mtu or clip the users requested mtu
+ mtu.recv_mtu = std::min(size_t(device_addr.cast<double>("recv_frame_size", 9000)), mtu.recv_mtu);
+ mtu.send_mtu = std::min(size_t(device_addr.cast<double>("send_frame_size", 9000)), mtu.send_mtu);
- //use the discovered mtu if not specified by the user
- if (not device_addr.has_key("recv_frame_size"))
device_addr["recv_frame_size"] = boost::lexical_cast<std::string>(mtu.recv_mtu);
- if (not device_addr.has_key("send_frame_size"))
device_addr["send_frame_size"] = boost::lexical_cast<std::string>(mtu.send_mtu);
+ std::cout << boost::format("Current recv frame size: %d bytes") % mtu.recv_mtu << std::endl;
+ std::cout << boost::format("Current send frame size: %d bytes") % mtu.send_mtu << std::endl;
+ }
+ catch(const uhd::not_implemented_error &){
+ //just ignore this error, makes older fw work...
+ }
+
+ device_args = separate_device_addr(device_addr); //update args for new frame sizes
+
//setup rx otw type
_rx_otw_type.width = 16;
_rx_otw_type.shift = 0;
diff --git a/host/lib/usrp/usrp_e100/CMakeLists.txt b/host/lib/usrp/usrp_e100/CMakeLists.txt
index acbac177e..d0e20a3d8 100644
--- a/host/lib/usrp/usrp_e100/CMakeLists.txt
+++ b/host/lib/usrp/usrp_e100/CMakeLists.txt
@@ -22,11 +22,7 @@
########################################################################
# Conditionally configure the USRP-E100 support
########################################################################
-IF(CMAKE_SYSTEM_NAME STREQUAL "Linux")
- SET(LINUX_TARGET TRUE)
-ENDIF(CMAKE_SYSTEM_NAME STREQUAL "Linux")
-
-LIBUHD_REGISTER_COMPONENT("USRP-E100" ENABLE_USRP_E100 OFF "ENABLE_LIBUHD;LINUX_TARGET" OFF)
+LIBUHD_REGISTER_COMPONENT("USRP-E100" ENABLE_USRP_E100 OFF "ENABLE_LIBUHD;LINUX" OFF)
IF(ENABLE_USRP_E100)
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include)
diff --git a/host/lib/usrp/usrp_e100/clock_ctrl.cpp b/host/lib/usrp/usrp_e100/clock_ctrl.cpp
index bb6fb7e3b..1ac2b804c 100644
--- a/host/lib/usrp/usrp_e100/clock_ctrl.cpp
+++ b/host/lib/usrp/usrp_e100/clock_ctrl.cpp
@@ -287,6 +287,10 @@ public:
if (_out_rate == rate) return;
if (rate == 61.44e6) set_clock_settings_with_external_vcxo(rate);
else set_clock_settings_with_internal_vco(rate);
+ //clock rate changed! update dboard clocks and FPGA ticks per second
+ set_rx_dboard_clock_rate(rate);
+ set_tx_dboard_clock_rate(rate);
+ _iface->poke32(UE_REG_TIME64_TPS, boost::uint32_t(get_fpga_clock_rate()));
}
double get_fpga_clock_rate(void){
@@ -302,7 +306,7 @@ public:
_ad9522_regs.out4_cmos_configuration = (enb)?
ad9522_regs_t::OUT4_CMOS_CONFIGURATION_A_ON :
ad9522_regs_t::OUT4_CMOS_CONFIGURATION_OFF;
- this->send_reg(0x0F0);
+ this->send_reg(0x0F4);
this->latch_regs();
}
@@ -327,6 +331,7 @@ public:
void set_rx_dboard_clock_rate(double rate){
assert_has(get_rx_dboard_clock_rates(), rate, "rx dboard clock rate");
+ _rx_clock_rate = rate;
size_t divider = size_t(this->_chan_rate/rate);
//set the divider registers
set_clock_divider(divider,
@@ -339,6 +344,10 @@ public:
this->latch_regs();
}
+ double get_rx_clock_rate(void){
+ return _rx_clock_rate;
+ }
+
/***********************************************************************
* TX Dboard Clock Control (output 6, divider 2)
**********************************************************************/
@@ -357,6 +366,7 @@ public:
void set_tx_dboard_clock_rate(double rate){
assert_has(get_tx_dboard_clock_rates(), rate, "tx dboard clock rate");
+ _tx_clock_rate = rate;
size_t divider = size_t(this->_chan_rate/rate);
//set the divider registers
set_clock_divider(divider,
@@ -368,7 +378,11 @@ public:
this->send_reg(0x197);
this->latch_regs();
}
-
+
+ double get_tx_clock_rate(void){
+ return _tx_clock_rate;
+ }
+
/***********************************************************************
* Clock reference control
**********************************************************************/
@@ -400,6 +414,7 @@ private:
ad9522_regs_t _ad9522_regs;
double _out_rate; //rate at the fpga and codec
double _chan_rate; //rate before final dividers
+ double _rx_clock_rate, _tx_clock_rate;
void latch_regs(void){
_ad9522_regs.io_update = 1;
diff --git a/host/lib/usrp/usrp_e100/clock_ctrl.hpp b/host/lib/usrp/usrp_e100/clock_ctrl.hpp
index 1f9960ce4..507f914f3 100644
--- a/host/lib/usrp/usrp_e100/clock_ctrl.hpp
+++ b/host/lib/usrp/usrp_e100/clock_ctrl.hpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 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
@@ -79,6 +79,18 @@ public:
virtual void set_tx_dboard_clock_rate(double rate) = 0;
/*!
+ * Get the current rx dboard clock rate.
+ * \return the clock rate in Hz
+ */
+ virtual double get_rx_clock_rate(void) = 0;
+
+ /*!
+ * Get the current tx dboard clock rate.
+ * \return the clock rate in Hz
+ */
+ virtual double get_tx_clock_rate(void) = 0;
+
+ /*!
* Enable/disable the rx dboard clock.
* \param enb true to enable
*/
diff --git a/host/lib/usrp/usrp_e100/dboard_iface.cpp b/host/lib/usrp/usrp_e100/dboard_iface.cpp
index 4ee354486..61b5a1c92 100644
--- a/host/lib/usrp/usrp_e100/dboard_iface.cpp
+++ b/host/lib/usrp/usrp_e100/dboard_iface.cpp
@@ -97,7 +97,6 @@ private:
usrp_e100_iface::sptr _iface;
usrp_e100_clock_ctrl::sptr _clock;
usrp_e100_codec_ctrl::sptr _codec;
- uhd::dict<unit_t, double> _clock_rates;
};
/***********************************************************************
@@ -115,7 +114,6 @@ dboard_iface::sptr make_usrp_e100_dboard_iface(
* Clock Rates
**********************************************************************/
void usrp_e100_dboard_iface::set_clock_rate(unit_t unit, double rate){
- _clock_rates[unit] = rate;
switch(unit){
case UNIT_RX: return _clock->set_rx_dboard_clock_rate(rate);
case UNIT_TX: return _clock->set_tx_dboard_clock_rate(rate);
@@ -131,7 +129,11 @@ std::vector<double> usrp_e100_dboard_iface::get_clock_rates(unit_t unit){
}
double usrp_e100_dboard_iface::get_clock_rate(unit_t unit){
- return _clock_rates[unit];
+ switch(unit){
+ case UNIT_RX: return _clock->get_rx_clock_rate();
+ case UNIT_TX: return _clock->get_tx_clock_rate();
+ }
+ UHD_THROW_INVALID_CODE_PATH();
}
void usrp_e100_dboard_iface::set_clock_enabled(unit_t unit, bool enb){
diff --git a/host/lib/usrp/usrp_e100/io_impl.cpp b/host/lib/usrp/usrp_e100/io_impl.cpp
index fc6aaeaee..cbab5a761 100644
--- a/host/lib/usrp/usrp_e100/io_impl.cpp
+++ b/host/lib/usrp/usrp_e100/io_impl.cpp
@@ -23,7 +23,8 @@
#include "../../transport/vrt_packet_handler.hpp"
#include <boost/bind.hpp>
#include <boost/format.hpp>
-#include <boost/thread.hpp>
+#include <boost/thread/thread.hpp>
+#include <boost/thread/barrier.hpp>
#include <iostream>
using namespace uhd;
@@ -93,7 +94,7 @@ struct usrp_e100_impl::io_impl{
bool continuous_streaming;
//a pirate's life is the life for me!
- void recv_pirate_loop(usrp_e100_clock_ctrl::sptr);
+ void recv_pirate_loop(boost::barrier &, usrp_e100_clock_ctrl::sptr);
bounded_buffer<managed_recv_buffer::sptr> recv_pirate_booty;
bounded_buffer<async_metadata_t> async_msg_fifo;
boost::thread_group recv_pirate_crew;
@@ -105,8 +106,10 @@ struct usrp_e100_impl::io_impl{
* - while raiding, loot for recv buffers
* - put booty into the alignment buffer
**********************************************************************/
-void usrp_e100_impl::io_impl::recv_pirate_loop(usrp_e100_clock_ctrl::sptr clock_ctrl)
-{
+void usrp_e100_impl::io_impl::recv_pirate_loop(
+ boost::barrier &spawn_barrier, usrp_e100_clock_ctrl::sptr clock_ctrl
+){
+ spawn_barrier.wait();
set_thread_priority_safe();
recv_pirate_crew_raiding = true;
@@ -201,9 +204,12 @@ void usrp_e100_impl::io_init(void){
_iface->poke32(UE_REG_CTRL_TX_POLICY, UE_FLAG_CTRL_TX_POLICY_NEXT_PACKET);
//spawn a pirate, yarrr!
+ boost::barrier spawn_barrier(2);
_io_impl->recv_pirate_crew.create_thread(boost::bind(
- &usrp_e100_impl::io_impl::recv_pirate_loop, _io_impl.get(), _clock_ctrl
+ &usrp_e100_impl::io_impl::recv_pirate_loop, _io_impl.get(),
+ boost::ref(spawn_barrier), _clock_ctrl
));
+ spawn_barrier.wait();
}
void usrp_e100_impl::issue_stream_cmd(const stream_cmd_t &stream_cmd){
diff --git a/host/lib/usrp/usrp_e100/mboard_impl.cpp b/host/lib/usrp/usrp_e100/mboard_impl.cpp
index cec4fd0ad..29e3c5da2 100644
--- a/host/lib/usrp/usrp_e100/mboard_impl.cpp
+++ b/host/lib/usrp/usrp_e100/mboard_impl.cpp
@@ -36,11 +36,6 @@ void usrp_e100_impl::mboard_init(void){
boost::bind(&usrp_e100_impl::mboard_set, this, _1, _2)
);
- //set the ticks per seconds into the vita time control
- _iface->poke32(UE_REG_TIME64_TPS,
- boost::uint32_t(_clock_ctrl->get_fpga_clock_rate())
- );
-
//init the clock config
_clock_config = clock_config_t::internal();
update_clock_config();
diff --git a/host/lib/usrp/usrp_e100/usrp_e100_iface.cpp b/host/lib/usrp/usrp_e100/usrp_e100_iface.cpp
index ec0baf490..55446da63 100644
--- a/host/lib/usrp/usrp_e100/usrp_e100_iface.cpp
+++ b/host/lib/usrp/usrp_e100/usrp_e100_iface.cpp
@@ -22,7 +22,7 @@
#include <fcntl.h> //open, close
#include <linux/usrp_e.h> //ioctl structures and constants
#include <boost/format.hpp>
-#include <boost/thread.hpp> //mutex
+#include <boost/thread/mutex.hpp>
#include <linux/i2c-dev.h>
#include <linux/i2c.h>
#include <stdexcept>
@@ -109,6 +109,15 @@ public:
throw uhd::io_error("Failed to open " + node);
}
+ //check the module compatibility number
+ int module_compat_num = ::ioctl(_node_fd, USRP_E_GET_COMPAT_NUMBER, NULL);
+ if (module_compat_num != USRP_E_COMPAT_NUMBER){
+ throw uhd::runtime_error(str(boost::format(
+ "Expected module compatibility number 0x%x, but got 0x%x:\n"
+ "The module build is not compatible with the host code build."
+ ) % USRP_E_COMPAT_NUMBER % module_compat_num));
+ }
+
mb_eeprom = mboard_eeprom_t(get_i2c_dev_iface(), mboard_eeprom_t::MAP_E100);
}
diff --git a/host/lib/usrp/usrp_e100/usrp_e100_iface.hpp b/host/lib/usrp/usrp_e100/usrp_e100_iface.hpp
index cb0ca2dd4..d9fe96db7 100644
--- a/host/lib/usrp/usrp_e100/usrp_e100_iface.hpp
+++ b/host/lib/usrp/usrp_e100/usrp_e100_iface.hpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 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
diff --git a/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp b/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp
index 1385688e0..a8fbe5d69 100644
--- a/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp
+++ b/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp
@@ -53,7 +53,7 @@ static device_addrs_t usrp_e100_find(const device_addr_t &hint){
if (fs::exists(hint["node"])){
device_addr_t new_addr;
new_addr["type"] = "usrp-e";
- new_addr["node"] = fs::system_complete(fs::path(hint["node"])).file_string();
+ new_addr["node"] = fs::system_complete(fs::path(hint["node"])).string();
try{
usrp_e100_iface::sptr iface = usrp_e100_iface::make(new_addr["node"]);
new_addr["name"] = iface->mb_eeprom["name"];
@@ -120,10 +120,10 @@ static device::sptr usrp_e100_make(const device_addr_t &device_addr){
try{std::ifstream(hash_file_path) >> loaded_hash;}catch(...){}
//if not loaded: load the fpga image and write the hash-file
- if (fpga_compat_num != USRP_E_COMPAT_NUM or loaded_hash != fpga_hash){
+ if (fpga_compat_num != USRP_E_FPGA_COMPAT_NUM or loaded_hash != fpga_hash){
iface.reset();
usrp_e100_load_fpga(usrp_e100_fpga_image);
- sleep(1); ///\todo do this better one day.
+ sleep(1); ///\todo do this better one day.
std::cout << boost::format("re-Opening USRP-E on %s") % node << std::endl;
iface = usrp_e100_iface::make(node);
try{std::ofstream(hash_file_path) << fpga_hash;}catch(...){}
@@ -131,11 +131,11 @@ static device::sptr usrp_e100_make(const device_addr_t &device_addr){
//check that the compatibility is correct
fpga_compat_num = iface->peek16(UE_REG_MISC_COMPAT);
- if (fpga_compat_num != USRP_E_COMPAT_NUM){
+ if (fpga_compat_num != USRP_E_FPGA_COMPAT_NUM){
throw uhd::runtime_error(str(boost::format(
"Expected fpga compatibility number 0x%x, but got 0x%x:\n"
"The fpga build is not compatible with the host code build."
- ) % USRP_E_COMPAT_NUM % fpga_compat_num));
+ ) % USRP_E_FPGA_COMPAT_NUM % fpga_compat_num));
}
return device::sptr(new usrp_e100_impl(iface));
diff --git a/host/lib/usrp/usrp_e100/usrp_e100_impl.hpp b/host/lib/usrp/usrp_e100/usrp_e100_impl.hpp
index 897616320..98117cf26 100644
--- a/host/lib/usrp/usrp_e100/usrp_e100_impl.hpp
+++ b/host/lib/usrp/usrp_e100/usrp_e100_impl.hpp
@@ -30,7 +30,7 @@
#ifndef INCLUDED_USRP_E100_IMPL_HPP
#define INCLUDED_USRP_E100_IMPL_HPP
-static const boost::uint16_t USRP_E_COMPAT_NUM = 0x03;
+static const boost::uint16_t USRP_E_FPGA_COMPAT_NUM = 0x03;
//! load an fpga image from a bin file into the usrp-e fpga
extern void usrp_e100_load_fpga(const std::string &bin_file);