diff options
| -rw-r--r-- | host/lib/usrp/x300/x300_adc_dac_utils.cpp | 68 | ||||
| -rw-r--r-- | host/lib/usrp/x300/x300_impl.cpp | 143 | ||||
| -rw-r--r-- | host/lib/usrp/x300/x300_impl.hpp | 52 | ||||
| -rw-r--r-- | host/lib/usrp/x300/x300_regs.hpp | 109 | 
4 files changed, 196 insertions, 176 deletions
diff --git a/host/lib/usrp/x300/x300_adc_dac_utils.cpp b/host/lib/usrp/x300/x300_adc_dac_utils.cpp index 2dadea26e..b1483b3a5 100644 --- a/host/lib/usrp/x300/x300_adc_dac_utils.cpp +++ b/host/lib/usrp/x300/x300_adc_dac_utils.cpp @@ -18,6 +18,8 @@  #include "x300_impl.hpp"  #include <boost/date_time/posix_time/posix_time_io.hpp> +using namespace uhd::usrp::x300; +  /***********************************************************************   * DAC: Reset and synchronization operations   **********************************************************************/ @@ -101,8 +103,8 @@ void x300_impl::self_test_adcs(mboard_members_t& mb, boost::uint32_t ramp_time_m          //Turn on ramp pattern test          perif.adc->set_test_word("ramp", "ramp"); -        perif.misc_outs->write(radio_misc_outs_reg::ADC_CHECKER_ENABLED, 0); -        perif.misc_outs->write(radio_misc_outs_reg::ADC_CHECKER_ENABLED, 1); +        perif.regmap->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 0); +        perif.regmap->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 1);      }      boost::this_thread::sleep(boost::posix_time::milliseconds(ramp_time_ms)); @@ -110,19 +112,19 @@ void x300_impl::self_test_adcs(mboard_members_t& mb, boost::uint32_t ramp_time_m      std::string status_str;      for (size_t r = 0; r < mboard_members_t::NUM_RADIOS; r++) {          radio_perifs_t &perif = mb.radio_perifs[r]; -        perif.misc_ins->refresh(); +        perif.regmap->misc_ins_reg.refresh();          std::string i_status, q_status; -        if (perif.misc_ins->get(radio_misc_ins_reg::ADC_CHECKER1_I_LOCKED)) -            if (perif.misc_ins->get(radio_misc_ins_reg::ADC_CHECKER1_I_ERROR)) +        if (perif.regmap->misc_ins_reg.get(radio_regmap_t::misc_ins_reg_t::ADC_CHECKER1_I_LOCKED)) +            if (perif.regmap->misc_ins_reg.get(radio_regmap_t::misc_ins_reg_t::ADC_CHECKER1_I_ERROR))                  i_status = "Bit Errors!";              else                  i_status = "Good";          else              i_status = "Not Locked!"; -        if (perif.misc_ins->get(radio_misc_ins_reg::ADC_CHECKER1_Q_LOCKED)) -            if (perif.misc_ins->get(radio_misc_ins_reg::ADC_CHECKER1_Q_ERROR)) +        if (perif.regmap->misc_ins_reg.get(radio_regmap_t::misc_ins_reg_t::ADC_CHECKER1_Q_LOCKED)) +            if (perif.regmap->misc_ins_reg.get(radio_regmap_t::misc_ins_reg_t::ADC_CHECKER1_Q_ERROR))                  q_status = "Bit Errors!";              else                  q_status = "Good"; @@ -193,9 +195,9 @@ void x300_impl::self_cal_adc_capture_delay(mboard_members_t& mb, const size_t ra      while (iter++ < NUM_RETRIES) {          for (boost::uint32_t dly_tap = 0; dly_tap < NUM_DELAY_STEPS; dly_tap++) {              //Apply delay -            perif.misc_outs->write(radio_misc_outs_reg::ADC_DATA_DLY_VAL, dly_tap); -            perif.misc_outs->write(radio_misc_outs_reg::ADC_DATA_DLY_STB, 1); -            perif.misc_outs->write(radio_misc_outs_reg::ADC_DATA_DLY_STB, 0); +            perif.regmap->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_DATA_DLY_VAL, dly_tap); +            perif.regmap->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_DATA_DLY_STB, 1); +            perif.regmap->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_DATA_DLY_STB, 0);              boost::uint32_t err_code = 0; @@ -204,12 +206,12 @@ void x300_impl::self_cal_adc_capture_delay(mboard_members_t& mb, const size_t ra              perif.adc->set_test_word("ramp", "ones");              //Turn on the pattern checker in the FPGA. It will lock when it sees a zero              //and count deviations from the expected value -            perif.misc_outs->write(radio_misc_outs_reg::ADC_CHECKER_ENABLED, 0); -            perif.misc_outs->write(radio_misc_outs_reg::ADC_CHECKER_ENABLED, 1); +            perif.regmap->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 0); +            perif.regmap->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 1);              //10ms @ 200MHz = 2 million samples              boost::this_thread::sleep(boost::posix_time::milliseconds(10)); -            if (perif.misc_ins->read(radio_misc_ins_reg::ADC_CHECKER0_I_LOCKED)) { -                err_code += perif.misc_ins->get(radio_misc_ins_reg::ADC_CHECKER0_I_ERROR); +            if (perif.regmap->misc_ins_reg.read(radio_regmap_t::misc_ins_reg_t::ADC_CHECKER0_I_LOCKED)) { +                err_code += perif.regmap->misc_ins_reg.get(radio_regmap_t::misc_ins_reg_t::ADC_CHECKER0_I_ERROR);              } else {                  err_code += 100;    //Increment error code by 100 to indicate no lock              } @@ -219,12 +221,12 @@ void x300_impl::self_cal_adc_capture_delay(mboard_members_t& mb, const size_t ra              perif.adc->set_test_word("ones", "ramp");              //Turn on the pattern checker in the FPGA. It will lock when it sees a zero              //and count deviations from the expected value -            perif.misc_outs->write(radio_misc_outs_reg::ADC_CHECKER_ENABLED, 0); -            perif.misc_outs->write(radio_misc_outs_reg::ADC_CHECKER_ENABLED, 1); +            perif.regmap->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 0); +            perif.regmap->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 1);              //10ms @ 200MHz = 2 million samples              boost::this_thread::sleep(boost::posix_time::milliseconds(10)); -            if (perif.misc_ins->read(radio_misc_ins_reg::ADC_CHECKER0_Q_LOCKED)) { -                err_code += perif.misc_ins->get(radio_misc_ins_reg::ADC_CHECKER0_Q_ERROR); +            if (perif.regmap->misc_ins_reg.read(radio_regmap_t::misc_ins_reg_t::ADC_CHECKER0_Q_LOCKED)) { +                err_code += perif.regmap->misc_ins_reg.get(radio_regmap_t::misc_ins_reg_t::ADC_CHECKER0_Q_ERROR);              } else {                  err_code += 100;    //Increment error code by 100 to indicate no lock              } @@ -258,7 +260,7 @@ void x300_impl::self_cal_adc_capture_delay(mboard_members_t& mb, const size_t ra          }      }      perif.adc->set_test_word("normal", "normal"); -    perif.misc_outs->write(radio_misc_outs_reg::ADC_CHECKER_ENABLED, 0); +    perif.regmap->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 0);      if (win_start == -1) {          throw uhd::runtime_error("self_cal_adc_capture_delay: Self calibration failed. Convergence error."); @@ -269,9 +271,9 @@ void x300_impl::self_cal_adc_capture_delay(mboard_members_t& mb, const size_t ra      }      boost::uint32_t ideal_tap = (win_stop + win_start) / 2; -    perif.misc_outs->write(radio_misc_outs_reg::ADC_DATA_DLY_VAL, ideal_tap); -    perif.misc_outs->write(radio_misc_outs_reg::ADC_DATA_DLY_STB, 1); -    perif.misc_outs->write(radio_misc_outs_reg::ADC_DATA_DLY_STB, 0); +    perif.regmap->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_DATA_DLY_VAL, ideal_tap); +    perif.regmap->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_DATA_DLY_STB, 1); +    perif.regmap->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_DATA_DLY_STB, 0);      if (print_status) {          double tap_delay = (1.0e12 / mb.clock->get_master_clock_rate()) / (2*32); //in ps @@ -300,7 +302,7 @@ double x300_impl::self_cal_adc_xfer_delay(mboard_members_t& mb, bool apply_delay      for (size_t i = 0; i < NUM_DELAY_STEPS; i++) {          //Delay the ADC clock (will set both Ch0 and Ch1 delays)          double delay = mb.clock->set_clock_delay(X300_CLOCK_WHICH_ADC0, delay_incr*i + delay_start); -        wait_for_clk_locked(mb.zpu_ctrl, ZPU_RB_CLK_STATUS_LMK_LOCK, 0.1); +        wait_for_clk_locked(mb, fw_regmap_t::clk_status_reg_t::LMK_LOCK, 0.1);          boost::uint32_t err_code = 0;          for (size_t r = 0; r < mboard_members_t::NUM_RADIOS; r++) { @@ -312,12 +314,12 @@ double x300_impl::self_cal_adc_xfer_delay(mboard_members_t& mb, bool apply_delay              mb.radio_perifs[r].adc->set_test_word("ramp", "ones");              //Turn on the pattern checker in the FPGA. It will lock when it sees a zero              //and count deviations from the expected value -            mb.radio_perifs[r].misc_outs->write(radio_misc_outs_reg::ADC_CHECKER_ENABLED, 0); -            mb.radio_perifs[r].misc_outs->write(radio_misc_outs_reg::ADC_CHECKER_ENABLED, 1); +            mb.radio_perifs[r].regmap->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 0); +            mb.radio_perifs[r].regmap->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 1);              //50ms @ 200MHz = 10 million samples              boost::this_thread::sleep(boost::posix_time::milliseconds(50)); -            if (mb.radio_perifs[r].misc_ins->read(radio_misc_ins_reg::ADC_CHECKER1_I_LOCKED)) { -                err_code += mb.radio_perifs[r].misc_ins->get(radio_misc_ins_reg::ADC_CHECKER1_I_ERROR); +            if (mb.radio_perifs[r].regmap->misc_ins_reg.read(radio_regmap_t::misc_ins_reg_t::ADC_CHECKER1_I_LOCKED)) { +                err_code += mb.radio_perifs[r].regmap->misc_ins_reg.get(radio_regmap_t::misc_ins_reg_t::ADC_CHECKER1_I_ERROR);              } else {                  err_code += 100;    //Increment error code by 100 to indicate no lock              } @@ -327,12 +329,12 @@ double x300_impl::self_cal_adc_xfer_delay(mboard_members_t& mb, bool apply_delay              mb.radio_perifs[r].adc->set_test_word("ones", "ramp");              //Turn on the pattern checker in the FPGA. It will lock when it sees a zero              //and count deviations from the expected value -            mb.radio_perifs[r].misc_outs->write(radio_misc_outs_reg::ADC_CHECKER_ENABLED, 0); -            mb.radio_perifs[r].misc_outs->write(radio_misc_outs_reg::ADC_CHECKER_ENABLED, 1); +            mb.radio_perifs[r].regmap->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 0); +            mb.radio_perifs[r].regmap->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 1);              //50ms @ 200MHz = 10 million samples              boost::this_thread::sleep(boost::posix_time::milliseconds(50)); -            if (mb.radio_perifs[r].misc_ins->read(radio_misc_ins_reg::ADC_CHECKER1_Q_LOCKED)) { -                err_code += mb.radio_perifs[r].misc_ins->get(radio_misc_ins_reg::ADC_CHECKER1_Q_ERROR); +            if (mb.radio_perifs[r].regmap->misc_ins_reg.read(radio_regmap_t::misc_ins_reg_t::ADC_CHECKER1_Q_LOCKED)) { +                err_code += mb.radio_perifs[r].regmap->misc_ins_reg.get(radio_regmap_t::misc_ins_reg_t::ADC_CHECKER1_Q_ERROR);              } else {                  err_code += 100;    //Increment error code by 100 to indicate no lock              } @@ -392,7 +394,7 @@ double x300_impl::self_cal_adc_xfer_delay(mboard_members_t& mb, bool apply_delay          UHD_MSG(status) << "Validating..." << std::flush;          //Apply delay          win_center = mb.clock->set_clock_delay(X300_CLOCK_WHICH_ADC0, win_center);  //Sets ADC0 and ADC1 -        wait_for_clk_locked(mb.zpu_ctrl, ZPU_RB_CLK_STATUS_LMK_LOCK, 0.1); +        wait_for_clk_locked(mb, fw_regmap_t::clk_status_reg_t::LMK_LOCK, 0.1);          //Validate          self_test_adcs(mb, 2000);      } else { @@ -403,7 +405,7 @@ double x300_impl::self_cal_adc_xfer_delay(mboard_members_t& mb, bool apply_delay      //Teardown      for (size_t r = 0; r < mboard_members_t::NUM_RADIOS; r++) {          mb.radio_perifs[r].adc->set_test_word("normal", "normal"); -        mb.radio_perifs[r].misc_outs->write(radio_misc_outs_reg::ADC_CHECKER_ENABLED, 0); +        mb.radio_perifs[r].regmap->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 0);      }      UHD_MSG(status) << (boost::format(" done (FPGA->ADC=%.3fns%s, Window=%.3fns)\n") %          (win_center-fpga_clk_delay) % (cycle_slip?" +cyc":"") % win_length); diff --git a/host/lib/usrp/x300/x300_impl.cpp b/host/lib/usrp/x300/x300_impl.cpp index f0332691d..437fec82d 100644 --- a/host/lib/usrp/x300/x300_impl.cpp +++ b/host/lib/usrp/x300/x300_impl.cpp @@ -46,6 +46,7 @@ using namespace uhd;  using namespace uhd::usrp;  using namespace uhd::transport;  using namespace uhd::niusrprio; +using namespace uhd::usrp::x300;  namespace asio = boost::asio;  /*********************************************************************** @@ -512,6 +513,9 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr)      this->check_fpga_compat(mb_path, mb);      this->check_fw_compat(mb_path, mb.zpu_ctrl); +    mb.fw_regmap = boost::make_shared<fw_regmap_t>(); +    mb.fw_regmap->initialize(*mb.zpu_ctrl.get(), true); +      //store which FPGA image is loaded      mb.loaded_fpga_image = get_fpga_option(mb.zpu_ctrl); @@ -663,7 +667,6 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr)      UHD_MSG(status) << "Setup RF frontend clocking..." << std::endl;      //Initialize clock control registers. NOTE: This does not configure the LMK yet. -    initialize_clock_control(mb);      mb.clock = x300_clock_ctrl::make(mb.zpu_spi,          1 /*slaveno*/,          mb.hw_rev, @@ -842,7 +845,7 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr)      // and do the misc mboard sensors      ////////////////////////////////////////////////////////////////////      _tree->create<sensor_value_t>(mb_path / "sensors" / "ref_locked") -        .publish(boost::bind(&x300_impl::get_ref_locked, this, mb.zpu_ctrl)); +        .publish(boost::bind(&x300_impl::get_ref_locked, this, mb));      ////////////////////////////////////////////////////////////////////      // do some post-init tasks @@ -860,6 +863,14 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr)      _tree->access<subdev_spec_t>(mb_path / "rx_subdev_spec").set(rx_fe_spec);      _tree->access<subdev_spec_t>(mb_path / "tx_subdev_spec").set(tx_fe_spec); +    mb.regmap_db = boost::make_shared<uhd::soft_regmap_db_t>(); +    mb.regmap_db->add(*mb.fw_regmap); +    mb.regmap_db->add(*mb.radio_perifs[0].regmap); +    mb.regmap_db->add(*mb.radio_perifs[1].regmap); + +    _tree->create<uhd::soft_regmap_accessor_t::sptr>(mb_path / "registers") +        .set(mb.regmap_db); +      mb.initialization_done = true;  } @@ -870,12 +881,12 @@ x300_impl::~x300_impl(void)          BOOST_FOREACH(mboard_members_t &mb, _mb)          {              //Disable/reset ADC/DAC -            mb.radio_perifs[0].misc_outs->set(radio_misc_outs_reg::ADC_RESET, 1); -            mb.radio_perifs[0].misc_outs->set(radio_misc_outs_reg::DAC_RESET_N, 0); -            mb.radio_perifs[0].misc_outs->set(radio_misc_outs_reg::DAC_ENABLED, 0); -            mb.radio_perifs[0].misc_outs->flush(); -            mb.radio_perifs[1].misc_outs->set(radio_misc_outs_reg::DAC_ENABLED, 0); -            mb.radio_perifs[1].misc_outs->flush(); +            mb.radio_perifs[0].regmap->misc_outs_reg.set(radio_regmap_t::misc_outs_reg_t::ADC_RESET, 1); +            mb.radio_perifs[0].regmap->misc_outs_reg.set(radio_regmap_t::misc_outs_reg_t::DAC_RESET_N, 0); +            mb.radio_perifs[0].regmap->misc_outs_reg.set(radio_regmap_t::misc_outs_reg_t::DAC_ENABLED, 0); +            mb.radio_perifs[0].regmap->misc_outs_reg.flush(); +            mb.radio_perifs[1].regmap->misc_outs_reg.set(radio_regmap_t::misc_outs_reg_t::DAC_ENABLED, 0); +            mb.radio_perifs[1].regmap->misc_outs_reg.flush();              //kill the claimer task and unclaim the device              mb.claimer_task.reset(); @@ -913,21 +924,19 @@ void x300_impl::setup_radio(const size_t mb_i, const std::string &slot_name, con      both_xports_t xport = this->make_transport(mb_i, dest, X300_RADIO_DEST_PREFIX_CTRL, device_addr_t(), ctrl_sid);      perif.ctrl = radio_ctrl_core_3000::make(mb.if_pkt_is_big_endian, xport.recv, xport.send, ctrl_sid, slot_name); -    perif.misc_outs = boost::make_shared<radio_misc_outs_reg>(); -    perif.misc_ins = boost::make_shared<radio_misc_ins_reg>(); -    perif.misc_outs->initialize(*perif.ctrl, true); -    perif.misc_ins->initialize(*perif.ctrl); +    perif.regmap = boost::make_shared<radio_regmap_t>(radio_index); +    perif.regmap->initialize(*perif.ctrl, true);      //Only Radio0 has the ADC/DAC reset bits. Those bits are reserved for Radio1      if (radio_index == 0) { -        perif.misc_outs->set(radio_misc_outs_reg::ADC_RESET, 1); -        perif.misc_outs->set(radio_misc_outs_reg::DAC_RESET_N, 0); -        perif.misc_outs->flush(); -        perif.misc_outs->set(radio_misc_outs_reg::ADC_RESET, 0); -        perif.misc_outs->set(radio_misc_outs_reg::DAC_RESET_N, 1); -        perif.misc_outs->flush(); +        perif.regmap->misc_outs_reg.set(radio_regmap_t::misc_outs_reg_t::ADC_RESET, 1); +        perif.regmap->misc_outs_reg.set(radio_regmap_t::misc_outs_reg_t::DAC_RESET_N, 0); +        perif.regmap->misc_outs_reg.flush(); +        perif.regmap->misc_outs_reg.set(radio_regmap_t::misc_outs_reg_t::ADC_RESET, 0); +        perif.regmap->misc_outs_reg.set(radio_regmap_t::misc_outs_reg_t::DAC_RESET_N, 1); +        perif.regmap->misc_outs_reg.flush();      } -    perif.misc_outs->write(radio_misc_outs_reg::DAC_ENABLED, 1); +    perif.regmap->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::DAC_ENABLED, 1);      this->register_loopback_self_test(perif.ctrl); @@ -1345,32 +1354,9 @@ void x300_impl::register_loopback_self_test(wb_iface::sptr iface)   * clock and time control logic   **********************************************************************/ -void x300_impl::update_clock_control(mboard_members_t &mb) -{ -    const size_t reg = mb.clock_control_regs_clock_source -        | (mb.clock_control_regs_pps_select << 2) -        | (mb.clock_control_regs_pps_out_enb << 4) -        | (mb.clock_control_regs_tcxo_enb << 5) -        | (mb.clock_control_regs_gpsdo_pwr << 6) -    ; -    mb.zpu_ctrl->poke32(SR_ADDR(SET0_BASE, ZPU_SR_CLOCK_CTRL), reg); -} - -void x300_impl::initialize_clock_control(mboard_members_t &mb) -{ -    //Initialize clock control register soft copies -    mb.clock_control_regs_clock_source = ZPU_SR_CLOCK_CTRL_CLK_SRC_INTERNAL; -    mb.clock_control_regs_pps_select = ZPU_SR_CLOCK_CTRL_PPS_SRC_INTERNAL; -    mb.clock_control_regs_pps_out_enb = 0; -    mb.clock_control_regs_tcxo_enb = 1; -    mb.clock_control_regs_gpsdo_pwr = 1;    //GPSDO power always ON -    this->update_clock_control(mb); -} -  void x300_impl::set_time_source_out(mboard_members_t &mb, const bool enb)  { -    mb.clock_control_regs_pps_out_enb = enb? 1 : 0; -    this->update_clock_control(mb); +    mb.fw_regmap->clock_ctrl_reg.write(fw_regmap_t::fw_regmap_t::clk_ctrl_reg_t::PPS_OUT_EN, enb?1:0);  }  void x300_impl::update_clock_source(mboard_members_t &mb, const std::string &source) @@ -1381,19 +1367,19 @@ void x300_impl::update_clock_source(mboard_members_t &mb, const std::string &sou      const bool reconfigure_clks = (mb.current_refclk_src != "internal") or (source != "internal");      if (reconfigure_clks) {          //Update the clock MUX on the motherboard to select the requested source -        mb.clock_control_regs_clock_source = 0; -        mb.clock_control_regs_tcxo_enb = 0;          if (source == "internal") { -            mb.clock_control_regs_clock_source = ZPU_SR_CLOCK_CTRL_CLK_SRC_INTERNAL; -            mb.clock_control_regs_tcxo_enb = 1; +            mb.fw_regmap->clock_ctrl_reg.set(fw_regmap_t::clk_ctrl_reg_t::CLK_SOURCE, fw_regmap_t::clk_ctrl_reg_t::SRC_INTERNAL); +            mb.fw_regmap->clock_ctrl_reg.set(fw_regmap_t::clk_ctrl_reg_t::TCXO_EN, 1);          } else if (source == "external") { -            mb.clock_control_regs_clock_source = ZPU_SR_CLOCK_CTRL_CLK_SRC_EXTERNAL; +            mb.fw_regmap->clock_ctrl_reg.set(fw_regmap_t::clk_ctrl_reg_t::CLK_SOURCE, fw_regmap_t::clk_ctrl_reg_t::SRC_EXTERNAL); +            mb.fw_regmap->clock_ctrl_reg.set(fw_regmap_t::clk_ctrl_reg_t::TCXO_EN, 0);          } else if (source == "gpsdo") { -            mb.clock_control_regs_clock_source = ZPU_SR_CLOCK_CTRL_CLK_SRC_GPSDO; +            mb.fw_regmap->clock_ctrl_reg.set(fw_regmap_t::clk_ctrl_reg_t::CLK_SOURCE, fw_regmap_t::clk_ctrl_reg_t::SRC_GPSDO); +            mb.fw_regmap->clock_ctrl_reg.set(fw_regmap_t::clk_ctrl_reg_t::TCXO_EN, 0);          } else {              throw uhd::key_error("update_clock_source: unknown source: " + source);          } -        this->update_clock_control(mb); +        mb.fw_regmap->clock_ctrl_reg.flush();          //Reset the LMK to make sure it re-locks to the new reference          mb.clock->reset_clocks(); @@ -1408,7 +1394,7 @@ void x300_impl::update_clock_source(mboard_members_t &mb, const std::string &sou      //The programming code in x300_clock_ctrl is not compatible with revs <= 4 and may      //lead to locking issues. So, disable the ref-locked check for older (unsupported) boards.      if (mb.hw_rev > 4) { -        if (not wait_for_clk_locked(mb.zpu_ctrl, ZPU_RB_CLK_STATUS_LMK_LOCK, timeout)) { +        if (not wait_for_clk_locked(mb, fw_regmap_t::clk_status_reg_t::LMK_LOCK, timeout)) {              //failed to lock on reference              if (mb.initialization_done) {                  throw uhd::runtime_error((boost::format("Reference Clock PLL failed to lock to %s source.") % source).str()); @@ -1426,7 +1412,7 @@ void x300_impl::update_clock_source(mboard_members_t &mb, const std::string &sou          mb.zpu_ctrl->poke32(SR_ADDR(SET0_BASE, ZPU_SR_SW_RST), 0);          //Wait for radio clock PLL to lock -        if (not wait_for_clk_locked(mb.zpu_ctrl, ZPU_RB_CLK_STATUS_RADIO_CLK_LOCK, 0.01)) { +        if (not wait_for_clk_locked(mb, fw_regmap_t::clk_status_reg_t::RADIO_CLK_LOCK, 0.01)) {              throw uhd::runtime_error((boost::format("Reference Clock PLL in FPGA failed to lock to %s source.") % source).str());          } @@ -1435,20 +1421,20 @@ void x300_impl::update_clock_source(mboard_members_t &mb, const std::string &sou          mb.zpu_ctrl->poke32(SR_ADDR(SET0_BASE, ZPU_SR_SW_RST), 0);          //Wait for the ADC IDELAYCTRL to be ready -        if (not wait_for_clk_locked(mb.zpu_ctrl, ZPU_RB_CLK_STATUS_IDELAYCTRL_LOCK, 0.01)) { +        if (not wait_for_clk_locked(mb, fw_regmap_t::clk_status_reg_t::IDELAYCTRL_LOCK, 0.01)) {              throw uhd::runtime_error((boost::format("ADC Calibration Clock in FPGA failed to lock to %s source.") % source).str());          }          // Reset ADCs and DACs          for (size_t r = 0; r < mboard_members_t::NUM_RADIOS; r++) {              radio_perifs_t &perif = mb.radio_perifs[r]; -            if (perif.misc_outs && r==0) {  //ADC/DAC reset lines only exist in Radio0 -                perif.misc_outs->set(radio_misc_outs_reg::ADC_RESET, 1); -                perif.misc_outs->set(radio_misc_outs_reg::DAC_RESET_N, 0); -                perif.misc_outs->flush(); -                perif.misc_outs->set(radio_misc_outs_reg::ADC_RESET, 0); -                perif.misc_outs->set(radio_misc_outs_reg::DAC_RESET_N, 1); -                perif.misc_outs->flush(); +            if (perif.regmap && r==0) {  //ADC/DAC reset lines only exist in Radio0 +                perif.regmap->misc_outs_reg.set(radio_regmap_t::misc_outs_reg_t::ADC_RESET, 1); +                perif.regmap->misc_outs_reg.set(radio_regmap_t::misc_outs_reg_t::DAC_RESET_N, 0); +                perif.regmap->misc_outs_reg.flush(); +                perif.regmap->misc_outs_reg.set(radio_regmap_t::misc_outs_reg_t::ADC_RESET, 0); +                perif.regmap->misc_outs_reg.set(radio_regmap_t::misc_outs_reg_t::DAC_RESET_N, 1); +                perif.regmap->misc_outs_reg.flush();              }              if (perif.adc) perif.adc->reset();              if (perif.dac) perif.dac->reset(); @@ -1462,61 +1448,54 @@ void x300_impl::update_clock_source(mboard_members_t &mb, const std::string &sou  void x300_impl::update_time_source(mboard_members_t &mb, const std::string &source)  {      if (source == "internal") { -        mb.clock_control_regs_pps_select = ZPU_SR_CLOCK_CTRL_PPS_SRC_INTERNAL; +        mb.fw_regmap->clock_ctrl_reg.write(fw_regmap_t::clk_ctrl_reg_t::PPS_SELECT, fw_regmap_t::clk_ctrl_reg_t::SRC_INTERNAL);      } else if (source == "external") { -        mb.clock_control_regs_pps_select = ZPU_SR_CLOCK_CTRL_PPS_SRC_EXTERNAL; +        mb.fw_regmap->clock_ctrl_reg.write(fw_regmap_t::clk_ctrl_reg_t::PPS_SELECT, fw_regmap_t::clk_ctrl_reg_t::SRC_EXTERNAL);      } else if (source == "gpsdo") { -        mb.clock_control_regs_pps_select = ZPU_SR_CLOCK_CTRL_PPS_SRC_GPSDO; +        mb.fw_regmap->clock_ctrl_reg.write(fw_regmap_t::clk_ctrl_reg_t::PPS_SELECT, fw_regmap_t::clk_ctrl_reg_t::SRC_GPSDO);      } else {          throw uhd::key_error("update_time_source: unknown source: " + source);      } -    this->update_clock_control(mb); -      //check for valid pps -    if (!is_pps_present(mb.zpu_ctrl)) +    if (!is_pps_present(mb))      {          // TODO - Implement intelligent PPS detection          /* throw uhd::runtime_error((boost::format("The %d PPS was not detected.  Please check the PPS source and try again.") % source).str()); */      }  } -static bool get_clk_locked(wb_iface::sptr ctrl, boost::uint32_t which) -{ -    return (ctrl->peek32(SR_ADDR(SET0_BASE, ZPU_RB_CLK_STATUS)) & which) != 0; -} - -bool x300_impl::wait_for_clk_locked(wb_iface::sptr ctrl, boost::uint32_t which, double timeout) +bool x300_impl::wait_for_clk_locked(mboard_members_t& mb, boost::uint32_t which, double timeout)  {      boost::system_time timeout_time = boost::get_system_time() + boost::posix_time::milliseconds(timeout * 1000.0);      do { -        if (get_clk_locked(ctrl, which)) +        if (mb.fw_regmap->clock_status_reg.read(which)==1)              return true;          boost::this_thread::sleep(boost::posix_time::milliseconds(1));      } while (boost::get_system_time() < timeout_time);      //Check one last time -    return get_clk_locked(ctrl, which); +    return (mb.fw_regmap->clock_status_reg.read(which)==1);  } -sensor_value_t x300_impl::get_ref_locked(wb_iface::sptr ctrl) +sensor_value_t x300_impl::get_ref_locked(mboard_members_t& mb)  { -    const bool lock = get_clk_locked(ctrl, ZPU_RB_CLK_STATUS_LMK_LOCK) && -                      get_clk_locked(ctrl, ZPU_RB_CLK_STATUS_RADIO_CLK_LOCK) && -                      get_clk_locked(ctrl, ZPU_RB_CLK_STATUS_IDELAYCTRL_LOCK); +    mb.fw_regmap->clock_status_reg.refresh(); +    const bool lock = (mb.fw_regmap->clock_status_reg.get(fw_regmap_t::clk_status_reg_t::LMK_LOCK)==1) && +                      (mb.fw_regmap->clock_status_reg.get(fw_regmap_t::clk_status_reg_t::RADIO_CLK_LOCK)==1) && +                      (mb.fw_regmap->clock_status_reg.get(fw_regmap_t::clk_status_reg_t::IDELAYCTRL_LOCK)==1);      return sensor_value_t("Ref", lock, "locked", "unlocked");  } -bool x300_impl::is_pps_present(wb_iface::sptr ctrl) +bool x300_impl::is_pps_present(mboard_members_t& mb)  {      // The ZPU_RB_CLK_STATUS_PPS_DETECT bit toggles with each rising edge of the PPS.      // We monitor it for up to 1.5 seconds looking for it to toggle. -    boost::uint32_t pps_detect = ctrl->peek32(SR_ADDR(SET0_BASE, ZPU_RB_CLK_STATUS)) & ZPU_RB_CLK_STATUS_PPS_DETECT; +    boost::uint32_t pps_detect = mb.fw_regmap->clock_status_reg.read(fw_regmap_t::clk_status_reg_t::PPS_DETECT);      for (int i = 0; i < 15; i++)      {          boost::this_thread::sleep(boost::posix_time::milliseconds(100)); -        boost::uint32_t clk_status = ctrl->peek32(SR_ADDR(SET0_BASE, ZPU_RB_CLK_STATUS)); -        if (pps_detect != (clk_status & ZPU_RB_CLK_STATUS_PPS_DETECT)) +        if (pps_detect != mb.fw_regmap->clock_status_reg.read(fw_regmap_t::clk_status_reg_t::PPS_DETECT))              return true;      }      return false; diff --git a/host/lib/usrp/x300/x300_impl.hpp b/host/lib/usrp/x300/x300_impl.hpp index 20cd4d754..78c497ad9 100644 --- a/host/lib/usrp/x300/x300_impl.hpp +++ b/host/lib/usrp/x300/x300_impl.hpp @@ -49,7 +49,6 @@  #include <uhd/transport/nirio/niusrprio_session.h>  #include <uhd/transport/vrt_if_packet.hpp>  #include "recv_packet_demuxer_3000.hpp" -#include <uhd/utils/soft_register.hpp>  #include "x300_regs.hpp"  static const std::string X300_FW_FILE_NAME  = "usrp_x300_fw.bin"; @@ -173,39 +172,6 @@ public:  private:      boost::shared_ptr<async_md_type> _async_md; -    class radio_misc_outs_reg : public uhd::soft_reg32_wo_t { -    public: -        UHD_DEFINE_SOFT_REG_FIELD(DAC_ENABLED,          /*width*/ 1, /*shift*/ 0);  //[0] -        UHD_DEFINE_SOFT_REG_FIELD(DAC_RESET_N,          /*width*/ 1, /*shift*/ 1);  //[1] -        UHD_DEFINE_SOFT_REG_FIELD(ADC_RESET,            /*width*/ 1, /*shift*/ 2);  //[2] -        UHD_DEFINE_SOFT_REG_FIELD(ADC_DATA_DLY_STB,     /*width*/ 1, /*shift*/ 3);  //[3] -        UHD_DEFINE_SOFT_REG_FIELD(ADC_DATA_DLY_VAL,     /*width*/ 5, /*shift*/ 4);  //[8:4] -        UHD_DEFINE_SOFT_REG_FIELD(ADC_CHECKER_ENABLED,  /*width*/ 1, /*shift*/ 9);  //[9] - -        radio_misc_outs_reg(): uhd::soft_reg32_wo_t(TOREG(SR_MISC_OUTS)) { -            //Initial values -            set(DAC_ENABLED, 0); -            set(DAC_RESET_N, 0); -            set(ADC_RESET, 0); -            set(ADC_DATA_DLY_STB, 0); -            set(ADC_DATA_DLY_VAL, 16); -            set(ADC_CHECKER_ENABLED, 0); -        } -    }; -    class radio_misc_ins_reg : public uhd::soft_reg32_ro_t { -    public: -        UHD_DEFINE_SOFT_REG_FIELD(ADC_CHECKER0_Q_LOCKED, /*width*/ 1, /*shift*/ 0);  //[0] -        UHD_DEFINE_SOFT_REG_FIELD(ADC_CHECKER0_I_LOCKED, /*width*/ 1, /*shift*/ 1);  //[1] -        UHD_DEFINE_SOFT_REG_FIELD(ADC_CHECKER1_Q_LOCKED, /*width*/ 1, /*shift*/ 2);  //[2] -        UHD_DEFINE_SOFT_REG_FIELD(ADC_CHECKER1_I_LOCKED, /*width*/ 1, /*shift*/ 3);  //[3] -        UHD_DEFINE_SOFT_REG_FIELD(ADC_CHECKER0_Q_ERROR,  /*width*/ 1, /*shift*/ 4);  //[4] -        UHD_DEFINE_SOFT_REG_FIELD(ADC_CHECKER0_I_ERROR,  /*width*/ 1, /*shift*/ 5);  //[5] -        UHD_DEFINE_SOFT_REG_FIELD(ADC_CHECKER1_Q_ERROR,  /*width*/ 1, /*shift*/ 6);  //[6] -        UHD_DEFINE_SOFT_REG_FIELD(ADC_CHECKER1_I_ERROR,  /*width*/ 1, /*shift*/ 7);  //[7] - -        radio_misc_ins_reg(): uhd::soft_reg32_ro_t(RB32_MISC_INS) { } -    }; -      //perifs in the radio core      struct radio_perifs_t      { @@ -223,8 +189,7 @@ private:          rx_frontend_core_200::sptr rx_fe;          tx_frontend_core_200::sptr tx_fe;          //Registers -        radio_misc_outs_reg::sptr misc_outs; -        radio_misc_ins_reg::sptr misc_ins; +        uhd::usrp::x300::radio_regmap_t::sptr regmap;      };      //overflow recovery impl @@ -266,18 +231,15 @@ private:          uhd::gps_ctrl::sptr gps;          gpio_core_200::sptr fp_gpio; -        //clock control register bits -        int clock_control_regs_clock_source; -        int clock_control_regs_pps_select; -        int clock_control_regs_pps_out_enb; -        int clock_control_regs_tcxo_enb; -        int clock_control_regs_gpsdo_pwr; +        uhd::usrp::x300::fw_regmap_t::sptr fw_regmap;          //which FPGA image is loaded          std::string loaded_fpga_image;          size_t hw_rev;          std::string current_refclk_src; + +        uhd::soft_regmap_db_t::sptr regmap_db;      };      std::vector<mboard_members_t> _mb; @@ -391,9 +353,9 @@ private:      void update_clock_source(mboard_members_t&, const std::string &);      void update_time_source(mboard_members_t&, const std::string &); -    uhd::sensor_value_t get_ref_locked(uhd::wb_iface::sptr); -    bool wait_for_clk_locked(uhd::wb_iface::sptr, boost::uint32_t which, double timeout); -    bool is_pps_present(uhd::wb_iface::sptr); +    uhd::sensor_value_t get_ref_locked(mboard_members_t& mb); +    bool wait_for_clk_locked(mboard_members_t& mb, boost::uint32_t which, double timeout); +    bool is_pps_present(mboard_members_t& mb);      void set_db_eeprom(uhd::i2c_iface::sptr i2c, const size_t, const uhd::usrp::dboard_eeprom_t &);      void set_mb_eeprom(uhd::i2c_iface::sptr i2c, const uhd::usrp::mboard_eeprom_t &); diff --git a/host/lib/usrp/x300/x300_regs.hpp b/host/lib/usrp/x300/x300_regs.hpp index 6e92a6dbc..350845f28 100644 --- a/host/lib/usrp/x300/x300_regs.hpp +++ b/host/lib/usrp/x300/x300_regs.hpp @@ -20,6 +20,7 @@  #include <stdint.h>  #include <boost/cstdint.hpp> +#include <uhd/utils/soft_register.hpp>  #define TOREG(x) ((x)*4) @@ -76,28 +77,12 @@ localparam ZPU_SR_ETHINT1    = 56;  #define ZPU_SR_SW_RST_RADIO_CLK_PLL     (1<<2)  #define ZPU_SR_SW_RST_ADC_IDELAYCTRL    (1<<3) -//clock controls -#define ZPU_SR_CLOCK_CTRL_CLK_SRC_EXTERNAL 0x00 -#define ZPU_SR_CLOCK_CTRL_CLK_SRC_INTERNAL 0x02 -#define ZPU_SR_CLOCK_CTRL_CLK_SRC_GPSDO    0x03 -#define ZPU_SR_CLOCK_CTRL_PPS_SRC_EXTERNAL 0x00 -#define ZPU_SR_CLOCK_CTRL_PPS_SRC_INTERNAL 0x02 -#define ZPU_SR_CLOCK_CTRL_PPS_SRC_GPSDO    0x03 -  localparam ZPU_RB_SPI        = 2;  localparam ZPU_RB_CLK_STATUS = 3;  localparam ZPU_RB_COMPAT_NUM = 6;  localparam ZPU_RB_ETH_TYPE0  = 4;  localparam ZPU_RB_ETH_TYPE1  = 5; -//clock status -#define ZPU_RB_CLK_STATUS_LMK_STATUS        (0x3 << 0) -#define ZPU_RB_CLK_STATUS_LMK_LOCK          (0x1 << 2) -#define ZPU_RB_CLK_STATUS_LMK_HOLDOVER      (0x1 << 3) -#define ZPU_RB_CLK_STATUS_PPS_DETECT        (0x1 << 4) -#define ZPU_RB_CLK_STATUS_RADIO_CLK_LOCK    (0x1 << 5) -#define ZPU_RB_CLK_STATUS_IDELAYCTRL_LOCK   (0x1 << 6) -  //spi slaves on radio  #define DB_DAC_SEN      (1 << 7)  #define DB_ADC_SEN      (1 << 6) @@ -202,5 +187,97 @@ static const uint32_t PCIE_ZPU_READ_CLOBBER     = 0x80000000;  static const uint32_t PCIE_ZPU_STATUS_BUSY      = 0x1;  static const uint32_t PCIE_ZPU_STATUS_SUSPENDED = 0x80000000; +//------------------------------------------------------------------- +// Register Maps +//------------------------------------------------------------------- +namespace uhd { namespace usrp { namespace x300 { +    class fw_regmap_t : public uhd::soft_regmap_t { +    public: +        typedef boost::shared_ptr<fw_regmap_t> sptr; + +        class clk_ctrl_reg_t : public uhd::soft_reg32_wo_t { +        public: +            UHD_DEFINE_SOFT_REG_FIELD(CLK_SOURCE,   /*width*/ 2, /*shift*/ 0);  //[1:0] +            UHD_DEFINE_SOFT_REG_FIELD(PPS_SELECT,   /*width*/ 2, /*shift*/ 2);  //[3:2] +            UHD_DEFINE_SOFT_REG_FIELD(PPS_OUT_EN,   /*width*/ 1, /*shift*/ 4);  //[4] +            UHD_DEFINE_SOFT_REG_FIELD(TCXO_EN,      /*width*/ 1, /*shift*/ 5);  //[5] +            UHD_DEFINE_SOFT_REG_FIELD(GPSDO_PWR_EN, /*width*/ 1, /*shift*/ 6);  //[6] + +            static const boost::uint32_t SRC_EXTERNAL = 0x0; +            static const boost::uint32_t SRC_INTERNAL = 0x2; +            static const boost::uint32_t SRC_GPSDO    = 0x3; + +            clk_ctrl_reg_t(): uhd::soft_reg32_wo_t(SR_ADDR(SET0_BASE, ZPU_SR_CLOCK_CTRL)) { +                //Initial values +                set(CLK_SOURCE, SRC_INTERNAL); +                set(PPS_SELECT, SRC_INTERNAL); +                set(PPS_OUT_EN, 0); +                set(TCXO_EN, 1); +                set(GPSDO_PWR_EN, 1);   //GPSDO power always ON +            } +        } clock_ctrl_reg; + +        class clk_status_reg_t : public uhd::soft_reg32_ro_t { +        public: +            UHD_DEFINE_SOFT_REG_FIELD(LMK_STATUS,       /*width*/ 2, /*shift*/ 0);  //[1:0] +            UHD_DEFINE_SOFT_REG_FIELD(LMK_LOCK,         /*width*/ 1, /*shift*/ 2);  //[2] +            UHD_DEFINE_SOFT_REG_FIELD(LMK_HOLDOVER,     /*width*/ 1, /*shift*/ 3);  //[3] +            UHD_DEFINE_SOFT_REG_FIELD(PPS_DETECT,       /*width*/ 1, /*shift*/ 4);  //[4] +            UHD_DEFINE_SOFT_REG_FIELD(RADIO_CLK_LOCK,   /*width*/ 1, /*shift*/ 5);  //[5] +            UHD_DEFINE_SOFT_REG_FIELD(IDELAYCTRL_LOCK,  /*width*/ 1, /*shift*/ 6);  //[6] + +            clk_status_reg_t(): uhd::soft_reg32_ro_t(SR_ADDR(SET0_BASE, ZPU_RB_CLK_STATUS)) {} +        } clock_status_reg; + +        fw_regmap_t() : soft_regmap_t("fw_regmap") { +            add_to_map(clock_ctrl_reg, "clock_ctrl_reg", PUBLIC); +            add_to_map(clock_status_reg, "clock_status_reg", PUBLIC); +        } +    }; + +    class radio_regmap_t : public uhd::soft_regmap_t { +    public: +        typedef boost::shared_ptr<radio_regmap_t> sptr; +        class misc_outs_reg_t : public uhd::soft_reg32_wo_t { +        public: +            UHD_DEFINE_SOFT_REG_FIELD(DAC_ENABLED,          /*width*/ 1, /*shift*/ 0);  //[0] +            UHD_DEFINE_SOFT_REG_FIELD(DAC_RESET_N,          /*width*/ 1, /*shift*/ 1);  //[1] +            UHD_DEFINE_SOFT_REG_FIELD(ADC_RESET,            /*width*/ 1, /*shift*/ 2);  //[2] +            UHD_DEFINE_SOFT_REG_FIELD(ADC_DATA_DLY_STB,     /*width*/ 1, /*shift*/ 3);  //[3] +            UHD_DEFINE_SOFT_REG_FIELD(ADC_DATA_DLY_VAL,     /*width*/ 5, /*shift*/ 4);  //[8:4] +            UHD_DEFINE_SOFT_REG_FIELD(ADC_CHECKER_ENABLED,  /*width*/ 1, /*shift*/ 9);  //[9] + +            misc_outs_reg_t(): uhd::soft_reg32_wo_t(TOREG(SR_MISC_OUTS)) { +                //Initial values +                set(DAC_ENABLED, 0); +                set(DAC_RESET_N, 0); +                set(ADC_RESET, 0); +                set(ADC_DATA_DLY_STB, 0); +                set(ADC_DATA_DLY_VAL, 16); +                set(ADC_CHECKER_ENABLED, 0); +            } +        } misc_outs_reg; + +        class misc_ins_reg_t : public uhd::soft_reg32_ro_t { +        public: +            UHD_DEFINE_SOFT_REG_FIELD(ADC_CHECKER0_Q_LOCKED, /*width*/ 1, /*shift*/ 0);  //[0] +            UHD_DEFINE_SOFT_REG_FIELD(ADC_CHECKER0_I_LOCKED, /*width*/ 1, /*shift*/ 1);  //[1] +            UHD_DEFINE_SOFT_REG_FIELD(ADC_CHECKER1_Q_LOCKED, /*width*/ 1, /*shift*/ 2);  //[2] +            UHD_DEFINE_SOFT_REG_FIELD(ADC_CHECKER1_I_LOCKED, /*width*/ 1, /*shift*/ 3);  //[3] +            UHD_DEFINE_SOFT_REG_FIELD(ADC_CHECKER0_Q_ERROR,  /*width*/ 1, /*shift*/ 4);  //[4] +            UHD_DEFINE_SOFT_REG_FIELD(ADC_CHECKER0_I_ERROR,  /*width*/ 1, /*shift*/ 5);  //[5] +            UHD_DEFINE_SOFT_REG_FIELD(ADC_CHECKER1_Q_ERROR,  /*width*/ 1, /*shift*/ 6);  //[6] +            UHD_DEFINE_SOFT_REG_FIELD(ADC_CHECKER1_I_ERROR,  /*width*/ 1, /*shift*/ 7);  //[7] + +            misc_ins_reg_t(): uhd::soft_reg32_ro_t(RB32_MISC_INS) { } +        } misc_ins_reg; + +        radio_regmap_t(int radio_num) : soft_regmap_t("radio" + boost::lexical_cast<std::string>(radio_num) + "_regmap") { +            add_to_map(misc_outs_reg, "misc_outs_reg", PUBLIC); +            add_to_map(misc_ins_reg, "misc_ins_reg", PUBLIC); +        } +    }; + +}}}  #endif /* INCLUDED_X300_REGS_HPP */  | 
