------------------------------------------------------------------------

r5297 | bsomervi | 2015-04-26 17:26:54 +0100 (Sun, 26 Apr 2015) | 49 lines

Various defect repairs and ambigous behaviour clarifications

A regression introduced in v1.5.0-rc1 where PTT on an alternate serial
port when using no CAT control is resolved.

A regression introduced  in v1.5.0-rc1 where the  network server field
was not being restored in the settings dialog has been resolved.

In settings the "Test PTT" button is now styled  by checked state.

The  "Test PTT"  button is  enabled without  needing click  "Test CAT"
first when no CAT rig control is selected.

Various parts of the settings dialog  are now disabled when no CAT rig
control is selected. These are the "Mode" group, the "Split Operation"
group and the "Monitor returns to last used frequency" check box. None
of  these have  any  visible impact  nor make  sense  without CAT  rig
control.

Initialization and teardown of rig  control internals has been revised
to avoid several problems related to timing and when switching between
different  CAT  settings. This  includes  improvements  in having  the
operating frequency restored  between sessions when not  using CAT rig
control.

The  initialization   of  OmniRig   connections  has   been  improved,
unfortunately it is  still possible to get an  exception when clicking
the  "Test  CAT" button  where  just  clicking  "OK" and  leaving  the
settings dialog will probably work.

Some unnecessary  CAT commands output  during direct rig  control have
been elided to reduce the level of traffic a little.

The handling of  some automatically generated free  text messages used
when the station is a type 2  compound callsign or is working a type 2
compound callsign has  been improved. This is related to  how a double
click  on  a  message  of  the   form  "DE  TI4/N0URE  73"  is  double
clicked. The  new behaviour depends  on whether the current  "DX Call"
matches the  call in the message.   This resolves the ambiguity  as to
whether this message  is a sign off  at the end of a  QSO with current
operator (a 73  message is generated) or a tail  end opportunity where
the message should be treated the same  as a CQ or QRZ message (WSJT-X
QSYs  to the  frequency, generates  messages and  selects message  one
ready to call).  This still  leaves some potential ambiguous behaviors
in  this complex  area but  selecting "Clear  DX call  and grid  after
logging" should resolve most of them.

Rig  control trace  messages have  been cleaned  up and  are now  more
helpful, less verbose and, tidier in the source code.
------------------------------------------------------------------------

Merged from the wsjtx-1.5 branch.



git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@5298 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
This commit is contained in:
Bill Somerville 2015-04-26 16:41:12 +00:00
parent a51c5c4251
commit a84b7cdfd3
17 changed files with 869 additions and 1369 deletions

View File

