diff options
author | Martin Braun <martin.braun@ettus.com> | 2021-09-16 13:33:23 +0200 |
---|---|---|
committer | Aaron Rossetto <aaron.rossetto@ni.com> | 2021-09-17 13:29:01 -0700 |
commit | 6c8f24a9ca136c78fd73e94e937b3325a26a1fab (patch) | |
tree | ade34172b63790bc1d6f98078b7259c38ff19c46 /host/lib/usrp/common | |
parent | 652873b664393120b284e3303f82f80c7a1f4f9a (diff) | |
download | uhd-6c8f24a9ca136c78fd73e94e937b3325a26a1fab.tar.gz uhd-6c8f24a9ca136c78fd73e94e937b3325a26a1fab.tar.bz2 uhd-6c8f24a9ca136c78fd73e94e937b3325a26a1fab.zip |
ad9361: Modify set-tx-gain procedure to update gain in one go
The previous behaviour of UHD for setting gain was:
1. Set "Mask Clr Atten Update". This will avoid "Immediately Update TPC
Atten" to be cleared.
2. Then, assert "Immediately Update TPC Atten".
3. Poke the LSBs of the attenuation value.
4. Poke the MSB of the attenuation value.
This order of operations has the downside of causing large Tx power
spikes when setting the attenuation, because you need both registers to
properly set the attenuation, but we are updating the gain immediately,
even between the two attenuation register's update.
Moreover, the upstream Linux driver for AD9361 by ADI also does not
do this. We therefore change the procedure to match the kernel driver
behaviour, which is:
0. [During initialization: Clear "Mask Clr Atten Update"
1. Poke the attenuation registers
2. Then, assert "Immediately Update TPC Atten".
This avoids Tx power spikes. It also reduces the Tx-gain procedure to
3 pokes instead of 4.
Diffstat (limited to 'host/lib/usrp/common')
-rw-r--r-- | host/lib/usrp/common/ad9361_driver/ad9361_device.cpp | 20 |
1 files changed, 13 insertions, 7 deletions
diff --git a/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp b/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp index 9275c83f5..5574022b6 100644 --- a/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp +++ b/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp @@ -1817,6 +1817,10 @@ void ad9361_device_t::initialize() /* Set TXers & RXers on (only works in FDD mode) */ _io_iface->poke8(0x014, 0x21); + + /* We won't be using immediate-Tx-attenuation, so we de-assert "Mask Clr + * Atten Update". */ + _io_iface->poke8(0x077, 0x00); } void ad9361_device_t::set_io_iface(ad9361_io::sptr io_iface) @@ -2203,11 +2207,6 @@ double ad9361_device_t::set_gain(direction_t direction, chain_t chain, const dou return gain_index; } else { - /* Setting the below bits causes a change in the TX attenuation word - * to immediately take effect. */ - _io_iface->poke8(0x077, 0x40); - _io_iface->poke8(0x07c, 0x40); - /* Each gain step is -0.25dB. Calculate the attenuation necessary * for the requested gain, convert it into gain steps, then write * the attenuation word. Max gain (so zero attenuation) is 89.75. @@ -2215,8 +2214,8 @@ double ad9361_device_t::set_gain(direction_t direction, chain_t chain, const dou * "value" is out of bounds, so range checking must be performed * outside this function. */ - double atten = AD9361_MAX_GAIN - value; - uint32_t attenreg = uint32_t(atten * 4); + const double atten = AD9361_MAX_GAIN - value; + const uint32_t attenreg = uint32_t(atten * 4); if (chain == CHAIN_1) { _tx1_gain = value; _io_iface->poke8(0x073, attenreg & 0xFF); @@ -2226,6 +2225,13 @@ double ad9361_device_t::set_gain(direction_t direction, chain_t chain, const dou _io_iface->poke8(0x075, attenreg & 0xFF); _io_iface->poke8(0x076, (attenreg >> 8) & 0x01); } + + /* After we've set both registers for the new gain, we apply it (assert + * "Immediately Update TPC Atten"). This avoids the attenuation from + * intermediately becoming very small (i.e., high output power) during + * the set-gain cycle. + */ + _io_iface->poke8(0x07c, 0x40); return AD9361_MAX_GAIN - ((double)(attenreg) / 4); } } |