mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2024-11-22 04:11:16 -05:00
Improved frequency calibration
Measure check box added to FreqCal mode, check to record to fmt.all with current calibration correction disabled, uncheck to see the impact of the current calibration parameters. The fmt.all file is now optionally renamed to fmt.bak when a calibration solution is accepted. This allows users to preserve an fmt.all file that they might have edited for best fit. A calibration procedure might proceed thus:- 1) select FreqCal mode, 2) step through suggested calibration test frequencies deleting those that have no usable signal, 3) enable "Menu->Tools->Execute frequency calibration cycle" and check that suitable signals are present, 4) select a suitable FTol and T/R period, 5) check "Measure" and let the cycle complete a few times to gather data, 6) uncheck "Measure" to complete the data capture, optionally tidy the fmt.all file with your favourite editor, 7) push "Menu->Tools->Solve for calibration parameters" and accept if you like what you see, 8) sit back and admire your accurately frequency calibrated station. git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@8167 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
This commit is contained in:
parent
a9a1ac1d7a
commit
6424b4986f
@ -517,8 +517,8 @@ private:
|
||||
bool rig_changed_;
|
||||
TransceiverState cached_rig_state_;
|
||||
int rig_resolution_; // see Transceiver::resolution signal
|
||||
double frequency_calibration_intercept_;
|
||||
double frequency_calibration_slope_ppm_;
|
||||
CalibrationParams calibration_;
|
||||
bool frequency_calibration_disabled_; // not persistent
|
||||
unsigned transceiver_command_number_;
|
||||
|
||||
// configuration fields that we publish
|
||||
@ -672,15 +672,17 @@ QDir Configuration::azel_directory () const {return m_->azel_directory_;}
|
||||
QString Configuration::rig_name () const {return m_->rig_params_.rig_name;}
|
||||
bool Configuration::pwrBandTxMemory () const {return m_->pwrBandTxMemory_;}
|
||||
bool Configuration::pwrBandTuneMemory () const {return m_->pwrBandTuneMemory_;}
|
||||
auto Configuration::calibration_params () const -> CalibrationParams
|
||||
|
||||
void Configuration::set_calibration (CalibrationParams params)
|
||||
{
|
||||
return {m_->frequency_calibration_intercept_, m_->frequency_calibration_slope_ppm_};
|
||||
m_->calibration_ = params;
|
||||
}
|
||||
|
||||
void Configuration::adjust_calibration_parameters (double intercept, double slope_ppm)
|
||||
void Configuration::enable_calibration (bool on)
|
||||
{
|
||||
m_->frequency_calibration_intercept_ += intercept;
|
||||
m_->frequency_calibration_slope_ppm_ += slope_ppm;
|
||||
auto target_frequency = m_->remove_calibration (m_->cached_rig_state_.frequency ()) - m_->current_offset_;
|
||||
m_->frequency_calibration_disabled_ = !on;
|
||||
transceiver_frequency (target_frequency);
|
||||
}
|
||||
|
||||
bool Configuration::is_transceiver_online () const
|
||||
@ -802,12 +804,15 @@ Configuration::impl::impl (Configuration * self, QDir const& temp_directory,
|
||||
QSettings * settings, QWidget * parent)
|
||||
: QDialog {parent}
|
||||
, self_ {self}
|
||||
, transceiver_thread_ {nullptr}
|
||||
, ui_ {new Ui::configuration_dialog}
|
||||
, settings_ {settings}
|
||||
, doc_dir_ {doc_path ()}
|
||||
, data_dir_ {data_path ()}
|
||||
, temp_dir_ {temp_directory}
|
||||
, writeable_data_dir_ {QStandardPaths::writableLocation (QStandardPaths::DataLocation)}
|
||||
, restart_sound_input_device_ {false}
|
||||
, restart_sound_output_device_ {false}
|
||||
, frequencies_ {&bands_}
|
||||
, next_frequencies_ {&bands_}
|
||||
, stations_ {&bands_}
|
||||
@ -822,6 +827,7 @@ Configuration::impl::impl (Configuration * self, QDir const& temp_directory,
|
||||
, have_rig_ {false}
|
||||
, rig_changed_ {false}
|
||||
, rig_resolution_ {0}
|
||||
, frequency_calibration_disabled_ {false}
|
||||
, transceiver_command_number_ {0}
|
||||
, degrade_ {0.} // initialize to zero each run, not
|
||||
// saved in settings
|
||||
@ -1033,9 +1039,6 @@ Configuration::impl::impl (Configuration * self, QDir const& temp_directory,
|
||||
ui_->sound_input_channel_combo_box->setCurrentIndex (audio_input_channel_);
|
||||
ui_->sound_output_channel_combo_box->setCurrentIndex (audio_output_channel_);
|
||||
|
||||
restart_sound_input_device_ = false;
|
||||
restart_sound_output_device_ = false;
|
||||
|
||||
enumerate_rigs ();
|
||||
initialize_models ();
|
||||
|
||||
@ -1135,8 +1138,8 @@ void Configuration::impl::initialize_models ()
|
||||
ui_->accept_udp_requests_check_box->setChecked (accept_udp_requests_);
|
||||
ui_->udpWindowToFront->setChecked(udpWindowToFront_);
|
||||
ui_->udpWindowRestore->setChecked(udpWindowRestore_);
|
||||
ui_->calibration_intercept_spin_box->setValue (frequency_calibration_intercept_);
|
||||
ui_->calibration_slope_ppm_spin_box->setValue (frequency_calibration_slope_ppm_);
|
||||
ui_->calibration_intercept_spin_box->setValue (calibration_.intercept);
|
||||
ui_->calibration_slope_ppm_spin_box->setValue (calibration_.slope_ppm);
|
||||
|
||||
if (rig_params_.ptt_port.isEmpty ())
|
||||
{
|
||||
@ -1338,8 +1341,8 @@ void Configuration::impl::read_settings ()
|
||||
accept_udp_requests_ = settings_->value ("AcceptUDPRequests", false).toBool ();
|
||||
udpWindowToFront_ = settings_->value ("udpWindowToFront",false).toBool ();
|
||||
udpWindowRestore_ = settings_->value ("udpWindowRestore",false).toBool ();
|
||||
frequency_calibration_intercept_ = settings_->value ("CalibrationIntercept", 0.).toDouble ();
|
||||
frequency_calibration_slope_ppm_ = settings_->value ("CalibrationSlopePPM", 0.).toDouble ();
|
||||
calibration_.intercept = settings_->value ("CalibrationIntercept", 0.).toDouble ();
|
||||
calibration_.slope_ppm = settings_->value ("CalibrationSlopePPM", 0.).toDouble ();
|
||||
pwrBandTxMemory_ = settings_->value("pwrBandTxMemory",false).toBool ();
|
||||
pwrBandTuneMemory_ = settings_->value("pwrBandTuneMemory",false).toBool ();
|
||||
}
|
||||
@ -1434,8 +1437,8 @@ void Configuration::impl::write_settings ()
|
||||
settings_->setValue ("AcceptUDPRequests", accept_udp_requests_);
|
||||
settings_->setValue ("udpWindowToFront", udpWindowToFront_);
|
||||
settings_->setValue ("udpWindowRestore", udpWindowRestore_);
|
||||
settings_->setValue ("CalibrationIntercept", frequency_calibration_intercept_);
|
||||
settings_->setValue ("CalibrationSlopePPM", frequency_calibration_slope_ppm_);
|
||||
settings_->setValue ("CalibrationIntercept", calibration_.intercept);
|
||||
settings_->setValue ("CalibrationSlopePPM", calibration_.slope_ppm);
|
||||
settings_->setValue ("pwrBandTxMemory", pwrBandTxMemory_);
|
||||
settings_->setValue ("pwrBandTuneMemory", pwrBandTuneMemory_);
|
||||
settings_->setValue ("Region", QVariant::fromValue (region_));
|
||||
@ -1824,8 +1827,8 @@ void Configuration::impl::accept ()
|
||||
twoPass_ = ui_->cbTwoPass->isChecked ();
|
||||
x2ToneSpacing_ = ui_->cbx2ToneSpacing->isChecked ();
|
||||
realTimeDecode_ = ui_->cbRealTime->isChecked ();
|
||||
frequency_calibration_intercept_ = ui_->calibration_intercept_spin_box->value ();
|
||||
frequency_calibration_slope_ppm_ = ui_->calibration_slope_ppm_spin_box->value ();
|
||||
calibration_.intercept = ui_->calibration_intercept_spin_box->value ();
|
||||
calibration_.slope_ppm = ui_->calibration_slope_ppm_spin_box->value ();
|
||||
pwrBandTxMemory_ = ui_->checkBoxPwrBandTxMemory->isChecked ();
|
||||
pwrBandTuneMemory_ = ui_->checkBoxPwrBandTuneMemory->isChecked ();
|
||||
auto new_server = ui_->udp_server_line_edit->text ();
|
||||
@ -2677,14 +2680,16 @@ void Configuration::impl::fill_port_combo_box (QComboBox * cb)
|
||||
|
||||
auto Configuration::impl::apply_calibration (Frequency f) const -> Frequency
|
||||
{
|
||||
return std::llround (frequency_calibration_intercept_
|
||||
+ (1. + frequency_calibration_slope_ppm_ / 1.e6) * f);
|
||||
if (frequency_calibration_disabled_) return f;
|
||||
return std::llround (calibration_.intercept
|
||||
+ (1. + calibration_.slope_ppm / 1.e6) * f);
|
||||
}
|
||||
|
||||
auto Configuration::impl::remove_calibration (Frequency f) const -> Frequency
|
||||
{
|
||||
return std::llround ((f - frequency_calibration_intercept_)
|
||||
/ (1. + frequency_calibration_slope_ppm_ / 1.e6));
|
||||
if (frequency_calibration_disabled_) return f;
|
||||
return std::llround ((f - calibration_.intercept)
|
||||
/ (1. + calibration_.slope_ppm / 1.e6));
|
||||
}
|
||||
|
||||
#if !defined (QT_NO_DEBUG_STREAM)
|
||||
|
@ -159,16 +159,30 @@ public:
|
||||
QColor color_NewCall () const;
|
||||
bool pwrBandTxMemory () const;
|
||||
bool pwrBandTuneMemory () const;
|
||||
|
||||
struct CalibrationParams
|
||||
{
|
||||
double intercept;
|
||||
double slope_ppm;
|
||||
};
|
||||
CalibrationParams calibration_params () const;
|
||||
CalibrationParams ()
|
||||
: intercept {0.}
|
||||
, slope_ppm {0.}
|
||||
{
|
||||
}
|
||||
|
||||
// Adjust the current calibration parameters, both arguments are in
|
||||
// Hertz. They will be added to the current values.
|
||||
void adjust_calibration_parameters (double intercept, double slope_ppm);
|
||||
CalibrationParams (double the_intercept, double the_slope_ppm)
|
||||
: intercept {the_intercept}
|
||||
, slope_ppm {the_slope_ppm}
|
||||
{
|
||||
}
|
||||
|
||||
double intercept; // Hertz
|
||||
double slope_ppm; // Hertz
|
||||
};
|
||||
|
||||
// Temporarily enable or disable calibration adjustments.
|
||||
void enable_calibration (bool = true);
|
||||
|
||||
// Set the calibration parameters and enable calibration corrections.
|
||||
void set_calibration (CalibrationParams);
|
||||
|
||||
// This method queries if a CAT and PTT connection is operational.
|
||||
bool is_transceiver_online () const;
|
||||
|
@ -6,7 +6,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>552</width>
|
||||
<width>521</width>
|
||||
<height>507</height>
|
||||
</rect>
|
||||
</property>
|
||||
@ -2622,12 +2622,12 @@ soundcard changes</string>
|
||||
</connection>
|
||||
</connections>
|
||||
<buttongroups>
|
||||
<buttongroup name="CAT_handshake_button_group"/>
|
||||
<buttongroup name="CAT_stop_bits_button_group"/>
|
||||
<buttongroup name="TX_audio_source_button_group"/>
|
||||
<buttongroup name="split_mode_button_group"/>
|
||||
<buttongroup name="PTT_method_button_group"/>
|
||||
<buttongroup name="TX_mode_button_group"/>
|
||||
<buttongroup name="CAT_handshake_button_group"/>
|
||||
<buttongroup name="CAT_data_bits_button_group"/>
|
||||
<buttongroup name="CAT_stop_bits_button_group"/>
|
||||
</buttongroups>
|
||||
</ui>
|
||||
|
@ -1225,18 +1225,20 @@ void MainWindow::dataSink(qint64 frames)
|
||||
QString t=QString::fromLatin1(line);
|
||||
DecodedText decodedtext {t, false, m_config.my_grid ()};
|
||||
ui->decodedTextBrowser->displayDecodedText (decodedtext,m_baseCall,m_config.DXCC(),
|
||||
m_logBook,m_config.color_CQ(),m_config.color_MyCall(),m_config.color_DXCC(),
|
||||
m_config.color_NewCall());
|
||||
// Append results text to file "fmt.all".
|
||||
QFile f {m_config.writeable_data_dir ().absoluteFilePath ("fmt.all")};
|
||||
if (f.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append)) {
|
||||
QTextStream out(&f);
|
||||
out << t << endl;
|
||||
f.close();
|
||||
} else {
|
||||
MessageBox::warning_message (this, tr ("File Open Error")
|
||||
, tr ("Cannot open \"%1\" for append: %2")
|
||||
.arg (f.fileName ()).arg (f.errorString ()));
|
||||
m_logBook,m_config.color_CQ(),m_config.color_MyCall(),m_config.color_DXCC(),
|
||||
m_config.color_NewCall());
|
||||
if (ui->measure_check_box->isChecked ()) {
|
||||
// Append results text to file "fmt.all".
|
||||
QFile f {m_config.writeable_data_dir ().absoluteFilePath ("fmt.all")};
|
||||
if (f.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append)) {
|
||||
QTextStream out(&f);
|
||||
out << t << endl;
|
||||
f.close();
|
||||
} else {
|
||||
MessageBox::warning_message (this, tr ("File Open Error")
|
||||
, tr ("Cannot open \"%1\" for append: %2")
|
||||
.arg (f.fileName ()).arg (f.errorString ()));
|
||||
}
|
||||
}
|
||||
if(m_ihsym==m_hsymStop && ui->actionFrequency_calibration->isChecked()) {
|
||||
freqCalStep();
|
||||
@ -2133,12 +2135,16 @@ void MainWindow::on_actionSolve_FreqCal_triggered()
|
||||
.arg ("StdDev: ", 12).arg (rms, 0, 'f', 2)
|
||||
, QString {}
|
||||
, MessageBox::Cancel | MessageBox::Apply)) {
|
||||
m_config.adjust_calibration_parameters (a, b);
|
||||
// rename fmt.all as we have consumed the resulting calibration
|
||||
// solution
|
||||
auto const& backup_file_name = m_config.writeable_data_dir ().absoluteFilePath ("fmt.bak");
|
||||
QFile::remove (backup_file_name);
|
||||
QFile::rename (m_config.writeable_data_dir ().absoluteFilePath ("fmt.all"), backup_file_name);
|
||||
m_config.set_calibration (Configuration::CalibrationParams {a, b});
|
||||
if (MessageBox::Yes == MessageBox::query_message (this
|
||||
, tr ("Delete Calibration Measurements")
|
||||
, tr ("The \"fmt.all\" file will be renamed as \"fmt.bak\""))) {
|
||||
// rename fmt.all as we have consumed the resulting calibration
|
||||
// solution
|
||||
auto const& backup_file_name = m_config.writeable_data_dir ().absoluteFilePath ("fmt.bak");
|
||||
QFile::remove (backup_file_name);
|
||||
QFile::rename (m_config.writeable_data_dir ().absoluteFilePath ("fmt.all"), backup_file_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -4682,6 +4688,7 @@ void MainWindow::displayWidgets(int n)
|
||||
ui->cbFirst->setVisible ("FT8" == m_mode);
|
||||
ui->actionEnable_AP->setVisible ("FT8" == m_mode);
|
||||
ui->cbVHFcontest->setVisible(m_mode=="FT8" or m_mode=="MSK144");
|
||||
ui->measure_check_box->setVisible ("FreqCal" == m_mode);
|
||||
m_lastCallsign.clear (); // ensures Tx5 is updated for new modes
|
||||
genStdMsgs (m_rpt, true);
|
||||
}
|
||||
@ -5121,6 +5128,7 @@ void MainWindow::on_actionFreqCal_triggered()
|
||||
setup_status_bar (true);
|
||||
// 18:15:47 0 1 1500 1550.349 0.100 3.5 10.2
|
||||
ui->decodedTextLabel->setText(" UTC Freq CAL Offset fMeas DF Level S/N");
|
||||
ui->measure_check_box->setChecked (false);
|
||||
displayWidgets(nWidgets("001101000000000000000000"));
|
||||
statusChanged();
|
||||
}
|
||||
@ -5214,9 +5222,8 @@ void MainWindow::on_TxFreqSpinBox_valueChanged(int n)
|
||||
void MainWindow::on_RxFreqSpinBox_valueChanged(int n)
|
||||
{
|
||||
m_wideGraph->setRxFreq(n);
|
||||
if (m_mode == "FreqCal"
|
||||
&& m_frequency_list_fcal_iter != m_config.frequencies ()->end ()) {
|
||||
setRig (m_frequency_list_fcal_iter->frequency_ - n);
|
||||
if (m_mode == "FreqCal") {
|
||||
setRig ();
|
||||
}
|
||||
statusUpdate ();
|
||||
}
|
||||
@ -5349,15 +5356,11 @@ void MainWindow::band_changed (Frequency f)
|
||||
if ("FreqCal" == m_mode)
|
||||
{
|
||||
m_frequency_list_fcal_iter = m_config.frequencies ()->find (f);
|
||||
setRig (f - ui->RxFreqSpinBox->value ());
|
||||
}
|
||||
else
|
||||
{
|
||||
float r=m_freqNominal/(f+0.0001);
|
||||
if(r<0.9 or r>1.1) m_bVHFwarned=false;
|
||||
setRig (f);
|
||||
setXIT (ui->TxFreqSpinBox->value ());
|
||||
}
|
||||
float r=m_freqNominal/(f+0.0001);
|
||||
if(r<0.9 or r>1.1) m_bVHFwarned=false;
|
||||
setRig (f);
|
||||
setXIT (ui->TxFreqSpinBox->value ());
|
||||
if(monitor_off) monitor(false);
|
||||
}
|
||||
}
|
||||
@ -6656,6 +6659,10 @@ void MainWindow::setRig (Frequency f)
|
||||
m_freqTxNominal = m_freqNominal;
|
||||
if (m_astroWidget) m_astroWidget->nominal_frequency (m_freqNominal, m_freqTxNominal);
|
||||
}
|
||||
if (m_mode == "FreqCal"
|
||||
&& m_frequency_list_fcal_iter != m_config.frequencies ()->end ()) {
|
||||
m_freqNominal = m_frequency_list_fcal_iter->frequency_ - ui->RxFreqSpinBox->value ();
|
||||
}
|
||||
if(m_transmitting && !m_config.tx_QSY_allowed ()) return;
|
||||
if ((m_monitoring || m_transmitting) && m_config.transceiver_online ())
|
||||
{
|
||||
@ -6855,6 +6862,13 @@ void MainWindow::on_cbAutoSeq_toggled(bool b)
|
||||
ui->cbFirst->setVisible((m_mode=="FT8") and b);
|
||||
}
|
||||
|
||||
void MainWindow::on_measure_check_box_stateChanged (int state)
|
||||
{
|
||||
if ("FreqCal" == m_mode) {
|
||||
m_config.enable_calibration (Qt::Checked != state);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::write_transmit_entry (QString const& file_name)
|
||||
{
|
||||
QFile f {m_config.writeable_data_dir ().absoluteFilePath (file_name)};
|
||||
|
@ -281,6 +281,7 @@ private slots:
|
||||
void on_actionQRA64_triggered();
|
||||
void on_actionFreqCal_triggered();
|
||||
void splash_done ();
|
||||
void on_measure_check_box_stateChanged (int);
|
||||
|
||||
private:
|
||||
Q_SIGNAL void initializeAudioOutputStream (QAudioDeviceInfo,
|
||||
|
@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>815</width>
|
||||
<height>548</height>
|
||||
<height>555</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -21,7 +21,7 @@
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout" stretch="1,0,0">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout" columnstretch="0,0">
|
||||
<layout class="QGridLayout" name="gridLayout" columnstretch="2,1">
|
||||
<property name="horizontalSpacing">
|
||||
<number>3</number>
|
||||
</property>
|
||||
@ -974,6 +974,16 @@ QLabel[oob="true"] {
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="measure_check_box">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Check this to start recording calibration data.<br/>While measuring calibration correction is disabled.<br/>When not checked you can view the calibration results.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Measure</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="10" column="0" colspan="2">
|
||||
|
Loading…
Reference in New Issue
Block a user