Revision 615af6ca host/lib/usrp/usrp_e100/dsp_impl.cpp
| b/host/lib/usrp/usrp_e100/dsp_impl.cpp | ||
|---|---|---|
| 22 | 22 |
#include <boost/math/special_functions/round.hpp> |
| 23 | 23 |
#include <boost/bind.hpp> |
| 24 | 24 |
|
| 25 |
#define rint boost::math::iround |
|
| 26 |
|
|
| 27 | 25 |
using namespace uhd; |
| 28 | 26 |
using namespace uhd::usrp; |
| 29 | 27 |
|
| 30 | 28 |
/*********************************************************************** |
| 29 |
* DSP impl and methods |
|
| 30 |
**********************************************************************/ |
|
| 31 |
struct usrp_e100_impl::dsp_impl{
|
|
| 32 |
uhd::dict<size_t, size_t> ddc_decim; |
|
| 33 |
uhd::dict<size_t, double> ddc_freq; |
|
| 34 |
uhd::dict<size_t, size_t> duc_interp; |
|
| 35 |
uhd::dict<size_t, double> duc_freq; |
|
| 36 |
}; |
|
| 37 |
|
|
| 38 |
/*********************************************************************** |
|
| 31 | 39 |
* RX DDC Initialization |
| 32 | 40 |
**********************************************************************/ |
| 33 |
void usrp_e100_impl::rx_ddc_init(void){
|
|
| 34 |
_rx_ddc_proxy = wax_obj_proxy::make( |
|
| 35 |
boost::bind(&usrp_e100_impl::rx_ddc_get, this, _1, _2), |
|
| 36 |
boost::bind(&usrp_e100_impl::rx_ddc_set, this, _1, _2) |
|
| 37 |
); |
|
| 38 |
|
|
| 39 |
//initial config and update |
|
| 40 |
rx_ddc_set(DSP_PROP_FREQ_SHIFT, double(0)); |
|
| 41 |
rx_ddc_set(DSP_PROP_HOST_RATE, double(16e6)); |
|
| 41 |
void usrp_e100_impl::dsp_init(void){
|
|
| 42 |
//create new dsp impl |
|
| 43 |
_dsp_impl = UHD_PIMPL_MAKE(dsp_impl, ()); |
|
| 44 |
|
|
| 45 |
//bind and initialize the rx dsps |
|
| 46 |
for (size_t i = 0; i < E100_NUM_RX_DSPS; i++){
|
|
| 47 |
_rx_dsp_proxies[str(boost::format("DSP%d")%i)] = wax_obj_proxy::make(
|
|
| 48 |
boost::bind(&usrp_e100_impl::ddc_get, this, _1, _2, i), |
|
| 49 |
boost::bind(&usrp_e100_impl::ddc_set, this, _1, _2, i) |
|
| 50 |
); |
|
| 51 |
|
|
| 52 |
//initial config and update |
|
| 53 |
ddc_set(DSP_PROP_FREQ_SHIFT, double(0), i); |
|
| 54 |
ddc_set(DSP_PROP_HOST_RATE, double(_clock_ctrl->get_fpga_clock_rate()/16), i); |
|
| 55 |
|
|
| 56 |
//setup the rx control registers |
|
| 57 |
_iface->poke32(UE_REG_RX_CTRL_CLEAR(i), 1); //reset |
|
| 58 |
_iface->poke32(UE_REG_RX_CTRL_NSAMPS_PP(i), this->get_max_recv_samps_per_packet()); |
|
| 59 |
_iface->poke32(UE_REG_RX_CTRL_NCHANNELS(i), 1); |
|
| 60 |
_iface->poke32(UE_REG_RX_CTRL_VRT_HDR(i), 0 |
|
| 61 |
| (0x1 << 28) //if data with stream id |
|
| 62 |
| (0x1 << 26) //has trailer |
|
| 63 |
| (0x3 << 22) //integer time other |
|
| 64 |
| (0x1 << 20) //fractional time sample count |
|
| 65 |
); |
|
| 66 |
_iface->poke32(UE_REG_RX_CTRL_VRT_SID(i), E100_DSP_SID_BASE + i); |
|
| 67 |
_iface->poke32(UE_REG_RX_CTRL_VRT_TLR(i), 0); |
|
| 68 |
_iface->poke32(UE_REG_TIME64_TPS, size_t(_clock_ctrl->get_fpga_clock_rate())); |
|
| 69 |
} |
|
| 70 |
|
|
| 71 |
//bind and initialize the tx dsps |
|
| 72 |
for (size_t i = 0; i < E100_NUM_TX_DSPS; i++){
|
|
| 73 |
_tx_dsp_proxies[str(boost::format("DSP%d")%i)] = wax_obj_proxy::make(
|
|
| 74 |
boost::bind(&usrp_e100_impl::duc_get, this, _1, _2, i), |
|
| 75 |
boost::bind(&usrp_e100_impl::duc_set, this, _1, _2, i) |
|
| 76 |
); |
|
| 77 |
|
|
| 78 |
//initial config and update |
|
| 79 |
duc_set(DSP_PROP_FREQ_SHIFT, double(0), i); |
|
| 80 |
duc_set(DSP_PROP_HOST_RATE, double(_clock_ctrl->get_fpga_clock_rate()/16), i); |
|
| 81 |
|
|
| 82 |
//init the tx control registers |
|
| 83 |
_iface->poke32(UE_REG_TX_CTRL_CLEAR_STATE, 1); //reset |
|
| 84 |
_iface->poke32(UE_REG_TX_CTRL_NUM_CHAN, 0); //1 channel |
|
| 85 |
_iface->poke32(UE_REG_TX_CTRL_REPORT_SID, E100_ASYNC_SID); |
|
| 86 |
_iface->poke32(UE_REG_TX_CTRL_POLICY, UE_FLAG_TX_CTRL_POLICY_NEXT_PACKET); |
|
| 87 |
} |
|
| 42 | 88 |
} |
| 43 | 89 |
|
| 44 | 90 |
/*********************************************************************** |
| 45 | 91 |
* RX DDC Get |
| 46 | 92 |
**********************************************************************/ |
| 47 |
void usrp_e100_impl::rx_ddc_get(const wax::obj &key_, wax::obj &val){
|
|
| 93 |
void usrp_e100_impl::ddc_get(const wax::obj &key_, wax::obj &val, size_t which_dsp){
|
|
| 48 | 94 |
named_prop_t key = named_prop_t::extract(key_); |
| 49 | 95 |
|
| 50 | 96 |
switch(key.as<dsp_prop_t>()){
|
| 51 | 97 |
case DSP_PROP_NAME: |
| 52 |
val = std::string("usrp-e ddc0");
|
|
| 98 |
val = str(boost::format("%s ddc%d") % _iface->get_cname() % which_dsp);
|
|
| 53 | 99 |
return; |
| 54 | 100 |
|
| 55 | 101 |
case DSP_PROP_OTHERS: |
| ... | ... | |
| 57 | 103 |
return; |
| 58 | 104 |
|
| 59 | 105 |
case DSP_PROP_FREQ_SHIFT: |
| 60 |
val = _ddc_freq;
|
|
| 106 |
val = _dsp_impl->ddc_freq[which_dsp];
|
|
| 61 | 107 |
return; |
| 62 | 108 |
|
| 63 | 109 |
case DSP_PROP_CODEC_RATE: |
| ... | ... | |
| 65 | 111 |
return; |
| 66 | 112 |
|
| 67 | 113 |
case DSP_PROP_HOST_RATE: |
| 68 |
val = _clock_ctrl->get_fpga_clock_rate()/_ddc_decim;
|
|
| 114 |
val = _clock_ctrl->get_fpga_clock_rate()/_dsp_impl->ddc_decim[which_dsp];
|
|
| 69 | 115 |
return; |
| 70 | 116 |
|
| 71 | 117 |
default: UHD_THROW_PROP_GET_ERROR(); |
| ... | ... | |
| 75 | 121 |
/*********************************************************************** |
| 76 | 122 |
* RX DDC Set |
| 77 | 123 |
**********************************************************************/ |
| 78 |
void usrp_e100_impl::rx_ddc_set(const wax::obj &key_, const wax::obj &val){
|
|
| 124 |
void usrp_e100_impl::ddc_set(const wax::obj &key_, const wax::obj &val, size_t which_dsp){
|
|
| 79 | 125 |
named_prop_t key = named_prop_t::extract(key_); |
| 80 | 126 |
|
| 81 | 127 |
switch(key.as<dsp_prop_t>()){
|
| 82 | 128 |
|
| 83 | 129 |
case DSP_PROP_STREAM_CMD: |
| 84 |
issue_stream_cmd(val.as<stream_cmd_t>());
|
|
| 130 |
issue_ddc_stream_cmd(val.as<stream_cmd_t>(), which_dsp);
|
|
| 85 | 131 |
return; |
| 86 | 132 |
|
| 87 | 133 |
case DSP_PROP_FREQ_SHIFT:{
|
| 88 | 134 |
double new_freq = val.as<double>(); |
| 89 |
_iface->poke32(UE_REG_DSP_RX_FREQ, |
|
| 135 |
_iface->poke32(UE_REG_DSP_RX_FREQ(which_dsp),
|
|
| 90 | 136 |
dsp_type1::calc_cordic_word_and_update(new_freq, _clock_ctrl->get_fpga_clock_rate()) |
| 91 | 137 |
); |
| 92 |
_ddc_freq = new_freq; //shadow
|
|
| 138 |
_dsp_impl->ddc_freq[which_dsp] = new_freq; //shadow
|
|
| 93 | 139 |
} |
| 94 | 140 |
return; |
| 95 | 141 |
|
| 96 | 142 |
case DSP_PROP_HOST_RATE:{
|
| 97 |
//set the decimation |
|
| 98 |
_ddc_decim = rint(_clock_ctrl->get_fpga_clock_rate()/val.as<double>()); |
|
| 99 |
_iface->poke32(UE_REG_DSP_RX_DECIM_RATE, dsp_type1::calc_cic_filter_word(_ddc_decim)); |
|
| 143 |
_dsp_impl->ddc_decim[which_dsp] = boost::math::iround(_clock_ctrl->get_fpga_clock_rate()/val.as<double>()); |
|
| 100 | 144 |
|
| 101 |
//set the scaling |
|
| 102 |
static const boost::int16_t default_rx_scale_iq = 1024; |
|
| 103 |
_iface->poke32(UE_REG_DSP_RX_SCALE_IQ, |
|
| 104 |
dsp_type1::calc_iq_scale_word(default_rx_scale_iq, default_rx_scale_iq) |
|
| 105 |
); |
|
| 145 |
//set the decimation |
|
| 146 |
_iface->poke32(UE_REG_DSP_RX_DECIM(which_dsp), dsp_type1::calc_cic_filter_word(_dsp_impl->ddc_decim[which_dsp])); |
|
| 106 | 147 |
} |
| 107 | 148 |
this->update_xport_channel_mapping(); //rate changed -> update |
| 108 | 149 |
return; |
| ... | ... | |
| 112 | 153 |
} |
| 113 | 154 |
|
| 114 | 155 |
/*********************************************************************** |
| 115 |
* TX DUC Initialization |
|
| 116 |
**********************************************************************/ |
|
| 117 |
void usrp_e100_impl::tx_duc_init(void){
|
|
| 118 |
_tx_duc_proxy = wax_obj_proxy::make( |
|
| 119 |
boost::bind(&usrp_e100_impl::tx_duc_get, this, _1, _2), |
|
| 120 |
boost::bind(&usrp_e100_impl::tx_duc_set, this, _1, _2) |
|
| 121 |
); |
|
| 122 |
|
|
| 123 |
//initial config and update |
|
| 124 |
tx_duc_set(DSP_PROP_FREQ_SHIFT, double(0)); |
|
| 125 |
tx_duc_set(DSP_PROP_HOST_RATE, double(16e6)); |
|
| 126 |
} |
|
| 127 |
|
|
| 128 |
/*********************************************************************** |
|
| 129 | 156 |
* TX DUC Get |
| 130 | 157 |
**********************************************************************/ |
| 131 |
void usrp_e100_impl::tx_duc_get(const wax::obj &key_, wax::obj &val){
|
|
| 158 |
void usrp_e100_impl::duc_get(const wax::obj &key_, wax::obj &val, size_t which_dsp){
|
|
| 132 | 159 |
named_prop_t key = named_prop_t::extract(key_); |
| 133 | 160 |
|
| 134 | 161 |
switch(key.as<dsp_prop_t>()){
|
| 135 | 162 |
case DSP_PROP_NAME: |
| 136 |
val = std::string("usrp-e duc0");
|
|
| 163 |
val = str(boost::format("%s duc%d") % _iface->get_cname() % which_dsp);
|
|
| 137 | 164 |
return; |
| 138 | 165 |
|
| 139 | 166 |
case DSP_PROP_OTHERS: |
| ... | ... | |
| 141 | 168 |
return; |
| 142 | 169 |
|
| 143 | 170 |
case DSP_PROP_FREQ_SHIFT: |
| 144 |
val = _duc_freq;
|
|
| 171 |
val = _dsp_impl->duc_freq[which_dsp];
|
|
| 145 | 172 |
return; |
| 146 | 173 |
|
| 147 | 174 |
case DSP_PROP_CODEC_RATE: |
| ... | ... | |
| 149 | 176 |
return; |
| 150 | 177 |
|
| 151 | 178 |
case DSP_PROP_HOST_RATE: |
| 152 |
val = _clock_ctrl->get_fpga_clock_rate()/_duc_interp;
|
|
| 179 |
val = _clock_ctrl->get_fpga_clock_rate()/_dsp_impl->duc_interp[which_dsp];
|
|
| 153 | 180 |
return; |
| 154 | 181 |
|
| 155 | 182 |
default: UHD_THROW_PROP_GET_ERROR(); |
| ... | ... | |
| 159 | 186 |
/*********************************************************************** |
| 160 | 187 |
* TX DUC Set |
| 161 | 188 |
**********************************************************************/ |
| 162 |
void usrp_e100_impl::tx_duc_set(const wax::obj &key_, const wax::obj &val){
|
|
| 189 |
void usrp_e100_impl::duc_set(const wax::obj &key_, const wax::obj &val, size_t which_dsp){
|
|
| 163 | 190 |
named_prop_t key = named_prop_t::extract(key_); |
| 164 | 191 |
|
| 165 | 192 |
switch(key.as<dsp_prop_t>()){
|
| ... | ... | |
| 169 | 196 |
_iface->poke32(UE_REG_DSP_TX_FREQ, |
| 170 | 197 |
dsp_type1::calc_cordic_word_and_update(new_freq, _clock_ctrl->get_fpga_clock_rate()) |
| 171 | 198 |
); |
| 172 |
_duc_freq = new_freq; //shadow
|
|
| 199 |
_dsp_impl->duc_freq[which_dsp] = new_freq; //shadow
|
|
| 173 | 200 |
} |
| 174 | 201 |
return; |
| 175 | 202 |
|
| 176 | 203 |
case DSP_PROP_HOST_RATE:{
|
| 177 |
_duc_interp = rint(_clock_ctrl->get_fpga_clock_rate()/val.as<double>());
|
|
| 204 |
_dsp_impl->duc_interp[which_dsp] = boost::math::iround(_clock_ctrl->get_fpga_clock_rate()/val.as<double>());
|
|
| 178 | 205 |
|
| 179 | 206 |
//set the interpolation |
| 180 |
_iface->poke32(UE_REG_DSP_TX_INTERP_RATE, dsp_type1::calc_cic_filter_word(_duc_interp));
|
|
| 207 |
_iface->poke32(UE_REG_DSP_TX_INTERP_RATE, dsp_type1::calc_cic_filter_word(_dsp_impl->duc_interp[which_dsp]));
|
|
| 181 | 208 |
|
| 182 | 209 |
//set the scaling |
| 183 |
_iface->poke32(UE_REG_DSP_TX_SCALE_IQ, dsp_type1::calc_iq_scale_word(_duc_interp));
|
|
| 210 |
_iface->poke32(UE_REG_DSP_TX_SCALE_IQ, dsp_type1::calc_iq_scale_word(_dsp_impl->duc_interp[which_dsp]));
|
|
| 184 | 211 |
} |
| 185 | 212 |
this->update_xport_channel_mapping(); //rate changed -> update |
| 186 | 213 |
return; |
Also available in: Unified diff