mirror of
https://github.com/saymrwulf/uhd.git
synced 2026-05-16 21:10:10 +00:00
240 lines
9.5 KiB
Text
240 lines
9.5 KiB
Text
/*! \page page_calibration Device Calibration and Frontend Correction
|
|
|
|
\tableofcontents
|
|
|
|
\section calibration_self Self-Calibration
|
|
|
|
UHD software comes with several self-calibration utilities for
|
|
minimizing IQ imbalance and DC offset. These utilities perform
|
|
calibration sweeps using transmit leakage into the receive path (special
|
|
equipment is not required). The results from a calibration are written
|
|
to a file in the user's home directory. UHD software will
|
|
automatically apply corrections at runtime when the user re-tunes the
|
|
daughterboard LO. Calibration results are specific to an individual RF
|
|
board.
|
|
|
|
<b>Note:</b> When a calibration table is present, and the user wishes to
|
|
override the calibration settings through the API: the user should
|
|
re-apply the desired setting every time the LO is re-tuned.
|
|
|
|
UHD software comes with the following calibration utilities:
|
|
|
|
- **uhd_cal_rx_iq_balance:** - minimizes RX IQ imbalance vs. LO
|
|
frequency
|
|
- **uhd_cal_tx_dc_offset:** - minimizes TX DC offset vs. LO
|
|
frequency
|
|
- **uhd_cal_tx_iq_balance:** - minimizes TX IQ imbalance vs. LO
|
|
frequency
|
|
|
|
The following RF frontends are supported by the self-calibration
|
|
utilities:
|
|
|
|
- RFX Series transceiver boards
|
|
- WBX Series transceiver boards
|
|
- SBX Series transceiver boards
|
|
- CBX Series transceiver boards
|
|
- UBX Series transceiver boards
|
|
- USRP N320
|
|
|
|
\subsection calibration_self_utils Calibration Utilities
|
|
|
|
UHD software installs the calibration utilities into
|
|
`<install-path>/bin`. **Disconnect** any external hardware from the
|
|
RF antenna ports, and run the following from the command line. Each
|
|
utility will take several minutes to complete:
|
|
|
|
uhd_cal_rx_iq_balance --verbose --args=<optional device args>
|
|
uhd_cal_tx_iq_balance --verbose --args=<optional device args>
|
|
uhd_cal_tx_dc_offset --verbose --args=<optional device args>
|
|
|
|
See the output given by `--help` for more advanced options, such as
|
|
manually choosing the frequency range and step size for the sweeps.
|
|
|
|
<b>Note:</b> Your daughterboard needs a serial number to run a calibration
|
|
utility. Some older daughterboards may not have a serial number. If this
|
|
is the case, run the following command to burn a serial number into the
|
|
daughterboard's EEPROM:
|
|
|
|
<install dir>/lib/uhd/utils/usrp_burn_db_eeprom --ser=<desired serial> --args=<optional device args>
|
|
|
|
\subsection calibration_data Calibration Data
|
|
|
|
By default, calibration files are stored in the user's home/application
|
|
directory (`$XDG_DATA_HOME`):
|
|
|
|
- **Linux:** `${HOME}/.local/share/uhd/cal/`
|
|
- **Windows:** `%LOCALAPPDATA%\uhd\cal\`
|
|
|
|
Calibration files are binary files with a `.cal` file extension.
|
|
|
|
If you would like to specify a custom directory, you can do so with the
|
|
`$UHD_CAL_DATA_PATH` environment variable.
|
|
|
|
Calibration files can easily be moved from one machine to another by copying the
|
|
"cal" directory, or individual files therein. Re-running a calibration utility
|
|
will replace the existing calibration file. The old calibration file will be
|
|
renamed so it may be recovered by the user.
|
|
|
|
\subsection modify_cal_data Modify Calibration Data
|
|
|
|
There might be reasons to analyse or modify the calibration data outside UHD's
|
|
calibration process. Because the data is stored using FlatBuffers this can be
|
|
done without relying on UHD. UHD provides all FlatBuffers schema files in
|
|
`<install-path>/share/uhd/cal`.
|
|
|
|
First, install FlatBuffers. The package can be obtained from
|
|
https://google.github.io/flatbuffers/.
|
|
Once installed, `.cal` files can be converted to JSON using
|
|
|
|
flatc --strict-json -t <install dir>/share/uhd/cal/<foo>_cal.fbs -- <data>.cal
|
|
|
|
where `<foo>_cal.fbs` is the scheme file used for the data,
|
|
e.g. `pwr_cal.fbs` for power calibration. `data.cal` is a calibration file in
|
|
your working directory. This will generate a `<data>.json` in the same
|
|
directory.
|
|
|
|
The JSON data can be converted back to binary using
|
|
|
|
flatc -b <install dir>/include/uhd/cal/<foo>_cal.fbs <data>.json
|
|
|
|
This generates a `<data>.cal` that can be read by the calibration routines
|
|
of UHD.
|
|
|
|
\subsection calibration_data_csv Converting UHD 3.x calibration data to UHD 4
|
|
|
|
Older versions of UHD used a CSV-based format for storing calbration data for
|
|
IQ imbalance and DC offset correction on some devices (e.g., X300, N200
|
|
motherboards and WBX/SBX/CBX/UBX daughterboards).
|
|
|
|
Going forward, all calibration data is stored as binary, to facilitate storing
|
|
it on device's flash memory, among other reasons. Running the `uhd_cal_*`
|
|
utilities will automatically generate the calibration data in the new format.
|
|
|
|
To convert existing calbration data to the new format, use the convert_cal_data.py
|
|
utility. By default, it will convert all existing data. Use `convert_cal_data.py --help`
|
|
to get a full list of command line options.
|
|
The tool is installed with the other utilities, for example into `/usr/share/lib/uhd/utils`,
|
|
depending on your OS and CMake settings.
|
|
|
|
|
|
\subsection ignore_cal_file Ignoring Calibration Files
|
|
|
|
At runtime, the user can choose to ignore a daughterboard's calibration file by
|
|
adding "ignore-cal-file" to the arguments. With the UHD API, it can be done as
|
|
follows:
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
|
|
auto usrp = uhd::usrp::multi_usrp::make("type=x300,ignore-cal-file=1");
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Using tx_waveforms as an example, the user can apply this argument as follows:
|
|
|
|
tx_waveforms --args="addr=192.168.10.2,ignore-cal-file=1" --freq=100e6 --rate=1e6
|
|
|
|
|
|
\section calibration_fe_corr Frontend Corrections
|
|
|
|
The calibrations for IQ imbalance and DC offset compensation rely on frontend
|
|
correction logic that is located in the FPGA.
|
|
|
|
Note that USRP E310, E320, N320, and B200-Series use a dedicated RFIC which does
|
|
its own calibration. For those, any calibrations are very device-specific and
|
|
are not covered in this section.
|
|
|
|
\subsection calibration_fe_corr_dc_offset Single-Tap DC Offset Compensation
|
|
|
|
A DC offset is a fixed voltage that is permanently present on the signal of
|
|
interest. It is an additive error, meaning if the signal of interest is x(t),
|
|
the actual, observed signal y(t) includes a constant offset:
|
|
|
|
\f[
|
|
y(t) = x(t) + D
|
|
\f]
|
|
|
|
If the constant value D is known, it can simply be subtracted again. For this
|
|
reason, the DC offset compensation consists of a simple adder. The calibration
|
|
tool `uhd_cal_tx_dc_offset` will estimate the value D' which minimizes the DC
|
|
offset for various frequencies (i.e., D' is approximately equal to -D).
|
|
|
|
To program the adder, set the DC offset correction value using these API calls:
|
|
|
|
- uhd::usrp::multi_usrp::set_tx_dc_offset()
|
|
- uhd::usrp::multi_usrp::set_rx_dc_offset()
|
|
- uhd::rfnoc::radio_control::set_tx_dc_offset()
|
|
- uhd::rfnoc::radio_control::set_rx_dc_offset()
|
|
|
|
For RX DC offset compensation, the estimation of D can be difficult. Therefore,
|
|
the RX DC offset compensation also includes an automatic mode, which acts as a
|
|
notch filter around DC. It is implemented as a single-tap IIR filter with the
|
|
following difference equation:
|
|
|
|
\f[
|
|
y[k] = x[k] - \alpha * y[k-1]
|
|
\f]
|
|
|
|
The values for \f$\alpha\f$ are device-dependent, but the default value is \f$2^{-20}\f$.
|
|
|
|
To enable the automatic DC offset correction, call one of these API calls with
|
|
an argument of 'true':
|
|
|
|
- uhd::usrp::multi_usrp::set_rx_dc_offset()
|
|
- uhd::rfnoc::radio_control::set_rx_dc_offset()
|
|
|
|
DC offset is often caused by LO leakage. It is therefore advised to offset-tune
|
|
the radio to avoid having the LO in the band of interest. The DC offset
|
|
compensation will not only remove LO spurs, but also affect the signal of
|
|
interest if the LO is within the band of interest.
|
|
|
|
Superheterodyne receivers such as the TwinRX do usually not require DC offset
|
|
correction values.
|
|
|
|
\subsection calibration_fe_corr_iq_offset Single-Point IQ offset compensation
|
|
|
|
In order to correct IQ imbalance, the user can specify two real values A and B.
|
|
In the FPGA, the complex signal is modified according to the following equation:
|
|
|
|
\f[
|
|
\begin{pmatrix}
|
|
I' \\
|
|
Q'
|
|
\end{pmatrix}
|
|
=
|
|
\begin{pmatrix}
|
|
A/64+1 & 0 \\
|
|
B/64 & 1 \\
|
|
\end{pmatrix}
|
|
\begin{pmatrix}
|
|
I \\
|
|
Q
|
|
\end{pmatrix}
|
|
\f]
|
|
|
|
This is a normalized version of the usual correction matrix for IQ imbalance
|
|
which is easier to implement in the FPGA. Because the top-left value of this
|
|
matrix depends on the magnitude error of the IQ imbalance, and the bottom row
|
|
depends on the phase error, the value "A" is often referred to as the "magnitude
|
|
correction value", and the value "B" is referred to as the "phase correction value".
|
|
These values are however not identical to the actual phase and magnitude error
|
|
caused by IQ imbalance.
|
|
|
|
The `uhd_cal_tx_iq_balance` and `uhd_cal_rx_iq_balance` tools will simply search
|
|
for A and B values which minimize the error caused by IQ imbalance.
|
|
|
|
Notes:
|
|
- The API calls uhd::usrp::multi_usrp::set_rx_iq_balance() and
|
|
uhd::usrp::multi_usrp::set_tx_iq_balance() take complex numbers as a correction
|
|
value, which is generated by `std::complex<double>(A, B)`. The complex math is
|
|
not necessary, given the correction algorithm, but the argument was chosen due
|
|
to its symmetry to the DC offset correction APIs, and also because treating the
|
|
correction value as a complex number lets it be handled and stored easily and
|
|
exactly as with the DC offset correction.
|
|
- This correction algorithm is suboptimal for high bandwidths, albeit better
|
|
than nothing.
|
|
|
|
IQ imbalance is caused by the inphase and quadrature paths of a direct-conversion
|
|
receiver being slightly different in amplitude as well as their phase not being
|
|
exactly 90 degrees apart (due to analog components). It is therefore not
|
|
required for superheterodyne architectures like the TwinRX.
|
|
|
|
*/
|
|
// vim:ft=doxygen:
|