@ -50,7 +50,7 @@
// queries. This should be the only place where a hard coded value for // queries. This should be the only place where a hard coded value for
// a settings item is defined. Any remaining one-time UI // a settings item is defined. Any remaining one-time UI
// initialization is also done. At the end of the constructor a method // initialization is also done. At the end of the constructor a method
// initialise_models() is called to load the UI with the current // initialize_models() is called to load the UI with the current
// settings values. // settings values.
// //
// 2) When the settings UI is displayed by a client calling the exec() // 2) When the settings UI is displayed by a client calling the exec()
@ -65,7 +65,7 @@
// //
// 4) If the user discards the settings changes by dismissing the UI // 4) If the user discards the settings changes by dismissing the UI
// with the "Cancel" button; the reject() operation is called. The // with the "Cancel" button; the reject() operation is called. The
// reject() operation calls initialise_models() which will revert all // reject() operation calls initialize_models() which will revert all
// the UI visible state to the values as at the initial exec() // the UI visible state to the values as at the initial exec()
// operation. No changes are moved into the data fields in // operation. No changes are moved into the data fields in
// Configuration::impl that reflect the settings state published by // Configuration::impl that reflect the settings state published by
@ -107,7 +107,7 @@
// default value. If the setting value is dynamic, add a signal emit // default value. If the setting value is dynamic, add a signal emit
// call to broadcast the setting value change. // call to broadcast the setting value change.
// //
// 6) Add code to initialise_models() to load the widget control's // 6) Add code to initialize_models() to load the widget control's
// data model with the current value. // data model with the current value.
// //
// 7) If there is no convenient data model field, add a data member to // 7) If there is no convenient data model field, add a data member to
@ -135,6 +135,7 @@
#include <QApplication> #include <QApplication>
#include <QMetaType> #include <QMetaType>
#include <QList>
#include <QSettings> #include <QSettings>
#include <QAudioDeviceInfo> #include <QAudioDeviceInfo>
#include <QAudioInput> #include <QAudioInput>
@ -335,40 +336,6 @@ public:
}; };
// Fields that are transceiver related.
//
// These are aggregated in a structure to enable a non-equivalence to
// be provided.
//
// don't forget to update the != operator if any fields are added
// otherwise rig parameter changes will not trigger reconfiguration
struct RigParams
{
QString CAT_serial_port_;
QString CAT_network_port_;
qint32 CAT_baudrate_;
TransceiverFactory::DataBits CAT_data_bits_;
TransceiverFactory::StopBits CAT_stop_bits_;
TransceiverFactory::Handshake CAT_handshake_;
bool CAT_force_control_lines_;
bool CAT_DTR_high_;
bool CAT_RTS_high_;
qint32 CAT_poll_interval_;
TransceiverFactory::PTTMethod PTT_method_;
QString PTT_port_;
TransceiverFactory::TXAudioSource TX_audio_source_;
TransceiverFactory::SplitMode split_mode_;
QString rig_name_;
};
bool operator != (RigParams const&, RigParams const&);
inline
bool operator == (RigParams const& lhs, RigParams const& rhs)
{
return !(lhs != rhs);
}
// Internal implementation of the Configuration class. // Internal implementation of the Configuration class.
class Configuration::impl final class Configuration::impl final
: public QDialog : public QDialog
@ -407,10 +374,11 @@ private:
void set_application_font (QFont const&); void set_application_font (QFont const&);
void initialise_models (); void initialize_models ();
bool open_rig (); bool open_rig ();
//bool set_mode (); //bool set_mode ();
void close_rig (); void close_rig ();
TransceiverFactory::ParameterPack gather_rig_data ();
void enumerate_rigs (); void enumerate_rigs ();
void set_rig_invariants (); void set_rig_invariants ();
bool validate (); bool validate ();
@ -428,7 +396,7 @@ private:
Q_SLOT void on_CAT_poll_interval_spin_box_valueChanged (int); Q_SLOT void on_CAT_poll_interval_spin_box_valueChanged (int);
Q_SLOT void on_split_mode_button_group_buttonClicked (int); Q_SLOT void on_split_mode_button_group_buttonClicked (int);
Q_SLOT void on_test_CAT_push_button_clicked (); Q_SLOT void on_test_CAT_push_button_clicked ();
Q_SLOT void on_test_PTT_push_button_clicked (); Q_SLOT void on_test_PTT_push_button_clicked (bool checked);
Q_SLOT void on_CAT_control_lines_group_box_toggled (bool); Q_SLOT void on_CAT_control_lines_group_box_toggled (bool);
Q_SLOT void on_CAT_DTR_check_box_toggled (bool); Q_SLOT void on_CAT_DTR_check_box_toggled (bool);
Q_SLOT void on_CAT_RTS_check_box_toggled (bool); Q_SLOT void on_CAT_RTS_check_box_toggled (bool);
@ -457,6 +425,7 @@ private:
Q_SLOT void on_pbNewCall_clicked(); Q_SLOT void on_pbNewCall_clicked();
// typenames used as arguments must match registered type names :( // typenames used as arguments must match registered type names :(
Q_SIGNAL void start_transceiver () const;
Q_SIGNAL void stop_transceiver () const; Q_SIGNAL void stop_transceiver () const;
Q_SIGNAL void frequency (Frequency rx, Transceiver::MODE) const; Q_SIGNAL void frequency (Frequency rx, Transceiver::MODE) const;
Q_SIGNAL void tx_frequency (Frequency tx, bool rationalize_mode) const; Q_SIGNAL void tx_frequency (Frequency tx, bool rationalize_mode) const;
@ -468,6 +437,7 @@ private:
QThread transceiver_thread_; QThread transceiver_thread_;
TransceiverFactory transceiver_factory_; TransceiverFactory transceiver_factory_;
QList<QMetaObject::Connection> rig_connections_;
Ui::configuration_dialog * ui_; Ui::configuration_dialog * ui_;
@ -511,14 +481,13 @@ private:
QAction * station_insert_action_; QAction * station_insert_action_;
StationDialog * station_dialog_; StationDialog * station_dialog_;
RigParams rig_params_; TransceiverFactory::ParameterPack rig_params_;
RigParams saved_rig_params_; TransceiverFactory::ParameterPack saved_rig_params_;
bool rig_is_dummy_; bool rig_is_dummy_;
bool rig_active_; bool rig_active_;
bool have_rig_; bool have_rig_;
bool rig_changed_; bool rig_changed_;
TransceiverState cached_rig_state_; TransceiverState cached_rig_state_;
bool ptt_state_;
// the following members are required to get the rig into split the // the following members are required to get the rig into split the
// first time monitor or tune or Tx occur // first time monitor or tune or Tx occur
@ -626,7 +595,7 @@ bool Configuration::id_after_73 () const {return m_->id_after_73_;}
bool Configuration::tx_QSY_allowed () const {return m_->tx_QSY_allowed_;} bool Configuration::tx_QSY_allowed () const {return m_->tx_QSY_allowed_;}
bool Configuration::spot_to_psk_reporter () const {return m_->spot_to_psk_reporter_;} bool Configuration::spot_to_psk_reporter () const {return m_->spot_to_psk_reporter_;}
bool Configuration::monitor_off_at_startup () const {return m_->monitor_off_at_startup_;} bool Configuration::monitor_off_at_startup () const {return m_->monitor_off_at_startup_;}
bool Configuration::monitor_last_used () const {return m_->monitor_last_used_;} bool Configuration::monitor_last_used () const {return m_->rig_is_dummy_ || m_->monitor_last_used_;}
bool Configuration::log_as_RTTY () const {return m_->log_as_RTTY_;} bool Configuration::log_as_RTTY () const {return m_->log_as_RTTY_;}
bool Configuration::report_in_comments () const {return m_->report_in_comments_;} bool Configuration::report_in_comments () const {return m_->report_in_comments_;}
bool Configuration::prompt_to_log () const {return m_->prompt_to_log_;} bool Configuration::prompt_to_log () const {return m_->prompt_to_log_;}
@ -642,7 +611,7 @@ bool Configuration::enable_VHF_features () const {return m_->enable_VHF_features
bool Configuration::decode_at_52s () const {return m_->decode_at_52s_;} bool Configuration::decode_at_52s () const {return m_->decode_at_52s_;}
bool Configuration::split_mode () const bool Configuration::split_mode () const
{ {
return !m_->rig_is_dummy_ && m_->rig_params_.split_mode_ != TransceiverFactory::split_mode_none; return !m_->rig_is_dummy_ && m_->rig_params_.split_mode != TransceiverFactory::split_mode_none;
} }
QString Configuration::udp_server_name () const {return m_->udp_server_name_;} QString Configuration::udp_server_name () const {return m_->udp_server_name_;}
auto Configuration::udp_server_port () const -> port_type {return m_->udp_server_port_;} auto Configuration::udp_server_port () const -> port_type {return m_->udp_server_port_;}
@ -654,7 +623,7 @@ StationList * Configuration::stations () {return &m_->stations_;}
FrequencyList * Configuration::frequencies () {return &m_->frequencies_;} FrequencyList * Configuration::frequencies () {return &m_->frequencies_;}
QStringListModel * Configuration::macros () {return &m_->macros_;} QStringListModel * Configuration::macros () {return &m_->macros_;}
QDir Configuration::save_directory () const {return m_->save_directory_;} QDir Configuration::save_directory () const {return m_->save_directory_;}
QString Configuration::rig_name () const {return m_->rig_params_.rig_name_;} QString Configuration::rig_name () const {return m_->rig_params_.rig_name;}
bool Configuration::transceiver_online (bool open_if_closed) bool Configuration::transceiver_online (bool open_if_closed)
{ {
@ -742,7 +711,7 @@ Configuration::impl::impl (Configuration * self, QSettings * settings, QWidget *
, rig_active_ {false} , rig_active_ {false}
, have_rig_ {false} , have_rig_ {false}
, rig_changed_ {false} , rig_changed_ {false}
, ptt_state_ {false} // , ptt_state_ {false}
, setup_split_ {false} , setup_split_ {false}
, required_tx_frequency_ {0} , required_tx_frequency_ {0}
, enforce_mode_and_split_ {false} , enforce_mode_and_split_ {false}
@ -966,7 +935,7 @@ Configuration::impl::impl (Configuration * self, QSettings * settings, QWidget *
restart_sound_output_device_ = false; restart_sound_output_device_ = false;
enumerate_rigs (); enumerate_rigs ();
initialise_models (); initialize_models ();
transceiver_thread_.start (); transceiver_thread_.start ();
@ -987,7 +956,7 @@ Configuration::impl::~impl ()
temp_dir_.removeRecursively (); // clean up temp files temp_dir_.removeRecursively (); // clean up temp files
} }
void Configuration::impl::initialise_models () void Configuration::impl::initialize_models ()
{ {
auto pal = ui_->callsign_line_edit->palette (); auto pal = ui_->callsign_line_edit->palette ();
if (my_callsign_.isEmpty ()) if (my_callsign_.isEmpty ())
@ -1008,7 +977,7 @@ void Configuration::impl::initialise_models ()
ui_->labDXCC->setStyleSheet(QString("background: %1").arg(color_DXCC_.name())); ui_->labDXCC->setStyleSheet(QString("background: %1").arg(color_DXCC_.name()));
ui_->labNewCall->setStyleSheet(QString("background: %1").arg(color_NewCall_.name())); ui_->labNewCall->setStyleSheet(QString("background: %1").arg(color_NewCall_.name()));
ui_->CW_id_interval_spin_box->setValue (id_interval_); ui_->CW_id_interval_spin_box->setValue (id_interval_);
ui_->PTT_method_button_group->button (rig_params_.PTT_method_)->setChecked (true); ui_->PTT_method_button_group->button (rig_params_.ptt_type)->setChecked (true);
ui_->save_path_display_label->setText (save_directory_.absolutePath ()); ui_->save_path_display_label->setText (save_directory_.absolutePath ());
ui_->CW_id_after_73_check_box->setChecked (id_after_73_); ui_->CW_id_after_73_check_box->setChecked (id_after_73_);
ui_->tx_QSY_check_box->setChecked (tx_QSY_allowed_); ui_->tx_QSY_check_box->setChecked (tx_QSY_allowed_);
@ -1032,25 +1001,25 @@ void Configuration::impl::initialise_models ()
ui_->jt9w_min_dt_double_spin_box->setValue (jt9w_min_dt_); ui_->jt9w_min_dt_double_spin_box->setValue (jt9w_min_dt_);
ui_->jt9w_max_dt_double_spin_box->setValue (jt9w_max_dt_); ui_->jt9w_max_dt_double_spin_box->setValue (jt9w_max_dt_);
ui_->type_2_msg_gen_combo_box->setCurrentIndex (type_2_msg_gen_); ui_->type_2_msg_gen_combo_box->setCurrentIndex (type_2_msg_gen_);
ui_->rig_combo_box->setCurrentText (rig_params_.rig_name_); ui_->rig_combo_box->setCurrentText (rig_params_.rig_name);
ui_->TX_mode_button_group->button (data_mode_)->setChecked (true); ui_->TX_mode_button_group->button (data_mode_)->setChecked (true);
ui_->split_mode_button_group->button (rig_params_.split_mode_)->setChecked (true); ui_->split_mode_button_group->button (rig_params_.split_mode)->setChecked (true);
ui_->CAT_serial_baud_combo_box->setCurrentText (QString::number (rig_params_.CAT_baudrate_)); ui_->CAT_serial_baud_combo_box->setCurrentText (QString::number (rig_params_.baud));
ui_->CAT_data_bits_button_group->button (rig_params_.CAT_data_bits_)->setChecked (true); ui_->CAT_data_bits_button_group->button (rig_params_.data_bits)->setChecked (true);
ui_->CAT_stop_bits_button_group->button (rig_params_.CAT_stop_bits_)->setChecked (true); ui_->CAT_stop_bits_button_group->button (rig_params_.stop_bits)->setChecked (true);
ui_->CAT_handshake_button_group->button (rig_params_.CAT_handshake_)->setChecked (true); ui_->CAT_handshake_button_group->button (rig_params_.handshake)->setChecked (true);
ui_->CAT_control_lines_group_box->setChecked (rig_params_.CAT_force_control_lines_); ui_->CAT_control_lines_group_box->setChecked (rig_params_.force_line_control);
ui_->CAT_DTR_check_box->setChecked (rig_params_.CAT_DTR_high_); ui_->CAT_DTR_check_box->setChecked (rig_params_.dtr_high);
ui_->CAT_RTS_check_box->setChecked (rig_params_.CAT_RTS_high_); ui_->CAT_RTS_check_box->setChecked (rig_params_.rts_high);
ui_->TX_audio_source_button_group->button (rig_params_.TX_audio_source_)->setChecked (true); ui_->TX_audio_source_button_group->button (rig_params_.audio_source)->setChecked (true);
ui_->CAT_poll_interval_spin_box->setValue (rig_params_.CAT_poll_interval_); ui_->CAT_poll_interval_spin_box->setValue (rig_params_.poll_interval);
ui_->udp_server_line_edit->setText (udp_server_name_); ui_->udp_server_line_edit->setText (udp_server_name_);
ui_->udp_server_port_spin_box->setValue (udp_server_port_); ui_->udp_server_port_spin_box->setValue (udp_server_port_);
ui_->accept_udp_requests_check_box->setChecked (accept_udp_requests_); ui_->accept_udp_requests_check_box->setChecked (accept_udp_requests_);
ui_->udpWindowToFront->setChecked(udpWindowToFront_); ui_->udpWindowToFront->setChecked(udpWindowToFront_);
ui_->udpWindowRestore->setChecked(udpWindowRestore_); ui_->udpWindowRestore->setChecked(udpWindowRestore_);
if (rig_params_.PTT_port_.isEmpty ()) if (rig_params_.ptt_port.isEmpty ())
{ {
if (ui_->PTT_port_combo_box->count ()) if (ui_->PTT_port_combo_box->count ())
{ {
@ -1059,7 +1028,7 @@ void Configuration::impl::initialise_models ()
} }
else else
{ {
ui_->PTT_port_combo_box->setCurrentText (rig_params_.PTT_port_); ui_->PTT_port_combo_box->setCurrentText (rig_params_.ptt_port);
} }
next_macros_.setStringList (macros_.stringList ()); next_macros_.setStringList (macros_.stringList ());
@ -1199,20 +1168,20 @@ void Configuration::impl::read_settings ()
log_as_RTTY_ = settings_->value ("toRTTY", false).toBool (); log_as_RTTY_ = settings_->value ("toRTTY", false).toBool ();
report_in_comments_ = settings_->value("dBtoComments", false).toBool (); report_in_comments_ = settings_->value("dBtoComments", false).toBool ();
rig_params_.rig_name_ = settings_->value ("Rig", TransceiverFactory::basic_transceiver_name_).toString (); rig_params_.rig_name = settings_->value ("Rig", TransceiverFactory::basic_transceiver_name_).toString ();
rig_is_dummy_ = TransceiverFactory::basic_transceiver_name_ == rig_params_.rig_name_; rig_is_dummy_ = TransceiverFactory::basic_transceiver_name_ == rig_params_.rig_name;
rig_params_.CAT_network_port_ = settings_->value ("CATNetworkPort").toString (); rig_params_.network_port = settings_->value ("CATNetworkPort").toString ();
rig_params_.CAT_serial_port_ = settings_->value ("CATSerialPort").toString (); rig_params_.serial_port = settings_->value ("CATSerialPort").toString ();
rig_params_.CAT_baudrate_ = settings_->value ("CATSerialRate", 4800).toInt (); rig_params_.baud = settings_->value ("CATSerialRate", 4800).toInt ();
rig_params_.CAT_data_bits_ = settings_->value ("CATDataBits", QVariant::fromValue (TransceiverFactory::eight_data_bits)).value<TransceiverFactory::DataBits> (); rig_params_.data_bits = settings_->value ("CATDataBits", QVariant::fromValue (TransceiverFactory::eight_data_bits)).value<TransceiverFactory::DataBits> ();
rig_params_.CAT_stop_bits_ = settings_->value ("CATStopBits", QVariant::fromValue (TransceiverFactory::two_stop_bits)).value<TransceiverFactory::StopBits> (); rig_params_.stop_bits = settings_->value ("CATStopBits", QVariant::fromValue (TransceiverFactory::two_stop_bits)).value<TransceiverFactory::StopBits> ();
rig_params_.CAT_handshake_ = settings_->value ("CATHandshake", QVariant::fromValue (TransceiverFactory::handshake_none)).value<TransceiverFactory::Handshake> (); rig_params_.handshake = settings_->value ("CATHandshake", QVariant::fromValue (TransceiverFactory::handshake_none)).value<TransceiverFactory::Handshake> ();
rig_params_.CAT_force_control_lines_ = settings_->value ("CATForceControlLines", false).toBool (); rig_params_.force_line_control = settings_->value ("CATForceControlLines", false).toBool ();
rig_params_.CAT_DTR_high_ = settings_->value ("DTR", false).toBool (); rig_params_.dtr_high = settings_->value ("DTR", false).toBool ();
rig_params_.CAT_RTS_high_ = settings_->value ("RTS", false).toBool (); rig_params_.rts_high = settings_->value ("RTS", false).toBool ();
rig_params_.PTT_method_ = settings_->value ("PTTMethod", QVariant::fromValue (TransceiverFactory::PTT_method_VOX)).value<TransceiverFactory::PTTMethod> (); rig_params_.ptt_type = settings_->value ("PTTMethod", QVariant::fromValue (TransceiverFactory::PTT_method_VOX)).value<TransceiverFactory::PTTMethod> ();
rig_params_.TX_audio_source_ = settings_->value ("TXAudioSource", QVariant::fromValue (TransceiverFactory::TX_audio_source_front)).value<TransceiverFactory::TXAudioSource> (); rig_params_.audio_source = settings_->value ("TXAudioSource", QVariant::fromValue (TransceiverFactory::TX_audio_source_front)).value<TransceiverFactory::TXAudioSource> ();
rig_params_.PTT_port_ = settings_->value ("PTTport").toString (); rig_params_.ptt_port = settings_->value ("PTTport").toString ();
data_mode_ = settings_->value ("DataMode", QVariant::fromValue (data_mode_none)).value<Configuration::DataMode> (); data_mode_ = settings_->value ("DataMode", QVariant::fromValue (data_mode_none)).value<Configuration::DataMode> ();
prompt_to_log_ = settings_->value ("PromptToLog", false).toBool (); prompt_to_log_ = settings_->value ("PromptToLog", false).toBool ();
insert_blank_ = settings_->value ("InsertBlank", false).toBool (); insert_blank_ = settings_->value ("InsertBlank", false).toBool ();
@ -1225,8 +1194,8 @@ void Configuration::impl::read_settings ()
TX_messages_ = settings_->value ("Tx2QSO", false).toBool (); TX_messages_ = settings_->value ("Tx2QSO", false).toBool ();
enable_VHF_features_ = settings_->value("VHFUHF",false).toBool (); enable_VHF_features_ = settings_->value("VHFUHF",false).toBool ();
decode_at_52s_ = settings_->value("Decode52",false).toBool (); decode_at_52s_ = settings_->value("Decode52",false).toBool ();
rig_params_.CAT_poll_interval_ = settings_->value ("Polling", 0).toInt (); rig_params_.poll_interval = settings_->value ("Polling", 0).toInt ();
rig_params_.split_mode_ = settings_->value ("SplitMode", QVariant::fromValue (TransceiverFactory::split_mode_none)).value<TransceiverFactory::SplitMode> (); rig_params_.split_mode = settings_->value ("SplitMode", QVariant::fromValue (TransceiverFactory::split_mode_none)).value<TransceiverFactory::SplitMode> ();
udp_server_name_ = settings_->value ("UDPServer", "localhost").toString (); udp_server_name_ = settings_->value ("UDPServer", "localhost").toString ();
udp_server_port_ = settings_->value ("UDPServerPort", 2237).toUInt (); udp_server_port_ = settings_->value ("UDPServerPort", 2237).toUInt ();
accept_udp_requests_ = settings_->value ("AcceptUDPRequests", false).toBool (); accept_udp_requests_ = settings_->value ("AcceptUDPRequests", false).toBool ();
@ -1248,8 +1217,8 @@ void Configuration::impl::write_settings ()
settings_->setValue ("Font", font_.toString ()); settings_->setValue ("Font", font_.toString ());
settings_->setValue ("DecodedTextFont", decoded_text_font_.toString ()); settings_->setValue ("DecodedTextFont", decoded_text_font_.toString ());
settings_->setValue ("IDint", id_interval_); settings_->setValue ("IDint", id_interval_);
settings_->setValue ("PTTMethod", QVariant::fromValue (rig_params_.PTT_method_)); settings_->setValue ("PTTMethod", QVariant::fromValue (rig_params_.ptt_type));
settings_->setValue ("PTTport", rig_params_.PTT_port_); settings_->setValue ("PTTport", rig_params_.ptt_port);
settings_->setValue ("SaveDir", save_directory_.absolutePath ()); settings_->setValue ("SaveDir", save_directory_.absolutePath ());
if (default_audio_input_device_selected_) if (default_audio_input_device_selected_)
@ -1286,13 +1255,13 @@ void Configuration::impl::write_settings ()
settings_->setValue ("stations", QVariant::fromValue (stations_.stations ())); settings_->setValue ("stations", QVariant::fromValue (stations_.stations ()));
settings_->setValue ("toRTTY", log_as_RTTY_); settings_->setValue ("toRTTY", log_as_RTTY_);
settings_->setValue ("dBtoComments", report_in_comments_); settings_->setValue ("dBtoComments", report_in_comments_);
settings_->setValue ("Rig", rig_params_.rig_name_); settings_->setValue ("Rig", rig_params_.rig_name);
settings_->setValue ("CATNetworkPort", rig_params_.CAT_network_port_); settings_->setValue ("CATNetworkPort", rig_params_.network_port);
settings_->setValue ("CATSerialPort", rig_params_.CAT_serial_port_); settings_->setValue ("CATSerialPort", rig_params_.serial_port);
settings_->setValue ("CATSerialRate", rig_params_.CAT_baudrate_); settings_->setValue ("CATSerialRate", rig_params_.baud);
settings_->setValue ("CATDataBits", QVariant::fromValue (rig_params_.CAT_data_bits_)); settings_->setValue ("CATDataBits", QVariant::fromValue (rig_params_.data_bits));
settings_->setValue ("CATStopBits", QVariant::fromValue (rig_params_.CAT_stop_bits_)); settings_->setValue ("CATStopBits", QVariant::fromValue (rig_params_.stop_bits));
settings_->setValue ("CATHandshake", QVariant::fromValue (rig_params_.CAT_handshake_)); settings_->setValue ("CATHandshake", QVariant::fromValue (rig_params_.handshake));
settings_->setValue ("DataMode", QVariant::fromValue (data_mode_)); settings_->setValue ("DataMode", QVariant::fromValue (data_mode_));
settings_->setValue ("PromptToLog", prompt_to_log_); settings_->setValue ("PromptToLog", prompt_to_log_);
settings_->setValue ("InsertBlank", insert_blank_); settings_->setValue ("InsertBlank", insert_blank_);
@ -1303,12 +1272,12 @@ void Configuration::impl::write_settings ()
settings_->setValue ("73TxDisable", disable_TX_on_73_); settings_->setValue ("73TxDisable", disable_TX_on_73_);
settings_->setValue ("Runaway", watchdog_); settings_->setValue ("Runaway", watchdog_);
settings_->setValue ("Tx2QSO", TX_messages_); settings_->setValue ("Tx2QSO", TX_messages_);
settings_->setValue ("CATForceControlLines", rig_params_.CAT_force_control_lines_); settings_->setValue ("CATForceControlLines", rig_params_.force_line_control);
settings_->setValue ("DTR", rig_params_.CAT_DTR_high_); settings_->setValue ("DTR", rig_params_.dtr_high);
settings_->setValue ("RTS", rig_params_.CAT_RTS_high_); settings_->setValue ("RTS", rig_params_.rts_high);
settings_->setValue ("TXAudioSource", QVariant::fromValue (rig_params_.TX_audio_source_)); settings_->setValue ("TXAudioSource", QVariant::fromValue (rig_params_.audio_source));
settings_->setValue ("Polling", rig_params_.CAT_poll_interval_); settings_->setValue ("Polling", rig_params_.poll_interval);
settings_->setValue ("SplitMode", QVariant::fromValue (rig_params_.split_mode_)); settings_->setValue ("SplitMode", QVariant::fromValue (rig_params_.split_mode));
settings_->setValue ("VHFUHF", enable_VHF_features_); settings_->setValue ("VHFUHF", enable_VHF_features_);
settings_->setValue ("Decode52", decode_at_52s_); settings_->setValue ("Decode52", decode_at_52s_);
settings_->setValue ("UDPServer", udp_server_name_); settings_->setValue ("UDPServer", udp_server_name_);
@ -1342,11 +1311,26 @@ void Configuration::impl::set_rig_invariants ()
if (TransceiverFactory::basic_transceiver_name_ == rig) if (TransceiverFactory::basic_transceiver_name_ == rig)
{ {
// makes no sense with rig as "None"
ui_->monitor_last_used_check_box->setEnabled (false);
ui_->CAT_control_group_box->setEnabled (false); ui_->CAT_control_group_box->setEnabled (false);
ui_->test_CAT_push_button->setEnabled (false);
ui_->test_PTT_push_button->setEnabled (TransceiverFactory::PTT_method_DTR == ptt_method
|| TransceiverFactory::PTT_method_RTS == ptt_method);
ui_->TX_audio_source_group_box->setEnabled (false);
ui_->mode_group_box->setEnabled (false);
ui_->split_operation_group_box->setEnabled (false);
} }
else else
{ {
ui_->monitor_last_used_check_box->setEnabled (true);
ui_->CAT_control_group_box->setEnabled (true); ui_->CAT_control_group_box->setEnabled (true);
ui_->test_CAT_push_button->setEnabled (true);
ui_->test_PTT_push_button->setEnabled (false);
ui_->TX_audio_source_group_box->setEnabled (transceiver_factory_.has_CAT_PTT_mic_data (rig) && TransceiverFactory::PTT_method_CAT == ptt_method);
ui_->mode_group_box->setEnabled (true);
ui_->split_operation_group_box->setEnabled (true);
if (port_type != last_port_type) if (port_type != last_port_type)
{ {
last_port_type = port_type; last_port_type = port_type;
@ -1354,7 +1338,7 @@ void Configuration::impl::set_rig_invariants ()
{ {
case TransceiverFactory::Capabilities::serial: case TransceiverFactory::Capabilities::serial:
fill_port_combo_box (ui_->CAT_port_combo_box); fill_port_combo_box (ui_->CAT_port_combo_box);
ui_->CAT_port_combo_box->setCurrentText (rig_params_.CAT_serial_port_); ui_->CAT_port_combo_box->setCurrentText (rig_params_.serial_port);
if (ui_->CAT_port_combo_box->currentText ().isEmpty () && ui_->CAT_port_combo_box->count ()) if (ui_->CAT_port_combo_box->currentText ().isEmpty () && ui_->CAT_port_combo_box->count ())
{ {
ui_->CAT_port_combo_box->setCurrentText (ui_->CAT_port_combo_box->itemText (0)); ui_->CAT_port_combo_box->setCurrentText (ui_->CAT_port_combo_box->itemText (0));
@ -1365,7 +1349,8 @@ void Configuration::impl::set_rig_invariants ()
break; break;
case TransceiverFactory::Capabilities::network: case TransceiverFactory::Capabilities::network:
ui_->CAT_port_combo_box->setCurrentText (rig_params_.CAT_network_port_); ui_->CAT_port_combo_box->clear ();
ui_->CAT_port_combo_box->setCurrentText (rig_params_.network_port);
ui_->CAT_port_label->setText (tr ("Network Server:")); ui_->CAT_port_label->setText (tr ("Network Server:"));
ui_->CAT_port_combo_box->setToolTip (tr ("Optional hostname and port of network service.\n" ui_->CAT_port_combo_box->setToolTip (tr ("Optional hostname and port of network service.\n"
"Leave blank for a sensible default on this machine.\n" "Leave blank for a sensible default on this machine.\n"
@ -1373,7 +1358,6 @@ void Configuration::impl::set_rig_invariants ()
"\thostname:port\n" "\thostname:port\n"
"\tIPv4-address:port\n" "\tIPv4-address:port\n"
"\t[IPv6-address]:port")); "\t[IPv6-address]:port"));
ui_->CAT_port_combo_box->clear ();
ui_->CAT_port_combo_box->setEnabled (true); ui_->CAT_port_combo_box->setEnabled (true);
break; break;
@ -1389,16 +1373,6 @@ void Configuration::impl::set_rig_invariants ()
auto const& cat_port = ui_->CAT_port_combo_box->currentText (); auto const& cat_port = ui_->CAT_port_combo_box->currentText ();
ui_->TX_audio_source_group_box->setEnabled (transceiver_factory_.has_CAT_PTT_mic_data (rig) && TransceiverFactory::PTT_method_CAT == ptt_method);
// if (ui_->test_PTT_push_button->isEnabled ()) // don't enable if disabled - "Test CAT" must succeed first
// {
// ui_->test_PTT_push_button->setEnabled ((TransceiverFactory::PTT_method_CAT == ptt_method && CAT_PTT_enabled)
// || TransceiverFactory::PTT_method_DTR == ptt_method
// || TransceiverFactory::PTT_method_RTS == ptt_method);
// }
ui_->test_PTT_push_button->setEnabled (false);
// only enable CAT option if transceiver has CAT PTT // only enable CAT option if transceiver has CAT PTT
ui_->PTT_CAT_radio_button->setEnabled (CAT_PTT_enabled); ui_->PTT_CAT_radio_button->setEnabled (CAT_PTT_enabled);
@ -1443,13 +1417,6 @@ bool Configuration::impl::validate ()
return false; return false;
} }
// auto CAT_port = ui_->CAT_port_combo_box->currentText ();
// if (ui_->CAT_port_combo_box->isEnabled () && CAT_port.isEmpty ())
// {
// message_box (tr ("Invalid CAT port"));
// return false;
// }
auto ptt_method = static_cast<TransceiverFactory::PTTMethod> (ui_->PTT_method_button_group->checkedId ()); auto ptt_method = static_cast<TransceiverFactory::PTTMethod> (ui_->PTT_method_button_group->checkedId ());
auto ptt_port = ui_->PTT_port_combo_box->currentText (); auto ptt_port = ui_->PTT_port_combo_box->currentText ();
if ((TransceiverFactory::PTT_method_DTR == ptt_method || TransceiverFactory::PTT_method_RTS == ptt_method) if ((TransceiverFactory::PTT_method_DTR == ptt_method || TransceiverFactory::PTT_method_RTS == ptt_method)
@ -1468,17 +1435,49 @@ int Configuration::impl::exec ()
// macros can be modified in the main window // macros can be modified in the main window
next_macros_.setStringList (macros_.stringList ()); next_macros_.setStringList (macros_.stringList ());
ptt_state_ = false;
have_rig_ = rig_active_; // record that we started with a rig open have_rig_ = rig_active_; // record that we started with a rig open
saved_rig_params_ = rig_params_; // used to detect changes that saved_rig_params_ = rig_params_; // used to detect changes that
// require the Transceiver to be // require the Transceiver to be
// re-opened // re-opened
rig_changed_ = false; rig_changed_ = false;
initialize_models ();
return QDialog::exec(); return QDialog::exec();
} }
TransceiverFactory::ParameterPack Configuration::impl::gather_rig_data ()
{
TransceiverFactory::ParameterPack result;
result.rig_name = ui_->rig_combo_box->currentText ();
switch (transceiver_factory_.CAT_port_type (result.rig_name))
{
case TransceiverFactory::Capabilities::network:
result.network_port = ui_->CAT_port_combo_box->currentText ();
result.serial_port = rig_params_.serial_port;
break;
default:
result.serial_port = ui_->CAT_port_combo_box->currentText ();
result.network_port = rig_params_.network_port;
break;
}
result.baud = ui_->CAT_serial_baud_combo_box->currentText ().toInt ();
result.data_bits = static_cast<TransceiverFactory::DataBits> (ui_->CAT_data_bits_button_group->checkedId ());
result.stop_bits = static_cast<TransceiverFactory::StopBits> (ui_->CAT_stop_bits_button_group->checkedId ());
result.handshake = static_cast<TransceiverFactory::Handshake> (ui_->CAT_handshake_button_group->checkedId ());
result.force_line_control = ui_->CAT_control_lines_group_box->isChecked ();
result.dtr_high = ui_->CAT_DTR_check_box->isChecked ();
result.rts_high = ui_->CAT_RTS_check_box->isChecked ();
result.poll_interval = ui_->CAT_poll_interval_spin_box->value ();
result.ptt_type = static_cast<TransceiverFactory::PTTMethod> (ui_->PTT_method_button_group->checkedId ());
result.ptt_port = ui_->PTT_port_combo_box->currentText ();
result.audio_source = static_cast<TransceiverFactory::TXAudioSource> (ui_->TX_audio_source_button_group->checkedId ());
result.split_mode = static_cast<TransceiverFactory::SplitMode> (ui_->split_mode_button_group->checkedId ());
return result;
}
void Configuration::impl::accept () void Configuration::impl::accept ()
{ {
// Called when OK button is clicked. // Called when OK button is clicked.
@ -1491,39 +1490,7 @@ void Configuration::impl::accept ()
// extract all rig related configuration parameters into temporary // extract all rig related configuration parameters into temporary
// structure for checking if the rig needs re-opening without // structure for checking if the rig needs re-opening without
// actually updating our live state // actually updating our live state
RigParams temp_rig_params; auto temp_rig_params = gather_rig_data ();
temp_rig_params.rig_name_ = ui_->rig_combo_box->currentText ();
switch (transceiver_factory_.CAT_port_type (temp_rig_params.rig_name_))
{
case TransceiverFactory::Capabilities::serial:
temp_rig_params.CAT_serial_port_ = ui_->CAT_port_combo_box->currentText ();
temp_rig_params.CAT_network_port_ = rig_params_.CAT_network_port_;
break;
case TransceiverFactory::Capabilities::network:
temp_rig_params.CAT_network_port_ = ui_->CAT_port_combo_box->currentText ();
temp_rig_params.CAT_serial_port_ = rig_params_.CAT_serial_port_;
break;
default:
temp_rig_params.CAT_serial_port_ = rig_params_.CAT_serial_port_;
temp_rig_params.CAT_network_port_ = rig_params_.CAT_network_port_;
break;
}
temp_rig_params.CAT_baudrate_ = ui_->CAT_serial_baud_combo_box->currentText ().toInt ();
temp_rig_params.CAT_data_bits_ = static_cast<TransceiverFactory::DataBits> (ui_->CAT_data_bits_button_group->checkedId ());
temp_rig_params.CAT_stop_bits_ = static_cast<TransceiverFactory::StopBits> (ui_->CAT_stop_bits_button_group->checkedId ());
temp_rig_params.CAT_handshake_ = static_cast<TransceiverFactory::Handshake> (ui_->CAT_handshake_button_group->checkedId ());
temp_rig_params.CAT_force_control_lines_ = ui_->CAT_control_lines_group_box->isChecked ();
temp_rig_params.CAT_DTR_high_ = ui_->CAT_DTR_check_box->isChecked ();
temp_rig_params.CAT_RTS_high_ = ui_->CAT_RTS_check_box->isChecked ();
temp_rig_params.CAT_poll_interval_ = ui_->CAT_poll_interval_spin_box->value ();
temp_rig_params.PTT_method_ = static_cast<TransceiverFactory::PTTMethod> (ui_->PTT_method_button_group->checkedId ());
temp_rig_params.PTT_port_ = ui_->PTT_port_combo_box->currentText ();
temp_rig_params.TX_audio_source_ = static_cast<TransceiverFactory::TXAudioSource> (ui_->TX_audio_source_button_group->checkedId ());
temp_rig_params.split_mode_ = static_cast<TransceiverFactory::SplitMode> (ui_->split_mode_button_group->checkedId ());
// open_rig() uses values from models so we use it to validate the // open_rig() uses values from models so we use it to validate the
// Transceiver settings before agreeing to accept the configuration // Transceiver settings before agreeing to accept the configuration
@ -1565,7 +1532,7 @@ void Configuration::impl::accept ()
rig_params_ = temp_rig_params; // now we can go live with the rig rig_params_ = temp_rig_params; // now we can go live with the rig
// related configuration parameters // related configuration parameters
rig_is_dummy_ = TransceiverFactory::basic_transceiver_name_ == rig_params_.rig_name_; rig_is_dummy_ = TransceiverFactory::basic_transceiver_name_ == rig_params_.rig_name;
// Check to see whether SoundInThread must be restarted, // Check to see whether SoundInThread must be restarted,
// and save user parameters. // and save user parameters.
@ -1709,7 +1676,7 @@ void Configuration::impl::accept ()
void Configuration::impl::reject () void Configuration::impl::reject ()
{ {
initialise_models (); // reverts to settings as at exec () initialize_models (); // reverts to settings as at exec ()
// check if the Transceiver instance changed, in which case we need // check if the Transceiver instance changed, in which case we need
// to re open any prior Transceiver type // to re open any prior Transceiver type
@ -1871,19 +1838,19 @@ void Configuration::impl::on_test_CAT_push_button_clicked ()
set_rig_invariants (); set_rig_invariants ();
} }
void Configuration::impl::on_test_PTT_push_button_clicked () void Configuration::impl::on_test_PTT_push_button_clicked (bool checked)
{ {
ui_->test_PTT_push_button->setChecked (!checked); // let status
// update check us
if (!validate ()) if (!validate ())
{ {
return; return;
} }
Q_EMIT self_->transceiver_ptt ((ptt_state_ = !ptt_state_)); if (open_rig ())
{
ui_->test_PTT_push_button->setStyleSheet (ptt_state_ ? "QPushButton{background-color: red;" Q_EMIT self_->transceiver_ptt (checked);
"border-style: outset; border-width: 1px; border-radius: 5px;" }
"border-color: black; min-width: 5em; padding: 3px;}"
: "");
} }
void Configuration::impl::on_CAT_control_lines_group_box_toggled (bool /* checked */) void Configuration::impl::on_CAT_control_lines_group_box_toggled (bool /* checked */)
@ -2034,7 +2001,7 @@ void Configuration::impl::on_save_path_select_push_button_clicked (bool /* check
bool Configuration::impl::have_rig (bool open_if_closed) bool Configuration::impl::have_rig (bool open_if_closed)
{ {
if (open_if_closed && !rig_active_ && !open_rig ()) if (open_if_closed && !open_rig ())
{ {
QMessageBox::critical (this, "WSJT-X", tr ("Failed to open connection to rig")); QMessageBox::critical (this, "WSJT-X", tr ("Failed to open connection to rig"));
} }
@ -2045,84 +2012,76 @@ bool Configuration::impl::open_rig ()
{ {
auto result = false; auto result = false;
try auto const rig_data = gather_rig_data ();
if (!rig_active_ || rig_data != saved_rig_params_)
{ {
close_rig (); try
// create a new Transceiver object
TransceiverFactory::LineControl DTR {TransceiverFactory::no_control};
TransceiverFactory::LineControl RTS {TransceiverFactory::no_control};
if (ui_->CAT_control_lines_group_box->isChecked ())
{ {
DTR = ui_->CAT_DTR_check_box->isEnabled () && ui_->CAT_DTR_check_box->isChecked () ? TransceiverFactory::force_high : TransceiverFactory::force_low; close_rig ();
RTS = ui_->CAT_RTS_check_box->isEnabled () && ui_->CAT_RTS_check_box->isChecked () ? TransceiverFactory::force_high : TransceiverFactory::force_low;
// create a new Transceiver object
auto rig = transceiver_factory_.create (rig_data, &transceiver_thread_);
// hook up Configuration transceiver control signals to Transceiver slots
//
// these connections cross the thread boundary
rig_connections_ << connect (this, &Configuration::impl::frequency, rig.get (), &Transceiver::frequency);
rig_connections_ << connect (this, &Configuration::impl::tx_frequency, rig.get (), &Transceiver::tx_frequency);
rig_connections_ << connect (this, &Configuration::impl::mode, rig.get (), &Transceiver::mode);
rig_connections_ << connect (this, &Configuration::impl::ptt, rig.get (), &Transceiver::ptt);
rig_connections_ << connect (this, &Configuration::impl::sync, rig.get (), &Transceiver::sync);
// hook up Transceiver signals to Configuration signals
//
// these connections cross the thread boundary
connect (rig.get (), &Transceiver::update, this, &Configuration::impl::handle_transceiver_update);
connect (rig.get (), &Transceiver::failure, this, &Configuration::impl::handle_transceiver_failure);
// setup thread safe startup and close down semantics
rig_connections_ << connect (this, &Configuration::impl::start_transceiver, rig.get (), &Transceiver::start);
connect (this, &Configuration::impl::stop_transceiver, rig.get (), &Transceiver::stop);
auto p = rig.release (); // take ownership
// schedule eventual destruction
//
// must be queued connection to avoid premature self-immolation
// since finished signal is going to be emitted from the object
// that will get destroyed in its own stop slot i.e. a same
// thread signal to slot connection which by default will be
// reduced to a method function call.
connect (p, &Transceiver::finished, p, &Transceiver::deleteLater, Qt::QueuedConnection);
ui_->test_CAT_push_button->setStyleSheet ({});
rig_active_ = true;
Q_EMIT start_transceiver (); // start rig on its thread
result = true;
}
catch (std::exception const& e)
{
handle_transceiver_failure (e.what ());
} }
auto rig = transceiver_factory_.create (ui_->rig_combo_box->currentText ()
, ui_->CAT_port_combo_box->currentText ()
, ui_->CAT_serial_baud_combo_box->currentText ().toInt ()
, static_cast<TransceiverFactory::DataBits> (ui_->CAT_data_bits_button_group->checkedId ())
, static_cast<TransceiverFactory::StopBits> (ui_->CAT_stop_bits_button_group->checkedId ())
, static_cast<TransceiverFactory::Handshake> (ui_->CAT_handshake_button_group->checkedId ())
, DTR
, RTS
, static_cast<TransceiverFactory::PTTMethod> (ui_->PTT_method_button_group->checkedId ())
, static_cast<TransceiverFactory::TXAudioSource> (ui_->TX_audio_source_button_group->checkedId ())
, static_cast<TransceiverFactory::SplitMode> (ui_->split_mode_button_group->checkedId ())
, ui_->PTT_port_combo_box->currentText ()
, ui_->CAT_poll_interval_spin_box->value () * 1000
, &transceiver_thread_
);
// hook up Configuration transceiver control signals to Transceiver slots saved_rig_params_ = rig_data;
// rig_changed_ = true;
// these connections cross the thread boundary }
connect (this, &Configuration::impl::frequency, rig.get (), &Transceiver::frequency); else
connect (this, &Configuration::impl::tx_frequency, rig.get (), &Transceiver::tx_frequency); {
connect (this, &Configuration::impl::mode, rig.get (), &Transceiver::mode);
connect (this, &Configuration::impl::ptt, rig.get (), &Transceiver::ptt);
connect (this, &Configuration::impl::sync, rig.get (), &Transceiver::sync);
// hook up Transceiver signals to Configuration signals
//
// these connections cross the thread boundary
connect (rig.get (), &Transceiver::update, this, &Configuration::impl::handle_transceiver_update);
connect (rig.get (), &Transceiver::failure, this, &Configuration::impl::handle_transceiver_failure);
// setup thread safe startup and close down semantics
connect (this, &Configuration::impl::stop_transceiver, rig.get (), &Transceiver::stop);
auto p = rig.release (); // take ownership
// schedule eventual destruction
//
// must be queued connection to avoid premature self-immolation
// since finished signal is going to be emitted from the object
// that will get destroyed in its own stop slot i.e. a same
// thread signal to slot connection which by default will be
// reduced to a method function call.
connect (p, &Transceiver::finished, p, &Transceiver::deleteLater, Qt::QueuedConnection);
ui_->test_CAT_push_button->setStyleSheet ({});
rig_active_ = true;
QTimer::singleShot (0, p, SLOT (start ())); // start rig on its thread
result = true; result = true;
} }
catch (std::exception const& e)
{
handle_transceiver_failure (e.what ());
}
rig_changed_ = true;
return result; return result;
} }
void Configuration::impl::transceiver_frequency (Frequency f) void Configuration::impl::transceiver_frequency (Frequency f)
{ {
Transceiver::MODE mode {Transceiver::UNK}; Transceiver::MODE mode {Transceiver::UNK};
switch (static_cast<DataMode> (ui_->TX_mode_button_group->checkedId ())) if (ui_->mode_group_box->isEnabled ())
{ {
case data_mode_USB: mode = Transceiver::USB; break; switch (static_cast<DataMode> (ui_->TX_mode_button_group->checkedId ()))
case data_mode_data: mode = Transceiver::DIG_U; break; {
case data_mode_none: break; case data_mode_USB: mode = Transceiver::USB; break;
case data_mode_data: mode = Transceiver::DIG_U; break;
case data_mode_none: break;
}
} }
if (cached_rig_state_.frequency () != f if (cached_rig_state_.frequency () != f
@ -2137,38 +2096,6 @@ void Configuration::impl::transceiver_frequency (Frequency f)
} }
} }
// bool Configuration::impl::set_mode ()
// {
// // Some rigs change frequency when switching between some modes so
// // we need to check if we change mode and not elide the frequency
// // setting in the same as the cached frequency.
// bool mode_changed {false};
// auto data_mode = static_cast<DataMode> (ui_->TX_mode_button_group->checkedId ());
// // Set mode if we are responsible for it.
// if (data_mode_USB == data_mode && cached_rig_state_.mode () != Transceiver::USB)
// {
// if (Transceiver::USB != cached_rig_state_.mode ())
// {
// cached_rig_state_.mode (Transceiver::USB);
// Q_EMIT mode (Transceiver::USB, cached_rig_state_.split () && data_mode_none != data_mode_);
// mode_changed = true;
// }
// }
// if (data_mode_data == data_mode && cached_rig_state_.mode () != Transceiver::DIG_U)
// {
// if (Transceiver::DIG_U != cached_rig_state_.mode ())
// {
// cached_rig_state_.mode (Transceiver::DIG_U);
// Q_EMIT mode (Transceiver::DIG_U, cached_rig_state_.split () && data_mode_none != data_mode_);
// mode_changed = true;
// }
// }
// return mode_changed;
// }
void Configuration::impl::transceiver_tx_frequency (Frequency f) void Configuration::impl::transceiver_tx_frequency (Frequency f)
{ {
if (/* set_mode () || */ cached_rig_state_.tx_frequency () != f || cached_rig_state_.split () != !!f) if (/* set_mode () || */ cached_rig_state_.tx_frequency () != f || cached_rig_state_.split () != !!f)
@ -2185,7 +2112,9 @@ void Configuration::impl::transceiver_tx_frequency (Frequency f)
// Rationalise TX VFO mode if we ask for split and are // Rationalise TX VFO mode if we ask for split and are
// responsible for mode. // responsible for mode.
Q_EMIT tx_frequency (f, cached_rig_state_.split () && data_mode_none != data_mode_); Q_EMIT tx_frequency (f, cached_rig_state_.split ()
&& ui_->mode_group_box->isEnabled ()
&& data_mode_none != data_mode_);
} }
} }
@ -2196,14 +2125,14 @@ void Configuration::impl::transceiver_mode (MODE m)
cached_rig_state_.mode (m); cached_rig_state_.mode (m);
// Rationalise mode if we are responsible for it and in split mode. // Rationalise mode if we are responsible for it and in split mode.
Q_EMIT mode (m, cached_rig_state_.split () && data_mode_none != data_mode_); Q_EMIT mode (m, cached_rig_state_.split ()
&& ui_->mode_group_box->isEnabled ()
&& data_mode_none != data_mode_);
} }
} }
void Configuration::impl::transceiver_ptt (bool on) void Configuration::impl::transceiver_ptt (bool on)
{ {
// set_mode ();
cached_rig_state_.ptt (on); cached_rig_state_.ptt (on);
// pass this on regardless of cache // pass this on regardless of cache
@ -2224,6 +2153,8 @@ void Configuration::impl::handle_transceiver_update (TransceiverState state)
if (state.online ()) if (state.online ())
{ {
ui_->test_PTT_push_button->setChecked (state.ptt ());
TransceiverFactory::SplitMode split_mode_selected; TransceiverFactory::SplitMode split_mode_selected;
if (isVisible ()) if (isVisible ())
{ {
@ -2236,7 +2167,6 @@ void Configuration::impl::handle_transceiver_update (TransceiverState state)
|| TransceiverFactory::PTT_method_DTR == ptt_method || TransceiverFactory::PTT_method_DTR == ptt_method
|| TransceiverFactory::PTT_method_RTS == ptt_method); || TransceiverFactory::PTT_method_RTS == ptt_method);
// set_mode ();
// Follow the setup choice. // Follow the setup choice.
split_mode_selected = static_cast<TransceiverFactory::SplitMode> (ui_->split_mode_button_group->checkedId ()); split_mode_selected = static_cast<TransceiverFactory::SplitMode> (ui_->split_mode_button_group->checkedId ());
@ -2244,11 +2174,12 @@ void Configuration::impl::handle_transceiver_update (TransceiverState state)
else else
{ {
// Follow the rig unless configuration has been changed. // Follow the rig unless configuration has been changed.
split_mode_selected = static_cast<TransceiverFactory::SplitMode> (rig_params_.split_mode_); split_mode_selected = static_cast<TransceiverFactory::SplitMode> (rig_params_.split_mode);
if (enforce_mode_and_split_) if (enforce_mode_and_split_)
{ {
if ((TransceiverFactory::split_mode_none != split_mode_selected) != state.split ()) if (TransceiverFactory::basic_transceiver_name_ != ui_->rig_combo_box->currentText ()
&& ((TransceiverFactory::split_mode_none != split_mode_selected) != state.split ()))
{ {
if (!setup_split_) if (!setup_split_)
{ {
@ -2259,7 +2190,7 @@ void Configuration::impl::handle_transceiver_update (TransceiverState state)
// (e.g.Icom) this is going to confuse operators, but // (e.g.Icom) this is going to confuse operators, but
// what can we do if they change the rig? // what can we do if they change the rig?
// auto split_mode = state.split () ? TransceiverFactory::split_mode_rig : TransceiverFactory::split_mode_none; // auto split_mode = state.split () ? TransceiverFactory::split_mode_rig : TransceiverFactory::split_mode_none;
// rig_params_.split_mode_ = split_mode; // rig_params_.split_mode = split_mode;
// ui_->split_mode_button_group->button (split_mode)->setChecked (true); // ui_->split_mode_button_group->button (split_mode)->setChecked (true);
// split_mode_selected = split_mode; // split_mode_selected = split_mode;
setup_split_ = true; setup_split_ = true;
@ -2269,8 +2200,6 @@ void Configuration::impl::handle_transceiver_update (TransceiverState state)
Q_EMIT self_->transceiver_failure (tr ("Rig split mode setting not consistent with WSJT-X settings.")); Q_EMIT self_->transceiver_failure (tr ("Rig split mode setting not consistent with WSJT-X settings."));
} }
} }
// set_mode ();
} }
} }
@ -2307,6 +2236,7 @@ void Configuration::impl::handle_transceiver_failure (QString reason)
#endif #endif
close_rig (); close_rig ();
ui_->test_PTT_push_button->setChecked (false);
if (isVisible ()) if (isVisible ())
{ {
@ -2321,15 +2251,18 @@ void Configuration::impl::handle_transceiver_failure (QString reason)
void Configuration::impl::close_rig () void Configuration::impl::close_rig ()
{ {
ui_->test_PTT_push_button->setStyleSheet ({});
ui_->test_PTT_push_button->setEnabled (false); ui_->test_PTT_push_button->setEnabled (false);
ptt_state_ = false;
// revert to no rig configured // revert to no rig configured
if (rig_active_) if (rig_active_)
{ {
ui_->test_CAT_push_button->setStyleSheet ("QPushButton {background-color: red;}"); ui_->test_CAT_push_button->setStyleSheet ("QPushButton {background-color: red;}");
Q_EMIT stop_transceiver (); Q_EMIT stop_transceiver ();
Q_FOREACH (auto const& connection, rig_connections_)
{
disconnect (connection);
}
rig_connections_.clear ();
rig_active_ = false; rig_active_ = false;
} }
} }
@ -2454,7 +2387,7 @@ void Configuration::impl::enumerate_rigs ()
} }
} }
ui_->rig_combo_box->setCurrentText (rig_params_.rig_name_); ui_->rig_combo_box->setCurrentText (rig_params_.rig_name);
} }
void Configuration::impl::fill_port_combo_box (QComboBox * cb) void Configuration::impl::fill_port_combo_box (QComboBox * cb)
@ -2474,27 +2407,6 @@ void Configuration::impl::fill_port_combo_box (QComboBox * cb)
cb->setEditText (current_text); cb->setEditText (current_text);
} }
inline
bool operator != (RigParams const& lhs, RigParams const& rhs)
{
return
lhs.CAT_serial_port_ != rhs.CAT_serial_port_
|| lhs.CAT_network_port_ != rhs.CAT_network_port_
|| lhs.CAT_baudrate_ != rhs.CAT_baudrate_
|| lhs.CAT_data_bits_ != rhs.CAT_data_bits_
|| lhs.CAT_stop_bits_ != rhs.CAT_stop_bits_
|| lhs.CAT_handshake_ != rhs.CAT_handshake_
|| lhs.CAT_force_control_lines_ != rhs.CAT_force_control_lines_
|| lhs.CAT_DTR_high_ != rhs.CAT_DTR_high_
|| lhs.CAT_RTS_high_ != rhs.CAT_RTS_high_
|| lhs.CAT_poll_interval_ != rhs.CAT_poll_interval_
|| lhs.PTT_method_ != rhs.PTT_method_
|| lhs.PTT_port_ != rhs.PTT_port_
|| lhs.TX_audio_source_ != rhs.TX_audio_source_
|| lhs.split_mode_ != rhs.split_mode_
|| lhs.rig_name_ != rhs.rig_name_;
}
#if !defined (QT_NO_DEBUG_STREAM) #if !defined (QT_NO_DEBUG_STREAM)
ENUM_QDEBUG_OPS_IMPL (Configuration, DataMode); ENUM_QDEBUG_OPS_IMPL (Configuration, DataMode);

View File

@ -203,6 +203,7 @@ private:
pimpl<impl> m_; pimpl<impl> m_;
}; };
Q_DECLARE_METATYPE (Configuration::DataMode); Q_DECLARE_METATYPE (Configuration::DataMode);
Q_DECLARE_METATYPE (Configuration::Type2MsgGen); Q_DECLARE_METATYPE (Configuration::Type2MsgGen);

View File

@ -1074,10 +1074,24 @@ Click again to deactivate. Normally no power should be
output since there is no audio being generated at this time. output since there is no audio being generated at this time.
Check that any Tx indication on your radio and/or your Check that any Tx indication on your radio and/or your
radio interface behave as expected.</string> radio interface behave as expected.</string>
</property>
<property name="styleSheet">
<string notr="true">QPushButton:checked {
background-color: red;
border-style : outset;
border-width: 1px;
border-radius: 5px;
border-color: black;
min-width: 5em;
padding: 3px;
}</string>
</property> </property>
<property name="text"> <property name="text">
<string>Test PTT</string> <string>Test PTT</string>
</property> </property>
<property name="checkable">
<bool>true</bool>
</property>
</widget> </widget>
</item> </item>
</layout> </layout>
@ -2237,12 +2251,12 @@ soundcard changes</string>
</connection> </connection>
</connections> </connections>
<buttongroups> <buttongroups>
<buttongroup name="CAT_stop_bits_button_group"/>
<buttongroup name="CAT_data_bits_button_group"/>
<buttongroup name="TX_audio_source_button_group"/>
<buttongroup name="PTT_method_button_group"/> <buttongroup name="PTT_method_button_group"/>
<buttongroup name="TX_mode_button_group"/> <buttongroup name="TX_audio_source_button_group"/>
<buttongroup name="split_mode_button_group"/> <buttongroup name="CAT_data_bits_button_group"/>
<buttongroup name="CAT_handshake_button_group"/> <buttongroup name="CAT_handshake_button_group"/>
<buttongroup name="CAT_stop_bits_button_group"/>
<buttongroup name="split_mode_button_group"/>
<buttongroup name="TX_mode_button_group"/>
</buttongroups> </buttongroups>
</ui> </ui>

View File

@ -54,10 +54,7 @@ DXLabSuiteCommanderTransceiver::~DXLabSuiteCommanderTransceiver ()
void DXLabSuiteCommanderTransceiver::do_start () void DXLabSuiteCommanderTransceiver::do_start ()
{ {
#if WSJT_TRACE_CAT TRACE_CAT ("starting");
qDebug () << "DXLabSuiteCommanderTransceiver::start";
#endif
wrapped_->start (); wrapped_->start ();
auto server_details = network_server_lookup (server_, 52002u, QHostAddress::LocalHost, QAbstractSocket::IPv4Protocol); auto server_details = network_server_lookup (server_, 52002u, QHostAddress::LocalHost, QAbstractSocket::IPv4Protocol);
@ -70,10 +67,7 @@ void DXLabSuiteCommanderTransceiver::do_start ()
commander_->connectToHost (std::get<0> (server_details), std::get<1> (server_details)); commander_->connectToHost (std::get<0> (server_details), std::get<1> (server_details));
if (!commander_->waitForConnected ()) if (!commander_->waitForConnected ())
{ {
#if WSJT_TRACE_CAT TRACE_CAT ("failed to connect" << commander_->errorString ());
qDebug () << "DXLabSuiteCommanderTransceiver::start failed to connect" << commander_->errorString ();
#endif
throw error {tr ("Failed to connect to DX Lab Suite Commander\n") + commander_->errorString ()}; throw error {tr ("Failed to connect to DX Lab Suite Commander\n") + commander_->errorString ()};
} }
@ -89,18 +83,12 @@ void DXLabSuiteCommanderTransceiver::do_stop ()
} }
wrapped_->stop (); wrapped_->stop ();
TRACE_CAT ("stopped");
#if WSJT_TRACE_CAT
qDebug () << "DXLabSuiteCommanderTransceiver::stop";
#endif
} }
void DXLabSuiteCommanderTransceiver::do_ptt (bool on) void DXLabSuiteCommanderTransceiver::do_ptt (bool on)
{ {
#if WSJT_TRACE_CAT TRACE_CAT (on << state ());
qDebug () << "DXLabSuiteCommanderTransceiver::do_ptt:" << on << state ();
#endif
if (use_for_ptt_) if (use_for_ptt_)
{ {
simple_command (on ? "<command:5>CmdTX<parameters:0>" : "<command:5>CmdRX<parameters:0>"); simple_command (on ? "<command:5>CmdTX<parameters:0>" : "<command:5>CmdRX<parameters:0>");
@ -109,16 +97,12 @@ void DXLabSuiteCommanderTransceiver::do_ptt (bool on)
{ {
wrapped_->ptt (on); wrapped_->ptt (on);
} }
update_PTT (on); update_PTT (on);
} }
void DXLabSuiteCommanderTransceiver::do_frequency (Frequency f, MODE m) void DXLabSuiteCommanderTransceiver::do_frequency (Frequency f, MODE m)
{ {
#if WSJT_TRACE_CAT TRACE_CAT (f << state ());
qDebug () << "DXLabSuiteCommanderTransceiver::do_frequency:" << f << state ();
#endif
auto f_string = frequency_to_string (f); auto f_string = frequency_to_string (f);
if (UNK != m) if (UNK != m)
{ {
@ -137,10 +121,7 @@ void DXLabSuiteCommanderTransceiver::do_frequency (Frequency f, MODE m)
void DXLabSuiteCommanderTransceiver::do_tx_frequency (Frequency tx, bool /* rationalise_mode */) void DXLabSuiteCommanderTransceiver::do_tx_frequency (Frequency tx, bool /* rationalise_mode */)
{ {
#if WSJT_TRACE_CAT TRACE_CAT (tx << state ());
qDebug () << "DXLabSuiteCommanderTransceiver::do_tx_frequency:" << tx << state ();
#endif
if (tx) if (tx)
{ {
auto f_string = frequency_to_string (tx); auto f_string = frequency_to_string (tx);
@ -157,15 +138,10 @@ void DXLabSuiteCommanderTransceiver::do_tx_frequency (Frequency tx, bool /* rati
void DXLabSuiteCommanderTransceiver::do_mode (MODE m, bool /* rationalise */) void DXLabSuiteCommanderTransceiver::do_mode (MODE m, bool /* rationalise */)
{ {
#if WSJT_TRACE_CAT TRACE_CAT (m << state ());
qDebug () << "DXLabSuiteCommanderTransceiver::do_mode:" << m << state ();
#endif
auto m_string = map_mode (m); auto m_string = map_mode (m);
auto params = ("<1:%1>" + m_string).arg (m_string.size ()); auto params = ("<1:%1>" + m_string).arg (m_string.size ());
simple_command (("<command:10>CmdSetMode<parameters:%1>" + params).arg (params.size ())); simple_command (("<command:10>CmdSetMode<parameters:%1>" + params).arg (params.size ()));
update_mode (m); update_mode (m);
} }
@ -192,10 +168,7 @@ void DXLabSuiteCommanderTransceiver::poll ()
} }
else else
{ {
#if WSJT_TRACE_CAT TRACE_CAT_POLL ("get frequency unexpected response");
qDebug () << "DXLabSuiteCommanderTransceiver::poll: get frequency unexpected response";
#endif
throw error {tr ("DX Lab Suite Commander didn't respond correctly polling frequency")}; throw error {tr ("DX Lab Suite Commander didn't respond correctly polling frequency")};
} }
@ -216,10 +189,7 @@ void DXLabSuiteCommanderTransceiver::poll ()
} }
else else
{ {
#if WSJT_TRACE_CAT TRACE_CAT_POLL ("get tx frequency unexpected response");
qDebug () << "DXLabSuiteCommanderTransceiver::poll: get tx frequency unexpected response";
#endif
throw error {tr ("DX Lab Suite Commander didn't respond correctly polling TX frequency")}; throw error {tr ("DX Lab Suite Commander didn't respond correctly polling TX frequency")};
} }
} }
@ -238,19 +208,13 @@ void DXLabSuiteCommanderTransceiver::poll ()
} }
else else
{ {
#if WSJT_TRACE_CAT TRACE_CAT_POLL ("unexpected split state" << split);
qDebug () << "DXLabSuiteCommanderTransceiver::poll: unexpected split state" << split;
#endif
throw error {tr ("DX Lab Suite Commander sent an unrecognised split state: ") + split}; throw error {tr ("DX Lab Suite Commander sent an unrecognised split state: ") + split};
} }
} }
else else
{ {
#if WSJT_TRACE_CAT TRACE_CAT_POLL ("get split mode unexpected response");
qDebug () << "DXLabSuiteCommanderTransceiver::poll: get split mode unexpected response";
#endif
throw error {tr ("DX Lab Suite Commander didn't respond correctly polling split status")}; throw error {tr ("DX Lab Suite Commander didn't respond correctly polling split status")};
} }
@ -301,20 +265,14 @@ void DXLabSuiteCommanderTransceiver::poll ()
} }
else else
{ {
#if WSJT_TRACE_CAT TRACE_CAT_POLL ("unexpected mode name" << mode);
qDebug () << "DXLabSuiteCommanderTransceiver::poll: unexpected mode name" << mode;
#endif
throw error {tr ("DX Lab Suite Commander sent an unrecognised mode: \"") + mode + '"'}; throw error {tr ("DX Lab Suite Commander sent an unrecognised mode: \"") + mode + '"'};
} }
update_mode (m); update_mode (m);
} }
else else
{ {
#if WSJT_TRACE_CAT TRACE_CAT_POLL ("unexpected response");
qDebug () << "DXLabSuiteCommanderTransceiver::poll: unexpected response";
#endif
throw error {tr ("DX Lab Suite Commander didn't respond correctly polling mode")}; throw error {tr ("DX Lab Suite Commander didn't respond correctly polling mode")};
} }
} }
@ -325,17 +283,12 @@ void DXLabSuiteCommanderTransceiver::simple_command (QString const& cmd, bool no
if (!no_debug) if (!no_debug)
{ {
#if WSJT_TRACE_CAT TRACE_CAT (cmd);
qDebug () << "DXLabSuiteCommanderTransceiver:simple_command(" << cmd << ')';
#endif
} }
if (!write_to_port (cmd)) if (!write_to_port (cmd))
{ {
#if WSJT_TRACE_CAT TRACE_CAT ("failed:" << commander_->errorString ());
qDebug () << "DXLabSuiteCommanderTransceiver::simple_command failed:" << commander_->errorString ();
#endif
throw error {tr ("DX Lab Suite Commander send command failed\n") + commander_->errorString ()}; throw error {tr ("DX Lab Suite Commander send command failed\n") + commander_->errorString ()};
} }
} }
@ -346,10 +299,7 @@ QString DXLabSuiteCommanderTransceiver::command_with_reply (QString const& cmd,
if (!write_to_port (cmd)) if (!write_to_port (cmd))
{ {
#if WSJT_TRACE_CAT TRACE_CAT ("failed to send command:" << commander_->errorString ());
qDebug () << "DXLabSuiteCommanderTransceiver::command_with_reply failed to send command:" << commander_->errorString ();
#endif
throw error { throw error {
tr ("DX Lab Suite Commander failed to send command \"%1\": %2\n") tr ("DX Lab Suite Commander failed to send command \"%1\": %2\n")
.arg (cmd) .arg (cmd)
@ -366,10 +316,7 @@ QString DXLabSuiteCommanderTransceiver::command_with_reply (QString const& cmd,
replied = commander_->waitForReadyRead (); replied = commander_->waitForReadyRead ();
if (!replied && commander_->error () != commander_->SocketTimeoutError) if (!replied && commander_->error () != commander_->SocketTimeoutError)
{ {
#if WSJT_TRACE_CAT TRACE_CAT (cmd << "failed to read reply:" << commander_->errorString ());
qDebug () << "DXLabSuiteCommanderTransceiver::command_with_reply \"" << cmd << "\" failed to read reply:" << commander_->errorString ();
#endif
throw error { throw error {
tr ("DX Lab Suite Commander send command \"%1\" read reply failed: %2\n") tr ("DX Lab Suite Commander send command \"%1\" read reply failed: %2\n")
.arg (cmd) .arg (cmd)
@ -380,10 +327,7 @@ QString DXLabSuiteCommanderTransceiver::command_with_reply (QString const& cmd,
if (!replied) if (!replied)
{ {
#if WSJT_TRACE_CAT TRACE_CAT (cmd << "retries exhausted");
qDebug () << "DXLabSuiteCommanderTransceiver::command_with_reply \"" << cmd << "\" retries exhausted";
#endif
throw error { throw error {
tr ("DX Lab Suite Commander retries exhausted sending command \"%1\"") tr ("DX Lab Suite Commander retries exhausted sending command \"%1\"")
.arg (cmd) .arg (cmd)
@ -399,9 +343,7 @@ QString DXLabSuiteCommanderTransceiver::command_with_reply (QString const& cmd,
if (!no_debug) if (!no_debug)
{ {
#if WSJT_TRACE_CAT TRACE_CAT (cmd << "->" << result);
qDebug () << "DXLabSuiteCommanderTransceiver:command_with_reply(" << cmd << ") ->" << result;
#endif
} }
return result; // converting raw UTF-8 bytes to QString return result; // converting raw UTF-8 bytes to QString

View File

@ -104,26 +104,18 @@ HRDTransceiver::~HRDTransceiver ()
void HRDTransceiver::do_start () void HRDTransceiver::do_start ()
{ {
#if WSJT_TRACE_CAT TRACE_CAT ("starting");
qDebug () << "HRDTransceiver::start";
#endif
wrapped_->start (); wrapped_->start ();
auto server_details = network_server_lookup (server_, 7809u); auto server_details = network_server_lookup (server_, 7809u);
if (!hrd_) if (!hrd_)
{ {
hrd_ = new QTcpSocket {this}; // QObject takes ownership hrd_ = new QTcpSocket {this}; // QObject takes ownership
} }
hrd_->connectToHost (std::get<0> (server_details), std::get<1> (server_details)); hrd_->connectToHost (std::get<0> (server_details), std::get<1> (server_details));
if (!hrd_->waitForConnected ()) if (!hrd_->waitForConnected ())
{ {
#if WSJT_TRACE_CAT TRACE_CAT ("failed to connect:" << hrd_->errorString ());
qDebug () << "HRDTransceiver::start failed to connect:" << hrd_->errorString ();
#endif
throw error {tr ("Failed to connect to Ham Radio Deluxe\n") + hrd_->errorString ()}; throw error {tr ("Failed to connect to Ham Radio Deluxe\n") + hrd_->errorString ()};
} }
@ -148,10 +140,7 @@ void HRDTransceiver::do_start ()
hrd_->connectToHost (std::get<0> (server_details), std::get<1> (server_details)); hrd_->connectToHost (std::get<0> (server_details), std::get<1> (server_details));
if (!hrd_->waitForConnected ()) if (!hrd_->waitForConnected ())
{ {
#if WSJT_TRACE_CAT TRACE_CAT ("failed to connect:" << hrd_->errorString ());
qDebug () << "HRDTransceiver::do_start failed to connect:" << hrd_->errorString ();
#endif
throw error {tr ("Failed to connect to Ham Radio Deluxe\n") + hrd_->errorString ()}; throw error {tr ("Failed to connect to Ham Radio Deluxe\n") + hrd_->errorString ()};
} }
@ -168,21 +157,14 @@ void HRDTransceiver::do_start ()
auto id = send_command ("get id", false, false); auto id = send_command ("get id", false, false);
auto version = send_command ("get version", false, false); auto version = send_command ("get version", false, false);
#if WSJT_TRACE_CAT TRACE_CAT ("Id:" << id << "Version:" << version);
qDebug () << "Id:" << id;
qDebug () << "Version:" << version;
#endif
HRD_info << "Id: " << id << "\n"; HRD_info << "Id: " << id << "\n";
HRD_info << "Version: " << version << "\n"; HRD_info << "Version: " << version << "\n";
auto radios = send_command ("get radios", false, false).trimmed ().split (',', QString::SkipEmptyParts); auto radios = send_command ("get radios", false, false).trimmed ().split (',', QString::SkipEmptyParts);
if (radios.isEmpty ()) if (radios.isEmpty ())
{ {
#if WSJT_TRACE_CAT TRACE_CAT ("no rig found");
qDebug () << "HRDTransceiver::do_start no rig found";
#endif
throw error {tr ("Ham Radio Deluxe: no rig found")}; throw error {tr ("Ham Radio Deluxe: no rig found")};
} }
@ -195,10 +177,10 @@ void HRDTransceiver::do_start ()
} }
#if WSJT_TRACE_CAT #if WSJT_TRACE_CAT
qDebug () << "radios:"; TRACE_CAT ("radios:-");
Q_FOREACH (auto const& radio, radios_) Q_FOREACH (auto const& radio, radios_)
{ {
qDebug () << "\t[" << std::get<0> (radio) << "] " << std::get<1> (radio); TRACE_CAT ("\t[" << std::get<0> (radio) << "] " << std::get<1> (radio));
} }
#endif #endif
@ -206,51 +188,36 @@ void HRDTransceiver::do_start ()
HRD_info << "Current radio: " << current_radio_name << "\n"; HRD_info << "Current radio: " << current_radio_name << "\n";
if (current_radio_name.isEmpty ()) if (current_radio_name.isEmpty ())
{ {
#if WSJT_TRACE_CAT TRACE_CAT ("no rig found");
qDebug () << "HRDTransceiver::do_start no rig found";
#endif
throw error {tr ("Ham Radio Deluxe: no rig found")}; throw error {tr ("Ham Radio Deluxe: no rig found")};
} }
vfo_count_ = send_command ("get vfo-count").toUInt (); vfo_count_ = send_command ("get vfo-count").toUInt ();
HRD_info << "VFO count: " << vfo_count_ << "\n"; HRD_info << "VFO count: " << vfo_count_ << "\n";
#if WSJT_TRACE_CAT TRACE_CAT ("vfo count:" << vfo_count_);
qDebug () << "vfo count:" << vfo_count_;
#endif
buttons_ = send_command ("get buttons").trimmed ().split (',', QString::SkipEmptyParts).replaceInStrings (" ", "~"); buttons_ = send_command ("get buttons").trimmed ().split (',', QString::SkipEmptyParts).replaceInStrings (" ", "~");
#if WSJT_TRACE_CAT TRACE_CAT ("HRD Buttons: " << buttons_);
qDebug () << "HRD Buttons: " << buttons_;
#endif
HRD_info << "Buttons: {" << buttons_.join (", ") << "}\n"; HRD_info << "Buttons: {" << buttons_.join (", ") << "}\n";
dropdown_names_ = send_command ("get dropdowns").trimmed ().split (',', QString::SkipEmptyParts); dropdown_names_ = send_command ("get dropdowns").trimmed ().split (',', QString::SkipEmptyParts);
#if WSJT_TRACE_CAT TRACE_CAT ("Dropdowns:");
qDebug () << "Dropdowns:\n";
#endif
HRD_info << "Dropdowns:\n"; HRD_info << "Dropdowns:\n";
Q_FOREACH (auto const& dd, dropdown_names_) Q_FOREACH (auto const& dd, dropdown_names_)
{ {
auto selections = send_command ("get dropdown-list {" + dd + "}").trimmed ().split (',', QString::SkipEmptyParts); auto selections = send_command ("get dropdown-list {" + dd + "}").trimmed ().split (',', QString::SkipEmptyParts);
#if WSJT_TRACE_CAT TRACE_CAT ("\t" << dd << ": {" << selections.join (", ") << "}");
qDebug () << "\t" << dd << ": {" << selections.join (", ") << "}\n";
#endif
HRD_info << "\t" << dd << ": {" << selections.join (", ") << "}\n"; HRD_info << "\t" << dd << ": {" << selections.join (", ") << "}\n";
dropdowns_[dd] = selections; dropdowns_[dd] = selections;
} }
slider_names_ = send_command ("get sliders").trimmed ().split (',', QString::SkipEmptyParts).replaceInStrings (" ", "~"); slider_names_ = send_command ("get sliders").trimmed ().split (',', QString::SkipEmptyParts).replaceInStrings (" ", "~");
#if WSJT_TRACE_CAT TRACE_CAT ("Sliders:-");
qDebug () << "Sliders:\n";
#endif
HRD_info << "Sliders:\n"; HRD_info << "Sliders:\n";
Q_FOREACH (auto const& s, slider_names_) Q_FOREACH (auto const& s, slider_names_)
{ {
auto range = send_command ("get slider-range " + current_radio_name + " " + s).trimmed ().split (',', QString::SkipEmptyParts); auto range = send_command ("get slider-range " + current_radio_name + " " + s).trimmed ().split (',', QString::SkipEmptyParts);
#if WSJT_TRACE_CAT TRACE_CAT ("\t" << s << ": {" << range.join (", ") << "}");
qDebug () << "\t" << s << ": {" << range.join (", ") << "}\n";
#endif
HRD_info << "\t" << s << ": {" << range.join (", ") << "}\n"; HRD_info << "\t" << s << ": {" << range.join (", ") << "}\n";
sliders_[s] = range; sliders_[s] = range;
} }
@ -334,10 +301,7 @@ void HRDTransceiver::do_stop ()
{ {
wrapped_->stop (); wrapped_->stop ();
} }
TRACE_CAT ("stopped" << state () << "reversed" << reversed_);
#if WSJT_TRACE_CAT
qDebug () << "HRDTransceiver::stop: state:" << state () << "reversed =" << reversed_;
#endif
} }
int HRDTransceiver::find_button (QRegExp const& re) const int HRDTransceiver::find_button (QRegExp const& re) const
@ -384,12 +348,11 @@ void HRDTransceiver::map_modes (int dropdown, ModeMap *map)
map->push_back (std::forward_as_tuple (DIG_FM, find_dropdown_selection (dropdown, QRegExp ("^(PKT-FM|PKT|FM)$")))); map->push_back (std::forward_as_tuple (DIG_FM, find_dropdown_selection (dropdown, QRegExp ("^(PKT-FM|PKT|FM)$"))));
#if WSJT_TRACE_CAT #if WSJT_TRACE_CAT
qDebug () << "HRDTransceiver::map_modes: for dropdown" << dropdown_names_[dropdown]; TRACE_CAT ("for dropdown" << dropdown_names_[dropdown]);
std::for_each (map->begin (), map->end (), [this, dropdown] (ModeMap::value_type const& item) std::for_each (map->begin (), map->end (), [this, dropdown] (ModeMap::value_type const& item)
{ {
auto const& rhs = std::get<1> (item); auto const& rhs = std::get<1> (item);
qDebug () << '\t' << std::get<0> (item) << "<->" << (rhs.size () ? dropdowns_[dropdown_names_[dropdown]][rhs.front ()] : "None"); TRACE_CAT ('\t' << std::get<0> (item) << "<->" << (rhs.size () ? dropdowns_[dropdown_names_[dropdown]][rhs.front ()] : "None"));
}); });
#endif #endif
} }
@ -452,20 +415,14 @@ void HRDTransceiver::set_dropdown (int dd, int value)
} }
else else
{ {
#if WSJT_TRACE_CAT TRACE_CAT ("item" << value << "not found in" << dd_name);
qDebug () << "HRDTransceiver::set_dropdown item" << value << "not found in" << dd_name;
#endif
throw error {tr ("Ham Radio Deluxe: item not found in %1 dropdown list").arg (dd_name)}; throw error {tr ("Ham Radio Deluxe: item not found in %1 dropdown list").arg (dd_name)};
} }
} }
void HRDTransceiver::do_ptt (bool on) void HRDTransceiver::do_ptt (bool on)
{ {
#if WSJT_TRACE_CAT TRACE_CAT (on);
qDebug () << "HRDTransceiver::do_ptt:" << on;
#endif
if (use_for_ptt_) if (use_for_ptt_)
{ {
if (ptt_button_ >= 0) if (ptt_button_ >= 0)
@ -491,25 +448,18 @@ void HRDTransceiver::set_button (int button_index, bool checked)
} }
else else
{ {
#if WSJT_TRACE_CAT TRACE_CAT ("invalid button");
qDebug () << "HRDTransceiver::set_button invalid button";
#endif
throw error {tr ("Ham Radio Deluxe: button not available")}; throw error {tr ("Ham Radio Deluxe: button not available")};
} }
} }
void HRDTransceiver::do_frequency (Frequency f, MODE m) void HRDTransceiver::do_frequency (Frequency f, MODE m)
{ {
#if WSJT_TRACE_CAT TRACE_CAT (f << "reversed" << reversed_);
qDebug () << "HRDTransceiver::do_frequency:" << f << "reversed:" << reversed_;
#endif
if (UNK != m) if (UNK != m)
{ {
do_mode (m, false); do_mode (m, false);
} }
auto fo_string = QString::number (f); auto fo_string = QString::number (f);
if (vfo_count_ > 1 && reversed_) if (vfo_count_ > 1 && reversed_)
{ {
@ -525,9 +475,7 @@ void HRDTransceiver::do_frequency (Frequency f, MODE m)
void HRDTransceiver::do_tx_frequency (Frequency tx, bool rationalise_mode) void HRDTransceiver::do_tx_frequency (Frequency tx, bool rationalise_mode)
{ {
#if WSJT_TRACE_CAT TRACE_CAT (tx << "rationalize mode:" << rationalise_mode << "reversed" << reversed_);
qDebug () << "HRDTransceiver::do_tx_frequency:" << tx << "rationalize mode:" << rationalise_mode << "reversed:" << reversed_;
#endif
// re-check if reversed VFOs // re-check if reversed VFOs
bool rx_A {true}; bool rx_A {true};
@ -683,10 +631,7 @@ void HRDTransceiver::do_tx_frequency (Frequency tx, bool rationalise_mode)
void HRDTransceiver::do_mode (MODE mode, bool rationalise) void HRDTransceiver::do_mode (MODE mode, bool rationalise)
{ {
#if WSJT_TRACE_CAT TRACE_CAT (mode);
qDebug () << "HRDTransceiver::do_mode:" << mode;
#endif
if (reversed_ && mode_B_dropdown_ >= 0) if (reversed_ && mode_B_dropdown_ >= 0)
{ {
set_dropdown (mode_B_dropdown_, lookup_mode (mode, mode_B_map_)); set_dropdown (mode_B_dropdown_, lookup_mode (mode, mode_B_map_));
@ -695,7 +640,6 @@ void HRDTransceiver::do_mode (MODE mode, bool rationalise)
{ {
set_dropdown (mode_A_dropdown_, lookup_mode (mode, mode_A_map_)); set_dropdown (mode_A_dropdown_, lookup_mode (mode, mode_A_map_));
} }
if (rationalise && state ().split ()) // rationalise mode if split if (rationalise && state ().split ()) // rationalise mode if split
{ {
if (reversed_) if (reversed_)
@ -767,7 +711,6 @@ void HRDTransceiver::do_mode (MODE mode, bool rationalise)
} }
} }
} }
update_mode (mode); update_mode (mode);
} }
@ -781,10 +724,7 @@ bool HRDTransceiver::is_button_checked (int button_index, bool no_debug)
auto reply = send_command ("get button-select " + buttons_.value (button_index), no_debug); auto reply = send_command ("get button-select " + buttons_.value (button_index), no_debug);
if ("1" != reply && "0" != reply) if ("1" != reply && "0" != reply)
{ {
#if WSJT_TRACE_CAT TRACE_CAT ("bad response");
qDebug () << "HRDTransceiver::is_button_checked bad response";
#endif
throw error {tr ("Ham Radio Deluxe didn't respond as expected")}; throw error {tr ("Ham Radio Deluxe didn't respond as expected")};
} }
return "1" == reply; return "1" == reply;
@ -794,7 +734,6 @@ void HRDTransceiver::poll ()
{ {
#if WSJT_TRACE_CAT && WSJT_TRACE_CAT_POLLS #if WSJT_TRACE_CAT && WSJT_TRACE_CAT_POLLS
bool quiet {false}; bool quiet {false};
qDebug () << "+++++++ poll dump +++++++"; qDebug () << "+++++++ poll dump +++++++";
qDebug () << "reversed:" << reversed_; qDebug () << "reversed:" << reversed_;
is_button_checked (vfo_A_button_); is_button_checked (vfo_A_button_);
@ -815,7 +754,6 @@ void HRDTransceiver::poll ()
get_dropdown (split_mode_dropdown_); get_dropdown (split_mode_dropdown_);
} }
qDebug () << "------- poll dump -------"; qDebug () << "------- poll dump -------";
#else #else
bool quiet {true}; bool quiet {true};
#endif #endif
@ -913,10 +851,7 @@ QString HRDTransceiver::send_command (QString const& cmd, bool no_debug, bool pr
}); });
if (radio_iter == radios_.end ()) if (radio_iter == radios_.end ())
{ {
#if WSJT_TRACE_CAT TRACE_CAT ("rig disappeared or changed");
qDebug () << "HRDTransceiver::send_command rig disappeared or changed";
#endif
throw error {tr ("Ham Radio Deluxe: rig has disappeared or changed")}; throw error {tr ("Ham Radio Deluxe: rig has disappeared or changed")};
} }
@ -930,10 +865,7 @@ QString HRDTransceiver::send_command (QString const& cmd, bool no_debug, bool pr
if (QTcpSocket::ConnectedState != hrd_->state ()) if (QTcpSocket::ConnectedState != hrd_->state ())
{ {
#if WSJT_TRACE_CAT TRACE_CAT (cmd << "failed" << hrd_->errorString ());
qDebug () << "HRDTransceiver::send_command" << cmd << "failed" << hrd_->errorString ();
#endif
throw error { throw error {
tr ("Ham Radio Deluxe send command \"%1\" failed %2\n") tr ("Ham Radio Deluxe send command \"%1\" failed %2\n")
.arg (cmd) .arg (cmd)
@ -946,10 +878,7 @@ QString HRDTransceiver::send_command (QString const& cmd, bool no_debug, bool pr
auto message = ((prepend_context ? context + cmd : cmd) + "\r").toLocal8Bit (); auto message = ((prepend_context ? context + cmd : cmd) + "\r").toLocal8Bit ();
if (!write_to_port (message.constData (), message.size ())) if (!write_to_port (message.constData (), message.size ()))
{ {
#if WSJT_TRACE_CAT TRACE_CAT ("failed to write command" << cmd << "to HRD");
qDebug () << "HRDTransceiver::send_command failed to write command" << cmd << "to HRD";
#endif
throw error { throw error {
tr ("Ham Radio Deluxe: failed to write command \"%1\"") tr ("Ham Radio Deluxe: failed to write command \"%1\"")
.arg (cmd) .arg (cmd)
@ -962,19 +891,14 @@ QString HRDTransceiver::send_command (QString const& cmd, bool no_debug, bool pr
QScopedPointer<HRDMessage> message {new (string) HRDMessage}; QScopedPointer<HRDMessage> message {new (string) HRDMessage};
if (!write_to_port (reinterpret_cast<char const *> (message.data ()), message->size_)) if (!write_to_port (reinterpret_cast<char const *> (message.data ()), message->size_))
{ {
#if WSJT_TRACE_CAT TRACE_CAT ("failed to write command" << cmd << "to HRD");
qDebug () << "HRDTransceiver::send_command failed to write command" << cmd << "to HRD";
#endif
throw error { throw error {
tr ("Ham Radio Deluxe: failed to write command \"%1\"") tr ("Ham Radio Deluxe: failed to write command \"%1\"")
.arg (cmd) .arg (cmd)
}; };
} }
} }
auto buffer = read_reply (cmd); auto buffer = read_reply (cmd);
if (v4 == protocol_) if (v4 == protocol_)
{ {
result = QString {buffer}.trimmed (); result = QString {buffer}.trimmed ();
@ -982,13 +906,9 @@ QString HRDTransceiver::send_command (QString const& cmd, bool no_debug, bool pr
else else
{ {
HRDMessage const * reply {new (buffer) HRDMessage}; HRDMessage const * reply {new (buffer) HRDMessage};
if (reply->magic_1_value_ != reply->magic_1_ && reply->magic_2_value_ != reply->magic_2_) if (reply->magic_1_value_ != reply->magic_1_ && reply->magic_2_value_ != reply->magic_2_)
{ {
#if WSJT_TRACE_CAT TRACE_CAT (cmd << "invalid reply");
qDebug () << "HRDTransceiver::send_command" << cmd << "invalid reply";
#endif
throw error { throw error {
tr ("Ham Radio Deluxe sent an invalid reply to our command \"%1\"") tr ("Ham Radio Deluxe sent an invalid reply to our command \"%1\"")
.arg (cmd) .arg (cmd)
@ -998,24 +918,20 @@ QString HRDTransceiver::send_command (QString const& cmd, bool no_debug, bool pr
// keep reading until expected size arrives // keep reading until expected size arrives
while (buffer.size () - offsetof (HRDMessage, size_) < reply->size_) while (buffer.size () - offsetof (HRDMessage, size_) < reply->size_)
{ {
#if WSJT_TRACE_CAT if (!no_debug)
qDebug () << "HRDTransceiver::send_command" << cmd << "reading more reply data"; {
#endif TRACE_CAT (cmd << "reading more reply data");
}
buffer += read_reply (cmd); buffer += read_reply (cmd);
reply = new (buffer) HRDMessage; reply = new (buffer) HRDMessage;
} }
result = QString {reply->payload_}; // this is not a memory leak (honest!) result = QString {reply->payload_}; // this is not a memory leak (honest!)
} }
if (!no_debug) if (!no_debug)
{ {
#if WSJT_TRACE_CAT TRACE_CAT (cmd << " ->" << result);
qDebug () << "HRDTransceiver::send_command(" << cmd << "): ->" << result;
#endif
} }
return result; return result;
} }
@ -1046,10 +962,7 @@ QByteArray HRDTransceiver::read_reply (QString const& cmd)
replied = hrd_->waitForReadyRead (); replied = hrd_->waitForReadyRead ();
if (!replied && hrd_->error () != hrd_->SocketTimeoutError) if (!replied && hrd_->error () != hrd_->SocketTimeoutError)
{ {
#if WSJT_TRACE_CAT TRACE_CAT (cmd << "failed to reply" << hrd_->errorString ());
qDebug () << "HRDTransceiver::send_command" << cmd << "failed to reply" << hrd_->errorString ();
#endif
throw error { throw error {
tr ("Ham Radio Deluxe failed to reply to command \"%1\" %2\n") tr ("Ham Radio Deluxe failed to reply to command \"%1\" %2\n")
.arg (cmd) .arg (cmd)
@ -1057,19 +970,14 @@ QByteArray HRDTransceiver::read_reply (QString const& cmd)
}; };
} }
} }
if (!replied) if (!replied)
{ {
#if WSJT_TRACE_CAT TRACE_CAT (cmd << "retries exhausted");
qDebug () << "HRDTransceiver::send_command" << cmd << "retries exhausted";
#endif
throw error { throw error {
tr ("Ham Radio Deluxe retries exhausted sending command \"%1\"") tr ("Ham Radio Deluxe retries exhausted sending command \"%1\"")
.arg (cmd) .arg (cmd)
}; };
} }
return hrd_->readAll (); return hrd_->readAll ();
} }
@ -1077,10 +985,7 @@ void HRDTransceiver::send_simple_command (QString const& command, bool no_debug)
{ {
if ("OK" != send_command (command, no_debug)) if ("OK" != send_command (command, no_debug))
{ {
#if WSJT_TRACE_CAT TRACE_CAT (command << "unexpected response");
qDebug () << "HRDTransceiver::send_simple_command" << command << "unexpected response";
#endif
throw error { throw error {
tr ("Ham Radio Deluxe didn't respond to command \"%1\" as expected") tr ("Ham Radio Deluxe didn't respond to command \"%1\" as expected")
.arg (command) .arg (command)

View File

@ -28,24 +28,25 @@ namespace
int debug_callback (enum rig_debug_level_e level, rig_ptr_t /* arg */, char const * format, va_list ap) int debug_callback (enum rig_debug_level_e level, rig_ptr_t /* arg */, char const * format, va_list ap)
{ {
QString message; QString message;
static char const fmt[] = "Hamlib: %s";
message = message.vsprintf (format, ap).trimmed (); message = message.vsprintf (format, ap).trimmed ();
switch (level) switch (level)
{ {
case RIG_DEBUG_BUG: case RIG_DEBUG_BUG:
qFatal ("%s", message.toLocal8Bit ().data ()); qFatal (fmt, message.toLocal8Bit ().data ());
break; break;
case RIG_DEBUG_ERR: case RIG_DEBUG_ERR:
qCritical ("%s", message.toLocal8Bit ().data ()); qCritical (fmt, message.toLocal8Bit ().data ());
break; break;
case RIG_DEBUG_WARN: case RIG_DEBUG_WARN:
qWarning ("%s", message.toLocal8Bit ().data ()); qWarning (fmt, message.toLocal8Bit ().data ());
break; break;
default: default:
qDebug ("%s", message.toLocal8Bit ().data ()); qDebug (fmt, message.toLocal8Bit ().data ());
break; break;
} }
@ -59,8 +60,7 @@ namespace
TransceiverFactory::Transceivers * rigs = reinterpret_cast<TransceiverFactory::Transceivers *> (callback_data); TransceiverFactory::Transceivers * rigs = reinterpret_cast<TransceiverFactory::Transceivers *> (callback_data);
QString key; QString key;
if ("Hamlib" == QString::fromLatin1 (caps->mfg_name).trimmed () if (RIG_MODEL_DUMMY == caps->rig_model)
&& "Dummy" == QString::fromLatin1 (caps->model_name).trimmed ())
{ {
key = TransceiverFactory::basic_transceiver_name_; key = TransceiverFactory::basic_transceiver_name_;
} }
@ -88,7 +88,9 @@ namespace
} }
(*rigs)[key] = TransceiverFactory::Capabilities (caps->rig_model (*rigs)[key] = TransceiverFactory::Capabilities (caps->rig_model
, port_type , port_type
, RIG_PTT_RIG == caps->ptt_type || RIG_PTT_RIG_MICDATA == caps->ptt_type , RIG_MODEL_DUMMY != caps->rig_model
&& (RIG_PTT_RIG == caps->ptt_type
|| RIG_PTT_RIG_MICDATA == caps->ptt_type)
, RIG_PTT_RIG_MICDATA == caps->ptt_type); , RIG_PTT_RIG_MICDATA == caps->ptt_type);
return 1; // keep them coming return 1; // keep them coming
@ -126,6 +128,9 @@ namespace
}; };
} }
freq_t HamlibTransceiver::dummy_frequency_;
rmode_t HamlibTransceiver::dummy_mode_ {RIG_MODE_NONE};
void HamlibTransceiver::register_transceivers (TransceiverFactory::Transceivers * registry) void HamlibTransceiver::register_transceivers (TransceiverFactory::Transceivers * registry)
{ {
rig_set_debug_callback (debug_callback, nullptr); rig_set_debug_callback (debug_callback, nullptr);
@ -155,22 +160,11 @@ void HamlibTransceiver::RIGDeleter::cleanup (RIG * rig)
} }
} }
HamlibTransceiver::HamlibTransceiver (int model_number HamlibTransceiver::HamlibTransceiver (TransceiverFactory::PTTMethod ptt_type, QString const& ptt_port)
, QString const& cat_port : PollingTransceiver {0}
, int cat_baud , rig_ {rig_init (RIG_MODEL_DUMMY)}
, TransceiverFactory::DataBits cat_data_bits , back_ptt_port_ {false}
, TransceiverFactory::StopBits cat_stop_bits , is_dummy_ {true}
, TransceiverFactory::Handshake cat_handshake
, TransceiverFactory::LineControl cat_dtr_control
, TransceiverFactory::LineControl cat_rts_control
, TransceiverFactory::PTTMethod ptt_type
, TransceiverFactory::TXAudioSource back_ptt_port
, QString const& ptt_port
, int poll_interval)
: PollingTransceiver {poll_interval}
, rig_ {rig_init (model_number)}
, back_ptt_port_ {TransceiverFactory::TX_audio_source_rear == back_ptt_port}
, is_dummy_ {RIG_MODEL_DUMMY == model_number}
, reversed_ {false} , reversed_ {false}
, split_query_works_ {true} , split_query_works_ {true}
, get_vfo_works_ {true} , get_vfo_works_ {true}
@ -180,34 +174,6 @@ HamlibTransceiver::HamlibTransceiver (int model_number
throw error {tr ("Hamlib initialisation error")}; throw error {tr ("Hamlib initialisation error")};
} }
// rig_->state.obj = this;
if (!cat_port.isEmpty ())
{
set_conf ("rig_pathname", cat_port.toLatin1 ().data ());
}
set_conf ("serial_speed", QByteArray::number (cat_baud).data ());
set_conf ("data_bits", TransceiverFactory::seven_data_bits == cat_data_bits ? "7" : "8");
set_conf ("stop_bits", TransceiverFactory::one_stop_bit == cat_stop_bits ? "1" : "2");
switch (cat_handshake)
{
case TransceiverFactory::handshake_none: set_conf ("serial_handshake", "None"); break;
case TransceiverFactory::handshake_XonXoff: set_conf ("serial_handshake", "XONXOFF"); break;
case TransceiverFactory::handshake_hardware: set_conf ("serial_handshake", "Hardware"); break;
}
if (TransceiverFactory::no_control != cat_dtr_control)
{
set_conf ("dtr_state", TransceiverFactory::force_high == cat_dtr_control ? "ON" : "OFF");
}
if (TransceiverFactory::handshake_hardware != cat_handshake
&& TransceiverFactory::no_control != cat_rts_control)
{
set_conf ("rts_state", TransceiverFactory::force_high == cat_rts_control ? "ON" : "OFF");
}
switch (ptt_type) switch (ptt_type)
{ {
case TransceiverFactory::PTT_method_VOX: case TransceiverFactory::PTT_method_VOX:
@ -221,7 +187,7 @@ HamlibTransceiver::HamlibTransceiver (int model_number
case TransceiverFactory::PTT_method_DTR: case TransceiverFactory::PTT_method_DTR:
case TransceiverFactory::PTT_method_RTS: case TransceiverFactory::PTT_method_RTS:
if (!ptt_port.isEmpty () && ptt_port != "None" && ptt_port != cat_port) if (!ptt_port.isEmpty ())
{ {
#if defined (WIN32) #if defined (WIN32)
set_conf ("ptt_pathname", ("\\\\.\\" + ptt_port).toLatin1 ().data ()); set_conf ("ptt_pathname", ("\\\\.\\" + ptt_port).toLatin1 ().data ());
@ -239,6 +205,100 @@ HamlibTransceiver::HamlibTransceiver (int model_number
set_conf ("ptt_type", "RTS"); set_conf ("ptt_type", "RTS");
} }
} }
}
HamlibTransceiver::HamlibTransceiver (int model_number, TransceiverFactory::ParameterPack const& params)
: PollingTransceiver {params.poll_interval}
, rig_ {rig_init (model_number)}
, back_ptt_port_ {TransceiverFactory::TX_audio_source_rear == params.audio_source}
, is_dummy_ {RIG_MODEL_DUMMY == model_number}
, reversed_ {false}
, split_query_works_ {true}
, tickle_hamlib_ {false}
, get_vfo_works_ {true}
{
if (!rig_)
{
throw error {tr ("Hamlib initialisation error")};
}
// rig_->state.obj = this;
if (RIG_MODEL_DUMMY != model_number)
{
switch (rig_->caps->port_type)
{
case RIG_PORT_SERIAL:
if (!params.serial_port.isEmpty ())
{
set_conf ("rig_pathname", params.serial_port.toLatin1 ().data ());
}
break;
case RIG_PORT_NETWORK:
if (!params.network_port.isEmpty ())
{
set_conf ("rig_pathname", params.network_port.toLatin1 ().data ());
}
break;
default:
throw error {tr ("Unsupported CAT type")};
break;
}
set_conf ("serial_speed", QByteArray::number (params.baud).data ());
set_conf ("data_bits", TransceiverFactory::seven_data_bits == params.data_bits ? "7" : "8");
set_conf ("stop_bits", TransceiverFactory::one_stop_bit == params.stop_bits ? "1" : "2");
switch (params.handshake)
{
case TransceiverFactory::handshake_none: set_conf ("serial_handshake", "None"); break;
case TransceiverFactory::handshake_XonXoff: set_conf ("serial_handshake", "XONXOFF"); break;
case TransceiverFactory::handshake_hardware: set_conf ("serial_handshake", "Hardware"); break;
}
if (params.force_line_control)
{
set_conf ("dtr_state", params.dtr_high ? "ON" : "OFF");
set_conf ("rts_state", params.rts_high ? "ON" : "OFF");
}
}
switch (params.ptt_type)
{
case TransceiverFactory::PTT_method_VOX:
set_conf ("ptt_type", "None");
break;
case TransceiverFactory::PTT_method_CAT:
// Use the default PTT_TYPE for the rig (defined in the Hamlib
// rig back-end capabilities).
break;
case TransceiverFactory::PTT_method_DTR:
case TransceiverFactory::PTT_method_RTS:
if (!params.ptt_port.isEmpty ()
&& params.ptt_port != "None"
&& (RIG_MODEL_DUMMY == model_number
|| params.ptt_port != params.serial_port))
{
#if defined (WIN32)
set_conf ("ptt_pathname", ("\\\\.\\" + params.ptt_port).toLatin1 ().data ());
#else
set_conf ("ptt_pathname", params.ptt_port.toLatin1 ().data ());
#endif
}
if (TransceiverFactory::PTT_method_DTR == params.ptt_type)
{
set_conf ("ptt_type", "DTR");
}
else
{
set_conf ("ptt_type", "RTS");
}
}
// Make Icom CAT split commands less glitchy // Make Icom CAT split commands less glitchy
set_conf ("no_xchg", "1"); set_conf ("no_xchg", "1");
@ -255,20 +315,14 @@ void HamlibTransceiver::error_check (int ret_code, QString const& doing) const
{ {
if (RIG_OK != ret_code) if (RIG_OK != ret_code)
{ {
#if WSJT_TRACE_CAT && WSJT_TRACE_CAT_POLLS TRACE_CAT_POLL ("error:" << rigerror (ret_code));
qDebug () << "HamlibTransceiver::error_check: error:" << rigerror (ret_code);
#endif
throw error {tr ("Hamlib error: %1 while %2").arg (rigerror (ret_code)).arg (doing)}; throw error {tr ("Hamlib error: %1 while %2").arg (rigerror (ret_code)).arg (doing)};
} }
} }
void HamlibTransceiver::do_start () void HamlibTransceiver::do_start ()
{ {
#if WSJT_TRACE_CAT TRACE_CAT (QString::fromLatin1 (rig_->caps->mfg_name).trimmed () << QString::fromLatin1 (rig_->caps->model_name).trimmed ());
qDebug () << "HamlibTransceiver::do_start rig:" << QString::fromLatin1 (rig_->caps->mfg_name).trimmed () + ' '
+ QString::fromLatin1 (rig_->caps->model_name).trimmed ();
#endif
error_check (rig_open (rig_.data ()), tr ("opening connection to rig")); error_check (rig_open (rig_.data ()), tr ("opening connection to rig"));
@ -286,7 +340,7 @@ void HamlibTransceiver::do_start ()
} }
if (!is_dummy_ && rig_->caps->set_split_vfo) // if split is possible if (!is_dummy_ && rig_->caps->set_split_vfo) // if split is possible
// do some extra setup // do some extra setup
{ {
freq_t f1; freq_t f1;
freq_t f2; freq_t f2;
@ -301,67 +355,39 @@ void HamlibTransceiver::do_start ()
// VFO is selected or if SPLIT is selected so we have to simply // VFO is selected or if SPLIT is selected so we have to simply
// assume it is as when we started by setting at open time right // assume it is as when we started by setting at open time right
// here. We also gather/set other initial state. // here. We also gather/set other initial state.
#if WSJT_TRACE_CAT
qDebug () << "HamlibTransceiver::init_rig rig_get_freq";
#endif
error_check (rig_get_freq (rig_.data (), RIG_VFO_CURR, &f1), tr ("getting current frequency")); error_check (rig_get_freq (rig_.data (), RIG_VFO_CURR, &f1), tr ("getting current frequency"));
#if WSJT_TRACE_CAT TRACE_CAT ("current frequency =" << f1);
qDebug () << "HamlibTransceiver::init_rig rig_get_freq current frequency =" << f1;
#endif
#if WSJT_TRACE_CAT
qDebug () << "HamlibTransceiver::init_rig rig_get_mode current mode";
#endif
error_check (rig_get_mode (rig_.data (), RIG_VFO_CURR, &m, &w), tr ("getting current mode")); error_check (rig_get_mode (rig_.data (), RIG_VFO_CURR, &m, &w), tr ("getting current mode"));
#if WSJT_TRACE_CAT TRACE_CAT ("current mode =" << rig_strrmode (m) << "bw =" << w);
qDebug () << "HamlibTransceiver::init_rig rig_get_mode current mode =" << rig_strrmode (m) << "bw =" << w;
#endif
if (!rig_->caps->set_vfo) if (!rig_->caps->set_vfo)
{ {
#if WSJT_TRACE_CAT TRACE_CAT ("rig_vfo_op TOGGLE");
qDebug () << "HamlibTransceiver::init_rig rig_vfo_op TOGGLE";
#endif
error_check (rig_vfo_op (rig_.data (), RIG_VFO_CURR, RIG_OP_TOGGLE), tr ("exchanging VFOs")); error_check (rig_vfo_op (rig_.data (), RIG_VFO_CURR, RIG_OP_TOGGLE), tr ("exchanging VFOs"));
} }
else else
{ {
#if WSJT_TRACE_CAT TRACE_CAT ("rig_set_vfo to other VFO");
qDebug () << "HamlibTransceiver::init_rig rig_set_vfo to other VFO";
#endif
error_check (rig_set_vfo (rig_.data (), rig_->state.vfo_list & RIG_VFO_B ? RIG_VFO_B : RIG_VFO_SUB), tr ("setting current VFO")); error_check (rig_set_vfo (rig_.data (), rig_->state.vfo_list & RIG_VFO_B ? RIG_VFO_B : RIG_VFO_SUB), tr ("setting current VFO"));
} }
#if WSJT_TRACE_CAT
qDebug () << "HamlibTransceiver::init_rig rig_get_freq other frequency";
#endif
error_check (rig_get_freq (rig_.data (), RIG_VFO_CURR, &f2), tr ("getting other VFO frequency")); error_check (rig_get_freq (rig_.data (), RIG_VFO_CURR, &f2), tr ("getting other VFO frequency"));
#if WSJT_TRACE_CAT TRACE_CAT ("rig_get_freq other frequency =" << f2);
qDebug () << "HamlibTransceiver::init_rig rig_get_freq other frequency =" << f2;
#endif
#if WSJT_TRACE_CAT
qDebug () << "HamlibTransceiver::init_rig rig_get_mode other VFO";
#endif
error_check (rig_get_mode (rig_.data (), RIG_VFO_CURR, &mb, &wb), tr ("getting other VFO mode")); error_check (rig_get_mode (rig_.data (), RIG_VFO_CURR, &mb, &wb), tr ("getting other VFO mode"));
#if WSJT_TRACE_CAT TRACE_CAT ("rig_get_mode other mode =" << rig_strrmode (mb) << "bw =" << wb);
qDebug () << "HamlibTransceiver::init_rig rig_get_mode other mode =" << rig_strrmode (mb) << "bw =" << wb;
#endif
update_other_frequency (f2); update_other_frequency (f2);
if (!rig_->caps->set_vfo) if (!rig_->caps->set_vfo)
{ {
#if WSJT_TRACE_CAT TRACE_CAT ("rig_vfo_op TOGGLE");
qDebug () << "HamlibTransceiver::init_rig rig_vfo_op TOGGLE";
#endif
error_check (rig_vfo_op (rig_.data (), RIG_VFO_CURR, RIG_OP_TOGGLE), tr ("exchanging VFOs")); error_check (rig_vfo_op (rig_.data (), RIG_VFO_CURR, RIG_OP_TOGGLE), tr ("exchanging VFOs"));
} }
else else
{ {
#if WSJT_TRACE_CAT TRACE_CAT ("rig_set_vfo A/MAIN");
qDebug () << "HamlibTransceiver::init_rig rig_set_vfo A/MAIN";
#endif
error_check (rig_set_vfo (rig_.data (), rig_->state.vfo_list & RIG_VFO_A ? RIG_VFO_A : RIG_VFO_MAIN), tr ("setting current VFO")); error_check (rig_set_vfo (rig_.data (), rig_->state.vfo_list & RIG_VFO_A ? RIG_VFO_A : RIG_VFO_MAIN), tr ("setting current VFO"));
} }
@ -371,28 +397,16 @@ void HamlibTransceiver::do_start ()
} }
else else
{ {
#if WSJT_TRACE_CAT
qDebug () << "HamlibTransceiver::init_rig rig_get_freq";
#endif
error_check (rig_get_freq (rig_.data (), RIG_VFO_CURR, &f1), tr ("getting frequency")); error_check (rig_get_freq (rig_.data (), RIG_VFO_CURR, &f1), tr ("getting frequency"));
#if WSJT_TRACE_CAT TRACE_CAT ("rig_get_freq frequency =" << f1);
qDebug () << "HamlibTransceiver::init_rig rig_get_freq frequency =" << f1;
#endif
#if WSJT_TRACE_CAT
qDebug () << "HamlibTransceiver::init_rig rig_get_mode";
#endif
error_check (rig_get_mode (rig_.data (), RIG_VFO_CURR, &m, &w), tr ("getting mode")); error_check (rig_get_mode (rig_.data (), RIG_VFO_CURR, &m, &w), tr ("getting mode"));
#if WSJT_TRACE_CAT TRACE_CAT ("rig_get_mode mode =" << rig_strrmode (m) << "bw =" << w);
qDebug () << "HamlibTransceiver::init_rig rig_get_mode mode =" << rig_strrmode (m) << "bw =" << w;
#endif
update_rx_frequency (f1); update_rx_frequency (f1);
} }
#if WSJT_TRACE_CAT // TRACE_CAT ("rig_set_split_vfo split off");
// qDebug () << "HamlibTransceiver::init_rig rig_set_split_vfo split off";
#endif
// error_check (rig_set_split_vfo (rig_.data (), RIG_VFO_CURR, RIG_SPLIT_OFF, RIG_VFO_CURR), tr ("setting split off")); // error_check (rig_set_split_vfo (rig_.data (), RIG_VFO_CURR, RIG_SPLIT_OFF, RIG_VFO_CURR), tr ("setting split off"));
// update_split (false); // update_split (false);
} }
@ -402,26 +416,16 @@ void HamlibTransceiver::do_start ()
if (get_vfo_works_ && rig_->caps->get_vfo) if (get_vfo_works_ && rig_->caps->get_vfo)
{ {
#if WSJT_TRACE_CAT
qDebug () << "HamlibTransceiver::init_rig rig_get_vfo current VFO";
#endif
error_check (rig_get_vfo (rig_.data (), &v), tr ("getting current VFO")); // has side effect of establishing current VFO inside hamlib error_check (rig_get_vfo (rig_.data (), &v), tr ("getting current VFO")); // has side effect of establishing current VFO inside hamlib
#if WSJT_TRACE_CAT TRACE_CAT ("rig_get_vfo current VFO = " << rig_strvfo (v));
qDebug () << "HamlibTransceiver::init_rig rig_get_vfo current VFO = " << rig_strvfo (v);
#endif
} }
reversed_ = RIG_VFO_B == v; reversed_ = RIG_VFO_B == v;
if (!(rig_->caps->targetable_vfo & (RIG_TARGETABLE_MODE | RIG_TARGETABLE_PURE))) if (!(rig_->caps->targetable_vfo & (RIG_TARGETABLE_MODE | RIG_TARGETABLE_PURE)))
{ {
#if WSJT_TRACE_CAT
qDebug () << "HamlibTransceiver::init_rig rig_get_mode current mode";
#endif
error_check (rig_get_mode (rig_.data (), RIG_VFO_CURR, &m, &w), tr ("getting current mode")); error_check (rig_get_mode (rig_.data (), RIG_VFO_CURR, &m, &w), tr ("getting current mode"));
#if WSJT_TRACE_CAT TRACE_CAT ("rig_get_mode current mode =" << rig_strrmode (m) << "bw =" << w);
qDebug () << "HamlibTransceiver::init_rig rig_get_mode current mode =" << rig_strrmode (m) << "bw =" << w;
#endif
} }
} }
update_mode (map_mode (m)); update_mode (map_mode (m));
@ -429,23 +433,38 @@ void HamlibTransceiver::do_start ()
tickle_hamlib_ = true; tickle_hamlib_ = true;
if (is_dummy_ && dummy_frequency_)
{
// return to where last dummy instance was
// TODO: this is going to break down if multiple dummy rigs are used
rig_set_freq (rig_.data (), RIG_VFO_CURR, dummy_frequency_);
update_rx_frequency (dummy_frequency_);
if (RIG_MODE_NONE != dummy_mode_)
{
rig_set_mode (rig_.data (), RIG_VFO_CURR, dummy_mode_, RIG_PASSBAND_NORMAL);
update_mode (map_mode (dummy_mode_));
}
}
poll (); poll ();
#if WSJT_TRACE_CAT TRACE_CAT ("exit" << state () << "reversed =" << reversed_);
qDebug () << "HamlibTransceiver::init_rig exit" << state () << "reversed =" << reversed_;
#endif
} }
void HamlibTransceiver::do_stop () void HamlibTransceiver::do_stop ()
{ {
if (is_dummy_)
{
rig_get_freq (rig_.data (), RIG_VFO_CURR, &dummy_frequency_);
pbwidth_t width;
rig_get_mode (rig_.data (), RIG_VFO_CURR, &dummy_mode_, &width);
}
if (rig_) if (rig_)
{ {
rig_close (rig_.data ()); rig_close (rig_.data ());
} }
#if WSJT_TRACE_CAT TRACE_CAT ("state:" << state () << "reversed =" << reversed_);
qDebug () << "HamlibTransceiver::do_stop: state:" << state () << "reversed =" << reversed_;
#endif
} }
auto HamlibTransceiver::get_vfos () const -> std::tuple<vfo_t, vfo_t> auto HamlibTransceiver::get_vfos () const -> std::tuple<vfo_t, vfo_t>
@ -453,13 +472,8 @@ auto HamlibTransceiver::get_vfos () const -> std::tuple<vfo_t, vfo_t>
if (get_vfo_works_ && rig_->caps->get_vfo) if (get_vfo_works_ && rig_->caps->get_vfo)
{ {
vfo_t v; vfo_t v;
#if WSJT_TRACE_CAT
qDebug () << "HamlibTransceiver::get_vfos rig_get_vfo";
#endif
error_check (rig_get_vfo (rig_.data (), &v), tr ("getting current VFO")); // has side effect of establishing current VFO inside hamlib error_check (rig_get_vfo (rig_.data (), &v), tr ("getting current VFO")); // has side effect of establishing current VFO inside hamlib
#if WSJT_TRACE_CAT TRACE_CAT ("rig_get_vfo VFO = " << rig_strvfo (v));
qDebug () << "HamlibTransceiver::get_vfos rig_get_vfo VFO = " << rig_strvfo (v);
#endif
reversed_ = RIG_VFO_B == v; reversed_ = RIG_VFO_B == v;
} }
@ -469,57 +483,41 @@ auto HamlibTransceiver::get_vfos () const -> std::tuple<vfo_t, vfo_t>
// frequency if split since these type of radios can only // frequency if split since these type of radios can only
// support this way around // support this way around
#if WSJT_TRACE_CAT TRACE_CAT ("rig_set_vfo VFO = A/MAIN");
qDebug () << "HamlibTransceiver::get_vfos rig_set_vfo VFO = A/MAIN";
#endif
error_check (rig_set_vfo (rig_.data (), rig_->state.vfo_list & RIG_VFO_A ? RIG_VFO_A : RIG_VFO_MAIN), tr ("setting current VFO")); error_check (rig_set_vfo (rig_.data (), rig_->state.vfo_list & RIG_VFO_A ? RIG_VFO_A : RIG_VFO_MAIN), tr ("setting current VFO"));
} }
// else only toggle available but both VFOs should be substitutable // else only toggle available but both VFOs should be substitutable
auto rx_vfo = rig_->state.vfo_list & RIG_VFO_A ? RIG_VFO_A : RIG_VFO_MAIN; auto rx_vfo = rig_->state.vfo_list & RIG_VFO_A ? RIG_VFO_A : RIG_VFO_MAIN;
auto tx_vfo = state ().split () ? (rig_->state.vfo_list & RIG_VFO_B ? RIG_VFO_B : RIG_VFO_SUB) : rx_vfo; auto tx_vfo = !is_dummy_ && state ().split ()
? (rig_->state.vfo_list & RIG_VFO_B ? RIG_VFO_B : RIG_VFO_SUB)
: rx_vfo;
if (reversed_) if (reversed_)
{ {
#if WSJT_TRACE_CAT TRACE_CAT ("reversing VFOs");
qDebug () << "HamlibTransceiver::get_vfos reversing VFOs";
#endif
std::swap (rx_vfo, tx_vfo); std::swap (rx_vfo, tx_vfo);
} }
#if WSJT_TRACE_CAT TRACE_CAT ("RX VFO = " << rig_strvfo (rx_vfo) << " TX VFO = " << rig_strvfo (tx_vfo));
qDebug () << "HamlibTransceiver::get_vfos RX VFO = " << rig_strvfo (rx_vfo) << " TX VFO = " << rig_strvfo (tx_vfo);
#endif
return std::make_tuple (rx_vfo, tx_vfo); return std::make_tuple (rx_vfo, tx_vfo);
} }
void HamlibTransceiver::do_frequency (Frequency f, MODE m) void HamlibTransceiver::do_frequency (Frequency f, MODE m)
{ {
#if WSJT_TRACE_CAT TRACE_CAT (f << "mode:" << m << "reversed:" << reversed_);
qDebug () << "HamlibTransceiver::do_frequency:" << f << "mode:" << m << "reversed:" << reversed_;
#endif
if (!is_dummy_) // for the 1st time as a band change may cause a recalled mode to be
{ // set
// for the 1st time as a band change may cause a recalled mode error_check (rig_set_freq (rig_.data (), RIG_VFO_CURR, f), tr ("setting frequency"));
// to be set
error_check (rig_set_freq (rig_.data (), RIG_VFO_CURR, f), tr ("setting frequency"));
}
if (UNK != m) if (UNK != m)
{ {
do_mode (m, false); do_mode (m, false);
}
if (!is_dummy_)
{
// for the 2nd time because a mode change may have caused a // for the 2nd time because a mode change may have caused a
// frequency change // frequency change
error_check (rig_set_freq (rig_.data (), RIG_VFO_CURR, f), tr ("setting frequency")); error_check (rig_set_freq (rig_.data (), RIG_VFO_CURR, f), tr ("setting frequency"));
}
if (UNK != m)
{
// for the second time because some rigs change mode according // for the second time because some rigs change mode according
// to frequency such as the TS-2000 auto mode setting // to frequency such as the TS-2000 auto mode setting
do_mode (m, false); do_mode (m, false);
@ -530,11 +528,10 @@ void HamlibTransceiver::do_frequency (Frequency f, MODE m)
void HamlibTransceiver::do_tx_frequency (Frequency tx, bool rationalise_mode) void HamlibTransceiver::do_tx_frequency (Frequency tx, bool rationalise_mode)
{ {
#if WSJT_TRACE_CAT TRACE_CAT (tx << "rationalise mode:" << rationalise_mode << "reversed:" << reversed_);
qDebug () << "HamlibTransceiver::do_tx_frequency:" << tx << "rationalise mode:" << rationalise_mode << "reversed:" << reversed_;
#endif
if (!is_dummy_) if (!is_dummy_) // split is meaning less if you can't
// see it
{ {
auto split = tx ? RIG_SPLIT_ON : RIG_SPLIT_OFF; auto split = tx ? RIG_SPLIT_ON : RIG_SPLIT_OFF;
update_split (tx); update_split (tx);
@ -557,9 +554,7 @@ void HamlibTransceiver::do_tx_frequency (Frequency tx, bool rationalise_mode)
// much we can do since the Hamlib Library needs this // much we can do since the Hamlib Library needs this
// call at least once to establish the Tx VFO. Best we // call at least once to establish the Tx VFO. Best we
// can do is only do this once per session. // can do is only do this once per session.
#if WSJT_TRACE_CAT TRACE_CAT ("rig_set_split_vfo split =" << split);
qDebug () << "HamlibTransceiver::do_tx_frequency rig_set_split_vfo split =" << split;
#endif
auto rc = rig_set_split_vfo (rig_.data (), RIG_VFO_CURR, split, tx_vfo); auto rc = rig_set_split_vfo (rig_.data (), RIG_VFO_CURR, split, tx_vfo);
if (tx || (-RIG_ENAVAIL != rc && -RIG_ENIMPL != rc)) if (tx || (-RIG_ENAVAIL != rc && -RIG_ENIMPL != rc))
{ {
@ -575,12 +570,7 @@ void HamlibTransceiver::do_tx_frequency (Frequency tx, bool rationalise_mode)
tickle_hamlib_ = false; tickle_hamlib_ = false;
} }
#if WSJT_TRACE_CAT
qDebug () << "HamlibTransceiver::do_tx_frequency rig_set_split_freq";
#endif
hamlib_tx_vfo_fixup fixup (rig_.data (), tx_vfo); hamlib_tx_vfo_fixup fixup (rig_.data (), tx_vfo);
// do this before setting the mode because changing band may // do this before setting the mode because changing band may
// recall the last mode used on the target band // recall the last mode used on the target band
error_check (rig_set_split_freq (rig_.data (), RIG_VFO_CURR, tx), tr ("setting split TX frequency")); error_check (rig_set_split_freq (rig_.data (), RIG_VFO_CURR, tx), tr ("setting split TX frequency"));
@ -590,20 +580,13 @@ void HamlibTransceiver::do_tx_frequency (Frequency tx, bool rationalise_mode)
rmode_t current_mode; rmode_t current_mode;
pbwidth_t current_width; pbwidth_t current_width;
#if WSJT_TRACE_CAT
qDebug () << "HamlibTransceiver::do_tx_frequency rig_get_split_mode";
#endif
error_check (rig_get_split_mode (rig_.data (), RIG_VFO_CURR, &current_mode, &current_width), tr ("getting mode of split TX VFO")); error_check (rig_get_split_mode (rig_.data (), RIG_VFO_CURR, &current_mode, &current_width), tr ("getting mode of split TX VFO"));
#if WSJT_TRACE_CAT TRACE_CAT ("rig_get_split_mode mode = " << rig_strrmode (current_mode) << "bw =" << current_width);
qDebug () << "HamlibTransceiver::do_tx_frequency rig_get_split_mode mode = " << rig_strrmode (current_mode) << "bw =" << current_width;
#endif
auto new_mode = map_mode (state ().mode ()); auto new_mode = map_mode (state ().mode ());
if (new_mode != current_mode) if (new_mode != current_mode)
{ {
#if WSJT_TRACE_CAT TRACE_CAT ("rig_set_split_mode mode = " << rig_strrmode (new_mode));
qDebug () << "HamlibTransceiver::do_tx_frequency rig_set_split_mode mode = " << rig_strrmode (new_mode);
#endif
error_check (rig_set_split_mode (rig_.data (), RIG_VFO_CURR, new_mode, RIG_PASSBAND_NORMAL), tr ("setting split TX VFO mode")); error_check (rig_set_split_mode (rig_.data (), RIG_VFO_CURR, new_mode, RIG_PASSBAND_NORMAL), tr ("setting split TX VFO mode"));
// do this again as setting the mode may change the frequency // do this again as setting the mode may change the frequency
@ -616,9 +599,7 @@ void HamlibTransceiver::do_tx_frequency (Frequency tx, bool rationalise_mode)
// of split when you switch RX VFO (to set split mode above for // of split when you switch RX VFO (to set split mode above for
// example). Also the Elecraft K3 will refuse to go to split // example). Also the Elecraft K3 will refuse to go to split
// with certain VFO A/B mode combinations. // with certain VFO A/B mode combinations.
#if WSJT_TRACE_CAT TRACE_CAT ("rig_set_split_vfo split =" << split);
qDebug () << "HamlibTransceiver::do_tx_frequency rig_set_split_vfo split =" << split;
#endif
auto rc = rig_set_split_vfo (rig_.data (), RIG_VFO_CURR, split, tx_vfo); auto rc = rig_set_split_vfo (rig_.data (), RIG_VFO_CURR, split, tx_vfo);
if (tx || (-RIG_ENAVAIL != rc && -RIG_ENIMPL != rc)) if (tx || (-RIG_ENAVAIL != rc && -RIG_ENIMPL != rc))
{ {
@ -630,209 +611,136 @@ void HamlibTransceiver::do_tx_frequency (Frequency tx, bool rationalise_mode)
// specific rig. // specific rig.
error_check (rc, tr ("setting/unsetting split mode")); error_check (rc, tr ("setting/unsetting split mode"));
} }
}
update_other_frequency (tx); update_other_frequency (tx);
}
} }
void HamlibTransceiver::do_mode (MODE mode, bool rationalise) void HamlibTransceiver::do_mode (MODE mode, bool rationalise)
{ {
#if WSJT_TRACE_CAT TRACE_CAT (mode << "rationalise:" << rationalise);
qDebug () << "HamlibTransceiver::do_mode:" << mode << "rationalise:" << rationalise;
#endif
if (!is_dummy_) auto vfos = get_vfos ();
// auto rx_vfo = std::get<0> (vfos);
auto tx_vfo = std::get<1> (vfos);
rmode_t current_mode;
pbwidth_t current_width;
error_check (rig_get_mode (rig_.data (), RIG_VFO_CURR, &current_mode, &current_width), tr ("getting current VFO mode"));
TRACE_CAT ("rig_get_mode mode = " << rig_strrmode (current_mode) << "bw =" << current_width);
auto new_mode = map_mode (mode);
if (new_mode != current_mode)
{ {
auto vfos = get_vfos (); TRACE_CAT ("rig_set_mode mode = " << rig_strrmode (new_mode));
// auto rx_vfo = std::get<0> (vfos); error_check (rig_set_mode (rig_.data (), RIG_VFO_CURR, new_mode, RIG_PASSBAND_NORMAL), tr ("setting current VFO mode"));
auto tx_vfo = std::get<1> (vfos); }
if (!is_dummy_ && state ().split () && rationalise)
{
error_check (rig_get_split_mode (rig_.data (), RIG_VFO_CURR, &current_mode, &current_width), tr ("getting split TX VFO mode"));
TRACE_CAT ("rig_get_split_mode mode = " << rig_strrmode (current_mode) << "bw =" << current_width);
rmode_t current_mode;
pbwidth_t current_width;
#if WSJT_TRACE_CAT
qDebug () << "HamlibTransceiver::do_mode rig_get_mode";
#endif
error_check (rig_get_mode (rig_.data (), RIG_VFO_CURR, &current_mode, &current_width), tr ("getting current VFO mode"));
#if WSJT_TRACE_CAT
qDebug () << "HamlibTransceiver::do_mode rig_get_mode mode = " << rig_strrmode (current_mode) << "bw =" << current_width;
#endif
auto new_mode = map_mode (mode);
if (new_mode != current_mode) if (new_mode != current_mode)
{ {
#if WSJT_TRACE_CAT TRACE_CAT ("rig_set_split_mode mode = " << rig_strrmode (new_mode));
qDebug () << "HamlibTransceiver::do_mode rig_set_mode mode = " << rig_strrmode (new_mode); hamlib_tx_vfo_fixup fixup (rig_.data (), tx_vfo);
#endif error_check (rig_set_split_mode (rig_.data (), RIG_VFO_CURR, new_mode, RIG_PASSBAND_NORMAL), tr ("setting split TX VFO mode"));
error_check (rig_set_mode (rig_.data (), RIG_VFO_CURR, new_mode, RIG_PASSBAND_NORMAL), tr ("setting current VFO mode"));
}
if (state ().split () && rationalise)
{
#if WSJT_TRACE_CAT
qDebug () << "HamlibTransceiver::do_mode rig_get_split_mode";
#endif
error_check (rig_get_split_mode (rig_.data (), RIG_VFO_CURR, &current_mode, &current_width), tr ("getting split TX VFO mode"));
#if WSJT_TRACE_CAT
qDebug () << "HamlibTransceiver::do_mode rig_get_split_mode mode = " << rig_strrmode (current_mode) << "bw =" << current_width;
#endif
if (new_mode != current_mode)
{
#if WSJT_TRACE_CAT
qDebug () << "HamlibTransceiver::do_mode rig_set_split_mode mode = " << rig_strrmode (new_mode);
#endif
hamlib_tx_vfo_fixup fixup (rig_.data (), tx_vfo);
error_check (rig_set_split_mode (rig_.data (), RIG_VFO_CURR, new_mode, RIG_PASSBAND_NORMAL), tr ("setting split TX VFO mode"));
}
} }
} }
update_mode (mode); update_mode (mode);
} }
void HamlibTransceiver::poll () void HamlibTransceiver::poll ()
{ {
if (is_dummy_)
{
// split with dummy is never reported since there is no rig
if (state ().split ())
{
update_split (false);
}
}
else
{
#if !WSJT_TRACE_CAT_POLLS #if !WSJT_TRACE_CAT_POLLS
#if defined (NDEBUG) #if defined (NDEBUG)
rig_set_debug (RIG_DEBUG_ERR); rig_set_debug (RIG_DEBUG_ERR);
#else #else
rig_set_debug (RIG_DEBUG_WARN); rig_set_debug (RIG_DEBUG_WARN);
#endif #endif
#endif #endif
freq_t f; freq_t f;
rmode_t m; rmode_t m;
pbwidth_t w; pbwidth_t w;
split_t s; split_t s;
if (get_vfo_works_ && rig_->caps->get_vfo) if (get_vfo_works_ && rig_->caps->get_vfo)
{
vfo_t v;
error_check (rig_get_vfo (rig_.data (), &v), tr ("getting current VFO")); // has side effect of establishing current VFO inside hamlib
TRACE_CAT_POLL ("VFO =" << rig_strvfo (v));
reversed_ = RIG_VFO_B == v;
}
error_check (rig_get_freq (rig_.data (), RIG_VFO_CURR, &f), tr ("getting current VFO frequency"));
TRACE_CAT_POLL ("rig_get_freq frequency =" << f);
update_rx_frequency (f);
if (!is_dummy_ && state ().split () && (rig_->caps->targetable_vfo & (RIG_TARGETABLE_FREQ | RIG_TARGETABLE_PURE)))
{
// only read "other" VFO if in split, this allows rigs like
// FlexRadio to work in Kenwood TS-2000 mode despite them
// not having a FB; command
// we can only probe current VFO unless rig supports reading
// the other one directly because we can't glitch the Rx
error_check (rig_get_freq (rig_.data ()
, reversed_
? (rig_->state.vfo_list & RIG_VFO_A ? RIG_VFO_A : RIG_VFO_MAIN)
: (rig_->state.vfo_list & RIG_VFO_B ? RIG_VFO_B : RIG_VFO_SUB)
, &f), tr ("getting current VFO frequency"));
TRACE_CAT_POLL ("rig_get_freq other VFO =" << f);
update_other_frequency (f);
}
error_check (rig_get_mode (rig_.data (), RIG_VFO_CURR, &m, &w), tr ("getting current VFO mode"));
TRACE_CAT_POLL ("rig_get_mode mode =" << rig_strrmode (m) << "bw =" << w);
update_mode (map_mode (m));
if (!is_dummy_ && rig_->caps->get_split_vfo && split_query_works_)
{
vfo_t v {RIG_VFO_NONE}; // so we can tell if it doesn't get updated :(
auto rc = rig_get_split_vfo (rig_.data (), RIG_VFO_CURR, &s, &v);
if (-RIG_OK == rc && RIG_SPLIT_ON == s)
{ {
#if WSJT_TRACE_CAT && WSJT_TRACE_CAT_POLLS TRACE_CAT_POLL ("rig_get_split_vfo split = " << s << " VFO = " << rig_strvfo (v));
qDebug () << "HamlibTransceiver::poll rig_get_vfo"; update_split (true);
#endif // if (RIG_VFO_A == v)
vfo_t v; // {
error_check (rig_get_vfo (rig_.data (), &v), tr ("getting current VFO")); // has side effect of establishing current VFO inside hamlib // reversed_ = true; // not sure if this helps us here
#if WSJT_TRACE_CAT && WSJT_TRACE_CAT_POLLS // }
qDebug () << "HamlibTransceiver::poll rig_get_vfo VFO = " << rig_strvfo (v);
#endif
reversed_ = RIG_VFO_B == v;
} }
else if (-RIG_OK == rc) // not split
#if WSJT_TRACE_CAT && WSJT_TRACE_CAT_POLLS
qDebug () << "HamlibTransceiver::poll rig_get_freq";
#endif
error_check (rig_get_freq (rig_.data (), RIG_VFO_CURR, &f), tr ("getting current VFO frequency"));
#if WSJT_TRACE_CAT && WSJT_TRACE_CAT_POLLS
qDebug () << "HamlibTransceiver::poll rig_get_freq frequency =" << f;
#endif
update_rx_frequency (f);
if (state ().split () && (rig_->caps->targetable_vfo & (RIG_TARGETABLE_FREQ | RIG_TARGETABLE_PURE)))
{ {
// only read "other" VFO if in split, this allows rigs like TRACE_CAT_POLL ("rig_get_split_vfo split = " << s << " VFO = " << rig_strvfo (v));
// FlexRadio to work in Kenwood TS-2000 mode despite them update_split (false);
// not having a FB; command
// we can only probe current VFO unless rig supports reading
// the other one directly because we can't glitch the Rx
#if WSJT_TRACE_CAT && WSJT_TRACE_CAT_POLLS
qDebug () << "HamlibTransceiver::poll rig_get_freq other VFO";
#endif
error_check (rig_get_freq (rig_.data ()
, reversed_
? (rig_->state.vfo_list & RIG_VFO_A ? RIG_VFO_A : RIG_VFO_MAIN)
: (rig_->state.vfo_list & RIG_VFO_B ? RIG_VFO_B : RIG_VFO_SUB)
, &f), tr ("getting current VFO frequency"));
#if WSJT_TRACE_CAT && WSJT_TRACE_CAT_POLLS
qDebug () << "HamlibTransceiver::poll rig_get_freq other VFO =" << f;
#endif
update_other_frequency (f);
} }
else
#if WSJT_TRACE_CAT && WSJT_TRACE_CAT_POLLS
qDebug () << "HamlibTransceiver::poll rig_get_mode";
#endif
error_check (rig_get_mode (rig_.data (), RIG_VFO_CURR, &m, &w), tr ("getting current VFO mode"));
#if WSJT_TRACE_CAT && WSJT_TRACE_CAT_POLLS
qDebug () << "HamlibTransceiver::poll rig_get_mode mode =" << rig_strrmode (m) << "bw =" << w;
#endif
update_mode (map_mode (m));
if (rig_->caps->get_split_vfo && split_query_works_)
{ {
#if WSJT_TRACE_CAT && WSJT_TRACE_CAT_POLLS // Some rigs (Icom) don't have a way of reporting SPLIT
qDebug () << "HamlibTransceiver::poll rig_get_split_vfo"; // mode
#endif TRACE_CAT_POLL ("rig_get_split_vfo can't do on this rig");
vfo_t v {RIG_VFO_NONE}; // so we can tell if it doesn't get updated :( // just report how we see it based on prior commands
auto rc = rig_get_split_vfo (rig_.data (), RIG_VFO_CURR, &s, &v); split_query_works_ = false;
if (-RIG_OK == rc && RIG_SPLIT_ON == s)
{
#if WSJT_TRACE_CAT && WSJT_TRACE_CAT_POLLS
qDebug () << "HamlibTransceiver::poll rig_get_split_vfo split = " << s << " VFO = " << rig_strvfo (v);
#endif
update_split (true);
// if (RIG_VFO_A == v)
// {
// reversed_ = true; // not sure if this helps us here
// }
}
else if (-RIG_OK == rc) // not split
{
#if WSJT_TRACE_CAT && WSJT_TRACE_CAT_POLLS
qDebug () << "HamlibTransceiver::poll rig_get_split_vfo split = " << s << " VFO = " << rig_strvfo (v);
#endif
update_split (false);
}
else
{
// Some rigs (Icom) don't have a way of reporting SPLIT
// mode
#if WSJT_TRACE_CAT && WSJT_TRACE_CAT_POLLS
qDebug () << "HamlibTransceiver::poll rig_get_split_vfo can't do on this rig";
#endif
// just report how we see it based on prior commands
split_query_works_ = false;
}
} }
}
if (RIG_PTT_NONE != rig_->state.pttport.type.ptt && rig_->caps->get_ptt) if (RIG_PTT_NONE != rig_->state.pttport.type.ptt && rig_->caps->get_ptt)
{
ptt_t p;
auto rc = rig_get_ptt (rig_.data (), RIG_VFO_CURR, &p);
if (-RIG_ENAVAIL != rc && -RIG_ENIMPL != rc) // may fail if
// Net rig ctl and target doesn't
// support command
{ {
#if WSJT_TRACE_CAT && WSJT_TRACE_CAT_POLLS error_check (rc, tr ("getting PTT state"));
qDebug () << "HamlibTransceiver::poll rig_get_ptt"; TRACE_CAT_POLL ("rig_get_ptt PTT =" << p);
#endif update_PTT (!(RIG_PTT_OFF == p));
ptt_t p;
auto rc = rig_get_ptt (rig_.data (), RIG_VFO_CURR, &p);
if (-RIG_ENAVAIL != rc && -RIG_ENIMPL != rc) // may fail if
// Net rig ctl and target doesn't
// support command
{
error_check (rc, tr ("getting PTT state"));
#if WSJT_TRACE_CAT && WSJT_TRACE_CAT_POLLS
qDebug () << "HamlibTransceiver::poll rig_get_ptt PTT =" << p;
#endif
update_PTT (!(RIG_PTT_OFF == p));
}
} }
}
#if !WSJT_TRACE_CAT_POLLS #if !WSJT_TRACE_CAT_POLLS
#if WSJT_HAMLIB_TRACE #if WSJT_HAMLIB_TRACE
@ -847,32 +755,26 @@ void HamlibTransceiver::poll ()
rig_set_debug (RIG_DEBUG_WARN); rig_set_debug (RIG_DEBUG_WARN);
#endif #endif
#endif #endif
}
} }
void HamlibTransceiver::do_ptt (bool on) void HamlibTransceiver::do_ptt (bool on)
{ {
#if WSJT_TRACE_CAT TRACE_CAT (on << state () << "reversed =" << reversed_);
qDebug () << "HamlibTransceiver::do_ptt:" << on << state () << "reversed =" << reversed_;
#endif
if (on) if (on)
{ {
if (RIG_PTT_NONE != rig_->state.pttport.type.ptt) if (RIG_PTT_NONE != rig_->state.pttport.type.ptt)
{ {
#if WSJT_TRACE_CAT TRACE_CAT ("rig_set_ptt PTT = true");
qDebug () << "HamlibTransceiver::do_ptt rig_set_ptt PTT = true"; error_check (rig_set_ptt (rig_.data (), RIG_VFO_CURR
#endif , RIG_PTT_RIG_MICDATA == rig_->caps->ptt_type && back_ptt_port_
error_check (rig_set_ptt (rig_.data (), RIG_VFO_CURR, back_ptt_port_ ? RIG_PTT_ON_DATA : RIG_PTT_ON), tr ("setting PTT on")); ? RIG_PTT_ON_DATA : RIG_PTT_ON), tr ("setting PTT on"));
} }
} }
else else
{ {
if (RIG_PTT_NONE != rig_->state.pttport.type.ptt) if (RIG_PTT_NONE != rig_->state.pttport.type.ptt)
{ {
#if WSJT_TRACE_CAT TRACE_CAT ("rig_set_ptt PTT = false");
qDebug () << "HamlibTransceiver::do_ptt rig_set_ptt PTT = false";
#endif
error_check (rig_set_ptt (rig_.data (), RIG_VFO_CURR, RIG_PTT_OFF), tr ("setting PTT off")); error_check (rig_set_ptt (rig_.data (), RIG_VFO_CURR, RIG_PTT_OFF), tr ("setting PTT off"));
} }
} }

View File

@ -26,18 +26,8 @@ class HamlibTransceiver final
public: public:
static void register_transceivers (TransceiverFactory::Transceivers *); static void register_transceivers (TransceiverFactory::Transceivers *);
explicit HamlibTransceiver (int model_number explicit HamlibTransceiver (int model_number, TransceiverFactory::ParameterPack const&);
, QString const& cat_port explicit HamlibTransceiver (TransceiverFactory::PTTMethod ptt_type, QString const& ptt_port);
, int cat_baud
, TransceiverFactory::DataBits cat_data_bits
, TransceiverFactory::StopBits cat_stop_bits
, TransceiverFactory::Handshake cat_handshake
, TransceiverFactory::LineControl cat_dtr_control
, TransceiverFactory::LineControl cat_rts_control
, TransceiverFactory::PTTMethod ptt_type
, TransceiverFactory::TXAudioSource back_ptt_port
, QString const& ptt_port
, int poll_interval = 0);
~HamlibTransceiver (); ~HamlibTransceiver ();
private: private:
@ -63,6 +53,11 @@ class HamlibTransceiver final
bool back_ptt_port_; bool back_ptt_port_;
bool is_dummy_; bool is_dummy_;
// these are saved on destruction so we can start new instances
// where the last one left off
static freq_t dummy_frequency_;
static rmode_t dummy_mode_;
bool mutable reversed_; bool mutable reversed_;
bool split_query_works_; bool split_query_works_;

View File

@ -2,9 +2,10 @@
#include <QTimer> #include <QTimer>
#include <QDebug> #include <QDebug>
#include <objbase.h> #include <objbase.h>
#include "qt_helpers.hpP"
#include "moc_OmniRigTransceiver.cpp" #include "moc_OmniRigTransceiver.cpp"
namespace namespace
@ -47,12 +48,9 @@ auto OmniRigTransceiver::map_mode (OmniRig::RigParamX param) -> MODE
{ {
return FM; return FM;
} }
TRACE_CAT ("unrecognized mode");
#if WSJT_TRACE_CAT throw_qstring (tr ("OmniRig: unrecognized mode"));
qDebug () << "OmniRig map_mode unrecognized mode"; return UNK;
#endif
throw error {tr ("OmniRig: unrecognized mode")};
} }
OmniRig::RigParamX OmniRigTransceiver::map_mode (MODE mode) OmniRig::RigParamX OmniRigTransceiver::map_mode (MODE mode)
@ -115,10 +113,7 @@ OmniRigTransceiver::~OmniRigTransceiver ()
void OmniRigTransceiver::do_start () void OmniRigTransceiver::do_start ()
{ {
#if WSJT_TRACE_CAT TRACE_CAT ("starting");
qDebug () << "OmniRigTransceiver::do_start";
#endif
wrapped_->start (); wrapped_->start ();
CoInitializeEx (nullptr, 0 /*COINIT_APARTMENTTHREADED*/); // required because Qt only does this for GUI thread CoInitializeEx (nullptr, 0 /*COINIT_APARTMENTTHREADED*/); // required because Qt only does this for GUI thread
@ -126,11 +121,8 @@ void OmniRigTransceiver::do_start ()
omni_rig_.reset (new OmniRig::OmniRigX {this}); omni_rig_.reset (new OmniRig::OmniRigX {this});
if (omni_rig_->isNull ()) if (omni_rig_->isNull ())
{ {
#if WSJT_TRACE_CAT TRACE_CAT ("failed to start COM server");
qDebug () << "OmniRigTransceiver::do_start: failed to start COM server"; throw_qstring (tr ("Failed to start OmniRig COM server"));
#endif
throw error {tr ("Failed to start OmniRig COM server")};
} }
// COM/OLE exceptions get signalled // COM/OLE exceptions get signalled
@ -145,12 +137,8 @@ void OmniRigTransceiver::do_start ()
, SIGNAL (CustomReply (int, QVariant const&, QVariant const&)) , SIGNAL (CustomReply (int, QVariant const&, QVariant const&))
, this, SLOT (handle_custom_reply (int, QVariant const&, QVariant const&))); , this, SLOT (handle_custom_reply (int, QVariant const&, QVariant const&)));
#if WSJT_TRACE_CAT TRACE_CAT ("OmniRig s/w version:" << QString::number (omni_rig_->SoftwareVersion ()).toLocal8Bit ()
qDebug () << "i/f version:" << QString::number (omni_rig_->InterfaceVersion ()).toLocal8Bit ());
<< "OmniRig s/w version:" << QString::number (omni_rig_->SoftwareVersion ()).toLocal8Bit ()
<< "i/f version:" << QString::number (omni_rig_->InterfaceVersion ()).toLocal8Bit ()
;
#endif
// fetch the interface of the RigX CoClass and instantiate a proxy object // fetch the interface of the RigX CoClass and instantiate a proxy object
switch (rig_number_) switch (rig_number_)
@ -172,7 +160,7 @@ void OmniRigTransceiver::do_start ()
// if (!port_->Lock ()) // try to take exclusive use of the OmniRig serial port for PTT // if (!port_->Lock ()) // try to take exclusive use of the OmniRig serial port for PTT
// { // {
// throw error {tr ("Failed to get exclusive use of %1" from OmniRig").arg (ptt_type)}; // throw_qstring (tr ("Failed to get exclusive use of %1" from OmniRig").arg (ptt_type));
// } // }
// start off so we don't accidentally key the radio // start off so we don't accidentally key the radio
@ -189,17 +177,19 @@ void OmniRigTransceiver::do_start ()
readable_params_ = rig_->ReadableParams (); readable_params_ = rig_->ReadableParams ();
writable_params_ = rig_->WriteableParams (); writable_params_ = rig_->WriteableParams ();
#if WSJT_TRACE_CAT TRACE_CAT (QString {"OmniRig initial rig type: %1 readable params = 0x%2 writable params = 0x%3 for rig %4"}
qDebug ()
<< QString ("OmniRig initial rig type: %1 readable params = 0x%2 writable params = 0x%3 for rig %4")
.arg (rig_->RigType ()) .arg (rig_->RigType ())
.arg (readable_params_, 8, 16, QChar ('0')) .arg (readable_params_, 8, 16, QChar ('0'))
.arg (writable_params_, 8, 16, QChar ('0')) .arg (writable_params_, 8, 16, QChar ('0'))
.arg (rig_number_).toLocal8Bit () .arg (rig_number_).toLocal8Bit ());
;
#endif
QTimer::singleShot (5000, this, SLOT (online_check ())); rig_->GetRxFrequency ();
if (OmniRig::ST_ONLINE != rig_->Status ())
{
throw_qstring ("OmniRig exception: " + rig_->StatusStr ());
}
init_rig ();
} }
void OmniRigTransceiver::do_stop () void OmniRigTransceiver::do_stop ()
@ -209,18 +199,11 @@ void OmniRigTransceiver::do_stop ()
// port_->Unlock (); // release serial port // port_->Unlock (); // release serial port
port_->clear (); port_->clear ();
} }
rig_->clear (); rig_->clear ();
omni_rig_->clear (); omni_rig_->clear ();
CoUninitialize (); CoUninitialize ();
wrapped_->stop (); wrapped_->stop ();
TRACE_CAT ("stopped");
#if WSJT_TRACE_CAT
qDebug () << "OmniRigTransceiver::do_stop";
#endif
} }
void OmniRigTransceiver::online_check () void OmniRigTransceiver::online_check ()
@ -248,20 +231,15 @@ void OmniRigTransceiver::online_check ()
void OmniRigTransceiver::init_rig () void OmniRigTransceiver::init_rig ()
{ {
update_rx_frequency (rig_->GetRxFrequency ());
if (state ().split ()) if (state ().split ())
{ {
#if WSJT_TRACE_CAT TRACE_CAT ("set split");
qDebug () << "OmniRigTransceiver::init_rig: set split";
#endif
rig_->SetSplitMode (state ().frequency (), state ().tx_frequency ()); rig_->SetSplitMode (state ().frequency (), state ().tx_frequency ());
} }
else else
{ {
#if WSJT_TRACE_CAT TRACE_CAT ("set simplex");
qDebug () << "OmniRigTransceiver::init_rig: set simplex";
#endif
rig_->SetSimplexMode (state ().frequency ()); rig_->SetSimplexMode (state ().frequency ());
} }
} }
@ -279,18 +257,13 @@ void OmniRigTransceiver::do_sync (bool force_signal)
void OmniRigTransceiver::handle_COM_exception (int code, QString source, QString desc, QString help) void OmniRigTransceiver::handle_COM_exception (int code, QString source, QString desc, QString help)
{ {
#if WSJT_TRACE_CAT TRACE_CAT (QString::number (code) + " at " + source + ": " + desc + " (" + help + ')');
qDebug () << "OmniRigTransceiver::handle_COM_exception:" << QString::number (code) + " at " + source + ": " + desc + " (" + help + ')'; throw_qstring (tr ("OmniRig COM/OLE error: %1 at %2: %3 (%4)").arg (QString::number (code)).arg (source). arg (desc). arg (help));
#endif
throw error {tr ("OmniRig COM/OLE error: %1 at %2: %3 (%4)").arg (QString::number (code)).arg (source). arg (desc). arg (help)};
} }
void OmniRigTransceiver::handle_visible_change () void OmniRigTransceiver::handle_visible_change ()
{ {
#if WSJT_TRACE_CAT TRACE_CAT ("visibility change: visibility =" << omni_rig_->DialogVisible ());
qDebug () << "OmniRig visibility change: visibility =" << omni_rig_->DialogVisible ();
#endif
} }
void OmniRigTransceiver::handle_rig_type_change (int rig_number) void OmniRigTransceiver::handle_rig_type_change (int rig_number)
@ -299,17 +272,11 @@ void OmniRigTransceiver::handle_rig_type_change (int rig_number)
{ {
readable_params_ = rig_->ReadableParams (); readable_params_ = rig_->ReadableParams ();
writable_params_ = rig_->WriteableParams (); writable_params_ = rig_->WriteableParams ();
TRACE_CAT (QString {"OmniRig rig type change to: %1 readable params = 0x%2 writable params = 0x%3 for rig %4"}
#if WSJT_TRACE_CAT
qDebug ()
<< QString ("OmniRig rig type change to: %1 readable params = 0x%2 writable params = 0x%3 for rig %4")
.arg (rig_->RigType ()) .arg (rig_->RigType ())
.arg (readable_params_, 8, 16, QChar ('0')) .arg (readable_params_, 8, 16, QChar ('0'))
.arg (writable_params_, 8, 16, QChar ('0')) .arg (writable_params_, 8, 16, QChar ('0'))
.arg (rig_number).toLocal8Bit () .arg (rig_number).toLocal8Bit ());
;
#endif
offline ("OmniRig rig changed"); offline ("OmniRig rig changed");
} }
} }
@ -318,11 +285,7 @@ void OmniRigTransceiver::handle_status_change (int rig_number)
{ {
if (rig_number_ == rig_number) if (rig_number_ == rig_number)
{ {
#if WSJT_TRACE_CAT TRACE_CAT (QString {"OmniRig status change: new status for rig %1 = "}.arg (rig_number).toLocal8Bit () << rig_->StatusStr ().toLocal8Bit ());
qDebug ()
<< QString ("OmniRig status change: new status for rig %1 = ").arg (rig_number).toLocal8Bit () << rig_->StatusStr ().toLocal8Bit ();
#endif
if (OmniRig::ST_ONLINE != rig_->Status ()) if (OmniRig::ST_ONLINE != rig_->Status ())
{ {
QTimer::singleShot (5000, this, SLOT (online_check ())); QTimer::singleShot (5000, this, SLOT (online_check ()));
@ -347,24 +310,16 @@ void OmniRigTransceiver::handle_params_change (int rig_number, int params)
{ {
if (rig_number_ == rig_number) if (rig_number_ == rig_number)
{ {
#if WSJT_TRACE_CAT TRACE_CAT (QString {"OmniRig params change: params = 0x%1 for rig %2"}
qDebug ()
<< QString ("OmniRig params change: params = 0x%1 for rig %2")
.arg (params, 8, 16, QChar ('0')) .arg (params, 8, 16, QChar ('0'))
.arg (rig_number).toLocal8Bit () .arg (rig_number).toLocal8Bit ()
<< "state before:" << state () << "state before:" << state ());
;
#endif
starting_ = false; starting_ = false;
TransceiverState old_state {state ()}; TransceiverState old_state {state ()};
auto need_frequency = false; auto need_frequency = false;
// state_.online = true; // sometimes we don't get an initial // state_.online = true; // sometimes we don't get an initial
// // OmniRig::ST_ONLINE status change // // OmniRig::ST_ONLINE status change
// // event // // event
if (params & OmniRig::PM_VFOAA) if (params & OmniRig::PM_VFOAA)
{ {
update_split (false); update_split (false);
@ -430,7 +385,6 @@ void OmniRigTransceiver::handle_params_change (int rig_number, int params)
update_other_frequency (rig_->FreqB ()); update_other_frequency (rig_->FreqB ());
} }
} }
if (need_frequency) if (need_frequency)
{ {
if (readable_params_ & OmniRig::PM_FREQA) if (readable_params_ & OmniRig::PM_FREQA)
@ -461,7 +415,6 @@ void OmniRigTransceiver::handle_params_change (int rig_number, int params)
{ {
update_rx_frequency (rig_->Freq ()); update_rx_frequency (rig_->Freq ());
} }
if (params & OmniRig::PM_PITCH) if (params & OmniRig::PM_PITCH)
{ {
} }
@ -551,12 +504,7 @@ void OmniRigTransceiver::handle_params_change (int rig_number, int params)
update_complete (); update_complete ();
send_update_signal_ = false; send_update_signal_ = false;
} }
TRACE_CAT ("OmniRig params change: state after:" << state ());
#if WSJT_TRACE_CAT
qDebug ()
<< "OmniRig params change: state after:" << state ()
;
#endif
} }
} }
@ -567,30 +515,19 @@ void OmniRigTransceiver::handle_custom_reply (int rig_number, QVariant const& co
if (rig_number_ == rig_number) if (rig_number_ == rig_number)
{ {
#if WSJT_TRACE_CAT TRACE_CAT ("OmniRig custom command" << command.toString ().toLocal8Bit ()
qDebug () << "with reply" << reply.toString ().toLocal8Bit ()
<< "OmniRig custom command" << command.toString ().toLocal8Bit () << QString ("for rig %1").arg (rig_number).toLocal8Bit ());
<< "with reply" << reply.toString ().toLocal8Bit () TRACE_CAT ("OmniRig rig number:" << rig_number_ << ':' << state ());
<< QString ("for rig %1").arg (rig_number).toLocal8Bit ()
;
qDebug () << "OmniRig rig number:" << rig_number_ << ':' << state ();
#endif
} }
} }
void OmniRigTransceiver::do_ptt (bool on) void OmniRigTransceiver::do_ptt (bool on)
{ {
#if WSJT_TRACE_CAT TRACE_CAT (on << state ());
qDebug () << "OmniRigTransceiver::do_ptt:" << on << state ();
#endif
if (use_for_ptt_ && TransceiverFactory::PTT_method_CAT == ptt_type_) if (use_for_ptt_ && TransceiverFactory::PTT_method_CAT == ptt_type_)
{ {
#if WSJT_TRACE_CAT TRACE_CAT ("set PTT");
qDebug () << "OmniRigTransceiver::do_ptt: set PTT";
#endif
rig_->SetTx (on ? OmniRig::PM_TX : OmniRig::PM_RX); rig_->SetTx (on ? OmniRig::PM_TX : OmniRig::PM_RX);
} }
else else
@ -599,33 +536,23 @@ void OmniRigTransceiver::do_ptt (bool on)
{ {
if (TransceiverFactory::PTT_method_RTS == ptt_type_) if (TransceiverFactory::PTT_method_RTS == ptt_type_)
{ {
#if WSJT_TRACE_CAT TRACE_CAT ("set RTS");
qDebug () << "OmniRigTransceiver::do_ptt: set RTS";
#endif
port_->SetRts (on); port_->SetRts (on);
} }
else // "DTR" else // "DTR"
{ {
#if WSJT_TRACE_CAT TRACE_CAT ("set DTR");
qDebug () << "OmniRigTransceiver::do_ptt: set DTR";
#endif
port_->SetDtr (on); port_->SetDtr (on);
} }
} }
else else
{ {
#if WSJT_TRACE_CAT TRACE_CAT ("set PTT using basic transceiver");
qDebug () << "OmniRigTransceiver::do_ptt: set PTT using basic transceiver";
#endif
wrapped_->ptt (on); wrapped_->ptt (on);
} }
if (state ().ptt () != on) if (state ().ptt () != on)
{ {
update_PTT (on); update_PTT (on);
// no need for this as currently update_PTT() does it for us // no need for this as currently update_PTT() does it for us
// update_complete (); // update_complete ();
} }
@ -634,15 +561,11 @@ void OmniRigTransceiver::do_ptt (bool on)
void OmniRigTransceiver::do_frequency (Frequency f, MODE m) void OmniRigTransceiver::do_frequency (Frequency f, MODE m)
{ {
#if WSJT_TRACE_CAT TRACE_CAT (f << state ());
qDebug () << "OmniRigTransceiver::do_frequency:" << f << state ();
#endif
if (UNK != m) if (UNK != m)
{ {
do_mode (m, false); do_mode (m, false);
} }
if (OmniRig::PM_FREQ & writable_params_) if (OmniRig::PM_FREQ & writable_params_)
{ {
rig_->SetFreq (f); rig_->SetFreq (f);
@ -660,40 +583,28 @@ void OmniRigTransceiver::do_frequency (Frequency f, MODE m)
} }
else else
{ {
throw error {tr ("OmniRig: don't know how to set rig frequency")}; throw_qstring (tr ("OmniRig: don't know how to set rig frequency"));
} }
} }
void OmniRigTransceiver::do_tx_frequency (Frequency tx, bool /* rationalise_mode */) void OmniRigTransceiver::do_tx_frequency (Frequency tx, bool /* rationalise_mode */)
{ {
#if WSJT_TRACE_CAT TRACE_CAT (tx << state ());
qDebug () << "OmniRigTransceiver::do_tx_frequency:" << tx << state ();
#endif
bool split {tx != 0}; bool split {tx != 0};
if (split) if (split)
{ {
#if WSJT_TRACE_CAT TRACE_CAT ("set SPLIT mode on");
qDebug () << "OmniRigTransceiver::do_tx_frequency: set SPLIT mode on";
#endif
rig_->SetSplitMode (state ().frequency (), tx); rig_->SetSplitMode (state ().frequency (), tx);
update_other_frequency (tx); update_other_frequency (tx);
update_split (true); update_split (true);
} }
else else
{ {
#if WSJT_TRACE_CAT TRACE_CAT ("set SPLIT mode off");
qDebug () << "OmniRigTransceiver::do_tx_frequency: set SPLIT mode off";
#endif
rig_->SetSimplexMode (state ().frequency ()); rig_->SetSimplexMode (state ().frequency ());
update_split (false); update_split (false);
} }
bool notify {false}; bool notify {false};
if (readable_params_ & OmniRig::PM_FREQ || !(readable_params_ & (OmniRig::PM_FREQA | OmniRig::PM_FREQB))) if (readable_params_ & OmniRig::PM_FREQ || !(readable_params_ & (OmniRig::PM_FREQA | OmniRig::PM_FREQB)))
{ {
update_other_frequency (tx); // async updates won't return this update_other_frequency (tx); // async updates won't return this
@ -702,18 +613,13 @@ void OmniRigTransceiver::do_tx_frequency (Frequency tx, bool /* rationalise_mode
// "back" VFO on rig // "back" VFO on rig
notify = true; notify = true;
} }
if (!((OmniRig::PM_VFOAB | OmniRig::PM_VFOBA | OmniRig::PM_SPLITON) & readable_params_)) if (!((OmniRig::PM_VFOAB | OmniRig::PM_VFOBA | OmniRig::PM_SPLITON) & readable_params_))
{ {
#if WSJT_TRACE_CAT TRACE_CAT ("setting SPLIT manually");
qDebug () << "OmniRigTransceiver::do_tx_frequency: setting SPLIT manually";
#endif
update_split (split); // we can't read it so just set and update_split (split); // we can't read it so just set and
// hope op doesn't change it // hope op doesn't change it
notify = true; notify = true;
} }
if (notify) if (notify)
{ {
update_complete (); update_complete ();
@ -722,14 +628,9 @@ void OmniRigTransceiver::do_tx_frequency (Frequency tx, bool /* rationalise_mode
void OmniRigTransceiver::do_mode (MODE mode, bool /* rationalise */) void OmniRigTransceiver::do_mode (MODE mode, bool /* rationalise */)
{ {
#if WSJT_TRACE_CAT TRACE_CAT (mode << state ());
qDebug () << "OmniRigTransceiver::do_mode:" << mode << state ();
#endif
// TODO: G4WJS OmniRig doesn't seem to have any capability of tracking/setting VFO B mode // TODO: G4WJS OmniRig doesn't seem to have any capability of tracking/setting VFO B mode
auto mapped = map_mode (mode); auto mapped = map_mode (mode);
if (mapped & writable_params_) if (mapped & writable_params_)
{ {
rig_->SetMode (mapped); rig_->SetMode (mapped);

View File

@ -6,96 +6,48 @@
#include <QString> #include <QString>
#include <QTimer> #include <QTimer>
#include "pimpl_impl.hpp"
#include "moc_PollingTransceiver.cpp"
namespace namespace
{ {
unsigned const polls_to_stabilize {3}; unsigned const polls_to_stabilize {3};
} }
// Internal implementation of the PollingTransceiver class.
class PollingTransceiver::impl final
: public QObject
{
Q_OBJECT;
public:
impl (PollingTransceiver * self, int poll_interval)
: QObject {self}
, self_ {self}
, interval_ {poll_interval}
, poll_timer_ {nullptr}
, retries_ {0}
{
}
private:
impl (impl const&) = delete;
impl& operator = (impl const&) = delete;
void start_timer ()
{
if (interval_)
{
if (!poll_timer_)
{
poll_timer_ = new QTimer {this}; // pass ownership to QObject which handles destruction for us
connect (poll_timer_, &QTimer::timeout, this, &PollingTransceiver::impl::handle_timeout);
}
poll_timer_->start (interval_);
}
}
void stop_timer ()
{
if (poll_timer_)
{
poll_timer_->stop ();
}
}
Q_SLOT void handle_timeout ();
PollingTransceiver * self_; // our owner so we can call methods
int interval_; // polling interval in milliseconds
QTimer * poll_timer_;
// keep a record of the last state signalled so we can elide
// duplicate updates
Transceiver::TransceiverState last_signalled_state_;
// keep a record of expected state so we can compare with actual
// updates to determine when state changes have bubbled through
Transceiver::TransceiverState next_state_;
unsigned retries_; // number of incorrect polls left
friend class PollingTransceiver;
};
#include "PollingTransceiver.moc"
PollingTransceiver::PollingTransceiver (int poll_interval) PollingTransceiver::PollingTransceiver (int poll_interval)
: m_ {this, poll_interval} : interval_ {poll_interval * 1000}
, poll_timer_ {nullptr}
, retries_ {0}
{ {
} }
PollingTransceiver::~PollingTransceiver () void PollingTransceiver::start_timer ()
{ {
if (interval_)
{
if (!poll_timer_)
{
poll_timer_ = new QTimer {this}; // pass ownership to QObject which handles destruction for us
connect (poll_timer_, &QTimer::timeout, this, &PollingTransceiver::handle_timeout);
}
poll_timer_->start (interval_);
}
}
void PollingTransceiver::stop_timer ()
{
if (poll_timer_)
{
poll_timer_->stop ();
}
} }
void PollingTransceiver::do_post_start () void PollingTransceiver::do_post_start ()
{ {
m_->start_timer (); start_timer ();
if (!m_->next_state_.online ()) if (!next_state_.online ())
{ {
// remember that we are expecting to go online // remember that we are expecting to go online
m_->next_state_.online (true); next_state_.online (true);
m_->retries_ = polls_to_stabilize; retries_ = polls_to_stabilize;
} }
} }
@ -103,7 +55,7 @@ void PollingTransceiver::do_post_stop ()
{ {
// not much point waiting for rig to go offline since we are ceasing // not much point waiting for rig to go offline since we are ceasing
// polls // polls
m_->stop_timer (); stop_timer ();
} }
void PollingTransceiver::do_post_frequency (Frequency f, MODE m) void PollingTransceiver::do_post_frequency (Frequency f, MODE m)
@ -111,55 +63,55 @@ void PollingTransceiver::do_post_frequency (Frequency f, MODE m)
// take care not to set the expected next mode to unknown since some // take care not to set the expected next mode to unknown since some
// callers use mode == unknown to signify that they do not know the // callers use mode == unknown to signify that they do not know the
// mode and don't care // mode and don't care
if (m_->next_state_.frequency () != f || (m != UNK && m_->next_state_.mode () != m)) if (next_state_.frequency () != f || (m != UNK && next_state_.mode () != m))
{ {
// update expected state with new frequency and set poll count // update expected state with new frequency and set poll count
m_->next_state_.frequency (f); next_state_.frequency (f);
if (m != UNK) if (m != UNK)
{ {
m_->next_state_.mode (m); next_state_.mode (m);
} }
m_->retries_ = polls_to_stabilize; retries_ = polls_to_stabilize;
} }
} }
void PollingTransceiver::do_post_tx_frequency (Frequency f, bool /* rationalize */) void PollingTransceiver::do_post_tx_frequency (Frequency f, bool /* rationalize */)
{ {
if (m_->next_state_.tx_frequency () != f) if (next_state_.tx_frequency () != f)
{ {
// update expected state with new TX frequency and set poll // update expected state with new TX frequency and set poll
// count // count
m_->next_state_.tx_frequency (f); next_state_.tx_frequency (f);
m_->next_state_.split (f); // setting non-zero TX frequency means split next_state_.split (f); // setting non-zero TX frequency means split
m_->retries_ = polls_to_stabilize; retries_ = polls_to_stabilize;
} }
} }
void PollingTransceiver::do_post_mode (MODE m, bool /*rationalize_mode*/) void PollingTransceiver::do_post_mode (MODE m, bool /*rationalize_mode*/)
{ {
// we don't ever expect mode to goto to unknown // we don't ever expect mode to goto to unknown
if (m != UNK && m_->next_state_.mode () != m) if (m != UNK && next_state_.mode () != m)
{ {
// update expected state with new mode and set poll count // update expected state with new mode and set poll count
m_->next_state_.mode (m); next_state_.mode (m);
m_->retries_ = polls_to_stabilize; retries_ = polls_to_stabilize;
} }
} }
void PollingTransceiver::do_post_ptt (bool p) void PollingTransceiver::do_post_ptt (bool p)
{ {
if (m_->next_state_.ptt () != p) if (next_state_.ptt () != p)
{ {
// update expected state with new PTT and set poll count // update expected state with new PTT and set poll count
m_->next_state_.ptt (p); next_state_.ptt (p);
m_->retries_ = polls_to_stabilize; retries_ = 0; // fast feedback on PTT
} }
} }
bool PollingTransceiver::do_pre_update () bool PollingTransceiver::do_pre_update ()
{ {
// if we are holding off a change then withhold the signal // if we are holding off a change then withhold the signal
if (m_->retries_ && state () != m_->next_state_) if (retries_ && state () != next_state_)
{ {
return false; return false;
} }
@ -175,10 +127,10 @@ void PollingTransceiver::do_sync (bool force_signal)
// or, hasn't become what we expected after polls_to_stabilize // or, hasn't become what we expected after polls_to_stabilize
// polls. Unsolicited changes will be signalled immediately unless // polls. Unsolicited changes will be signalled immediately unless
// they intervene in a expected sequence where they will be delayed. // they intervene in a expected sequence where they will be delayed.
if (m_->retries_) if (retries_)
{ {
--m_->retries_; --retries_;
if (force_signal || state () == m_->next_state_ || !m_->retries_) if (force_signal || state () == next_state_ || !retries_)
{ {
// our client wants a signal regardless // our client wants a signal regardless
// or the expected state has arrived // or the expected state has arrived
@ -186,7 +138,7 @@ void PollingTransceiver::do_sync (bool force_signal)
force_signal = true; force_signal = true;
} }
} }
else if (force_signal || state () != m_->last_signalled_state_) else if (force_signal || state () != last_signalled_state_)
{ {
// here is the normal passive polling path // here is the normal passive polling path
// either our client has requested a state update regardless of change // either our client has requested a state update regardless of change
@ -197,14 +149,14 @@ void PollingTransceiver::do_sync (bool force_signal)
if (force_signal) if (force_signal)
{ {
// reset everything, record and signal the current state // reset everything, record and signal the current state
m_->retries_ = 0; retries_ = 0;
m_->next_state_ = state (); next_state_ = state ();
m_->last_signalled_state_ = state (); last_signalled_state_ = state ();
update_complete (); update_complete ();
} }
} }
void PollingTransceiver::impl::handle_timeout () void PollingTransceiver::handle_timeout ()
{ {
QString message; QString message;
@ -212,7 +164,7 @@ void PollingTransceiver::impl::handle_timeout ()
// inform our parent of the failure via the offline() message // inform our parent of the failure via the offline() message
try try
{ {
self_->do_sync (false); do_sync (false);
} }
catch (std::exception const& e) catch (std::exception const& e)
{ {
@ -224,6 +176,6 @@ void PollingTransceiver::impl::handle_timeout ()
} }
if (!message.isEmpty ()) if (!message.isEmpty ())
{ {
self_->offline (message); offline (message);
} }
} }

View File

@ -5,7 +5,7 @@
#include "TransceiverBase.hpp" #include "TransceiverBase.hpp"
#include "pimpl_h.hpp" class QTimer;
// //
// Polling Transceiver // Polling Transceiver
@ -17,7 +17,7 @@
// //
// Implements the TransceiverBase post action interface and provides // Implements the TransceiverBase post action interface and provides
// the abstract poll() operation for sub-classes to implement. The // the abstract poll() operation for sub-classes to implement. The
// pol operation is invoked every poll_interval milliseconds. // poll operation is invoked every poll_interval seconds.
// //
// Responsibilities // Responsibilities
// //
@ -35,10 +35,7 @@ class PollingTransceiver
Q_OBJECT; // for translation context Q_OBJECT; // for translation context
protected: protected:
explicit PollingTransceiver (int poll_interval); // in milliseconds explicit PollingTransceiver (int poll_interval); // in seconds
public:
~PollingTransceiver ();
protected: protected:
void do_sync (bool force_signal) override final; void do_sync (bool force_signal) override final;
@ -56,8 +53,23 @@ protected:
bool do_pre_update () override final; bool do_pre_update () override final;
private: private:
class impl; void start_timer ();
pimpl<impl> m_; void stop_timer ();
Q_SLOT void handle_timeout ();
int interval_; // polling interval in milliseconds
QTimer * poll_timer_;
// keep a record of the last state signalled so we can elide
// duplicate updates
Transceiver::TransceiverState last_signalled_state_;
// keep a record of expected state so we can compare with actual
// updates to determine when state changes have bubbled through
Transceiver::TransceiverState next_state_;
unsigned retries_; // number of incorrect polls left
}; };
#endif #endif

View File

@ -122,9 +122,6 @@ public:
Q_SLOT virtual void start () noexcept = 0; Q_SLOT virtual void start () noexcept = 0;
Q_SLOT virtual void stop () noexcept = 0; Q_SLOT virtual void stop () noexcept = 0;
// Ready to be destroyed.
Q_SIGNAL void finished () const;
// Set frequency in Hertz. // Set frequency in Hertz.
Q_SLOT virtual void frequency (Frequency, MODE = UNK) noexcept = 0; Q_SLOT virtual void frequency (Frequency, MODE = UNK) noexcept = 0;
@ -148,6 +145,9 @@ public:
// asynchronous status updates // asynchronous status updates
Q_SIGNAL void update (Transceiver::TransceiverState) const; Q_SIGNAL void update (Transceiver::TransceiverState) const;
Q_SIGNAL void failure (QString reason) const; Q_SIGNAL void failure (QString reason) const;
// Ready to be destroyed.
Q_SIGNAL void finished () const;
}; };
Q_DECLARE_METATYPE (Transceiver::TransceiverState); Q_DECLARE_METATYPE (Transceiver::TransceiverState);

View File

@ -3,73 +3,38 @@
#include <exception> #include <exception>
#include <QString> #include <QString>
#include <QTimer>
#include "pimpl_impl.hpp" #include <QThread>
#include <QDebug>
namespace namespace
{ {
auto const unexpected = TransceiverBase::tr ("Unexpected rig error"); auto const unexpected = TransceiverBase::tr ("Unexpected rig error");
} }
class TransceiverBase::impl final
: public QObject
{
Q_OBJECT;
public:
impl (TransceiverBase * parent)
: parent_ {parent}
{
connect (this, &TransceiverBase::impl::updated, this, &TransceiverBase::impl::update_complete, Qt::QueuedConnection);
}
impl (impl const&) = delete;
impl& operator = (impl const&) = delete;
Q_SIGNAL void updated ();
Q_SLOT void update_complete ()
{
if (parent_->do_pre_update ())
{
Q_EMIT parent_->update (state_);
}
}
TransceiverBase * parent_;
TransceiverState state_;
};
#include "TransceiverBase.moc"
TransceiverBase::TransceiverBase ()
: m_ {this}
{
}
TransceiverBase::~TransceiverBase ()
{
}
void TransceiverBase::start () noexcept void TransceiverBase::start () noexcept
{ {
QString message; QString message;
try try
{ {
if (m_->state_.online ()) if (state_.online ())
{ {
m_->state_.online (false); try
{
// ensure PTT isn't left set // try and ensure PTT isn't left set
do_ptt (false); do_ptt (false);
do_post_ptt (false); do_post_ptt (false);
}
catch (...)
{
// don't care about exceptions
}
do_stop (); do_stop ();
do_post_stop (); do_post_stop ();
} }
do_start (); do_start ();
do_post_start (); do_post_start ();
m_->state_.online (true); state_.online (true);
} }
catch (std::exception const& e) catch (std::exception const& e)
{ {
@ -90,17 +55,22 @@ void TransceiverBase::stop () noexcept
QString message; QString message;
try try
{ {
if (m_->state_.online ()) if (state_.online ())
{ {
m_->state_.online (false); try
{
// ensure PTT isn't left set // try and ensure PTT isn't left set
do_ptt (false); do_ptt (false);
do_post_ptt (false); do_post_ptt (false);
}
catch (...)
{
// don't care about exceptions
}
} }
do_stop (); do_stop ();
do_post_stop (); do_post_stop ();
state_.online (false);
} }
catch (std::exception const& e) catch (std::exception const& e)
{ {
@ -125,7 +95,7 @@ void TransceiverBase::frequency (Frequency f, MODE m) noexcept
QString message; QString message;
try try
{ {
if (m_->state_.online ()) if (state_.online ())
{ {
do_frequency (f, m); do_frequency (f, m);
do_post_frequency (f, m); do_post_frequency (f, m);
@ -150,7 +120,7 @@ void TransceiverBase::tx_frequency (Frequency tx, bool rationalise_mode) noexcep
QString message; QString message;
try try
{ {
if (m_->state_.online ()) if (state_.online ())
{ {
do_tx_frequency (tx, rationalise_mode); do_tx_frequency (tx, rationalise_mode);
do_post_tx_frequency (tx, rationalise_mode); do_post_tx_frequency (tx, rationalise_mode);
@ -175,7 +145,7 @@ void TransceiverBase::mode (MODE m, bool rationalise) noexcept
QString message; QString message;
try try
{ {
if (m_->state_.online ()) if (state_.online ())
{ {
do_mode (m, rationalise); do_mode (m, rationalise);
do_post_mode (m, rationalise); do_post_mode (m, rationalise);
@ -200,7 +170,7 @@ void TransceiverBase::ptt (bool on) noexcept
QString message; QString message;
try try
{ {
if (m_->state_.online ()) if (state_.online ())
{ {
do_ptt (on); do_ptt (on);
do_post_ptt (on); do_post_ptt (on);
@ -225,7 +195,7 @@ void TransceiverBase::sync (bool force_signal) noexcept
QString message; QString message;
try try
{ {
if (m_->state_.online ()) if (state_.online ())
{ {
do_sync (force_signal); do_sync (force_signal);
} }
@ -246,28 +216,28 @@ void TransceiverBase::sync (bool force_signal) noexcept
void TransceiverBase::update_rx_frequency (Frequency rx) void TransceiverBase::update_rx_frequency (Frequency rx)
{ {
m_->state_.frequency (rx); state_.frequency (rx);
} }
void TransceiverBase::update_other_frequency (Frequency tx) void TransceiverBase::update_other_frequency (Frequency tx)
{ {
m_->state_.tx_frequency (tx); state_.tx_frequency (tx);
} }
void TransceiverBase::update_split (bool state) void TransceiverBase::update_split (bool state)
{ {
m_->state_.split (state); state_.split (state);
} }
void TransceiverBase::update_mode (MODE m) void TransceiverBase::update_mode (MODE m)
{ {
m_->state_.mode (m); state_.mode (m);
} }
void TransceiverBase::update_PTT (bool state) void TransceiverBase::update_PTT (bool state)
{ {
auto prior = m_->state_.ptt (); auto prior = state_.ptt ();
m_->state_.ptt (state); state_.ptt (state);
if (state != prior) if (state != prior)
{ {
// always signal PTT changes because some MainWindow logic // always signal PTT changes because some MainWindow logic
@ -276,11 +246,19 @@ void TransceiverBase::update_PTT (bool state)
} }
} }
void TransceiverBase::updated ()
{
if (do_pre_update ())
{
Q_EMIT update (state_);
}
}
void TransceiverBase::update_complete () void TransceiverBase::update_complete ()
{ {
// Use a signal to ensure that the calling function completes before // Use a timer to ensure that the calling function completes before
// the Transceiver::update signal is triggered. // the Transceiver::update signal is triggered.
Q_EMIT m_->updated (); QTimer::singleShot (0, this, SLOT (updated ()));
} }
void TransceiverBase::offline (QString const& reason) void TransceiverBase::offline (QString const& reason)
@ -288,16 +266,22 @@ void TransceiverBase::offline (QString const& reason)
QString message; QString message;
try try
{ {
if (m_->state_.online ()) if (state_.online ())
{ {
m_->state_.online (false); try
{
// ensure PTT isn't left set // try and ensure PTT isn't left set
do_ptt (false); do_ptt (false);
do_post_ptt (false); do_post_ptt (false);
}
catch (...)
{
// don't care about exceptions
}
} }
do_stop (); do_stop ();
do_post_stop (); do_post_stop ();
state_.online (false);
} }
catch (std::exception const& e) catch (std::exception const& e)
{ {
@ -309,8 +293,3 @@ void TransceiverBase::offline (QString const& reason)
} }
Q_EMIT failure (reason + '\n' + message); Q_EMIT failure (reason + '\n' + message);
} }
auto TransceiverBase::state () const -> TransceiverState const&
{
return m_->state_;
}

View File

@ -7,8 +7,6 @@
#include "Transceiver.hpp" #include "Transceiver.hpp"
#include "pimpl_h.hpp"
// //
// Base Transceiver Implementation // Base Transceiver Implementation
// //
@ -60,12 +58,12 @@
class TransceiverBase class TransceiverBase
: public Transceiver : public Transceiver
{ {
Q_OBJECT;
protected: protected:
TransceiverBase (); TransceiverBase () = default;
public: public:
~TransceiverBase ();
// //
// Implement the Transceiver abstract interface. // Implement the Transceiver abstract interface.
// //
@ -127,11 +125,25 @@ protected:
void offline (QString const& reason); void offline (QString const& reason);
// and query state with this one // and query state with this one
TransceiverState const& state () const; TransceiverState const& state () const {return state_;}
private: private:
class impl; Q_SLOT void updated ();
pimpl<impl> m_;
TransceiverState state_;
}; };
// some trace macros
#if WSJT_TRACE_CAT
#define TRACE_CAT(MSG) qDebug () << __PRETTY_FUNCTION__ << MSG
#else
#define TRACE_CAT(MSG)
#endif
#if WSJT_TRACE_CAT && WSJT_TRACE_CAT_POLLS
#define TRACE_CAT_POLL(MSG) qDebug () << __PRETTY_FUNCTION__ << MSG
#else
#define TRACE_CAT_POLL(MSG)
#endif
#endif #endif

View File

@ -94,50 +94,22 @@ bool TransceiverFactory::has_asynchronous_CAT (QString const& name) const
return supported_transceivers ()[name].asynchronous_; return supported_transceivers ()[name].asynchronous_;
} }
std::unique_ptr<Transceiver> TransceiverFactory::create (QString const& name std::unique_ptr<Transceiver> TransceiverFactory::create (ParameterPack const& params, QThread * target_thread)
, QString const& cat_port
, int cat_baud
, DataBits cat_data_bits
, StopBits cat_stop_bits
, Handshake cat_handshake
, LineControl cat_dtr_control
, LineControl cat_rts_control
, PTTMethod ptt_type
, TXAudioSource ptt_use_data_ptt
, SplitMode split_mode
, QString const& ptt_port
, int poll_interval
, QThread * target_thread
)
{ {
std::unique_ptr<Transceiver> result; std::unique_ptr<Transceiver> result;
switch (supported_transceivers ()[name].model_number_) switch (supported_transceivers ()[params.rig_name].model_number_)
{ {
case CommanderId: case CommanderId:
{ {
// we start with a dummy HamlibTransceiver object instance that can support direct PTT // we start with a dummy HamlibTransceiver object instance that can support direct PTT
std::unique_ptr<TransceiverBase> basic_transceiver { std::unique_ptr<TransceiverBase> basic_transceiver {new HamlibTransceiver {params.ptt_type, params.ptt_port}};
new HamlibTransceiver {
supported_transceivers ()[basic_transceiver_name_].model_number_
, cat_port
, cat_baud
, cat_data_bits
, cat_stop_bits
, cat_handshake
, force_low
, force_low
, ptt_type
, ptt_use_data_ptt
, "CAT" == ptt_port ? "" : ptt_port
}
};
if (target_thread) if (target_thread)
{ {
basic_transceiver.get ()->moveToThread (target_thread); basic_transceiver.get ()->moveToThread (target_thread);
} }
// wrap the basic Transceiver object instance with a decorator object that talks to DX Lab Suite Commander // wrap the basic Transceiver object instance with a decorator object that talks to DX Lab Suite Commander
result.reset (new DXLabSuiteCommanderTransceiver {std::move (basic_transceiver), cat_port, PTT_method_CAT == ptt_type, poll_interval}); result.reset (new DXLabSuiteCommanderTransceiver {std::move (basic_transceiver), params.network_port, PTT_method_CAT == params.ptt_type, params.poll_interval});
if (target_thread) if (target_thread)
{ {
result.get ()->moveToThread (target_thread); result.get ()->moveToThread (target_thread);
@ -148,28 +120,14 @@ std::unique_ptr<Transceiver> TransceiverFactory::create (QString const& name
case HRDId: case HRDId:
{ {
// we start with a dummy HamlibTransceiver object instance that can support direct PTT // we start with a dummy HamlibTransceiver object instance that can support direct PTT
std::unique_ptr<TransceiverBase> basic_transceiver { std::unique_ptr<TransceiverBase> basic_transceiver {new HamlibTransceiver {params.ptt_type, params.ptt_port}};
new HamlibTransceiver {
supported_transceivers ()[basic_transceiver_name_].model_number_
, cat_port
, cat_baud
, cat_data_bits
, cat_stop_bits
, cat_handshake
, cat_dtr_control
, cat_rts_control
, ptt_type
, ptt_use_data_ptt
, "CAT" == ptt_port ? "" : ptt_port
}
};
if (target_thread) if (target_thread)
{ {
basic_transceiver.get ()->moveToThread (target_thread); basic_transceiver.get ()->moveToThread (target_thread);
} }
// wrap the basic Transceiver object instance with a decorator object that talks to ham Radio Deluxe // wrap the basic Transceiver object instance with a decorator object that talks to ham Radio Deluxe
result.reset (new HRDTransceiver {std::move (basic_transceiver), cat_port, PTT_method_CAT == ptt_type, poll_interval}); result.reset (new HRDTransceiver {std::move (basic_transceiver), params.network_port, PTT_method_CAT == params.ptt_type, params.poll_interval});
if (target_thread) if (target_thread)
{ {
result.get ()->moveToThread (target_thread); result.get ()->moveToThread (target_thread);
@ -181,28 +139,14 @@ std::unique_ptr<Transceiver> TransceiverFactory::create (QString const& name
case OmniRigOneId: case OmniRigOneId:
{ {
// we start with a dummy HamlibTransceiver object instance that can support direct PTT // we start with a dummy HamlibTransceiver object instance that can support direct PTT
std::unique_ptr<TransceiverBase> basic_transceiver { std::unique_ptr<TransceiverBase> basic_transceiver {new HamlibTransceiver {params.ptt_type, params.ptt_port}};
new HamlibTransceiver {
supported_transceivers ()[basic_transceiver_name_].model_number_
, cat_port
, cat_baud
, cat_data_bits
, cat_stop_bits
, cat_handshake
, cat_dtr_control
, cat_rts_control
, ptt_type
, ptt_use_data_ptt
, "CAT" == ptt_port ? "" : ptt_port
}
};
if (target_thread) if (target_thread)
{ {
basic_transceiver.get ()->moveToThread (target_thread); basic_transceiver.get ()->moveToThread (target_thread);
} }
// wrap the basic Transceiver object instance with a decorator object that talks to OmniRig rig one // wrap the basic Transceiver object instance with a decorator object that talks to OmniRig rig one
result.reset (new OmniRigTransceiver {std::move (basic_transceiver), OmniRigTransceiver::One, ptt_type, ptt_port}); result.reset (new OmniRigTransceiver {std::move (basic_transceiver), OmniRigTransceiver::One, params.ptt_type, params.ptt_port});
if (target_thread) if (target_thread)
{ {
result.get ()->moveToThread (target_thread); result.get ()->moveToThread (target_thread);
@ -213,28 +157,14 @@ std::unique_ptr<Transceiver> TransceiverFactory::create (QString const& name
case OmniRigTwoId: case OmniRigTwoId:
{ {
// we start with a dummy HamlibTransceiver object instance that can support direct PTT // we start with a dummy HamlibTransceiver object instance that can support direct PTT
std::unique_ptr<TransceiverBase> basic_transceiver { std::unique_ptr<TransceiverBase> basic_transceiver {new HamlibTransceiver {params.ptt_type, params.ptt_port}};
new HamlibTransceiver {
supported_transceivers ()[basic_transceiver_name_].model_number_
, cat_port
, cat_baud
, cat_data_bits
, cat_stop_bits
, cat_handshake
, cat_dtr_control
, cat_rts_control
, ptt_type
, ptt_use_data_ptt
, "CAT" == ptt_port ? "" : ptt_port
}
};
if (target_thread) if (target_thread)
{ {
basic_transceiver.get ()->moveToThread (target_thread); basic_transceiver.get ()->moveToThread (target_thread);
} }
// wrap the basic Transceiver object instance with a decorator object that talks to OmniRig rig two // wrap the basic Transceiver object instance with a decorator object that talks to OmniRig rig two
result.reset (new OmniRigTransceiver {std::move (basic_transceiver), OmniRigTransceiver::Two, ptt_type, ptt_port}); result.reset (new OmniRigTransceiver {std::move (basic_transceiver), OmniRigTransceiver::Two, params.ptt_type, params.ptt_port});
if (target_thread) if (target_thread)
{ {
result.get ()->moveToThread (target_thread); result.get ()->moveToThread (target_thread);
@ -244,20 +174,7 @@ std::unique_ptr<Transceiver> TransceiverFactory::create (QString const& name
#endif #endif
default: default:
result.reset (new HamlibTransceiver { result.reset (new HamlibTransceiver {supported_transceivers ()[params.rig_name].model_number_, params});
supported_transceivers ()[name].model_number_
, cat_port
, cat_baud
, cat_data_bits
, cat_stop_bits
, cat_handshake
, cat_dtr_control
, cat_rts_control
, ptt_type
, ptt_use_data_ptt
, "CAT" == ptt_port ? cat_port : ptt_port
, poll_interval
});
if (target_thread) if (target_thread)
{ {
result.get ()->moveToThread (target_thread); result.get ()->moveToThread (target_thread);
@ -265,7 +182,7 @@ std::unique_ptr<Transceiver> TransceiverFactory::create (QString const& name
break; break;
} }
if (split_mode_emulate == split_mode) if (split_mode_emulate == params.split_mode)
{ {
// wrap the Transceiver object instance with a decorator that emulates split mode // wrap the Transceiver object instance with a decorator that emulates split mode
result.reset (new EmulateSplitTransceiver {std::move (result)}); result.reset (new EmulateSplitTransceiver {std::move (result)});
@ -282,7 +199,6 @@ std::unique_ptr<Transceiver> TransceiverFactory::create (QString const& name
ENUM_QDEBUG_OPS_IMPL (TransceiverFactory, DataBits); ENUM_QDEBUG_OPS_IMPL (TransceiverFactory, DataBits);
ENUM_QDEBUG_OPS_IMPL (TransceiverFactory, StopBits); ENUM_QDEBUG_OPS_IMPL (TransceiverFactory, StopBits);
ENUM_QDEBUG_OPS_IMPL (TransceiverFactory, Handshake); ENUM_QDEBUG_OPS_IMPL (TransceiverFactory, Handshake);
ENUM_QDEBUG_OPS_IMPL (TransceiverFactory, LineControl);
ENUM_QDEBUG_OPS_IMPL (TransceiverFactory, PTTMethod); ENUM_QDEBUG_OPS_IMPL (TransceiverFactory, PTTMethod);
ENUM_QDEBUG_OPS_IMPL (TransceiverFactory, TXAudioSource); ENUM_QDEBUG_OPS_IMPL (TransceiverFactory, TXAudioSource);
ENUM_QDEBUG_OPS_IMPL (TransceiverFactory, SplitMode); ENUM_QDEBUG_OPS_IMPL (TransceiverFactory, SplitMode);
@ -291,7 +207,6 @@ ENUM_QDEBUG_OPS_IMPL (TransceiverFactory, SplitMode);
ENUM_QDATASTREAM_OPS_IMPL (TransceiverFactory, DataBits); ENUM_QDATASTREAM_OPS_IMPL (TransceiverFactory, DataBits);
ENUM_QDATASTREAM_OPS_IMPL (TransceiverFactory, StopBits); ENUM_QDATASTREAM_OPS_IMPL (TransceiverFactory, StopBits);
ENUM_QDATASTREAM_OPS_IMPL (TransceiverFactory, Handshake); ENUM_QDATASTREAM_OPS_IMPL (TransceiverFactory, Handshake);
ENUM_QDATASTREAM_OPS_IMPL (TransceiverFactory, LineControl);
ENUM_QDATASTREAM_OPS_IMPL (TransceiverFactory, PTTMethod); ENUM_QDATASTREAM_OPS_IMPL (TransceiverFactory, PTTMethod);
ENUM_QDATASTREAM_OPS_IMPL (TransceiverFactory, TXAudioSource); ENUM_QDATASTREAM_OPS_IMPL (TransceiverFactory, TXAudioSource);
ENUM_QDATASTREAM_OPS_IMPL (TransceiverFactory, SplitMode); ENUM_QDATASTREAM_OPS_IMPL (TransceiverFactory, SplitMode);
@ -299,7 +214,6 @@ ENUM_QDATASTREAM_OPS_IMPL (TransceiverFactory, SplitMode);
ENUM_CONVERSION_OPS_IMPL (TransceiverFactory, DataBits); ENUM_CONVERSION_OPS_IMPL (TransceiverFactory, DataBits);
ENUM_CONVERSION_OPS_IMPL (TransceiverFactory, StopBits); ENUM_CONVERSION_OPS_IMPL (TransceiverFactory, StopBits);
ENUM_CONVERSION_OPS_IMPL (TransceiverFactory, Handshake); ENUM_CONVERSION_OPS_IMPL (TransceiverFactory, Handshake);
ENUM_CONVERSION_OPS_IMPL (TransceiverFactory, LineControl);
ENUM_CONVERSION_OPS_IMPL (TransceiverFactory, PTTMethod); ENUM_CONVERSION_OPS_IMPL (TransceiverFactory, PTTMethod);
ENUM_CONVERSION_OPS_IMPL (TransceiverFactory, TXAudioSource); ENUM_CONVERSION_OPS_IMPL (TransceiverFactory, TXAudioSource);
ENUM_CONVERSION_OPS_IMPL (TransceiverFactory, SplitMode); ENUM_CONVERSION_OPS_IMPL (TransceiverFactory, SplitMode);

View File

@ -21,10 +21,7 @@ class TransceiverFactory
: public QObject : public QObject
{ {
Q_OBJECT; Q_OBJECT;
Q_ENUMS (DataBits StopBits Handshake LineControl PTTMethod TXAudioSource SplitMode); Q_ENUMS (DataBits StopBits Handshake PTTMethod TXAudioSource SplitMode);
private:
Q_DISABLE_COPY (TransceiverFactory);
public: public:
// //
@ -70,7 +67,6 @@ public:
enum DataBits {seven_data_bits = 7, eight_data_bits}; enum DataBits {seven_data_bits = 7, eight_data_bits};
enum StopBits {one_stop_bit = 1, two_stop_bits}; enum StopBits {one_stop_bit = 1, two_stop_bits};
enum Handshake {handshake_none, handshake_XonXoff, handshake_hardware}; enum Handshake {handshake_none, handshake_XonXoff, handshake_hardware};
enum LineControl {no_control, force_low, force_high};
enum PTTMethod {PTT_method_VOX, PTT_method_CAT, PTT_method_DTR, PTT_method_RTS}; enum PTTMethod {PTT_method_VOX, PTT_method_CAT, PTT_method_DTR, PTT_method_RTS};
enum TXAudioSource {TX_audio_source_front, TX_audio_source_rear}; enum TXAudioSource {TX_audio_source_front, TX_audio_source_rear};
enum SplitMode {split_mode_none, split_mode_rig, split_mode_emulate}; enum SplitMode {split_mode_none, split_mode_rig, split_mode_emulate};
@ -91,6 +87,47 @@ public:
bool has_CAT_indirect_serial_PTT (QString const& name) const; // Can PTT via CAT port use DTR or RTS (OmniRig for example) bool has_CAT_indirect_serial_PTT (QString const& name) const; // Can PTT via CAT port use DTR or RTS (OmniRig for example)
bool has_asynchronous_CAT (QString const& name) const; // CAT asynchronous rather than polled bool has_asynchronous_CAT (QString const& name) const; // CAT asynchronous rather than polled
struct ParameterPack
{
QString rig_name; // from supported_transceivers () key
QString serial_port; // serial port device name or empty
QString network_port; // hostname:port or empty
int baud;
DataBits data_bits;
StopBits stop_bits;
Handshake handshake;
bool force_line_control;
bool dtr_high; // to power interface
bool rts_high; // to power interface
PTTMethod ptt_type; // "CAT" | "DTR" | "RTS" | "VOX"
TXAudioSource audio_source; // some rigs allow audio routing
// to Mic/Data connector
SplitMode split_mode; // how to support split TX mode
QString ptt_port; // serial port device name or special
// value "CAT"
int poll_interval; // in seconds for interfaces that
// require polling for state changes
bool operator == (ParameterPack const& rhs) const
{
return rhs.rig_name == rig_name
&& rhs.serial_port == serial_port
&& rhs.network_port == network_port
&& rhs.baud == baud
&& rhs.data_bits == data_bits
&& rhs.stop_bits == stop_bits
&& rhs.handshake == handshake
&& rhs.force_line_control == force_line_control
&& rhs.dtr_high == dtr_high
&& rhs.rts_high == rts_high
&& rhs.ptt_type == ptt_type
&& rhs.audio_source == audio_source
&& rhs.split_mode == split_mode
&& rhs.ptt_port == ptt_port
&& rhs.poll_interval == poll_interval;
}
};
// make a new Transceiver instance // make a new Transceiver instance
// //
// cat_port, cat_baud, cat_data_bits, cat_stop_bits, cat_handshake, // cat_port, cat_baud, cat_data_bits, cat_stop_bits, cat_handshake,
@ -100,26 +137,18 @@ public:
// PTT port and to some extent ptt_type are independent of interface // PTT port and to some extent ptt_type are independent of interface
// type // type
// //
std::unique_ptr<Transceiver> create (QString const& name // from supported_transceivers () key std::unique_ptr<Transceiver> create (ParameterPack const&, QThread * target_thread = nullptr);
, QString const& cat_port // serial port device name or empty
, int cat_baud
, DataBits cat_data_bits
, StopBits cat_stop_bits
, Handshake cat_handshake
, LineControl cat_dtr_control // to power interface
, LineControl cat_rts_control // to power inteface
, PTTMethod ptt_type // "CAT" | "DTR" | "RTS" | "VOX"
, TXAudioSource ptt_use_data_ptt // some rigs allow audio routing to Mic/Data connector
, SplitMode split_mode // how to support split TX mode
, QString const& ptt_port // serial port device name or special value "CAT"
, int poll_interval // in milliseconds for interfaces that require polling for parameter changes
, QThread * target_thread = nullptr
);
private: private:
Transceivers transceivers_; Transceivers transceivers_;
}; };
inline
bool operator != (TransceiverFactory::ParameterPack const& lhs, TransceiverFactory::ParameterPack const& rhs)
{
return !(lhs == rhs);
}
// //
// boilerplate routines to make enum types useable and debuggable in // boilerplate routines to make enum types useable and debuggable in
// Qt // Qt
@ -135,7 +164,6 @@ Q_DECLARE_METATYPE (TransceiverFactory::SplitMode);
ENUM_QDEBUG_OPS_DECL (TransceiverFactory, DataBits); ENUM_QDEBUG_OPS_DECL (TransceiverFactory, DataBits);
ENUM_QDEBUG_OPS_DECL (TransceiverFactory, StopBits); ENUM_QDEBUG_OPS_DECL (TransceiverFactory, StopBits);
ENUM_QDEBUG_OPS_DECL (TransceiverFactory, Handshake); ENUM_QDEBUG_OPS_DECL (TransceiverFactory, Handshake);
ENUM_QDEBUG_OPS_DECL (TransceiverFactory, LineControl);
ENUM_QDEBUG_OPS_DECL (TransceiverFactory, PTTMethod); ENUM_QDEBUG_OPS_DECL (TransceiverFactory, PTTMethod);
ENUM_QDEBUG_OPS_DECL (TransceiverFactory, TXAudioSource); ENUM_QDEBUG_OPS_DECL (TransceiverFactory, TXAudioSource);
ENUM_QDEBUG_OPS_DECL (TransceiverFactory, SplitMode); ENUM_QDEBUG_OPS_DECL (TransceiverFactory, SplitMode);
@ -144,7 +172,6 @@ ENUM_QDEBUG_OPS_DECL (TransceiverFactory, SplitMode);
ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, DataBits); ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, DataBits);
ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, StopBits); ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, StopBits);
ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, Handshake); ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, Handshake);
ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, LineControl);
ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, PTTMethod); ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, PTTMethod);
ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, TXAudioSource); ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, TXAudioSource);
ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, SplitMode); ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, SplitMode);
@ -152,7 +179,6 @@ ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, SplitMode);
ENUM_CONVERSION_OPS_DECL (TransceiverFactory, DataBits); ENUM_CONVERSION_OPS_DECL (TransceiverFactory, DataBits);
ENUM_CONVERSION_OPS_DECL (TransceiverFactory, StopBits); ENUM_CONVERSION_OPS_DECL (TransceiverFactory, StopBits);
ENUM_CONVERSION_OPS_DECL (TransceiverFactory, Handshake); ENUM_CONVERSION_OPS_DECL (TransceiverFactory, Handshake);
ENUM_CONVERSION_OPS_DECL (TransceiverFactory, LineControl);
ENUM_CONVERSION_OPS_DECL (TransceiverFactory, PTTMethod); ENUM_CONVERSION_OPS_DECL (TransceiverFactory, PTTMethod);
ENUM_CONVERSION_OPS_DECL (TransceiverFactory, TXAudioSource); ENUM_CONVERSION_OPS_DECL (TransceiverFactory, TXAudioSource);
ENUM_CONVERSION_OPS_DECL (TransceiverFactory, SplitMode); ENUM_CONVERSION_OPS_DECL (TransceiverFactory, SplitMode);

View File

@ -2131,7 +2131,7 @@ void MainWindow::processMessage(QString const& messages, int position, bool ctrl
// QString t3=t.mid(i1,i4); // QString t3=t.mid(i1,i4);
auto t3 = decodedtext.string (); auto t3 = decodedtext.string ();
auto t4 = t3.replace (" CQ DX ", " CQ_DX ").split (" ", QString::SkipEmptyParts); auto t4 = t3.replace (" CQ DX ", " CQ_DX ").split (" ", QString::SkipEmptyParts);
if(t4.size () <5) return; //Skip the rest if no decoded text if(t4.size () < 6) return; //Skip the rest if no decoded text
*/ */
auto t3 = decodedtext.string (); auto t3 = decodedtext.string ();
auto t4 = t3.replace (" CQ DX ", " CQ_DX ").split (" ", QString::SkipEmptyParts); auto t4 = t3.replace (" CQ DX ", " CQ_DX ").split (" ", QString::SkipEmptyParts);
@ -2141,8 +2141,14 @@ void MainWindow::processMessage(QString const& messages, int position, bool ctrl
QString hiscall; QString hiscall;
QString hisgrid; QString hisgrid;
decodedtext.deCallAndGrid(/*out*/hiscall,hisgrid); decodedtext.deCallAndGrid(/*out*/hiscall,hisgrid);
if (!Radio::is_callsign (hiscall)) if (!Radio::is_callsign (hiscall) // not interested if not from QSO partner
&& !(t4.size () == 7 // unless it is of the form
&& (t4.at (5) == m_baseCall // "<our-call> 73"
|| t4.at (5).startsWith (m_baseCall + '/')
|| t4.at (5).endsWith ('/' + m_baseCall))
&& t4.at (6) == "73"))
{ {
qDebug () << "Not processing message - hiscall:" << hiscall << "hisgrid:" << hisgrid;
return; return;
} }
@ -2207,6 +2213,9 @@ void MainWindow::processMessage(QString const& messages, int position, bool ctrl
return; return;
} }
// prior DX call (possible QSO partner)
auto qso_partner_base_call = Radio::base_callsign (ui->dxCallEntry-> text ().toUpper ().trimmed ());
auto base_call = Radio::base_callsign (hiscall); auto base_call = Radio::base_callsign (hiscall);
if (base_call != Radio::base_callsign (ui->dxCallEntry-> text ().toUpper ().trimmed ()) || base_call != hiscall) if (base_call != Radio::base_callsign (ui->dxCallEntry-> text ().toUpper ().trimmed ()) || base_call != hiscall)
{ {
@ -2234,13 +2243,13 @@ void MainWindow::processMessage(QString const& messages, int position, bool ctrl
if(dtext.contains (" " + m_baseCall + " ") if(dtext.contains (" " + m_baseCall + " ")
|| dtext.contains ("/" + m_baseCall + " ") || dtext.contains ("/" + m_baseCall + " ")
|| dtext.contains (" " + m_baseCall + "/") || dtext.contains (" " + m_baseCall + "/")
|| firstcall == "DE") || (firstcall == "DE" && ((t4.size () > 7 && t4.at(7) != "73") || t4.size () <= 7)))
{ {
if (t4.size () > 7 // enough fields for a normal msg if (t4.size () > 7 // enough fields for a normal msg
and !gridOK (t4.at (7))) // but no grid on end of msg and !gridOK (t4.at (7))) // but no grid on end of msg
{ {
QString r=t4.at (7); QString r=t4.at (7);
if(r.mid(0,3)=="RRR") { if(r.mid(0,3)=="RRR" || (r.toInt()==73)) {
m_ntx=5; m_ntx=5;
ui->txrb5->setChecked(true); ui->txrb5->setChecked(true);
if(ui->tabWidget->currentIndex()==1) { if(ui->tabWidget->currentIndex()==1) {
@ -2264,16 +2273,19 @@ void MainWindow::processMessage(QString const& messages, int position, bool ctrl
m_ntx=7; m_ntx=7;
ui->rbGenMsg->setChecked(true); ui->rbGenMsg->setChecked(true);
} }
} else if(r.toInt()==73) {
m_ntx=5;
ui->txrb5->setChecked(true);
if(ui->tabWidget->currentIndex()==1) {
ui->genMsg->setText(ui->tx5->currentText());
m_ntx=7;
ui->rbGenMsg->setChecked(true);
}
} }
} else { }
else if (t4.size () == 7 && t4.at (6) == "73") {
// 73 back to compound call holder
m_ntx=5;
ui->txrb5->setChecked(true);
if(ui->tabWidget->currentIndex()==1) {
ui->genMsg->setText(ui->tx5->currentText());
m_ntx=7;
ui->rbGenMsg->setChecked(true);
}
}
else {
m_ntx=2; m_ntx=2;
ui->txrb2->setChecked(true); ui->txrb2->setChecked(true);
if(ui->tabWidget->currentIndex()==1) { if(ui->tabWidget->currentIndex()==1) {
@ -2282,8 +2294,29 @@ void MainWindow::processMessage(QString const& messages, int position, bool ctrl
ui->rbGenMsg->setChecked(true); ui->rbGenMsg->setChecked(true);
} }
} }
} }
else if (firstcall == "DE" && t4.size () == 8 && t4.at (7) == "73") {
if (base_call == qso_partner_base_call) {
// 73 back to compound call holder
m_ntx=5;
ui->txrb5->setChecked(true);
if(ui->tabWidget->currentIndex()==1) {
ui->genMsg->setText(ui->tx5->currentText());
m_ntx=7;
ui->rbGenMsg->setChecked(true);
}
}
else {
// treat like a CQ/QRZ
m_ntx=1;
ui->txrb1->setChecked(true);
if(ui->tabWidget->currentIndex()==1) {
ui->genMsg->setText(ui->tx1->text());
m_ntx=7;
ui->rbGenMsg->setChecked(true);
}
}
}
else // myCall not in msg else // myCall not in msg
{ {
m_ntx=1; m_ntx=1;

View File

@ -67,7 +67,7 @@
inline inline
void throw_qstring (QString const& qs) void throw_qstring (QString const& qs)
{ {
throw std::runtime_error (qs.toLocal8Bit ().data ()); throw std::runtime_error {qs.toLocal8Bit ().constData ()};
} }
QString font_as_stylesheet (QFont const&); QString font_as_stylesheet (QFont const&);