UHDDevice: Compute TxGain on UHD API based on expected Tx output power

Right now, according to a few measurements taken on B210, we expect the
Tx Gain at UHD level to relate 1:1 with the slope in Tx output power
given a specific band.

If more fine-grained results are wanted or some device doesn't follow a
1:1 slope relationship, functions TxGain2TxPower and TxPower2TxGain need
to be adapted/improved.

Change-Id: I6f432465dce5c6ec1f1bc4653f6149efb18c3f43
This commit is contained in:
Pau Espin 2020-06-08 14:49:33 +02:00
parent 992c9bd1ce
commit b899c19f1f
2 changed files with 58 additions and 47 deletions

View File

@ -212,12 +212,23 @@ static void uhd_msg_handler(uhd::msg::type_t type, const std::string &msg)
}
#endif
/* So far measurements done for B210 show really close to linear relationship
* between gain and real output power, so we simply adjust the measured offset
*/
static double TxGain2TxPower(const dev_band_desc &desc, double tx_gain_db)
{
return desc.nom_out_tx_power - (desc.nom_uhd_tx_gain - tx_gain_db);
}
static double TxPower2TxGain(const dev_band_desc &desc, double tx_power_dbm)
{
return desc.nom_uhd_tx_gain - (desc.nom_out_tx_power - tx_power_dbm);
}
uhd_device::uhd_device(size_t tx_sps, size_t rx_sps,
InterfaceType iface, size_t chan_num, double lo_offset,
const std::vector<std::string>& tx_paths,
const std::vector<std::string>& rx_paths)
: RadioDevice(tx_sps, rx_sps, iface, chan_num, lo_offset, tx_paths, rx_paths),
tx_gain_min(0.0), tx_gain_max(0.0),
rx_gain_min(0.0), rx_gain_max(0.0),
band((enum gsm_band)0), tx_spp(0), rx_spp(0),
started(false), aligned(false), drop_cnt(0),
@ -256,6 +267,7 @@ void uhd_device::get_dev_band_desc(dev_band_desc& desc)
void uhd_device::init_gains()
{
double tx_gain_min, tx_gain_max;
uhd::gain_range_t range;
if (dev_type == UMTRX) {
@ -320,37 +332,6 @@ void uhd_device::set_rates()
LOGC(DDEV, INFO) << "Rates configured for " << desc.str;
}
double uhd_device::setTxGain(double db, size_t chan)
{
if (chan >= tx_gains.size()) {
LOGC(DDEV, ALERT) << "Requested non-existent channel" << chan;
return 0.0f;
}
if (dev_type == UMTRX) {
std::vector<std::string> gain_stages = usrp_dev->get_tx_gain_names(0);
if (gain_stages[0] == "VGA" || gain_stages[0] == "PA") {
usrp_dev->set_tx_gain(db, chan);
} else {
// New UHD versions support split configuration of
// Tx gain stages. We utilize this to set the gain
// configuration, optimal for the Tx signal quality.
// From our measurements, VGA1 must be 18dB plus-minus
// one and VGA2 is the best when 23dB or lower.
usrp_dev->set_tx_gain(UMTRX_VGA1_DEF, "VGA1", chan);
usrp_dev->set_tx_gain(db-UMTRX_VGA1_DEF, "VGA2", chan);
}
} else {
usrp_dev->set_tx_gain(db, chan);
}
tx_gains[chan] = usrp_dev->get_tx_gain(chan);
LOGC(DDEV, INFO) << "Set TX gain to " << tx_gains[chan] << "dB (asked for " << db << "dB)";
return tx_gains[chan];
}
double uhd_device::setRxGain(double db, size_t chan)
{
if (chan >= rx_gains.size()) {
@ -376,14 +357,50 @@ double uhd_device::getRxGain(size_t chan)
return rx_gains[chan];
}
double uhd_device::getTxGain(size_t chan)
{
double uhd_device::setPowerAttenuation(int atten, size_t chan) {
double db;
dev_band_desc desc;
if (chan >= tx_gains.size()) {
LOGC(DDEV, ALERT) << "Requested non-existent channel" << chan;
return 0.0f;
}
get_dev_band_desc(desc);
db = TxPower2TxGain(desc, desc.nom_out_tx_power - atten);
if (dev_type == UMTRX) {
std::vector<std::string> gain_stages = usrp_dev->get_tx_gain_names(0);
if (gain_stages[0] == "VGA" || gain_stages[0] == "PA") {
usrp_dev->set_tx_gain(db, chan);
} else {
// New UHD versions support split configuration of
// Tx gain stages. We utilize this to set the gain
// configuration, optimal for the Tx signal quality.
// From our measurements, VGA1 must be 18dB plus-minus
// one and VGA2 is the best when 23dB or lower.
usrp_dev->set_tx_gain(UMTRX_VGA1_DEF, "VGA1", chan);
usrp_dev->set_tx_gain(db-UMTRX_VGA1_DEF, "VGA2", chan);
}
} else {
usrp_dev->set_tx_gain(db, chan);
}
tx_gains[chan] = usrp_dev->get_tx_gain(chan);
LOGC(DDEV, INFO) << "Set TX gain to " << tx_gains[chan] << "dB (asked for " << db << "dB)";
return desc.nom_out_tx_power - TxGain2TxPower(desc, tx_gains[chan]);
}
double uhd_device::getPowerAttenuation(size_t chan) {
dev_band_desc desc;
if (chan >= tx_gains.size()) {
LOGC(DDEV, ALERT) << "Requested non-existent channel " << chan;
return 0.0f;
}
return tx_gains[chan];
get_dev_band_desc(desc);
return desc.nom_out_tx_power - TxGain2TxPower(desc, tx_gains[chan]);
}
int uhd_device::getNominalTxPower(size_t chan)
@ -1007,7 +1024,6 @@ bool uhd_device::setTxFreq(double wFreq, size_t chan)
{
uint16_t req_arfcn;
enum gsm_band req_band;
dev_band_desc desc;
if (chan >= tx_freqs.size()) {
LOGC(DDEV, ALERT) << "Requested non-existent channel " << chan;
@ -1036,12 +1052,6 @@ bool uhd_device::setTxFreq(double wFreq, size_t chan)
return false;
band = req_band;
/* Update Max Tx Gain */
get_dev_band_desc(desc);
tx_gain_max = desc.nom_uhd_tx_gain;
LOGCHAN(chan, DDEV, INFO) << "Updating max Gain to " << tx_gain_max
<< " dB based on GSM band information";
return true;
}

View File

@ -101,6 +101,9 @@ public:
double maxRxGain(void) { return rx_gain_max; }
double minRxGain(void) { return rx_gain_min; }
double setPowerAttenuation(int atten, size_t chan);
double getPowerAttenuation(size_t chan = 0);
int getNominalTxPower(size_t chan = 0);
double getTxFreq(size_t chan);
@ -131,10 +134,9 @@ public:
};
private:
double setTxGain(double db, size_t chan);
double getTxGain(size_t chan = 0);
double maxTxGain(void) { return tx_gain_max; }
double minTxGain(void) { return tx_gain_min; }
double setTxGain(double db, size_t chan) {OSMO_ASSERT(false); return 0.0f; }
double getTxGain(size_t chan = 0) { OSMO_ASSERT(false); return 0.0f; };
double maxTxGain(void) { OSMO_ASSERT(false); return 0.0f; };
uhd::usrp::multi_usrp::sptr usrp_dev;
uhd::tx_streamer::sptr tx_stream;
@ -144,7 +146,6 @@ private:
double tx_rate, rx_rate;
double tx_gain_min, tx_gain_max;
double rx_gain_min, rx_gain_max;
std::vector<double> tx_gains, rx_gains;