diff options
Diffstat (limited to 'host/lib/usrp/usrp2')
-rw-r--r-- | host/lib/usrp/usrp2/clock_ctrl.cpp | 474 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/clock_ctrl.hpp | 8 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/codec_ctrl.cpp | 308 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/codec_ctrl.hpp | 6 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/dboard_iface.cpp | 317 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/io_impl.cpp | 497 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/mb_eeprom.cpp | 251 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/n200_image_loader.cpp | 529 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/usrp2_clk_regs.hpp | 138 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/usrp2_fifo_ctrl.cpp | 181 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/usrp2_fifo_ctrl.hpp | 8 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/usrp2_iface.cpp | 479 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/usrp2_iface.hpp | 22 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/usrp2_impl.cpp | 1099 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/usrp2_impl.hpp | 114 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/usrp2_regs.hpp | 88 |
16 files changed, 2448 insertions, 2071 deletions
diff --git a/host/lib/usrp/usrp2/clock_ctrl.cpp b/host/lib/usrp/usrp2/clock_ctrl.cpp index 40f7c75f6..19a7fc1c5 100644 --- a/host/lib/usrp/usrp2/clock_ctrl.cpp +++ b/host/lib/usrp/usrp2/clock_ctrl.cpp @@ -8,10 +8,10 @@ #include "clock_ctrl.hpp" #include "ad9510_regs.hpp" -#include "usrp2_regs.hpp" //spi slave constants #include "usrp2_clk_regs.hpp" -#include <uhd/utils/safe_call.hpp> +#include "usrp2_regs.hpp" //spi slave constants #include <uhd/utils/assert_has.hpp> +#include <uhd/utils/safe_call.hpp> #include <uhdlib/utils/narrow.hpp> #include <stdint.h> #include <boost/math/special_functions/round.hpp> @@ -21,17 +21,20 @@ using namespace uhd; static const bool enb_test_clk = false; -usrp2_clock_ctrl::~usrp2_clock_ctrl(void){ +usrp2_clock_ctrl::~usrp2_clock_ctrl(void) +{ /* NOP */ } /*! * A usrp2 clock control specific to the ad9510 ic. */ -class usrp2_clock_ctrl_impl : public usrp2_clock_ctrl{ +class usrp2_clock_ctrl_impl : public usrp2_clock_ctrl +{ public: - usrp2_clock_ctrl_impl(usrp2_iface::sptr iface, uhd::spi_iface::sptr spiface){ - _iface = iface; + usrp2_clock_ctrl_impl(usrp2_iface::sptr iface, uhd::spi_iface::sptr spiface) + { + _iface = iface; _spiface = spiface; clk_regs = usrp2_clk_regs_t(_iface->get_rev()); @@ -44,7 +47,7 @@ public: // But why not leave it in for those who want to mess with clock settings? // 100mhz = 10mhz/R * (P*B + A) - _ad9510_regs.pll_power_down = ad9510_regs_t::PLL_POWER_DOWN_NORMAL; + _ad9510_regs.pll_power_down = ad9510_regs_t::PLL_POWER_DOWN_NORMAL; _ad9510_regs.prescaler_value = ad9510_regs_t::PRESCALER_VALUE_DIV2; this->write_reg(clk_regs.pll_4); @@ -74,181 +77,213 @@ public: this->enable_test_clock(enb_test_clk); } - ~usrp2_clock_ctrl_impl(void){UHD_SAFE_CALL( - //power down clock outputs - this->enable_external_ref(false); - this->enable_rx_dboard_clock(false); - this->enable_tx_dboard_clock(false); - this->enable_dac_clock(false); - this->enable_adc_clock(false); - this->enable_mimo_clock_out(false); - this->enable_test_clock(false); - )} - - void enable_mimo_clock_out(bool enb){ - //calculate the low and high dividers - size_t divider = size_t(this->get_master_clock_rate()/10e6); - size_t high = divider/2; - size_t low = divider - high; - - switch(clk_regs.exp){ - case 2: //U2 rev 3 - _ad9510_regs.power_down_lvpecl_out2 = enb? - ad9510_regs_t::POWER_DOWN_LVPECL_OUT2_NORMAL : - ad9510_regs_t::POWER_DOWN_LVPECL_OUT2_SAFE_PD; - _ad9510_regs.output_level_lvpecl_out2 = ad9510_regs_t::OUTPUT_LEVEL_LVPECL_OUT2_810MV; - //set the registers (divider - 1) - _ad9510_regs.divider_low_cycles_out2 = uhd::narrow_cast<uint8_t>(low - 1); - _ad9510_regs.divider_high_cycles_out2 = uhd::narrow_cast<uint8_t>(high - 1); - _ad9510_regs.bypass_divider_out2 = 0; - break; - - case 5: //U2 rev 4 - _ad9510_regs.power_down_lvds_cmos_out5 = enb? 0 : 1; - _ad9510_regs.lvds_cmos_select_out5 = ad9510_regs_t::LVDS_CMOS_SELECT_OUT5_LVDS; - _ad9510_regs.output_level_lvds_out5 = ad9510_regs_t::OUTPUT_LEVEL_LVDS_OUT5_1_75MA; - //set the registers (divider - 1) - _ad9510_regs.divider_low_cycles_out5 = uhd::narrow_cast<uint8_t>(low - 1); - _ad9510_regs.divider_high_cycles_out5 = uhd::narrow_cast<uint8_t>(high - 1); - _ad9510_regs.bypass_divider_out5 = 0; - break; - - case 6: //U2+ - _ad9510_regs.power_down_lvds_cmos_out6 = enb? 0 : 1; - _ad9510_regs.lvds_cmos_select_out6 = ad9510_regs_t::LVDS_CMOS_SELECT_OUT6_LVDS; - _ad9510_regs.output_level_lvds_out6 = ad9510_regs_t::OUTPUT_LEVEL_LVDS_OUT6_1_75MA; - //set the registers (divider - 1) - _ad9510_regs.divider_low_cycles_out6 = uhd::narrow_cast<uint8_t>(low - 1); - _ad9510_regs.divider_high_cycles_out6 = uhd::narrow_cast<uint8_t>(high - 1); - _ad9510_regs.bypass_divider_out5 = 0; - break; - - default: - break; + ~usrp2_clock_ctrl_impl(void) + { + UHD_SAFE_CALL( + // power down clock outputs + this->enable_external_ref(false); this->enable_rx_dboard_clock(false); + this->enable_tx_dboard_clock(false); + this->enable_dac_clock(false); + this->enable_adc_clock(false); + this->enable_mimo_clock_out(false); + this->enable_test_clock(false);) + } + + void enable_mimo_clock_out(bool enb) + { + // calculate the low and high dividers + size_t divider = size_t(this->get_master_clock_rate() / 10e6); + size_t high = divider / 2; + size_t low = divider - high; + + switch (clk_regs.exp) { + case 2: // U2 rev 3 + _ad9510_regs.power_down_lvpecl_out2 = + enb ? ad9510_regs_t::POWER_DOWN_LVPECL_OUT2_NORMAL + : ad9510_regs_t::POWER_DOWN_LVPECL_OUT2_SAFE_PD; + _ad9510_regs.output_level_lvpecl_out2 = + ad9510_regs_t::OUTPUT_LEVEL_LVPECL_OUT2_810MV; + // set the registers (divider - 1) + _ad9510_regs.divider_low_cycles_out2 = uhd::narrow_cast<uint8_t>(low - 1); + _ad9510_regs.divider_high_cycles_out2 = + uhd::narrow_cast<uint8_t>(high - 1); + _ad9510_regs.bypass_divider_out2 = 0; + break; + + case 5: // U2 rev 4 + _ad9510_regs.power_down_lvds_cmos_out5 = enb ? 0 : 1; + _ad9510_regs.lvds_cmos_select_out5 = + ad9510_regs_t::LVDS_CMOS_SELECT_OUT5_LVDS; + _ad9510_regs.output_level_lvds_out5 = + ad9510_regs_t::OUTPUT_LEVEL_LVDS_OUT5_1_75MA; + // set the registers (divider - 1) + _ad9510_regs.divider_low_cycles_out5 = uhd::narrow_cast<uint8_t>(low - 1); + _ad9510_regs.divider_high_cycles_out5 = + uhd::narrow_cast<uint8_t>(high - 1); + _ad9510_regs.bypass_divider_out5 = 0; + break; + + case 6: // U2+ + _ad9510_regs.power_down_lvds_cmos_out6 = enb ? 0 : 1; + _ad9510_regs.lvds_cmos_select_out6 = + ad9510_regs_t::LVDS_CMOS_SELECT_OUT6_LVDS; + _ad9510_regs.output_level_lvds_out6 = + ad9510_regs_t::OUTPUT_LEVEL_LVDS_OUT6_1_75MA; + // set the registers (divider - 1) + _ad9510_regs.divider_low_cycles_out6 = uhd::narrow_cast<uint8_t>(low - 1); + _ad9510_regs.divider_high_cycles_out6 = + uhd::narrow_cast<uint8_t>(high - 1); + _ad9510_regs.bypass_divider_out5 = 0; + break; + + default: + break; } this->write_reg(clk_regs.output(clk_regs.exp)); this->write_reg(clk_regs.div_lo(clk_regs.exp)); this->update_regs(); } - //uses output clock 7 (cmos) - void enable_rx_dboard_clock(bool enb){ - switch(_iface->get_rev()) { + // uses output clock 7 (cmos) + void enable_rx_dboard_clock(bool enb) + { + switch (_iface->get_rev()) { case usrp2_iface::USRP_N200_R4: case usrp2_iface::USRP_N210_R4: - _ad9510_regs.power_down_lvds_cmos_out7 = enb? 0 : 1; - _ad9510_regs.lvds_cmos_select_out7 = ad9510_regs_t::LVDS_CMOS_SELECT_OUT7_LVDS; - _ad9510_regs.output_level_lvds_out7 = ad9510_regs_t::OUTPUT_LEVEL_LVDS_OUT7_1_75MA; + _ad9510_regs.power_down_lvds_cmos_out7 = enb ? 0 : 1; + _ad9510_regs.lvds_cmos_select_out7 = + ad9510_regs_t::LVDS_CMOS_SELECT_OUT7_LVDS; + _ad9510_regs.output_level_lvds_out7 = + ad9510_regs_t::OUTPUT_LEVEL_LVDS_OUT7_1_75MA; this->write_reg(clk_regs.output(clk_regs.rx_db)); this->update_regs(); break; default: - _ad9510_regs.power_down_lvds_cmos_out7 = enb? 0 : 1; - _ad9510_regs.lvds_cmos_select_out7 = ad9510_regs_t::LVDS_CMOS_SELECT_OUT7_CMOS; - _ad9510_regs.output_level_lvds_out7 = ad9510_regs_t::OUTPUT_LEVEL_LVDS_OUT7_1_75MA; + _ad9510_regs.power_down_lvds_cmos_out7 = enb ? 0 : 1; + _ad9510_regs.lvds_cmos_select_out7 = + ad9510_regs_t::LVDS_CMOS_SELECT_OUT7_CMOS; + _ad9510_regs.output_level_lvds_out7 = + ad9510_regs_t::OUTPUT_LEVEL_LVDS_OUT7_1_75MA; this->write_reg(clk_regs.output(clk_regs.rx_db)); this->update_regs(); break; } } - void set_rate_rx_dboard_clock(double rate){ + void set_rate_rx_dboard_clock(double rate) + { assert_has(get_rates_rx_dboard_clock(), rate, "rx dboard clock rate"); - size_t divider = size_t(get_master_clock_rate()/rate); - //bypass when the divider ratio is one - _ad9510_regs.bypass_divider_out7 = (divider == 1)? 1 : 0; - //calculate the low and high dividers - size_t high = divider/2; - size_t low = divider - high; - //set the registers (divider - 1) - _ad9510_regs.divider_low_cycles_out7 = uhd::narrow_cast<uint8_t>(low - 1); + size_t divider = size_t(get_master_clock_rate() / rate); + // bypass when the divider ratio is one + _ad9510_regs.bypass_divider_out7 = (divider == 1) ? 1 : 0; + // calculate the low and high dividers + size_t high = divider / 2; + size_t low = divider - high; + // set the registers (divider - 1) + _ad9510_regs.divider_low_cycles_out7 = uhd::narrow_cast<uint8_t>(low - 1); _ad9510_regs.divider_high_cycles_out7 = uhd::narrow_cast<uint8_t>(high - 1); - //write the registers + // write the registers this->write_reg(clk_regs.div_lo(clk_regs.rx_db)); this->write_reg(clk_regs.div_hi(clk_regs.rx_db)); this->update_regs(); } - std::vector<double> get_rates_rx_dboard_clock(void){ + std::vector<double> get_rates_rx_dboard_clock(void) + { std::vector<double> rates; - for (size_t i = 1; i <= 16+16; i++) rates.push_back(get_master_clock_rate()/i); + for (size_t i = 1; i <= 16 + 16; i++) + rates.push_back(get_master_clock_rate() / i); return rates; } - //uses output clock 6 (cmos) on USRP2, output clock 5 (cmos) on N200/N210 r3, - //and output clock 5 (lvds) on N200/N210 r4 - void enable_tx_dboard_clock(bool enb){ - switch(_iface->get_rev()) { - case usrp2_iface::USRP_N200_R4: - case usrp2_iface::USRP_N210_R4: - _ad9510_regs.power_down_lvds_cmos_out5 = enb? 0 : 1; - _ad9510_regs.lvds_cmos_select_out5 = ad9510_regs_t::LVDS_CMOS_SELECT_OUT5_LVDS; - _ad9510_regs.output_level_lvds_out5 = ad9510_regs_t::OUTPUT_LEVEL_LVDS_OUT5_1_75MA; - break; - case usrp2_iface::USRP_N200: - case usrp2_iface::USRP_N210: - _ad9510_regs.power_down_lvds_cmos_out5 = enb? 0 : 1; - _ad9510_regs.lvds_cmos_select_out5 = ad9510_regs_t::LVDS_CMOS_SELECT_OUT5_CMOS; - _ad9510_regs.output_level_lvds_out5 = ad9510_regs_t::OUTPUT_LEVEL_LVDS_OUT5_1_75MA; - break; - case usrp2_iface::USRP2_REV3: - case usrp2_iface::USRP2_REV4: - _ad9510_regs.power_down_lvds_cmos_out6 = enb? 0 : 1; - _ad9510_regs.lvds_cmos_select_out6 = ad9510_regs_t::LVDS_CMOS_SELECT_OUT6_CMOS; - _ad9510_regs.output_level_lvds_out6 = ad9510_regs_t::OUTPUT_LEVEL_LVDS_OUT6_1_75MA; - break; - - default: - //throw uhd::not_implemented_error("enable_tx_dboard_clock: unknown hardware version"); - break; + // uses output clock 6 (cmos) on USRP2, output clock 5 (cmos) on N200/N210 r3, + // and output clock 5 (lvds) on N200/N210 r4 + void enable_tx_dboard_clock(bool enb) + { + switch (_iface->get_rev()) { + case usrp2_iface::USRP_N200_R4: + case usrp2_iface::USRP_N210_R4: + _ad9510_regs.power_down_lvds_cmos_out5 = enb ? 0 : 1; + _ad9510_regs.lvds_cmos_select_out5 = + ad9510_regs_t::LVDS_CMOS_SELECT_OUT5_LVDS; + _ad9510_regs.output_level_lvds_out5 = + ad9510_regs_t::OUTPUT_LEVEL_LVDS_OUT5_1_75MA; + break; + case usrp2_iface::USRP_N200: + case usrp2_iface::USRP_N210: + _ad9510_regs.power_down_lvds_cmos_out5 = enb ? 0 : 1; + _ad9510_regs.lvds_cmos_select_out5 = + ad9510_regs_t::LVDS_CMOS_SELECT_OUT5_CMOS; + _ad9510_regs.output_level_lvds_out5 = + ad9510_regs_t::OUTPUT_LEVEL_LVDS_OUT5_1_75MA; + break; + case usrp2_iface::USRP2_REV3: + case usrp2_iface::USRP2_REV4: + _ad9510_regs.power_down_lvds_cmos_out6 = enb ? 0 : 1; + _ad9510_regs.lvds_cmos_select_out6 = + ad9510_regs_t::LVDS_CMOS_SELECT_OUT6_CMOS; + _ad9510_regs.output_level_lvds_out6 = + ad9510_regs_t::OUTPUT_LEVEL_LVDS_OUT6_1_75MA; + break; + + default: + // throw uhd::not_implemented_error("enable_tx_dboard_clock: unknown + // hardware version"); + break; } this->write_reg(clk_regs.output(clk_regs.tx_db)); this->update_regs(); } - void set_rate_tx_dboard_clock(double rate){ + void set_rate_tx_dboard_clock(double rate) + { assert_has(get_rates_tx_dboard_clock(), rate, "tx dboard clock rate"); - size_t divider = size_t(get_master_clock_rate()/rate); - //bypass when the divider ratio is one - _ad9510_regs.bypass_divider_out6 = (divider == 1)? 1 : 0; - //calculate the low and high dividers - size_t high = divider/2; - size_t low = divider - high; - - switch(clk_regs.tx_db) { - case 5: //USRP2+ - _ad9510_regs.bypass_divider_out5 = (divider == 1)? 1 : 0; - _ad9510_regs.divider_low_cycles_out5 = uhd::narrow_cast<uint8_t>(low - 1); - _ad9510_regs.divider_high_cycles_out5 = uhd::narrow_cast<uint8_t>(high - 1); - break; - case 6: //USRP2 - //bypass when the divider ratio is one - _ad9510_regs.bypass_divider_out6 = (divider == 1)? 1 : 0; - //set the registers (divider - 1) - _ad9510_regs.divider_low_cycles_out6 = uhd::narrow_cast<uint8_t>(low - 1); - _ad9510_regs.divider_high_cycles_out6 = uhd::narrow_cast<uint8_t>(high - 1); - break; + size_t divider = size_t(get_master_clock_rate() / rate); + // bypass when the divider ratio is one + _ad9510_regs.bypass_divider_out6 = (divider == 1) ? 1 : 0; + // calculate the low and high dividers + size_t high = divider / 2; + size_t low = divider - high; + + switch (clk_regs.tx_db) { + case 5: // USRP2+ + _ad9510_regs.bypass_divider_out5 = (divider == 1) ? 1 : 0; + _ad9510_regs.divider_low_cycles_out5 = uhd::narrow_cast<uint8_t>(low - 1); + _ad9510_regs.divider_high_cycles_out5 = + uhd::narrow_cast<uint8_t>(high - 1); + break; + case 6: // USRP2 + // bypass when the divider ratio is one + _ad9510_regs.bypass_divider_out6 = (divider == 1) ? 1 : 0; + // set the registers (divider - 1) + _ad9510_regs.divider_low_cycles_out6 = uhd::narrow_cast<uint8_t>(low - 1); + _ad9510_regs.divider_high_cycles_out6 = + uhd::narrow_cast<uint8_t>(high - 1); + break; } - //write the registers + // write the registers this->write_reg(clk_regs.div_hi(clk_regs.tx_db)); this->write_reg(clk_regs.div_lo(clk_regs.tx_db)); this->update_regs(); } - std::vector<double> get_rates_tx_dboard_clock(void){ - return get_rates_rx_dboard_clock(); //same master clock, same dividers... + std::vector<double> get_rates_tx_dboard_clock(void) + { + return get_rates_rx_dboard_clock(); // same master clock, same dividers... } - - void enable_test_clock(bool enb) { - _ad9510_regs.power_down_lvpecl_out0 = enb? - ad9510_regs_t::POWER_DOWN_LVPECL_OUT0_NORMAL : - ad9510_regs_t::POWER_DOWN_LVPECL_OUT0_SAFE_PD; - _ad9510_regs.output_level_lvpecl_out0 = ad9510_regs_t::OUTPUT_LEVEL_LVPECL_OUT0_810MV; - _ad9510_regs.divider_low_cycles_out0 = 0; + + void enable_test_clock(bool enb) + { + _ad9510_regs.power_down_lvpecl_out0 = + enb ? ad9510_regs_t::POWER_DOWN_LVPECL_OUT0_NORMAL + : ad9510_regs_t::POWER_DOWN_LVPECL_OUT0_SAFE_PD; + _ad9510_regs.output_level_lvpecl_out0 = + ad9510_regs_t::OUTPUT_LEVEL_LVPECL_OUT0_810MV; + _ad9510_regs.divider_low_cycles_out0 = 0; _ad9510_regs.divider_high_cycles_out0 = 0; - _ad9510_regs.bypass_divider_out0 = 1; + _ad9510_regs.bypass_divider_out0 = 1; this->write_reg(0x3c); this->write_reg(0x48); this->write_reg(0x49); @@ -258,64 +293,69 @@ public: * If we are to use an external reference, enable the charge pump. * \param enb true to enable the CP */ - void enable_external_ref(bool enb){ - _ad9510_regs.charge_pump_mode = (enb)? - ad9510_regs_t::CHARGE_PUMP_MODE_NORMAL : - ad9510_regs_t::CHARGE_PUMP_MODE_3STATE ; + void enable_external_ref(bool enb) + { + _ad9510_regs.charge_pump_mode = (enb) ? ad9510_regs_t::CHARGE_PUMP_MODE_NORMAL + : ad9510_regs_t::CHARGE_PUMP_MODE_3STATE; _ad9510_regs.pll_mux_control = ad9510_regs_t::PLL_MUX_CONTROL_DLD_HIGH; - _ad9510_regs.pfd_polarity = ad9510_regs_t::PFD_POLARITY_POS; + _ad9510_regs.pfd_polarity = ad9510_regs_t::PFD_POLARITY_POS; this->write_reg(clk_regs.pll_2); this->update_regs(); } - double get_master_clock_rate(void){ + double get_master_clock_rate(void) + { return 100e6; } - - void set_mimo_clock_delay(double delay) { - //delay_val is a 5-bit value (0-31) for fine control - //the equations below determine delay for a given ramp current, # of caps and fine delay register - //delay range: - //range_ns = 200*((caps+3)/i_ramp_ua)*1.3286 - //offset (zero delay): - //offset_ns = 0.34 + (1600 - i_ramp_ua)*1e-4 + ((caps-1)/ramp)*6 - //delay_ns = offset_ns + range_ns * delay / 31 - - int delay_val = boost::math::iround(delay/9.744e-9*31); - - if(delay_val == 0) { - switch(clk_regs.exp) { - case 5: - _ad9510_regs.delay_control_out5 = 1; - break; - case 6: - _ad9510_regs.delay_control_out6 = 1; - break; - default: - break; //delay not supported on U2 rev 3 + + void set_mimo_clock_delay(double delay) + { + // delay_val is a 5-bit value (0-31) for fine control + // the equations below determine delay for a given ramp current, # of caps and + // fine delay register delay range: range_ns = 200*((caps+3)/i_ramp_ua)*1.3286 + // offset (zero delay): + // offset_ns = 0.34 + (1600 - i_ramp_ua)*1e-4 + ((caps-1)/ramp)*6 + // delay_ns = offset_ns + range_ns * delay / 31 + + int delay_val = boost::math::iround(delay / 9.744e-9 * 31); + + if (delay_val == 0) { + switch (clk_regs.exp) { + case 5: + _ad9510_regs.delay_control_out5 = 1; + break; + case 6: + _ad9510_regs.delay_control_out6 = 1; + break; + default: + break; // delay not supported on U2 rev 3 } } else { - switch(clk_regs.exp) { - case 5: - _ad9510_regs.delay_control_out5 = 0; - _ad9510_regs.ramp_current_out5 = ad9510_regs_t::RAMP_CURRENT_OUT5_200UA; - _ad9510_regs.ramp_capacitor_out5 = ad9510_regs_t::RAMP_CAPACITOR_OUT5_4CAPS; - _ad9510_regs.delay_fine_adjust_out5 = delay_val; - this->write_reg(0x34); - this->write_reg(0x35); - this->write_reg(0x36); - break; - case 6: - _ad9510_regs.delay_control_out6 = 0; - _ad9510_regs.ramp_current_out6 = ad9510_regs_t::RAMP_CURRENT_OUT6_200UA; - _ad9510_regs.ramp_capacitor_out6 = ad9510_regs_t::RAMP_CAPACITOR_OUT6_4CAPS; - _ad9510_regs.delay_fine_adjust_out6 = delay_val; - this->write_reg(0x38); - this->write_reg(0x39); - this->write_reg(0x3A); - break; - default: - break; + switch (clk_regs.exp) { + case 5: + _ad9510_regs.delay_control_out5 = 0; + _ad9510_regs.ramp_current_out5 = + ad9510_regs_t::RAMP_CURRENT_OUT5_200UA; + _ad9510_regs.ramp_capacitor_out5 = + ad9510_regs_t::RAMP_CAPACITOR_OUT5_4CAPS; + _ad9510_regs.delay_fine_adjust_out5 = delay_val; + this->write_reg(0x34); + this->write_reg(0x35); + this->write_reg(0x36); + break; + case 6: + _ad9510_regs.delay_control_out6 = 0; + _ad9510_regs.ramp_current_out6 = + ad9510_regs_t::RAMP_CURRENT_OUT6_200UA; + _ad9510_regs.ramp_capacitor_out6 = + ad9510_regs_t::RAMP_CAPACITOR_OUT6_4CAPS; + _ad9510_regs.delay_fine_adjust_out6 = delay_val; + this->write_reg(0x38); + this->write_reg(0x39); + this->write_reg(0x3A); + break; + default: + break; } } } @@ -325,7 +365,8 @@ private: * Write a single register to the spi regs. * \param addr the address to write */ - void write_reg(uint8_t addr){ + void write_reg(uint8_t addr) + { uint32_t data = _ad9510_regs.get_write_reg(addr); _spiface->write_spi(SPI_SS_AD9510, spi_config_t::EDGE_RISE, data, 24); } @@ -333,45 +374,54 @@ private: /*! * Tells the ad9510 to latch the settings into the operational registers. */ - void update_regs(void){ + void update_regs(void) + { _ad9510_regs.update_registers = 1; this->write_reg(clk_regs.update); } - //uses output clock 3 (pecl) - //this is the same between USRP2 and USRP2+ and doesn't get a switch statement - void enable_dac_clock(bool enb){ - _ad9510_regs.power_down_lvpecl_out3 = (enb)? - ad9510_regs_t::POWER_DOWN_LVPECL_OUT3_NORMAL : - ad9510_regs_t::POWER_DOWN_LVPECL_OUT3_SAFE_PD; - _ad9510_regs.output_level_lvpecl_out3 = ad9510_regs_t::OUTPUT_LEVEL_LVPECL_OUT3_810MV; + // uses output clock 3 (pecl) + // this is the same between USRP2 and USRP2+ and doesn't get a switch statement + void enable_dac_clock(bool enb) + { + _ad9510_regs.power_down_lvpecl_out3 = + (enb) ? ad9510_regs_t::POWER_DOWN_LVPECL_OUT3_NORMAL + : ad9510_regs_t::POWER_DOWN_LVPECL_OUT3_SAFE_PD; + _ad9510_regs.output_level_lvpecl_out3 = + ad9510_regs_t::OUTPUT_LEVEL_LVPECL_OUT3_810MV; _ad9510_regs.bypass_divider_out3 = 1; this->write_reg(clk_regs.output(clk_regs.dac)); this->write_reg(clk_regs.div_hi(clk_regs.dac)); this->update_regs(); } - //uses output clock 4 (lvds) on USRP2 and output clock 2 (lvpecl) on USRP2+ - void enable_adc_clock(bool enb){ - switch(clk_regs.adc) { - case 2: - _ad9510_regs.power_down_lvpecl_out2 = enb? ad9510_regs_t::POWER_DOWN_LVPECL_OUT2_NORMAL : ad9510_regs_t::POWER_DOWN_LVPECL_OUT2_SAFE_PD; - _ad9510_regs.output_level_lvpecl_out2 = ad9510_regs_t::OUTPUT_LEVEL_LVPECL_OUT2_500MV; - _ad9510_regs.bypass_divider_out2 = 1; - break; - case 4: - _ad9510_regs.power_down_lvds_cmos_out4 = enb? 0 : 1; - _ad9510_regs.lvds_cmos_select_out4 = ad9510_regs_t::LVDS_CMOS_SELECT_OUT4_LVDS; - _ad9510_regs.output_level_lvds_out4 = ad9510_regs_t::OUTPUT_LEVEL_LVDS_OUT4_1_75MA; - _ad9510_regs.bypass_divider_out4 = 1; - break; + // uses output clock 4 (lvds) on USRP2 and output clock 2 (lvpecl) on USRP2+ + void enable_adc_clock(bool enb) + { + switch (clk_regs.adc) { + case 2: + _ad9510_regs.power_down_lvpecl_out2 = + enb ? ad9510_regs_t::POWER_DOWN_LVPECL_OUT2_NORMAL + : ad9510_regs_t::POWER_DOWN_LVPECL_OUT2_SAFE_PD; + _ad9510_regs.output_level_lvpecl_out2 = + ad9510_regs_t::OUTPUT_LEVEL_LVPECL_OUT2_500MV; + _ad9510_regs.bypass_divider_out2 = 1; + break; + case 4: + _ad9510_regs.power_down_lvds_cmos_out4 = enb ? 0 : 1; + _ad9510_regs.lvds_cmos_select_out4 = + ad9510_regs_t::LVDS_CMOS_SELECT_OUT4_LVDS; + _ad9510_regs.output_level_lvds_out4 = + ad9510_regs_t::OUTPUT_LEVEL_LVDS_OUT4_1_75MA; + _ad9510_regs.bypass_divider_out4 = 1; + break; } this->write_reg(clk_regs.output(clk_regs.adc)); this->write_reg(clk_regs.div_hi(clk_regs.adc)); this->update_regs(); } - + usrp2_iface::sptr _iface; uhd::spi_iface::sptr _spiface; usrp2_clk_regs_t clk_regs; @@ -381,6 +431,8 @@ private: /*********************************************************************** * Public make function for the ad9510 clock control **********************************************************************/ -usrp2_clock_ctrl::sptr usrp2_clock_ctrl::make(usrp2_iface::sptr iface, uhd::spi_iface::sptr spiface){ +usrp2_clock_ctrl::sptr usrp2_clock_ctrl::make( + usrp2_iface::sptr iface, uhd::spi_iface::sptr spiface) +{ return sptr(new usrp2_clock_ctrl_impl(iface, spiface)); } diff --git a/host/lib/usrp/usrp2/clock_ctrl.hpp b/host/lib/usrp/usrp2/clock_ctrl.hpp index b82dd4723..d1e8ee551 100644 --- a/host/lib/usrp/usrp2/clock_ctrl.hpp +++ b/host/lib/usrp/usrp2/clock_ctrl.hpp @@ -13,7 +13,8 @@ #include <memory> #include <vector> -class usrp2_clock_ctrl : uhd::noncopyable{ +class usrp2_clock_ctrl : uhd::noncopyable +{ public: typedef std::shared_ptr<usrp2_clock_ctrl> sptr; @@ -76,7 +77,7 @@ public: * \param enb true to enable */ virtual void enable_external_ref(bool enb) = 0; - + /*! * Enable/disable test clock output. * \param enb true to enable @@ -88,7 +89,7 @@ public: * \param enb true to enable */ virtual void enable_mimo_clock_out(bool enb) = 0; - + /*! * Set the output delay of the mimo clock * Used to synchronise daisy-chained USRPs over the MIMO cable @@ -96,7 +97,6 @@ public: * \param delay the clock delay in seconds */ virtual void set_mimo_clock_delay(double delay) = 0; - }; #endif /* INCLUDED_CLOCK_CTRL_HPP */ diff --git a/host/lib/usrp/usrp2/codec_ctrl.cpp b/host/lib/usrp/usrp2/codec_ctrl.cpp index 88f6007e8..6fe91da9e 100644 --- a/host/lib/usrp/usrp2/codec_ctrl.cpp +++ b/host/lib/usrp/usrp2/codec_ctrl.cpp @@ -9,173 +9,197 @@ #include "ad9777_regs.hpp" #include "ads62p44_regs.hpp" #include "usrp2_regs.hpp" +#include <uhd/exception.hpp> #include <uhd/utils/log.hpp> #include <uhd/utils/safe_call.hpp> -#include <uhd/exception.hpp> #include <stdint.h> using namespace uhd; -usrp2_codec_ctrl::~usrp2_codec_ctrl(void){ +usrp2_codec_ctrl::~usrp2_codec_ctrl(void) +{ /* NOP */ } /*! * A usrp2 codec control specific to the ad9777 ic. */ -class usrp2_codec_ctrl_impl : public usrp2_codec_ctrl{ +class usrp2_codec_ctrl_impl : public usrp2_codec_ctrl +{ public: - usrp2_codec_ctrl_impl(usrp2_iface::sptr iface, uhd::spi_iface::sptr spiface){ - _iface = iface; + usrp2_codec_ctrl_impl(usrp2_iface::sptr iface, uhd::spi_iface::sptr spiface) + { + _iface = iface; _spiface = spiface; - //setup the ad9777 dac - _ad9777_regs.x_1r_2r_mode = ad9777_regs_t::X_1R_2R_MODE_1R; + // setup the ad9777 dac + _ad9777_regs.x_1r_2r_mode = ad9777_regs_t::X_1R_2R_MODE_1R; _ad9777_regs.filter_interp_rate = ad9777_regs_t::FILTER_INTERP_RATE_4X; - _ad9777_regs.mix_mode = ad9777_regs_t::MIX_MODE_COMPLEX; - _ad9777_regs.pll_divide_ratio = ad9777_regs_t::PLL_DIVIDE_RATIO_DIV1; - _ad9777_regs.pll_state = ad9777_regs_t::PLL_STATE_ON; - _ad9777_regs.auto_cp_control = ad9777_regs_t::AUTO_CP_CONTROL_AUTO; - //I dac values - _ad9777_regs.idac_fine_gain_adjust = 0; + _ad9777_regs.mix_mode = ad9777_regs_t::MIX_MODE_COMPLEX; + _ad9777_regs.pll_divide_ratio = ad9777_regs_t::PLL_DIVIDE_RATIO_DIV1; + _ad9777_regs.pll_state = ad9777_regs_t::PLL_STATE_ON; + _ad9777_regs.auto_cp_control = ad9777_regs_t::AUTO_CP_CONTROL_AUTO; + // I dac values + _ad9777_regs.idac_fine_gain_adjust = 0; _ad9777_regs.idac_coarse_gain_adjust = 0xf; - _ad9777_regs.idac_offset_adjust_lsb = 0; - _ad9777_regs.idac_offset_adjust_msb = 0; - //Q dac values - _ad9777_regs.qdac_fine_gain_adjust = 0; + _ad9777_regs.idac_offset_adjust_lsb = 0; + _ad9777_regs.idac_offset_adjust_msb = 0; + // Q dac values + _ad9777_regs.qdac_fine_gain_adjust = 0; _ad9777_regs.qdac_coarse_gain_adjust = 0xf; - _ad9777_regs.qdac_offset_adjust_lsb = 0; - _ad9777_regs.qdac_offset_adjust_msb = 0; - //write all regs - for(uint8_t addr = 0; addr <= 0xC; addr++){ + _ad9777_regs.qdac_offset_adjust_lsb = 0; + _ad9777_regs.qdac_offset_adjust_msb = 0; + // write all regs + for (uint8_t addr = 0; addr <= 0xC; addr++) { this->send_ad9777_reg(addr); } set_tx_mod_mode(0); - //power-up adc - switch(_iface->get_rev()){ - case usrp2_iface::USRP2_REV3: - case usrp2_iface::USRP2_REV4: - _iface->poke32(U2_REG_MISC_CTRL_ADC, U2_FLAG_MISC_CTRL_ADC_ON); - break; - - case usrp2_iface::USRP_N200: - case usrp2_iface::USRP_N210: - _ads62p44_regs.reset = 1; - this->send_ads62p44_reg(0x00); //issue a reset to the ADC - //everything else should be pretty much default, i think - //_ads62p44_regs.decimation = DECIMATION_DECIMATE_1; - _ads62p44_regs.power_down = ads62p44_regs_t::POWER_DOWN_NORMAL; - this->send_ads62p44_reg(0x14); - this->set_rx_analog_gain(1); - break; - - case usrp2_iface::USRP_N200_R4: - case usrp2_iface::USRP_N210_R4: - _ads62p44_regs.reset = 1; - this->send_ads62p44_reg(0x00); //issue a reset to the ADC - //everything else should be pretty much default, i think - //_ads62p44_regs.decimation = DECIMATION_DECIMATE_1; - _ads62p44_regs.override = 1; - this->send_ads62p44_reg(0x14); - _ads62p44_regs.power_down = ads62p44_regs_t::POWER_DOWN_NORMAL; - _ads62p44_regs.output_interface = ads62p44_regs_t::OUTPUT_INTERFACE_LVDS; - _ads62p44_regs.lvds_current = ads62p44_regs_t::LVDS_CURRENT_2_5MA; - _ads62p44_regs.lvds_data_term = ads62p44_regs_t::LVDS_DATA_TERM_100; - this->send_ads62p44_reg(0x11); - this->send_ads62p44_reg(0x12); - this->send_ads62p44_reg(0x14); - this->set_rx_analog_gain(1); - break; - - case usrp2_iface::USRP_NXXX: break; + // power-up adc + switch (_iface->get_rev()) { + case usrp2_iface::USRP2_REV3: + case usrp2_iface::USRP2_REV4: + _iface->poke32(U2_REG_MISC_CTRL_ADC, U2_FLAG_MISC_CTRL_ADC_ON); + break; + + case usrp2_iface::USRP_N200: + case usrp2_iface::USRP_N210: + _ads62p44_regs.reset = 1; + this->send_ads62p44_reg(0x00); // issue a reset to the ADC + // everything else should be pretty much default, i think + //_ads62p44_regs.decimation = DECIMATION_DECIMATE_1; + _ads62p44_regs.power_down = ads62p44_regs_t::POWER_DOWN_NORMAL; + this->send_ads62p44_reg(0x14); + this->set_rx_analog_gain(1); + break; + + case usrp2_iface::USRP_N200_R4: + case usrp2_iface::USRP_N210_R4: + _ads62p44_regs.reset = 1; + this->send_ads62p44_reg(0x00); // issue a reset to the ADC + // everything else should be pretty much default, i think + //_ads62p44_regs.decimation = DECIMATION_DECIMATE_1; + _ads62p44_regs.override = 1; + this->send_ads62p44_reg(0x14); + _ads62p44_regs.power_down = ads62p44_regs_t::POWER_DOWN_NORMAL; + _ads62p44_regs.output_interface = ads62p44_regs_t::OUTPUT_INTERFACE_LVDS; + _ads62p44_regs.lvds_current = ads62p44_regs_t::LVDS_CURRENT_2_5MA; + _ads62p44_regs.lvds_data_term = ads62p44_regs_t::LVDS_DATA_TERM_100; + this->send_ads62p44_reg(0x11); + this->send_ads62p44_reg(0x12); + this->send_ads62p44_reg(0x14); + this->set_rx_analog_gain(1); + break; + + case usrp2_iface::USRP_NXXX: + break; } } - ~usrp2_codec_ctrl_impl(void){UHD_SAFE_CALL( - //power-down dac - _ad9777_regs.power_down_mode = 1; - this->send_ad9777_reg(0); - - //power-down adc - switch(_iface->get_rev()){ - case usrp2_iface::USRP2_REV3: - case usrp2_iface::USRP2_REV4: - _iface->poke32(U2_REG_MISC_CTRL_ADC, U2_FLAG_MISC_CTRL_ADC_OFF); - break; - - case usrp2_iface::USRP_N200: - case usrp2_iface::USRP_N210: - case usrp2_iface::USRP_N200_R4: - case usrp2_iface::USRP_N210_R4: - //send a global power-down to the ADC here... it will get lifted on reset - _ads62p44_regs.power_down = ads62p44_regs_t::POWER_DOWN_GLOBAL_PD; - this->send_ads62p44_reg(0x14); - break; - - case usrp2_iface::USRP_NXXX: break; - } - )} - - void set_tx_mod_mode(int mod_mode){ - //set the sign of the frequency shift - _ad9777_regs.modulation_form = (mod_mode > 0)? - ad9777_regs_t::MODULATION_FORM_E_PLUS_JWT: - ad9777_regs_t::MODULATION_FORM_E_MINUS_JWT - ; - - //set the frequency shift - switch(std::abs(mod_mode)){ - case 0: - case 1: _ad9777_regs.modulation_mode = ad9777_regs_t::MODULATION_MODE_NONE; break; - case 2: _ad9777_regs.modulation_mode = ad9777_regs_t::MODULATION_MODE_FS_2; break; - case 4: _ad9777_regs.modulation_mode = ad9777_regs_t::MODULATION_MODE_FS_4; break; - case 8: _ad9777_regs.modulation_mode = ad9777_regs_t::MODULATION_MODE_FS_8; break; - default: throw uhd::value_error("unknown modulation mode for ad9777"); + ~usrp2_codec_ctrl_impl(void) + { + UHD_SAFE_CALL( + // power-down dac + _ad9777_regs.power_down_mode = 1; this->send_ad9777_reg(0); + + // power-down adc + switch (_iface->get_rev()) { + case usrp2_iface::USRP2_REV3: + case usrp2_iface::USRP2_REV4: + _iface->poke32(U2_REG_MISC_CTRL_ADC, U2_FLAG_MISC_CTRL_ADC_OFF); + break; + + case usrp2_iface::USRP_N200: + case usrp2_iface::USRP_N210: + case usrp2_iface::USRP_N200_R4: + case usrp2_iface::USRP_N210_R4: + // send a global power-down to the ADC here... it will get lifted on + // reset + _ads62p44_regs.power_down = ads62p44_regs_t::POWER_DOWN_GLOBAL_PD; + this->send_ads62p44_reg(0x14); + break; + + case usrp2_iface::USRP_NXXX: + break; + }) + } + + void set_tx_mod_mode(int mod_mode) + { + // set the sign of the frequency shift + _ad9777_regs.modulation_form = (mod_mode > 0) + ? ad9777_regs_t::MODULATION_FORM_E_PLUS_JWT + : ad9777_regs_t::MODULATION_FORM_E_MINUS_JWT; + + // set the frequency shift + switch (std::abs(mod_mode)) { + case 0: + case 1: + _ad9777_regs.modulation_mode = ad9777_regs_t::MODULATION_MODE_NONE; + break; + case 2: + _ad9777_regs.modulation_mode = ad9777_regs_t::MODULATION_MODE_FS_2; + break; + case 4: + _ad9777_regs.modulation_mode = ad9777_regs_t::MODULATION_MODE_FS_4; + break; + case 8: + _ad9777_regs.modulation_mode = ad9777_regs_t::MODULATION_MODE_FS_8; + break; + default: + throw uhd::value_error("unknown modulation mode for ad9777"); } - this->send_ad9777_reg(0x01); //set the register + this->send_ad9777_reg(0x01); // set the register } - void set_rx_digital_gain(double gain) { //fine digital gain - switch(_iface->get_rev()){ - case usrp2_iface::USRP_N200: - case usrp2_iface::USRP_N210: - case usrp2_iface::USRP_N200_R4: - case usrp2_iface::USRP_N210_R4: - _ads62p44_regs.fine_gain = int(gain/0.5); - this->send_ads62p44_reg(0x17); - break; - - default: UHD_THROW_INVALID_CODE_PATH(); + void set_rx_digital_gain(double gain) + { // fine digital gain + switch (_iface->get_rev()) { + case usrp2_iface::USRP_N200: + case usrp2_iface::USRP_N210: + case usrp2_iface::USRP_N200_R4: + case usrp2_iface::USRP_N210_R4: + _ads62p44_regs.fine_gain = int(gain / 0.5); + this->send_ads62p44_reg(0x17); + break; + + default: + UHD_THROW_INVALID_CODE_PATH(); } } - void set_rx_digital_fine_gain(double gain) { //gain correction - switch(_iface->get_rev()){ - case usrp2_iface::USRP_N200: - case usrp2_iface::USRP_N210: - case usrp2_iface::USRP_N200_R4: - case usrp2_iface::USRP_N210_R4: - _ads62p44_regs.gain_correction = int(gain / 0.05); - this->send_ads62p44_reg(0x1A); - break; - - default: UHD_THROW_INVALID_CODE_PATH(); + void set_rx_digital_fine_gain(double gain) + { // gain correction + switch (_iface->get_rev()) { + case usrp2_iface::USRP_N200: + case usrp2_iface::USRP_N210: + case usrp2_iface::USRP_N200_R4: + case usrp2_iface::USRP_N210_R4: + _ads62p44_regs.gain_correction = int(gain / 0.05); + this->send_ads62p44_reg(0x1A); + break; + + default: + UHD_THROW_INVALID_CODE_PATH(); } } - void set_rx_analog_gain(bool /*gain*/) { //turns on/off analog 3.5dB preamp - switch(_iface->get_rev()){ - case usrp2_iface::USRP_N200: - case usrp2_iface::USRP_N210: - case usrp2_iface::USRP_N200_R4: - case usrp2_iface::USRP_N210_R4: - _ads62p44_regs.coarse_gain = ads62p44_regs_t::COARSE_GAIN_3_5DB;//gain ? ads62p44_regs_t::COARSE_GAIN_3_5DB : ads62p44_regs_t::COARSE_GAIN_0DB; - this->send_ads62p44_reg(0x14); - break; - - default: UHD_THROW_INVALID_CODE_PATH(); + void set_rx_analog_gain(bool /*gain*/) + { // turns on/off analog 3.5dB preamp + switch (_iface->get_rev()) { + case usrp2_iface::USRP_N200: + case usrp2_iface::USRP_N210: + case usrp2_iface::USRP_N200_R4: + case usrp2_iface::USRP_N210_R4: + _ads62p44_regs.coarse_gain = ads62p44_regs_t:: + COARSE_GAIN_3_5DB; // gain ? ads62p44_regs_t::COARSE_GAIN_3_5DB : + // ads62p44_regs_t::COARSE_GAIN_0DB; + this->send_ads62p44_reg(0x14); + break; + + default: + UHD_THROW_INVALID_CODE_PATH(); } } @@ -190,27 +214,25 @@ private: usrp2_iface::sptr _iface; uhd::spi_iface::sptr _spiface; - void send_ad9777_reg(uint8_t addr){ + void send_ad9777_reg(uint8_t addr) + { uint16_t reg = _ad9777_regs.get_write_reg(addr); UHD_LOG_TRACE("USRP2", "send_ad9777_reg: 0x" << std::hex << reg); - _spiface->write_spi( - SPI_SS_AD9777, spi_config_t::EDGE_RISE, - reg, 16 - ); + _spiface->write_spi(SPI_SS_AD9777, spi_config_t::EDGE_RISE, reg, 16); } - void send_ads62p44_reg(uint8_t addr) { + void send_ads62p44_reg(uint8_t addr) + { uint16_t reg = _ads62p44_regs.get_write_reg(addr); - _spiface->write_spi( - SPI_SS_ADS62P44, spi_config_t::EDGE_FALL, - reg, 16 - ); + _spiface->write_spi(SPI_SS_ADS62P44, spi_config_t::EDGE_FALL, reg, 16); } }; /*********************************************************************** * Public make function for the usrp2 codec control **********************************************************************/ -usrp2_codec_ctrl::sptr usrp2_codec_ctrl::make(usrp2_iface::sptr iface, uhd::spi_iface::sptr spiface){ +usrp2_codec_ctrl::sptr usrp2_codec_ctrl::make( + usrp2_iface::sptr iface, uhd::spi_iface::sptr spiface) +{ return sptr(new usrp2_codec_ctrl_impl(iface, spiface)); } diff --git a/host/lib/usrp/usrp2/codec_ctrl.hpp b/host/lib/usrp/usrp2/codec_ctrl.hpp index c769d102a..550e7208a 100644 --- a/host/lib/usrp/usrp2/codec_ctrl.hpp +++ b/host/lib/usrp/usrp2/codec_ctrl.hpp @@ -9,10 +9,11 @@ #define INCLUDED_CODEC_CTRL_HPP #include "usrp2_iface.hpp" -#include <memory> #include <uhd/utils/noncopyable.hpp> +#include <memory> -class usrp2_codec_ctrl : uhd::noncopyable{ +class usrp2_codec_ctrl : uhd::noncopyable +{ public: typedef std::shared_ptr<usrp2_codec_ctrl> sptr; @@ -62,7 +63,6 @@ public: * modulation. */ virtual size_t get_tx_interpolation() const = 0; - }; #endif /* INCLUDED_CODEC_CTRL_HPP */ diff --git a/host/lib/usrp/usrp2/dboard_iface.cpp b/host/lib/usrp/usrp2/dboard_iface.cpp index a245705df..55325dafc 100644 --- a/host/lib/usrp/usrp2/dboard_iface.cpp +++ b/host/lib/usrp/usrp2/dboard_iface.cpp @@ -5,39 +5,39 @@ // SPDX-License-Identifier: GPL-3.0-or-later // +#include "ad5623_regs.hpp" //aux dac +#include "ad7922_regs.hpp" //aux adc #include "clock_ctrl.hpp" -#include "usrp2_regs.hpp" //wishbone address constants #include "usrp2_fifo_ctrl.hpp" -#include "ad7922_regs.hpp" //aux adc -#include "ad5623_regs.hpp" //aux dac -#include <uhdlib/usrp/cores/gpio_core_200.hpp> +#include "usrp2_regs.hpp" //wishbone address constants +#include <uhd/exception.hpp> +#include <uhd/types/dict.hpp> #include <uhd/types/serial.hpp> #include <uhd/usrp/dboard_iface.hpp> -#include <uhd/types/dict.hpp> -#include <uhd/exception.hpp> #include <uhd/utils/algorithm.hpp> -#include <boost/assign/list_of.hpp> +#include <uhdlib/usrp/cores/gpio_core_200.hpp> #include <boost/asio.hpp> //htonl and ntohl +#include <boost/assign/list_of.hpp> #include <boost/math/special_functions/round.hpp> using namespace uhd; using namespace uhd::usrp; using namespace boost::assign; -class usrp2_dboard_iface : public dboard_iface{ +class usrp2_dboard_iface : public dboard_iface +{ public: - usrp2_dboard_iface( - timed_wb_iface::sptr wb_iface, + usrp2_dboard_iface(timed_wb_iface::sptr wb_iface, uhd::i2c_iface::sptr i2c_iface, uhd::spi_iface::sptr spi_iface, - usrp2_clock_ctrl::sptr clock_ctrl - ); + usrp2_clock_ctrl::sptr clock_ctrl); ~usrp2_dboard_iface(void); - special_props_t get_special_props(void){ + special_props_t get_special_props(void) + { special_props_t props; props.soft_clock_divider = false; - props.mangle_i2c_addrs = false; + props.mangle_i2c_addrs = false; return props; } @@ -46,7 +46,8 @@ public: void set_pin_ctrl(unit_t unit, uint32_t value, uint32_t mask = 0xffffffff); uint32_t get_pin_ctrl(unit_t unit); - void set_atr_reg(unit_t unit, atr_reg_t reg, uint32_t value, uint32_t mask = 0xffffffff); + void set_atr_reg( + unit_t unit, atr_reg_t reg, uint32_t value, uint32_t mask = 0xffffffff); uint32_t get_atr_reg(unit_t unit, atr_reg_t reg); void set_gpio_ddr(unit_t unit, uint32_t value, uint32_t mask = 0xffffffff); uint32_t get_gpio_ddr(unit_t unit); @@ -57,7 +58,7 @@ public: void set_command_time(const uhd::time_spec_t& t); uhd::time_spec_t get_command_time(void); - void write_i2c(uint16_t, const byte_vector_t &); + void write_i2c(uint16_t, const byte_vector_t&); byte_vector_t read_i2c(uint16_t, size_t); void set_clock_rate(unit_t, double); @@ -65,21 +66,14 @@ public: std::vector<double> get_clock_rates(unit_t); void set_clock_enabled(unit_t, bool); double get_codec_rate(unit_t); - void set_fe_connection(unit_t unit, const std::string&, const fe_connection_t& fe_conn); + void set_fe_connection( + unit_t unit, const std::string&, const fe_connection_t& fe_conn); void write_spi( - unit_t unit, - const spi_config_t &config, - uint32_t data, - size_t num_bits - ); + unit_t unit, const spi_config_t& config, uint32_t data, size_t num_bits); uint32_t read_write_spi( - unit_t unit, - const spi_config_t &config, - uint32_t data, - size_t num_bits - ); + unit_t unit, const spi_config_t& config, uint32_t data, size_t num_bits); private: timed_wb_iface::sptr _wb_iface; @@ -96,241 +90,264 @@ private: /*********************************************************************** * Make Function **********************************************************************/ -dboard_iface::sptr make_usrp2_dboard_iface( - timed_wb_iface::sptr wb_iface, +dboard_iface::sptr make_usrp2_dboard_iface(timed_wb_iface::sptr wb_iface, uhd::i2c_iface::sptr i2c_iface, uhd::spi_iface::sptr spi_iface, - usrp2_clock_ctrl::sptr clock_ctrl -){ - return dboard_iface::sptr(new usrp2_dboard_iface(wb_iface, i2c_iface, spi_iface, clock_ctrl)); + usrp2_clock_ctrl::sptr clock_ctrl) +{ + return dboard_iface::sptr( + new usrp2_dboard_iface(wb_iface, i2c_iface, spi_iface, clock_ctrl)); } /*********************************************************************** * Structors **********************************************************************/ -usrp2_dboard_iface::usrp2_dboard_iface( - timed_wb_iface::sptr wb_iface, +usrp2_dboard_iface::usrp2_dboard_iface(timed_wb_iface::sptr wb_iface, uhd::i2c_iface::sptr i2c_iface, uhd::spi_iface::sptr spi_iface, - usrp2_clock_ctrl::sptr clock_ctrl -): - _wb_iface(wb_iface), - _i2c_iface(i2c_iface), - _spi_iface(spi_iface), - _clock_ctrl(clock_ctrl) + usrp2_clock_ctrl::sptr clock_ctrl) + : _wb_iface(wb_iface) + , _i2c_iface(i2c_iface) + , _spi_iface(spi_iface) + , _clock_ctrl(clock_ctrl) { _gpio = gpio_core_200::make(wb_iface, U2_REG_SR_ADDR(SR_GPIO), U2_REG_GPIO_RB); - //reset the aux dacs + // reset the aux dacs _dac_regs[UNIT_RX] = ad5623_regs_t(); _dac_regs[UNIT_TX] = ad5623_regs_t(); - for(unit_t unit: _dac_regs.keys()){ + for (unit_t unit : _dac_regs.keys()) { _dac_regs[unit].data = 1; _dac_regs[unit].addr = ad5623_regs_t::ADDR_ALL; _dac_regs[unit].cmd = ad5623_regs_t::CMD_RESET; this->_write_aux_dac(unit); } - //init the clock rate shadows with max rate clock + // init the clock rate shadows with max rate clock this->set_clock_rate(UNIT_RX, sorted(this->get_clock_rates(UNIT_RX)).back()); this->set_clock_rate(UNIT_TX, sorted(this->get_clock_rates(UNIT_TX)).back()); } -usrp2_dboard_iface::~usrp2_dboard_iface(void){ +usrp2_dboard_iface::~usrp2_dboard_iface(void) +{ /* NOP */ } /*********************************************************************** * Clocks **********************************************************************/ -void usrp2_dboard_iface::set_clock_rate(unit_t unit, double rate){ - if (unit == UNIT_BOTH) throw uhd::runtime_error("UNIT_BOTH not supported."); - _clock_rates[unit] = rate; //set to shadow - switch(unit){ - case UNIT_RX: _clock_ctrl->set_rate_rx_dboard_clock(rate); return; - case UNIT_TX: _clock_ctrl->set_rate_tx_dboard_clock(rate); return; - default: UHD_THROW_INVALID_CODE_PATH(); +void usrp2_dboard_iface::set_clock_rate(unit_t unit, double rate) +{ + if (unit == UNIT_BOTH) + throw uhd::runtime_error("UNIT_BOTH not supported."); + _clock_rates[unit] = rate; // set to shadow + switch (unit) { + case UNIT_RX: + _clock_ctrl->set_rate_rx_dboard_clock(rate); + return; + case UNIT_TX: + _clock_ctrl->set_rate_tx_dboard_clock(rate); + return; + default: + UHD_THROW_INVALID_CODE_PATH(); } } -double usrp2_dboard_iface::get_clock_rate(unit_t unit){ - if (unit == UNIT_BOTH) throw uhd::runtime_error("UNIT_BOTH not supported."); - return _clock_rates[unit]; //get from shadow +double usrp2_dboard_iface::get_clock_rate(unit_t unit) +{ + if (unit == UNIT_BOTH) + throw uhd::runtime_error("UNIT_BOTH not supported."); + return _clock_rates[unit]; // get from shadow } -std::vector<double> usrp2_dboard_iface::get_clock_rates(unit_t unit){ - if (unit == UNIT_BOTH) throw uhd::runtime_error("UNIT_BOTH not supported."); - switch(unit){ - case UNIT_RX: return _clock_ctrl->get_rates_rx_dboard_clock(); - case UNIT_TX: return _clock_ctrl->get_rates_tx_dboard_clock(); - default: UHD_THROW_INVALID_CODE_PATH(); +std::vector<double> usrp2_dboard_iface::get_clock_rates(unit_t unit) +{ + if (unit == UNIT_BOTH) + throw uhd::runtime_error("UNIT_BOTH not supported."); + switch (unit) { + case UNIT_RX: + return _clock_ctrl->get_rates_rx_dboard_clock(); + case UNIT_TX: + return _clock_ctrl->get_rates_tx_dboard_clock(); + default: + UHD_THROW_INVALID_CODE_PATH(); } } -void usrp2_dboard_iface::set_clock_enabled(unit_t unit, bool enb){ - if (unit == UNIT_BOTH) throw uhd::runtime_error("UNIT_BOTH not supported."); - switch(unit){ - case UNIT_RX: _clock_ctrl->enable_rx_dboard_clock(enb); return; - case UNIT_TX: _clock_ctrl->enable_tx_dboard_clock(enb); return; - default: UHD_THROW_INVALID_CODE_PATH(); +void usrp2_dboard_iface::set_clock_enabled(unit_t unit, bool enb) +{ + if (unit == UNIT_BOTH) + throw uhd::runtime_error("UNIT_BOTH not supported."); + switch (unit) { + case UNIT_RX: + _clock_ctrl->enable_rx_dboard_clock(enb); + return; + case UNIT_TX: + _clock_ctrl->enable_tx_dboard_clock(enb); + return; + default: + UHD_THROW_INVALID_CODE_PATH(); } } -double usrp2_dboard_iface::get_codec_rate(unit_t unit){ - if (unit == UNIT_BOTH) throw uhd::runtime_error("UNIT_BOTH not supported."); +double usrp2_dboard_iface::get_codec_rate(unit_t unit) +{ + if (unit == UNIT_BOTH) + throw uhd::runtime_error("UNIT_BOTH not supported."); return _clock_ctrl->get_master_clock_rate(); } /*********************************************************************** * GPIO **********************************************************************/ -void usrp2_dboard_iface::set_pin_ctrl(unit_t unit, uint32_t value, uint32_t mask){ +void usrp2_dboard_iface::set_pin_ctrl(unit_t unit, uint32_t value, uint32_t mask) +{ _gpio->set_pin_ctrl(unit, static_cast<uint16_t>(value), static_cast<uint16_t>(mask)); } -uint32_t usrp2_dboard_iface::get_pin_ctrl(unit_t unit){ +uint32_t usrp2_dboard_iface::get_pin_ctrl(unit_t unit) +{ return static_cast<uint32_t>(_gpio->get_pin_ctrl(unit)); } -void usrp2_dboard_iface::set_atr_reg(unit_t unit, atr_reg_t reg, uint32_t value, uint32_t mask){ - _gpio->set_atr_reg(unit, reg, static_cast<uint16_t>(value), static_cast<uint16_t>(mask)); +void usrp2_dboard_iface::set_atr_reg( + unit_t unit, atr_reg_t reg, uint32_t value, uint32_t mask) +{ + _gpio->set_atr_reg( + unit, reg, static_cast<uint16_t>(value), static_cast<uint16_t>(mask)); } -uint32_t usrp2_dboard_iface::get_atr_reg(unit_t unit, atr_reg_t reg){ +uint32_t usrp2_dboard_iface::get_atr_reg(unit_t unit, atr_reg_t reg) +{ return static_cast<uint32_t>(_gpio->get_atr_reg(unit, reg)); } -void usrp2_dboard_iface::set_gpio_ddr(unit_t unit, uint32_t value, uint32_t mask){ +void usrp2_dboard_iface::set_gpio_ddr(unit_t unit, uint32_t value, uint32_t mask) +{ _gpio->set_gpio_ddr(unit, static_cast<uint16_t>(value), static_cast<uint16_t>(mask)); } -uint32_t usrp2_dboard_iface::get_gpio_ddr(unit_t unit){ +uint32_t usrp2_dboard_iface::get_gpio_ddr(unit_t unit) +{ return static_cast<uint32_t>(_gpio->get_gpio_ddr(unit)); } -void usrp2_dboard_iface::set_gpio_out(unit_t unit, uint32_t value, uint32_t mask){ +void usrp2_dboard_iface::set_gpio_out(unit_t unit, uint32_t value, uint32_t mask) +{ _gpio->set_gpio_out(unit, static_cast<uint16_t>(value), static_cast<uint16_t>(mask)); } -uint32_t usrp2_dboard_iface::get_gpio_out(unit_t unit){ +uint32_t usrp2_dboard_iface::get_gpio_out(unit_t unit) +{ return static_cast<uint32_t>(_gpio->get_gpio_out(unit)); } -uint32_t usrp2_dboard_iface::read_gpio(unit_t unit){ +uint32_t usrp2_dboard_iface::read_gpio(unit_t unit) +{ return _gpio->read_gpio(unit); } /*********************************************************************** * SPI **********************************************************************/ -static const uhd::dict<dboard_iface::unit_t, int> unit_to_spi_dev = map_list_of - (dboard_iface::UNIT_TX, SPI_SS_TX_DB) - (dboard_iface::UNIT_RX, SPI_SS_RX_DB) -; +static const uhd::dict<dboard_iface::unit_t, int> unit_to_spi_dev = + map_list_of(dboard_iface::UNIT_TX, SPI_SS_TX_DB)(dboard_iface::UNIT_RX, SPI_SS_RX_DB); void usrp2_dboard_iface::write_spi( - unit_t unit, - const spi_config_t &config, - uint32_t data, - size_t num_bits -){ - if (unit == UNIT_BOTH) throw uhd::runtime_error("UNIT_BOTH not supported."); + unit_t unit, const spi_config_t& config, uint32_t data, size_t num_bits) +{ + if (unit == UNIT_BOTH) + throw uhd::runtime_error("UNIT_BOTH not supported."); _spi_iface->write_spi(unit_to_spi_dev[unit], config, data, num_bits); } uint32_t usrp2_dboard_iface::read_write_spi( - unit_t unit, - const spi_config_t &config, - uint32_t data, - size_t num_bits -){ - if (unit == UNIT_BOTH) throw uhd::runtime_error("UNIT_BOTH not supported."); + unit_t unit, const spi_config_t& config, uint32_t data, size_t num_bits) +{ + if (unit == UNIT_BOTH) + throw uhd::runtime_error("UNIT_BOTH not supported."); return _spi_iface->read_spi(unit_to_spi_dev[unit], config, data, num_bits); } /*********************************************************************** * I2C **********************************************************************/ -void usrp2_dboard_iface::write_i2c(uint16_t addr, const byte_vector_t &bytes){ +void usrp2_dboard_iface::write_i2c(uint16_t addr, const byte_vector_t& bytes) +{ return _i2c_iface->write_i2c(addr, bytes); } -byte_vector_t usrp2_dboard_iface::read_i2c(uint16_t addr, size_t num_bytes){ +byte_vector_t usrp2_dboard_iface::read_i2c(uint16_t addr, size_t num_bytes) +{ return _i2c_iface->read_i2c(addr, num_bytes); } /*********************************************************************** * Aux DAX/ADC **********************************************************************/ -void usrp2_dboard_iface::_write_aux_dac(unit_t unit){ - static const uhd::dict<unit_t, int> unit_to_spi_dac = map_list_of - (UNIT_RX, SPI_SS_RX_DAC) - (UNIT_TX, SPI_SS_TX_DAC) - ; - if (unit == UNIT_BOTH) throw uhd::runtime_error("UNIT_BOTH not supported."); +void usrp2_dboard_iface::_write_aux_dac(unit_t unit) +{ + static const uhd::dict<unit_t, int> unit_to_spi_dac = + map_list_of(UNIT_RX, SPI_SS_RX_DAC)(UNIT_TX, SPI_SS_TX_DAC); + if (unit == UNIT_BOTH) + throw uhd::runtime_error("UNIT_BOTH not supported."); _spi_iface->write_spi( - unit_to_spi_dac[unit], spi_config_t::EDGE_FALL, - _dac_regs[unit].get_reg(), 24 - ); + unit_to_spi_dac[unit], spi_config_t::EDGE_FALL, _dac_regs[unit].get_reg(), 24); } -void usrp2_dboard_iface::write_aux_dac(unit_t unit, aux_dac_t which, double value){ - if (unit == UNIT_BOTH) throw uhd::runtime_error("UNIT_BOTH not supported."); +void usrp2_dboard_iface::write_aux_dac(unit_t unit, aux_dac_t which, double value) +{ + if (unit == UNIT_BOTH) + throw uhd::runtime_error("UNIT_BOTH not supported."); - _dac_regs[unit].data = boost::math::iround(4095*value/3.3); - _dac_regs[unit].cmd = ad5623_regs_t::CMD_WR_UP_DAC_CHAN_N; + _dac_regs[unit].data = boost::math::iround(4095 * value / 3.3); + _dac_regs[unit].cmd = ad5623_regs_t::CMD_WR_UP_DAC_CHAN_N; typedef uhd::dict<aux_dac_t, ad5623_regs_t::addr_t> aux_dac_to_addr; - static const uhd::dict<unit_t, aux_dac_to_addr> unit_to_which_to_addr = map_list_of - (UNIT_RX, map_list_of - (AUX_DAC_A, ad5623_regs_t::ADDR_DAC_B) - (AUX_DAC_B, ad5623_regs_t::ADDR_DAC_A) - (AUX_DAC_C, ad5623_regs_t::ADDR_DAC_A) - (AUX_DAC_D, ad5623_regs_t::ADDR_DAC_B) - ) - (UNIT_TX, map_list_of - (AUX_DAC_A, ad5623_regs_t::ADDR_DAC_A) - (AUX_DAC_B, ad5623_regs_t::ADDR_DAC_B) - (AUX_DAC_C, ad5623_regs_t::ADDR_DAC_B) - (AUX_DAC_D, ad5623_regs_t::ADDR_DAC_A) - ) - ; + static const uhd::dict<unit_t, aux_dac_to_addr> unit_to_which_to_addr = + map_list_of(UNIT_RX, + map_list_of(AUX_DAC_A, ad5623_regs_t::ADDR_DAC_B)(AUX_DAC_B, + ad5623_regs_t::ADDR_DAC_A)(AUX_DAC_C, ad5623_regs_t::ADDR_DAC_A)( + AUX_DAC_D, ad5623_regs_t::ADDR_DAC_B))(UNIT_TX, + map_list_of(AUX_DAC_A, ad5623_regs_t::ADDR_DAC_A)(AUX_DAC_B, + ad5623_regs_t::ADDR_DAC_B)(AUX_DAC_C, ad5623_regs_t::ADDR_DAC_B)( + AUX_DAC_D, ad5623_regs_t::ADDR_DAC_A)); _dac_regs[unit].addr = unit_to_which_to_addr[unit][which]; this->_write_aux_dac(unit); } -double usrp2_dboard_iface::read_aux_adc(unit_t unit, aux_adc_t which){ - static const uhd::dict<unit_t, int> unit_to_spi_adc = map_list_of - (UNIT_RX, SPI_SS_RX_ADC) - (UNIT_TX, SPI_SS_TX_ADC) - ; +double usrp2_dboard_iface::read_aux_adc(unit_t unit, aux_adc_t which) +{ + static const uhd::dict<unit_t, int> unit_to_spi_adc = + map_list_of(UNIT_RX, SPI_SS_RX_ADC)(UNIT_TX, SPI_SS_TX_ADC); - if (unit == UNIT_BOTH) throw uhd::runtime_error("UNIT_BOTH not supported."); + if (unit == UNIT_BOTH) + throw uhd::runtime_error("UNIT_BOTH not supported."); - //setup spi config args + // setup spi config args spi_config_t config; config.mosi_edge = spi_config_t::EDGE_FALL; config.miso_edge = spi_config_t::EDGE_RISE; - //setup the spi registers + // setup the spi registers ad7922_regs_t ad7922_regs; - switch(which){ - case AUX_ADC_A: ad7922_regs.mod = 0; break; - case AUX_ADC_B: ad7922_regs.mod = 1; break; - } ad7922_regs.chn = ad7922_regs.mod; //normal mode: mod == chn + switch (which) { + case AUX_ADC_A: + ad7922_regs.mod = 0; + break; + case AUX_ADC_B: + ad7922_regs.mod = 1; + break; + } + ad7922_regs.chn = ad7922_regs.mod; // normal mode: mod == chn - //write and read spi - _spi_iface->write_spi( - unit_to_spi_adc[unit], config, - ad7922_regs.get_reg(), 16 - ); - ad7922_regs.set_reg(uint16_t(_spi_iface->read_spi( - unit_to_spi_adc[unit], config, - ad7922_regs.get_reg(), 16 - ))); - - //convert to voltage and return - return 3.3*ad7922_regs.result/4095; + // write and read spi + _spi_iface->write_spi(unit_to_spi_adc[unit], config, ad7922_regs.get_reg(), 16); + ad7922_regs.set_reg(uint16_t( + _spi_iface->read_spi(unit_to_spi_adc[unit], config, ad7922_regs.get_reg(), 16))); + + // convert to voltage and return + return 3.3 * ad7922_regs.result / 4095; } uhd::time_spec_t usrp2_dboard_iface::get_command_time() @@ -343,7 +360,9 @@ void usrp2_dboard_iface::set_command_time(const uhd::time_spec_t& t) _wb_iface->set_time(t); } -void usrp2_dboard_iface::set_fe_connection(unit_t, const std::string&, const fe_connection_t&) +void usrp2_dboard_iface::set_fe_connection( + unit_t, const std::string&, const fe_connection_t&) { - throw uhd::not_implemented_error("fe connection configuration support not implemented"); + throw uhd::not_implemented_error( + "fe connection configuration support not implemented"); } diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 1f8540c16..792b4721b 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -32,13 +32,14 @@ using namespace uhd; using namespace uhd::usrp; using namespace uhd::transport; namespace asio = boost::asio; -namespace pt = boost::posix_time; +namespace pt = boost::posix_time; /*********************************************************************** * helpers **********************************************************************/ -static UHD_INLINE pt::time_duration to_time_dur(double timeout){ - return pt::microseconds(long(timeout*1e6)); +static UHD_INLINE pt::time_duration to_time_dur(double timeout) +{ + return pt::microseconds(long(timeout * 1e6)); } /*********************************************************************** @@ -51,7 +52,8 @@ static const size_t vrt_send_header_offset_words32 = 1; * - the pirate thread calls update * - the get send buffer calls check **********************************************************************/ -class flow_control_monitor{ +class flow_control_monitor +{ public: typedef uint32_t seq_type; typedef std::shared_ptr<flow_control_monitor> sptr; @@ -60,13 +62,15 @@ public: * Make a new flow control monitor. * \param max_seqs_out num seqs before throttling */ - flow_control_monitor(seq_type max_seqs_out):_max_seqs_out(max_seqs_out){ + flow_control_monitor(seq_type max_seqs_out) : _max_seqs_out(max_seqs_out) + { this->clear(); _ready_fcn = std::bind(&flow_control_monitor::ready, this); } //! Clear the monitor, Ex: when a streamer is created - void clear(void){ + void clear(void) + { _last_seq_out = 0; _last_seq_ack = 0; } @@ -76,7 +80,8 @@ public: * Increments the sequence for the next call * \return the sequence to be sent to the dsp */ - UHD_INLINE seq_type get_curr_seq_out(void){ + UHD_INLINE seq_type get_curr_seq_out(void) + { return _last_seq_out++; } @@ -85,10 +90,12 @@ public: * \param timeout the timeout in seconds * \return false on timeout */ - UHD_INLINE bool check_fc_condition(double timeout){ + UHD_INLINE bool check_fc_condition(double timeout) + { boost::mutex::scoped_lock lock(_fc_mutex); - if (this->ready()) return true; - boost::this_thread::disable_interruption di; //disable because the wait can throw + if (this->ready()) + return true; + boost::this_thread::disable_interruption di; // disable because the wait can throw return _fc_cond.timed_wait(lock, to_time_dur(timeout), _ready_fcn); } @@ -96,7 +103,8 @@ public: * Update the flow control condition. * \param seq the last sequence number to be ACK'd */ - UHD_INLINE void update_fc_condition(seq_type seq){ + UHD_INLINE void update_fc_condition(seq_type seq) + { boost::mutex::scoped_lock lock(_fc_mutex); _last_seq_ack = seq; lock.unlock(); @@ -104,8 +112,9 @@ public: } private: - bool ready(void){ - return seq_type(_last_seq_out -_last_seq_ack) < _max_seqs_out; + bool ready(void) + { + return seq_type(_last_seq_out - _last_seq_ack) < _max_seqs_out; } boost::mutex _fc_mutex; @@ -122,41 +131,44 @@ private: * - thread loop * - vrt packet handler states **********************************************************************/ -struct usrp2_impl::io_impl{ - - io_impl(void): - async_msg_fifo(1000/*messages deep*/), - tick_rate(1 /*non-zero default*/) +struct usrp2_impl::io_impl +{ + io_impl(void) + : async_msg_fifo(1000 /*messages deep*/), tick_rate(1 /*non-zero default*/) { /* NOP */ } - ~io_impl(void){ - //Manually deconstuct the tasks, since this was not happening automatically. + ~io_impl(void) + { + // Manually deconstuct the tasks, since this was not happening automatically. pirate_tasks.clear(); } - managed_send_buffer::sptr get_send_buff(size_t chan, double timeout){ - flow_control_monitor &fc_mon = *fc_mons[chan]; + managed_send_buffer::sptr get_send_buff(size_t chan, double timeout) + { + flow_control_monitor& fc_mon = *fc_mons[chan]; - //wait on flow control w/ timeout - if (not fc_mon.check_fc_condition(timeout)) return managed_send_buffer::sptr(); + // wait on flow control w/ timeout + if (not fc_mon.check_fc_condition(timeout)) + return managed_send_buffer::sptr(); - //get a buffer from the transport w/ timeout + // get a buffer from the transport w/ timeout managed_send_buffer::sptr buff = tx_xports[chan]->get_send_buff(timeout); - //write the flow control word into the buffer - if (buff.get()) buff->cast<uint32_t *>()[0] = uhd::htonx(fc_mon.get_curr_seq_out()); + // write the flow control word into the buffer + if (buff.get()) + buff->cast<uint32_t*>()[0] = uhd::htonx(fc_mon.get_curr_seq_out()); return buff; } - //tx dsp: xports and flow control monitors + // tx dsp: xports and flow control monitors std::vector<zero_copy_if::sptr> tx_xports; std::vector<flow_control_monitor::sptr> fc_mons; - //methods and variables for the pirate crew - void recv_pirate_loop(zero_copy_if::sptr, size_t, const std::atomic<bool> &); + // methods and variables for the pirate crew + void recv_pirate_loop(zero_copy_if::sptr, size_t, const std::atomic<bool>&); std::list<task::sptr> pirate_tasks; bounded_buffer<async_metadata_t> async_msg_fifo; double tick_rate; @@ -169,47 +181,54 @@ struct usrp2_impl::io_impl{ * - put async message packets into queue **********************************************************************/ void usrp2_impl::io_impl::recv_pirate_loop( - zero_copy_if::sptr err_xport, size_t index, const std::atomic<bool> &exit_loop -){ + zero_copy_if::sptr err_xport, size_t index, const std::atomic<bool>& exit_loop) +{ set_thread_priority_safe(); - //store a reference to the flow control monitor (offset by max dsps) - flow_control_monitor &fc_mon = *(this->fc_mons[index]); + // store a reference to the flow control monitor (offset by max dsps) + flow_control_monitor& fc_mon = *(this->fc_mons[index]); - while (not exit_loop){ + while (not exit_loop) { managed_recv_buffer::sptr buff = err_xport->get_recv_buff(); - if (not buff.get()) continue; //ignore timeout/error buffers + if (not buff.get()) + continue; // ignore timeout/error buffers - try{ - //extract the vrt header packet info + try { + // extract the vrt header packet info vrt::if_packet_info_t if_packet_info; - if_packet_info.num_packet_words32 = buff->size()/sizeof(uint32_t); - const uint32_t *vrt_hdr = buff->cast<const uint32_t *>(); + if_packet_info.num_packet_words32 = buff->size() / sizeof(uint32_t); + const uint32_t* vrt_hdr = buff->cast<const uint32_t*>(); vrt::if_hdr_unpack_be(vrt_hdr, if_packet_info); - //handle a tx async report message - if (if_packet_info.sid == USRP2_TX_ASYNC_SID and if_packet_info.packet_type != vrt::if_packet_info_t::PACKET_TYPE_DATA){ - - //fill in the async metadata + // handle a tx async report message + if (if_packet_info.sid == USRP2_TX_ASYNC_SID + and if_packet_info.packet_type + != vrt::if_packet_info_t::PACKET_TYPE_DATA) { + // fill in the async metadata async_metadata_t metadata; - load_metadata_from_buff(uhd::ntohx<uint32_t>, metadata, if_packet_info, vrt_hdr, tick_rate, index); - - //catch the flow control packets and react - if (metadata.event_code == 0){ + load_metadata_from_buff(uhd::ntohx<uint32_t>, + metadata, + if_packet_info, + vrt_hdr, + tick_rate, + index); + + // catch the flow control packets and react + if (metadata.event_code == 0) { uint32_t fc_word32 = (vrt_hdr + if_packet_info.num_header_words32)[1]; fc_mon.update_fc_condition(uhd::ntohx(fc_word32)); continue; } - //else UHD_LOGGER_DEBUG("USRP2") << "metadata.event_code " << metadata.event_code; + // else UHD_LOGGER_DEBUG("USRP2") << "metadata.event_code " << + // metadata.event_code; async_msg_fifo.push_with_pop_on_full(metadata); standard_async_msg_prints(metadata); + } else { + // TODO unknown received packet, may want to print error... } - else{ - //TODO unknown received packet, may want to print error... - } - }catch(const std::exception &e){ - UHD_LOGGER_ERROR("USRP2") << "Error in recv pirate loop: " << e.what() ; + } catch (const std::exception& e) { + UHD_LOGGER_ERROR("USRP2") << "Error in recv pirate loop: " << e.what(); } } } @@ -217,137 +236,166 @@ void usrp2_impl::io_impl::recv_pirate_loop( /*********************************************************************** * Helper Functions **********************************************************************/ -void usrp2_impl::io_init(void){ - //create new io impl +void usrp2_impl::io_init(void) +{ + // create new io impl _io_impl = UHD_PIMPL_MAKE(io_impl, ()); - //init first so we dont have an access race - for(const std::string &mb: _mbc.keys()){ - //init the tx xport and flow control monitor + // init first so we dont have an access race + for (const std::string& mb : _mbc.keys()) { + // init the tx xport and flow control monitor _io_impl->tx_xports.push_back(_mbc[mb].tx_dsp_xport); - _io_impl->fc_mons.push_back(flow_control_monitor::sptr(new flow_control_monitor( - device_addr.cast("send_buff_size", USRP2_SRAM_BYTES) / - _mbc[mb].tx_dsp_xport->get_send_frame_size() - ))); + _io_impl->fc_mons.push_back(flow_control_monitor::sptr( + new flow_control_monitor(device_addr.cast("send_buff_size", USRP2_SRAM_BYTES) + / _mbc[mb].tx_dsp_xport->get_send_frame_size()))); } - //allocate streamer weak ptrs containers - for(const std::string &mb: _mbc.keys()){ + // allocate streamer weak ptrs containers + for (const std::string& mb : _mbc.keys()) { _mbc[mb].rx_streamers.resize(_mbc[mb].rx_dsps.size()); - _mbc[mb].tx_streamers.resize(1/*known to be 1 dsp*/); + _mbc[mb].tx_streamers.resize(1 /*known to be 1 dsp*/); } - //create a new pirate thread for each zc if (yarr!!) + // create a new pirate thread for each zc if (yarr!!) size_t index = 0; - for(const std::string &mb: _mbc.keys()){ - //spawn a new pirate to plunder the recv booty - _io_impl->pirate_tasks.push_back(task::make(std::bind( - &usrp2_impl::io_impl::recv_pirate_loop, _io_impl.get(), - _mbc[mb].tx_dsp_xport, index++, - std::ref(_pirate_task_exit) - ))); + for (const std::string& mb : _mbc.keys()) { + // spawn a new pirate to plunder the recv booty + _io_impl->pirate_tasks.push_back( + task::make(std::bind(&usrp2_impl::io_impl::recv_pirate_loop, + _io_impl.get(), + _mbc[mb].tx_dsp_xport, + index++, + std::ref(_pirate_task_exit)))); } } -void usrp2_impl::update_tick_rate(const double rate){ - _io_impl->tick_rate = rate; //shadow for async msg +void usrp2_impl::update_tick_rate(const double rate) +{ + _io_impl->tick_rate = rate; // shadow for async msg - //update the tick rate on all existing streamers -> thread safe - for(const std::string &mb: _mbc.keys()){ - for (size_t i = 0; i < _mbc[mb].rx_streamers.size(); i++){ + // update the tick rate on all existing streamers -> thread safe + for (const std::string& mb : _mbc.keys()) { + for (size_t i = 0; i < _mbc[mb].rx_streamers.size(); i++) { std::shared_ptr<sph::recv_packet_streamer> my_streamer = - std::dynamic_pointer_cast<sph::recv_packet_streamer>(_mbc[mb].rx_streamers[i].lock()); - if (my_streamer.get() == NULL) continue; + std::dynamic_pointer_cast<sph::recv_packet_streamer>( + _mbc[mb].rx_streamers[i].lock()); + if (my_streamer.get() == NULL) + continue; my_streamer->set_tick_rate(rate); } - for (size_t i = 0; i < _mbc[mb].tx_streamers.size(); i++){ + for (size_t i = 0; i < _mbc[mb].tx_streamers.size(); i++) { std::shared_ptr<sph::send_packet_streamer> my_streamer = - std::dynamic_pointer_cast<sph::send_packet_streamer>(_mbc[mb].tx_streamers[i].lock()); - if (my_streamer.get() == NULL) continue; + std::dynamic_pointer_cast<sph::send_packet_streamer>( + _mbc[mb].tx_streamers[i].lock()); + if (my_streamer.get() == NULL) + continue; my_streamer->set_tick_rate(rate); } } } -void usrp2_impl::update_rx_samp_rate(const std::string &mb, const size_t dsp, const double rate){ +void usrp2_impl::update_rx_samp_rate( + const std::string& mb, const size_t dsp, const double rate) +{ std::shared_ptr<sph::recv_packet_streamer> my_streamer = - std::dynamic_pointer_cast<sph::recv_packet_streamer>(_mbc[mb].rx_streamers[dsp].lock()); - if (my_streamer.get() == NULL) return; + std::dynamic_pointer_cast<sph::recv_packet_streamer>( + _mbc[mb].rx_streamers[dsp].lock()); + if (my_streamer.get() == NULL) + return; my_streamer->set_samp_rate(rate); const double adj = _mbc[mb].rx_dsps[dsp]->get_scaling_adjustment(); my_streamer->set_scale_factor(adj); } -void usrp2_impl::update_tx_samp_rate(const std::string &mb, const size_t dsp, const double rate){ +void usrp2_impl::update_tx_samp_rate( + const std::string& mb, const size_t dsp, const double rate) +{ std::shared_ptr<sph::send_packet_streamer> my_streamer = - std::dynamic_pointer_cast<sph::send_packet_streamer>(_mbc[mb].tx_streamers[dsp].lock()); - if (my_streamer.get() == NULL) return; + std::dynamic_pointer_cast<sph::send_packet_streamer>( + _mbc[mb].tx_streamers[dsp].lock()); + if (my_streamer.get() == NULL) + return; my_streamer->set_samp_rate(rate); const double adj = _mbc[mb].tx_dsp->get_scaling_adjustment(); my_streamer->set_scale_factor(adj); } -void usrp2_impl::update_rates(void){ - for(const std::string &mb: _mbc.keys()){ +void usrp2_impl::update_rates(void) +{ + for (const std::string& mb : _mbc.keys()) { fs_path root = "/mboards/" + mb; _tree->access<double>(root / "tick_rate").update(); - //and now that the tick rate is set, init the host rates to something - for(const std::string &name: _tree->list(root / "rx_dsps")){ + // and now that the tick rate is set, init the host rates to something + for (const std::string& name : _tree->list(root / "rx_dsps")) { _tree->access<double>(root / "rx_dsps" / name / "rate" / "value").update(); } - for(const std::string &name: _tree->list(root / "tx_dsps")){ + for (const std::string& name : _tree->list(root / "tx_dsps")) { _tree->access<double>(root / "tx_dsps" / name / "rate" / "value").update(); } } } -void usrp2_impl::update_rx_subdev_spec(const std::string &which_mb, const subdev_spec_t &spec){ +void usrp2_impl::update_rx_subdev_spec( + const std::string& which_mb, const subdev_spec_t& spec) +{ fs_path root = "/mboards/" + which_mb + "/dboards"; - //sanity checking + // sanity checking validate_subdev_spec(_tree, spec, "rx", which_mb); - //setup mux for this spec + // setup mux for this spec bool fe_swapped = false; - for (size_t i = 0; i < spec.size(); i++){ - const std::string conn = _tree->access<std::string>(root / spec[i].db_name / "rx_frontends" / spec[i].sd_name / "connection").get(); - if (i == 0 and (conn == "QI" or conn == "Q")) fe_swapped = true; + for (size_t i = 0; i < spec.size(); i++) { + const std::string conn = + _tree + ->access<std::string>(root / spec[i].db_name / "rx_frontends" + / spec[i].sd_name / "connection") + .get(); + if (i == 0 and (conn == "QI" or conn == "Q")) + fe_swapped = true; _mbc[which_mb].rx_dsps[i]->set_mux(conn, fe_swapped); } _mbc[which_mb].rx_fe->set_mux(fe_swapped); - //compute the new occupancy and resize + // compute the new occupancy and resize _mbc[which_mb].rx_chan_occ = spec.size(); - size_t nchan = 0; - for(const std::string &mb: _mbc.keys()) nchan += _mbc[mb].rx_chan_occ; + size_t nchan = 0; + for (const std::string& mb : _mbc.keys()) + nchan += _mbc[mb].rx_chan_occ; } -void usrp2_impl::update_tx_subdev_spec(const std::string &which_mb, const subdev_spec_t &spec){ +void usrp2_impl::update_tx_subdev_spec( + const std::string& which_mb, const subdev_spec_t& spec) +{ fs_path root = "/mboards/" + which_mb + "/dboards"; - //sanity checking + // sanity checking validate_subdev_spec(_tree, spec, "tx", which_mb); - //set the mux for this spec - const std::string conn = _tree->access<std::string>(root / spec[0].db_name / "tx_frontends" / spec[0].sd_name / "connection").get(); + // set the mux for this spec + const std::string conn = + _tree + ->access<std::string>( + root / spec[0].db_name / "tx_frontends" / spec[0].sd_name / "connection") + .get(); _mbc[which_mb].tx_fe->set_mux(conn); - //compute the new occupancy and resize + // compute the new occupancy and resize _mbc[which_mb].tx_chan_occ = spec.size(); - size_t nchan = 0; - for(const std::string &mb: _mbc.keys()) nchan += _mbc[mb].tx_chan_occ; + size_t nchan = 0; + for (const std::string& mb : _mbc.keys()) + nchan += _mbc[mb].tx_chan_occ; } /*********************************************************************** * Async Data **********************************************************************/ -bool usrp2_impl::recv_async_msg( - async_metadata_t &async_metadata, double timeout -){ - boost::this_thread::disable_interruption di; //disable because the wait can throw +bool usrp2_impl::recv_async_msg(async_metadata_t& async_metadata, double timeout) +{ + boost::this_thread::disable_interruption di; // disable because the wait can throw return _io_impl->async_msg_fifo.pop_with_timed_wait(async_metadata, timeout); } @@ -355,120 +403,132 @@ bool usrp2_impl::recv_async_msg( * Stream destination programmer **********************************************************************/ void usrp2_impl::program_stream_dest( - zero_copy_if::sptr &xport, const uhd::stream_args_t &args -){ - //perform an initial flush of transport - while (xport->get_recv_buff(0.0)){} + zero_copy_if::sptr& xport, const uhd::stream_args_t& args) +{ + // perform an initial flush of transport + while (xport->get_recv_buff(0.0)) { + } - //program the stream command + // program the stream command usrp2_stream_ctrl_t stream_ctrl = usrp2_stream_ctrl_t(); - stream_ctrl.sequence = uhd::htonx(uint32_t(0 /* don't care seq num */)); - stream_ctrl.vrt_hdr = uhd::htonx(uint32_t(USRP2_INVALID_VRT_HEADER)); + stream_ctrl.sequence = uhd::htonx(uint32_t(0 /* don't care seq num */)); + stream_ctrl.vrt_hdr = uhd::htonx(uint32_t(USRP2_INVALID_VRT_HEADER)); - //user has provided an alternative address and port for destination - if (args.args.has_key("addr") and args.args.has_key("port")){ - UHD_LOGGER_INFO("USRP2") << boost::format( - "Programming streaming destination for custom address. " - "IPv4 Address: %s, UDP Port: %s" - ) % args.args["addr"] % args.args["port"]; + // user has provided an alternative address and port for destination + if (args.args.has_key("addr") and args.args.has_key("port")) { + UHD_LOGGER_INFO("USRP2") + << boost::format("Programming streaming destination for custom address. " + "IPv4 Address: %s, UDP Port: %s") + % args.args["addr"] % args.args["port"]; asio::io_service io_service; asio::ip::udp::resolver resolver(io_service); - asio::ip::udp::resolver::query query(asio::ip::udp::v4(), args.args["addr"], args.args["port"]); + asio::ip::udp::resolver::query query( + asio::ip::udp::v4(), args.args["addr"], args.args["port"]); asio::ip::udp::endpoint endpoint = *resolver.resolve(query); stream_ctrl.ip_addr = uhd::htonx(uint32_t(endpoint.address().to_v4().to_ulong())); stream_ctrl.udp_port = uhd::htonx(uint32_t(endpoint.port())); - for (size_t i = 0; i < 3; i++){ + for (size_t i = 0; i < 3; i++) { UHD_LOGGER_INFO("USRP2") << "ARP attempt " << i; managed_send_buffer::sptr send_buff = xport->get_send_buff(); - std::memcpy(send_buff->cast<void *>(), &stream_ctrl, sizeof(stream_ctrl)); + std::memcpy(send_buff->cast<void*>(), &stream_ctrl, sizeof(stream_ctrl)); send_buff->commit(sizeof(stream_ctrl)); send_buff.reset(); std::this_thread::sleep_for(std::chrono::milliseconds(300)); managed_recv_buffer::sptr recv_buff = xport->get_recv_buff(0.0); - if (recv_buff and recv_buff->size() >= sizeof(uint32_t)){ - const uint32_t result = uhd::ntohx(recv_buff->cast<const uint32_t *>()[0]); - if (result == 0){ + if (recv_buff and recv_buff->size() >= sizeof(uint32_t)) { + const uint32_t result = uhd::ntohx(recv_buff->cast<const uint32_t*>()[0]); + if (result == 0) { UHD_LOGGER_INFO("USRP2") << "Success! "; return; } } } - throw uhd::runtime_error("Device failed to ARP when programming alternative streaming destination."); + throw uhd::runtime_error( + "Device failed to ARP when programming alternative streaming destination."); } - else{ - //send the partial stream control without destination + else { + // send the partial stream control without destination managed_send_buffer::sptr send_buff = xport->get_send_buff(); - std::memcpy(send_buff->cast<void *>(), &stream_ctrl, sizeof(stream_ctrl)); - send_buff->commit(sizeof(stream_ctrl)/2); + std::memcpy(send_buff->cast<void*>(), &stream_ctrl, sizeof(stream_ctrl)); + send_buff->commit(sizeof(stream_ctrl) / 2); } } /*********************************************************************** * Receive streamer **********************************************************************/ -rx_streamer::sptr usrp2_impl::get_rx_stream(const uhd::stream_args_t &args_){ +rx_streamer::sptr usrp2_impl::get_rx_stream(const uhd::stream_args_t& args_) +{ stream_args_t args = args_; - //setup defaults for unspecified values - args.otw_format = args.otw_format.empty()? "sc16" : args.otw_format; - args.channels = args.channels.empty()? std::vector<size_t>(1, 0) : args.channels; - - //calculate packet size - static const size_t hdr_size = 0 - + vrt::max_if_hdr_words32*sizeof(uint32_t) - + sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer - - sizeof(vrt::if_packet_info_t().cid) //no class id ever used - - sizeof(vrt::if_packet_info_t().tsi) //no int time ever used - ; - const size_t bpp = _mbc[_mbc.keys().front()].rx_dsp_xports[0]->get_recv_frame_size() - hdr_size; + // setup defaults for unspecified values + args.otw_format = args.otw_format.empty() ? "sc16" : args.otw_format; + args.channels = args.channels.empty() ? std::vector<size_t>(1, 0) : args.channels; + + // calculate packet size + static const size_t hdr_size = + 0 + vrt::max_if_hdr_words32 * sizeof(uint32_t) + + sizeof(vrt::if_packet_info_t().tlr) // forced to have trailer + - sizeof(vrt::if_packet_info_t().cid) // no class id ever used + - sizeof(vrt::if_packet_info_t().tsi) // no int time ever used + ; + const size_t bpp = + _mbc[_mbc.keys().front()].rx_dsp_xports[0]->get_recv_frame_size() - hdr_size; const size_t bpi = convert::get_bytes_per_item(args.otw_format); - const size_t spp = args.args.cast<size_t>("spp", bpp/bpi); + const size_t spp = args.args.cast<size_t>("spp", bpp / bpi); - //make the new streamer given the samples per packet - std::shared_ptr<sph::recv_packet_streamer> my_streamer = std::make_shared<sph::recv_packet_streamer>(spp); + // make the new streamer given the samples per packet + std::shared_ptr<sph::recv_packet_streamer> my_streamer = + std::make_shared<sph::recv_packet_streamer>(spp); - //init some streamer stuff + // init some streamer stuff my_streamer->resize(args.channels.size()); my_streamer->set_vrt_unpacker(&vrt::if_hdr_unpack_be); - //set the converter + // set the converter uhd::convert::id_type id; - id.input_format = args.otw_format + "_item32_be"; - id.num_inputs = 1; + id.input_format = args.otw_format + "_item32_be"; + id.num_inputs = 1; id.output_format = args.cpu_format; - id.num_outputs = 1; + id.num_outputs = 1; my_streamer->set_converter(id); - //bind callbacks for the handler - for (size_t chan_i = 0; chan_i < args.channels.size(); chan_i++){ - const size_t chan = args.channels[chan_i]; + // bind callbacks for the handler + for (size_t chan_i = 0; chan_i < args.channels.size(); chan_i++) { + const size_t chan = args.channels[chan_i]; size_t num_chan_so_far = 0; - for(const std::string &mb: _mbc.keys()){ + for (const std::string& mb : _mbc.keys()) { num_chan_so_far += _mbc[mb].rx_chan_occ; - if (chan < num_chan_so_far){ + if (chan < num_chan_so_far) { const size_t dsp = chan + _mbc[mb].rx_chan_occ - num_chan_so_far; - _mbc[mb].rx_dsps[dsp]->set_nsamps_per_packet(spp); //seems to be a good place to set this + _mbc[mb].rx_dsps[dsp]->set_nsamps_per_packet( + spp); // seems to be a good place to set this _mbc[mb].rx_dsps[dsp]->setup(args); this->program_stream_dest(_mbc[mb].rx_dsp_xports[dsp], args); - my_streamer->set_xport_chan_get_buff(chan_i, std::bind( - &zero_copy_if::get_recv_buff, _mbc[mb].rx_dsp_xports[dsp], std::placeholders::_1 - ), true /*flush*/); - my_streamer->set_issue_stream_cmd(chan_i, std::bind( - &rx_dsp_core_200::issue_stream_command, _mbc[mb].rx_dsps[dsp], std::placeholders::_1)); - _mbc[mb].rx_streamers[dsp] = my_streamer; //store weak pointer + my_streamer->set_xport_chan_get_buff(chan_i, + std::bind(&zero_copy_if::get_recv_buff, + _mbc[mb].rx_dsp_xports[dsp], + std::placeholders::_1), + true /*flush*/); + my_streamer->set_issue_stream_cmd(chan_i, + std::bind(&rx_dsp_core_200::issue_stream_command, + _mbc[mb].rx_dsps[dsp], + std::placeholders::_1)); + _mbc[mb].rx_streamers[dsp] = my_streamer; // store weak pointer break; } } } - //set the packet threshold to be an entire socket buffer's worth - const size_t packets_per_sock_buff = size_t(50e6/_mbc[_mbc.keys().front()].rx_dsp_xports[0]->get_recv_frame_size()); + // set the packet threshold to be an entire socket buffer's worth + const size_t packets_per_sock_buff = + size_t(50e6 / _mbc[_mbc.keys().front()].rx_dsp_xports[0]->get_recv_frame_size()); my_streamer->set_alignment_failure_threshold(packets_per_sock_buff); - //sets all tick and samp rates on this streamer + // sets all tick and samp rates on this streamer this->update_rates(); return my_streamer; @@ -477,65 +537,74 @@ rx_streamer::sptr usrp2_impl::get_rx_stream(const uhd::stream_args_t &args_){ /*********************************************************************** * Transmit streamer **********************************************************************/ -tx_streamer::sptr usrp2_impl::get_tx_stream(const uhd::stream_args_t &args_){ +tx_streamer::sptr usrp2_impl::get_tx_stream(const uhd::stream_args_t& args_) +{ stream_args_t args = args_; - //setup defaults for unspecified values - args.otw_format = args.otw_format.empty()? "sc16" : args.otw_format; - args.channels = args.channels.empty()? std::vector<size_t>(1, 0) : args.channels; - - //calculate packet size - static const size_t hdr_size = 0 - + vrt_send_header_offset_words32*sizeof(uint32_t) - + vrt::max_if_hdr_words32*sizeof(uint32_t) - + sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer - - sizeof(vrt::if_packet_info_t().cid) //no class id ever used - - sizeof(vrt::if_packet_info_t().sid) //no stream id ever used - - sizeof(vrt::if_packet_info_t().tsi) //no int time ever used - ; - const size_t bpp = _mbc[_mbc.keys().front()].tx_dsp_xport->get_send_frame_size() - hdr_size; - const size_t spp = bpp/convert::get_bytes_per_item(args.otw_format); - - //make the new streamer given the samples per packet - std::shared_ptr<sph::send_packet_streamer> my_streamer = std::make_shared<sph::send_packet_streamer>(spp); - - //init some streamer stuff + // setup defaults for unspecified values + args.otw_format = args.otw_format.empty() ? "sc16" : args.otw_format; + args.channels = args.channels.empty() ? std::vector<size_t>(1, 0) : args.channels; + + // calculate packet size + static const size_t hdr_size = + 0 + vrt_send_header_offset_words32 * sizeof(uint32_t) + + vrt::max_if_hdr_words32 * sizeof(uint32_t) + + sizeof(vrt::if_packet_info_t().tlr) // forced to have trailer + - sizeof(vrt::if_packet_info_t().cid) // no class id ever used + - sizeof(vrt::if_packet_info_t().sid) // no stream id ever used + - sizeof(vrt::if_packet_info_t().tsi) // no int time ever used + ; + const size_t bpp = + _mbc[_mbc.keys().front()].tx_dsp_xport->get_send_frame_size() - hdr_size; + const size_t spp = bpp / convert::get_bytes_per_item(args.otw_format); + + // make the new streamer given the samples per packet + std::shared_ptr<sph::send_packet_streamer> my_streamer = + std::make_shared<sph::send_packet_streamer>(spp); + + // init some streamer stuff my_streamer->resize(args.channels.size()); my_streamer->set_vrt_packer(&vrt::if_hdr_pack_be, vrt_send_header_offset_words32); - //set the converter + // set the converter uhd::convert::id_type id; - id.input_format = args.cpu_format; - id.num_inputs = 1; + id.input_format = args.cpu_format; + id.num_inputs = 1; id.output_format = args.otw_format + "_item32_be"; - id.num_outputs = 1; + id.num_outputs = 1; my_streamer->set_converter(id); - //bind callbacks for the handler - for (size_t chan_i = 0; chan_i < args.channels.size(); chan_i++){ - const size_t chan = args.channels[chan_i]; + // bind callbacks for the handler + for (size_t chan_i = 0; chan_i < args.channels.size(); chan_i++) { + const size_t chan = args.channels[chan_i]; size_t num_chan_so_far = 0; - size_t abs = 0; - for(const std::string &mb: _mbc.keys()){ + size_t abs = 0; + for (const std::string& mb : _mbc.keys()) { num_chan_so_far += _mbc[mb].tx_chan_occ; - if (chan < num_chan_so_far){ + if (chan < num_chan_so_far) { const size_t dsp = chan + _mbc[mb].tx_chan_occ - num_chan_so_far; - if (not args.args.has_key("noclear")){ + if (not args.args.has_key("noclear")) { _io_impl->fc_mons[abs]->clear(); } _mbc[mb].tx_dsp->setup(args); - my_streamer->set_xport_chan_get_buff(chan_i, std::bind( - &usrp2_impl::io_impl::get_send_buff, _io_impl.get(), abs, std::placeholders::_1 - )); - my_streamer->set_async_receiver(std::bind(&bounded_buffer<async_metadata_t>::pop_with_timed_wait, &(_io_impl->async_msg_fifo), std::placeholders::_1, std::placeholders::_2)); - _mbc[mb].tx_streamers[dsp] = my_streamer; //store weak pointer + my_streamer->set_xport_chan_get_buff(chan_i, + std::bind(&usrp2_impl::io_impl::get_send_buff, + _io_impl.get(), + abs, + std::placeholders::_1)); + my_streamer->set_async_receiver( + std::bind(&bounded_buffer<async_metadata_t>::pop_with_timed_wait, + &(_io_impl->async_msg_fifo), + std::placeholders::_1, + std::placeholders::_2)); + _mbc[mb].tx_streamers[dsp] = my_streamer; // store weak pointer break; } - abs += 1; //assume 1 tx dsp + abs += 1; // assume 1 tx dsp } } - //sets all tick and samp rates on this streamer + // sets all tick and samp rates on this streamer this->update_rates(); return my_streamer; diff --git a/host/lib/usrp/usrp2/mb_eeprom.cpp b/host/lib/usrp/usrp2/mb_eeprom.cpp index bd91b527c..7bfe6159d 100644 --- a/host/lib/usrp/usrp2/mb_eeprom.cpp +++ b/host/lib/usrp/usrp2/mb_eeprom.cpp @@ -5,98 +5,105 @@ // #include "usrp2_impl.hpp" -#include <uhdlib/utils/eeprom_utils.hpp> -#include <uhd/usrp/mboard_eeprom.hpp> #include <uhd/types/byte_vector.hpp> #include <uhd/types/mac_addr.hpp> +#include <uhd/usrp/mboard_eeprom.hpp> +#include <uhdlib/utils/eeprom_utils.hpp> #include <boost/asio/ip/address_v4.hpp> namespace { - const uint8_t N200_EEPROM_ADDR = 0x50; - - struct n200_eeprom_map{ - uint16_t hardware; - uint8_t mac_addr[6]; - uint32_t subnet; - uint32_t ip_addr; - uint16_t _pad0; - uint16_t revision; - uint16_t product; - unsigned char _pad1; - unsigned char gpsdo; - unsigned char serial[SERIAL_LEN]; - unsigned char name[NAME_MAX_LEN]; - uint32_t gateway; - }; - - enum n200_gpsdo_type{ - N200_GPSDO_NONE = 0, - N200_GPSDO_INTERNAL = 1, - N200_GPSDO_ONBOARD = 2 - }; -} +const uint8_t N200_EEPROM_ADDR = 0x50; + +struct n200_eeprom_map +{ + uint16_t hardware; + uint8_t mac_addr[6]; + uint32_t subnet; + uint32_t ip_addr; + uint16_t _pad0; + uint16_t revision; + uint16_t product; + unsigned char _pad1; + unsigned char gpsdo; + unsigned char serial[SERIAL_LEN]; + unsigned char name[NAME_MAX_LEN]; + uint32_t gateway; +}; + +enum n200_gpsdo_type { + N200_GPSDO_NONE = 0, + N200_GPSDO_INTERNAL = 1, + N200_GPSDO_ONBOARD = 2 +}; +} // namespace using namespace uhd; using uhd::usrp::mboard_eeprom_t; -mboard_eeprom_t usrp2_impl::get_mb_eeprom(usrp2_iface &iface) +mboard_eeprom_t usrp2_impl::get_mb_eeprom(usrp2_iface& iface) { uhd::usrp::mboard_eeprom_t mb_eeprom; - //extract the hardware number + // extract the hardware number mb_eeprom["hardware"] = uint16_bytes_to_string( - iface.read_eeprom(N200_EEPROM_ADDR, offsetof(n200_eeprom_map, hardware), 2) - ); + iface.read_eeprom(N200_EEPROM_ADDR, offsetof(n200_eeprom_map, hardware), 2)); - //extract the revision number + // extract the revision number mb_eeprom["revision"] = uint16_bytes_to_string( - iface.read_eeprom(N200_EEPROM_ADDR, offsetof(n200_eeprom_map, revision), 2) - ); + iface.read_eeprom(N200_EEPROM_ADDR, offsetof(n200_eeprom_map, revision), 2)); - //extract the product code + // extract the product code mb_eeprom["product"] = uint16_bytes_to_string( - iface.read_eeprom(N200_EEPROM_ADDR, offsetof(n200_eeprom_map, product), 2) - ); + iface.read_eeprom(N200_EEPROM_ADDR, offsetof(n200_eeprom_map, product), 2)); - //extract the addresses - mb_eeprom["mac-addr"] = mac_addr_t::from_bytes(iface.read_eeprom( - N200_EEPROM_ADDR, offsetof(n200_eeprom_map, mac_addr), 6 - )).to_string(); + // extract the addresses + mb_eeprom["mac-addr"] = mac_addr_t::from_bytes( + iface.read_eeprom(N200_EEPROM_ADDR, offsetof(n200_eeprom_map, mac_addr), 6)) + .to_string(); boost::asio::ip::address_v4::bytes_type ip_addr_bytes; - byte_copy(iface.read_eeprom(N200_EEPROM_ADDR, offsetof(n200_eeprom_map, ip_addr), 4), ip_addr_bytes); + byte_copy(iface.read_eeprom(N200_EEPROM_ADDR, offsetof(n200_eeprom_map, ip_addr), 4), + ip_addr_bytes); mb_eeprom["ip-addr"] = boost::asio::ip::address_v4(ip_addr_bytes).to_string(); - byte_copy(iface.read_eeprom(N200_EEPROM_ADDR, offsetof(n200_eeprom_map, subnet), 4), ip_addr_bytes); + byte_copy(iface.read_eeprom(N200_EEPROM_ADDR, offsetof(n200_eeprom_map, subnet), 4), + ip_addr_bytes); mb_eeprom["subnet"] = boost::asio::ip::address_v4(ip_addr_bytes).to_string(); - byte_copy(iface.read_eeprom(N200_EEPROM_ADDR, offsetof(n200_eeprom_map, gateway), 4), ip_addr_bytes); + byte_copy(iface.read_eeprom(N200_EEPROM_ADDR, offsetof(n200_eeprom_map, gateway), 4), + ip_addr_bytes); mb_eeprom["gateway"] = boost::asio::ip::address_v4(ip_addr_bytes).to_string(); - //gpsdo capabilities - uint8_t gpsdo_byte = iface.read_eeprom(N200_EEPROM_ADDR, offsetof(n200_eeprom_map, gpsdo), 1).at(0); - switch(n200_gpsdo_type(gpsdo_byte)){ - case N200_GPSDO_INTERNAL: mb_eeprom["gpsdo"] = "internal"; break; - case N200_GPSDO_ONBOARD: mb_eeprom["gpsdo"] = "onboard"; break; - default: mb_eeprom["gpsdo"] = "none"; + // gpsdo capabilities + uint8_t gpsdo_byte = + iface.read_eeprom(N200_EEPROM_ADDR, offsetof(n200_eeprom_map, gpsdo), 1).at(0); + switch (n200_gpsdo_type(gpsdo_byte)) { + case N200_GPSDO_INTERNAL: + mb_eeprom["gpsdo"] = "internal"; + break; + case N200_GPSDO_ONBOARD: + mb_eeprom["gpsdo"] = "onboard"; + break; + default: + mb_eeprom["gpsdo"] = "none"; } - //extract the serial + // extract the serial mb_eeprom["serial"] = bytes_to_string(iface.read_eeprom( - N200_EEPROM_ADDR, offsetof(n200_eeprom_map, serial), SERIAL_LEN - )); + N200_EEPROM_ADDR, offsetof(n200_eeprom_map, serial), SERIAL_LEN)); - //extract the name + // extract the name mb_eeprom["name"] = bytes_to_string(iface.read_eeprom( - N200_EEPROM_ADDR, offsetof(n200_eeprom_map, name), NAME_MAX_LEN - )); - - //Empty serial correction: use the mac address to determine serial. - //Older usrp2 models don't have a serial burned into EEPROM. - //The lower mac address bits will function as the serial number. - if (mb_eeprom["serial"].empty()){ - byte_vector_t mac_addr_bytes = mac_addr_t::from_string(mb_eeprom["mac-addr"]).to_bytes(); - unsigned serial = mac_addr_bytes.at(5) | (unsigned(mac_addr_bytes.at(4) & 0x0f) << 8); + N200_EEPROM_ADDR, offsetof(n200_eeprom_map, name), NAME_MAX_LEN)); + + // Empty serial correction: use the mac address to determine serial. + // Older usrp2 models don't have a serial burned into EEPROM. + // The lower mac address bits will function as the serial number. + if (mb_eeprom["serial"].empty()) { + byte_vector_t mac_addr_bytes = + mac_addr_t::from_string(mb_eeprom["mac-addr"]).to_bytes(); + unsigned serial = mac_addr_bytes.at(5) + | (unsigned(mac_addr_bytes.at(4) & 0x0f) << 8); mb_eeprom["serial"] = std::to_string(serial); } @@ -104,72 +111,82 @@ mboard_eeprom_t usrp2_impl::get_mb_eeprom(usrp2_iface &iface) } -void usrp2_impl::set_mb_eeprom( - const std::string &mb, - const mboard_eeprom_t &mb_eeprom -) { - auto &iface = _mbc[mb].iface; - - //parse the revision number - if (mb_eeprom.has_key("hardware")) iface->write_eeprom( - N200_EEPROM_ADDR, offsetof(n200_eeprom_map, hardware), - string_to_uint16_bytes(mb_eeprom["hardware"]) - ); - - //parse the revision number - if (mb_eeprom.has_key("revision")) iface->write_eeprom( - N200_EEPROM_ADDR, offsetof(n200_eeprom_map, revision), - string_to_uint16_bytes(mb_eeprom["revision"]) - ); - - //parse the product code - if (mb_eeprom.has_key("product")) iface->write_eeprom( - N200_EEPROM_ADDR, offsetof(n200_eeprom_map, product), - string_to_uint16_bytes(mb_eeprom["product"]) - ); - - //store the addresses - if (mb_eeprom.has_key("mac-addr")) iface->write_eeprom( - N200_EEPROM_ADDR, offsetof(n200_eeprom_map, mac_addr), - mac_addr_t::from_string(mb_eeprom["mac-addr"]).to_bytes() - ); - - if (mb_eeprom.has_key("ip-addr")){ +void usrp2_impl::set_mb_eeprom(const std::string& mb, const mboard_eeprom_t& mb_eeprom) +{ + auto& iface = _mbc[mb].iface; + + // parse the revision number + if (mb_eeprom.has_key("hardware")) + iface->write_eeprom(N200_EEPROM_ADDR, + offsetof(n200_eeprom_map, hardware), + string_to_uint16_bytes(mb_eeprom["hardware"])); + + // parse the revision number + if (mb_eeprom.has_key("revision")) + iface->write_eeprom(N200_EEPROM_ADDR, + offsetof(n200_eeprom_map, revision), + string_to_uint16_bytes(mb_eeprom["revision"])); + + // parse the product code + if (mb_eeprom.has_key("product")) + iface->write_eeprom(N200_EEPROM_ADDR, + offsetof(n200_eeprom_map, product), + string_to_uint16_bytes(mb_eeprom["product"])); + + // store the addresses + if (mb_eeprom.has_key("mac-addr")) + iface->write_eeprom(N200_EEPROM_ADDR, + offsetof(n200_eeprom_map, mac_addr), + mac_addr_t::from_string(mb_eeprom["mac-addr"]).to_bytes()); + + if (mb_eeprom.has_key("ip-addr")) { byte_vector_t ip_addr_bytes(4); - byte_copy(boost::asio::ip::address_v4::from_string(mb_eeprom["ip-addr"]).to_bytes(), ip_addr_bytes); - iface->write_eeprom(N200_EEPROM_ADDR, offsetof(n200_eeprom_map, ip_addr), ip_addr_bytes); + byte_copy( + boost::asio::ip::address_v4::from_string(mb_eeprom["ip-addr"]).to_bytes(), + ip_addr_bytes); + iface->write_eeprom( + N200_EEPROM_ADDR, offsetof(n200_eeprom_map, ip_addr), ip_addr_bytes); } - if (mb_eeprom.has_key("subnet")){ + if (mb_eeprom.has_key("subnet")) { byte_vector_t ip_addr_bytes(4); - byte_copy(boost::asio::ip::address_v4::from_string(mb_eeprom["subnet"]).to_bytes(), ip_addr_bytes); - iface->write_eeprom(N200_EEPROM_ADDR, offsetof(n200_eeprom_map, subnet), ip_addr_bytes); + byte_copy( + boost::asio::ip::address_v4::from_string(mb_eeprom["subnet"]).to_bytes(), + ip_addr_bytes); + iface->write_eeprom( + N200_EEPROM_ADDR, offsetof(n200_eeprom_map, subnet), ip_addr_bytes); } - if (mb_eeprom.has_key("gateway")){ + if (mb_eeprom.has_key("gateway")) { byte_vector_t ip_addr_bytes(4); - byte_copy(boost::asio::ip::address_v4::from_string(mb_eeprom["gateway"]).to_bytes(), ip_addr_bytes); - iface->write_eeprom(N200_EEPROM_ADDR, offsetof(n200_eeprom_map, gateway), ip_addr_bytes); + byte_copy( + boost::asio::ip::address_v4::from_string(mb_eeprom["gateway"]).to_bytes(), + ip_addr_bytes); + iface->write_eeprom( + N200_EEPROM_ADDR, offsetof(n200_eeprom_map, gateway), ip_addr_bytes); } - //gpsdo capabilities - if (mb_eeprom.has_key("gpsdo")){ + // gpsdo capabilities + if (mb_eeprom.has_key("gpsdo")) { uint8_t gpsdo_byte = N200_GPSDO_NONE; - if (mb_eeprom["gpsdo"] == "internal") gpsdo_byte = N200_GPSDO_INTERNAL; - if (mb_eeprom["gpsdo"] == "onboard") gpsdo_byte = N200_GPSDO_ONBOARD; - iface->write_eeprom(N200_EEPROM_ADDR, offsetof(n200_eeprom_map, gpsdo), byte_vector_t(1, gpsdo_byte)); + if (mb_eeprom["gpsdo"] == "internal") + gpsdo_byte = N200_GPSDO_INTERNAL; + if (mb_eeprom["gpsdo"] == "onboard") + gpsdo_byte = N200_GPSDO_ONBOARD; + iface->write_eeprom(N200_EEPROM_ADDR, + offsetof(n200_eeprom_map, gpsdo), + byte_vector_t(1, gpsdo_byte)); } - //store the serial - if (mb_eeprom.has_key("serial")) iface->write_eeprom( - N200_EEPROM_ADDR, offsetof(n200_eeprom_map, serial), - string_to_bytes(mb_eeprom["serial"], SERIAL_LEN) - ); - - //store the name - if (mb_eeprom.has_key("name")) iface->write_eeprom( - N200_EEPROM_ADDR, offsetof(n200_eeprom_map, name), - string_to_bytes(mb_eeprom["name"], NAME_MAX_LEN) - ); + // store the serial + if (mb_eeprom.has_key("serial")) + iface->write_eeprom(N200_EEPROM_ADDR, + offsetof(n200_eeprom_map, serial), + string_to_bytes(mb_eeprom["serial"], SERIAL_LEN)); + + // store the name + if (mb_eeprom.has_key("name")) + iface->write_eeprom(N200_EEPROM_ADDR, + offsetof(n200_eeprom_map, name), + string_to_bytes(mb_eeprom["name"], NAME_MAX_LEN)); } - diff --git a/host/lib/usrp/usrp2/n200_image_loader.cpp b/host/lib/usrp/usrp2/n200_image_loader.cpp index 36da357e4..55b441c8b 100644 --- a/host/lib/usrp/usrp2/n200_image_loader.cpp +++ b/host/lib/usrp/usrp2/n200_image_loader.cpp @@ -5,30 +5,27 @@ // SPDX-License-Identifier: GPL-3.0-or-later // -#include <cstring> -#include <iostream> -#include <fstream> - -#include <boost/asio/ip/address_v4.hpp> -#include <boost/assign.hpp> -#include <boost/filesystem.hpp> -#include <boost/format.hpp> -#include <boost/thread.hpp> -#include <boost/algorithm/string/erase.hpp> - +#include "fw_common.h" +#include "usrp2_iface.hpp" +#include "usrp2_impl.hpp" #include <uhd/config.hpp> -#include <uhd/image_loader.hpp> #include <uhd/exception.hpp> +#include <uhd/image_loader.hpp> #include <uhd/transport/if_addrs.hpp> #include <uhd/transport/udp_simple.hpp> +#include <uhd/types/dict.hpp> #include <uhd/utils/byteswap.hpp> #include <uhd/utils/paths.hpp> #include <uhd/utils/static.hpp> -#include <uhd/types/dict.hpp> - -#include "fw_common.h" -#include "usrp2_iface.hpp" -#include "usrp2_impl.hpp" +#include <boost/algorithm/string/erase.hpp> +#include <boost/asio/ip/address_v4.hpp> +#include <boost/assign.hpp> +#include <boost/filesystem.hpp> +#include <boost/format.hpp> +#include <boost/thread.hpp> +#include <cstring> +#include <fstream> +#include <iostream> typedef boost::asio::ip::address_v4 ip_v4; @@ -48,12 +45,12 @@ using namespace uhd::transport; #define UDP_TIMEOUT 0.5 #define N200_FW_MAX_SIZE_BYTES 31744 -#define N200_PROD_FW_IMAGE_ADDR 0x00300000 -#define N200_SAFE_FW_IMAGE_ADDR 0x003F0000 +#define N200_PROD_FW_IMAGE_ADDR 0x00300000 +#define N200_SAFE_FW_IMAGE_ADDR 0x003F0000 #define N200_FPGA_MAX_SIZE_BYTES 1572864 -#define N200_PROD_FPGA_IMAGE_ADDR 0x00180000 -#define N200_SAFE_FPGA_IMAGE_ADDR 0x00000000 +#define N200_PROD_FPGA_IMAGE_ADDR 0x00180000 +#define N200_SAFE_FPGA_IMAGE_ADDR 0x00000000 /* * Packet codes @@ -62,7 +59,7 @@ typedef enum { UNKNOWN = ' ', N200_QUERY = 'a', - N200_ACK = 'A', + N200_ACK = 'A', GET_FLASH_INFO_CMD = 'f', GET_FLASH_INFO_ACK = 'F', @@ -71,8 +68,8 @@ typedef enum { ERASE_FLASH_ACK = 'E', CHECK_ERASING_DONE_CMD = 'd', - DONE_ERASING_ACK = 'D', - NOT_DONE_ERASING_ACK = 'B', + DONE_ERASING_ACK = 'D', + NOT_DONE_ERASING_ACK = 'B', WRITE_FLASH_CMD = 'w', WRITE_FLASH_ACK = 'W', @@ -90,30 +87,30 @@ typedef enum { /* * Mapping revision numbers to names */ -static const uhd::dict<uint32_t, std::string> n200_filename_map = boost::assign::map_list_of - (0, "n2xx") // Is an N-Series, but the EEPROM value is invalid - (0xa, "n200_r3") - (0x100a, "n200_r4") - (0x10a, "n210_r3") - (0x110a, "n210_r4") -; +static const uhd::dict<uint32_t, std::string> n200_filename_map = + boost::assign::map_list_of( + 0, "n2xx") // Is an N-Series, but the EEPROM value is invalid + (0xa, "n200_r3")(0x100a, "n200_r4")(0x10a, "n210_r3")(0x110a, "n210_r4"); /* * Packet structure */ -typedef struct { +typedef struct +{ uint32_t proto_ver; uint32_t id; uint32_t seq; union { uint32_t ip_addr; uint32_t hw_rev; - struct { + struct + { uint32_t flash_addr; uint32_t length; - uint8_t data[256]; + uint8_t data[256]; } flash_args; - struct { + struct + { uint32_t sector_size_bytes; uint32_t memory_size_bytes; } flash_info_args; @@ -123,90 +120,97 @@ typedef struct { /* * N-Series burn session */ -typedef struct { - bool fw; - bool overwrite_safe; - bool reset; +typedef struct +{ + bool fw; + bool overwrite_safe; + bool reset; uhd::device_addr_t dev_addr; - std::string burn_type; - std::string filepath; - uint8_t data_in[udp_simple::mtu]; - uint32_t size; - uint32_t max_size; - uint32_t flash_addr; - udp_simple::sptr xport; + std::string burn_type; + std::string filepath; + uint8_t data_in[udp_simple::mtu]; + uint32_t size; + uint32_t max_size; + uint32_t flash_addr; + udp_simple::sptr xport; } n200_session_t; /*********************************************************************** * uhd::image_loader functionality **********************************************************************/ -static void print_usrp2_error(const image_loader::image_loader_args_t &image_loader_args){ - #ifdef UHD_PLATFORM_WIN32 +static void print_usrp2_error(const image_loader::image_loader_args_t& image_loader_args) +{ +#ifdef UHD_PLATFORM_WIN32 std::string usrp2_card_burner_gui = "\""; - const std::string nl = " ^\n "; - #else + const std::string nl = " ^\n "; +#else std::string usrp2_card_burner_gui = "sudo \""; - const std::string nl = " \\\n "; - #endif + const std::string nl = " \\\n "; +#endif usrp2_card_burner_gui += find_utility("usrp2_card_burner_gui.py"); usrp2_card_burner_gui += "\""; - if(image_loader_args.load_firmware){ - usrp2_card_burner_gui += str(boost::format("%s--fw=\"%s\"") - % nl + if (image_loader_args.load_firmware) { + usrp2_card_burner_gui += str(boost::format("%s--fw=\"%s\"") % nl % ((image_loader_args.firmware_path == "") - ? find_image_path("usrp2_fw.bin") - : image_loader_args.firmware_path)); + ? find_image_path("usrp2_fw.bin") + : image_loader_args.firmware_path)); } - if(image_loader_args.load_fpga){ - usrp2_card_burner_gui += str(boost::format("%s--fpga=\"%s\"") - % nl - % ((image_loader_args.fpga_path == "") - ? find_image_path("usrp2_fpga.bin") - : image_loader_args.fpga_path)); + if (image_loader_args.load_fpga) { + usrp2_card_burner_gui += + str(boost::format("%s--fpga=\"%s\"") % nl + % ((image_loader_args.fpga_path == "") ? find_image_path("usrp2_fpga.bin") + : image_loader_args.fpga_path)); } - throw uhd::runtime_error(str(boost::format("The specified device is a USRP2, which is not supported by this utility.\n" - "Instead, plug the device's SD card into your machine and run this command:\n\n" - "%s" - ) % usrp2_card_burner_gui)); + throw uhd::runtime_error(str( + boost::format( + "The specified device is a USRP2, which is not supported by this utility.\n" + "Instead, plug the device's SD card into your machine and run this " + "command:\n\n" + "%s") + % usrp2_card_burner_gui)); } /* * Ethernet communication functions */ static UHD_INLINE size_t n200_send_and_recv(udp_simple::sptr xport, - n200_fw_update_id_t pkt_code, - n200_fw_update_data_t *pkt_out, - uint8_t* data){ + n200_fw_update_id_t pkt_code, + n200_fw_update_data_t* pkt_out, + uint8_t* data) +{ pkt_out->proto_ver = htonx<uint32_t>(USRP2_FW_COMPAT_NUM); - pkt_out->id = htonx<uint32_t>(pkt_code); + pkt_out->id = htonx<uint32_t>(pkt_code); xport->send(boost::asio::buffer(pkt_out, sizeof(*pkt_out))); return xport->recv(boost::asio::buffer(data, udp_simple::mtu), UDP_TIMEOUT); } -static UHD_INLINE bool n200_response_matches(const n200_fw_update_data_t *pkt_in, - n200_fw_update_id_t pkt_code, - size_t len){ - return (len > offsetof(n200_fw_update_data_t, data) and - ntohl(pkt_in->id) == (unsigned)pkt_code); +static UHD_INLINE bool n200_response_matches( + const n200_fw_update_data_t* pkt_in, n200_fw_update_id_t pkt_code, size_t len) +{ + return (len > offsetof(n200_fw_update_data_t, data) + and ntohl(pkt_in->id) == (unsigned)pkt_code); } -static uhd::device_addr_t n200_find(const image_loader::image_loader_args_t &image_loader_args){ - bool user_specified = image_loader_args.args.has_key("addr") or - image_loader_args.args.has_key("serial") or - image_loader_args.args.has_key("name"); +static uhd::device_addr_t n200_find( + const image_loader::image_loader_args_t& image_loader_args) +{ + bool user_specified = image_loader_args.args.has_key("addr") + or image_loader_args.args.has_key("serial") + or image_loader_args.args.has_key("name"); uhd::device_addrs_t found = usrp2_find(image_loader_args.args); - if(found.size() > 0){ + if (found.size() > 0) { uhd::device_addrs_t n200_found; udp_simple::sptr rev_xport; n200_fw_update_data_t pkt_out; uint8_t data_in[udp_simple::mtu]; - const n200_fw_update_data_t *pkt_in = reinterpret_cast<const n200_fw_update_data_t*>(data_in); + const n200_fw_update_data_t* pkt_in = + reinterpret_cast<const n200_fw_update_data_t*>(data_in); size_t len = 0; /* @@ -215,45 +219,43 @@ static uhd::device_addr_t n200_find(const image_loader::image_loader_args_t &ima * this query. If the user supplied specific arguments that * led to a USRP2, throw an error. */ - for(const uhd::device_addr_t &dev: found){ + for (const uhd::device_addr_t& dev : found) { rev_xport = udp_simple::make_connected( - dev.get("addr"), - BOOST_STRINGIZE(N200_UDP_FW_UPDATE_PORT) - ); + dev.get("addr"), BOOST_STRINGIZE(N200_UDP_FW_UPDATE_PORT)); len = n200_send_and_recv(rev_xport, GET_HW_REV_CMD, &pkt_out, data_in); - if(n200_response_matches(pkt_in, GET_HW_REV_ACK, len)){ - uint32_t rev = ntohl(pkt_in->data.hw_rev); + if (n200_response_matches(pkt_in, GET_HW_REV_ACK, len)) { + uint32_t rev = ntohl(pkt_in->data.hw_rev); std::string hw_rev = n200_filename_map.get(rev, "n2xx"); n200_found.push_back(dev); - n200_found[n200_found.size()-1]["hw_rev"] = hw_rev; - } - else if(len > offsetof(n200_fw_update_data_t, data) and ntohl(pkt_in->id) != GET_HW_REV_ACK){ - throw uhd::runtime_error(str(boost::format("Received invalid reply %d from device.") - % ntohl(pkt_in->id))); - } - else if(user_specified){ + n200_found[n200_found.size() - 1]["hw_rev"] = hw_rev; + } else if (len > offsetof(n200_fw_update_data_t, data) + and ntohl(pkt_in->id) != GET_HW_REV_ACK) { + throw uhd::runtime_error( + str(boost::format("Received invalid reply %d from device.") + % ntohl(pkt_in->id))); + } else if (user_specified) { // At this point, we haven't received any response, so assume it's a USRP2 print_usrp2_error(image_loader_args); } } // At this point, we should have a single N-Series device - if(n200_found.size() == 1){ + if (n200_found.size() == 1) { return n200_found[0]; - } - else if(n200_found.size() > 1){ - std::string err_msg = "Could not resolve given args to a single N-Series device.\n" - "Applicable devices:\n"; + } else if (n200_found.size() > 1) { + std::string err_msg = + "Could not resolve given args to a single N-Series device.\n" + "Applicable devices:\n"; - for(const uhd::device_addr_t &dev: n200_found){ - err_msg += str(boost::format("* %s (addr=%s)\n") - % dev.get("hw_rev") + for (const uhd::device_addr_t& dev : n200_found) { + err_msg += str(boost::format("* %s (addr=%s)\n") % dev.get("hw_rev") % dev.get("addr")); } - err_msg += "\nSpecify one of these devices with the given args to load an image onto it."; + err_msg += "\nSpecify one of these devices with the given args to load an " + "image onto it."; throw uhd::runtime_error(err_msg); } @@ -265,47 +267,53 @@ static uhd::device_addr_t n200_find(const image_loader::image_loader_args_t &ima /* * Validate and read firmware image */ -static void n200_validate_firmware_image(n200_session_t &session){ - if(not fs::exists(session.filepath)){ - throw uhd::runtime_error(str(boost::format("Could not find image at path \"%s\".") - % session.filepath)); +static void n200_validate_firmware_image(n200_session_t& session) +{ + if (not fs::exists(session.filepath)) { + throw uhd::runtime_error(str( + boost::format("Could not find image at path \"%s\".") % session.filepath)); } session.size = fs::file_size(session.filepath); session.max_size = N200_FW_MAX_SIZE_BYTES; - if(session.size > session.max_size){ - throw uhd::runtime_error(str(boost::format("The specified firmware image is too large: %d vs. %d") - % session.size % session.max_size)); + if (session.size > session.max_size) { + throw uhd::runtime_error( + str(boost::format("The specified firmware image is too large: %d vs. %d") + % session.size % session.max_size)); } // File must have proper header std::ifstream image_file(session.filepath.c_str(), std::ios::binary); uint8_t test_bytes[4]; image_file.seekg(0, std::ios::beg); - image_file.read((char*)test_bytes,4); + image_file.read((char*)test_bytes, 4); image_file.close(); - for(int i = 0; i < 4; i++) if(test_bytes[i] != 11){ - throw uhd::runtime_error(str(boost::format("The file at path \"%s\" is not a valid firmware image.") - % session.filepath)); - } + for (int i = 0; i < 4; i++) + if (test_bytes[i] != 11) { + throw uhd::runtime_error(str( + boost::format("The file at path \"%s\" is not a valid firmware image.") + % session.filepath)); + } } /* * Validate and validate FPGA image */ -static void n200_validate_fpga_image(n200_session_t &session){ - if(not fs::exists(session.filepath)){ - throw uhd::runtime_error(str(boost::format("Could not find image at path \"%s\".") - % session.filepath)); +static void n200_validate_fpga_image(n200_session_t& session) +{ + if (not fs::exists(session.filepath)) { + throw uhd::runtime_error(str( + boost::format("Could not find image at path \"%s\".") % session.filepath)); } session.size = fs::file_size(session.filepath); session.max_size = N200_FPGA_MAX_SIZE_BYTES; - if(session.size > session.max_size){ - throw uhd::runtime_error(str(boost::format("The specified FPGA image is too large: %d vs. %d") - % session.size % session.max_size)); + if (session.size > session.max_size) { + throw uhd::runtime_error( + str(boost::format("The specified FPGA image is too large: %d vs. %d") + % session.size % session.max_size)); } // File must have proper header @@ -314,18 +322,19 @@ static void n200_validate_fpga_image(n200_session_t &session){ image_file.seekg(0, std::ios::beg); image_file.read((char*)test_bytes, 63); bool is_good = false; - for(int i = 0; i < 62; i++){ - if(test_bytes[i] == 255) continue; - else if(test_bytes[i] == 170 and - test_bytes[i+1] == 153){ + for (int i = 0; i < 62; i++) { + if (test_bytes[i] == 255) + continue; + else if (test_bytes[i] == 170 and test_bytes[i + 1] == 153) { is_good = true; break; } } image_file.close(); - if(not is_good){ - throw uhd::runtime_error(str(boost::format("The file at path \"%s\" is not a valid FPGA image.") - % session.filepath)); + if (not is_good) { + throw uhd::runtime_error( + str(boost::format("The file at path \"%s\" is not a valid FPGA image.") + % session.filepath)); } } @@ -333,12 +342,11 @@ static void n200_validate_fpga_image(n200_session_t &session){ * Set up a session for burning an N-Series image. This session info * will be passed into the erase, burn, and verify functions. */ -static void n200_setup_session(n200_session_t &session, - const image_loader::image_loader_args_t &image_loader_args, - bool fw){ - - - session.fw = fw; +static void n200_setup_session(n200_session_t& session, + const image_loader::image_loader_args_t& image_loader_args, + bool fw) +{ + session.fw = fw; session.reset = image_loader_args.args.has_key("reset"); /* @@ -347,156 +355,162 @@ static void n200_setup_session(n200_session_t &session, * EEPROM or is otherwise unable to provide its revision, this is * impossible, and the user must manually provide a firmware file. */ - if((session.fw and image_loader_args.firmware_path == "") or - image_loader_args.fpga_path == ""){ - if(session.dev_addr["hw_rev"] == "n2xx"){ + if ((session.fw and image_loader_args.firmware_path == "") + or image_loader_args.fpga_path == "") { + if (session.dev_addr["hw_rev"] == "n2xx") { throw uhd::runtime_error("This device's revision cannot be determined. " "You must manually specify a filepath."); + } else { + session.filepath = + session.fw ? find_image_path( + str(boost::format("usrp_%s_fw.bin") + % erase_tail_copy(session.dev_addr["hw_rev"], 3))) + : find_image_path(str(boost::format("usrp_%s_fpga.bin") + % session.dev_addr["hw_rev"])); } - else{ - session.filepath = session.fw ? find_image_path(str(boost::format("usrp_%s_fw.bin") - % erase_tail_copy(session.dev_addr["hw_rev"],3))) - : find_image_path(str(boost::format("usrp_%s_fpga.bin") - % session.dev_addr["hw_rev"])); - } - } - else{ + } else { session.filepath = session.fw ? image_loader_args.firmware_path : image_loader_args.fpga_path; } - if(session.fw) n200_validate_firmware_image(session); - else n200_validate_fpga_image(session); + if (session.fw) + n200_validate_firmware_image(session); + else + n200_validate_fpga_image(session); session.overwrite_safe = image_loader_args.args.has_key("overwrite-safe"); - if(session.overwrite_safe){ + if (session.overwrite_safe) { session.flash_addr = session.fw ? N200_SAFE_FW_IMAGE_ADDR : N200_SAFE_FPGA_IMAGE_ADDR; - session.burn_type = session.fw ? "firmware safe" - : "FPGA safe"; - } - else{ + session.burn_type = session.fw ? "firmware safe" : "FPGA safe"; + } else { session.flash_addr = session.fw ? N200_PROD_FW_IMAGE_ADDR : N200_PROD_FPGA_IMAGE_ADDR; - session.burn_type = session.fw ? "firmware" - : "FPGA"; + session.burn_type = session.fw ? "firmware" : "FPGA"; } - session.xport = udp_simple::make_connected(session.dev_addr["addr"], - BOOST_STRINGIZE(N200_UDP_FW_UPDATE_PORT)); + session.xport = udp_simple::make_connected( + session.dev_addr["addr"], BOOST_STRINGIZE(N200_UDP_FW_UPDATE_PORT)); } -static void n200_erase_image(n200_session_t &session){ - +static void n200_erase_image(n200_session_t& session) +{ // UDP receive buffer n200_fw_update_data_t pkt_out; - const n200_fw_update_data_t *pkt_in = reinterpret_cast<const n200_fw_update_data_t*>(session.data_in); + const n200_fw_update_data_t* pkt_in = + reinterpret_cast<const n200_fw_update_data_t*>(session.data_in); // Setting up UDP packet pkt_out.data.flash_args.flash_addr = htonx<uint32_t>(session.flash_addr); - pkt_out.data.flash_args.length = htonx<uint32_t>(session.size); + pkt_out.data.flash_args.length = htonx<uint32_t>(session.size); // Begin erasing - size_t len = n200_send_and_recv(session.xport, ERASE_FLASH_CMD, &pkt_out, session.data_in); - if(n200_response_matches(pkt_in, ERASE_FLASH_ACK, len)){ - std::cout << boost::format("-- Erasing %s image...") % session.burn_type << std::flush; - } - else if(len < offsetof(n200_fw_update_data_t, data)){ + size_t len = + n200_send_and_recv(session.xport, ERASE_FLASH_CMD, &pkt_out, session.data_in); + if (n200_response_matches(pkt_in, ERASE_FLASH_ACK, len)) { + std::cout << boost::format("-- Erasing %s image...") % session.burn_type + << std::flush; + } else if (len < offsetof(n200_fw_update_data_t, data)) { std::cout << "failed." << std::endl; throw uhd::runtime_error("Timed out waiting for reply from device."); - } - else if(ntohl(pkt_in->id) != ERASE_FLASH_ACK){ + } else if (ntohl(pkt_in->id) != ERASE_FLASH_ACK) { std::cout << "failed." << std::endl; - throw uhd::runtime_error(str(boost::format("Received invalid reply %d from device.\n") - % ntohl(pkt_in->id))); - } - else{ + throw uhd::runtime_error( + str(boost::format("Received invalid reply %d from device.\n") + % ntohl(pkt_in->id))); + } else { std::cout << "failed." << std::endl; throw uhd::runtime_error("Did not receive response from device."); } // Check for erase completion - while(true){ - len = n200_send_and_recv(session.xport, CHECK_ERASING_DONE_CMD, &pkt_out, session.data_in); - if(n200_response_matches(pkt_in, DONE_ERASING_ACK, len)){ + while (true) { + len = n200_send_and_recv( + session.xport, CHECK_ERASING_DONE_CMD, &pkt_out, session.data_in); + if (n200_response_matches(pkt_in, DONE_ERASING_ACK, len)) { std::cout << "successful." << std::endl; break; - } - else if(len < offsetof(n200_fw_update_data_t, data)){ + } else if (len < offsetof(n200_fw_update_data_t, data)) { std::cout << "failed." << std::endl; throw uhd::runtime_error("Timed out waiting for reply from device."); - } - else if(ntohl(pkt_in->id) != NOT_DONE_ERASING_ACK){ + } else if (ntohl(pkt_in->id) != NOT_DONE_ERASING_ACK) { std::cout << "failed." << std::endl; - throw uhd::runtime_error(str(boost::format("Received invalid reply %d from device.\n") - % ntohl(pkt_in->id))); + throw uhd::runtime_error( + str(boost::format("Received invalid reply %d from device.\n") + % ntohl(pkt_in->id))); } } } -static void n200_write_image(n200_session_t &session){ - +static void n200_write_image(n200_session_t& session) +{ // UDP receive buffer n200_fw_update_data_t pkt_out; - const n200_fw_update_data_t *pkt_in = reinterpret_cast<const n200_fw_update_data_t*>(session.data_in); + const n200_fw_update_data_t* pkt_in = + reinterpret_cast<const n200_fw_update_data_t*>(session.data_in); size_t len = 0; // Write image std::ifstream image(session.filepath.c_str(), std::ios::binary); - uint32_t current_addr = session.flash_addr; + uint32_t current_addr = session.flash_addr; pkt_out.data.flash_args.length = htonx<uint32_t>(N200_FLASH_DATA_PACKET_SIZE); - for(size_t i = 0; i < ((session.size/N200_FLASH_DATA_PACKET_SIZE)+1); i++){ + for (size_t i = 0; i < ((session.size / N200_FLASH_DATA_PACKET_SIZE) + 1); i++) { pkt_out.data.flash_args.flash_addr = htonx<uint32_t>(current_addr); memset(pkt_out.data.flash_args.data, 0x0, N200_FLASH_DATA_PACKET_SIZE); image.read((char*)pkt_out.data.flash_args.data, N200_FLASH_DATA_PACKET_SIZE); - len = n200_send_and_recv(session.xport, WRITE_FLASH_CMD, &pkt_out, session.data_in); - if(n200_response_matches(pkt_in, WRITE_FLASH_ACK, len)){ - std::cout << boost::format("\r-- Writing %s image (%d%%)") - % session.burn_type - % int((double(current_addr-session.flash_addr)/double(session.size))*100) + len = + n200_send_and_recv(session.xport, WRITE_FLASH_CMD, &pkt_out, session.data_in); + if (n200_response_matches(pkt_in, WRITE_FLASH_ACK, len)) { + std::cout << boost::format("\r-- Writing %s image (%d%%)") % session.burn_type + % int((double(current_addr - session.flash_addr) + / double(session.size)) + * 100) << std::flush; - } - else if(len < offsetof(n200_fw_update_data_t, data)){ + } else if (len < offsetof(n200_fw_update_data_t, data)) { image.close(); std::cout << boost::format("\r--Writing %s image..failed at %d%%.") % session.burn_type - % int((double(current_addr-session.flash_addr)/double(session.size))*100) + % int((double(current_addr - session.flash_addr) + / double(session.size)) + * 100) << std::endl; throw uhd::runtime_error("Timed out waiting for reply from device."); - } - else if(ntohl(pkt_in->id) != WRITE_FLASH_ACK){ + } else if (ntohl(pkt_in->id) != WRITE_FLASH_ACK) { image.close(); std::cout << boost::format("\r--Writing %s image..failed at %d%%.") % session.burn_type - % int((double(current_addr-session.flash_addr)/double(session.size))*100) + % int((double(current_addr - session.flash_addr) + / double(session.size)) + * 100) << std::endl; - throw uhd::runtime_error(str(boost::format("Received invalid reply %d from device.\n") - % ntohl(pkt_in->id))); + throw uhd::runtime_error( + str(boost::format("Received invalid reply %d from device.\n") + % ntohl(pkt_in->id))); } current_addr += N200_FLASH_DATA_PACKET_SIZE; } - std::cout << boost::format("\r-- Writing %s image...successful.") - % session.burn_type + std::cout << boost::format("\r-- Writing %s image...successful.") % session.burn_type << std::endl; image.close(); } -static void n200_verify_image(n200_session_t &session){ - +static void n200_verify_image(n200_session_t& session) +{ // UDP receive buffer n200_fw_update_data_t pkt_out; - const n200_fw_update_data_t *pkt_in = reinterpret_cast<const n200_fw_update_data_t*>(session.data_in); + const n200_fw_update_data_t* pkt_in = + reinterpret_cast<const n200_fw_update_data_t*>(session.data_in); size_t len = 0; // Read and verify image std::ifstream image(session.filepath.c_str(), std::ios::binary); uint8_t image_part[N200_FLASH_DATA_PACKET_SIZE]; - uint32_t current_addr = session.flash_addr; + uint32_t current_addr = session.flash_addr; pkt_out.data.flash_args.length = htonx<uint32_t>(N200_FLASH_DATA_PACKET_SIZE); - uint16_t cmp_len = 0; - for(size_t i = 0; i < ((session.size/N200_FLASH_DATA_PACKET_SIZE)+1); i++){ + uint16_t cmp_len = 0; + for (size_t i = 0; i < ((session.size / N200_FLASH_DATA_PACKET_SIZE) + 1); i++) { memset(image_part, 0x0, N200_FLASH_DATA_PACKET_SIZE); memset((void*)pkt_in->data.flash_args.data, 0x0, N200_FLASH_DATA_PACKET_SIZE); @@ -504,57 +518,66 @@ static void n200_verify_image(n200_session_t &session){ image.read((char*)image_part, N200_FLASH_DATA_PACKET_SIZE); cmp_len = image.gcount(); - len = n200_send_and_recv(session.xport, READ_FLASH_CMD, &pkt_out, session.data_in); - if(n200_response_matches(pkt_in, READ_FLASH_ACK, len)){ + len = + n200_send_and_recv(session.xport, READ_FLASH_CMD, &pkt_out, session.data_in); + if (n200_response_matches(pkt_in, READ_FLASH_ACK, len)) { std::cout << boost::format("\r-- Verifying %s image (%d%%)") % session.burn_type - % int((double(current_addr-session.flash_addr)/double(session.size))*100) + % int((double(current_addr - session.flash_addr) + / double(session.size)) + * 100) << std::flush; - if(memcmp(image_part, pkt_in->data.flash_args.data, cmp_len)){ + if (memcmp(image_part, pkt_in->data.flash_args.data, cmp_len)) { std::cout << boost::format("\r-- Verifying %s image...failed at %d%%.") % session.burn_type - % int((double(current_addr-session.flash_addr)/double(session.size))*100) + % int((double(current_addr - session.flash_addr) + / double(session.size)) + * 100) << std::endl; - throw uhd::runtime_error(str(boost::format("Failed to verify %s image.") - % session.burn_type)); + throw uhd::runtime_error( + str(boost::format("Failed to verify %s image.") % session.burn_type)); } - } - else if(len < offsetof(n200_fw_update_data_t, data)){ + } else if (len < offsetof(n200_fw_update_data_t, data)) { image.close(); std::cout << boost::format("\r-- Verifying %s image...failed at %d%%.") % session.burn_type - % int((double(current_addr-session.flash_addr)/double(session.size))*100) + % int((double(current_addr - session.flash_addr) + / double(session.size)) + * 100) << std::endl; throw uhd::runtime_error("Timed out waiting for reply from device."); - } - else if(ntohl(pkt_in->id) != READ_FLASH_ACK){ + } else if (ntohl(pkt_in->id) != READ_FLASH_ACK) { image.close(); std::cout << boost::format("\r-- Verifying %s image...failed at %d%%.") % session.burn_type - % int((double(current_addr-session.flash_addr)/double(session.size))*100) + % int((double(current_addr - session.flash_addr) + / double(session.size)) + * 100) << std::endl; - throw uhd::runtime_error(str(boost::format("Received invalid reply %d from device.\n") - % ntohl(pkt_in->id))); + throw uhd::runtime_error( + str(boost::format("Received invalid reply %d from device.\n") + % ntohl(pkt_in->id))); } current_addr += N200_FLASH_DATA_PACKET_SIZE; } - std::cout << boost::format("\r-- Verifying %s image...successful.") % session.burn_type + std::cout << boost::format("\r-- Verifying %s image...successful.") + % session.burn_type << std::endl; image.close(); } -static void n200_reset(n200_session_t &session){ - +static void n200_reset(n200_session_t& session) +{ // UDP receive buffer n200_fw_update_data_t pkt_out; // There should be no response std::cout << "-- Resetting device..." << std::flush; size_t len = n200_send_and_recv(session.xport, RESET_CMD, &pkt_out, session.data_in); - if(len > 0){ + if (len > 0) { std::cout << "failed." << std::endl; throw uhd::runtime_error("Failed to reset N200."); } @@ -562,20 +585,22 @@ static void n200_reset(n200_session_t &session){ } // n210_r4 -> N210 r4 -static std::string nice_name(const std::string &fw_rev){ +static std::string nice_name(const std::string& fw_rev) +{ std::string ret = fw_rev; - ret[0] = ::toupper(ret[0]); + ret[0] = ::toupper(ret[0]); size_t pos = 0; - if((pos = fw_rev.find("_")) != std::string::npos){ + if ((pos = fw_rev.find("_")) != std::string::npos) { ret[pos] = ' '; } return ret; } -static bool n200_image_loader(const image_loader::image_loader_args_t &image_loader_args){ - if(!image_loader_args.load_firmware and !image_loader_args.load_fpga){ +static bool n200_image_loader(const image_loader::image_loader_args_t& image_loader_args) +{ + if (!image_loader_args.load_firmware and !image_loader_args.load_fpga) { return false; } @@ -583,43 +608,36 @@ static bool n200_image_loader(const image_loader::image_loader_args_t &image_loa // This will throw if specific args lead to a USRP2 n200_session_t session; session.dev_addr = n200_find(image_loader_args); - if(session.dev_addr.size() == 0){ + if (session.dev_addr.size() == 0) { return false; } std::cout << boost::format("Unit: USRP %s (%s, %s)") - % nice_name(session.dev_addr.get("hw_rev")) - % session.dev_addr.get("serial") - % session.dev_addr.get("addr") - << std::endl; + % nice_name(session.dev_addr.get("hw_rev")) + % session.dev_addr.get("serial") % session.dev_addr.get("addr") + << std::endl; - if(image_loader_args.load_firmware){ - n200_setup_session(session, - image_loader_args, - true - ); + if (image_loader_args.load_firmware) { + n200_setup_session(session, image_loader_args, true); std::cout << "Firmware image: " << session.filepath << std::endl; n200_erase_image(session); n200_write_image(session); n200_verify_image(session); - if(session.reset and !image_loader_args.load_fpga){ + if (session.reset and !image_loader_args.load_fpga) { n200_reset(session); } } - if(image_loader_args.load_fpga){ - n200_setup_session(session, - image_loader_args, - false - ); + if (image_loader_args.load_fpga) { + n200_setup_session(session, image_loader_args, false); std::cout << "FPGA image: " << session.filepath << std::endl; n200_erase_image(session); n200_write_image(session); n200_verify_image(session); - if(session.reset){ + if (session.reset) { n200_reset(session); } } @@ -627,10 +645,13 @@ static bool n200_image_loader(const image_loader::image_loader_args_t &image_loa return true; } -UHD_STATIC_BLOCK(register_n200_image_loader){ - std::string recovery_instructions = "Aborting. Your USRP-N Series unit will likely be unusable.\n" - "Refer to http://files.ettus.com/manual/page_usrp2.html#usrp2_loadflash_brick\n" - "for details on restoring your device."; +UHD_STATIC_BLOCK(register_n200_image_loader) +{ + std::string recovery_instructions = + "Aborting. Your USRP-N Series unit will likely be unusable.\n" + "Refer to http://files.ettus.com/manual/page_usrp2.html#usrp2_loadflash_brick\n" + "for details on restoring your device."; - image_loader::register_image_loader("usrp2", n200_image_loader, recovery_instructions); + image_loader::register_image_loader( + "usrp2", n200_image_loader, recovery_instructions); } diff --git a/host/lib/usrp/usrp2/usrp2_clk_regs.hpp b/host/lib/usrp/usrp2/usrp2_clk_regs.hpp index ac58decc0..c85bdf35d 100644 --- a/host/lib/usrp/usrp2/usrp2_clk_regs.hpp +++ b/host/lib/usrp/usrp2/usrp2_clk_regs.hpp @@ -10,78 +10,84 @@ #include "usrp2_iface.hpp" -class usrp2_clk_regs_t { +class usrp2_clk_regs_t +{ public: - usrp2_clk_regs_t(void): - test(0), - fpga(0), - adc(0), - dac(0), - serdes(0), - exp(0), - tx_db(0), - rx_db(0) {} + usrp2_clk_regs_t(void) + : test(0), fpga(0), adc(0), dac(0), serdes(0), exp(0), tx_db(0), rx_db(0) + { + } - usrp2_clk_regs_t(usrp2_iface::rev_type rev) { - fpga = adc = serdes = exp = tx_db = 0; - test = 0; - fpga = 1; - dac = 3; + usrp2_clk_regs_t(usrp2_iface::rev_type rev) + { + fpga = adc = serdes = exp = tx_db = 0; + test = 0; + fpga = 1; + dac = 3; - switch(rev) { - case usrp2_iface::USRP2_REV3: - exp = 2; - adc = 4; - serdes = 2; - tx_db = 6; - break; - case usrp2_iface::USRP2_REV4: - exp = 5; - adc = 4; - serdes = 2; - tx_db = 6; - break; - case usrp2_iface::USRP_N200: - case usrp2_iface::USRP_N210: - case usrp2_iface::USRP_N200_R4: - case usrp2_iface::USRP_N210_R4: - exp = 6; - adc = 2; - serdes = 4; - tx_db = 5; - break; - case usrp2_iface::USRP_NXXX: - //dont throw, it may be unitialized - break; - } + switch (rev) { + case usrp2_iface::USRP2_REV3: + exp = 2; + adc = 4; + serdes = 2; + tx_db = 6; + break; + case usrp2_iface::USRP2_REV4: + exp = 5; + adc = 4; + serdes = 2; + tx_db = 6; + break; + case usrp2_iface::USRP_N200: + case usrp2_iface::USRP_N210: + case usrp2_iface::USRP_N200_R4: + case usrp2_iface::USRP_N210_R4: + exp = 6; + adc = 2; + serdes = 4; + tx_db = 5; + break; + case usrp2_iface::USRP_NXXX: + // dont throw, it may be unitialized + break; + } - rx_db = 7; - } + rx_db = 7; + } - static int output(int clknum) { return 0x3C + clknum; } - static int div_lo(int clknum) { return 0x48 + 2 * clknum; } - static int div_hi(int clknum) { return 0x49 + 2 * clknum; } + static int output(int clknum) + { + return 0x3C + clknum; + } + static int div_lo(int clknum) + { + return 0x48 + 2 * clknum; + } + static int div_hi(int clknum) + { + return 0x49 + 2 * clknum; + } - const static int acounter = 0x04; - const static int bcounter_msb = 0x05; - const static int bcounter_lsb = 0x06; - const static int pll_1 = 0x07; - const static int pll_2 = 0x08; - const static int pll_3 = 0x09; - const static int pll_4 = 0x0A; - const static int ref_counter_msb = 0x0B; - const static int ref_counter_lsb = 0x0C; - const static int pll_5 = 0x0D; - const static int update = 0x5A; + const static int acounter = 0x04; + const static int bcounter_msb = 0x05; + const static int bcounter_lsb = 0x06; + const static int pll_1 = 0x07; + const static int pll_2 = 0x08; + const static int pll_3 = 0x09; + const static int pll_4 = 0x0A; + const static int ref_counter_msb = 0x0B; + const static int ref_counter_lsb = 0x0C; + const static int pll_5 = 0x0D; + const static int update = 0x5A; - int test; - int fpga; - int adc; - int dac; - int serdes; - int exp; - int tx_db; - int rx_db; + int test; + int fpga; + int adc; + int dac; + int serdes; + int exp; + int tx_db; + int rx_db; }; -#endif //INCLUDED_USRP2_CLK_REGS_HPP +#endif // INCLUDED_USRP2_CLK_REGS_HPP diff --git a/host/lib/usrp/usrp2/usrp2_fifo_ctrl.cpp b/host/lib/usrp/usrp2/usrp2_fifo_ctrl.cpp index 0c0a21851..ca3a79ca5 100644 --- a/host/lib/usrp/usrp2/usrp2_fifo_ctrl.cpp +++ b/host/lib/usrp/usrp2/usrp2_fifo_ctrl.cpp @@ -5,24 +5,24 @@ // SPDX-License-Identifier: GPL-3.0-or-later // +#include "usrp2_fifo_ctrl.hpp" #include "usrp2_regs.hpp" #include <uhd/exception.hpp> +#include <uhd/transport/vrt_if_packet.hpp> #include <uhd/utils/log.hpp> #include <uhd/utils/safe_call.hpp> -#include <uhd/transport/vrt_if_packet.hpp> -#include "usrp2_fifo_ctrl.hpp" -#include <boost/thread/mutex.hpp> -#include <boost/thread/thread.hpp> #include <boost/asio.hpp> //htonl #include <boost/format.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> using namespace uhd; using namespace uhd::transport; -static const size_t POKE32_CMD = (1 << 8); -static const size_t PEEK32_CMD = 0; +static const size_t POKE32_CMD = (1 << 8); +static const size_t PEEK32_CMD = 0; static const double ACK_TIMEOUT = 0.5; -static const double MASSIVE_TIMEOUT = 10.0; //for when we wait on a timed command +static const double MASSIVE_TIMEOUT = 10.0; // for when we wait on a timed command static const uint32_t MAX_SEQS_OUT = 63; #define SPI_DIV SR_SPI_CORE + 0 @@ -32,43 +32,44 @@ static const uint32_t MAX_SEQS_OUT = 63; // spi clock rate = master_clock/(div+1)/2 (10MHz in this case) #define SPI_DIVIDER 4 -class usrp2_fifo_ctrl_impl : public usrp2_fifo_ctrl{ +class usrp2_fifo_ctrl_impl : public usrp2_fifo_ctrl +{ public: - - usrp2_fifo_ctrl_impl(zero_copy_if::sptr xport): - _xport(xport), - _seq_out(0), - _seq_ack(0), - _timeout(ACK_TIMEOUT) + usrp2_fifo_ctrl_impl(zero_copy_if::sptr xport) + : _xport(xport), _seq_out(0), _seq_ack(0), _timeout(ACK_TIMEOUT) { - while (_xport->get_recv_buff(0.0)){} //flush + while (_xport->get_recv_buff(0.0)) { + } // flush this->set_time(uhd::time_spec_t(0.0)); - this->set_tick_rate(1.0); //something possible but bogus + this->set_tick_rate(1.0); // something possible but bogus this->init_spi(); } - ~usrp2_fifo_ctrl_impl(void){ - _timeout = ACK_TIMEOUT; //reset timeout to something small + ~usrp2_fifo_ctrl_impl(void) + { + _timeout = ACK_TIMEOUT; // reset timeout to something small UHD_SAFE_CALL( - this->peek32(0); //dummy peek with the purpose of ack'ing all packets + this->peek32(0); // dummy peek with the purpose of ack'ing all packets ) } /******************************************************************* * Peek and poke 32 bit implementation ******************************************************************/ - void poke32(const wb_addr_type addr, const uint32_t data){ + void poke32(const wb_addr_type addr, const uint32_t data) + { boost::mutex::scoped_lock lock(_mutex); - this->send_pkt((addr - SETTING_REGS_BASE)/4, data, POKE32_CMD); + this->send_pkt((addr - SETTING_REGS_BASE) / 4, data, POKE32_CMD); - this->wait_for_ack(_seq_out-MAX_SEQS_OUT); + this->wait_for_ack(_seq_out - MAX_SEQS_OUT); } - uint32_t peek32(const wb_addr_type addr){ + uint32_t peek32(const wb_addr_type addr) + { boost::mutex::scoped_lock lock(_mutex); - this->send_pkt((addr - READBACK_BASE)/4, 0, PEEK32_CMD); + this->send_pkt((addr - READBACK_BASE) / 4, 0, PEEK32_CMD); return this->wait_for_ack(_seq_out); } @@ -76,58 +77,62 @@ public: /******************************************************************* * Peek and poke 16 bit not implemented ******************************************************************/ - void poke16(const wb_addr_type, const uint16_t){ + void poke16(const wb_addr_type, const uint16_t) + { throw uhd::not_implemented_error("poke16 not implemented in fifo ctrl module"); } - uint16_t peek16(const wb_addr_type){ + uint16_t peek16(const wb_addr_type) + { throw uhd::not_implemented_error("peek16 not implemented in fifo ctrl module"); } /******************************************************************* * FIFO controlled SPI implementation ******************************************************************/ - void init_spi(void){ + void init_spi(void) + { boost::mutex::scoped_lock lock(_mutex); this->send_pkt(SPI_DIV, SPI_DIVIDER, POKE32_CMD); - this->wait_for_ack(_seq_out-MAX_SEQS_OUT); + this->wait_for_ack(_seq_out - MAX_SEQS_OUT); _ctrl_word_cache = 0; // force update first time around } - uint32_t transact_spi( - int which_slave, - const spi_config_t &config, + uint32_t transact_spi(int which_slave, + const spi_config_t& config, uint32_t data, size_t num_bits, - bool readback - ){ + bool readback) + { boost::mutex::scoped_lock lock(_mutex); - //load control word + // load control word uint32_t ctrl_word = 0; ctrl_word |= ((which_slave & 0xffffff) << 0); ctrl_word |= ((num_bits & 0x3ff) << 24); - if (config.mosi_edge == spi_config_t::EDGE_FALL) ctrl_word |= (1 << 31); - if (config.miso_edge == spi_config_t::EDGE_RISE) ctrl_word |= (1 << 30); + if (config.mosi_edge == spi_config_t::EDGE_FALL) + ctrl_word |= (1 << 31); + if (config.miso_edge == spi_config_t::EDGE_RISE) + ctrl_word |= (1 << 30); - //load data word (must be in upper bits) + // load data word (must be in upper bits) const uint32_t data_out = data << (32 - num_bits); - //conditionally send control word - if (_ctrl_word_cache != ctrl_word){ + // conditionally send control word + if (_ctrl_word_cache != ctrl_word) { this->send_pkt(SPI_CTRL, ctrl_word, POKE32_CMD); - this->wait_for_ack(_seq_out-MAX_SEQS_OUT); + this->wait_for_ack(_seq_out - MAX_SEQS_OUT); _ctrl_word_cache = ctrl_word; } - //send data word + // send data word this->send_pkt(SPI_DATA, data_out, POKE32_CMD); - this->wait_for_ack(_seq_out-MAX_SEQS_OUT); + this->wait_for_ack(_seq_out - MAX_SEQS_OUT); - //conditional readback - if (readback){ + // conditional readback + if (readback) { this->send_pkt(SPI_READBACK, 0, PEEK32_CMD); return this->wait_for_ack(_seq_out); } @@ -138,11 +143,13 @@ public: /******************************************************************* * Update methods for time ******************************************************************/ - void set_time(const uhd::time_spec_t &time){ + void set_time(const uhd::time_spec_t& time) + { boost::mutex::scoped_lock lock(_mutex); - _time = time; + _time = time; _use_time = _time != uhd::time_spec_t(0.0); - if (_use_time) _timeout = MASSIVE_TIMEOUT; //permanently sets larger timeout + if (_use_time) + _timeout = MASSIVE_TIMEOUT; // permanently sets larger timeout } uhd::time_spec_t get_time() @@ -151,72 +158,75 @@ public: return _time; } - void set_tick_rate(const double rate){ + void set_tick_rate(const double rate) + { boost::mutex::scoped_lock lock(_mutex); _tick_rate = rate; } private: - /******************************************************************* * Primary control and interaction private methods ******************************************************************/ - UHD_INLINE void send_pkt(wb_addr_type addr, uint32_t data, int cmd){ + UHD_INLINE void send_pkt(wb_addr_type addr, uint32_t data, int cmd) + { managed_send_buffer::sptr buff = _xport->get_send_buff(0.0); - if (not buff){ + if (not buff) { throw uhd::runtime_error("fifo ctrl timed out getting a send buffer"); } - uint32_t *trans = buff->cast<uint32_t *>(); - trans[0] = htonl(++_seq_out); - uint32_t *pkt = trans + 1; + uint32_t* trans = buff->cast<uint32_t*>(); + trans[0] = htonl(++_seq_out); + uint32_t* pkt = trans + 1; - //load packet info + // load packet info vrt::if_packet_info_t packet_info; - packet_info.packet_type = vrt::if_packet_info_t::PACKET_TYPE_CONTEXT; + packet_info.packet_type = vrt::if_packet_info_t::PACKET_TYPE_CONTEXT; packet_info.num_payload_words32 = 2; - packet_info.num_payload_bytes = packet_info.num_payload_words32*sizeof(uint32_t); + packet_info.num_payload_bytes = + packet_info.num_payload_words32 * sizeof(uint32_t); packet_info.packet_count = _seq_out; - packet_info.tsf = _time.to_ticks(_tick_rate); - packet_info.sob = false; - packet_info.eob = false; - packet_info.has_sid = false; - packet_info.has_cid = false; - packet_info.has_tsi = false; - packet_info.has_tsf = _use_time; - packet_info.has_tlr = false; - - //load header + packet_info.tsf = _time.to_ticks(_tick_rate); + packet_info.sob = false; + packet_info.eob = false; + packet_info.has_sid = false; + packet_info.has_cid = false; + packet_info.has_tsi = false; + packet_info.has_tsf = _use_time; + packet_info.has_tlr = false; + + // load header vrt::if_hdr_pack_be(pkt, packet_info); - //load payload - const uint32_t ctrl_word = (addr & 0xff) | cmd | (_seq_out << 16); - pkt[packet_info.num_header_words32+0] = htonl(ctrl_word); - pkt[packet_info.num_header_words32+1] = htonl(data); + // load payload + const uint32_t ctrl_word = (addr & 0xff) | cmd | (_seq_out << 16); + pkt[packet_info.num_header_words32 + 0] = htonl(ctrl_word); + pkt[packet_info.num_header_words32 + 1] = htonl(data); - //send the buffer over the interface - buff->commit(sizeof(uint32_t)*(packet_info.num_packet_words32+1)); + // send the buffer over the interface + buff->commit(sizeof(uint32_t) * (packet_info.num_packet_words32 + 1)); } - UHD_INLINE bool wraparound_lt16(const int16_t i0, const int16_t i1){ - if (((i0 ^ i1) & 0x8000) == 0) //same sign bits + UHD_INLINE bool wraparound_lt16(const int16_t i0, const int16_t i1) + { + if (((i0 ^ i1) & 0x8000) == 0) // same sign bits return uint16_t(i0) < uint16_t(i1); return int16_t(i1 - i0) > 0; } - UHD_INLINE uint32_t wait_for_ack(const uint16_t seq_to_ack){ - - while (wraparound_lt16(_seq_ack, seq_to_ack)){ + UHD_INLINE uint32_t wait_for_ack(const uint16_t seq_to_ack) + { + while (wraparound_lt16(_seq_ack, seq_to_ack)) { managed_recv_buffer::sptr buff = _xport->get_recv_buff(_timeout); - if (not buff){ + if (not buff) { throw uhd::runtime_error("fifo ctrl timed out looking for acks"); } - const uint32_t *pkt = buff->cast<const uint32_t *>(); + const uint32_t* pkt = buff->cast<const uint32_t*>(); vrt::if_packet_info_t packet_info; - packet_info.num_packet_words32 = buff->size()/sizeof(uint32_t); + packet_info.num_packet_words32 = buff->size() / sizeof(uint32_t); vrt::if_hdr_unpack_be(pkt, packet_info); - _seq_ack = ntohl(pkt[packet_info.num_header_words32+0]) >> 16; - if (_seq_ack == seq_to_ack){ - return ntohl(pkt[packet_info.num_header_words32+1]); + _seq_ack = ntohl(pkt[packet_info.num_header_words32 + 0]) >> 16; + if (_seq_ack == seq_to_ack) { + return ntohl(pkt[packet_info.num_header_words32 + 1]); } } @@ -235,6 +245,7 @@ private: }; -usrp2_fifo_ctrl::sptr usrp2_fifo_ctrl::make(zero_copy_if::sptr xport){ +usrp2_fifo_ctrl::sptr usrp2_fifo_ctrl::make(zero_copy_if::sptr xport) +{ return sptr(new usrp2_fifo_ctrl_impl(xport)); } diff --git a/host/lib/usrp/usrp2/usrp2_fifo_ctrl.hpp b/host/lib/usrp/usrp2/usrp2_fifo_ctrl.hpp index cbb243a79..5f8cdb264 100644 --- a/host/lib/usrp/usrp2/usrp2_fifo_ctrl.hpp +++ b/host/lib/usrp/usrp2/usrp2_fifo_ctrl.hpp @@ -8,12 +8,12 @@ #ifndef INCLUDED_USRP2_FIFO_CTRL_HPP #define INCLUDED_USRP2_FIFO_CTRL_HPP -#include <uhd/types/time_spec.hpp> -#include <uhd/types/serial.hpp> #include <uhd/transport/zero_copy.hpp> -#include <memory> -#include <boost/utility.hpp> +#include <uhd/types/serial.hpp> +#include <uhd/types/time_spec.hpp> #include <uhd/types/wb_iface.hpp> +#include <boost/utility.hpp> +#include <memory> #include <string> /*! diff --git a/host/lib/usrp/usrp2/usrp2_iface.cpp b/host/lib/usrp/usrp2/usrp2_iface.cpp index 962ead769..029d2b30a 100644 --- a/host/lib/usrp/usrp2/usrp2_iface.cpp +++ b/host/lib/usrp/usrp2/usrp2_iface.cpp @@ -36,13 +36,12 @@ namespace fs = boost::filesystem; static const double CTRL_RECV_TIMEOUT = 1.0; static const size_t CTRL_RECV_RETRIES = 3; -//custom timeout error for retry logic to catch/retry +// custom timeout error for retry logic to catch/retry struct timeout_error : uhd::runtime_error { - timeout_error(const std::string &what): - uhd::runtime_error(what) + timeout_error(const std::string& what) : uhd::runtime_error(what) { - //NOP + // NOP } }; @@ -51,24 +50,25 @@ static const 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 uint32_t MIN_PROTO_COMPAT_REG = 10; -//static const uint32_t MIN_PROTO_COMPAT_UART = 7; +// static const uint32_t MIN_PROTO_COMPAT_UART = 7; -class usrp2_iface_impl : public usrp2_iface{ +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), - _protocol_compat(0) //initialized below... + /*********************************************************************** + * Structors + **********************************************************************/ + 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 + // 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 = usrp2_ctrl_data_t(); - ctrl_data.id = htonl(USRP2_CTRL_ID_WAZZUP_BRO); - ctrl_data = ctrl_send_and_recv(ctrl_data, 0, ~0); + 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); @@ -76,71 +76,82 @@ public: mb_eeprom = usrp2_impl::get_mb_eeprom(*this); } - ~usrp2_iface_impl(void){UHD_SAFE_CALL( - this->lock_device(false); - )} + ~usrp2_iface_impl(void) + { + UHD_SAFE_CALL(this->lock_device(false);) + } -/*********************************************************************** - * Device locking - **********************************************************************/ + /*********************************************************************** + * Device locking + **********************************************************************/ - void lock_device(bool lock){ - if (lock){ + void lock_device(bool lock) + { + if (lock) { this->pokefw(U2_FW_REG_LOCK_GPID, get_process_hash()); _lock_task = task::make(std::bind(&usrp2_iface_impl::lock_task, this)); - } - else{ - _lock_task.reset(); //shutdown the task - this->pokefw(U2_FW_REG_LOCK_TIME, 0); //unlock + } else { + _lock_task.reset(); // shutdown the task + this->pokefw(U2_FW_REG_LOCK_TIME, 0); // unlock } } - bool is_device_locked(void){ - //never assume lock with fpga image mismatch - if ((this->peek32(U2_REG_COMPAT_NUM_RB) >> 16) != USRP2_FPGA_COMPAT_NUM) return false; + bool is_device_locked(void) + { + // never assume lock with fpga image mismatch + if ((this->peek32(U2_REG_COMPAT_NUM_RB) >> 16) != USRP2_FPGA_COMPAT_NUM) + return false; uint32_t lock_time = this->peekfw(U2_FW_REG_LOCK_TIME); uint32_t lock_gpid = this->peekfw(U2_FW_REG_LOCK_GPID); - //may not be the right tick rate, but this is ok for locking purposes - const uint32_t lock_timeout_time = uint32_t(3*100e6); + // may not be the right tick rate, but this is ok for locking purposes + const uint32_t lock_timeout_time = uint32_t(3 * 100e6); - //if the difference is larger, assume not locked anymore - if ((lock_time & 1) == 0) return false; //bit0 says unlocked + // if the difference is larger, assume not locked anymore + if ((lock_time & 1) == 0) + return false; // bit0 says unlocked const uint32_t time_diff = this->get_curr_time() - lock_time; - if (time_diff >= lock_timeout_time) return false; + if (time_diff >= lock_timeout_time) + return false; - //otherwise only lock if the device hash is different that ours + // otherwise only lock if the device hash is different that ours return lock_gpid != get_process_hash(); } - void lock_task(void){ - //re-lock in task + void lock_task(void) + { + // re-lock in task this->pokefw(U2_FW_REG_LOCK_TIME, this->get_curr_time()); - //sleep for a bit + // sleep for a bit std::this_thread::sleep_for(std::chrono::milliseconds(1500)); } - uint32_t get_curr_time(void){ - return this->peek32(U2_REG_TIME64_LO_RB_IMM) | 1; //bit 1 says locked + uint32_t get_curr_time(void) + { + return this->peek32(U2_REG_TIME64_LO_RB_IMM) | 1; // bit 1 says locked } -/*********************************************************************** - * Peek and Poke - **********************************************************************/ - void poke32(const wb_addr_type addr, const uint32_t data){ + /*********************************************************************** + * Peek and Poke + **********************************************************************/ + void poke32(const wb_addr_type addr, const uint32_t data) + { this->get_reg<uint32_t, USRP2_REG_ACTION_FPGA_POKE32>(addr, data); } - uint32_t peek32(const wb_addr_type addr){ + uint32_t peek32(const wb_addr_type addr) + { return this->get_reg<uint32_t, USRP2_REG_ACTION_FPGA_PEEK32>(addr); } - void poke16(const wb_addr_type addr, const uint16_t data){ + void poke16(const wb_addr_type addr, const uint16_t data) + { this->get_reg<uint16_t, USRP2_REG_ACTION_FPGA_POKE16>(addr, data); } - uint16_t peek16(const wb_addr_type addr){ + uint16_t peek16(const wb_addr_type addr) + { return this->get_reg<uint16_t, USRP2_REG_ACTION_FPGA_PEEK16>(addr); } @@ -155,236 +166,294 @@ public: } template <class T, usrp2_reg_action_t action> - T get_reg(wb_addr_type addr, T data = 0){ - //setup the out data - usrp2_ctrl_data_t out_data = usrp2_ctrl_data_t(); - out_data.id = htonl(USRP2_CTRL_ID_GET_THIS_REGISTER_FOR_ME_BRO); - out_data.data.reg_args.addr = htonl(addr); - out_data.data.reg_args.data = htonl(uint32_t(data)); + T get_reg(wb_addr_type addr, T data = 0) + { + // setup the out data + usrp2_ctrl_data_t out_data = usrp2_ctrl_data_t(); + out_data.id = htonl(USRP2_CTRL_ID_GET_THIS_REGISTER_FOR_ME_BRO); + out_data.data.reg_args.addr = htonl(addr); + out_data.data.reg_args.data = htonl(uint32_t(data)); out_data.data.reg_args.action = action; - //send and recv - usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data, MIN_PROTO_COMPAT_REG); + // send and recv + 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_GOT_REGISTER_SO_BAD_DUDE); return T(ntohl(in_data.data.reg_args.data)); } -/*********************************************************************** - * SPI - **********************************************************************/ - uint32_t transact_spi( - int which_slave, - const spi_config_t &config, + /*********************************************************************** + * SPI + **********************************************************************/ + uint32_t transact_spi(int which_slave, + const spi_config_t& config, uint32_t data, size_t num_bits, - bool readback - ){ - static const uhd::dict<spi_config_t::edge_t, int> spi_edge_to_otw = boost::assign::map_list_of - (spi_config_t::EDGE_RISE, USRP2_CLK_EDGE_RISE) - (spi_config_t::EDGE_FALL, USRP2_CLK_EDGE_FALL) - ; - - //setup the out data - usrp2_ctrl_data_t out_data = usrp2_ctrl_data_t(); - out_data.id = htonl(USRP2_CTRL_ID_TRANSACT_ME_SOME_SPI_BRO); - out_data.data.spi_args.dev = htonl(which_slave); + bool readback) + { + static const uhd::dict<spi_config_t::edge_t, int> spi_edge_to_otw = + boost::assign::map_list_of(spi_config_t::EDGE_RISE, USRP2_CLK_EDGE_RISE)( + spi_config_t::EDGE_FALL, USRP2_CLK_EDGE_FALL); + + // setup the out data + usrp2_ctrl_data_t out_data = usrp2_ctrl_data_t(); + out_data.id = htonl(USRP2_CTRL_ID_TRANSACT_ME_SOME_SPI_BRO); + out_data.data.spi_args.dev = htonl(which_slave); out_data.data.spi_args.miso_edge = spi_edge_to_otw[config.miso_edge]; out_data.data.spi_args.mosi_edge = spi_edge_to_otw[config.mosi_edge]; - out_data.data.spi_args.readback = (readback)? 1 : 0; - out_data.data.spi_args.num_bits = num_bits; - out_data.data.spi_args.data = htonl(data); + out_data.data.spi_args.readback = (readback) ? 1 : 0; + out_data.data.spi_args.num_bits = num_bits; + out_data.data.spi_args.data = htonl(data); - //send and recv - usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data, MIN_PROTO_COMPAT_SPI); + // send and recv + 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); } -/*********************************************************************** - * I2C - **********************************************************************/ - void write_i2c(uint16_t addr, const byte_vector_t &buf){ - //setup the out data - usrp2_ctrl_data_t out_data = usrp2_ctrl_data_t(); - out_data.id = htonl(USRP2_CTRL_ID_WRITE_THESE_I2C_VALUES_BRO); - out_data.data.i2c_args.addr = uint8_t(addr); + /*********************************************************************** + * I2C + **********************************************************************/ + void write_i2c(uint16_t addr, const byte_vector_t& buf) + { + // setup the out data + usrp2_ctrl_data_t out_data = usrp2_ctrl_data_t(); + out_data.id = htonl(USRP2_CTRL_ID_WRITE_THESE_I2C_VALUES_BRO); + out_data.data.i2c_args.addr = uint8_t(addr); out_data.data.i2c_args.bytes = buf.size(); - //limitation of i2c transaction size + // limitation of i2c transaction size UHD_ASSERT_THROW(buf.size() <= sizeof(out_data.data.i2c_args.data)); - //copy in the data + // copy in the data 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, MIN_PROTO_COMPAT_I2C); + // send and recv + 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); } - byte_vector_t read_i2c(uint16_t addr, size_t num_bytes){ - //setup the out data - usrp2_ctrl_data_t out_data = usrp2_ctrl_data_t(); - out_data.id = htonl(USRP2_CTRL_ID_DO_AN_I2C_READ_FOR_ME_BRO); - out_data.data.i2c_args.addr = uint8_t(addr); + byte_vector_t read_i2c(uint16_t addr, size_t num_bytes) + { + // setup the out data + usrp2_ctrl_data_t out_data = usrp2_ctrl_data_t(); + out_data.id = htonl(USRP2_CTRL_ID_DO_AN_I2C_READ_FOR_ME_BRO); + out_data.data.i2c_args.addr = uint8_t(addr); out_data.data.i2c_args.bytes = num_bytes; - //limitation of i2c transaction size + // limitation of i2c transaction size 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, MIN_PROTO_COMPAT_I2C); + // send and recv + 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.bytes == num_bytes); - //copy out the data + // copy out the data byte_vector_t result(num_bytes); - std::copy(in_data.data.i2c_args.data, in_data.data.i2c_args.data + num_bytes, result.begin()); + std::copy(in_data.data.i2c_args.data, + in_data.data.i2c_args.data + num_bytes, + result.begin()); return result; } -/*********************************************************************** - * Send/Recv over control - **********************************************************************/ - usrp2_ctrl_data_t ctrl_send_and_recv( - const usrp2_ctrl_data_t &out_data, + /*********************************************************************** + * Send/Recv over control + **********************************************************************/ + usrp2_ctrl_data_t ctrl_send_and_recv(const usrp2_ctrl_data_t& out_data, uint32_t lo = USRP2_FW_COMPAT_NUM, - uint32_t hi = USRP2_FW_COMPAT_NUM - ){ + uint32_t hi = USRP2_FW_COMPAT_NUM) + { boost::mutex::scoped_lock lock(_ctrl_mutex); - for (size_t i = 0; i < CTRL_RECV_RETRIES; i++){ - try{ - return ctrl_send_and_recv_internal(out_data, lo, hi, CTRL_RECV_TIMEOUT/CTRL_RECV_RETRIES); - } - catch(const timeout_error &e){ + for (size_t i = 0; i < CTRL_RECV_RETRIES; i++) { + try { + return ctrl_send_and_recv_internal( + out_data, lo, hi, CTRL_RECV_TIMEOUT / CTRL_RECV_RETRIES); + } catch (const timeout_error& e) { UHD_LOGGER_ERROR("USRP2") - << "Control packet attempt " << i - << ", sequence number " << _ctrl_seq_num - << ":\n" << e.what() ; + << "Control packet attempt " << i << ", sequence number " + << _ctrl_seq_num << ":\n" + << e.what(); } } throw uhd::runtime_error("link dead: timeout waiting for control packet ACK"); } usrp2_ctrl_data_t ctrl_send_and_recv_internal( - const usrp2_ctrl_data_t &out_data, - uint32_t lo, uint32_t hi, - const double timeout - ){ - //fill in the seq number and send + const usrp2_ctrl_data_t& out_data, uint32_t lo, uint32_t hi, const double timeout) + { + // fill in the seq number and send usrp2_ctrl_data_t out_copy = out_data; - out_copy.proto_ver = htonl(_protocol_compat); - out_copy.seq = htonl(++_ctrl_seq_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))); - //loop until we get the packet or timeout - uint8_t usrp2_ctrl_data_in_mem[udp_simple::mtu]; //allocate max bytes for recv - 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), timeout); + // loop until we get the packet or timeout + uint8_t usrp2_ctrl_data_in_mem[udp_simple::mtu]; // allocate max bytes for recv + 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), timeout); uint32_t compat = ntohl(ctrl_data_in->proto_ver); - if(len >= sizeof(uint32_t) and (hi < compat or lo > compat)){ - 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 protocol compatibility number %s, but got %d:\n" - "The firmware build is not compatible with the host code build.\n" - "%s\n" - ) % ((lo == hi)? (boost::format("%d") % hi) : (boost::format("[%d to %d]") % lo % hi)) - % compat % this->images_warn_help_message())); + if (len >= sizeof(uint32_t) and (hi < compat or lo > compat)) { + 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 protocol compatibility number %s, but got %d:\n" + "The firmware build is not compatible with the host code build.\n" + "%s\n") + % ((lo == hi) ? (boost::format("%d") % hi) + : (boost::format("[%d to %d]") % lo % hi)) + % compat % this->images_warn_help_message())); } - if (len >= sizeof(usrp2_ctrl_data_t) and ntohl(ctrl_data_in->seq) == _ctrl_seq_num){ + if (len >= sizeof(usrp2_ctrl_data_t) + and ntohl(ctrl_data_in->seq) == _ctrl_seq_num) { return *ctrl_data_in; } - if (len == 0) break; //timeout - //didnt get seq or bad packet, continue looking... + if (len == 0) + break; // timeout + // didnt get seq or bad packet, continue looking... } throw timeout_error("no control response, possible packet loss"); } - rev_type get_rev(void){ + rev_type get_rev(void) + { std::string hw = mb_eeprom["hardware"]; - if (hw.empty()) return USRP_NXXX; - switch (boost::lexical_cast<uint16_t>(hw)){ - case 0x0300: - case 0x0301: return USRP2_REV3; - case 0x0400: return USRP2_REV4; - case 0x0A00: return USRP_N200; - case 0x0A01: return USRP_N210; - case 0x0A10: return USRP_N200_R4; - case 0x0A11: return USRP_N210_R4; + if (hw.empty()) + return USRP_NXXX; + switch (boost::lexical_cast<uint16_t>(hw)) { + case 0x0300: + case 0x0301: + return USRP2_REV3; + case 0x0400: + return USRP2_REV4; + case 0x0A00: + return USRP_N200; + case 0x0A01: + return USRP_N210; + case 0x0A10: + return USRP_N200_R4; + case 0x0A11: + return USRP_N210_R4; } - return USRP_NXXX; //unknown type + return USRP_NXXX; // unknown type } - const std::string get_cname(void){ - switch(this->get_rev()){ - case USRP2_REV3: return "USRP2 r3"; - case USRP2_REV4: return "USRP2 r4"; - case USRP_N200: return "N200"; - case USRP_N210: return "N210"; - case USRP_N200_R4: return "N200r4"; - case USRP_N210_R4: return "N210r4"; - case USRP_NXXX: return "N???"; + const std::string get_cname(void) + { + switch (this->get_rev()) { + case USRP2_REV3: + return "USRP2 r3"; + case USRP2_REV4: + return "USRP2 r4"; + case USRP_N200: + return "N200"; + case USRP_N210: + return "N210"; + case USRP_N200_R4: + return "N200r4"; + case USRP_N210_R4: + return "N210r4"; + case USRP_NXXX: + return "N???"; } UHD_THROW_INVALID_CODE_PATH(); } - const std::string get_fw_version_string(void){ - uint32_t minor = this->get_reg<uint32_t, USRP2_REG_ACTION_FW_PEEK32>(U2_FW_REG_VER_MINOR); + const std::string get_fw_version_string(void) + { + uint32_t minor = + this->get_reg<uint32_t, USRP2_REG_ACTION_FW_PEEK32>(U2_FW_REG_VER_MINOR); return str(boost::format("%u.%u") % _protocol_compat % minor); } - std::string images_warn_help_message(void){ - //determine the images names + std::string images_warn_help_message(void) + { + // determine the images names std::string fw_image, fpga_image; - switch(this->get_rev()){ - case USRP2_REV3: fpga_image = "usrp2_fpga.bin"; fw_image = "usrp2_fw.bin"; break; - case USRP2_REV4: fpga_image = "usrp2_fpga.bin"; fw_image = "usrp2_fw.bin"; break; - case USRP_N200: fpga_image = "usrp_n200_r2_fpga.bin"; fw_image = "usrp_n200_fw.bin"; break; - case USRP_N210: fpga_image = "usrp_n210_r2_fpga.bin"; fw_image = "usrp_n210_fw.bin"; break; - case USRP_N200_R4: fpga_image = "usrp_n200_r4_fpga.bin"; fw_image = "usrp_n200_fw.bin"; break; - case USRP_N210_R4: fpga_image = "usrp_n210_r4_fpga.bin"; fw_image = "usrp_n210_fw.bin"; break; - default: break; + switch (this->get_rev()) { + case USRP2_REV3: + fpga_image = "usrp2_fpga.bin"; + fw_image = "usrp2_fw.bin"; + break; + case USRP2_REV4: + fpga_image = "usrp2_fpga.bin"; + fw_image = "usrp2_fw.bin"; + break; + case USRP_N200: + fpga_image = "usrp_n200_r2_fpga.bin"; + fw_image = "usrp_n200_fw.bin"; + break; + case USRP_N210: + fpga_image = "usrp_n210_r2_fpga.bin"; + fw_image = "usrp_n210_fw.bin"; + break; + case USRP_N200_R4: + fpga_image = "usrp_n200_r4_fpga.bin"; + fw_image = "usrp_n200_fw.bin"; + break; + case USRP_N210_R4: + fpga_image = "usrp_n210_r4_fpga.bin"; + fw_image = "usrp_n210_fw.bin"; + break; + default: + break; } - if (fw_image.empty() or fpga_image.empty()) return ""; + if (fw_image.empty() or fpga_image.empty()) + return ""; - //does your platform use sudo? + // does your platform use sudo? std::string sudo; - #if defined(UHD_PLATFORM_LINUX) || defined(UHD_PLATFORM_MACOS) - sudo = "sudo "; - #endif +#if defined(UHD_PLATFORM_LINUX) || defined(UHD_PLATFORM_MACOS) + sudo = "sudo "; +#endif - //look up the real FS path to the images + // look up the real FS path to the images std::string fw_image_path, fpga_image_path; - try{ - fw_image_path = uhd::find_image_path(fw_image); + try { + fw_image_path = uhd::find_image_path(fw_image); fpga_image_path = uhd::find_image_path(fpga_image); - } - catch(const std::exception &){ - return str(boost::format("Could not find %s and %s in your images path!\n%s") % fw_image % fpga_image % print_utility_error("uhd_images_downloader.py")); + } catch (const std::exception&) { + return str(boost::format("Could not find %s and %s in your images path!\n%s") + % fw_image % fpga_image + % print_utility_error("uhd_images_downloader.py")); } - //escape char for multi-line cmd + newline + indent? - #ifdef UHD_PLATFORM_WIN32 - const std::string ml = "^\n "; - #else - const std::string ml = "\\\n "; - #endif +// escape char for multi-line cmd + newline + indent? +#ifdef UHD_PLATFORM_WIN32 + const std::string ml = "^\n "; +#else + const std::string ml = "\\\n "; +#endif - //create the burner commands - if (this->get_rev() == USRP2_REV3 or this->get_rev() == USRP2_REV4){ + // create the burner commands + if (this->get_rev() == USRP2_REV3 or this->get_rev() == USRP2_REV4) { const std::string card_burner = uhd::find_utility("usrp2_card_burner_gui.py"); - const std::string card_burner_cmd = str(boost::format(" %s\"%s\" %s--fpga=\"%s\" %s--fw=\"%s\"") % sudo % card_burner % ml % fpga_image_path % ml % fw_image_path); - return str(boost::format("%s\n%s") % print_utility_error("uhd_images_downloader.py") % card_burner_cmd); - } - else{ + const std::string card_burner_cmd = + str(boost::format(" %s\"%s\" %s--fpga=\"%s\" %s--fw=\"%s\"") % sudo + % card_burner % ml % fpga_image_path % ml % fw_image_path); + return str(boost::format("%s\n%s") + % print_utility_error("uhd_images_downloader.py") + % card_burner_cmd); + } else { const std::string addr = _ctrl_transport->get_recv_addr(); - const std::string image_loader_path = (fs::path(uhd::get_pkg_path()) / "bin" / "uhd_image_loader").string(); - const std::string image_loader_cmd = str(boost::format(" \"%s\" %s--args=\"type=usrp2,addr=%s\"") % image_loader_path % ml % addr); - return str(boost::format("%s\n%s") % print_utility_error("uhd_images_downloader.py") % image_loader_cmd); + const std::string image_loader_path = + (fs::path(uhd::get_pkg_path()) / "bin" / "uhd_image_loader").string(); + const std::string image_loader_cmd = + str(boost::format(" \"%s\" %s--args=\"type=usrp2,addr=%s\"") + % image_loader_path % ml % addr); + return str(boost::format("%s\n%s") + % print_utility_error("uhd_images_downloader.py") + % image_loader_cmd); } } @@ -399,22 +468,22 @@ public: } private: - //this lovely lady makes it all possible + // this lovely lady makes it all possible udp_simple::sptr _ctrl_transport; - //used in send/recv + // used in send/recv boost::mutex _ctrl_mutex; uint32_t _ctrl_seq_num; uint32_t _protocol_compat; - //lock thread stuff + // lock thread stuff task::sptr _lock_task; }; /*********************************************************************** * Public make function for usrp2 interface **********************************************************************/ -usrp2_iface::sptr usrp2_iface::make(udp_simple::sptr ctrl_transport){ +usrp2_iface::sptr usrp2_iface::make(udp_simple::sptr ctrl_transport) +{ return usrp2_iface::sptr(new usrp2_iface_impl(ctrl_transport)); } - diff --git a/host/lib/usrp/usrp2/usrp2_iface.hpp b/host/lib/usrp/usrp2/usrp2_iface.hpp index b602dab53..8d1700974 100644 --- a/host/lib/usrp/usrp2/usrp2_iface.hpp +++ b/host/lib/usrp/usrp2/usrp2_iface.hpp @@ -8,14 +8,14 @@ #ifndef INCLUDED_USRP2_IFACE_HPP #define INCLUDED_USRP2_IFACE_HPP +#include "usrp2_regs.hpp" #include <uhd/transport/udp_simple.hpp> #include <uhd/types/serial.hpp> +#include <uhd/types/wb_iface.hpp> #include <uhd/usrp/mboard_eeprom.hpp> -#include <memory> #include <boost/utility.hpp> #include <functional> -#include "usrp2_regs.hpp" -#include <uhd/types/wb_iface.hpp> +#include <memory> #include <string> /*! @@ -23,7 +23,9 @@ * Provides a set of functions to implementation layer. * Including spi, peek, poke, control... */ -class usrp2_iface : public uhd::timed_wb_iface, public uhd::spi_iface, public uhd::i2c_iface +class usrp2_iface : public uhd::timed_wb_iface, + public uhd::spi_iface, + public uhd::i2c_iface { public: typedef std::shared_ptr<usrp2_iface> sptr; @@ -42,13 +44,13 @@ public: //! The list of possible revision types enum rev_type { - USRP2_REV3 = 3, - USRP2_REV4 = 4, - USRP_N200 = 200, + USRP2_REV3 = 3, + USRP2_REV4 = 4, + USRP_N200 = 200, USRP_N200_R4 = 201, - USRP_N210 = 210, + USRP_N210 = 210, USRP_N210_R4 = 211, - USRP_NXXX = 0 + USRP_NXXX = 0 }; //! Get the revision type for this device @@ -69,7 +71,7 @@ public: //! Construct a helpful warning message for images virtual std::string images_warn_help_message(void) = 0; - //motherboard eeprom map structure + // motherboard eeprom map structure uhd::usrp::mboard_eeprom_t mb_eeprom; }; diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index fd35f3a1d..6fed1521a 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -26,151 +26,155 @@ using namespace uhd::usrp; using namespace uhd::transport; namespace asio = boost::asio; -//A reasonable number of frames for send/recv and async/sync +// A reasonable number of frames for send/recv and async/sync static const size_t DEFAULT_NUM_FRAMES = 32; /*********************************************************************** * Discovery over the udp transport **********************************************************************/ -device_addrs_t usrp2_find(const device_addr_t &hint_){ - //handle the multi-device discovery +device_addrs_t usrp2_find(const device_addr_t& hint_) +{ + // handle the multi-device discovery device_addrs_t hints = separate_device_addr(hint_); - if (hints.size() > 1){ + if (hints.size() > 1) { device_addrs_t found_devices; std::string error_msg; - for(const device_addr_t &hint_i: hints){ + for (const device_addr_t& hint_i : hints) { device_addrs_t found_devices_i = usrp2_find(hint_i); - if (found_devices_i.size() != 1) error_msg += str(boost::format( - "Could not resolve device hint \"%s\" to a single device." - ) % hint_i.to_string()); - else found_devices.push_back(found_devices_i[0]); + if (found_devices_i.size() != 1) + error_msg += + str(boost::format( + "Could not resolve device hint \"%s\" to a single device.") + % hint_i.to_string()); + else + found_devices.push_back(found_devices_i[0]); } - if (found_devices.empty()) return device_addrs_t(); - if (not error_msg.empty()) throw uhd::value_error(error_msg); + if (found_devices.empty()) + return device_addrs_t(); + if (not error_msg.empty()) + throw uhd::value_error(error_msg); return device_addrs_t(1, combine_device_addrs(found_devices)); } - //initialize the hint for a single device case + // initialize the hint for a single device case UHD_ASSERT_THROW(hints.size() <= 1); - hints.resize(1); //in case it was empty + hints.resize(1); // in case it was empty device_addr_t hint = hints[0]; device_addrs_t usrp2_addrs; - //return an empty list of addresses when type is set to non-usrp2 - if (hint.has_key("type") and hint["type"] != "usrp2") return usrp2_addrs; + // return an empty list of addresses when type is set to non-usrp2 + if (hint.has_key("type") and hint["type"] != "usrp2") + return usrp2_addrs; - //Return an empty list of addresses when a resource is specified, - //since a resource is intended for a different, non-USB, device. - if (hint.has_key("resource")) return usrp2_addrs; + // Return an empty list of addresses when a resource is specified, + // since a resource is intended for a different, non-USB, device. + if (hint.has_key("resource")) + return usrp2_addrs; - //if no address was specified, send a broadcast on each interface - if (not hint.has_key("addr")){ - for(const if_addrs_t &if_addrs: get_if_addrs()){ - //avoid the loopback device - if (if_addrs.inet == asio::ip::address_v4::loopback().to_string()) continue; + // if no address was specified, send a broadcast on each interface + if (not hint.has_key("addr")) { + for (const if_addrs_t& if_addrs : get_if_addrs()) { + // avoid the loopback device + if (if_addrs.inet == asio::ip::address_v4::loopback().to_string()) + continue; - //create a new hint with this broadcast address + // create a new hint with this broadcast address device_addr_t new_hint = hint; - new_hint["addr"] = if_addrs.bcast; + new_hint["addr"] = if_addrs.bcast; - //call discover with the new hint and append results + // call discover with the new hint and append results device_addrs_t new_usrp2_addrs = usrp2_find(new_hint); - usrp2_addrs.insert(usrp2_addrs.begin(), - new_usrp2_addrs.begin(), new_usrp2_addrs.end() - ); + usrp2_addrs.insert( + usrp2_addrs.begin(), new_usrp2_addrs.begin(), new_usrp2_addrs.end()); } return usrp2_addrs; } - //Create a UDP transport to communicate: - //Some devices will cause a throw when opened for a broadcast address. - //We print and recover so the caller can loop through all bcast addrs. + // Create a UDP transport to communicate: + // Some devices will cause a throw when opened for a broadcast address. + // We print and recover so the caller can loop through all bcast addrs. udp_simple::sptr udp_transport; - try{ - udp_transport = udp_simple::make_broadcast(hint["addr"], BOOST_STRINGIZE(USRP2_UDP_CTRL_PORT)); - } - catch(const std::exception &e){ - UHD_LOGGER_ERROR("USRP2") << boost::format("Cannot open UDP transport on %s\n%s") % hint["addr"] % e.what() ; - return usrp2_addrs; //dont throw, but return empty address so caller can insert + try { + udp_transport = udp_simple::make_broadcast( + hint["addr"], BOOST_STRINGIZE(USRP2_UDP_CTRL_PORT)); + } catch (const std::exception& e) { + UHD_LOGGER_ERROR("USRP2") << boost::format("Cannot open UDP transport on %s\n%s") + % hint["addr"] % e.what(); + return usrp2_addrs; // dont throw, but return empty address so caller can insert } - //send a hello control packet + // send a hello control packet usrp2_ctrl_data_t ctrl_data_out = usrp2_ctrl_data_t(); - ctrl_data_out.proto_ver = uhd::htonx<uint32_t>(USRP2_FW_COMPAT_NUM); - ctrl_data_out.id = uhd::htonx<uint32_t>(USRP2_CTRL_ID_WAZZUP_BRO); - try - { + ctrl_data_out.proto_ver = uhd::htonx<uint32_t>(USRP2_FW_COMPAT_NUM); + ctrl_data_out.id = uhd::htonx<uint32_t>(USRP2_CTRL_ID_WAZZUP_BRO); + try { udp_transport->send(boost::asio::buffer(&ctrl_data_out, sizeof(ctrl_data_out))); - } - catch(const std::exception &ex) - { - UHD_LOGGER_ERROR("USRP2") << "USRP2 Network discovery error " << ex.what() ; - } - catch(...) - { - UHD_LOGGER_ERROR("USRP2") << "USRP2 Network discovery unknown error " ; + } catch (const std::exception& ex) { + UHD_LOGGER_ERROR("USRP2") << "USRP2 Network discovery error " << ex.what(); + } catch (...) { + UHD_LOGGER_ERROR("USRP2") << "USRP2 Network discovery unknown error "; } - //loop and recieve until the timeout - uint8_t usrp2_ctrl_data_in_mem[udp_simple::mtu]; //allocate max bytes for recv - const usrp2_ctrl_data_t *ctrl_data_in = reinterpret_cast<const usrp2_ctrl_data_t *>(usrp2_ctrl_data_in_mem); - while(true){ + // loop and recieve until the timeout + uint8_t usrp2_ctrl_data_in_mem[udp_simple::mtu]; // allocate max bytes for recv + 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 = udp_transport->recv(asio::buffer(usrp2_ctrl_data_in_mem)); - if (len > offsetof(usrp2_ctrl_data_t, data) and ntohl(ctrl_data_in->id) == USRP2_CTRL_ID_WAZZUP_DUDE){ - - //make a boost asio ipv4 with the raw addr in host byte order + if (len > offsetof(usrp2_ctrl_data_t, data) + and ntohl(ctrl_data_in->id) == USRP2_CTRL_ID_WAZZUP_DUDE) { + // make a boost asio ipv4 with the raw addr in host byte order device_addr_t new_addr; new_addr["type"] = "usrp2"; - //We used to get the address from the control packet. - //Now now uses the socket itself to yield the address. - //boost::asio::ip::address_v4 ip_addr(ntohl(ctrl_data_in->data.ip_addr)); - //new_addr["addr"] = ip_addr.to_string(); + // We used to get the address from the control packet. + // Now now uses the socket itself to yield the address. + // boost::asio::ip::address_v4 ip_addr(ntohl(ctrl_data_in->data.ip_addr)); + // new_addr["addr"] = ip_addr.to_string(); new_addr["addr"] = udp_transport->get_recv_addr(); - //Attempt a simple 2-way communication with a connected socket. - //Reason: Although the USRP will respond the broadcast above, - //we may not be able to communicate directly (non-broadcast). + // Attempt a simple 2-way communication with a connected socket. + // Reason: Although the USRP will respond the broadcast above, + // we may not be able to communicate directly (non-broadcast). udp_simple::sptr ctrl_xport = udp_simple::make_connected( - new_addr["addr"], BOOST_STRINGIZE(USRP2_UDP_CTRL_PORT) - ); + new_addr["addr"], BOOST_STRINGIZE(USRP2_UDP_CTRL_PORT)); ctrl_xport->send(boost::asio::buffer(&ctrl_data_out, sizeof(ctrl_data_out))); size_t len = ctrl_xport->recv(asio::buffer(usrp2_ctrl_data_in_mem)); - if (len > offsetof(usrp2_ctrl_data_t, data) and ntohl(ctrl_data_in->id) == USRP2_CTRL_ID_WAZZUP_DUDE){ - //found the device, open up for communication! - } - else{ - //otherwise we don't find it... + if (len > offsetof(usrp2_ctrl_data_t, data) + and ntohl(ctrl_data_in->id) == USRP2_CTRL_ID_WAZZUP_DUDE) { + // found the device, open up for communication! + } else { + // otherwise we don't find it... continue; } - //Attempt to read the name from the EEPROM and perform filtering. - //This operation can throw due to compatibility mismatch. - try{ + // Attempt to read the name from the EEPROM and perform filtering. + // This operation can throw due to compatibility mismatch. + try { usrp2_iface::sptr iface = usrp2_iface::make(ctrl_xport); - if (iface->is_device_locked()) continue; //ignore locked devices + if (iface->is_device_locked()) + continue; // ignore locked devices mboard_eeprom_t mb_eeprom = iface->mb_eeprom; - new_addr["name"] = mb_eeprom["name"]; - new_addr["serial"] = mb_eeprom["serial"]; - } - catch(const std::exception &){ - //set these values as empty string so the device may still be found - //and the filter's below can still operate on the discovered device - new_addr["name"] = ""; + new_addr["name"] = mb_eeprom["name"]; + new_addr["serial"] = mb_eeprom["serial"]; + } catch (const std::exception&) { + // set these values as empty string so the device may still be found + // and the filter's below can still operate on the discovered device + new_addr["name"] = ""; new_addr["serial"] = ""; } - //filter the discovered device below by matching optional keys - if ( - (not hint.has_key("name") or hint["name"] == new_addr["name"]) and - (not hint.has_key("serial") or hint["serial"] == new_addr["serial"]) - ){ + // filter the discovered device below by matching optional keys + if ((not hint.has_key("name") or hint["name"] == new_addr["name"]) + and (not hint.has_key("serial") + or hint["serial"] == new_addr["serial"])) { usrp2_addrs.push_back(new_addr); } - //dont break here, it will exit the while loop - //just continue on to the next loop iteration + // dont break here, it will exit the while loop + // just continue on to the next loop iteration } - if (len == 0) break; //timeout + if (len == 0) + break; // timeout } return usrp2_addrs; @@ -179,36 +183,39 @@ device_addrs_t usrp2_find(const device_addr_t &hint_){ /*********************************************************************** * Make **********************************************************************/ -static device::sptr usrp2_make(const device_addr_t &device_addr){ +static device::sptr usrp2_make(const device_addr_t& device_addr) +{ return device::sptr(new usrp2_impl(device_addr)); } -UHD_STATIC_BLOCK(register_usrp2_device){ +UHD_STATIC_BLOCK(register_usrp2_device) +{ device::register_device(&usrp2_find, &usrp2_make, device::USRP); } /*********************************************************************** * MTU Discovery **********************************************************************/ -struct mtu_result_t{ +struct mtu_result_t +{ size_t recv_mtu, send_mtu; }; -static mtu_result_t determine_mtu(const std::string &addr, const mtu_result_t &user_mtu){ - udp_simple::sptr udp_sock = udp_simple::make_connected( - addr, BOOST_STRINGIZE(USRP2_UDP_CTRL_PORT) - ); +static mtu_result_t determine_mtu(const std::string& addr, const mtu_result_t& user_mtu) +{ + udp_simple::sptr udp_sock = + udp_simple::make_connected(addr, BOOST_STRINGIZE(USRP2_UDP_CTRL_PORT)); - //The FPGA offers 4K buffers, and the user may manually request this. - //However, multiple simultaneous receives (2DSP slave + 2DSP master), - //require that buffering to be used internally, and this is a safe setting. + // The FPGA offers 4K buffers, and the user may manually request this. + // However, multiple simultaneous receives (2DSP slave + 2DSP master), + // require that buffering to be used internally, and this is a safe setting. std::vector<uint8_t> buffer(std::max(user_mtu.recv_mtu, user_mtu.send_mtu)); - usrp2_ctrl_data_t *ctrl_data = reinterpret_cast<usrp2_ctrl_data_t *>(&buffer.front()); - static const double echo_timeout = 0.020; //20 ms + usrp2_ctrl_data_t* ctrl_data = reinterpret_cast<usrp2_ctrl_data_t*>(&buffer.front()); + 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); + // 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); @@ -218,36 +225,38 @@ static mtu_result_t determine_mtu(const std::string &addr, const mtu_result_t &u size_t min_recv_mtu = sizeof(usrp2_ctrl_data_t), max_recv_mtu = user_mtu.recv_mtu; size_t min_send_mtu = sizeof(usrp2_ctrl_data_t), max_send_mtu = user_mtu.send_mtu; - while (min_recv_mtu < max_recv_mtu){ + while (min_recv_mtu < max_recv_mtu) { + size_t test_mtu = (max_recv_mtu / 2 + min_recv_mtu / 2 + 3) & ~3; - size_t test_mtu = (max_recv_mtu/2 + min_recv_mtu/2 + 3) & ~3; - - ctrl_data->id = htonl(USRP2_CTRL_ID_HOLLER_AT_ME_BRO); - ctrl_data->proto_ver = htonl(USRP2_FW_COMPAT_NUM); + 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(test_mtu); udp_sock->send(boost::asio::buffer(buffer, sizeof(usrp2_ctrl_data_t))); size_t len = udp_sock->recv(boost::asio::buffer(buffer), echo_timeout); - if (len >= test_mtu) min_recv_mtu = test_mtu; - else max_recv_mtu = test_mtu - 4; - + if (len >= test_mtu) + min_recv_mtu = test_mtu; + else + max_recv_mtu = test_mtu - 4; } - while (min_send_mtu < max_send_mtu){ - - size_t test_mtu = (max_send_mtu/2 + min_send_mtu/2 + 3) & ~3; + while (min_send_mtu < max_send_mtu) { + size_t test_mtu = (max_send_mtu / 2 + min_send_mtu / 2 + 3) & ~3; - ctrl_data->id = htonl(USRP2_CTRL_ID_HOLLER_AT_ME_BRO); - ctrl_data->proto_ver = htonl(USRP2_FW_COMPAT_NUM); + 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, test_mtu)); size_t len = udp_sock->recv(boost::asio::buffer(buffer), echo_timeout); - if (len >= sizeof(usrp2_ctrl_data_t)) len = ntohl(ctrl_data->data.echo_args.len); + if (len >= sizeof(usrp2_ctrl_data_t)) + len = ntohl(ctrl_data->data.echo_args.len); - if (len >= test_mtu) min_send_mtu = test_mtu; - else max_send_mtu = test_mtu - 4; + if (len >= test_mtu) + min_send_mtu = test_mtu; + else + max_send_mtu = test_mtu - 4; } mtu_result_t mtu; @@ -259,17 +268,16 @@ static mtu_result_t determine_mtu(const std::string &addr, const mtu_result_t &u /*********************************************************************** * Helpers **********************************************************************/ -static zero_copy_if::sptr make_xport( - const std::string &addr, - const std::string &port, - const device_addr_t &hints, - const std::string &filter -){ - - //only copy hints that contain the filter word +static zero_copy_if::sptr make_xport(const std::string& addr, + const std::string& port, + const device_addr_t& hints, + const std::string& filter) +{ + // only copy hints that contain the filter word device_addr_t filtered_hints; - for(const std::string &key: hints.keys()){ - if (key.find(filter) == std::string::npos) continue; + for (const std::string& key : hints.keys()) { + if (key.find(filter) == std::string::npos) + continue; filtered_hints[key] = hints[key]; } @@ -279,17 +287,16 @@ static zero_copy_if::sptr make_xport( default_buff_args.num_send_frames = DEFAULT_NUM_FRAMES; default_buff_args.num_recv_frames = DEFAULT_NUM_FRAMES; - //make the transport object with the filtered hints + // make the transport object with the filtered hints udp_zero_copy::buff_params ignored_params; - zero_copy_if::sptr xport = udp_zero_copy::make(addr, port, default_buff_args, ignored_params, filtered_hints); - - //Send a small data packet so the usrp2 knows the udp source port. - //This setup must happen before further initialization occurs - //or the async update packets will cause ICMP destination unreachable. - static const uint32_t data[2] = { - uhd::htonx(uint32_t(0 /* don't care seq num */)), - uhd::htonx(uint32_t(USRP2_INVALID_VRT_HEADER)) - }; + zero_copy_if::sptr xport = udp_zero_copy::make( + addr, port, default_buff_args, ignored_params, filtered_hints); + + // Send a small data packet so the usrp2 knows the udp source port. + // This setup must happen before further initialization occurs + // or the async update packets will cause ICMP destination unreachable. + static const uint32_t data[2] = {uhd::htonx(uint32_t(0 /* don't care seq num */)), + uhd::htonx(uint32_t(USRP2_INVALID_VRT_HEADER))}; transport::managed_send_buffer::sptr send_buff = xport->get_send_buff(); std::memcpy(send_buff->cast<void*>(), &data, sizeof(data)); send_buff->commit(sizeof(data)); @@ -300,157 +307,161 @@ static zero_copy_if::sptr make_xport( /*********************************************************************** * Structors **********************************************************************/ -usrp2_impl::usrp2_impl(const device_addr_t &_device_addr) : - device_addr(_device_addr), - _pirate_task_exit(false) +usrp2_impl::usrp2_impl(const device_addr_t& _device_addr) + : device_addr(_device_addr), _pirate_task_exit(false) { UHD_LOGGER_INFO("USRP2") << "Opening a USRP2/N-Series device..."; - //setup the dsp transport hints (default to a large recv buff) - if (not device_addr.has_key("recv_buff_size")){ - #if defined(UHD_PLATFORM_MACOS) || defined(UHD_PLATFORM_BSD) - //limit buffer resize on macos or it will error - device_addr["recv_buff_size"] = "1e6"; - #elif defined(UHD_PLATFORM_LINUX) || defined(UHD_PLATFORM_WIN32) - //set to half-a-second of buffering at max rate - device_addr["recv_buff_size"] = "50e6"; - #endif + // setup the dsp transport hints (default to a large recv buff) + if (not device_addr.has_key("recv_buff_size")) { +#if defined(UHD_PLATFORM_MACOS) || defined(UHD_PLATFORM_BSD) + // limit buffer resize on macos or it will error + device_addr["recv_buff_size"] = "1e6"; +#elif defined(UHD_PLATFORM_LINUX) || defined(UHD_PLATFORM_WIN32) + // set to half-a-second of buffering at max rate + device_addr["recv_buff_size"] = "50e6"; +#endif } - if (not device_addr.has_key("send_buff_size")){ - //The buffer should be the size of the SRAM on the device, - //because we will never commit more than the SRAM can hold. + if (not device_addr.has_key("send_buff_size")) { + // The buffer should be the size of the SRAM on the device, + // because we will never commit more than the SRAM can hold. device_addr["send_buff_size"] = std::to_string(USRP2_SRAM_BYTES); } device_addrs_t device_args = separate_device_addr(device_addr); - //extract the user's requested MTU size or default + // extract the user's requested MTU size or default mtu_result_t user_mtu; - user_mtu.recv_mtu = size_t(device_addr.cast<double>("recv_frame_size", udp_simple::mtu)); - user_mtu.send_mtu = size_t(device_addr.cast<double>("send_frame_size", udp_simple::mtu)); + user_mtu.recv_mtu = + size_t(device_addr.cast<double>("recv_frame_size", udp_simple::mtu)); + user_mtu.send_mtu = + size_t(device_addr.cast<double>("send_frame_size", udp_simple::mtu)); - try{ - //calculate the minimum send and recv mtu of all devices + try { + // calculate the minimum send and recv mtu of all devices mtu_result_t mtu = determine_mtu(device_args[0]["addr"], user_mtu); - for (size_t i = 1; i < device_args.size(); i++){ + for (size_t i = 1; i < device_args.size(); i++) { mtu_result_t mtu_i = determine_mtu(device_args[i]["addr"], user_mtu); - mtu.recv_mtu = std::min(mtu.recv_mtu, mtu_i.recv_mtu); - mtu.send_mtu = std::min(mtu.send_mtu, mtu_i.send_mtu); + mtu.recv_mtu = std::min(mtu.recv_mtu, mtu_i.recv_mtu); + mtu.send_mtu = std::min(mtu.send_mtu, mtu_i.send_mtu); } device_addr["recv_frame_size"] = std::to_string(mtu.recv_mtu); device_addr["send_frame_size"] = std::to_string(mtu.send_mtu); - UHD_LOGGER_INFO("USRP2") << boost::format("Current recv frame size: %d bytes") % mtu.recv_mtu; - UHD_LOGGER_INFO("USRP2") << boost::format("Current send frame size: %d bytes") % mtu.send_mtu; - } - catch(const uhd::not_implemented_error &){ - //just ignore this error, makes older fw work... + UHD_LOGGER_INFO("USRP2") + << boost::format("Current recv frame size: %d bytes") % mtu.recv_mtu; + UHD_LOGGER_INFO("USRP2") + << boost::format("Current send frame size: %d bytes") % mtu.send_mtu; + } 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 + device_args = separate_device_addr(device_addr); // update args for new frame sizes //////////////////////////////////////////////////////////////////// // create controller objects and initialize the properties tree //////////////////////////////////////////////////////////////////// - _tree = property_tree::make(); - _type = device::USRP; + _tree = property_tree::make(); + _type = device::USRP; _ignore_cal_file = device_addr.has_key("ignore-cal-file"); _tree->create<std::string>("/name").set("USRP2 / N-Series Device"); - for (size_t mbi = 0; mbi < device_args.size(); mbi++){ + for (size_t mbi = 0; mbi < device_args.size(); mbi++) { const device_addr_t device_args_i = device_args[mbi]; - const std::string mb = std::to_string(mbi); - const std::string addr = device_args_i["addr"]; - const fs_path mb_path = "/mboards/" + mb; + const std::string mb = std::to_string(mbi); + const std::string addr = device_args_i["addr"]; + const fs_path mb_path = "/mboards/" + mb; //////////////////////////////////////////////////////////////// // create the iface that controls i2c, spi, uart, and wb //////////////////////////////////////////////////////////////// - _mbc[mb].iface = usrp2_iface::make(udp_simple::make_connected( - addr, BOOST_STRINGIZE(USRP2_UDP_CTRL_PORT) - )); + _mbc[mb].iface = usrp2_iface::make( + udp_simple::make_connected(addr, BOOST_STRINGIZE(USRP2_UDP_CTRL_PORT))); _tree->create<std::string>(mb_path / "name").set(_mbc[mb].iface->get_cname()); - _tree->create<std::string>(mb_path / "fw_version").set(_mbc[mb].iface->get_fw_version_string()); + _tree->create<std::string>(mb_path / "fw_version") + .set(_mbc[mb].iface->get_fw_version_string()); - //check the fpga compatibility number + // check the fpga compatibility number const uint32_t fpga_compat_num = _mbc[mb].iface->peek32(U2_REG_COMPAT_NUM_RB); - uint16_t fpga_major = fpga_compat_num >> 16, fpga_minor = fpga_compat_num & 0xffff; - if (fpga_major == 0){ //old version scheme + uint16_t fpga_major = fpga_compat_num >> 16, + fpga_minor = fpga_compat_num & 0xffff; + if (fpga_major == 0) { // old version scheme fpga_major = fpga_minor; fpga_minor = 0; } - int expected_fpga_compat_num = std::min(USRP2_FPGA_COMPAT_NUM, N200_FPGA_COMPAT_NUM); - switch (_mbc[mb].iface->get_rev()) - { - case usrp2_iface::USRP2_REV3: - case usrp2_iface::USRP2_REV4: - expected_fpga_compat_num = USRP2_FPGA_COMPAT_NUM; - break; - case usrp2_iface::USRP_N200: - case usrp2_iface::USRP_N200_R4: - case usrp2_iface::USRP_N210: - case usrp2_iface::USRP_N210_R4: - expected_fpga_compat_num = N200_FPGA_COMPAT_NUM; - break; - default: - // handle case where the MB EEPROM is not programmed - if (fpga_major == USRP2_FPGA_COMPAT_NUM or fpga_major == N200_FPGA_COMPAT_NUM) - { - UHD_LOGGER_WARNING("USRP2") << "Unable to identify device - assuming USRP2/N-Series device" ; - expected_fpga_compat_num = fpga_major; - } + int expected_fpga_compat_num = + std::min(USRP2_FPGA_COMPAT_NUM, N200_FPGA_COMPAT_NUM); + switch (_mbc[mb].iface->get_rev()) { + case usrp2_iface::USRP2_REV3: + case usrp2_iface::USRP2_REV4: + expected_fpga_compat_num = USRP2_FPGA_COMPAT_NUM; + break; + case usrp2_iface::USRP_N200: + case usrp2_iface::USRP_N200_R4: + case usrp2_iface::USRP_N210: + case usrp2_iface::USRP_N210_R4: + expected_fpga_compat_num = N200_FPGA_COMPAT_NUM; + break; + default: + // handle case where the MB EEPROM is not programmed + if (fpga_major == USRP2_FPGA_COMPAT_NUM + or fpga_major == N200_FPGA_COMPAT_NUM) { + UHD_LOGGER_WARNING("USRP2") + << "Unable to identify device - assuming USRP2/N-Series device"; + expected_fpga_compat_num = fpga_major; + } } - if (fpga_major != expected_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.\n" - "%s\n" - ) % expected_fpga_compat_num % fpga_major % _mbc[mb].iface->images_warn_help_message())); + if (fpga_major != expected_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.\n" + "%s\n") + % expected_fpga_compat_num % fpga_major + % _mbc[mb].iface->images_warn_help_message())); } - _tree->create<std::string>(mb_path / "fpga_version").set(str(boost::format("%u.%u") % fpga_major % fpga_minor)); + _tree->create<std::string>(mb_path / "fpga_version") + .set(str(boost::format("%u.%u") % fpga_major % fpga_minor)); - //lock the device/motherboard to this process + // lock the device/motherboard to this process _mbc[mb].iface->lock_device(true); //////////////////////////////////////////////////////////////// // construct transports for RX and TX DSPs //////////////////////////////////////////////////////////////// - UHD_LOGGER_TRACE("USRP2") << "Making transport for RX DSP0..." ; + UHD_LOGGER_TRACE("USRP2") << "Making transport for RX DSP0..."; _mbc[mb].rx_dsp_xports.push_back(make_xport( - addr, BOOST_STRINGIZE(USRP2_UDP_RX_DSP0_PORT), device_args_i, "recv" - )); - UHD_LOGGER_TRACE("USRP2") << "Making transport for RX DSP1..." ; + addr, BOOST_STRINGIZE(USRP2_UDP_RX_DSP0_PORT), device_args_i, "recv")); + UHD_LOGGER_TRACE("USRP2") << "Making transport for RX DSP1..."; _mbc[mb].rx_dsp_xports.push_back(make_xport( - addr, BOOST_STRINGIZE(USRP2_UDP_RX_DSP1_PORT), device_args_i, "recv" - )); - UHD_LOGGER_TRACE("USRP2") << "Making transport for TX DSP0..." ; + addr, BOOST_STRINGIZE(USRP2_UDP_RX_DSP1_PORT), device_args_i, "recv")); + UHD_LOGGER_TRACE("USRP2") << "Making transport for TX DSP0..."; _mbc[mb].tx_dsp_xport = make_xport( - addr, BOOST_STRINGIZE(USRP2_UDP_TX_DSP0_PORT), device_args_i, "send" - ); - UHD_LOGGER_TRACE("USRP2") << "Making transport for Control..." ; + addr, BOOST_STRINGIZE(USRP2_UDP_TX_DSP0_PORT), device_args_i, "send"); + UHD_LOGGER_TRACE("USRP2") << "Making transport for Control..."; _mbc[mb].fifo_ctrl_xport = make_xport( - addr, BOOST_STRINGIZE(USRP2_UDP_FIFO_CRTL_PORT), device_addr_t(), "" - ); - //set the filter on the router to take dsp data from this port - _mbc[mb].iface->poke32(U2_REG_ROUTER_CTRL_PORTS, (USRP2_UDP_FIFO_CRTL_PORT << 16) | USRP2_UDP_TX_DSP0_PORT); + addr, BOOST_STRINGIZE(USRP2_UDP_FIFO_CRTL_PORT), device_addr_t(), ""); + // set the filter on the router to take dsp data from this port + _mbc[mb].iface->poke32(U2_REG_ROUTER_CTRL_PORTS, + (USRP2_UDP_FIFO_CRTL_PORT << 16) | USRP2_UDP_TX_DSP0_PORT); - //create the fifo control interface for high speed register access + // create the fifo control interface for high speed register access _mbc[mb].fifo_ctrl = usrp2_fifo_ctrl::make(_mbc[mb].fifo_ctrl_xport); - switch(_mbc[mb].iface->get_rev()){ - case usrp2_iface::USRP_N200: - case usrp2_iface::USRP_N210: - case usrp2_iface::USRP_N200_R4: - case usrp2_iface::USRP_N210_R4: - _mbc[mb].wbiface = _mbc[mb].fifo_ctrl; - _mbc[mb].spiface = _mbc[mb].fifo_ctrl; - break; - default: - _mbc[mb].wbiface = _mbc[mb].iface; - _mbc[mb].spiface = _mbc[mb].iface; - break; + switch (_mbc[mb].iface->get_rev()) { + case usrp2_iface::USRP_N200: + case usrp2_iface::USRP_N210: + case usrp2_iface::USRP_N200_R4: + case usrp2_iface::USRP_N210_R4: + _mbc[mb].wbiface = _mbc[mb].fifo_ctrl; + _mbc[mb].spiface = _mbc[mb].fifo_ctrl; + break; + default: + _mbc[mb].wbiface = _mbc[mb].iface; + _mbc[mb].spiface = _mbc[mb].iface; + break; } _tree->create<double>(mb_path / "link_max_rate").set(USRP2_LINK_RATE_BPS); @@ -467,39 +478,51 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr) : //////////////////////////////////////////////////////////////// _mbc[mb].clock = usrp2_clock_ctrl::make(_mbc[mb].iface, _mbc[mb].spiface); _tree->create<double>(mb_path / "tick_rate") - .set_publisher(std::bind(&usrp2_clock_ctrl::get_master_clock_rate, _mbc[mb].clock)) - .add_coerced_subscriber(std::bind(&usrp2_impl::update_tick_rate, this, std::placeholders::_1)); + .set_publisher( + std::bind(&usrp2_clock_ctrl::get_master_clock_rate, _mbc[mb].clock)) + .add_coerced_subscriber( + std::bind(&usrp2_impl::update_tick_rate, this, std::placeholders::_1)); //////////////////////////////////////////////////////////////// // create codec control objects //////////////////////////////////////////////////////////////// const fs_path rx_codec_path = mb_path / "rx_codecs/A"; const fs_path tx_codec_path = mb_path / "tx_codecs/A"; - _tree->create<int>(rx_codec_path / "gains"); //phony property so this dir exists - _tree->create<int>(tx_codec_path / "gains"); //phony property so this dir exists + _tree->create<int>(rx_codec_path / "gains"); // phony property so this dir exists + _tree->create<int>(tx_codec_path / "gains"); // phony property so this dir exists _mbc[mb].codec = usrp2_codec_ctrl::make(_mbc[mb].iface, _mbc[mb].spiface); - switch(_mbc[mb].iface->get_rev()){ - case usrp2_iface::USRP_N200: - case usrp2_iface::USRP_N210: - case usrp2_iface::USRP_N200_R4: - case usrp2_iface::USRP_N210_R4:{ - _tree->create<std::string>(rx_codec_path / "name").set("ads62p44"); - _tree->create<meta_range_t>(rx_codec_path / "gains/digital/range").set(meta_range_t(0, 6.0, 0.5)); - _tree->create<double>(rx_codec_path / "gains/digital/value") - .add_coerced_subscriber(std::bind(&usrp2_codec_ctrl::set_rx_digital_gain, _mbc[mb].codec, std::placeholders::_1)).set(0); - _tree->create<meta_range_t>(rx_codec_path / "gains/fine/range").set(meta_range_t(0, 0.5, 0.05)); - _tree->create<double>(rx_codec_path / "gains/fine/value") - .add_coerced_subscriber(std::bind(&usrp2_codec_ctrl::set_rx_digital_fine_gain, _mbc[mb].codec, std::placeholders::_1)).set(0); - }break; - - case usrp2_iface::USRP2_REV3: - case usrp2_iface::USRP2_REV4: - _tree->create<std::string>(rx_codec_path / "name").set("ltc2284"); - break; - - case usrp2_iface::USRP_NXXX: - _tree->create<std::string>(rx_codec_path / "name").set("??????"); - break; + switch (_mbc[mb].iface->get_rev()) { + case usrp2_iface::USRP_N200: + case usrp2_iface::USRP_N210: + case usrp2_iface::USRP_N200_R4: + case usrp2_iface::USRP_N210_R4: { + _tree->create<std::string>(rx_codec_path / "name").set("ads62p44"); + _tree->create<meta_range_t>(rx_codec_path / "gains/digital/range") + .set(meta_range_t(0, 6.0, 0.5)); + _tree->create<double>(rx_codec_path / "gains/digital/value") + .add_coerced_subscriber( + std::bind(&usrp2_codec_ctrl::set_rx_digital_gain, + _mbc[mb].codec, + std::placeholders::_1)) + .set(0); + _tree->create<meta_range_t>(rx_codec_path / "gains/fine/range") + .set(meta_range_t(0, 0.5, 0.05)); + _tree->create<double>(rx_codec_path / "gains/fine/value") + .add_coerced_subscriber( + std::bind(&usrp2_codec_ctrl::set_rx_digital_fine_gain, + _mbc[mb].codec, + std::placeholders::_1)) + .set(0); + } break; + + case usrp2_iface::USRP2_REV3: + case usrp2_iface::USRP2_REV4: + _tree->create<std::string>(rx_codec_path / "name").set("ltc2284"); + break; + + case usrp2_iface::USRP_NXXX: + _tree->create<std::string>(rx_codec_path / "name").set("??????"); + break; } _tree->create<std::string>(tx_codec_path / "name").set("ad9777"); @@ -508,39 +531,35 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr) : //////////////////////////////////////////////////////////////////// static const uint32_t dont_look_for_gpsdo = 0x1234abcdul; - //disable check for internal GPSDO when not the following: - switch(_mbc[mb].iface->get_rev()){ - case usrp2_iface::USRP_N200: - case usrp2_iface::USRP_N210: - case usrp2_iface::USRP_N200_R4: - case usrp2_iface::USRP_N210_R4: - break; - default: - _mbc[mb].iface->pokefw(U2_FW_REG_HAS_GPSDO, dont_look_for_gpsdo); + // disable check for internal GPSDO when not the following: + switch (_mbc[mb].iface->get_rev()) { + case usrp2_iface::USRP_N200: + case usrp2_iface::USRP_N210: + case usrp2_iface::USRP_N200_R4: + case usrp2_iface::USRP_N210_R4: + break; + default: + _mbc[mb].iface->pokefw(U2_FW_REG_HAS_GPSDO, dont_look_for_gpsdo); } - //otherwise if not disabled, look for the internal GPSDO - if (_mbc[mb].iface->peekfw(U2_FW_REG_HAS_GPSDO) != dont_look_for_gpsdo) - { + // otherwise if not disabled, look for the internal GPSDO + if (_mbc[mb].iface->peekfw(U2_FW_REG_HAS_GPSDO) != dont_look_for_gpsdo) { UHD_LOGGER_INFO("USRP2") << "Detecting internal GPSDO.... "; - try{ - _mbc[mb].gps = gps_ctrl::make(udp_simple::make_uart(udp_simple::make_connected( - addr, BOOST_STRINGIZE(USRP2_UDP_UART_GPS_PORT) - ))); - } - catch(std::exception &e){ - UHD_LOGGER_ERROR("USRP2") << "An error occurred making GPSDO control: " << e.what() ; + try { + _mbc[mb].gps = + gps_ctrl::make(udp_simple::make_uart(udp_simple::make_connected( + addr, BOOST_STRINGIZE(USRP2_UDP_UART_GPS_PORT)))); + } catch (std::exception& e) { + UHD_LOGGER_ERROR("USRP2") + << "An error occurred making GPSDO control: " << e.what(); } - if (_mbc[mb].gps and _mbc[mb].gps->gps_detected()) - { - for(const std::string &name: _mbc[mb].gps->get_sensors()) - { + if (_mbc[mb].gps and _mbc[mb].gps->gps_detected()) { + for (const std::string& name : _mbc[mb].gps->get_sensors()) { _tree->create<sensor_value_t>(mb_path / "sensors" / name) - .set_publisher(std::bind(&gps_ctrl::get_sensor, _mbc[mb].gps, name)); + .set_publisher( + std::bind(&gps_ctrl::get_sensor, _mbc[mb].gps, name)); } - } - else - { + } else { _mbc[mb].iface->pokefw(U2_FW_REG_HAS_GPSDO, dont_look_for_gpsdo); } } @@ -556,116 +575,134 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr) : //////////////////////////////////////////////////////////////// // create frontend control objects //////////////////////////////////////////////////////////////// - _mbc[mb].rx_fe = rx_frontend_core_200::make( - _mbc[mb].wbiface, U2_REG_SR_ADDR(SR_RX_FRONT) - ); - _mbc[mb].tx_fe = tx_frontend_core_200::make( - _mbc[mb].wbiface, U2_REG_SR_ADDR(SR_TX_FRONT) - ); + _mbc[mb].rx_fe = + rx_frontend_core_200::make(_mbc[mb].wbiface, U2_REG_SR_ADDR(SR_RX_FRONT)); + _mbc[mb].tx_fe = + tx_frontend_core_200::make(_mbc[mb].wbiface, U2_REG_SR_ADDR(SR_TX_FRONT)); _tree->create<subdev_spec_t>(mb_path / "rx_subdev_spec") - .add_coerced_subscriber(std::bind(&usrp2_impl::update_rx_subdev_spec, this, mb, std::placeholders::_1)); + .add_coerced_subscriber(std::bind( + &usrp2_impl::update_rx_subdev_spec, this, mb, std::placeholders::_1)); _tree->create<subdev_spec_t>(mb_path / "tx_subdev_spec") - .add_coerced_subscriber(std::bind(&usrp2_impl::update_tx_subdev_spec, this, mb, std::placeholders::_1)); + .add_coerced_subscriber(std::bind( + &usrp2_impl::update_tx_subdev_spec, this, mb, std::placeholders::_1)); const fs_path rx_fe_path = mb_path / "rx_frontends" / "A"; const fs_path tx_fe_path = mb_path / "tx_frontends" / "A"; - _tree->create<std::complex<double> >(rx_fe_path / "dc_offset" / "value") - .set_coercer(std::bind(&rx_frontend_core_200::set_dc_offset, _mbc[mb].rx_fe, std::placeholders::_1)) + _tree->create<std::complex<double>>(rx_fe_path / "dc_offset" / "value") + .set_coercer(std::bind(&rx_frontend_core_200::set_dc_offset, + _mbc[mb].rx_fe, + std::placeholders::_1)) .set(std::complex<double>(0.0, 0.0)); _tree->create<bool>(rx_fe_path / "dc_offset" / "enable") - .add_coerced_subscriber(std::bind(&rx_frontend_core_200::set_dc_offset_auto, _mbc[mb].rx_fe, std::placeholders::_1)) + .add_coerced_subscriber(std::bind(&rx_frontend_core_200::set_dc_offset_auto, + _mbc[mb].rx_fe, + std::placeholders::_1)) .set(true); - _tree->create<std::complex<double> >(rx_fe_path / "iq_balance" / "value") - .add_coerced_subscriber(std::bind(&rx_frontend_core_200::set_iq_balance, _mbc[mb].rx_fe, std::placeholders::_1)) + _tree->create<std::complex<double>>(rx_fe_path / "iq_balance" / "value") + .add_coerced_subscriber(std::bind(&rx_frontend_core_200::set_iq_balance, + _mbc[mb].rx_fe, + std::placeholders::_1)) .set(std::complex<double>(0.0, 0.0)); - _tree->create<std::complex<double> >(tx_fe_path / "dc_offset" / "value") - .set_coercer(std::bind(&tx_frontend_core_200::set_dc_offset, _mbc[mb].tx_fe, std::placeholders::_1)) + _tree->create<std::complex<double>>(tx_fe_path / "dc_offset" / "value") + .set_coercer(std::bind(&tx_frontend_core_200::set_dc_offset, + _mbc[mb].tx_fe, + std::placeholders::_1)) .set(std::complex<double>(0.0, 0.0)); - _tree->create<std::complex<double> >(tx_fe_path / "iq_balance" / "value") - .add_coerced_subscriber(std::bind(&tx_frontend_core_200::set_iq_balance, _mbc[mb].tx_fe, std::placeholders::_1)) + _tree->create<std::complex<double>>(tx_fe_path / "iq_balance" / "value") + .add_coerced_subscriber(std::bind(&tx_frontend_core_200::set_iq_balance, + _mbc[mb].tx_fe, + std::placeholders::_1)) .set(std::complex<double>(0.0, 0.0)); //////////////////////////////////////////////////////////////// // create rx dsp control objects //////////////////////////////////////////////////////////////// - _mbc[mb].rx_dsps.push_back(rx_dsp_core_200::make( - _mbc[mb].wbiface, U2_REG_SR_ADDR(SR_RX_DSP0), U2_REG_SR_ADDR(SR_RX_CTRL0), USRP2_RX_SID_BASE + 0, true - )); - _mbc[mb].rx_dsps.push_back(rx_dsp_core_200::make( - _mbc[mb].wbiface, U2_REG_SR_ADDR(SR_RX_DSP1), U2_REG_SR_ADDR(SR_RX_CTRL1), USRP2_RX_SID_BASE + 1, true - )); - for (size_t dspno = 0; dspno < _mbc[mb].rx_dsps.size(); dspno++){ + _mbc[mb].rx_dsps.push_back(rx_dsp_core_200::make(_mbc[mb].wbiface, + U2_REG_SR_ADDR(SR_RX_DSP0), + U2_REG_SR_ADDR(SR_RX_CTRL0), + USRP2_RX_SID_BASE + 0, + true)); + _mbc[mb].rx_dsps.push_back(rx_dsp_core_200::make(_mbc[mb].wbiface, + U2_REG_SR_ADDR(SR_RX_DSP1), + U2_REG_SR_ADDR(SR_RX_CTRL1), + USRP2_RX_SID_BASE + 1, + true)); + for (size_t dspno = 0; dspno < _mbc[mb].rx_dsps.size(); dspno++) { _mbc[mb].rx_dsps[dspno]->set_link_rate(USRP2_LINK_RATE_BPS); _tree->access<double>(mb_path / "tick_rate") - .add_coerced_subscriber(std::bind(&rx_dsp_core_200::set_tick_rate, _mbc[mb].rx_dsps[dspno], std::placeholders::_1)); + .add_coerced_subscriber(std::bind(&rx_dsp_core_200::set_tick_rate, + _mbc[mb].rx_dsps[dspno], + std::placeholders::_1)); fs_path rx_dsp_path = mb_path / str(boost::format("rx_dsps/%u") % dspno); _tree->create<meta_range_t>(rx_dsp_path / "rate/range") - .set_publisher(std::bind(&rx_dsp_core_200::get_host_rates, _mbc[mb].rx_dsps[dspno])); + .set_publisher( + std::bind(&rx_dsp_core_200::get_host_rates, _mbc[mb].rx_dsps[dspno])); _tree->create<double>(rx_dsp_path / "rate/value") - .set(1e6) //some default - .set_coercer(std::bind(&rx_dsp_core_200::set_host_rate, _mbc[mb].rx_dsps[dspno], std::placeholders::_1)) - .add_coerced_subscriber(std::bind(&usrp2_impl::update_rx_samp_rate, this, mb, dspno, std::placeholders::_1)); + .set(1e6) // some default + .set_coercer(std::bind(&rx_dsp_core_200::set_host_rate, + _mbc[mb].rx_dsps[dspno], + std::placeholders::_1)) + .add_coerced_subscriber(std::bind(&usrp2_impl::update_rx_samp_rate, + this, + mb, + dspno, + std::placeholders::_1)); _tree->create<double>(rx_dsp_path / "freq/value") - .set_coercer(std::bind(&rx_dsp_core_200::set_freq, _mbc[mb].rx_dsps[dspno], std::placeholders::_1)); + .set_coercer(std::bind(&rx_dsp_core_200::set_freq, + _mbc[mb].rx_dsps[dspno], + std::placeholders::_1)); _tree->create<meta_range_t>(rx_dsp_path / "freq/range") - .set_publisher(std::bind(&rx_dsp_core_200::get_freq_range, _mbc[mb].rx_dsps[dspno])); + .set_publisher( + std::bind(&rx_dsp_core_200::get_freq_range, _mbc[mb].rx_dsps[dspno])); _tree->create<stream_cmd_t>(rx_dsp_path / "stream_cmd") - .add_coerced_subscriber(std::bind(&rx_dsp_core_200::issue_stream_command, _mbc[mb].rx_dsps[dspno], std::placeholders::_1)); + .add_coerced_subscriber(std::bind(&rx_dsp_core_200::issue_stream_command, + _mbc[mb].rx_dsps[dspno], + std::placeholders::_1)); } //////////////////////////////////////////////////////////////// // create tx dsp control objects //////////////////////////////////////////////////////////////// - _mbc[mb].tx_dsp = tx_dsp_core_200::make( - _mbc[mb].wbiface, + _mbc[mb].tx_dsp = tx_dsp_core_200::make(_mbc[mb].wbiface, U2_REG_SR_ADDR(SR_TX_DSP), U2_REG_SR_ADDR(SR_TX_CTRL), - USRP2_TX_ASYNC_SID - ); + USRP2_TX_ASYNC_SID); _mbc[mb].tx_dsp->set_link_rate(USRP2_LINK_RATE_BPS); { // This scope can be removed once we're able to do named captures - auto this_tx_dsp = _mbc[mb].tx_dsp; // This can then also go away - _tree->access<double>(mb_path / "tick_rate") - .add_coerced_subscriber([this_tx_dsp](const double rate){ - this_tx_dsp->set_tick_rate(rate); - }) - ; - _tree->create<meta_range_t>(mb_path / "tx_dsps/0/rate/range") - .set_publisher([this_tx_dsp](){ - return this_tx_dsp->get_host_rates(); - }) - ; - _tree->create<double>(mb_path / "tx_dsps/0/rate/value") - .set(1e6) //some default - .set_coercer([this_tx_dsp](const double rate){ - return this_tx_dsp->set_host_rate(rate); - }) - .add_coerced_subscriber([this, mb](const double rate){ - this->update_tx_samp_rate(mb, 0, rate); - }) - ; + auto this_tx_dsp = _mbc[mb].tx_dsp; // This can then also go away + _tree->access<double>(mb_path / "tick_rate") + .add_coerced_subscriber([this_tx_dsp](const double rate) { + this_tx_dsp->set_tick_rate(rate); + }); + _tree->create<meta_range_t>(mb_path / "tx_dsps/0/rate/range") + .set_publisher([this_tx_dsp]() { return this_tx_dsp->get_host_rates(); }); + _tree->create<double>(mb_path / "tx_dsps/0/rate/value") + .set(1e6) // some default + .set_coercer([this_tx_dsp](const double rate) { + return this_tx_dsp->set_host_rate(rate); + }) + .add_coerced_subscriber([this, mb](const double rate) { + this->update_tx_samp_rate(mb, 0, rate); + }); } // End of non-C++14 scope (to release reference to this_tx_dsp) _tree->create<double>(mb_path / "tx_dsps/0/freq/value") - .set_coercer([this, mb](const double rate){ + .set_coercer([this, mb](const double rate) { return this->set_tx_dsp_freq(mb, rate); - }) - ; + }); _tree->create<meta_range_t>(mb_path / "tx_dsps/0/freq/range") - .set_publisher([this, mb](){ - return this->get_tx_dsp_freq_range(mb); - }) - ; + .set_publisher([this, mb]() { return this->get_tx_dsp_freq_range(mb); }); - //setup dsp flow control - const double ups_per_sec = device_args_i.cast<double>("ups_per_sec", 20); + // setup dsp flow control + const double ups_per_sec = device_args_i.cast<double>("ups_per_sec", 20); const size_t send_frame_size = _mbc[mb].tx_dsp_xport->get_send_frame_size(); - const double ups_per_fifo = device_args_i.cast<double>("ups_per_fifo", 8.0); + const double ups_per_fifo = device_args_i.cast<double>("ups_per_fifo", 8.0); _mbc[mb].tx_dsp->set_updates( - (ups_per_sec > 0.0)? size_t(100e6/*approx tick rate*//ups_per_sec) : 0, - (ups_per_fifo > 0.0)? size_t(USRP2_SRAM_BYTES/ups_per_fifo/send_frame_size) : 0 - ); + (ups_per_sec > 0.0) ? size_t(100e6 /*approx tick rate*/ / ups_per_sec) : 0, + (ups_per_fifo > 0.0) + ? size_t(USRP2_SRAM_BYTES / ups_per_fifo / send_frame_size) + : 0); //////////////////////////////////////////////////////////////// // create time control objects @@ -675,26 +712,36 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr) : time64_rb_bases.rb_lo_now = U2_REG_TIME64_LO_RB_IMM; time64_rb_bases.rb_hi_pps = U2_REG_TIME64_HI_RB_PPS; time64_rb_bases.rb_lo_pps = U2_REG_TIME64_LO_RB_PPS; - _mbc[mb].time64 = time64_core_200::make( - _mbc[mb].wbiface, U2_REG_SR_ADDR(SR_TIME64), time64_rb_bases, mimo_clock_sync_delay_cycles - ); + _mbc[mb].time64 = time64_core_200::make(_mbc[mb].wbiface, + U2_REG_SR_ADDR(SR_TIME64), + time64_rb_bases, + mimo_clock_sync_delay_cycles); _tree->access<double>(mb_path / "tick_rate") - .add_coerced_subscriber(std::bind(&time64_core_200::set_tick_rate, _mbc[mb].time64, std::placeholders::_1)); + .add_coerced_subscriber(std::bind( + &time64_core_200::set_tick_rate, _mbc[mb].time64, std::placeholders::_1)); _tree->create<time_spec_t>(mb_path / "time/now") .set_publisher(std::bind(&time64_core_200::get_time_now, _mbc[mb].time64)) - .add_coerced_subscriber(std::bind(&time64_core_200::set_time_now, _mbc[mb].time64, std::placeholders::_1)); + .add_coerced_subscriber(std::bind( + &time64_core_200::set_time_now, _mbc[mb].time64, std::placeholders::_1)); _tree->create<time_spec_t>(mb_path / "time/pps") - .set_publisher(std::bind(&time64_core_200::get_time_last_pps, _mbc[mb].time64)) - .add_coerced_subscriber(std::bind(&time64_core_200::set_time_next_pps, _mbc[mb].time64, std::placeholders::_1)); - //setup time source props + .set_publisher( + std::bind(&time64_core_200::get_time_last_pps, _mbc[mb].time64)) + .add_coerced_subscriber(std::bind(&time64_core_200::set_time_next_pps, + _mbc[mb].time64, + std::placeholders::_1)); + // setup time source props _tree->create<std::string>(mb_path / "time_source/value") - .add_coerced_subscriber(std::bind(&time64_core_200::set_time_source, _mbc[mb].time64, std::placeholders::_1)) + .add_coerced_subscriber(std::bind(&time64_core_200::set_time_source, + _mbc[mb].time64, + std::placeholders::_1)) .set("none"); - _tree->create<std::vector<std::string> >(mb_path / "time_source/options") - .set_publisher(std::bind(&time64_core_200::get_time_sources, _mbc[mb].time64)); - //setup reference source props + _tree->create<std::vector<std::string>>(mb_path / "time_source/options") + .set_publisher( + std::bind(&time64_core_200::get_time_sources, _mbc[mb].time64)); + // setup reference source props _tree->create<std::string>(mb_path / "clock_source/value") - .add_coerced_subscriber(std::bind(&usrp2_impl::update_clock_source, this, mb, std::placeholders::_1)) + .add_coerced_subscriber(std::bind( + &usrp2_impl::update_clock_source, this, mb, std::placeholders::_1)) .set("internal"); std::vector<std::string> clock_sources{"internal", "external", "mimo"}; if (_mbc[mb].gps and _mbc[mb].gps->gps_detected()) { @@ -702,229 +749,269 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr) : } _tree->create<std::vector<std::string>>(mb_path / "clock_source/options") .set(clock_sources); - //plug timed commands into tree here - switch(_mbc[mb].iface->get_rev()){ - case usrp2_iface::USRP_N200: - case usrp2_iface::USRP_N210: - case usrp2_iface::USRP_N200_R4: - case usrp2_iface::USRP_N210_R4: - _tree->create<time_spec_t>(mb_path / "time/cmd") - .add_coerced_subscriber(std::bind(&usrp2_fifo_ctrl::set_time, _mbc[mb].fifo_ctrl, std::placeholders::_1)); - default: break; //otherwise, do not register + // plug timed commands into tree here + switch (_mbc[mb].iface->get_rev()) { + case usrp2_iface::USRP_N200: + case usrp2_iface::USRP_N210: + case usrp2_iface::USRP_N200_R4: + case usrp2_iface::USRP_N210_R4: + _tree->create<time_spec_t>(mb_path / "time/cmd") + .add_coerced_subscriber(std::bind(&usrp2_fifo_ctrl::set_time, + _mbc[mb].fifo_ctrl, + std::placeholders::_1)); + default: + break; // otherwise, do not register } _tree->access<double>(mb_path / "tick_rate") - .add_coerced_subscriber(std::bind(&usrp2_fifo_ctrl::set_tick_rate, _mbc[mb].fifo_ctrl, std::placeholders::_1)); + .add_coerced_subscriber(std::bind(&usrp2_fifo_ctrl::set_tick_rate, + _mbc[mb].fifo_ctrl, + std::placeholders::_1)); //////////////////////////////////////////////////////////////////// // create user-defined control objects //////////////////////////////////////////////////////////////////// - _mbc[mb].user = user_settings_core_200::make(_mbc[mb].wbiface, U2_REG_SR_ADDR(SR_USER_REGS)); + _mbc[mb].user = + user_settings_core_200::make(_mbc[mb].wbiface, U2_REG_SR_ADDR(SR_USER_REGS)); _tree->create<user_settings_core_200::user_reg_t>(mb_path / "user/regs") - .add_coerced_subscriber(std::bind(&user_settings_core_200::set_reg, _mbc[mb].user, std::placeholders::_1)); + .add_coerced_subscriber(std::bind( + &user_settings_core_200::set_reg, _mbc[mb].user, std::placeholders::_1)); //////////////////////////////////////////////////////////////// // create dboard control objects //////////////////////////////////////////////////////////////// - //read the dboard eeprom to extract the dboard ids + // read the dboard eeprom to extract the dboard ids dboard_eeprom_t rx_db_eeprom, tx_db_eeprom, gdb_eeprom; rx_db_eeprom.load(*_mbc[mb].iface, USRP2_I2C_ADDR_RX_DB); tx_db_eeprom.load(*_mbc[mb].iface, USRP2_I2C_ADDR_TX_DB); gdb_eeprom.load(*_mbc[mb].iface, USRP2_I2C_ADDR_TX_DB ^ 5); - //disable rx dc offset if LFRX - if (rx_db_eeprom.id == 0x000f) _tree->access<bool>(rx_fe_path / "dc_offset" / "enable").set(false); + // disable rx dc offset if LFRX + if (rx_db_eeprom.id == 0x000f) + _tree->access<bool>(rx_fe_path / "dc_offset" / "enable").set(false); - //create the properties and register subscribers + // create the properties and register subscribers _tree->create<dboard_eeprom_t>(mb_path / "dboards/A/rx_eeprom") .set(rx_db_eeprom) - .add_coerced_subscriber(std::bind(&usrp2_impl::set_db_eeprom, this, mb, "rx", std::placeholders::_1)); + .add_coerced_subscriber(std::bind( + &usrp2_impl::set_db_eeprom, this, mb, "rx", std::placeholders::_1)); _tree->create<dboard_eeprom_t>(mb_path / "dboards/A/tx_eeprom") .set(tx_db_eeprom) - .add_coerced_subscriber(std::bind(&usrp2_impl::set_db_eeprom, this, mb, "tx", std::placeholders::_1)); + .add_coerced_subscriber(std::bind( + &usrp2_impl::set_db_eeprom, this, mb, "tx", std::placeholders::_1)); _tree->create<dboard_eeprom_t>(mb_path / "dboards/A/gdb_eeprom") .set(gdb_eeprom) - .add_coerced_subscriber(std::bind(&usrp2_impl::set_db_eeprom, this, mb, "gdb", std::placeholders::_1)); - - //create a new dboard interface and manager - _mbc[mb].dboard_manager = dboard_manager::make( - rx_db_eeprom, tx_db_eeprom, gdb_eeprom, - make_usrp2_dboard_iface(_mbc[mb].wbiface, _mbc[mb].iface/*i2c*/, _mbc[mb].spiface, _mbc[mb].clock), - _tree->subtree(mb_path / "dboards/A") - ); - - //bind frontend corrections to the dboard freq props + .add_coerced_subscriber(std::bind( + &usrp2_impl::set_db_eeprom, this, mb, "gdb", std::placeholders::_1)); + + // create a new dboard interface and manager + _mbc[mb].dboard_manager = dboard_manager::make(rx_db_eeprom, + tx_db_eeprom, + gdb_eeprom, + make_usrp2_dboard_iface(_mbc[mb].wbiface, + _mbc[mb].iface /*i2c*/, + _mbc[mb].spiface, + _mbc[mb].clock), + _tree->subtree(mb_path / "dboards/A")); + + // bind frontend corrections to the dboard freq props const fs_path db_tx_fe_path = mb_path / "dboards" / "A" / "tx_frontends"; - for(const std::string &name: _tree->list(db_tx_fe_path)){ + for (const std::string& name : _tree->list(db_tx_fe_path)) { _tree->access<double>(db_tx_fe_path / name / "freq" / "value") - .add_coerced_subscriber(std::bind(&usrp2_impl::set_tx_fe_corrections, this, mb, std::placeholders::_1)); + .add_coerced_subscriber(std::bind( + &usrp2_impl::set_tx_fe_corrections, this, mb, std::placeholders::_1)); } const fs_path db_rx_fe_path = mb_path / "dboards" / "A" / "rx_frontends"; - for(const std::string &name: _tree->list(db_rx_fe_path)){ + for (const std::string& name : _tree->list(db_rx_fe_path)) { _tree->access<double>(db_rx_fe_path / name / "freq" / "value") - .add_coerced_subscriber(std::bind(&usrp2_impl::set_rx_fe_corrections, this, mb, std::placeholders::_1)); + .add_coerced_subscriber(std::bind( + &usrp2_impl::set_rx_fe_corrections, this, mb, std::placeholders::_1)); } } - //initialize io handling + // initialize io handling this->io_init(); - //do some post-init tasks + // do some post-init tasks this->update_rates(); - for(const std::string &mb: _mbc.keys()){ + for (const std::string& mb : _mbc.keys()) { fs_path root = "/mboards/" + mb; - //reset cordic rates and their properties to zero - for(const std::string &name: _tree->list(root / "rx_dsps")){ + // reset cordic rates and their properties to zero + for (const std::string& name : _tree->list(root / "rx_dsps")) { _tree->access<double>(root / "rx_dsps" / name / "freq" / "value").set(0.0); } - for(const std::string &name: _tree->list(root / "tx_dsps")){ + for (const std::string& name : _tree->list(root / "tx_dsps")) { _tree->access<double>(root / "tx_dsps" / name / "freq" / "value").set(0.0); } - _tree->access<subdev_spec_t>(root / "rx_subdev_spec").set(subdev_spec_t("A:" + _tree->list(root / "dboards/A/rx_frontends").at(0))); - _tree->access<subdev_spec_t>(root / "tx_subdev_spec").set(subdev_spec_t("A:" + _tree->list(root / "dboards/A/tx_frontends").at(0))); + _tree->access<subdev_spec_t>(root / "rx_subdev_spec") + .set( + subdev_spec_t("A:" + _tree->list(root / "dboards/A/rx_frontends").at(0))); + _tree->access<subdev_spec_t>(root / "tx_subdev_spec") + .set( + subdev_spec_t("A:" + _tree->list(root / "dboards/A/tx_frontends").at(0))); _tree->access<std::string>(root / "clock_source/value").set("internal"); _tree->access<std::string>(root / "time_source/value").set("none"); - //GPS installed: use external ref, time, and init time spec - if (_mbc[mb].gps and _mbc[mb].gps->gps_detected()){ + // GPS installed: use external ref, time, and init time spec + if (_mbc[mb].gps and _mbc[mb].gps->gps_detected()) { _mbc[mb].time64->enable_gpsdo(); - UHD_LOGGER_INFO("USRP2") << "Setting references to the internal GPSDO" ; + UHD_LOGGER_INFO("USRP2") << "Setting references to the internal GPSDO"; _tree->access<std::string>(root / "time_source/value").set("gpsdo"); _tree->access<std::string>(root / "clock_source/value").set("gpsdo"); } } - } -usrp2_impl::~usrp2_impl(void){UHD_SAFE_CALL( - _pirate_task_exit = true; - for(const std::string &mb: _mbc.keys()){ - _mbc[mb].tx_dsp->set_updates(0, 0); - } -)} +usrp2_impl::~usrp2_impl(void) +{ + UHD_SAFE_CALL(_pirate_task_exit = true; + for (const std::string& mb + : _mbc.keys()) { _mbc[mb].tx_dsp->set_updates(0, 0); }) +} -void usrp2_impl::set_db_eeprom(const std::string &mb, const std::string &type, const uhd::usrp::dboard_eeprom_t &db_eeprom){ - if (type == "rx") db_eeprom.store(*_mbc[mb].iface, USRP2_I2C_ADDR_RX_DB); - if (type == "tx") db_eeprom.store(*_mbc[mb].iface, USRP2_I2C_ADDR_TX_DB); - if (type == "gdb") db_eeprom.store(*_mbc[mb].iface, USRP2_I2C_ADDR_TX_DB ^ 5); +void usrp2_impl::set_db_eeprom(const std::string& mb, + const std::string& type, + const uhd::usrp::dboard_eeprom_t& db_eeprom) +{ + if (type == "rx") + db_eeprom.store(*_mbc[mb].iface, USRP2_I2C_ADDR_RX_DB); + if (type == "tx") + db_eeprom.store(*_mbc[mb].iface, USRP2_I2C_ADDR_TX_DB); + if (type == "gdb") + db_eeprom.store(*_mbc[mb].iface, USRP2_I2C_ADDR_TX_DB ^ 5); } -sensor_value_t usrp2_impl::get_mimo_locked(const std::string &mb){ - const bool lock = (_mbc[mb].wbiface->peek32(U2_REG_IRQ_RB) & (1<<10)) != 0; +sensor_value_t usrp2_impl::get_mimo_locked(const std::string& mb) +{ + const bool lock = (_mbc[mb].wbiface->peek32(U2_REG_IRQ_RB) & (1 << 10)) != 0; return sensor_value_t("MIMO", lock, "locked", "unlocked"); } -sensor_value_t usrp2_impl::get_ref_locked(const std::string &mb){ - const bool lock = (_mbc[mb].wbiface->peek32(U2_REG_IRQ_RB) & (1<<11)) != 0; +sensor_value_t usrp2_impl::get_ref_locked(const std::string& mb) +{ + const bool lock = (_mbc[mb].wbiface->peek32(U2_REG_IRQ_RB) & (1 << 11)) != 0; return sensor_value_t("Ref", lock, "locked", "unlocked"); } -void usrp2_impl::set_rx_fe_corrections(const std::string &mb, const double lo_freq){ - if(not _ignore_cal_file){ - apply_rx_fe_corrections(this->get_tree()->subtree("/mboards/" + mb), "A", lo_freq); +void usrp2_impl::set_rx_fe_corrections(const std::string& mb, const double lo_freq) +{ + if (not _ignore_cal_file) { + apply_rx_fe_corrections( + this->get_tree()->subtree("/mboards/" + mb), "A", lo_freq); } } -void usrp2_impl::set_tx_fe_corrections(const std::string &mb, const double lo_freq){ - if(not _ignore_cal_file){ - apply_tx_fe_corrections(this->get_tree()->subtree("/mboards/" + mb), "A", lo_freq); +void usrp2_impl::set_tx_fe_corrections(const std::string& mb, const double lo_freq) +{ + if (not _ignore_cal_file) { + apply_tx_fe_corrections( + this->get_tree()->subtree("/mboards/" + mb), "A", lo_freq); } } -double usrp2_impl::set_tx_dsp_freq( - const std::string &mb, - const double freq_ -) { - double new_freq = freq_; - const double tick_rate = - _tree->access<double>("/mboards/"+mb+"/tick_rate").get(); - - //calculate the DAC shift (multiples of rate) - const int sign = boost::math::sign(new_freq); - const int zone = std::min(boost::math::iround(new_freq/tick_rate), 2); - const double dac_shift = sign*zone*tick_rate; - new_freq -= dac_shift; //update FPGA DSP target freq +double usrp2_impl::set_tx_dsp_freq(const std::string& mb, const double freq_) +{ + double new_freq = freq_; + const double tick_rate = _tree->access<double>("/mboards/" + mb + "/tick_rate").get(); + + // calculate the DAC shift (multiples of rate) + const int sign = boost::math::sign(new_freq); + const int zone = std::min(boost::math::iround(new_freq / tick_rate), 2); + const double dac_shift = sign * zone * tick_rate; + new_freq -= dac_shift; // update FPGA DSP target freq UHD_LOG_TRACE("USRP2", - "DSP Tuning: Requested " + std::to_string(freq_/1e6) + " MHz, Using " - "Nyquist zone " + std::to_string(sign*zone) + ", leftover DSP tuning: " - + std::to_string(new_freq/1e6) + " MHz."); + "DSP Tuning: Requested " + std::to_string(freq_ / 1e6) + + " MHz, Using " + "Nyquist zone " + + std::to_string(sign * zone) + + ", leftover DSP tuning: " + std::to_string(new_freq / 1e6) + " MHz."); - //set the DAC shift (modulation mode) + // set the DAC shift (modulation mode) if (zone == 0) { - _mbc[mb].codec->set_tx_mod_mode(0); //no shift + _mbc[mb].codec->set_tx_mod_mode(0); // no shift } else { - _mbc[mb].codec->set_tx_mod_mode(sign*4/zone); //DAC interp = 4 + _mbc[mb].codec->set_tx_mod_mode(sign * 4 / zone); // DAC interp = 4 } - return _mbc[mb].tx_dsp->set_freq(new_freq) + dac_shift; //actual freq + return _mbc[mb].tx_dsp->set_freq(new_freq) + dac_shift; // actual freq } -meta_range_t usrp2_impl::get_tx_dsp_freq_range(const std::string &mb) +meta_range_t usrp2_impl::get_tx_dsp_freq_range(const std::string& mb) { - const double dac_rate = - _tree->access<double>("/mboards/" + mb + "/tick_rate").get() - * _mbc[mb].codec->get_tx_interpolation(); + const double dac_rate = _tree->access<double>("/mboards/" + mb + "/tick_rate").get() + * _mbc[mb].codec->get_tx_interpolation(); const auto dsp_range_step = _mbc[mb].tx_dsp->get_freq_range().step(); // The DSP tuning rate is the entire range of the DAC clock rate. The step // size is determined by the FPGA IP, however. - return meta_range_t( - -dac_rate / 2, - +dac_rate / 2, - dsp_range_step - ); + return meta_range_t(-dac_rate / 2, +dac_rate / 2, dsp_range_step); } #include <boost/math/special_functions/round.hpp> #include <boost/math/special_functions/sign.hpp> -void usrp2_impl::update_clock_source(const std::string &mb, const std::string &source){ - //NOTICE: U2_REG_MISC_CTRL_CLOCK is on the wb clock, and cannot be set from fifo_ctrl - //clock source ref 10mhz - switch(_mbc[mb].iface->get_rev()){ - case usrp2_iface::USRP_N200: - case usrp2_iface::USRP_N210: - case usrp2_iface::USRP_N200_R4: - case usrp2_iface::USRP_N210_R4: - if (source == "internal") _mbc[mb].iface->poke32(U2_REG_MISC_CTRL_CLOCK, 0x12); - else if (source == "external") _mbc[mb].iface->poke32(U2_REG_MISC_CTRL_CLOCK, 0x1C); - else if (source == "gpsdo") _mbc[mb].iface->poke32(U2_REG_MISC_CTRL_CLOCK, 0x1C); - else if (source == "mimo") _mbc[mb].iface->poke32(U2_REG_MISC_CTRL_CLOCK, 0x15); - else throw uhd::value_error("unhandled clock configuration reference source: " + source); - _mbc[mb].clock->enable_external_ref(true); //USRP2P has an internal 10MHz TCXO - break; - - case usrp2_iface::USRP2_REV3: - case usrp2_iface::USRP2_REV4: - if (source == "internal") _mbc[mb].iface->poke32(U2_REG_MISC_CTRL_CLOCK, 0x10); - else if (source == "external") _mbc[mb].iface->poke32(U2_REG_MISC_CTRL_CLOCK, 0x1C); - else if (source == "mimo") _mbc[mb].iface->poke32(U2_REG_MISC_CTRL_CLOCK, 0x15); - else throw uhd::value_error("unhandled clock configuration reference source: " + source); - _mbc[mb].clock->enable_external_ref(source != "internal"); - break; - - case usrp2_iface::USRP_NXXX: break; - } - - //always drive the clock over serdes if not locking to it - _mbc[mb].clock->enable_mimo_clock_out(source != "mimo"); - - //set the mimo clock delay over the serdes - if (source != "mimo"){ - switch(_mbc[mb].iface->get_rev()){ +void usrp2_impl::update_clock_source(const std::string& mb, const std::string& source) +{ + // NOTICE: U2_REG_MISC_CTRL_CLOCK is on the wb clock, and cannot be set from fifo_ctrl + // clock source ref 10mhz + switch (_mbc[mb].iface->get_rev()) { case usrp2_iface::USRP_N200: case usrp2_iface::USRP_N210: case usrp2_iface::USRP_N200_R4: case usrp2_iface::USRP_N210_R4: - _mbc[mb].clock->set_mimo_clock_delay(mimo_clock_delay_usrp_n2xx); + if (source == "internal") + _mbc[mb].iface->poke32(U2_REG_MISC_CTRL_CLOCK, 0x12); + else if (source == "external") + _mbc[mb].iface->poke32(U2_REG_MISC_CTRL_CLOCK, 0x1C); + else if (source == "gpsdo") + _mbc[mb].iface->poke32(U2_REG_MISC_CTRL_CLOCK, 0x1C); + else if (source == "mimo") + _mbc[mb].iface->poke32(U2_REG_MISC_CTRL_CLOCK, 0x15); + else + throw uhd::value_error( + "unhandled clock configuration reference source: " + source); + _mbc[mb].clock->enable_external_ref(true); // USRP2P has an internal 10MHz + // TCXO break; + case usrp2_iface::USRP2_REV3: case usrp2_iface::USRP2_REV4: - _mbc[mb].clock->set_mimo_clock_delay(mimo_clock_delay_usrp2_rev4); + if (source == "internal") + _mbc[mb].iface->poke32(U2_REG_MISC_CTRL_CLOCK, 0x10); + else if (source == "external") + _mbc[mb].iface->poke32(U2_REG_MISC_CTRL_CLOCK, 0x1C); + else if (source == "mimo") + _mbc[mb].iface->poke32(U2_REG_MISC_CTRL_CLOCK, 0x15); + else + throw uhd::value_error( + "unhandled clock configuration reference source: " + source); + _mbc[mb].clock->enable_external_ref(source != "internal"); break; - default: break; //not handled + case usrp2_iface::USRP_NXXX: + break; + } + + // always drive the clock over serdes if not locking to it + _mbc[mb].clock->enable_mimo_clock_out(source != "mimo"); + + // set the mimo clock delay over the serdes + if (source != "mimo") { + switch (_mbc[mb].iface->get_rev()) { + case usrp2_iface::USRP_N200: + case usrp2_iface::USRP_N210: + case usrp2_iface::USRP_N200_R4: + case usrp2_iface::USRP_N210_R4: + _mbc[mb].clock->set_mimo_clock_delay(mimo_clock_delay_usrp_n2xx); + break; + + case usrp2_iface::USRP2_REV4: + _mbc[mb].clock->set_mimo_clock_delay(mimo_clock_delay_usrp2_rev4); + break; + + default: + break; // not handled } } } diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 9e4e507de..792c38a11 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -8,71 +8,71 @@ #ifndef INCLUDED_USRP2_IMPL_HPP #define INCLUDED_USRP2_IMPL_HPP -#include "usrp2_iface.hpp" -#include "usrp2_fifo_ctrl.hpp" #include "clock_ctrl.hpp" #include "codec_ctrl.hpp" -#include <uhdlib/usrp/cores/rx_frontend_core_200.hpp> -#include <uhdlib/usrp/cores/tx_frontend_core_200.hpp> -#include <uhdlib/usrp/cores/rx_dsp_core_200.hpp> -#include <uhdlib/usrp/cores/tx_dsp_core_200.hpp> -#include <uhdlib/usrp/cores/time64_core_200.hpp> -#include <uhdlib/usrp/cores/user_settings_core_200.hpp> -#include <uhdlib/usrp/cores/gpio_core_200.hpp> -#include <uhd/property_tree.hpp> -#include <uhd/usrp/gps_ctrl.hpp> +#include "usrp2_fifo_ctrl.hpp" +#include "usrp2_iface.hpp" #include <uhd/device.hpp> -#include <uhd/utils/pimpl.hpp> -#include <uhd/types/dict.hpp> -#include <uhd/types/stream_cmd.hpp> -#include <uhd/usrp/dboard_eeprom.hpp> -#include <uhd/transport/vrt_if_packet.hpp> +#include <uhd/property_tree.hpp> #include <uhd/transport/udp_simple.hpp> #include <uhd/transport/udp_zero_copy.hpp> +#include <uhd/transport/vrt_if_packet.hpp> #include <uhd/types/device_addr.hpp> +#include <uhd/types/dict.hpp> +#include <uhd/types/stream_cmd.hpp> +#include <uhd/usrp/dboard_eeprom.hpp> #include <uhd/usrp/dboard_manager.hpp> +#include <uhd/usrp/gps_ctrl.hpp> #include <uhd/usrp/subdev_spec.hpp> -#include <memory> -#include <functional> +#include <uhd/utils/pimpl.hpp> +#include <uhdlib/usrp/cores/gpio_core_200.hpp> +#include <uhdlib/usrp/cores/rx_dsp_core_200.hpp> +#include <uhdlib/usrp/cores/rx_frontend_core_200.hpp> +#include <uhdlib/usrp/cores/time64_core_200.hpp> +#include <uhdlib/usrp/cores/tx_dsp_core_200.hpp> +#include <uhdlib/usrp/cores/tx_frontend_core_200.hpp> +#include <uhdlib/usrp/cores/user_settings_core_200.hpp> #include <atomic> +#include <functional> +#include <memory> -static const double USRP2_LINK_RATE_BPS = 1000e6/8; -static const double mimo_clock_delay_usrp2_rev4 = 4.18e-9; -static const double mimo_clock_delay_usrp_n2xx = 4.10e-9; +static const double USRP2_LINK_RATE_BPS = 1000e6 / 8; +static const double mimo_clock_delay_usrp2_rev4 = 4.18e-9; +static const double mimo_clock_delay_usrp_n2xx = 4.10e-9; static const size_t mimo_clock_sync_delay_cycles = 138; -static const size_t USRP2_SRAM_BYTES = size_t(1 << 20); -static const uint32_t USRP2_TX_ASYNC_SID = 2; -static const uint32_t USRP2_RX_SID_BASE = 3; +static const size_t USRP2_SRAM_BYTES = size_t(1 << 20); +static const uint32_t USRP2_TX_ASYNC_SID = 2; +static const uint32_t USRP2_RX_SID_BASE = 3; -uhd::device_addrs_t usrp2_find(const uhd::device_addr_t &hint_); +uhd::device_addrs_t usrp2_find(const uhd::device_addr_t& hint_); //! Make a usrp2 dboard interface. -uhd::usrp::dboard_iface::sptr make_usrp2_dboard_iface( - uhd::timed_wb_iface::sptr wb_iface, +uhd::usrp::dboard_iface::sptr make_usrp2_dboard_iface(uhd::timed_wb_iface::sptr wb_iface, uhd::i2c_iface::sptr i2c_iface, uhd::spi_iface::sptr spi_iface, - usrp2_clock_ctrl::sptr clk_ctrl -); + usrp2_clock_ctrl::sptr clk_ctrl); /*! * USRP2 implementation guts: * The implementation details are encapsulated here. * Handles device properties and streaming... */ -class usrp2_impl : public uhd::device{ +class usrp2_impl : public uhd::device +{ public: - usrp2_impl(const uhd::device_addr_t &); + usrp2_impl(const uhd::device_addr_t&); ~usrp2_impl(void); - //the io interface - uhd::rx_streamer::sptr get_rx_stream(const uhd::stream_args_t &args); - uhd::tx_streamer::sptr get_tx_stream(const uhd::stream_args_t &args); - bool recv_async_msg(uhd::async_metadata_t &, double); + // the io interface + uhd::rx_streamer::sptr get_rx_stream(const uhd::stream_args_t& args); + uhd::tx_streamer::sptr get_tx_stream(const uhd::stream_args_t& args); + bool recv_async_msg(uhd::async_metadata_t&, double); - static uhd::usrp::mboard_eeprom_t get_mb_eeprom(usrp2_iface &); + static uhd::usrp::mboard_eeprom_t get_mb_eeprom(usrp2_iface&); private: - struct mb_container_type{ + struct mb_container_type + { usrp2_iface::sptr iface; usrp2_fifo_ctrl::sptr fifo_ctrl; uhd::spi_iface::sptr spiface; @@ -83,8 +83,8 @@ private: rx_frontend_core_200::sptr rx_fe; tx_frontend_core_200::sptr tx_fe; std::vector<rx_dsp_core_200::sptr> rx_dsps; - std::vector<std::weak_ptr<uhd::rx_streamer> > rx_streamers; - std::vector<std::weak_ptr<uhd::tx_streamer> > tx_streamers; + std::vector<std::weak_ptr<uhd::rx_streamer>> rx_streamers; + std::vector<std::weak_ptr<uhd::tx_streamer>> tx_streamers; tx_dsp_core_200::sptr tx_dsp; time64_core_200::sptr time64; user_settings_core_200::sptr user; @@ -93,36 +93,38 @@ private: uhd::transport::zero_copy_if::sptr fifo_ctrl_xport; uhd::usrp::dboard_manager::sptr dboard_manager; size_t rx_chan_occ, tx_chan_occ; - mb_container_type(void): rx_chan_occ(0), tx_chan_occ(0){} + mb_container_type(void) : rx_chan_occ(0), tx_chan_occ(0) {} }; uhd::dict<std::string, mb_container_type> _mbc; - void set_mb_eeprom(const std::string &, const uhd::usrp::mboard_eeprom_t &); - void set_db_eeprom(const std::string &, const std::string &, const uhd::usrp::dboard_eeprom_t &); + void set_mb_eeprom(const std::string&, const uhd::usrp::mboard_eeprom_t&); + void set_db_eeprom( + const std::string&, const std::string&, const uhd::usrp::dboard_eeprom_t&); - uhd::sensor_value_t get_mimo_locked(const std::string &); - uhd::sensor_value_t get_ref_locked(const std::string &); + uhd::sensor_value_t get_mimo_locked(const std::string&); + uhd::sensor_value_t get_ref_locked(const std::string&); - void set_rx_fe_corrections(const std::string &mb, const double); - void set_tx_fe_corrections(const std::string &mb, const double); + void set_rx_fe_corrections(const std::string& mb, const double); + void set_tx_fe_corrections(const std::string& mb, const double); bool _ignore_cal_file; - //io impl methods and members + // io impl methods and members uhd::device_addr_t device_addr; UHD_PIMPL_DECL(io_impl) _io_impl; std::atomic<bool> _pirate_task_exit; void io_init(void); void update_tick_rate(const double rate); - void update_rx_samp_rate(const std::string &, const size_t, const double rate); - void update_tx_samp_rate(const std::string &, const size_t, const double rate); + void update_rx_samp_rate(const std::string&, const size_t, const double rate); + void update_tx_samp_rate(const std::string&, const size_t, const double rate); void update_rates(void); - //update spec methods are coercers until we only accept db_name == A - void update_rx_subdev_spec(const std::string &, const uhd::usrp::subdev_spec_t &); - void update_tx_subdev_spec(const std::string &, const uhd::usrp::subdev_spec_t &); - double set_tx_dsp_freq(const std::string &, const double); - uhd::meta_range_t get_tx_dsp_freq_range(const std::string &); - void update_clock_source(const std::string &, const std::string &); - void program_stream_dest(uhd::transport::zero_copy_if::sptr &, const uhd::stream_args_t &); + // update spec methods are coercers until we only accept db_name == A + void update_rx_subdev_spec(const std::string&, const uhd::usrp::subdev_spec_t&); + void update_tx_subdev_spec(const std::string&, const uhd::usrp::subdev_spec_t&); + double set_tx_dsp_freq(const std::string&, const double); + uhd::meta_range_t get_tx_dsp_freq_range(const std::string&); + void update_clock_source(const std::string&, const std::string&); + void program_stream_dest( + uhd::transport::zero_copy_if::sptr&, const uhd::stream_args_t&); }; #endif /* INCLUDED_USRP2_IMPL_HPP */ diff --git a/host/lib/usrp/usrp2/usrp2_regs.hpp b/host/lib/usrp/usrp2/usrp2_regs.hpp index f26b33ecb..6fc973cdf 100644 --- a/host/lib/usrp/usrp2/usrp2_regs.hpp +++ b/host/lib/usrp/usrp2/usrp2_regs.hpp @@ -11,37 +11,37 @@ //////////////////////////////////////////////////////////////////////// // Define slave bases //////////////////////////////////////////////////////////////////////// -#define ROUTER_RAM_BASE 0x4000 -#define SPI_BASE 0x5000 -#define I2C_BASE 0x5400 -#define GPIO_BASE 0x5800 -#define READBACK_BASE 0x5C00 -#define ETH_BASE 0x6000 -#define SETTING_REGS_BASE 0x7000 -#define PIC_BASE 0x8000 -#define UART_BASE 0x8800 -#define ATR_BASE 0x8C00 +#define ROUTER_RAM_BASE 0x4000 +#define SPI_BASE 0x5000 +#define I2C_BASE 0x5400 +#define GPIO_BASE 0x5800 +#define READBACK_BASE 0x5C00 +#define ETH_BASE 0x6000 +#define SETTING_REGS_BASE 0x7000 +#define PIC_BASE 0x8000 +#define UART_BASE 0x8800 +#define ATR_BASE 0x8C00 //////////////////////////////////////////////////////////////////////// // Setting register offsets //////////////////////////////////////////////////////////////////////// -#define SR_MISC 0 // 7 regs -#define SR_USER_REGS 8 // 2 -#define SR_TIME64 10 // 6 -#define SR_BUF_POOL 16 // 4 -#define SR_SPI_CORE 20 // 3 -#define SR_RX_FRONT 24 // 5 -#define SR_RX_CTRL0 32 // 9 -#define SR_RX_DSP0 48 // 7 -#define SR_RX_CTRL1 80 // 9 -#define SR_RX_DSP1 96 // 7 +#define SR_MISC 0 // 7 regs +#define SR_USER_REGS 8 // 2 +#define SR_TIME64 10 // 6 +#define SR_BUF_POOL 16 // 4 +#define SR_SPI_CORE 20 // 3 +#define SR_RX_FRONT 24 // 5 +#define SR_RX_CTRL0 32 // 9 +#define SR_RX_DSP0 48 // 7 +#define SR_RX_CTRL1 80 // 9 +#define SR_RX_DSP1 96 // 7 -#define SR_TX_FRONT 128 // ? -#define SR_TX_CTRL 144 // 6 -#define SR_TX_DSP 160 // 5 +#define SR_TX_FRONT 128 // ? +#define SR_TX_CTRL 144 // 6 +#define SR_TX_DSP 160 // 5 -#define SR_GPIO 184 -#define SR_UDP_SM 192 // 64 +#define SR_GPIO 184 +#define SR_UDP_SM 192 // 64 #define U2_REG_SR_ADDR(sr) (SETTING_REGS_BASE + (4 * (sr))) @@ -51,15 +51,15 @@ // SPI Slave Constants //////////////////////////////////////////////// // Masks for controlling different peripherals -#define SPI_SS_AD9510 1 -#define SPI_SS_AD9777 2 -#define SPI_SS_RX_DAC 4 -#define SPI_SS_RX_ADC 8 -#define SPI_SS_RX_DB 16 -#define SPI_SS_TX_DAC 32 -#define SPI_SS_TX_ADC 64 -#define SPI_SS_TX_DB 128 -#define SPI_SS_ADS62P44 256 //for usrp2p +#define SPI_SS_AD9510 1 +#define SPI_SS_AD9777 2 +#define SPI_SS_RX_DAC 4 +#define SPI_SS_RX_ADC 8 +#define SPI_SS_RX_DB 16 +#define SPI_SS_TX_DAC 32 +#define SPI_SS_TX_ADC 64 +#define SPI_SS_TX_DB 128 +#define SPI_SS_ADS62P44 256 // for usrp2p ///////////////////////////////////////////////// // Misc Control @@ -77,21 +77,21 @@ #define U2_FLAG_MISC_CTRL_SERDES_ENABLE 8 #define U2_FLAG_MISC_CTRL_SERDES_PRBSEN 4 #define U2_FLAG_MISC_CTRL_SERDES_LOOPEN 2 -#define U2_FLAG_MISC_CTRL_SERDES_RXEN 1 +#define U2_FLAG_MISC_CTRL_SERDES_RXEN 1 -#define U2_FLAG_MISC_CTRL_ADC_ON 0x0F +#define U2_FLAG_MISC_CTRL_ADC_ON 0x0F #define U2_FLAG_MISC_CTRL_ADC_OFF 0x00 ///////////////////////////////////////////////// // Readback regs //////////////////////////////////////////////// -#define U2_REG_STATUS READBACK_BASE + 4*8 -#define U2_REG_GPIO_RB READBACK_BASE + 4*9 -#define U2_REG_TIME64_HI_RB_IMM READBACK_BASE + 4*10 -#define U2_REG_TIME64_LO_RB_IMM READBACK_BASE + 4*11 -#define U2_REG_COMPAT_NUM_RB READBACK_BASE + 4*12 -#define U2_REG_IRQ_RB READBACK_BASE + 4*13 -#define U2_REG_TIME64_HI_RB_PPS READBACK_BASE + 4*14 -#define U2_REG_TIME64_LO_RB_PPS READBACK_BASE + 4*15 +#define U2_REG_STATUS READBACK_BASE + 4 * 8 +#define U2_REG_GPIO_RB READBACK_BASE + 4 * 9 +#define U2_REG_TIME64_HI_RB_IMM READBACK_BASE + 4 * 10 +#define U2_REG_TIME64_LO_RB_IMM READBACK_BASE + 4 * 11 +#define U2_REG_COMPAT_NUM_RB READBACK_BASE + 4 * 12 +#define U2_REG_IRQ_RB READBACK_BASE + 4 * 13 +#define U2_REG_TIME64_HI_RB_PPS READBACK_BASE + 4 * 14 +#define U2_REG_TIME64_LO_RB_PPS READBACK_BASE + 4 * 15 #endif /* INCLUDED_USRP2_REGS_HPP */ |