diff options
Diffstat (limited to 'host')
| -rw-r--r-- | host/lib/usrp/common/ad9361_ctrl.cpp | 7 | ||||
| -rw-r--r-- | host/lib/usrp/common/ad9361_driver/ad9361_device.cpp | 39 | ||||
| -rw-r--r-- | host/lib/usrp/common/ad9361_driver/ad9361_device.h | 5 | ||||
| -rw-r--r-- | host/lib/usrp/common/ad9361_driver/ad9361_filter_taps.h | 35 | 
4 files changed, 69 insertions, 17 deletions
| diff --git a/host/lib/usrp/common/ad9361_ctrl.cpp b/host/lib/usrp/common/ad9361_ctrl.cpp index f94536ed9..85510530d 100644 --- a/host/lib/usrp/common/ad9361_ctrl.cpp +++ b/host/lib/usrp/common/ad9361_ctrl.cpp @@ -123,6 +123,13 @@ public:          const meta_range_t clock_rate_range = ad9361_ctrl::get_clock_rate_range();          const double clipped_rate = clock_rate_range.clip(rate); +        if (clipped_rate != rate) { +            UHD_MSG(warning) << boost::format( +                    "The requested master_clock_rate %f MHz exceeds bounds imposed by UHD.\n" +                    "The master_clock_rate has been forced to %f MHz.\n" +            ) % (rate/1e6) % (clipped_rate/1e6) << std::endl; +        } +          return _device.set_clock_rate(clipped_rate);      } diff --git a/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp b/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp index b5e116a70..3abcdc157 100644 --- a/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp +++ b/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp @@ -143,22 +143,22 @@ void ad9361_device_t::_program_fir_filter(direction_t direction, int num_taps, b  /* Program the RX FIR Filter. */ -void ad9361_device_t::_setup_rx_fir(size_t num_taps) +void ad9361_device_t::_setup_rx_fir(size_t num_taps, boost::int32_t interpolation)  {      boost::scoped_array<boost::uint16_t> coeffs(new boost::uint16_t[num_taps]);      for (size_t i = 0; i < num_taps; i++) {          switch (num_taps) {          case 128: -            coeffs[i] = boost::uint16_t(hb127_coeffs[i]); +            coeffs[i] = boost::uint16_t((interpolation==4) ? fir_128_x4_coeffs[i] : hb127_coeffs[i]);              break;          case 96: -            coeffs[i] = boost::uint16_t(hb95_coeffs[i]); +            coeffs[i] = boost::uint16_t((interpolation==4) ? fir_96_x4_coeffs[i] : hb95_coeffs[i]);              break;          case 64: -            coeffs[i] = boost::uint16_t(hb63_coeffs[i]); +            coeffs[i] = boost::uint16_t((interpolation==4) ? fir_64_x4_coeffs[i] : hb63_coeffs[i]);              break;          case 48: -            coeffs[i] = boost::uint16_t(hb47_coeffs[i]); +            coeffs[i] = boost::uint16_t((interpolation==4) ? fir_48_x4_coeffs[i] : hb47_coeffs[i]);              break;          default:              throw uhd::runtime_error("[ad9361_device_t] Unsupported number of Rx FIR taps."); @@ -169,22 +169,22 @@ void ad9361_device_t::_setup_rx_fir(size_t num_taps)  }  /* Program the TX FIR Filter. */ -void ad9361_device_t::_setup_tx_fir(size_t num_taps) +void ad9361_device_t::_setup_tx_fir(size_t num_taps, boost::int32_t interpolation)  {      boost::scoped_array<boost::uint16_t> coeffs(new boost::uint16_t[num_taps]);      for (size_t i = 0; i < num_taps; i++) {          switch (num_taps) {          case 128: -            coeffs[i] = boost::uint16_t(hb127_coeffs[i]); +	    coeffs[i] = boost::uint16_t((interpolation==4) ? fir_128_x4_coeffs[i] : hb127_coeffs[i]);              break;          case 96: -            coeffs[i] = boost::uint16_t(hb95_coeffs[i]); +            coeffs[i] = boost::uint16_t((interpolation==4) ? fir_96_x4_coeffs[i] : hb95_coeffs[i]);              break;          case 64: -            coeffs[i] = boost::uint16_t(hb63_coeffs[i]); +            coeffs[i] = boost::uint16_t((interpolation==4) ? fir_64_x4_coeffs[i] : hb63_coeffs[i]);              break;          case 48: -            coeffs[i] = boost::uint16_t(hb47_coeffs[i]); +            coeffs[i] = boost::uint16_t((interpolation==4) ? fir_48_x4_coeffs[i] : hb47_coeffs[i]);              break;          default:              throw uhd::runtime_error("[ad9361_device_t] Unsupported number of Tx FIR taps."); @@ -1231,6 +1231,7 @@ double ad9361_device_t::_setup_rates(const double rate)      /* If we make it into this function, then we are tuning to a new rate.       * Store the new rate. */      _req_clock_rate = rate; +    UHD_LOG << boost::format("[ad9361_device_t::_setup_rates] rate=%d\n") % rate;      /* Set the decimation and interpolation values in the RX and TX chains.       * This also switches filters in / out. Note that all transmitters and @@ -1239,6 +1240,7 @@ double ad9361_device_t::_setup_rates(const double rate)       * user-requested antenna selections. */      int divfactor = 0;      _tfir_factor = 0; +    _rfir_factor = 0;      if (rate < 0.33e6) {          // RX1 + RX2 enabled, 3, 2, 2, 4          _regs.rxfilt = B8(11101111); @@ -1247,7 +1249,8 @@ double ad9361_device_t::_setup_rates(const double rate)          _regs.txfilt = B8(11101111);          divfactor = 48; -        _tfir_factor = 2; +        _tfir_factor = 4; +        _rfir_factor = 4;      } else if (rate < 0.66e6) {          // RX1 + RX2 enabled, 2, 2, 2, 4          _regs.rxfilt = B8(11011111); @@ -1256,7 +1259,8 @@ double ad9361_device_t::_setup_rates(const double rate)          _regs.txfilt = B8(11011111);          divfactor = 32; -        _tfir_factor = 2; +        _tfir_factor = 4; +        _rfir_factor = 4;      } else if (rate <= 20e6) {          // RX1 + RX2 enabled, 2, 2, 2, 2          _regs.rxfilt = B8(11011110); @@ -1266,6 +1270,7 @@ double ad9361_device_t::_setup_rates(const double rate)          divfactor = 16;          _tfir_factor = 2; +        _rfir_factor = 2;      } else if ((rate > 20e6) && (rate < 23e6)) {          // RX1 + RX2 enabled, 3, 2, 2, 2          _regs.rxfilt = B8(11101110); @@ -1275,6 +1280,7 @@ double ad9361_device_t::_setup_rates(const double rate)          divfactor = 24;          _tfir_factor = 2; +        _rfir_factor = 2;      } else if ((rate >= 23e6) && (rate < 41e6)) {          // RX1 + RX2 enabled, 2, 2, 2, 2          _regs.rxfilt = B8(11011110); @@ -1284,6 +1290,7 @@ double ad9361_device_t::_setup_rates(const double rate)          divfactor = 16;          _tfir_factor = 2; +        _rfir_factor = 2;      } else if ((rate >= 41e6) && (rate <= 56e6)) {          // RX1 + RX2 enabled, 3, 1, 2, 2          _regs.rxfilt = B8(11100110); @@ -1293,6 +1300,7 @@ double ad9361_device_t::_setup_rates(const double rate)          divfactor = 12;          _tfir_factor = 2; +        _rfir_factor = 2;      } else if ((rate > 56e6) && (rate <= 61.44e6)) {          // RX1 + RX2 enabled, 3, 1, 1, 2          _regs.rxfilt = B8(11100010); @@ -1302,6 +1310,7 @@ double ad9361_device_t::_setup_rates(const double rate)          divfactor = 6;          _tfir_factor = 1; +        _rfir_factor = 2;      } else {          // should never get in here          throw uhd::runtime_error("[ad9361_device_t] [_setup_rates] INVALID_CODE_PATH"); @@ -1349,8 +1358,8 @@ double ad9361_device_t::_setup_rates(const double rate)      const size_t num_tx_taps = get_num_taps(max_tx_taps);      const size_t num_rx_taps = get_num_taps(max_rx_taps); -    _setup_tx_fir(num_tx_taps); -    _setup_rx_fir(num_rx_taps); +    _setup_tx_fir(num_tx_taps,_tfir_factor); +    _setup_rx_fir(num_rx_taps,_rfir_factor);      return _baseband_bw;  } @@ -1604,7 +1613,7 @@ double ad9361_device_t::set_clock_rate(const double req_rate)       * starts up. This prevents that, and any bugs in user code that request       * the same rate over and over. */      if (freq_is_nearly_equal(req_rate, _req_clock_rate)) { -        return _baseband_bw; +        return _baseband_bw; // IJB. Should this not return req_rate?      }      /* We must be in the SLEEP / WAIT state to do this. If we aren't already diff --git a/host/lib/usrp/common/ad9361_driver/ad9361_device.h b/host/lib/usrp/common/ad9361_driver/ad9361_device.h index 8c163572c..bd93bd06b 100644 --- a/host/lib/usrp/common/ad9361_driver/ad9361_device.h +++ b/host/lib/usrp/common/ad9361_driver/ad9361_device.h @@ -73,8 +73,8 @@ public:  private:    //Methods      void _program_fir_filter(direction_t direction, int num_taps, boost::uint16_t *coeffs); -    void _setup_tx_fir(size_t num_taps); -    void _setup_rx_fir(size_t num_taps); +    void _setup_tx_fir(size_t num_taps, boost::int32_t interpolation); +    void _setup_rx_fir(size_t num_taps, boost::int32_t interpolation);      void _calibrate_lock_bbpll();      void _calibrate_synth_charge_pumps();      double _calibrate_baseband_rx_analog_filter(); @@ -118,6 +118,7 @@ private:    //Members      boost::uint8_t      _curr_gain_table;      boost::uint32_t     _rx1_gain, _rx2_gain, _tx1_gain, _tx2_gain;      boost::int32_t      _tfir_factor; +    boost::int32_t      _rfir_factor;      //Register soft-copies      chip_regs_t         _regs;      //Synchronization diff --git a/host/lib/usrp/common/ad9361_driver/ad9361_filter_taps.h b/host/lib/usrp/common/ad9361_driver/ad9361_filter_taps.h index 4059ad7ee..a1a85a49a 100644 --- a/host/lib/usrp/common/ad9361_driver/ad9361_filter_taps.h +++ b/host/lib/usrp/common/ad9361_driver/ad9361_filter_taps.h @@ -45,6 +45,9 @@ static uint16_t lte10mhz_tx_coeffs[] = {  };  */ +/************************************************************/ +/* These filters suitable for decimation/interpolation by 2 */ +/************************************************************/  /* 127 tap Halfband designed with: round(2^16 * halfgen4(0.9/4,32)) (center tap tweaked to 32767) */  static boost::int16_t hb127_coeffs[] = { @@ -69,5 +72,37 @@ static boost::int16_t hb47_coeffs[] = {    -50,0,98,-0,-181,0,307,-0,-489,0,747,-0,-1109,0,1628,-0,-2413,0,3750,-0,-6693,0,20773,32767,20773,0,-6693,-0,3750,0,-2413,-0,    1628,0,-1109,-0,747,0,-489,-0,307,0,-181,-0,98,0,-50,0}; +/************************************************************/ +/* These filters suitable for decimation/interpolation by 4 */ +/* Designed for -3dB rolloff @ Fs/4                         */ +/************************************************************/ + +/* 128 tap equiripple FIR low-pass designed with: round(2^16 * fir1(127,0.25)); */ +static boost::int16_t fir_128_x4_coeffs[] = { +  -15,-27,-23,-6,17,33,31,9,-23,-47,-45,-13,34,69,67,21,-49,-102,-99,-32,69,146,143,48,-96,-204,-200,-69,129,278,275,97,-170, +  -372,-371,-135,222,494,497,187,-288,-654,-665,-258,376,875,902,363,-500,-1201,-1265,-530,699,1748,1906,845,-1089,-2922,-3424, +  -1697,2326,7714,12821,15921,15921,12821,7714,2326,-1697,-3424,-2922,-1089,845,1906,1748,699,-530,-1265,-1201,-500,363,902,875, +  376,-258,-665,-654,-288,187,497,494,222,-135,-371,-372,-170,97,275,278,129,-69,-200,-204,-96,48,143,146,69,-32,-99,-102,-49,21, +  67,69,34,-13,-45,-47,-23,9,31,33,17,-6,-23,-27,-15}; + +/* 96 tap equiripple FIR low-pass designed with: round(2^16 * fir1(95,0.25)); */ +static boost::int16_t fir_96_x4_coeffs[] = { +  -18,-35,-33,-11,23,50,51,18,-37,-83,-86,-31,62,140,145,54,-98,-224,-232,-88,149,343,356,138,-218,-509,-530,-211,313,743,781, +  320,-447,-1089,-1163,-494,658,1663,1830,819,-1062,-2868,-3379,-1682,2314,7695,12812,15924,15924,12812,7695,2314,-1682,-3379, +  -2868,-1062,819,1830,1663,658,-494,-1163,-1089,-447,320,781,743,313,-211,-530,-509,-218,138,356,343,149,-88,-232,-224,-98,54, +  145,140,62,-31,-86,-83,-37,18,51,50,23,-11,-33,-35,-18}; + +/* 64 tap equiripple FIR low-pass designed with: round(2^16 * fir1(63,0.25)); */ +static boost::int16_t fir_64_x4_coeffs[] = { +  -25,-54,-56,-22,41,102,117,50,-87,-223,-253,-109,174,443,496,215,-317,-809,-903,-398,550,1434,1623,744,-987,-2715,-3251, +  -1640,2279,7638,12782,15928,15928,12782,7638,2279,-1640,-3251,-2715,-987,744,1623,1434,550,-398,-903,-809,-317,215,496, +  443,174,-109,-253,-223,-87,50,117,102,41,-22,-56,-54,-25}; + + /* 48 tap equiripple FIR low-pass designed with: round(2^16 * fir1(47,0.25)); */ +static boost::int16_t fir_48_x4_coeffs[] = { +  -32,-74,-84,-39,68,191,237,114,-183,-508,-609,-287,419,1149,1358,647,-887,-2508,-3073,-1580,2230,7555,12736,15928,15928, +  12736,7555,2230,-1580,-3073,-2508,-887,647,1358,1149,419,-287,-609,-508,-183,114,237,191,68,-39,-84,-74,-32}; + +/* NOTE: To write coeffs directly from Octave in a format that's useful in C use: dlmwrite ("file.csv",bb,","); */  #endif // INCLUDED_AD9361_FILTER_TAPS_HPP | 
