aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIan Buckley <github@ionconcepts.com>2015-01-02 10:33:14 -0800
committerMartin Braun <martin.braun@ettus.com>2015-01-19 09:22:25 +0100
commit6b50a6bcd93bde8bced6adb9b09c6fe247bcde92 (patch)
tree681ace48f759d3811d644ff38a8bb6a47555fc90
parente76ceef05331fcf8bb6d1855f5c06b483851d07b (diff)
downloaduhd-6b50a6bcd93bde8bced6adb9b09c6fe247bcde92.tar.gz
uhd-6b50a6bcd93bde8bced6adb9b09c6fe247bcde92.tar.bz2
uhd-6b50a6bcd93bde8bced6adb9b09c6fe247bcde92.zip
B200: Bug #656. Added FIR coeffs for filters with Fs/4 stop band.
AD9361 driver can now select coeffs for different interpolation ratios.
-rw-r--r--host/lib/usrp/common/ad9361_ctrl.cpp7
-rw-r--r--host/lib/usrp/common/ad9361_driver/ad9361_device.cpp39
-rw-r--r--host/lib/usrp/common/ad9361_driver/ad9361_device.h5
-rw-r--r--host/lib/usrp/common/ad9361_driver/ad9361_filter_taps.h35
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