diff options
| -rw-r--r-- | host/lib/usrp/usrp2/usrp2_regs.hpp | 2 | ||||
| -rw-r--r-- | host/lib/usrp/usrp_e100/dsp_impl.cpp | 127 | ||||
| -rw-r--r-- | host/lib/usrp/usrp_e100/io_impl.cpp | 81 | ||||
| -rw-r--r-- | host/lib/usrp/usrp_e100/mboard_impl.cpp | 63 | ||||
| -rw-r--r-- | host/lib/usrp/usrp_e100/usrp_e100_iface.hpp | 5 | ||||
| -rw-r--r-- | host/lib/usrp/usrp_e100/usrp_e100_impl.cpp | 22 | ||||
| -rw-r--r-- | host/lib/usrp/usrp_e100/usrp_e100_impl.hpp | 38 | ||||
| -rw-r--r-- | host/lib/usrp/usrp_e100/usrp_e100_regs.hpp | 147 | 
8 files changed, 281 insertions, 204 deletions
| diff --git a/host/lib/usrp/usrp2/usrp2_regs.hpp b/host/lib/usrp/usrp2/usrp2_regs.hpp index d43dcc6bc..19c1b45f1 100644 --- a/host/lib/usrp/usrp2/usrp2_regs.hpp +++ b/host/lib/usrp/usrp2/usrp2_regs.hpp @@ -153,7 +153,7 @@  #define U2_REG_DSP_RX_FREQ(which)       U2_REG_DSP_RX_HELPER(which, 0)  #define U2_REG_DSP_RX_DECIM(which)      U2_REG_DSP_RX_HELPER(which, 2) -#define U2_REG_DSP_RX_MUX(which)        U2_REG_DSP_RX_HELPER(which, 5) +#define U2_REG_DSP_RX_MUX(which)        U2_REG_DSP_RX_HELPER(which, 3)  #define U2_FLAG_DSP_RX_MUX_SWAP_IQ   (1 << 0)  #define U2_FLAG_DSP_RX_MUX_REAL_MODE (1 << 1) diff --git a/host/lib/usrp/usrp_e100/dsp_impl.cpp b/host/lib/usrp/usrp_e100/dsp_impl.cpp index 93034b5dc..57bfdc3c4 100644 --- a/host/lib/usrp/usrp_e100/dsp_impl.cpp +++ b/host/lib/usrp/usrp_e100/dsp_impl.cpp @@ -22,34 +22,80 @@  #include <boost/math/special_functions/round.hpp>  #include <boost/bind.hpp> -#define rint boost::math::iround -  using namespace uhd;  using namespace uhd::usrp;  /*********************************************************************** + * DSP impl and methods + **********************************************************************/ +struct usrp_e100_impl::dsp_impl{ +    uhd::dict<size_t, size_t> ddc_decim; +    uhd::dict<size_t, double> ddc_freq; +    uhd::dict<size_t, size_t> duc_interp; +    uhd::dict<size_t, double> duc_freq; +}; + +/***********************************************************************   * RX DDC Initialization   **********************************************************************/ -void usrp_e100_impl::rx_ddc_init(void){ -    _rx_ddc_proxy = wax_obj_proxy::make( -        boost::bind(&usrp_e100_impl::rx_ddc_get, this, _1, _2), -        boost::bind(&usrp_e100_impl::rx_ddc_set, this, _1, _2) -    ); - -    //initial config and update -    rx_ddc_set(DSP_PROP_FREQ_SHIFT, double(0)); -    rx_ddc_set(DSP_PROP_HOST_RATE, double(16e6)); +void usrp_e100_impl::dsp_init(void){ +    //create new dsp impl +    _dsp_impl = UHD_PIMPL_MAKE(dsp_impl, ()); + +    //bind and initialize the rx dsps +    for (size_t i = 0; i < E100_NUM_RX_DSPS; i++){ +        _rx_dsp_proxies[str(boost::format("DSP%d")%i)] = wax_obj_proxy::make( +            boost::bind(&usrp_e100_impl::ddc_get, this, _1, _2, i), +            boost::bind(&usrp_e100_impl::ddc_set, this, _1, _2, i) +        ); + +        //initial config and update +        ddc_set(DSP_PROP_FREQ_SHIFT, double(0), i); +        ddc_set(DSP_PROP_HOST_RATE, double(_clock_ctrl->get_fpga_clock_rate()/16), i); + +        //setup the rx control registers +        _iface->poke32(UE_REG_RX_CTRL_CLEAR(i), 1); //reset +        _iface->poke32(UE_REG_RX_CTRL_NSAMPS_PP(i), this->get_max_recv_samps_per_packet()); +        _iface->poke32(UE_REG_RX_CTRL_NCHANNELS(i), 1); +        _iface->poke32(UE_REG_RX_CTRL_VRT_HDR(i), 0 +            | (0x1 << 28) //if data with stream id +            | (0x1 << 26) //has trailer +            | (0x3 << 22) //integer time other +            | (0x1 << 20) //fractional time sample count +        ); +        _iface->poke32(UE_REG_RX_CTRL_VRT_SID(i), E100_DSP_SID_BASE + i); +        _iface->poke32(UE_REG_RX_CTRL_VRT_TLR(i), 0); +        _iface->poke32(UE_REG_TIME64_TPS, size_t(_clock_ctrl->get_fpga_clock_rate())); +    } + +    //bind and initialize the tx dsps +    for (size_t i = 0; i < E100_NUM_TX_DSPS; i++){ +        _tx_dsp_proxies[str(boost::format("DSP%d")%i)] = wax_obj_proxy::make( +            boost::bind(&usrp_e100_impl::duc_get, this, _1, _2, i), +            boost::bind(&usrp_e100_impl::duc_set, this, _1, _2, i) +        ); + +        //initial config and update +        duc_set(DSP_PROP_FREQ_SHIFT, double(0), i); +        duc_set(DSP_PROP_HOST_RATE, double(_clock_ctrl->get_fpga_clock_rate()/16), i); + +        //init the tx control registers +        _iface->poke32(UE_REG_TX_CTRL_CLEAR_STATE, 1); //reset +        _iface->poke32(UE_REG_TX_CTRL_NUM_CHAN, 0);    //1 channel +        _iface->poke32(UE_REG_TX_CTRL_REPORT_SID, E100_ASYNC_SID); +        _iface->poke32(UE_REG_TX_CTRL_POLICY, UE_FLAG_TX_CTRL_POLICY_NEXT_PACKET); +    }  }  /***********************************************************************   * RX DDC Get   **********************************************************************/ -void usrp_e100_impl::rx_ddc_get(const wax::obj &key_, wax::obj &val){ +void usrp_e100_impl::ddc_get(const wax::obj &key_, wax::obj &val, size_t which_dsp){      named_prop_t key = named_prop_t::extract(key_);      switch(key.as<dsp_prop_t>()){      case DSP_PROP_NAME: -        val = std::string("usrp-e ddc0"); +        val = str(boost::format("%s ddc%d") % _iface->get_cname() % which_dsp);          return;      case DSP_PROP_OTHERS: @@ -57,7 +103,7 @@ void usrp_e100_impl::rx_ddc_get(const wax::obj &key_, wax::obj &val){          return;      case DSP_PROP_FREQ_SHIFT: -        val = _ddc_freq; +        val = _dsp_impl->ddc_freq[which_dsp];          return;      case DSP_PROP_CODEC_RATE: @@ -65,7 +111,7 @@ void usrp_e100_impl::rx_ddc_get(const wax::obj &key_, wax::obj &val){          return;      case DSP_PROP_HOST_RATE: -        val = _clock_ctrl->get_fpga_clock_rate()/_ddc_decim; +        val = _clock_ctrl->get_fpga_clock_rate()/_dsp_impl->ddc_decim[which_dsp];          return;      default: UHD_THROW_PROP_GET_ERROR(); @@ -75,34 +121,29 @@ void usrp_e100_impl::rx_ddc_get(const wax::obj &key_, wax::obj &val){  /***********************************************************************   * RX DDC Set   **********************************************************************/ -void usrp_e100_impl::rx_ddc_set(const wax::obj &key_, const wax::obj &val){ +void usrp_e100_impl::ddc_set(const wax::obj &key_, const wax::obj &val, size_t which_dsp){      named_prop_t key = named_prop_t::extract(key_);      switch(key.as<dsp_prop_t>()){      case DSP_PROP_STREAM_CMD: -        issue_stream_cmd(val.as<stream_cmd_t>()); +        issue_ddc_stream_cmd(val.as<stream_cmd_t>(), which_dsp);          return;      case DSP_PROP_FREQ_SHIFT:{              double new_freq = val.as<double>(); -            _iface->poke32(UE_REG_DSP_RX_FREQ, +            _iface->poke32(UE_REG_DSP_RX_FREQ(which_dsp),                  dsp_type1::calc_cordic_word_and_update(new_freq, _clock_ctrl->get_fpga_clock_rate())              ); -            _ddc_freq = new_freq; //shadow +            _dsp_impl->ddc_freq[which_dsp] = new_freq; //shadow          }          return;      case DSP_PROP_HOST_RATE:{ -            //set the decimation -            _ddc_decim = rint(_clock_ctrl->get_fpga_clock_rate()/val.as<double>()); -            _iface->poke32(UE_REG_DSP_RX_DECIM_RATE, dsp_type1::calc_cic_filter_word(_ddc_decim)); +            _dsp_impl->ddc_decim[which_dsp] = boost::math::iround(_clock_ctrl->get_fpga_clock_rate()/val.as<double>()); -            //set the scaling -            static const boost::int16_t default_rx_scale_iq = 1024; -            _iface->poke32(UE_REG_DSP_RX_SCALE_IQ, -                dsp_type1::calc_iq_scale_word(default_rx_scale_iq, default_rx_scale_iq) -            ); +            //set the decimation +            _iface->poke32(UE_REG_DSP_RX_DECIM(which_dsp), dsp_type1::calc_cic_filter_word(_dsp_impl->ddc_decim[which_dsp]));          }          this->update_xport_channel_mapping(); //rate changed -> update          return; @@ -112,28 +153,14 @@ void usrp_e100_impl::rx_ddc_set(const wax::obj &key_, const wax::obj &val){  }  /*********************************************************************** - * TX DUC Initialization - **********************************************************************/ -void usrp_e100_impl::tx_duc_init(void){ -    _tx_duc_proxy = wax_obj_proxy::make( -        boost::bind(&usrp_e100_impl::tx_duc_get, this, _1, _2), -        boost::bind(&usrp_e100_impl::tx_duc_set, this, _1, _2) -    ); - -    //initial config and update -    tx_duc_set(DSP_PROP_FREQ_SHIFT, double(0)); -    tx_duc_set(DSP_PROP_HOST_RATE, double(16e6)); -} - -/***********************************************************************   * TX DUC Get   **********************************************************************/ -void usrp_e100_impl::tx_duc_get(const wax::obj &key_, wax::obj &val){ +void usrp_e100_impl::duc_get(const wax::obj &key_, wax::obj &val, size_t which_dsp){      named_prop_t key = named_prop_t::extract(key_);      switch(key.as<dsp_prop_t>()){      case DSP_PROP_NAME: -        val = std::string("usrp-e duc0"); +        val = str(boost::format("%s duc%d") % _iface->get_cname() % which_dsp);          return;      case DSP_PROP_OTHERS: @@ -141,7 +168,7 @@ void usrp_e100_impl::tx_duc_get(const wax::obj &key_, wax::obj &val){          return;      case DSP_PROP_FREQ_SHIFT: -        val = _duc_freq; +        val = _dsp_impl->duc_freq[which_dsp];          return;      case DSP_PROP_CODEC_RATE: @@ -149,7 +176,7 @@ void usrp_e100_impl::tx_duc_get(const wax::obj &key_, wax::obj &val){          return;      case DSP_PROP_HOST_RATE: -        val = _clock_ctrl->get_fpga_clock_rate()/_duc_interp; +        val = _clock_ctrl->get_fpga_clock_rate()/_dsp_impl->duc_interp[which_dsp];          return;      default: UHD_THROW_PROP_GET_ERROR(); @@ -159,7 +186,7 @@ void usrp_e100_impl::tx_duc_get(const wax::obj &key_, wax::obj &val){  /***********************************************************************   * TX DUC Set   **********************************************************************/ -void usrp_e100_impl::tx_duc_set(const wax::obj &key_, const wax::obj &val){ +void usrp_e100_impl::duc_set(const wax::obj &key_, const wax::obj &val, size_t which_dsp){      named_prop_t key = named_prop_t::extract(key_);      switch(key.as<dsp_prop_t>()){ @@ -169,18 +196,18 @@ void usrp_e100_impl::tx_duc_set(const wax::obj &key_, const wax::obj &val){              _iface->poke32(UE_REG_DSP_TX_FREQ,                  dsp_type1::calc_cordic_word_and_update(new_freq, _clock_ctrl->get_fpga_clock_rate())              ); -            _duc_freq = new_freq; //shadow +            _dsp_impl->duc_freq[which_dsp] = new_freq; //shadow          }          return;      case DSP_PROP_HOST_RATE:{ -            _duc_interp = rint(_clock_ctrl->get_fpga_clock_rate()/val.as<double>()); +            _dsp_impl->duc_interp[which_dsp] = boost::math::iround(_clock_ctrl->get_fpga_clock_rate()/val.as<double>());              //set the interpolation -            _iface->poke32(UE_REG_DSP_TX_INTERP_RATE, dsp_type1::calc_cic_filter_word(_duc_interp)); +            _iface->poke32(UE_REG_DSP_TX_INTERP_RATE, dsp_type1::calc_cic_filter_word(_dsp_impl->duc_interp[which_dsp]));              //set the scaling -            _iface->poke32(UE_REG_DSP_TX_SCALE_IQ, dsp_type1::calc_iq_scale_word(_duc_interp)); +            _iface->poke32(UE_REG_DSP_TX_SCALE_IQ, dsp_type1::calc_iq_scale_word(_dsp_impl->duc_interp[which_dsp]));          }          this->update_xport_channel_mapping(); //rate changed -> update          return; diff --git a/host/lib/usrp/usrp_e100/io_impl.cpp b/host/lib/usrp/usrp_e100/io_impl.cpp index 91b129276..a87f53048 100644 --- a/host/lib/usrp/usrp_e100/io_impl.cpp +++ b/host/lib/usrp/usrp_e100/io_impl.cpp @@ -38,8 +38,6 @@ using namespace uhd::transport;  /***********************************************************************   * Constants   **********************************************************************/ -static const size_t rx_data_inline_sid = 1; -static const size_t tx_async_report_sid = 2;  static const int underflow_flags = async_metadata_t::EVENT_CODE_UNDERFLOW | async_metadata_t::EVENT_CODE_UNDERFLOW_IN_PACKET;  #define fp_recv_debug false @@ -53,22 +51,27 @@ static const int underflow_flags = async_metadata_t::EVENT_CODE_UNDERFLOW | asyn  struct usrp_e100_impl::io_impl{      io_impl(zero_copy_if::sptr &xport):          data_xport(xport), -        recv_pirate_booty(data_xport->get_num_recv_frames()),          async_msg_fifo(100/*messages deep*/)      { -        /* NOP */ +        for (size_t i = 0; i < E100_NUM_RX_DSPS; i++){ +            typedef bounded_buffer<managed_recv_buffer::sptr> booty_type; +            recv_pirate_booty.push_back(new booty_type(data_xport->get_num_recv_frames())); +        }      }      ~io_impl(void){          recv_pirate_crew_raiding = false;          recv_pirate_crew.interrupt_all();          recv_pirate_crew.join_all(); +        for (size_t i = 0; i < recv_pirate_booty.size(); i++){ +            delete recv_pirate_booty[i]; +        }      } -    managed_recv_buffer::sptr get_recv_buff(double timeout){ +    managed_recv_buffer::sptr get_recv_buff(const size_t index, double timeout){          boost::this_thread::disable_interruption di; //disable because the wait can throw          managed_recv_buffer::sptr buff; -        recv_pirate_booty.pop_with_timed_wait(buff, timeout); +        recv_pirate_booty[index]->pop_with_timed_wait(buff, timeout);          return buff; //ASSUME buff == NULL when pop times-out      } @@ -84,7 +87,7 @@ struct usrp_e100_impl::io_impl{      //a pirate's life is the life for me!      void recv_pirate_loop(boost::barrier &, usrp_e100_clock_ctrl::sptr); -    bounded_buffer<managed_recv_buffer::sptr> recv_pirate_booty; +    std::vector<bounded_buffer<managed_recv_buffer::sptr> *> recv_pirate_booty;      bounded_buffer<async_metadata_t> async_msg_fifo;      boost::thread_group recv_pirate_crew;      bool recv_pirate_crew_raiding; @@ -117,24 +120,22 @@ void usrp_e100_impl::io_impl::recv_pirate_loop(          }          try{ -            //extract the vrt header packet info -            vrt::if_packet_info_t if_packet_info; -            if_packet_info.num_packet_words32 = buff->size()/sizeof(boost::uint32_t); -            const boost::uint32_t *vrt_hdr = buff->cast<const boost::uint32_t *>(); -              //handle an rx data packet or inline message -            if (uhd::ntohx(vrt_hdr[1]) == rx_data_inline_sid){ //ASSUME has_sid +            const boost::uint32_t *vrt_hdr = buff->cast<const boost::uint32_t *>(); +            const size_t rx_index = uhd::ntohx(vrt_hdr[1]); +            if (rx_index < E100_NUM_RX_DSPS){                  if (fp_recv_debug) UHD_LOGV(always) << "this is rx_data_inline_sid\n"; -                //same number of frames as the data transport -> always immediate -                recv_pirate_booty.push_with_wait(buff); +                recv_pirate_booty[rx_index]->push_with_wait(buff);                  continue;              }              //unpack the vrt header and process below... +            vrt::if_packet_info_t if_packet_info; +            if_packet_info.num_packet_words32 = buff->size()/sizeof(boost::uint32_t);              vrt::if_hdr_unpack_le(vrt_hdr, if_packet_info);              //handle a tx async report message -            if (if_packet_info.sid == tx_async_report_sid and if_packet_info.packet_type != vrt::if_packet_info_t::PACKET_TYPE_DATA){ +            if (if_packet_info.sid == E100_ASYNC_SID and if_packet_info.packet_type != vrt::if_packet_info_t::PACKET_TYPE_DATA){                  if (fp_recv_debug) UHD_LOGV(always) << "this is tx_async_report_sid\n";                  //fill in the async metadata @@ -165,37 +166,13 @@ void usrp_e100_impl::io_impl::recv_pirate_loop(   * Helper Functions   **********************************************************************/  void usrp_e100_impl::io_init(void){ -    //setup otw types -    _send_otw_type.width = 16; -    _send_otw_type.shift = 0; -    _send_otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN; - -    _recv_otw_type.width = 16; -    _recv_otw_type.shift = 0; -    _recv_otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN;      //setup before the registers (transport called to calculate max spp)      _io_impl = UHD_PIMPL_MAKE(io_impl, (_data_xport));      //clear state machines -    _iface->poke32(UE_REG_CTRL_RX_CLEAR, 0); -    _iface->poke32(UE_REG_CTRL_TX_CLEAR, 0); - -    //setup rx data path -    _iface->poke32(UE_REG_CTRL_RX_NSAMPS_PER_PKT, get_max_recv_samps_per_packet()); -    _iface->poke32(UE_REG_CTRL_RX_NCHANNELS, 1); -    _iface->poke32(UE_REG_CTRL_RX_VRT_HEADER, 0 -        | (0x1 << 28) //if data with stream id -        | (0x1 << 26) //has trailer -        | (0x3 << 22) //integer time other -        | (0x1 << 20) //fractional time sample count -    ); -    _iface->poke32(UE_REG_CTRL_RX_VRT_STREAM_ID, rx_data_inline_sid); -    _iface->poke32(UE_REG_CTRL_RX_VRT_TRAILER, 0); - -    //setup the tx policy -    _iface->poke32(UE_REG_CTRL_TX_REPORT_SID, tx_async_report_sid); -    _iface->poke32(UE_REG_CTRL_TX_POLICY, UE_FLAG_CTRL_TX_POLICY_NEXT_PACKET); +    _iface->poke32(UE_REG_CLEAR_RX, 0); +    _iface->poke32(UE_REG_CLEAR_TX, 0);      //spawn a pirate, yarrr!      boost::barrier spawn_barrier(2); @@ -216,10 +193,11 @@ void usrp_e100_impl::update_xport_channel_mapping(void){      _io_impl->recv_handler.resize(_rx_subdev_spec.size());      _io_impl->recv_handler.set_vrt_unpacker(&vrt::if_hdr_unpack_le);      _io_impl->recv_handler.set_tick_rate(_clock_ctrl->get_fpga_clock_rate()); -    _io_impl->recv_handler.set_samp_rate(_rx_ddc_proxy->get_link()[DSP_PROP_HOST_RATE].as<double>()); +    //FIXME assumes homogeneous rates across all dsp +    _io_impl->recv_handler.set_samp_rate(_rx_dsp_proxies[_rx_dsp_proxies.keys().at(0)]->get_link()[DSP_PROP_HOST_RATE].as<double>());      for (size_t chan = 0; chan < _io_impl->recv_handler.size(); chan++){          _io_impl->recv_handler.set_xport_chan_get_buff(chan, boost::bind( -            &usrp_e100_impl::io_impl::get_recv_buff, _io_impl.get(), _1 +            &usrp_e100_impl::io_impl::get_recv_buff, _io_impl.get(), chan, _1          ));          _io_impl->recv_handler.set_overflow_handler(chan, boost::bind(              &usrp_e100_impl::handle_overrun, this, chan @@ -232,7 +210,8 @@ void usrp_e100_impl::update_xport_channel_mapping(void){      _io_impl->send_handler.resize(_tx_subdev_spec.size());      _io_impl->send_handler.set_vrt_packer(&vrt::if_hdr_pack_le);      _io_impl->send_handler.set_tick_rate(_clock_ctrl->get_fpga_clock_rate()); -    _io_impl->send_handler.set_samp_rate(_tx_duc_proxy->get_link()[DSP_PROP_HOST_RATE].as<double>()); +    //FIXME assumes homogeneous rates across all dsp +    _io_impl->send_handler.set_samp_rate(_tx_dsp_proxies[_tx_dsp_proxies.keys().at(0)]->get_link()[DSP_PROP_HOST_RATE].as<double>());      for (size_t chan = 0; chan < _io_impl->send_handler.size(); chan++){          _io_impl->send_handler.set_xport_chan_get_buff(chan, boost::bind(              &uhd::transport::zero_copy_if::get_send_buff, _io_impl->data_xport, _1 @@ -242,16 +221,16 @@ void usrp_e100_impl::update_xport_channel_mapping(void){      _io_impl->send_handler.set_max_samples_per_packet(get_max_send_samps_per_packet());  } -void usrp_e100_impl::issue_stream_cmd(const stream_cmd_t &stream_cmd){ +void usrp_e100_impl::issue_ddc_stream_cmd(const stream_cmd_t &stream_cmd, const size_t index){      _io_impl->continuous_streaming = (stream_cmd.stream_mode == stream_cmd_t::STREAM_MODE_START_CONTINUOUS); -    _iface->poke32(UE_REG_CTRL_RX_STREAM_CMD, dsp_type1::calc_stream_cmd_word(stream_cmd)); -    _iface->poke32(UE_REG_CTRL_RX_TIME_SECS,  boost::uint32_t(stream_cmd.time_spec.get_full_secs())); -    _iface->poke32(UE_REG_CTRL_RX_TIME_TICKS, stream_cmd.time_spec.get_tick_count(_clock_ctrl->get_fpga_clock_rate())); +    _iface->poke32(UE_REG_RX_CTRL_STREAM_CMD(index), dsp_type1::calc_stream_cmd_word(stream_cmd)); +    _iface->poke32(UE_REG_RX_CTRL_TIME_SECS(index),  boost::uint32_t(stream_cmd.time_spec.get_full_secs())); +    _iface->poke32(UE_REG_RX_CTRL_TIME_TICKS(index), stream_cmd.time_spec.get_tick_count(_clock_ctrl->get_fpga_clock_rate()));  } -void usrp_e100_impl::handle_overrun(size_t /*chan*/){ +void usrp_e100_impl::handle_overrun(const size_t index){      if (_io_impl->continuous_streaming){ -        this->issue_stream_cmd(stream_cmd_t::STREAM_MODE_START_CONTINUOUS); +        this->issue_ddc_stream_cmd(stream_cmd_t::STREAM_MODE_START_CONTINUOUS, index);      }  } diff --git a/host/lib/usrp/usrp_e100/mboard_impl.cpp b/host/lib/usrp/usrp_e100/mboard_impl.cpp index f4b8d79f6..2989321a4 100644 --- a/host/lib/usrp/usrp_e100/mboard_impl.cpp +++ b/host/lib/usrp/usrp_e100/mboard_impl.cpp @@ -98,21 +98,19 @@ void usrp_e100_impl::mboard_get(const wax::obj &key_, wax::obj &val){          return;      case MBOARD_PROP_RX_DSP: -        UHD_ASSERT_THROW(key.name == ""); -        val = _rx_ddc_proxy->get_link(); +        val = _rx_dsp_proxies[key.name]->get_link();          return;      case MBOARD_PROP_RX_DSP_NAMES: -        val = prop_names_t(1, ""); +        val = _rx_dsp_proxies.keys();          return;      case MBOARD_PROP_TX_DSP: -        UHD_ASSERT_THROW(key.name == ""); -        val = _tx_duc_proxy->get_link(); +        val = _tx_dsp_proxies[key.name]->get_link();          return;      case MBOARD_PROP_TX_DSP_NAMES: -        val = prop_names_t(1, ""); +        val = _tx_dsp_proxies.keys();          return;      case MBOARD_PROP_CLOCK_CONFIG: @@ -172,24 +170,59 @@ void usrp_e100_impl::mboard_set(const wax::obj &key, const wax::obj &val){          }          return; -    case MBOARD_PROP_RX_SUBDEV_SPEC: +    case MBOARD_PROP_RX_SUBDEV_SPEC:{          _rx_subdev_spec = val.as<subdev_spec_t>();          verify_rx_subdev_spec(_rx_subdev_spec, _mboard_proxy->get_link());          //sanity check -        UHD_ASSERT_THROW(_rx_subdev_spec.size() == 1); -        //set the mux -        _iface->poke32(UE_REG_DSP_RX_MUX, dsp_type1::calc_rx_mux_word( -            _dboard_manager->get_rx_subdev(_rx_subdev_spec.front().sd_name)[SUBDEV_PROP_CONNECTION].as<subdev_conn_t>() -        )); -        return; +        UHD_ASSERT_THROW(_rx_subdev_spec.size() <= E100_NUM_RX_DSPS); + +        //determine frontend swap IQ from the first channel +        bool fe_swap_iq = false; +        switch(_dboard_manager->get_rx_subdev(_rx_subdev_spec.at(0).sd_name)[SUBDEV_PROP_CONNECTION].as<subdev_conn_t>()){ +        case SUBDEV_CONN_COMPLEX_QI: +        case SUBDEV_CONN_REAL_Q: +            fe_swap_iq = true; +            break; +        default: fe_swap_iq = false; +        } +        _iface->poke32(UE_REG_RX_FE_SWAP_IQ, fe_swap_iq? 1 : 0); + +        //set the dsp mux for each channel +        for (size_t i = 0; i < _rx_subdev_spec.size(); i++){ +            bool iq_swap = false, real_mode = false; +            switch(_dboard_manager->get_rx_subdev(_rx_subdev_spec.at(i).sd_name)[SUBDEV_PROP_CONNECTION].as<subdev_conn_t>()){ +            case SUBDEV_CONN_COMPLEX_IQ: +                iq_swap = fe_swap_iq; +                real_mode = false; +                break; +            case SUBDEV_CONN_COMPLEX_QI: +                iq_swap = not fe_swap_iq; +                real_mode = false; +                break; +            case SUBDEV_CONN_REAL_I: +                iq_swap = fe_swap_iq; +                real_mode = true; +                break; +            case SUBDEV_CONN_REAL_Q: +                iq_swap = not fe_swap_iq; +                real_mode = true; +                break; +            } +            _iface->poke32(UE_REG_DSP_RX_MUX(i), +                (iq_swap?   UE_FLAG_DSP_RX_MUX_SWAP_IQ   : 0) | +                (real_mode? UE_FLAG_DSP_RX_MUX_REAL_MODE : 0) +            ); +        } +        this->update_xport_channel_mapping(); +    }return;      case MBOARD_PROP_TX_SUBDEV_SPEC:          _tx_subdev_spec = val.as<subdev_spec_t>();          verify_tx_subdev_spec(_tx_subdev_spec, _mboard_proxy->get_link());          //sanity check -        UHD_ASSERT_THROW(_tx_subdev_spec.size() == 1); +        UHD_ASSERT_THROW(_tx_subdev_spec.size() <= E100_NUM_TX_DSPS);          //set the mux -        _iface->poke32(UE_REG_DSP_TX_MUX, dsp_type1::calc_tx_mux_word( +        _iface->poke32(UE_REG_TX_FE_MUX, dsp_type1::calc_tx_mux_word(              _dboard_manager->get_tx_subdev(_tx_subdev_spec.front().sd_name)[SUBDEV_PROP_CONNECTION].as<subdev_conn_t>()          ));          return; diff --git a/host/lib/usrp/usrp_e100/usrp_e100_iface.hpp b/host/lib/usrp/usrp_e100/usrp_e100_iface.hpp index 7df99cf4e..c7fa13393 100644 --- a/host/lib/usrp/usrp_e100/usrp_e100_iface.hpp +++ b/host/lib/usrp/usrp_e100/usrp_e100_iface.hpp @@ -50,6 +50,11 @@ public:       */      static sptr make(void); +    //! TODO implement this for multiple hardwares revs in the future +    std::string get_cname(void){ +        return "USRP-E100"; +    } +      /*!       * Get the underlying file descriptor.       * \return the file descriptor diff --git a/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp b/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp index 36db810a8..c55d80a34 100644 --- a/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp +++ b/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp @@ -51,7 +51,7 @@ static device_addrs_t usrp_e100_find(const device_addr_t &hint){      //use the given device node name      if (fs::exists(hint["node"])){          device_addr_t new_addr; -        new_addr["type"] = "usrp-e"; +        new_addr["type"] = "e100";          new_addr["node"] = fs::system_complete(fs::path(hint["node"])).string();          try{              usrp_e100_iface::sptr iface = usrp_e100_iface::make(); @@ -93,11 +93,11 @@ static device::sptr usrp_e100_make(const device_addr_t &device_addr){      iface->open(node);      //setup clock control here to ensure that the FPGA has a good clock before we continue -    const double master_clock_rate = device_addr.cast<double>("master_clock_rate", USRP_E_DEFAULT_CLOCK_RATE); +    const double master_clock_rate = device_addr.cast<double>("master_clock_rate", E100_DEFAULT_CLOCK_RATE);      usrp_e100_clock_ctrl::sptr clock_ctrl = usrp_e100_clock_ctrl::make(iface, master_clock_rate);      //extract the fpga path for usrp-e and compute hash -    const std::string usrp_e100_fpga_image = find_image_path(device_addr.get("fpga", USRP_E_FPGA_FILE_NAME)); +    const std::string usrp_e100_fpga_image = find_image_path(device_addr.get("fpga", E100_FPGA_FILE_NAME));      const boost::uint32_t file_hash = boost::uint32_t(hash_fpga_file(usrp_e100_fpga_image));      //When the hash does not match: @@ -128,13 +128,13 @@ static device::sptr usrp_e100_make(const device_addr_t &device_addr){      //check that the compatibility is correct      const boost::uint16_t fpga_compat_num = iface->peek16(UE_REG_MISC_COMPAT); -    if (fpga_compat_num != USRP_E_FPGA_COMPAT_NUM){ +    if (fpga_compat_num != E100_FPGA_COMPAT_NUM){          throw uhd::runtime_error(str(boost::format(              "\nPlease update the FPGA image for your device.\n"              "See the application notes for USRP E-Series for instructions.\n"              "Expected FPGA compatibility number 0x%x, but got 0x%x:\n"              "The FPGA build is not compatible with the host code build." -        ) % USRP_E_FPGA_COMPAT_NUM % fpga_compat_num)); +        ) % E100_FPGA_COMPAT_NUM % fpga_compat_num));      }      return device::sptr(new usrp_e100_impl(device_addr, iface, clock_ctrl)); @@ -160,6 +160,15 @@ usrp_e100_impl::usrp_e100_impl(      _send_frame_size(std::min(_data_xport->get_send_frame_size(), size_t(device_addr.cast<double>("send_frame_size", 1e9))))  { +    //setup otw types +    _send_otw_type.width = 16; +    _send_otw_type.shift = 0; +    _send_otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN; + +    _recv_otw_type.width = 16; +    _recv_otw_type.shift = 0; +    _recv_otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN; +      //initialize the mboard      mboard_init(); @@ -167,8 +176,7 @@ usrp_e100_impl::usrp_e100_impl(      dboard_init();      //initialize the dsps -    rx_ddc_init(); -    tx_duc_init(); +    dsp_init();      //init the codec properties      codec_init(); diff --git a/host/lib/usrp/usrp_e100/usrp_e100_impl.hpp b/host/lib/usrp/usrp_e100/usrp_e100_impl.hpp index 0c6087a85..4aad18fab 100644 --- a/host/lib/usrp/usrp_e100/usrp_e100_impl.hpp +++ b/host/lib/usrp/usrp_e100/usrp_e100_impl.hpp @@ -33,9 +33,13 @@  uhd::transport::zero_copy_if::sptr usrp_e100_make_mmap_zero_copy(usrp_e100_iface::sptr iface); -static const std::string USRP_E_FPGA_FILE_NAME = "usrp_e100_fpga5.bin"; -static const boost::uint16_t USRP_E_FPGA_COMPAT_NUM = 0x05; -static const double USRP_E_DEFAULT_CLOCK_RATE = 64e6; +static const std::string     E100_FPGA_FILE_NAME = "usrp_e100_fpga5.bin"; +static const boost::uint16_t E100_FPGA_COMPAT_NUM = 0x05; +static const double          E100_DEFAULT_CLOCK_RATE = 64e6; +static const size_t          E100_NUM_RX_DSPS = 2; +static const size_t          E100_NUM_TX_DSPS = 1; +static const boost::uint32_t E100_DSP_SID_BASE = 2; //leave room for other dsp (increments by 1) +static const boost::uint32_t E100_ASYNC_SID = 1;  //! load an fpga image from a bin file into the usrp-e fpga  extern void usrp_e100_load_fpga(const std::string &bin_file); @@ -114,7 +118,6 @@ private:      size_t _recv_frame_size, _send_frame_size;      uhd::otw_type_t _send_otw_type, _recv_otw_type;      void io_init(void); -    void issue_stream_cmd(const uhd::stream_cmd_t &stream_cmd);      void handle_overrun(size_t);      void update_xport_channel_mapping(void); @@ -149,19 +152,20 @@ private:      void tx_dboard_set(const wax::obj &, const wax::obj &);      wax_obj_proxy::sptr _tx_dboard_proxy; -    //rx ddc functions and settings -    void rx_ddc_init(void); -    void rx_ddc_get(const wax::obj &, wax::obj &); -    void rx_ddc_set(const wax::obj &, const wax::obj &); -    double _ddc_freq; size_t _ddc_decim; -    wax_obj_proxy::sptr _rx_ddc_proxy; - -    //tx duc functions and settings -    void tx_duc_init(void); -    void tx_duc_get(const wax::obj &, wax::obj &); -    void tx_duc_set(const wax::obj &, const wax::obj &); -    double _duc_freq; size_t _duc_interp; -    wax_obj_proxy::sptr _tx_duc_proxy; +    //methods and shadows for the dsps +    UHD_PIMPL_DECL(dsp_impl) _dsp_impl; +    void dsp_init(void); +    void issue_ddc_stream_cmd(const uhd::stream_cmd_t &, size_t); + +    //properties interface for ddc +    void ddc_get(const wax::obj &, wax::obj &, size_t); +    void ddc_set(const wax::obj &, const wax::obj &, size_t); +    uhd::dict<std::string, wax_obj_proxy::sptr> _rx_dsp_proxies; + +    //properties interface for duc +    void duc_get(const wax::obj &, wax::obj &, size_t); +    void duc_set(const wax::obj &, const wax::obj &, size_t); +    uhd::dict<std::string, wax_obj_proxy::sptr> _tx_dsp_proxies;      //codec functions and settings      void codec_init(void); diff --git a/host/lib/usrp/usrp_e100/usrp_e100_regs.hpp b/host/lib/usrp/usrp_e100/usrp_e100_regs.hpp index 1bcae64c7..eace5d7df 100644 --- a/host/lib/usrp/usrp_e100/usrp_e100_regs.hpp +++ b/host/lib/usrp/usrp_e100/usrp_e100_regs.hpp @@ -121,92 +121,113 @@  //  Each register must be written 64 bits at a time  //  First the address xxx_xx00 and then xxx_xx10 -#define UE_REG_SETTINGS_BASE_ADDR(n) (UE_REG_SLAVE(8) + (4*(n))) +// 64 total regs in address space +#define UE_SR_RX_CTRL0 0       // 9 regs (+0 to +8) +#define UE_SR_RX_DSP0 10       // 4 regs (+0 to +3) +#define UE_SR_RX_CTRL1 16      // 9 regs (+0 to +8) +#define UE_SR_RX_DSP1 26       // 4 regs (+0 to +3) +#define UE_SR_TX_CTRL 32       // 4 regs (+0 to +3) +#define UE_SR_TX_DSP 38        // 3 regs (+0 to +2) -#define UE_REG_SR_MISC_TEST32        UE_REG_SETTINGS_BASE_ADDR(52) +#define UE_SR_TIME64 42        // 6 regs (+0 to +5) +#define UE_SR_RX_FRONT 48      // 5 regs (+0 to +4) +#define UE_SR_TX_FRONT 54      // 5 regs (+0 to +4) + +#define UE_SR_REG_TEST32 60    // 1 reg +#define UE_SR_CLEAR_RX_FIFO 61 // 1 reg +#define UE_SR_CLEAR_TX_FIFO 62 // 1 reg +#define UE_SR_GLOBAL_RESET 63  // 1 reg + +#define UE_REG_SR_ADDR(n) (UE_REG_SLAVE(8) + (4*(n))) + +#define UE_REG_SR_MISC_TEST32        UE_REG_SR_ADDR(UE_SR_REG_TEST32)  /////////////////////////////////////////////////  // Magic reset regs  //////////////////////////////////////////////// -#define UE_REG_CLEAR_ADDR(n)      (UE_REG_SETTINGS_BASE_ADDR(48) + (4*(n))) -#define UE_REG_CLEAR_RX           UE_REG_CLEAR_ADDR(0) -#define UE_REG_CLEAR_TX           UE_REG_CLEAR_ADDR(1) +#define UE_REG_CLEAR_RX           UE_REG_SR_ADDR(UE_SR_CLEAR_RX_FIFO) +#define UE_REG_CLEAR_TX           UE_REG_SR_ADDR(UE_SR_CLEAR_RX_FIFO) +#define UE_REG_GLOBAL_RESET       UE_REG_SR_ADDR(UE_SR_GLOBAL_RESET)  /////////////////////////////////////////////////  // DSP RX Regs  //////////////////////////////////////////////// -#define UE_REG_DSP_RX_ADDR(n)      (UE_REG_SETTINGS_BASE_ADDR(16) + (4*(n))) -#define UE_REG_DSP_RX_FREQ         UE_REG_DSP_RX_ADDR(0) -#define UE_REG_DSP_RX_SCALE_IQ     UE_REG_DSP_RX_ADDR(1) // {scale_i,scale_q} -#define UE_REG_DSP_RX_DECIM_RATE   UE_REG_DSP_RX_ADDR(2) // hb and decim rate -#define UE_REG_DSP_RX_DCOFFSET_I   UE_REG_DSP_RX_ADDR(3) // Bit 31 high sets fixed offset mode, using lower 14 bits, // otherwise it is automatic -#define UE_REG_DSP_RX_DCOFFSET_Q   UE_REG_DSP_RX_ADDR(4) // Bit 31 high sets fixed offset mode, using lower 14 bits -#define UE_REG_DSP_RX_MUX          UE_REG_DSP_RX_ADDR(5) +#define UE_REG_DSP_RX_HELPER(which, offset) ((which == 0)? \ +    (UE_REG_SR_ADDR(UE_SR_RX_DSP0 + offset)) : \ +    (UE_REG_SR_ADDR(UE_SR_RX_DSP1 + offset))) + +#define UE_REG_DSP_RX_FREQ(which)       UE_REG_DSP_RX_HELPER(which, 0) +#define UE_REG_DSP_RX_DECIM(which)      UE_REG_DSP_RX_HELPER(which, 2) +#define UE_REG_DSP_RX_MUX(which)        UE_REG_DSP_RX_HELPER(which, 3) + +#define UE_FLAG_DSP_RX_MUX_SWAP_IQ   (1 << 0) +#define UE_FLAG_DSP_RX_MUX_REAL_MODE (1 << 1)  /////////////////////////////////////////////////// -// VITA RX CTRL regs +// RX CTRL regs  /////////////////////////////////////////////////// -#define UE_REG_CTRL_RX_ADDR(n)           (UE_REG_SETTINGS_BASE_ADDR(0) + (4*(n))) -// The following 3 are logically a single command register. -// They are clocked into the underlying fifo when time_ticks is written. -#define UE_REG_CTRL_RX_STREAM_CMD        UE_REG_CTRL_RX_ADDR(0) // {now, chain, num_samples(30) -#define UE_REG_CTRL_RX_TIME_SECS         UE_REG_CTRL_RX_ADDR(1) -#define UE_REG_CTRL_RX_TIME_TICKS        UE_REG_CTRL_RX_ADDR(2) -#define UE_REG_CTRL_RX_CLEAR             UE_REG_CTRL_RX_ADDR(3) // write anything to clear -#define UE_REG_CTRL_RX_VRT_HEADER        UE_REG_CTRL_RX_ADDR(4) // word 0 of packet.  FPGA fills in packet counter -#define UE_REG_CTRL_RX_VRT_STREAM_ID     UE_REG_CTRL_RX_ADDR(5) // word 1 of packet. -#define UE_REG_CTRL_RX_VRT_TRAILER       UE_REG_CTRL_RX_ADDR(6) -#define UE_REG_CTRL_RX_NSAMPS_PER_PKT    UE_REG_CTRL_RX_ADDR(7) -#define UE_REG_CTRL_RX_NCHANNELS         UE_REG_CTRL_RX_ADDR(8) // 1 in basic case, up to 4 for vector sources +#define UE_REG_RX_CTRL_HELPER(which, offset) ((which == 0)? \ +    (UE_REG_SR_ADDR(UE_SR_RX_CTRL0 + offset)) : \ +    (UE_REG_SR_ADDR(UE_SR_RX_CTRL1 + offset))) + +#define UE_REG_RX_CTRL_STREAM_CMD(which)     UE_REG_RX_CTRL_HELPER(which, 0) +#define UE_REG_RX_CTRL_TIME_SECS(which)      UE_REG_RX_CTRL_HELPER(which, 1) +#define UE_REG_RX_CTRL_TIME_TICKS(which)     UE_REG_RX_CTRL_HELPER(which, 2) +#define UE_REG_RX_CTRL_CLEAR(which)          UE_REG_RX_CTRL_HELPER(which, 3) +#define UE_REG_RX_CTRL_VRT_HDR(which)        UE_REG_RX_CTRL_HELPER(which, 4) +#define UE_REG_RX_CTRL_VRT_SID(which)        UE_REG_RX_CTRL_HELPER(which, 5) +#define UE_REG_RX_CTRL_VRT_TLR(which)        UE_REG_RX_CTRL_HELPER(which, 6) +#define UE_REG_RX_CTRL_NSAMPS_PP(which)      UE_REG_RX_CTRL_HELPER(which, 7) +#define UE_REG_RX_CTRL_NCHANNELS(which)      UE_REG_RX_CTRL_HELPER(which, 8)  ///////////////////////////////////////////////// -// DSP TX Regs +// RX FE  //////////////////////////////////////////////// -#define UE_REG_DSP_TX_ADDR(n)      (UE_REG_SETTINGS_BASE_ADDR(32) + (4*(n))) -#define UE_REG_DSP_TX_FREQ         UE_REG_DSP_TX_ADDR(0) -#define UE_REG_DSP_TX_SCALE_IQ     UE_REG_DSP_TX_ADDR(1) // {scale_i,scale_q} -#define UE_REG_DSP_TX_INTERP_RATE  UE_REG_DSP_TX_ADDR(2) -#define UE_REG_DSP_TX_UNUSED       UE_REG_DSP_TX_ADDR(3) -#define UE_REG_DSP_TX_MUX          UE_REG_DSP_TX_ADDR(4) +#define UE_REG_RX_FE_SWAP_IQ             UE_REG_SR_ADDR(UE_SR_RX_FRONT + 0) //lower bit +#define UE_REG_RX_FE_MAG_CORRECTION      UE_REG_SR_ADDR(UE_SR_RX_FRONT + 1) //18 bits +#define UE_REG_RX_FE_PHASE_CORRECTION    UE_REG_SR_ADDR(UE_SR_RX_FRONT + 2) //18 bits +#define UE_REG_RX_FE_OFFSET_I            UE_REG_SR_ADDR(UE_SR_RX_FRONT + 3) //18 bits +#define UE_REG_RX_FE_OFFSET_Q            UE_REG_SR_ADDR(UE_SR_RX_FRONT + 4) //18 bits  ///////////////////////////////////////////////// -// VITA TX CTRL regs +// DSP TX Regs  //////////////////////////////////////////////// -#define UE_REG_CTRL_TX_ADDR(n)           (UE_REG_SETTINGS_BASE_ADDR(24) + (4*(n))) -#define UE_REG_CTRL_TX_NCHANNELS         UE_REG_CTRL_TX_ADDR(0) -#define UE_REG_CTRL_TX_CLEAR             UE_REG_CTRL_TX_ADDR(1) -#define UE_REG_CTRL_TX_REPORT_SID        UE_REG_CTRL_TX_ADDR(2) -#define UE_REG_CTRL_TX_POLICY            UE_REG_CTRL_TX_ADDR(3) +#define UE_REG_DSP_TX_FREQ          UE_REG_SR_ADDR(UE_SR_TX_DSP + 0) +#define UE_REG_DSP_TX_SCALE_IQ      UE_REG_SR_ADDR(UE_SR_TX_DSP + 1) +#define UE_REG_DSP_TX_INTERP_RATE   UE_REG_SR_ADDR(UE_SR_TX_DSP + 2) -#define UE_FLAG_CTRL_TX_POLICY_WAIT          (0x1 << 0) -#define UE_FLAG_CTRL_TX_POLICY_NEXT_PACKET   (0x1 << 1) -#define UE_FLAG_CTRL_TX_POLICY_NEXT_BURST    (0x1 << 2) +/////////////////////////////////////////////////// +// TX CTRL regs +/////////////////////////////////////////////////// +#define UE_REG_TX_CTRL_NUM_CHAN       UE_REG_SR_ADDR(UE_SR_TX_CTRL + 0) +#define UE_REG_TX_CTRL_CLEAR_STATE    UE_REG_SR_ADDR(UE_SR_TX_CTRL + 1) +#define UE_REG_TX_CTRL_REPORT_SID     UE_REG_SR_ADDR(UE_SR_TX_CTRL + 2) +#define UE_REG_TX_CTRL_POLICY         UE_REG_SR_ADDR(UE_SR_TX_CTRL + 3) +#define UE_REG_TX_CTRL_CYCLES_PER_UP  UE_REG_SR_ADDR(UE_SR_TX_CTRL + 4) +#define UE_REG_TX_CTRL_PACKETS_PER_UP UE_REG_SR_ADDR(UE_SR_TX_CTRL + 5) + +#define UE_FLAG_TX_CTRL_POLICY_WAIT          (0x1 << 0) +#define UE_FLAG_TX_CTRL_POLICY_NEXT_PACKET   (0x1 << 1) +#define UE_FLAG_TX_CTRL_POLICY_NEXT_BURST    (0x1 << 2) + +///////////////////////////////////////////////// +// TX FE +//////////////////////////////////////////////// +#define UE_REG_TX_FE_DC_OFFSET_I         UE_REG_SR_ADDR(UE_SR_TX_FRONT + 0) //24 bits +#define UE_REG_TX_FE_DC_OFFSET_Q         UE_REG_SR_ADDR(UE_SR_TX_FRONT + 1) //24 bits +#define UE_REG_TX_FE_MAC_CORRECTION      UE_REG_SR_ADDR(UE_SR_TX_FRONT + 2) //18 bits +#define UE_REG_TX_FE_PHASE_CORRECTION    UE_REG_SR_ADDR(UE_SR_TX_FRONT + 3) //18 bits +#define UE_REG_TX_FE_MUX                 UE_REG_SR_ADDR(UE_SR_TX_FRONT + 4) //8 bits (std output = 0x10, reversed = 0x01)  /////////////////////////////////////////////////  // VITA49 64 bit time (write only)  //////////////////////////////////////////////// -  /*! -   * \brief Time 64 flags -   * -   * <pre> -   * -   *    3                   2                   1 -   *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 -   * +-----------------------------------------------------------+-+-+ -   * |                                                           |S|P| -   * +-----------------------------------------------------------+-+-+ -   * -   * P - PPS edge selection (0=negedge, 1=posedge, default=0) -   * S - Source (0=sma, 1=mimo, 0=default) -   * -   * </pre> -   */ -#define UE_REG_TIME64_ADDR(n)     (UE_REG_SETTINGS_BASE_ADDR(40) + (4*(n))) -#define UE_REG_TIME64_SECS        UE_REG_TIME64_ADDR(0)  // value to set absolute secs to on next PPS -#define UE_REG_TIME64_TICKS       UE_REG_TIME64_ADDR(1)  // value to set absolute ticks to on next PPS -#define UE_REG_TIME64_FLAGS       UE_REG_TIME64_ADDR(2)  // flags - see chart above -#define UE_REG_TIME64_IMM         UE_REG_TIME64_ADDR(3)  // set immediate (0=latch on next pps, 1=latch immediate, default=0) -#define UE_REG_TIME64_TPS         UE_REG_TIME64_ADDR(4)  // clock ticks per second (counter rollover) +#define UE_REG_TIME64_SECS      UE_REG_SR_ADDR(UE_SR_TIME64 + 0) +#define UE_REG_TIME64_TICKS     UE_REG_SR_ADDR(UE_SR_TIME64 + 1) +#define UE_REG_TIME64_FLAGS     UE_REG_SR_ADDR(UE_SR_TIME64 + 2) +#define UE_REG_TIME64_IMM       UE_REG_SR_ADDR(UE_SR_TIME64 + 3) +#define UE_REG_TIME64_TPS       UE_REG_SR_ADDR(UE_SR_TIME64 + 4) +#define UE_REG_TIME64_MIMO_SYNC UE_REG_SR_ADDR(UE_SR_TIME64 + 5)  //pps flags (see above)  #define UE_FLAG_TIME64_PPS_NEGEDGE (0 << 0) | 
