From 6424b4986f1d13011986ddb939934cac2b51e42b Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Fri, 13 Oct 2017 22:34:21 +0000 Subject: [PATCH] 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 --- Configuration.cpp | 49 +++++++++++++++++--------------- Configuration.hpp | 28 +++++++++++++----- Configuration.ui | 6 ++-- mainwindow.cpp | 72 ++++++++++++++++++++++++++++------------------- mainwindow.h | 1 + mainwindow.ui | 14 +++++++-- 6 files changed, 107 insertions(+), 63 deletions(-) diff --git a/Configuration.cpp b/Configuration.cpp index bc551216f..c93660a71 100644 --- a/Configuration.cpp +++ b/Configuration.cpp @@ -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) diff --git a/Configuration.hpp b/Configuration.hpp index 58b7bde7d..c6e8875fb 100644 --- a/Configuration.hpp +++ b/Configuration.hpp @@ -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; diff --git a/Configuration.ui b/Configuration.ui index 19f3765b3..5f1a4c985 100644 --- a/Configuration.ui +++ b/Configuration.ui @@ -6,7 +6,7 @@ 0 0 - 552 + 521 507 @@ -2622,12 +2622,12 @@ soundcard changes + + - - diff --git a/mainwindow.cpp b/mainwindow.cpp index 486af6241..c401e49ae 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -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)}; diff --git a/mainwindow.h b/mainwindow.h index 5d39184fd..5f5b6b289 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -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, diff --git a/mainwindow.ui b/mainwindow.ui index 09a8349c5..44cf6eb25 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -7,7 +7,7 @@ 0 0 815 - 548 + 555 @@ -21,7 +21,7 @@ - + 3 @@ -974,6 +974,16 @@ QLabel[oob="true"] { + + + + <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> + + + Measure + + +