1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-12-25 12:12:02 -05:00

Spectrum calibration: further adjustments and documentation

This commit is contained in:
f4exb 2022-02-05 11:56:08 +01:00
parent cee7540399
commit 9d5d7b1113
22 changed files with 321 additions and 69 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

View File

@ -303,6 +303,7 @@ void SpectrumSettings::formatTo(SWGSDRangel::SWGObject *swgObject) const
swgSpectrum->setWaterfallShare(m_waterfallShare);
swgSpectrum->setMarkersDisplay((int) m_markersDisplay);
swgSpectrum->setUseCalibration(m_useCalibration ? 1 : 0);
swgSpectrum->setCalibrationInterpMode((int) m_calibrationInterpMode);
if (m_histogramMarkers.size() > 0)
{
@ -455,6 +456,9 @@ void SpectrumSettings::updateFrom(const QStringList& keys, const SWGSDRangel::SW
if (keys.contains("spectrumConfig.useCalibration")) {
m_useCalibration = swgSpectrum->getUseCalibration() != 0;
}
if (keys.contains("spectrumConfig.calibrationInterpMode")) {
m_calibrationInterpMode = (CalibrationInterpolationMode) swgSpectrum->getCalibrationInterpMode();
}
if (keys.contains("spectrumConfig.histogramMarkers"))
{

View File

@ -48,8 +48,8 @@ public:
enum CalibrationInterpolationMode
{
CalibInterpLinear, //!< linear power, linear frequency
CalibInterpLogLinear //!< log power, linear frequency
CalibInterpLinear, //!< linear power
CalibInterpLog //!< log power (dB linear)
};
int m_fftSize;

View File

@ -6159,6 +6159,10 @@ margin-bottom: 20px;
"type" : "integer",
"description" : "boolean"
},
"calibrationInterpMode" : {
"type" : "integer",
"description" : "Interpolation scheme between points SpectrumSettings::CalibrationInterpolationMode\n * 0 - Linear\n * 1 - Log (dB linear)\n"
},
"histogramMarkers" : {
"type" : "array",
"items" : {
@ -52000,7 +52004,7 @@ except ApiException as e:
</div>
<div id="generator">
<div class="content">
Generated 2022-01-30T07:47:20.311+01:00
Generated 2022-02-05T07:11:11.381+01:00
</div>
</div>
</div>

View File

@ -163,6 +163,12 @@ GLSpectrum:
useCalibration:
type: integer
description: boolean
calibrationInterpMode:
type: integer
description: >
Interpolation scheme between points SpectrumSettings::CalibrationInterpolationMode
* 0 - Linear
* 1 - Log (dB linear)
histogramMarkers:
type: array
items:

View File

@ -2433,7 +2433,7 @@ void GLSpectrum::updateCalibrationPoints()
m_calibrationGain = gainLow + interpolationRatio*(gainHigh - gainLow); // linear driven
m_calibrationShiftdB = CalcDb::dbPower(m_calibrationGain);
}
else if (m_calibrationInterpMode == SpectrumSettings::CalibInterpLogLinear)
else if (m_calibrationInterpMode == SpectrumSettings::CalibInterpLog)
{
m_calibrationShiftdB = CalcDb::dbPower(gainLow)
+ interpolationRatio*(CalcDb::dbPower(gainHigh) - CalcDb::dbPower(gainLow)); // log driven

View File

@ -379,6 +379,7 @@ void GLSpectrumGUI::on_markers_clicked(bool checked)
m_glSpectrum->getWaterfallMarkers(),
m_glSpectrum->getAnnotationMarkers(),
m_glSpectrum->getMarkersDisplay(),
m_calibrationShiftdB,
this
);

View File

@ -428,7 +428,7 @@
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="minimum">
<number>-150</number>
<number>-200</number>
</property>
<property name="maximum">
<number>40</number>

View File

@ -41,22 +41,24 @@ SpectrumCalibrationPointsDialog::SpectrumCalibrationPointsDialog(
m_markerZero(markerZero),
m_calibrationPointIndex(0),
m_centerFrequency(0),
m_globalCorrection(0.0)
m_globalCorrection(0.0),
m_setElseCorrectGlobal(false)
{
ui->setupUi(this);
ui->calibPointFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold));
ui->calibPointFrequency->setValueRange(false, 10, -9999999999L, 9999999999L);
ui->calibrationGlobalCorr->setColorMapper(ColorMapper(ColorMapper::GrayYellow));
ui->calibrationGlobalCorr->setValueRange(false, 5, -15000L, 4000L, 2);
ui->calibrationGlobalCorr->setValueRange(false, 5, -20000L, 4000L, 2);
ui->relativePower->setColorMapper(ColorMapper(ColorMapper::GrayYellow));
ui->relativePower->setValueRange(false, 5, -15000L, 4000L, 2);
ui->relativePower->setValueRange(false, 5, -20000L, 4000L, 2);
ui->calibratedPower->setColorMapper(ColorMapper(ColorMapper::GrayYellow));
ui->calibratedPower->setValueRange(false, 5, -15000L, 4000L, 2);
ui->calibratedPower->setValueRange(false, 5, -20000L, 4000L, 2);
ui->calibPoint->setMaximum(m_calibrationPoints.size() - 1);
ui->calibInterpMode->blockSignals(true);
ui->calibInterpMode->setCurrentIndex((int) m_calibrationInterpMode);
ui->calibInterpMode->blockSignals(false);
ui->calibrationGlobalCorr->setValue(m_globalCorrection * 100.0);
ui->corrOrSet->setText("Cor");
displayCalibrationPoint();
}
@ -91,9 +93,9 @@ void SpectrumCalibrationPointsDialog::displayCalibrationPoint()
ui->centerFrequency->setEnabled(true);
ui->calibPoint->setValue(m_calibrationPointIndex);
ui->calibPointText->setText(tr("%1").arg(m_calibrationPointIndex));
double powerDB = CalcDb::dbPower(m_calibrationPoints[m_calibrationPointIndex].m_powerRelativeReference);
double powerDB = CalcDb::dbPower(m_calibrationPoints[m_calibrationPointIndex].m_powerRelativeReference, 1e-20);
ui->relativePower->setValue(round(powerDB*100.0)); // fixed point 2 decimals
powerDB = CalcDb::dbPower(m_calibrationPoints[m_calibrationPointIndex].m_powerCalibratedReference);
powerDB = CalcDb::dbPower(m_calibrationPoints[m_calibrationPointIndex].m_powerCalibratedReference, 1e-20);
ui->calibratedPower->setValue(round(powerDB*100.0)); // fixed point 2 decimals
ui->calibPointFrequency->setValue(m_calibrationPoints[m_calibrationPointIndex].m_frequency);
}
@ -183,6 +185,17 @@ void SpectrumCalibrationPointsDialog::on_calibPointDuplicate_clicked()
displayCalibrationPoint();
}
void SpectrumCalibrationPointsDialog::on_calibPointsSort_clicked()
{
if (m_calibrationPoints.size() == 0) {
return;
}
std::sort(m_calibrationPoints.begin(), m_calibrationPoints.end(), calibrationPointsLessThan);
m_calibrationPointIndex = 0;
displayCalibrationPoint();
}
void SpectrumCalibrationPointsDialog::on_importMarkerZero_clicked()
{
if ((m_calibrationPoints.size() == 0) || (m_markerZero == nullptr)) {
@ -217,10 +230,26 @@ void SpectrumCalibrationPointsDialog::on_calibrationGlobalCorr_changed(qint64 va
m_globalCorrection = value / 100.0;
}
void SpectrumCalibrationPointsDialog::on_corrOrSet_toggled(bool checked)
{
if (checked) {
ui->corrOrSet->setText("Set");
} else {
ui->corrOrSet->setText("Cor");
}
m_setElseCorrectGlobal = checked;
}
void SpectrumCalibrationPointsDialog::on_globalRelativeCorrection_clicked()
{
for (auto& calibrationPoint : m_calibrationPoints) {
calibrationPoint.m_powerRelativeReference *= CalcDb::powerFromdB(m_globalCorrection);
for (auto& calibrationPoint : m_calibrationPoints)
{
if (m_setElseCorrectGlobal) {
calibrationPoint.m_powerRelativeReference = CalcDb::powerFromdB(m_globalCorrection);
} else {
calibrationPoint.m_powerRelativeReference *= CalcDb::powerFromdB(m_globalCorrection);
}
}
displayCalibrationPoint();
@ -229,8 +258,13 @@ void SpectrumCalibrationPointsDialog::on_globalRelativeCorrection_clicked()
void SpectrumCalibrationPointsDialog::on_globalCalibratedCorrection_clicked()
{
for (auto& calibrationPoint : m_calibrationPoints) {
calibrationPoint.m_powerCalibratedReference *= CalcDb::powerFromdB(m_globalCorrection);
for (auto& calibrationPoint : m_calibrationPoints)
{
if (m_setElseCorrectGlobal) {
calibrationPoint.m_powerCalibratedReference = CalcDb::powerFromdB(m_globalCorrection);
} else {
calibrationPoint.m_powerCalibratedReference *= CalcDb::powerFromdB(m_globalCorrection);
}
}
displayCalibrationPoint();
@ -259,13 +293,14 @@ void SpectrumCalibrationPointsDialog::on_calibPointsExport_clicked()
{
QTextStream stream;
stream.setDevice(&file);
stream << "Frequency,Reference,Absolute\n";
stream << "Frequency,Relative,Calibrated\n";
for (const auto &calibrationPint : m_calibrationPoints)
{
stream << calibrationPint.m_frequency << ","
<< calibrationPint.m_powerRelativeReference << ","
<< calibrationPint.m_powerCalibratedReference << "\n";
<< CalcDb::dbPower(calibrationPint.m_powerRelativeReference, 1e-20) << ","
<< CalcDb::dbPower(calibrationPint.m_powerCalibratedReference, 1e-20) << "\n";
}
stream.flush();
@ -299,7 +334,7 @@ void SpectrumCalibrationPointsDialog::on_calibPointsImport_clicked()
QString error;
QHash<QString, int> colIndexes = CSV::readHeader(
in,
{"Frequency", "Reference", "Absolute"},
{"Frequency", "Relative", "Calibrated"},
error
);
@ -307,8 +342,8 @@ void SpectrumCalibrationPointsDialog::on_calibPointsImport_clicked()
{
QStringList cols;
int frequencyCol = colIndexes.value("Frequency");
int referenceCol = colIndexes.value("Reference");
int absoluteCol = colIndexes.value("Absolute");
int referenceCol = colIndexes.value("Relative");
int absoluteCol = colIndexes.value("Calibrated");
m_calibrationPoints.clear();
@ -316,8 +351,8 @@ void SpectrumCalibrationPointsDialog::on_calibPointsImport_clicked()
{
m_calibrationPoints.push_back(SpectrumCalibrationPoint());
m_calibrationPoints.back().m_frequency = cols[frequencyCol].toLongLong();
m_calibrationPoints.back().m_powerRelativeReference = cols[referenceCol].toFloat();
m_calibrationPoints.back().m_powerCalibratedReference = cols[absoluteCol].toFloat();
m_calibrationPoints.back().m_powerRelativeReference = CalcDb::powerFromdB(cols[referenceCol].toFloat());
m_calibrationPoints.back().m_powerCalibratedReference = CalcDb::powerFromdB(cols[absoluteCol].toFloat());
}
m_calibrationPointIndex = 0;

View File

@ -53,9 +53,15 @@ private:
int m_calibrationPointIndex;
qint64 m_centerFrequency;
double m_globalCorrection;
bool m_setElseCorrectGlobal;
void displayCalibrationPoint();
static bool calibrationPointsLessThan(const SpectrumCalibrationPoint& m1, const SpectrumCalibrationPoint& m2)
{
return m1.m_frequency < m2.m_frequency;
}
private slots:
void on_calibPoint_valueChanged(int value);
void on_calibPointAdd_clicked();
@ -64,9 +70,11 @@ private slots:
void on_calibratedPower_changed(qint64 value);
void on_calibPointFrequency_changed(qint64 value);
void on_calibPointDuplicate_clicked();
void on_calibPointsSort_clicked();
void on_importMarkerZero_clicked();
void on_centerFrequency_clicked();
void on_calibInterpMode_currentIndexChanged(int index);
void on_corrOrSet_toggled(bool checked);
void on_calibrationGlobalCorr_changed(qint64 value);
void on_globalRelativeCorrection_clicked();
void on_globalCalibratedCorrection_clicked();

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>466</width>
<height>159</height>
<height>162</height>
</rect>
</property>
<property name="windowTitle">
@ -198,7 +198,7 @@
<widget class="QLabel" name="relativePowerLabel">
<property name="minimumSize">
<size>
<width>15</width>
<width>24</width>
<height>0</height>
</size>
</property>
@ -243,12 +243,6 @@
</item>
<item>
<widget class="QLabel" name="relativePowerUnits">
<property name="minimumSize">
<size>
<width>32</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>dB</string>
</property>
@ -268,7 +262,7 @@
<widget class="QLabel" name="calibratedPowerLabel">
<property name="minimumSize">
<size>
<width>15</width>
<width>24</width>
<height>0</height>
</size>
</property>
@ -313,12 +307,6 @@
</item>
<item>
<widget class="QLabel" name="calibratedPowerUnits">
<property name="minimumSize">
<size>
<width>32</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>dB</string>
</property>
@ -327,6 +315,19 @@
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
@ -410,6 +411,26 @@
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="calibPointsSort">
<property name="maximumSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="toolTip">
<string>Sort points by increasing frequency</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../resources/res.qrc">
<normaloff>:/sort.png</normaloff>:/sort.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="calibPointDuplicate">
<property name="maximumSize">
@ -480,21 +501,36 @@
</property>
<item>
<property name="text">
<string>Lin</string>
<string>Linear</string>
</property>
</item>
<item>
<property name="text">
<string>LogLin</string>
<string>Log</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QLabel" name="calibrationGlobalCorrLabel">
<widget class="QToolButton" name="corrOrSet">
<property name="minimumSize">
<size>
<width>52</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Correct or set value</string>
</property>
<property name="text">
<string>Cor</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item>
@ -524,7 +560,7 @@
<enum>Qt::StrongFocus</enum>
</property>
<property name="toolTip">
<string>Correction (dB)</string>
<string>Correction or set (dB)</string>
</property>
</widget>
</item>
@ -544,7 +580,7 @@
</size>
</property>
<property name="toolTip">
<string>Apply gain correction to all relative values</string>
<string>Set or apply correction to all relative values</string>
</property>
<property name="text">
<string>Rel</string>
@ -560,7 +596,7 @@
</size>
</property>
<property name="toolTip">
<string>Apply gain correction to all calibrated values</string>
<string>Set or apply correction to all calibrated values</string>
</property>
<property name="text">
<string>Cal</string>
@ -606,6 +642,9 @@
<iconset resource="../resources/res.qrc">
<normaloff>:/import.png</normaloff>:/import.png</iconset>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
</layout>

View File

@ -32,6 +32,7 @@ SpectrumMarkersDialog::SpectrumMarkersDialog(
QList<SpectrumWaterfallMarker>& waterfallMarkers,
QList<SpectrumAnnotationMarker>& annotationMarkers,
SpectrumSettings::MarkersDisplay& markersDisplay,
float calibrationShiftdB,
QWidget* parent) :
QDialog(parent),
ui(new Ui::SpectrumMarkersDialog),
@ -39,6 +40,7 @@ SpectrumMarkersDialog::SpectrumMarkersDialog(
m_waterfallMarkers(waterfallMarkers),
m_annotationMarkers(annotationMarkers),
m_markersDisplay(markersDisplay),
m_calibrationShiftdB(calibrationShiftdB),
m_histogramMarkerIndex(0),
m_waterfallMarkerIndex(0),
m_annotationMarkerIndex(0),
@ -56,8 +58,10 @@ SpectrumMarkersDialog::SpectrumMarkersDialog(
ui->aMarkerFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold));
ui->aMarkerFrequency->setValueRange(false, 10, -9999999999L, 9999999999L);
ui->aMarker->setMaximum(m_annotationMarkers.size() - 1);
ui->aMarkerBandwidth->setColorMapper(ColorMapper::GrayYellow);
ui->aMarkerBandwidth->setColorMapper(ColorMapper::GrayGreenYellow);
ui->aMarkerBandwidth->setValueRange(true, 9, 0, 999999999L);
ui->fixedPower->setColorMapper(ColorMapper::GrayYellow);
ui->fixedPower->setValueRange(false, 4, -2000, 400, 1);
ui->showSelect->setCurrentIndex((int) m_markersDisplay);
displayHistogramMarker();
displayWaterfallMarker();
@ -87,7 +91,6 @@ void SpectrumMarkersDialog::displayHistogramMarker()
ui->marker->setValue(0);
ui->markerText->setText("-");
ui->fixedPower->setValue(0);
ui->fixedPowerText->setText(tr("0.0"));
}
else
{
@ -100,9 +103,8 @@ void SpectrumMarkersDialog::displayHistogramMarker()
ui->markerText->setText(tr("%1").arg(m_histogramMarkerIndex));
ui->markerFrequency->setValue(m_histogramMarkers[m_histogramMarkerIndex].m_frequency);
ui->powerMode->setCurrentIndex((int) m_histogramMarkers[m_histogramMarkerIndex].m_markerType);
float powerDB = CalcDb::dbPower(m_histogramMarkers[m_histogramMarkerIndex].m_power);
float powerDB = CalcDb::dbPower(m_histogramMarkers[m_histogramMarkerIndex].m_power) + m_calibrationShiftdB;
ui->fixedPower->setValue(powerDB*10);
ui->fixedPowerText->setText(QString::number(powerDB, 'f', 1));
int r,g,b,a;
m_histogramMarkers[m_histogramMarkerIndex].m_markerColor.getRgb(&r, &g, &b, &a);
ui->markerColor->setStyleSheet(tr("QLabel { background-color : rgb(%1,%2,%3); }").arg(r).arg(g).arg(b));
@ -304,14 +306,13 @@ void SpectrumMarkersDialog::on_showMarker_clicked(bool clicked)
m_histogramMarkers[m_histogramMarkerIndex].m_show = clicked;
}
void SpectrumMarkersDialog::on_fixedPower_valueChanged(int value)
void SpectrumMarkersDialog::on_fixedPower_changed(qint64 value)
{
if (m_histogramMarkers.size() == 0) {
return;
}
float powerDB = value / 10.0f;
ui->fixedPowerText->setText(QString::number(powerDB, 'f', 1));
float powerDB = (value / 10.0f) - m_calibrationShiftdB;
m_histogramMarkers[m_histogramMarkerIndex].m_power = CalcDb::powerFromdB(powerDB);
emit updateHistogram();
}

View File

@ -39,6 +39,7 @@ public:
QList<SpectrumWaterfallMarker>& waterfallMarkers,
QList<SpectrumAnnotationMarker>& annotationMarkers,
SpectrumSettings::MarkersDisplay& markersDisplay,
float calibrationShiftdB,
QWidget* parent = nullptr
);
~SpectrumMarkersDialog();
@ -52,6 +53,7 @@ private:
QList<SpectrumWaterfallMarker>& m_waterfallMarkers;
QList<SpectrumAnnotationMarker>& m_annotationMarkers;
SpectrumSettings::MarkersDisplay& m_markersDisplay;
float m_calibrationShiftdB;
int m_histogramMarkerIndex;
int m_waterfallMarkerIndex;
int m_annotationMarkerIndex;
@ -71,7 +73,7 @@ private slots:
void on_centerFrequency_clicked();
void on_markerColor_clicked();
void on_showMarker_clicked(bool clicked);
void on_fixedPower_valueChanged(int value);
void on_fixedPower_changed(qint64 value);
void on_marker_valueChanged(int value);
void on_setReference_clicked();
void on_markerAdd_clicked();

View File

@ -431,26 +431,38 @@
</widget>
</item>
<item>
<widget class="QSlider" name="fixedPower">
<widget class="ValueDialZ" name="fixedPower" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>32</width>
<height>16</height>
</size>
</property>
<property name="font">
<font>
<family>DejaVu Sans Mono</family>
<pointsize>12</pointsize>
</font>
</property>
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
<property name="toolTip">
<string>Fixed power (dB)</string>
</property>
<property name="minimum">
<number>-1500</number>
</property>
<property name="maximum">
<number>1500</number>
</property>
<property name="pageStep">
<number>1</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="fixedPowerText">
<widget class="QLabel" name="fixedPowerUnits">
<property name="minimumSize">
<size>
<width>32</width>
@ -458,10 +470,10 @@
</size>
</property>
<property name="text">
<string>-100.0</string>
<string>dB</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>

View File

@ -0,0 +1,101 @@
<h1>Spectrum calibration management</h1>
The spectrum calibration is controlled by this dialog. It manages the list of calibration points (calibration chart), genaral options and the import/export from/to a .csv file.
This calibration is an artifact of the spectrum display it does not make any change in the actual levels in the DSP processing. It assumes nothing about the receiving or transmitting chains it is up to the user to run the calibration procedure to make the face power levels match the desired levels. If anything is changed in the receiving or transmitting parameters then the calibration procedure may have to be re-run again. Also it assumes nothing about the units of the calibrated power. Normally one would like to make dBm (or mW) measurements but it is up to the user to assume the actual units. One may want to use dBW or any other custom units therefore the displayed calibrated values will remain unit-less (dB).
For frequencies between calibration points the shift from relative value to displayed calibration value is interpolated using the next closest calibration points. If only one calibration point is provided then it applies regardless of frequency. The retained frequency for calculation is the center frequency of the spectrum and the shift applied is constant over the spectrum span. When no calibration points are provided turning on calibration correction has no effect.
<h2>Interface description</h2>
![Spectrum calibration dialog](../doc/img/Spectrum_Calibration_dialog.png)
<h3>1. Select point</h3>
Use the rotating button to select the point to edit
<h3>2. Add/Delete point</h3>
Click on the "+" button to add a new point and "-" to remove the current point.
<h3>3. Relative power</h3>
Enter the relative power in dB. This is the power displayed without calibration at this frequency point.
<h3>4. Calibrated power</h3>
Enter the calibrated power in dB. This is the power displayed with calibration at this frequency point.
<h3>5. Point frequency</h3>
This is the frequency of the calibration point
<h3>6. Point controls</h3>
![Spectrum calibration buttons](../doc/img/Spectrum_Calibration_buttons.png)
<h4>6.1. Sort points</h4>
Sort points by increasing frequency
<h4>6.2. Duplicate point</h4>
Append a new point to the list as a copy of the current point. The editor is automatically transferred to the new point.
<h4>6.3. Import from spectrum marker</h4>
Import data (frequency and relative power) from the first histogram marker (marker 0) if it exists. If there are no histogram markers this just does nothing.
<h4>6.4. Set frequency to center</h4>
Sets the point frequency to the center frequency of the spectrum
<h3>7. Interpolation method</h3>
The calibration shift between calibration points is interpolated based on the relative distance in frequency between points. The applied calibration shift is interpolated from the shift of the neighboring points. The interpolation can be:
- **Linear**: interpolation is linear in terms of power
- **Log**: interpolation is logarithmic in terms of power or linear if the power is expressed in dB
<h3>8. Apply correction or set value</h3>
This button lets you choose how the constant power next (9) is applied to all points
- **Cor**: applies a correction i.e. the value in (9) is added (in dB) to all points
- **Set**: sets power of all point to the value in (9)
The correction allows to take roughly into account the reception or transmission gain changes. It is like applying a constant gain over all frequencies.
You may apply correction to either the relative powers or the calibrated powers. The choice depends on whether you are in a reception or transmission chain (source or sink device set respectively).
In reception you would apply it to the relative powers as the input power that you measure for calibration remains the same.
In transmission you would apply it to the calibrated powers as the output power that you measure for calibration actually changes.
<h3>9. Constant power value in dB</h3>
This value is used to set all points to or to be applied as a correction depending on (8). It is used for relative powers (10) or calibrated powers (11)
<h3>10. Set or apply correction to relative powers</h3>
All relative power values are set to value in (9) if "Set" is selected in (8).
The value in (9) is added (in dB) to all relative power values if "Cor" is selected in (8)
<h3>11. Set or apply correction to calibrated powers</h3>
All calibrated power values are set to value in (9) if "Set" is selected in (8).
The value in (9) is added (in dB) to all calibrated power values if "Cor" is selected in (8)
<h3>12. Export calibrated points to .csv</h3>
Export the calibrated points to a .csv file. Colums are:
- **Frequency**: frequency in Hz of the point
- **Relative**: relative power in dB
- **Calibrated**: calibrated power in dB
<h3>13. Import calibrated points from .csv file</h3>
Import the calibrated points from a .csv file in the format described above.

View File

@ -163,6 +163,12 @@ GLSpectrum:
useCalibration:
type: integer
description: boolean
calibrationInterpMode:
type: integer
description: >
Interpolation scheme between points SpectrumSettings::CalibrationInterpolationMode
* 0 - Linear
* 1 - Log (dB linear)
histogramMarkers:
type: array
items:

View File

@ -6159,6 +6159,10 @@ margin-bottom: 20px;
"type" : "integer",
"description" : "boolean"
},
"calibrationInterpMode" : {
"type" : "integer",
"description" : "Interpolation scheme between points SpectrumSettings::CalibrationInterpolationMode\n * 0 - Linear\n * 1 - Log (dB linear)\n"
},
"histogramMarkers" : {
"type" : "array",
"items" : {
@ -52000,7 +52004,7 @@ except ApiException as e:
</div>
<div id="generator">
<div class="content">
Generated 2022-01-30T07:47:20.311+01:00
Generated 2022-02-05T07:11:11.381+01:00
</div>
</div>
</div>

View File

@ -84,6 +84,8 @@ SWGGLSpectrum::SWGGLSpectrum() {
m_markers_display_isSet = false;
use_calibration = 0;
m_use_calibration_isSet = false;
calibration_interp_mode = 0;
m_calibration_interp_mode_isSet = false;
histogram_markers = nullptr;
m_histogram_markers_isSet = false;
waterfall_markers = nullptr;
@ -156,6 +158,8 @@ SWGGLSpectrum::init() {
m_markers_display_isSet = false;
use_calibration = 0;
m_use_calibration_isSet = false;
calibration_interp_mode = 0;
m_calibration_interp_mode_isSet = false;
histogram_markers = new QList<SWGSpectrumHistogramMarker*>();
m_histogram_markers_isSet = false;
waterfall_markers = new QList<SWGSpectrumWaterfallMarker*>();
@ -198,6 +202,7 @@ SWGGLSpectrum::cleanup() {
if(histogram_markers != nullptr) {
auto arr = histogram_markers;
for(auto o: *arr) {
@ -295,6 +300,8 @@ SWGGLSpectrum::fromJsonObject(QJsonObject &pJson) {
::SWGSDRangel::setValue(&use_calibration, pJson["useCalibration"], "qint32", "");
::SWGSDRangel::setValue(&calibration_interp_mode, pJson["calibrationInterpMode"], "qint32", "");
::SWGSDRangel::setValue(&histogram_markers, pJson["histogramMarkers"], "QList", "SWGSpectrumHistogramMarker");
@ -403,6 +410,9 @@ SWGGLSpectrum::asJsonObject() {
if(m_use_calibration_isSet){
obj->insert("useCalibration", QJsonValue(use_calibration));
}
if(m_calibration_interp_mode_isSet){
obj->insert("calibrationInterpMode", QJsonValue(calibration_interp_mode));
}
if(histogram_markers && histogram_markers->size() > 0){
toJsonArray((QList<void*>*)histogram_markers, obj, "histogramMarkers", "SWGSpectrumHistogramMarker");
}
@ -699,6 +709,16 @@ SWGGLSpectrum::setUseCalibration(qint32 use_calibration) {
this->m_use_calibration_isSet = true;
}
qint32
SWGGLSpectrum::getCalibrationInterpMode() {
return calibration_interp_mode;
}
void
SWGGLSpectrum::setCalibrationInterpMode(qint32 calibration_interp_mode) {
this->calibration_interp_mode = calibration_interp_mode;
this->m_calibration_interp_mode_isSet = true;
}
QList<SWGSpectrumHistogramMarker*>*
SWGGLSpectrum::getHistogramMarkers() {
return histogram_markers;
@ -828,6 +848,9 @@ SWGGLSpectrum::isSet(){
if(m_use_calibration_isSet){
isObjectUpdated = true; break;
}
if(m_calibration_interp_mode_isSet){
isObjectUpdated = true; break;
}
if(histogram_markers && (histogram_markers->size() > 0)){
isObjectUpdated = true; break;
}

View File

@ -131,6 +131,9 @@ public:
qint32 getUseCalibration();
void setUseCalibration(qint32 use_calibration);
qint32 getCalibrationInterpMode();
void setCalibrationInterpMode(qint32 calibration_interp_mode);
QList<SWGSpectrumHistogramMarker*>* getHistogramMarkers();
void setHistogramMarkers(QList<SWGSpectrumHistogramMarker*>* histogram_markers);
@ -231,6 +234,9 @@ private:
qint32 use_calibration;
bool m_use_calibration_isSet;
qint32 calibration_interp_mode;
bool m_calibration_interp_mode_isSet;
QList<SWGSpectrumHistogramMarker*>* histogram_markers;
bool m_histogram_markers_isSet;