Transceiver52M: Add device offset correction table

Previously, two timing correction values were used for UHD devices
depending on the sample rate of 270.833e3 or 400e3 for native GSM or
resampled device rate respectively. The correction values compensate
for residual timing effects due to analog component delays, filters
lag times, and general fudge factors. These values are device
specific and over-generalized by the two value configuration.

This patch adds the following struct to store these correction
values by device type and sample rate - through samples-per-symbol.

struct uhd_dev_offset {
        enum uhd_dev_type type;
        int sps;
        double offset;
};

Signed-off-by: Thomas Tsou <tom@tsou.cc>
This commit is contained in:
Thomas Tsou 2013-04-05 20:42:41 -04:00
parent 02d88d1380
commit e3e8814948
4 changed files with 64 additions and 29 deletions

View File

@ -32,7 +32,9 @@
#include "config.h"
#endif
#define B100_CLK_RT 52e6
#define B100_CLK_RT 52e6
#define TX_AMPL 0.3
#define SAMPLE_BUF_SZ (1 << 20)
enum uhd_dev_type {
USRP1,
@ -41,28 +43,53 @@ enum uhd_dev_type {
NUM_USRP_TYPES,
};
struct uhd_dev_offset {
enum uhd_dev_type type;
int sps;
double offset;
};
/*
master_clk_rt - Master clock frequency - ignored if host resampling is
enabled
* Tx / Rx sample offset values. In a perfect world, there is no group delay
* though analog components, and behaviour through digital filters exactly
* matches calculated values. In reality, there are unaccounted factors,
* which are captured in these empirically measured (using a loopback test)
* timing correction values.
*
* Notes:
* USRP1 with timestamps is not supported by UHD.
*/
static struct uhd_dev_offset uhd_offsets[NUM_USRP_TYPES * 3] = {
{ USRP1, 1, 0.0 },
{ USRP1, 2, 0.0 },
{ USRP1, 4, 0.0 },
{ USRP2, 1, 5.4394e-5 },
{ USRP2, 2, 0.0 },
{ USRP2, 4, 0.0 },
{ B100, 1, 9.4778e-5 },
{ B100, 2, 5.1100e-5 },
{ B100, 4, 2.9418e-5 },
};
rx_smpl_offset - Timing correction in seconds between receive and
transmit timestamps. This value corrects for delays on
on the RF side of the timestamping point of the device.
This value is generally empirically measured.
static double get_dev_offset(enum uhd_dev_type type, int sps)
{
if (type == USRP1) {
LOG(ERR) << "Invalid device type";
return 0.0;
}
smpl_buf_sz - The receive sample buffer size in bytes.
switch (sps) {
case 1:
return uhd_offsets[3 * type + 0].offset;
case 2:
return uhd_offsets[3 * type + 1].offset;
case 4:
return uhd_offsets[3 * type + 2].offset;
}
tx_ampl - Transmit amplitude must be between 0 and 1.0
*/
const double master_clk_rt = 52e6;
const size_t smpl_buf_sz = (1 << 20);
const float tx_ampl = .3;
#ifdef RESAMPLE
const double rx_smpl_offset = .00005;
#else
const double rx_smpl_offset = .0000869;
#endif
LOG(ERR) << "Unsupported samples-per-symbols: " << sps;
return 0.0;
}
/** Timestamp conversion
@param timestamp a UHD or OpenBTS timestamp
@ -154,7 +181,7 @@ private:
*/
class uhd_device : public RadioDevice {
public:
uhd_device(double rate, bool skip_rx);
uhd_device(double rate, int sps, bool skip_rx);
~uhd_device();
bool open(const std::string &args);
@ -178,7 +205,7 @@ public:
inline TIMESTAMP initialWriteTimestamp() { return 0; }
inline TIMESTAMP initialReadTimestamp() { return 0; }
inline double fullScaleInputValue() { return 32000 * tx_ampl; }
inline double fullScaleInputValue() { return 32000 * TX_AMPL; }
inline double fullScaleOutputValue() { return 32000; }
double setRxGain(double db);
@ -215,6 +242,7 @@ private:
enum TxWindowType tx_window;
enum uhd_dev_type dev_type;
int sps;
double desired_smpl_rt, actual_smpl_rt;
double tx_gain, tx_gain_min, tx_gain_max;
@ -278,7 +306,7 @@ void uhd_msg_handler(uhd::msg::type_t type, const std::string &msg)
}
}
uhd_device::uhd_device(double rate, bool skip_rx)
uhd_device::uhd_device(double rate, int sps, bool skip_rx)
: desired_smpl_rt(rate), actual_smpl_rt(0),
tx_gain(0.0), tx_gain_min(0.0), tx_gain_max(0.0),
rx_gain(0.0), rx_gain_min(0.0), rx_gain_max(0.0),
@ -286,6 +314,7 @@ uhd_device::uhd_device(double rate, bool skip_rx)
started(false), aligned(false), rx_pkt_cnt(0), drop_cnt(0),
prev_ts(0,0), ts_offset(0), rx_smpl_buf(NULL)
{
this->sps = sps;
this->skip_rx = skip_rx;
}
@ -474,11 +503,17 @@ bool uhd_device::open(const std::string &args)
return false;
// Create receive buffer
size_t buf_len = smpl_buf_sz / sizeof(uint32_t);
size_t buf_len = SAMPLE_BUF_SZ / sizeof(uint32_t);
rx_smpl_buf = new smpl_buf(buf_len, actual_smpl_rt);
// Set receive chain sample offset
ts_offset = (TIMESTAMP)(rx_smpl_offset * actual_smpl_rt);
double offset = get_dev_offset(dev_type, sps);
if (offset == 0.0) {
LOG(ERR) << "Unsupported configuration, no correction applied";
ts_offset = 0;
} else {
ts_offset = (TIMESTAMP) (offset * actual_smpl_rt);
}
// Initialize and shadow gain values
init_gains();
@ -987,7 +1022,7 @@ std::string smpl_buf::str_code(ssize_t code)
}
}
RadioDevice *RadioDevice::make(double smpl_rt, bool skip_rx)
RadioDevice *RadioDevice::make(double smpl_rt, int sps, bool skip_rx)
{
return new uhd_device(smpl_rt, skip_rx);
return new uhd_device(smpl_rt, sps, skip_rx);
}

View File

@ -41,7 +41,7 @@ int main(int argc, char *argv[]) {
else gLogInit("DEBUG");
//if (argc>2) gSetLogFile(argv[2]);
RadioDevice *usrp = RadioDevice::make(52.0e6/192.0);
RadioDevice *usrp = RadioDevice::make(52.0e6/192.0, 1);
usrp->open("");

View File

@ -31,7 +31,7 @@ class RadioDevice {
/* Available transport bus types */
enum TxWindowType { TX_WINDOW_USRP1, TX_WINDOW_FIXED };
static RadioDevice *make(double desiredSampleRate, bool skipRx = false);
static RadioDevice *make(double desiredSampleRate, int sps, bool skipRx = false);
/** Initialize the USRP */
virtual bool open(const std::string &args)=0;

View File

@ -89,7 +89,7 @@ int main(int argc, char *argv[])
srandom(time(NULL));
int mOversamplingRate = numARFCN/2 + numARFCN;
RadioDevice *usrp = RadioDevice::make(DEVICERATE * SAMPSPERSYM);
RadioDevice *usrp = RadioDevice::make(DEVICERATE * SAMPSPERSYM, SAMPSPERSYM);
if (!usrp->open(deviceArgs)) {
LOG(ALERT) << "Transceiver exiting..." << std::endl;
return EXIT_FAILURE;