Compare commits
222 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 17416144a8 | |||
| b8ff10fde9 | |||
| 6c741e21b5 | |||
| 47eec2dc0b | |||
| 6504a1f220 | |||
| 91a2a801f9 | |||
| 8c74499700 | |||
| 51c9dd2761 | |||
| dc70d53f5c | |||
| 3c2a5f98ec | |||
| 5c1f890095 | |||
| 29f759dafe | |||
| 90858f8964 | |||
| e6464e952d | |||
| 186fed04e3 | |||
| 6716eb771e | |||
| b8b2cf33c3 | |||
| 4025edfc0f | |||
| c5930a0aa3 | |||
| 9079d45587 | |||
| 223a4a2183 | |||
| 1584cf0404 | |||
| 5619824bd8 | |||
| e1e2ae50e8 | |||
| cc96daa26f | |||
| 5ba31d6df7 | |||
| 73346240e5 | |||
| 886e678531 | |||
| 526b72022e | |||
| a1864fa3f0 | |||
| b0c57029e8 | |||
| 2d5b41d4b7 | |||
| 21004a7b28 | |||
| 94f2f510fc | |||
| b6745c9e2e | |||
| 8c81b3b83a | |||
| 9ddfec5e72 | |||
| a5f0937cbb | |||
| 26f21cd70a | |||
| bb7e2544b5 | |||
| 4df65585a3 | |||
| f406553a5f | |||
| ecf14dcb5c | |||
| 5163a4a630 | |||
| 4af1a14961 | |||
| 842896d867 | |||
| 4406e99670 | |||
| 79785dbef5 | |||
| 1d1bc254a4 | |||
| 4ddccd99a1 | |||
| dd6f50a5a3 | |||
| 55c365b834 | |||
| b55f8ba5c5 | |||
| fd77e5440f | |||
| 19cb0b859d | |||
| 3d3be02830 | |||
| 55f04d3cd7 | |||
| 693eec8b4b | |||
| 9244ac08c6 | |||
| 8004c51ed2 | |||
| 52b67a5609 | |||
| 3e7c64e994 | |||
| d9d3e6fba3 | |||
| 09cea086c7 | |||
| a013e79eff | |||
| a3e004375e | |||
| f018a622ce | |||
| 565c031b28 | |||
| d88d8aa440 | |||
| 3a59599253 | |||
| 22e4b0891e | |||
| 8c564b6637 | |||
| 97763ed82d | |||
| a7849c5b72 | |||
| 04394273dd | |||
| 1052dd3f9f | |||
| 78ed799a8b | |||
| c0d08f87b6 | |||
| f92b3db5ea | |||
| cebed44ccd | |||
| d47d88681b | |||
| 1be0ee4f4f | |||
| 43d8986e0a | |||
| fd69dce0ae | |||
| b2fb3f31ac | |||
| db704858e2 | |||
| 1d11f0f8ba | |||
| b6bc50a8e1 | |||
| 5addf8f61f | |||
| 367966f5e6 | |||
| caaaa957b6 | |||
| c440d4c143 | |||
| 740c0b4c04 | |||
| f5ce9f0e30 | |||
| 0a6ec136f9 | |||
| d5e1f2822d | |||
| 3fffb45338 | |||
| 1d255b1ebf | |||
| bb97799bdf | |||
| cc6a719f6d | |||
| ccd380356a | |||
| 9f8583c8e2 | |||
| c9016d7378 | |||
| cd683f9bf7 | |||
| 6d7b187269 | |||
| 13308a38f8 | |||
| 804605e9e6 | |||
| 4e981da9c8 | |||
| 6436e163bd | |||
| 379a0fa78f | |||
| 1c4a2ab7d8 | |||
| 54f6bdb0af | |||
| 5a0e2a8b14 | |||
| 1a9c611195 | |||
| c70661461e | |||
| 1f866e14f1 | |||
| c0e8a791e6 | |||
| 74523985bb | |||
| 8d28ea345a | |||
| 33446297fa | |||
| 6f648d5a60 | |||
| f1f618bbcd | |||
| ac7da998a2 | |||
| b3cd705fb6 | |||
| 604e366d4a | |||
| 8d73805dce | |||
| 5c491dc10d | |||
| d611259a25 | |||
| 00f2d46167 | |||
| e4cba50144 | |||
| 440311a75b | |||
| 38fc98702b | |||
| 6201de8c12 | |||
| 4321bd5e75 | |||
| 9f7fd2e7e2 | |||
| 65a2411c46 | |||
| d076eedeb8 | |||
| 7da30200f5 | |||
| cac5f798a3 | |||
| 41fb7481ed | |||
| 09effda8e4 | |||
| eecf7f65c7 | |||
| 0618b1cc09 | |||
| 00685b9117 | |||
| a5a6c95a44 | |||
| 8612f2cd32 | |||
| 5fa60659f3 | |||
| 08629019d4 | |||
| 7293d1e796 | |||
| aff001ce96 | |||
| 31d80a9b1d | |||
| 9010fa07c0 | |||
| 121bb0fdb5 | |||
| 47a7c06854 | |||
| c4089c0af9 | |||
| 5c28d154ff | |||
| 6dfd037736 | |||
| 3767b347d9 | |||
| ff12fd2240 | |||
| 6a0fea1d0a | |||
| f11e02c966 | |||
| 0763ecfe37 | |||
| 4c3ed5c719 | |||
| 0064176736 | |||
| 67386a09c7 | |||
| 3c81108cc6 | |||
| 71ed0c1f10 | |||
| 20a44171e4 | |||
| 644633721f | |||
| 8529ef0982 | |||
| 8bba574963 | |||
| 80d798d7e3 | |||
| 23a554220b | |||
| 7e903349ae | |||
| 55810e63a6 | |||
| 9162d851d4 | |||
| 2022908509 | |||
| 2e2551519d | |||
| 18052773f1 | |||
| 51010e7310 | |||
| a3eaf1cf74 | |||
| c731fa51ce | |||
| a5f59019d3 | |||
| 4a87edc4c7 | |||
| 2da25c3171 | |||
| 87a6e10bd6 | |||
| cf9c74b99e | |||
| dae50d3a99 | |||
| 83268fbdaf | |||
| 3b2242e258 | |||
| c42c3b7ad1 | |||
| 9496d5ed81 | |||
| 83174bc6fa | |||
| d74850b8e1 | |||
| 2f1dca3c49 | |||
| 4a38778808 | |||
| 960b9b14d1 | |||
| 9e93745587 | |||
| 8aa28108ea | |||
| 4168e1937c | |||
| f4b640df75 | |||
| cf1cece11c | |||
| 59893f6dfa | |||
| ead5c225b5 | |||
| 4744952a1a | |||
| a30bff5589 | |||
| e7e2f8357f | |||
| 4ffa82f695 | |||
| 3e38067561 | |||
| 52177a0513 | |||
| f79ca47a93 | |||
| f0e30dc7b0 | |||
| d20fe46447 | |||
| aa2c41f124 | |||
| ad563c0aed | |||
| 60b58fb50f | |||
| ca79a450ca | |||
| 3c8c80a5d7 | |||
| fc43c7fbb4 | |||
| 353d75ac49 | |||
| 2d392dd676 | |||
| 18fac2e4ba |
+7
-5
@@ -1272,12 +1272,14 @@ if (NOT WIN32 AND NOT APPLE)
|
||||
#COMPONENT runtime
|
||||
)
|
||||
|
||||
execute_process(COMMAND ln -s /opt/js8call/bin/js8call ljs8call)
|
||||
IF("${CMAKE_INSTALL_PREFIX}" STREQUAL "/opt/js8call")
|
||||
execute_process(COMMAND ln -s /opt/js8call/bin/js8call ljs8call)
|
||||
|
||||
install(FILES
|
||||
${CMAKE_BINARY_DIR}/ljs8call DESTINATION /usr/bin/ RENAME js8call
|
||||
#COMPONENT runtime
|
||||
)
|
||||
install(FILES
|
||||
${CMAKE_BINARY_DIR}/ljs8call DESTINATION /usr/bin/ RENAME js8call
|
||||
#COMPONENT runtime
|
||||
)
|
||||
endif()
|
||||
endif (NOT WIN32 AND NOT APPLE)
|
||||
|
||||
|
||||
|
||||
+177
-55
@@ -454,6 +454,7 @@ private:
|
||||
Q_SLOT void on_delete_macro_push_button_clicked (bool = false);
|
||||
Q_SLOT void on_PTT_method_button_group_buttonClicked (int);
|
||||
Q_SLOT void on_station_message_line_edit_textChanged(QString const&);
|
||||
Q_SLOT void on_groups_line_edit_textChanged(QString const&);
|
||||
Q_SLOT void on_qth_message_line_edit_textChanged(QString const&);
|
||||
Q_SLOT void on_cq_message_line_edit_textChanged(QString const&);
|
||||
Q_SLOT void on_reply_message_line_edit_textChanged(QString const&);
|
||||
@@ -462,6 +463,9 @@ private:
|
||||
void delete_selected_macros (QModelIndexList);
|
||||
Q_SLOT void on_save_path_select_push_button_clicked (bool);
|
||||
Q_SLOT void on_azel_path_select_push_button_clicked (bool);
|
||||
Q_SLOT void on_sound_cq_path_select_push_button_clicked();
|
||||
Q_SLOT void on_sound_cq_path_test_push_button_clicked();
|
||||
Q_SLOT void on_sound_cq_path_reset_push_button_clicked();
|
||||
Q_SLOT void on_sound_dm_path_select_push_button_clicked();
|
||||
Q_SLOT void on_sound_dm_path_test_push_button_clicked();
|
||||
Q_SLOT void on_sound_dm_path_reset_push_button_clicked();
|
||||
@@ -516,6 +520,7 @@ private:
|
||||
QDir default_azel_directory_;
|
||||
QDir azel_directory_;
|
||||
|
||||
QString sound_cq_path_; // cq message sound file
|
||||
QString sound_dm_path_; // directed message sound file
|
||||
QString sound_am_path_; // alert message sound file
|
||||
|
||||
@@ -584,6 +589,7 @@ private:
|
||||
QString my_callsign_;
|
||||
QString my_grid_;
|
||||
QString my_station_;
|
||||
QStringList my_groups_;
|
||||
QString my_qth_;
|
||||
QString cq_;
|
||||
QString reply_;
|
||||
@@ -626,7 +632,7 @@ private:
|
||||
bool spot_to_reporting_networks_;
|
||||
bool transmit_directed_;
|
||||
bool autoreply_off_at_startup_;
|
||||
bool beacon_anywhere_;
|
||||
bool heartbeat_anywhere_;
|
||||
bool relay_disabled_;
|
||||
bool monitor_off_at_startup_;
|
||||
bool monitor_last_used_;
|
||||
@@ -636,11 +642,11 @@ private:
|
||||
bool insert_blank_;
|
||||
bool DXCC_;
|
||||
bool ppfx_;
|
||||
bool clear_DX_;
|
||||
bool clear_callsign_;
|
||||
bool miles_;
|
||||
bool quick_call_;
|
||||
bool disable_TX_on_73_;
|
||||
int beacon_;
|
||||
int heartbeat_;
|
||||
int watchdog_;
|
||||
bool TX_messages_;
|
||||
bool enable_VHF_features_;
|
||||
@@ -757,7 +763,7 @@ void Configuration::set_spot_to_reporting_networks (bool spot)
|
||||
|
||||
bool Configuration::transmit_directed() const { return m_->transmit_directed_; }
|
||||
bool Configuration::autoreply_off_at_startup () const {return m_->autoreply_off_at_startup_;}
|
||||
bool Configuration::beacon_anywhere() const { return m_->beacon_anywhere_;}
|
||||
bool Configuration::heartbeat_anywhere() const { return m_->heartbeat_anywhere_;}
|
||||
bool Configuration::relay_off() const { return m_->relay_disabled_; }
|
||||
bool Configuration::monitor_off_at_startup () const {return m_->monitor_off_at_startup_;}
|
||||
bool Configuration::monitor_last_used () const {return m_->rig_is_dummy_ || m_->monitor_last_used_;}
|
||||
@@ -767,11 +773,11 @@ bool Configuration::prompt_to_log () const {return m_->prompt_to_log_;}
|
||||
bool Configuration::insert_blank () const {return m_->insert_blank_;}
|
||||
bool Configuration::DXCC () const {return m_->DXCC_;}
|
||||
bool Configuration::ppfx() const {return m_->ppfx_;}
|
||||
bool Configuration::clear_DX () const {return m_->clear_DX_;}
|
||||
bool Configuration::clear_callsign () const {return m_->clear_callsign_;}
|
||||
bool Configuration::miles () const {return m_->miles_;}
|
||||
bool Configuration::quick_call () const {return m_->quick_call_;}
|
||||
bool Configuration::disable_TX_on_73 () const {return m_->disable_TX_on_73_;}
|
||||
int Configuration::beacon () const {return m_->beacon_;}
|
||||
int Configuration::heartbeat () const {return m_->heartbeat_;}
|
||||
int Configuration::watchdog () const {return m_->watchdog_;}
|
||||
bool Configuration::TX_messages () const {return m_->TX_messages_;}
|
||||
bool Configuration::enable_VHF_features () const {return m_->enable_VHF_features_;}
|
||||
@@ -808,6 +814,7 @@ QStringListModel * Configuration::macros () {return &m_->macros_;}
|
||||
QStringListModel const * Configuration::macros () const {return &m_->macros_;}
|
||||
QDir Configuration::save_directory () const {return m_->save_directory_;}
|
||||
QDir Configuration::azel_directory () const {return m_->azel_directory_;}
|
||||
QString Configuration::sound_cq_path() const {return m_->sound_cq_path_;}
|
||||
QString Configuration::sound_dm_path() const {return m_->sound_dm_path_;}
|
||||
QString Configuration::sound_am_path() const {return m_->sound_am_path_;}
|
||||
QString Configuration::rig_name () const {return m_->rig_params_.rig_name;}
|
||||
@@ -922,7 +929,7 @@ QString Configuration::my_grid() const
|
||||
if (m_->use_dynamic_info_ && m_->dynamic_grid_.size () >= 4) {
|
||||
grid = m_->dynamic_grid_;
|
||||
}
|
||||
return grid;
|
||||
return grid.trimmed();
|
||||
}
|
||||
|
||||
QString Configuration::my_station() const
|
||||
@@ -931,22 +938,40 @@ QString Configuration::my_station() const
|
||||
if(m_->use_dynamic_info_ && !m_->dynamic_qtc_.isEmpty()){
|
||||
station = m_->dynamic_qtc_;
|
||||
}
|
||||
return station;
|
||||
return station.trimmed();
|
||||
}
|
||||
|
||||
QSet<QString> Configuration::my_groups() const {
|
||||
return QSet<QString>::fromList(m_->my_groups_);
|
||||
}
|
||||
|
||||
void Configuration::addGroup(QString const &group){
|
||||
QSet<QString> groups = my_groups();
|
||||
groups.insert(group.trimmed());
|
||||
m_->my_groups_ = groups.toList();
|
||||
m_->write_settings();
|
||||
}
|
||||
|
||||
void Configuration::removeGroup(QString const &group){
|
||||
QSet<QString> groups = my_groups();
|
||||
groups.remove(group.trimmed());
|
||||
m_->my_groups_ = groups.toList();
|
||||
m_->write_settings();
|
||||
}
|
||||
|
||||
QString Configuration::my_qth() const
|
||||
{
|
||||
return m_->my_qth_;
|
||||
return m_->my_qth_.trimmed();
|
||||
}
|
||||
|
||||
QString Configuration::cq_message() const
|
||||
{
|
||||
return m_->cq_;
|
||||
return m_->cq_.trimmed();
|
||||
}
|
||||
|
||||
QString Configuration::reply_message() const
|
||||
{
|
||||
return m_->reply_;
|
||||
return m_->reply_.trimmed();
|
||||
}
|
||||
|
||||
int Configuration::callsign_aging() const
|
||||
@@ -1003,6 +1028,12 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T> void setUppercase(T* t){
|
||||
auto f = t->font();
|
||||
f.setCapitalization(QFont::AllUppercase);
|
||||
t->setFont(f);
|
||||
}
|
||||
|
||||
Configuration::impl::impl (Configuration * self, QDir const& temp_directory,
|
||||
QSettings * settings, QWidget * parent)
|
||||
: QDialog {parent}
|
||||
@@ -1036,6 +1067,7 @@ Configuration::impl::impl (Configuration * self, QDir const& temp_directory,
|
||||
, default_audio_output_device_selected_ {false}
|
||||
{
|
||||
ui_->setupUi (this);
|
||||
|
||||
// ui_->groupBox_6->setVisible(false); //### Temporary ??? ###
|
||||
|
||||
{
|
||||
@@ -1111,6 +1143,16 @@ Configuration::impl::impl (Configuration * self, QDir const& temp_directory,
|
||||
ui_->qth_message_line_edit->setValidator (new QRegExpValidator {message_alphabet, this});
|
||||
ui_->reply_message_line_edit->setValidator (new QRegExpValidator {message_alphabet, this});
|
||||
ui_->cq_message_line_edit->setValidator (new QRegExpValidator {message_alphabet, this});
|
||||
ui_->groups_line_edit->setValidator (new QRegExpValidator {message_alphabet, this});
|
||||
|
||||
setUppercase(ui_->callsign_line_edit);
|
||||
setUppercase(ui_->grid_line_edit);
|
||||
setUppercase(ui_->add_macro_line_edit);
|
||||
setUppercase(ui_->station_message_line_edit);
|
||||
setUppercase(ui_->qth_message_line_edit);
|
||||
setUppercase(ui_->reply_message_line_edit);
|
||||
setUppercase(ui_->cq_message_line_edit);
|
||||
setUppercase(ui_->groups_line_edit);
|
||||
|
||||
ui_->udp_server_port_spin_box->setMinimum (1);
|
||||
ui_->udp_server_port_spin_box->setMaximum (std::numeric_limits<port_type>::max ());
|
||||
@@ -1300,6 +1342,7 @@ void Configuration::impl::initialize_models ()
|
||||
ui_->callsign_aging_spin_box->setValue(callsign_aging_);
|
||||
ui_->activity_aging_spin_box->setValue(activity_aging_);
|
||||
ui_->station_message_line_edit->setText (my_station_.toUpper());
|
||||
ui_->groups_line_edit->setText(my_groups_.join(", "));
|
||||
ui_->qth_message_line_edit->setText (my_qth_.toUpper());
|
||||
ui_->cq_message_line_edit->setText(cq_.toUpper());
|
||||
ui_->reply_message_line_edit->setText (reply_.toUpper());
|
||||
@@ -1324,6 +1367,7 @@ void Configuration::impl::initialize_models ()
|
||||
ui_->PTT_method_button_group->button (rig_params_.ptt_type)->setChecked (true);
|
||||
ui_->save_path_display_label->setText (save_directory_.absolutePath ());
|
||||
ui_->azel_path_display_label->setText (azel_directory_.absolutePath ());
|
||||
ui_->sound_cq_path_display_label->setText(sound_cq_path_);
|
||||
ui_->sound_dm_path_display_label->setText(sound_dm_path_);
|
||||
ui_->sound_am_path_display_label->setText(sound_am_path_);
|
||||
ui_->CW_id_after_73_check_box->setChecked (id_after_73_);
|
||||
@@ -1331,7 +1375,7 @@ void Configuration::impl::initialize_models ()
|
||||
ui_->psk_reporter_check_box->setChecked (spot_to_reporting_networks_);
|
||||
ui_->transmit_directed_check_box->setChecked(transmit_directed_);
|
||||
ui_->autoreply_off_check_box->setChecked (autoreply_off_at_startup_);
|
||||
ui_->beacon_anywhere_check_box->setChecked(beacon_anywhere_);
|
||||
ui_->heartbeat_anywhere_check_box->setChecked(heartbeat_anywhere_);
|
||||
ui_->relay_disabled_check_box->setChecked(relay_disabled_);
|
||||
ui_->monitor_off_check_box->setChecked (monitor_off_at_startup_);
|
||||
ui_->monitor_last_used_check_box->setChecked (monitor_last_used_);
|
||||
@@ -1339,11 +1383,11 @@ void Configuration::impl::initialize_models ()
|
||||
ui_->stations_table_view->setEnabled(ui_->auto_switch_bands_check_box->isChecked());
|
||||
ui_->report_in_comments_check_box->setChecked (report_in_comments_);
|
||||
ui_->prompt_to_log_check_box->setChecked (prompt_to_log_);
|
||||
ui_->clear_DX_check_box->setChecked (clear_DX_);
|
||||
ui_->clear_callsign_check_box->setChecked (clear_callsign_);
|
||||
ui_->miles_check_box->setChecked (miles_);
|
||||
ui_->quick_call_check_box->setChecked (quick_call_);
|
||||
ui_->disable_TX_on_73_check_box->setChecked (disable_TX_on_73_);
|
||||
ui_->beacon_spin_box->setValue (beacon_);
|
||||
ui_->heartbeat_spin_box->setValue (heartbeat_);
|
||||
ui_->tx_watchdog_spin_box->setValue (watchdog_);
|
||||
ui_->enable_VHF_features_check_box->setChecked(enable_VHF_features_);
|
||||
ui_->decode_at_52s_check_box->setChecked(decode_at_52s_);
|
||||
@@ -1423,7 +1467,7 @@ void Configuration::impl::done (int r)
|
||||
{
|
||||
// do this here since window is still on screen at this point
|
||||
SettingsGroup g {settings_, "Configuration"};
|
||||
settings_->setValue ("window/geometry", saveGeometry ());
|
||||
settings_->setValue ("WindowGeometry", saveGeometry ());
|
||||
|
||||
QDialog::done (r);
|
||||
}
|
||||
@@ -1431,16 +1475,19 @@ void Configuration::impl::done (int r)
|
||||
void Configuration::impl::read_settings ()
|
||||
{
|
||||
SettingsGroup g {settings_, "Configuration"};
|
||||
restoreGeometry (settings_->value ("window/geometry").toByteArray ());
|
||||
setMinimumSize(800, 400);
|
||||
restoreGeometry (settings_->value ("WindowGeometry").toByteArray ());
|
||||
setMinimumSize(800, 400);
|
||||
|
||||
auto_switch_bands_ = settings_->value("AutoSwitchBands", false).toBool();
|
||||
my_callsign_ = settings_->value ("MyCall", QString {}).toString ();
|
||||
my_grid_ = settings_->value ("MyGrid", QString {}).toString ();
|
||||
my_station_ = settings_->value("MyStation", QString {}).toString();
|
||||
my_groups_ = settings_->value("MyGroups", QStringList{}).toStringList();
|
||||
callsign_aging_ = settings_->value ("CallsignAging", 0).toInt ();
|
||||
activity_aging_ = settings_->value ("ActivityAging", 2).toInt ();
|
||||
my_qth_ = settings_->value("MyQTH", QString {}).toString();
|
||||
cq_ = settings_->value("CQMessage", QString {"CQCQCQ"}).toString();
|
||||
cq_ = settings_->value("CQMessage", QString {"CQCQCQ <MYGRID4>"}).toString();
|
||||
reply_ = settings_->value("Reply", QString {"HW CPY?"}).toString();
|
||||
next_color_cq_ = color_cq_ = settings_->value("colorCQ","#66ff66").toString();
|
||||
next_color_mycall_ = color_mycall_ = settings_->value("colorMyCall","#ff6666").toString();
|
||||
@@ -1525,6 +1572,7 @@ void Configuration::impl::read_settings ()
|
||||
RxBandwidth_ = settings_->value ("RxBandwidth", 2500).toInt ();
|
||||
save_directory_ = settings_->value ("SaveDir", default_save_directory_.absolutePath ()).toString ();
|
||||
azel_directory_ = settings_->value ("AzElDir", default_azel_directory_.absolutePath ()).toString ();
|
||||
sound_cq_path_ = settings_->value ("SoundCQPath", "").toString ();
|
||||
sound_dm_path_ = settings_->value ("SoundDMPath", "").toString ();
|
||||
sound_am_path_ = settings_->value ("SoundAMPath", "").toString ();
|
||||
|
||||
@@ -1588,7 +1636,7 @@ void Configuration::impl::read_settings ()
|
||||
|
||||
transmit_directed_ = settings_->value ("TransmitDirected", true).toBool();
|
||||
autoreply_off_at_startup_ = settings_->value ("AutoreplyOFF", false).toBool ();
|
||||
beacon_anywhere_ = settings_->value("BeaconAnywhere", false).toBool();
|
||||
heartbeat_anywhere_ = settings_->value("BeaconAnywhere", false).toBool();
|
||||
relay_disabled_ = settings_->value ("RelayOFF", false).toBool ();
|
||||
monitor_off_at_startup_ = settings_->value ("MonitorOFF", false).toBool ();
|
||||
monitor_last_used_ = settings_->value ("MonitorLastUsed", false).toBool ();
|
||||
@@ -1645,12 +1693,12 @@ void Configuration::impl::read_settings ()
|
||||
insert_blank_ = settings_->value ("InsertBlank", false).toBool ();
|
||||
DXCC_ = settings_->value ("DXCCEntity", false).toBool ();
|
||||
ppfx_ = settings_->value ("PrincipalPrefix", false).toBool ();
|
||||
clear_DX_ = settings_->value ("ClearCallGrid", false).toBool ();
|
||||
clear_callsign_ = settings_->value ("ClearCallGrid", false).toBool ();
|
||||
miles_ = settings_->value ("Miles", false).toBool ();
|
||||
quick_call_ = settings_->value ("QuickCall", false).toBool ();
|
||||
disable_TX_on_73_ = settings_->value ("73TxDisable", false).toBool ();
|
||||
beacon_ = settings_->value ("TxBeacon", 30).toInt ();
|
||||
watchdog_ = settings_->value ("TxWatchdog", 0).toInt ();
|
||||
heartbeat_ = settings_->value ("TxBeacon", 30).toInt ();
|
||||
watchdog_ = settings_->value ("TxIdleWatchdog", 60).toInt ();
|
||||
if(watchdog_){
|
||||
watchdog_ = qMax(5, watchdog_);
|
||||
}
|
||||
@@ -1692,6 +1740,7 @@ void Configuration::impl::write_settings ()
|
||||
settings_->setValue ("MyCall", my_callsign_);
|
||||
settings_->setValue ("MyGrid", my_grid_);
|
||||
settings_->setValue ("MyStation", my_station_);
|
||||
settings_->setValue ("MyGroups", my_groups_);
|
||||
settings_->setValue ("MyQTH", my_qth_);
|
||||
settings_->setValue ("CQMessage", cq_);
|
||||
settings_->setValue ("Reply", reply_);
|
||||
@@ -1727,6 +1776,7 @@ void Configuration::impl::write_settings ()
|
||||
settings_->setValue ("PTTport", rig_params_.ptt_port);
|
||||
settings_->setValue ("SaveDir", save_directory_.absolutePath ());
|
||||
settings_->setValue ("AzElDir", azel_directory_.absolutePath ());
|
||||
settings_->setValue ("SoundCQPath", sound_cq_path_);
|
||||
settings_->setValue ("SoundDMPath", sound_dm_path_);
|
||||
settings_->setValue ("SoundAMPath", sound_am_path_);
|
||||
|
||||
@@ -1753,7 +1803,7 @@ void Configuration::impl::write_settings ()
|
||||
settings_->setValue ("Type2MsgGen", QVariant::fromValue (type_2_msg_gen_));
|
||||
settings_->setValue ("TransmitDirected", transmit_directed_);
|
||||
settings_->setValue ("AutoreplyOFF", autoreply_off_at_startup_);
|
||||
settings_->setValue ("BeaconAnywhere", beacon_anywhere_);
|
||||
settings_->setValue ("BeaconAnywhere", heartbeat_anywhere_);
|
||||
settings_->setValue ("RelayOFF", relay_disabled_);
|
||||
settings_->setValue ("MonitorOFF", monitor_off_at_startup_);
|
||||
settings_->setValue ("MonitorLastUsed", monitor_last_used_);
|
||||
@@ -1778,12 +1828,12 @@ void Configuration::impl::write_settings ()
|
||||
settings_->setValue ("InsertBlank", insert_blank_);
|
||||
settings_->setValue ("DXCCEntity", DXCC_);
|
||||
settings_->setValue ("PrincipalPrefix", ppfx_);
|
||||
settings_->setValue ("ClearCallGrid", clear_DX_);
|
||||
settings_->setValue ("ClearCallGrid", clear_callsign_);
|
||||
settings_->setValue ("Miles", miles_);
|
||||
settings_->setValue ("QuickCall", quick_call_);
|
||||
settings_->setValue ("73TxDisable", disable_TX_on_73_);
|
||||
settings_->setValue ("TxBeacon", beacon_);
|
||||
settings_->setValue ("TxWatchdog", watchdog_);
|
||||
settings_->setValue ("TxBeacon", heartbeat_);
|
||||
settings_->setValue ("TxIdleWatchdog", watchdog_);
|
||||
settings_->setValue ("Tx2QSO", TX_messages_);
|
||||
settings_->setValue ("CATForceDTR", rig_params_.force_dtr);
|
||||
settings_->setValue ("DTR", rig_params_.dtr_high);
|
||||
@@ -1871,7 +1921,8 @@ void Configuration::impl::set_rig_invariants ()
|
||||
// makes no sense with rig as "None"
|
||||
ui_->monitor_last_used_check_box->setEnabled (false);
|
||||
|
||||
ui_->CAT_control_group_box->setEnabled (false);
|
||||
ui_->catTab->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);
|
||||
@@ -1880,7 +1931,8 @@ void Configuration::impl::set_rig_invariants ()
|
||||
else
|
||||
{
|
||||
ui_->monitor_last_used_check_box->setEnabled (true);
|
||||
ui_->CAT_control_group_box->setEnabled (true);
|
||||
ui_->catTab->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);
|
||||
@@ -1931,7 +1983,9 @@ void Configuration::impl::set_rig_invariants ()
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ui_->CAT_serial_port_parameters_group_box->setEnabled (is_serial_CAT);
|
||||
|
||||
ui_->force_DTR_combo_box->setEnabled (is_serial_CAT
|
||||
&& (cat_port != ptt_port
|
||||
|| !ui_->PTT_DTR_radio_button->isEnabled ()
|
||||
@@ -1948,8 +2002,45 @@ void Configuration::impl::set_rig_invariants ()
|
||||
|| TransceiverFactory::basic_transceiver_name_ != rig);
|
||||
}
|
||||
|
||||
|
||||
QStringList splitGroups(QString groupsString, bool filter){
|
||||
QStringList groups;
|
||||
if(groupsString.isEmpty()){
|
||||
return groups;
|
||||
}
|
||||
|
||||
foreach(QString group, groupsString.split(",")){
|
||||
auto g = group.trimmed();
|
||||
if(filter && !g.startsWith("@")){
|
||||
continue;
|
||||
}
|
||||
groups.append(group.trimmed());
|
||||
}
|
||||
|
||||
return groups;
|
||||
}
|
||||
|
||||
bool Configuration::impl::validate ()
|
||||
{
|
||||
auto callsign = ui_->callsign_line_edit->text().toUpper().trimmed();
|
||||
if(!Varicode::isValidCallsign(callsign, nullptr) || callsign.startsWith("@")){
|
||||
MessageBox::critical_message (this, tr ("The callsign format you provided is not supported"));
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach(auto group, splitGroups(ui_->groups_line_edit->text(), false)){
|
||||
if(!Varicode::isCompoundCallsign(group)){
|
||||
MessageBox::critical_message (this, QString("%1 is not a valid group").arg(group));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
auto cq = ui_->cq_message_line_edit->text().toUpper().trimmed();
|
||||
if(!cq.isEmpty() && !(cq.startsWith("CQ") || cq.contains(callsign))){
|
||||
MessageBox::critical_message (this, QString("The CQ message format is invalid. It must either start with \"CQ\" or contain your callsign."));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ui_->sound_input_combo_box->currentIndex () < 0
|
||||
&& !QAudioDeviceInfo::availableDevices (QAudio::AudioInput).empty ())
|
||||
{
|
||||
@@ -2198,9 +2289,10 @@ void Configuration::impl::accept ()
|
||||
Q_ASSERT (audio_output_channel_ <= AudioDevice::Both);
|
||||
|
||||
auto_switch_bands_ = ui_->auto_switch_bands_check_box->isChecked();
|
||||
my_callsign_ = ui_->callsign_line_edit->text ();
|
||||
my_grid_ = ui_->grid_line_edit->text ();
|
||||
my_callsign_ = ui_->callsign_line_edit->text ().toUpper();
|
||||
my_grid_ = ui_->grid_line_edit->text ().toUpper();
|
||||
my_station_ = ui_->station_message_line_edit->text().toUpper();
|
||||
my_groups_ = splitGroups(ui_->groups_line_edit->text().toUpper().trimmed(), true);
|
||||
cq_ = ui_->cq_message_line_edit->text().toUpper();
|
||||
reply_ = ui_->reply_message_line_edit->text().toUpper();
|
||||
my_qth_ = ui_->qth_message_line_edit->text().toUpper();
|
||||
@@ -2217,7 +2309,7 @@ void Configuration::impl::accept ()
|
||||
tx_qsy_allowed_ = ui_->tx_qsy_check_box->isChecked ();
|
||||
transmit_directed_ = ui_->transmit_directed_check_box->isChecked();
|
||||
autoreply_off_at_startup_ = ui_->autoreply_off_check_box->isChecked ();
|
||||
beacon_anywhere_ = ui_->beacon_anywhere_check_box->isChecked();
|
||||
heartbeat_anywhere_ = ui_->heartbeat_anywhere_check_box->isChecked();
|
||||
relay_disabled_ = ui_->relay_disabled_check_box->isChecked();
|
||||
monitor_off_at_startup_ = ui_->monitor_off_check_box->isChecked ();
|
||||
monitor_last_used_ = ui_->monitor_last_used_check_box->isChecked ();
|
||||
@@ -2225,15 +2317,16 @@ void Configuration::impl::accept ()
|
||||
log_as_DATA_ = ui_->log_as_RTTY_check_box->isChecked ();
|
||||
report_in_comments_ = ui_->report_in_comments_check_box->isChecked ();
|
||||
prompt_to_log_ = ui_->prompt_to_log_check_box->isChecked ();
|
||||
clear_DX_ = ui_->clear_DX_check_box->isChecked ();
|
||||
clear_callsign_ = ui_->clear_callsign_check_box->isChecked ();
|
||||
miles_ = ui_->miles_check_box->isChecked ();
|
||||
quick_call_ = ui_->quick_call_check_box->isChecked ();
|
||||
disable_TX_on_73_ = ui_->disable_TX_on_73_check_box->isChecked ();
|
||||
beacon_ = ui_->beacon_spin_box->value ();
|
||||
heartbeat_ = ui_->heartbeat_spin_box->value ();
|
||||
watchdog_ = ui_->tx_watchdog_spin_box->value ();
|
||||
data_mode_ = static_cast<DataMode> (ui_->TX_mode_button_group->checkedId ());
|
||||
save_directory_ = ui_->save_path_display_label->text ();
|
||||
azel_directory_ = ui_->azel_path_display_label->text ();
|
||||
sound_cq_path_ = ui_->sound_cq_path_display_label->text();
|
||||
sound_dm_path_ = ui_->sound_dm_path_display_label->text();
|
||||
sound_am_path_ = ui_->sound_am_path_display_label->text();
|
||||
enable_VHF_features_ = ui_->enable_VHF_features_check_box->isChecked ();
|
||||
@@ -2338,14 +2431,23 @@ void Configuration::impl::reject ()
|
||||
|
||||
void Configuration::impl::on_font_push_button_clicked ()
|
||||
{
|
||||
next_font_ = QFontDialog::getFont (0, next_font_, this);
|
||||
|
||||
next_font_ = QFontDialog::getFont (0, next_font_, this
|
||||
, tr ("Font Chooser")
|
||||
#if QT_VERSION >= 0x050201
|
||||
, QFontDialog::DontUseNativeDialog
|
||||
#endif
|
||||
);
|
||||
ui_->font_push_button->setText(QString("Application Font (%1 %2)").arg(next_font_.family()).arg(next_font_.pointSize()));
|
||||
}
|
||||
|
||||
void Configuration::impl::on_tableFontButton_clicked ()
|
||||
{
|
||||
next_table_font_ = QFontDialog::getFont (0, next_table_font_, this);
|
||||
next_table_font_ = QFontDialog::getFont (0, next_table_font_, this
|
||||
, tr ("Font Chooser")
|
||||
#if QT_VERSION >= 0x050201
|
||||
, QFontDialog::DontUseNativeDialog
|
||||
#endif
|
||||
);
|
||||
ui_->tableFontButton->setText(QString("Table Font (%1 %2)").arg(next_table_font_.family()).arg(next_table_font_.pointSize()));
|
||||
}
|
||||
|
||||
@@ -2453,7 +2555,7 @@ void Configuration::impl::on_rxFontButton_clicked ()
|
||||
next_rx_text_font_ = QFontDialog::getFont (0, next_rx_text_font_ , this
|
||||
, tr ("Font Chooser")
|
||||
#if QT_VERSION >= 0x050201
|
||||
, 0
|
||||
, QFontDialog::DontUseNativeDialog
|
||||
#endif
|
||||
);
|
||||
ui_->rxFontButton->setText(QString("Font (%1 %2)").arg(next_rx_text_font_.family()).arg(next_rx_text_font_.pointSize()));
|
||||
@@ -2495,7 +2597,7 @@ void Configuration::impl::on_txFontButton_clicked ()
|
||||
next_tx_text_font_ = QFontDialog::getFont (0, next_tx_text_font_ , this
|
||||
, tr ("Font Chooser")
|
||||
#if QT_VERSION >= 0x050201
|
||||
, 0
|
||||
, QFontDialog::DontUseNativeDialog
|
||||
#endif
|
||||
);
|
||||
|
||||
@@ -2507,7 +2609,7 @@ void Configuration::impl::on_composeFontButton_clicked ()
|
||||
next_compose_text_font_ = QFontDialog::getFont (0, next_compose_text_font_ , this
|
||||
, tr ("Font Chooser")
|
||||
#if QT_VERSION >= 0x050201
|
||||
, 0
|
||||
, QFontDialog::DontUseNativeDialog
|
||||
#endif
|
||||
);
|
||||
ui_->composeFontButton->setText(QString("Font (%1 %2)").arg(next_compose_text_font_.family()).arg(next_compose_text_font_.pointSize()));
|
||||
@@ -2616,34 +2718,23 @@ void Configuration::impl::on_sound_output_combo_box_currentTextChanged (QString
|
||||
|
||||
void Configuration::impl::on_station_message_line_edit_textChanged(QString const &text)
|
||||
{
|
||||
QString upper = text.toUpper();
|
||||
if(text != upper){
|
||||
ui_->station_message_line_edit->setText (upper);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Configuration::impl::on_groups_line_edit_textChanged(QString const &text)
|
||||
{
|
||||
}
|
||||
|
||||
void Configuration::impl::on_qth_message_line_edit_textChanged(QString const &text)
|
||||
{
|
||||
QString upper = text.toUpper();
|
||||
if(text != upper){
|
||||
ui_->qth_message_line_edit->setText (upper);
|
||||
}
|
||||
}
|
||||
|
||||
void Configuration::impl::on_cq_message_line_edit_textChanged(QString const &text)
|
||||
{
|
||||
QString upper = text.toUpper();
|
||||
if(text != upper){
|
||||
ui_->cq_message_line_edit->setText (upper);
|
||||
}
|
||||
}
|
||||
|
||||
void Configuration::impl::on_reply_message_line_edit_textChanged(QString const &text)
|
||||
{
|
||||
QString upper = text.toUpper();
|
||||
if(text != upper){
|
||||
ui_->reply_message_line_edit->setText (upper);
|
||||
}
|
||||
}
|
||||
|
||||
void Configuration::impl::on_add_macro_line_edit_editingFinished ()
|
||||
@@ -2702,7 +2793,7 @@ void Configuration::impl::on_add_macro_push_button_clicked (bool /* checked */)
|
||||
{
|
||||
auto index = next_macros_.index (next_macros_.rowCount () - 1);
|
||||
ui_->macros_list_view->setCurrentIndex (index);
|
||||
next_macros_.setData (index, ui_->add_macro_line_edit->text ());
|
||||
next_macros_.setData (index, ui_->add_macro_line_edit->text ().toUpper());
|
||||
ui_->add_macro_line_edit->clear ();
|
||||
}
|
||||
}
|
||||
@@ -2884,6 +2975,37 @@ void Configuration::impl::on_azel_path_select_push_button_clicked (bool /* check
|
||||
}
|
||||
}
|
||||
|
||||
void Configuration::impl::on_sound_cq_path_select_push_button_clicked(){
|
||||
QStringList filters;
|
||||
filters << "Audio files (*.wav)"
|
||||
<< "Any files (*)";
|
||||
|
||||
QFileDialog fd {this, tr ("Sound File"), ui_->sound_cq_path_display_label->text ()};
|
||||
fd.setNameFilters(filters);
|
||||
|
||||
if (fd.exec ()) {
|
||||
if (fd.selectedFiles ().size ()) {
|
||||
if(rig_params_.ptt_type == TransceiverFactory::PTT_method_VOX){
|
||||
QMessageBox::warning(this, "Notifications Sounds Warning", "You have enabled notification sounds while using VOX. To avoid transmitting these notification sounds, please make sure your rig is using a different sound card than your system.");
|
||||
}
|
||||
ui_->sound_cq_path_display_label->setText(fd.selectedFiles().at(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Configuration::impl::on_sound_cq_path_test_push_button_clicked(){
|
||||
auto path = ui_->sound_cq_path_display_label->text();
|
||||
if(path.isEmpty()){
|
||||
return;
|
||||
}
|
||||
|
||||
QSound::play(path);
|
||||
}
|
||||
|
||||
void Configuration::impl::on_sound_cq_path_reset_push_button_clicked(){
|
||||
ui_->sound_cq_path_display_label->clear();
|
||||
}
|
||||
|
||||
void Configuration::impl::on_sound_dm_path_select_push_button_clicked(){
|
||||
QStringList filters;
|
||||
filters << "Audio files (*.wav)"
|
||||
|
||||
+7
-3
@@ -98,6 +98,9 @@ public:
|
||||
QString my_callsign () const;
|
||||
QString my_grid () const;
|
||||
QString my_station () const;
|
||||
QSet<QString> my_groups() const;
|
||||
void addGroup(QString const &group);
|
||||
void removeGroup(QString const &group);
|
||||
int activity_aging() const;
|
||||
int callsign_aging() const;
|
||||
QString my_qth () const;
|
||||
@@ -120,7 +123,7 @@ public:
|
||||
void set_spot_to_reporting_networks (bool);
|
||||
bool transmit_directed() const;
|
||||
bool autoreply_off_at_startup () const;
|
||||
bool beacon_anywhere() const;
|
||||
bool heartbeat_anywhere() const;
|
||||
bool relay_off() const;
|
||||
bool monitor_off_at_startup () const;
|
||||
bool monitor_last_used () const;
|
||||
@@ -130,11 +133,11 @@ public:
|
||||
bool insert_blank () const;
|
||||
bool DXCC () const;
|
||||
bool ppfx() const;
|
||||
bool clear_DX () const;
|
||||
bool clear_callsign () const;
|
||||
bool miles () const;
|
||||
bool quick_call () const;
|
||||
bool disable_TX_on_73 () const;
|
||||
int beacon () const;
|
||||
int heartbeat () const;
|
||||
int watchdog () const;
|
||||
bool TX_messages () const;
|
||||
bool split_mode () const;
|
||||
@@ -179,6 +182,7 @@ public:
|
||||
QStringListModel const * macros () const;
|
||||
QDir save_directory () const;
|
||||
QDir azel_directory () const;
|
||||
QString sound_cq_path() const;
|
||||
QString sound_dm_path() const;
|
||||
QString sound_am_path() const;
|
||||
QString rig_name () const;
|
||||
|
||||
+3239
-2787
File diff suppressed because it is too large
Load Diff
+8
-1
@@ -50,6 +50,13 @@ require this so normally you can choose not to install libusb-1.0-dev
|
||||
but if you have a SoftRock USB or similar SDR that uses a custom USB
|
||||
interface then it is required.
|
||||
|
||||
On Debian based systems, install requirements like:
|
||||
|
||||
sudo apt install git cmake clang gfortran \
|
||||
libfftw3-dev git libgfortran3 libusb-1.0-dev autoconf libtool \
|
||||
texinfo qt5-default qtmultimedia5-dev libqt5multimedia5-plugins libqt5serialport5-dev \
|
||||
libudev-dev pkg-config
|
||||
|
||||
The Hamlib library is required. Currently WSJT-X needs to be built
|
||||
using a forked version of the Hamlib git master. This fork contains
|
||||
patches not yet accepted by the Hamlib development team which are
|
||||
@@ -413,4 +420,4 @@ $ cmake --build . --target install
|
||||
|
||||
73
|
||||
Bill
|
||||
G4WJS.
|
||||
G4WJS.
|
||||
|
||||
@@ -291,6 +291,7 @@ qint64 Modulator::readData (char * data, qint64 maxSize)
|
||||
if (m_ic > i1) m_amp = 0.0;
|
||||
|
||||
sample=qRound(m_amp*qSin(m_phi));
|
||||
if(m_toneSpacing < 0) sample=qRound(m_amp*foxcom_.wave[m_ic]);
|
||||
samples = load(postProcessSample(sample), samples);
|
||||
++framesGenerated;
|
||||
++m_ic;
|
||||
|
||||
@@ -10,10 +10,12 @@ JS8Call is an experiment to test the feasibility of a digital mode with the robu
|
||||
|
||||
* For release announcements and discussion, join the JS8Call mailing list here: https://groups.io/g/js8call
|
||||
|
||||
* Documentation is available here: https://docs.google.com/document/d/159S4wqMUVdMA7qBgaSWmU-iDI4C9wd4CuWnetN68O9U/edit?pli=1#heading=h.kfnyge37yfr
|
||||
|
||||
|
||||
# Notice
|
||||
|
||||
JS8Call is a derivative of the WSJT-X application, restructured and redesigned for message passing using FT8 modulation. It is not supported by nor endorsed by the WSJT-X development group. While the WSJT-X group maintains copyright over the original work and code, JS8Call is a derivative work licensed under and in accordance with the terms of the GPLv3 license. The source code modifications are public and can be found in this repository: https://bitbucket.org/widefido/wsjtx/
|
||||
JS8Call is a derivative of the WSJT-X application, restructured and redesigned for message passing using FT8 modulation. It is not supported by nor endorsed by the WSJT-X development group. While the WSJT-X group maintains copyright over the original work and code, JS8Call is a derivative work licensed under and in accordance with the terms of the GPLv3 license. The source code modifications are public and can be found in this repository: https://bitbucket.org/widefido/js8call/
|
||||
|
||||
|
||||
# History
|
||||
@@ -33,3 +35,7 @@ JS8Call is a derivative of the WSJT-X application, restructured and redesigned f
|
||||
* August 12, 2018 - Version 0.4 released - (“leaked” on QRZ) - 500 testers
|
||||
* September 2, 2018 - Version 0.5 released - 3000 testers
|
||||
* September 14, 2018 - Version 0.6 released - 5000 testers
|
||||
* October 8, 2018 - Version 0.7 released - 6000 testers, name changed to JS8 & JS8Call
|
||||
* October 31, 2018 - Version 0.8 released - ~7000 testers
|
||||
* November 15, 2018 - Version 0.9 released - ~7500 testers
|
||||
* November 30, 2018 - Version 0.10 released - ~7800 testers
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
# Version number components
|
||||
set (WSJTX_VERSION_MAJOR 0)
|
||||
set (WSJTX_VERSION_MINOR 7)
|
||||
set (WSJTX_VERSION_PATCH 2)
|
||||
set (WSJTX_VERSION_MINOR 11)
|
||||
set (WSJTX_VERSION_PATCH 0)
|
||||
set (WSJTX_RC 0) # release candidate number, comment out or zero for development versions
|
||||
set (WSJTX_VERSION_IS_RELEASE 0) # set to 1 for final release build
|
||||
|
||||
@@ -31,7 +31,7 @@ CAboutDlg::CAboutDlg(QWidget *parent) :
|
||||
"community.<br /><br />"
|
||||
"JS8Call stands on the shoulder of giants...the takeoff angle "
|
||||
"is better up there.<br /><br />"
|
||||
"A special thanks goes out to the JS8Call development team:<br/><br/><strong>"
|
||||
"A special thanks goes out to:<br/><br/><strong>"
|
||||
"KC9QNE, "
|
||||
"KI6SSI, "
|
||||
"K0OG, "
|
||||
@@ -41,8 +41,8 @@ CAboutDlg::CAboutDlg(QWidget *parent) :
|
||||
"OH8STN, "
|
||||
"VA3OSO, "
|
||||
"VK1MIC, "
|
||||
"W0FW,</strong><br/><br/>and the many other amateur radio operators who have given "
|
||||
"JS8Call a chance.");
|
||||
"W0FW,</strong><br/><br/>and the many other amateur radio operators who have helped<br/>"
|
||||
"bring JS8Call into the world.");
|
||||
}
|
||||
|
||||
CAboutDlg::~CAboutDlg()
|
||||
|
||||
+29
-19
@@ -22,8 +22,9 @@ DecodedText::DecodedText (QString const& the_string, bool contest_mode, QString
|
||||
, message_ {string_.mid (column_qsoText + padding_).trimmed ()}
|
||||
, is_standard_ {false}
|
||||
, frameType_(Varicode::FrameUnknown)
|
||||
, isBeacon_(false)
|
||||
, isHeartbeat_(false)
|
||||
, isAlt_(false)
|
||||
, bits_{0}
|
||||
{
|
||||
if(message_.length() >= 1) {
|
||||
message_ = message_.left (21).remove (QRegularExpression {"[<>]"});
|
||||
@@ -51,21 +52,29 @@ DecodedText::DecodedText (QString const& the_string, bool contest_mode, QString
|
||||
grid_c_string += QByteArray {6 - grid_c_string.size (), ' '};
|
||||
is_standard_ = stdmsg_ (message_c_string.constData (), contest_mode_, grid_c_string.constData (), 22, 6);
|
||||
|
||||
// We're only going to unpack standard messages for CQs && beacons...
|
||||
// We're only going to unpack standard messages for CQs && pings...
|
||||
// TODO: jsherer - this is a hack for now...
|
||||
if(is_standard_){
|
||||
is_standard_ = QRegularExpression("^(CQ|DE|QRZ)\\s").match(message_).hasMatch();
|
||||
}
|
||||
}
|
||||
|
||||
bits_ = bits();
|
||||
|
||||
// don't even try to unpack -24dB frames...they are *very* likely to be false decodes...
|
||||
if(snr() <= -24){
|
||||
return;
|
||||
}
|
||||
|
||||
tryUnpack();
|
||||
}
|
||||
|
||||
DecodedText::DecodedText (QString const& js8callmessage):
|
||||
DecodedText::DecodedText (QString const& js8callmessage, int bits):
|
||||
frameType_(Varicode::FrameUnknown),
|
||||
message_(js8callmessage),
|
||||
isBeacon_(false),
|
||||
isAlt_(false)
|
||||
isHeartbeat_(false),
|
||||
isAlt_(false),
|
||||
bits_(bits)
|
||||
{
|
||||
is_standard_ = QRegularExpression("^(CQ|DE|QRZ)\\s").match(message_).hasMatch();
|
||||
|
||||
@@ -80,7 +89,11 @@ bool DecodedText::tryUnpack(){
|
||||
|
||||
bool unpacked = false;
|
||||
if(!unpacked){
|
||||
unpacked = tryUnpackBeacon();
|
||||
unpacked = tryUnpackData();
|
||||
}
|
||||
|
||||
if(!unpacked){
|
||||
unpacked = tryUnpackHeartbeat();
|
||||
}
|
||||
|
||||
if(!unpacked){
|
||||
@@ -91,14 +104,10 @@ bool DecodedText::tryUnpack(){
|
||||
unpacked = tryUnpackDirected();
|
||||
}
|
||||
|
||||
if(!unpacked){
|
||||
unpacked = tryUnpackData();
|
||||
}
|
||||
|
||||
return unpacked;
|
||||
}
|
||||
|
||||
bool DecodedText::tryUnpackBeacon(){
|
||||
bool DecodedText::tryUnpackHeartbeat(){
|
||||
QString m = message().trimmed();
|
||||
|
||||
// directed calls will always be 12+ chars and contain no spaces.
|
||||
@@ -109,17 +118,17 @@ bool DecodedText::tryUnpackBeacon(){
|
||||
bool isAlt = false;
|
||||
quint8 type = Varicode::FrameUnknown;
|
||||
quint8 bits3 = 0;
|
||||
QStringList parts = Varicode::unpackBeaconMessage(m, &type, &isAlt, &bits3);
|
||||
QStringList parts = Varicode::unpackHeartbeatMessage(m, &type, &isAlt, &bits3);
|
||||
|
||||
if(parts.isEmpty() || parts.length() < 2){
|
||||
return false;
|
||||
}
|
||||
|
||||
// Beacon Alt Type
|
||||
// Heartbeat Alt Type
|
||||
// ---------------
|
||||
// 1 0 BCN
|
||||
// 1 0 HB
|
||||
// 1 1 CQ
|
||||
isBeacon_ = true;
|
||||
isHeartbeat_ = true;
|
||||
isAlt_ = isAlt;
|
||||
extra_ = parts.length() < 3 ? "" : parts.at(2);
|
||||
|
||||
@@ -131,7 +140,7 @@ bool DecodedText::tryUnpackBeacon(){
|
||||
cmp.append(parts.at(1));
|
||||
}
|
||||
compound_ = cmp.join("/");
|
||||
message_ = QString("%1: %2 %3 ").arg(compound_).arg(isAlt ? Varicode::cqString(bits3) : "BEACON").arg(extra_);
|
||||
message_ = QString("%1: %2 %3 ").arg(compound_).arg(isAlt ? Varicode::cqString(bits3) : Varicode::hbString(bits3)).arg(extra_);
|
||||
frameType_ = type;
|
||||
return true;
|
||||
}
|
||||
@@ -197,6 +206,8 @@ bool DecodedText::tryUnpackDirected(){
|
||||
message_ = QString(parts.join(""));
|
||||
}
|
||||
|
||||
message_ = message_.replace("APRS: ", "APRS:");
|
||||
|
||||
directed_ = parts;
|
||||
frameType_ = type;
|
||||
return true;
|
||||
@@ -210,15 +221,14 @@ bool DecodedText::tryUnpackData(){
|
||||
return false;
|
||||
}
|
||||
|
||||
quint8 type = Varicode::FrameUnknown;
|
||||
QString data = Varicode::unpackDataMessage(m, &type);
|
||||
QString data = Varicode::unpackDataMessage(m);
|
||||
|
||||
if(data.isEmpty()){
|
||||
return false;
|
||||
}
|
||||
|
||||
message_ = data;
|
||||
frameType_ = type;
|
||||
frameType_ = Varicode::FrameData;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+5
-4
@@ -31,10 +31,10 @@ class DecodedText
|
||||
{
|
||||
public:
|
||||
explicit DecodedText (QString const& message, bool, QString const& my_grid);
|
||||
explicit DecodedText (QString const& js8callmessage);
|
||||
explicit DecodedText (QString const& js8callmessage, int bits);
|
||||
|
||||
bool tryUnpack();
|
||||
bool tryUnpackBeacon();
|
||||
bool tryUnpackHeartbeat();
|
||||
bool tryUnpackCompound();
|
||||
bool tryUnpackDirected();
|
||||
bool tryUnpackData();
|
||||
@@ -45,7 +45,7 @@ public:
|
||||
QString compoundCall() const { return compound_; }
|
||||
bool isCompound() const { return !compound_.isEmpty(); }
|
||||
|
||||
bool isBeacon() const { return isBeacon_; }
|
||||
bool isHeartbeat() const { return isHeartbeat_; }
|
||||
bool isAlt() const { return isAlt_; }
|
||||
|
||||
QStringList directedMessage() const { return directed_; }
|
||||
@@ -99,7 +99,7 @@ private:
|
||||
column_qsoText = 22 };
|
||||
|
||||
quint8 frameType_;
|
||||
bool isBeacon_;
|
||||
bool isHeartbeat_;
|
||||
bool isAlt_;
|
||||
QString compound_;
|
||||
QString extra_;
|
||||
@@ -109,6 +109,7 @@ private:
|
||||
bool contest_mode_;
|
||||
QString message_;
|
||||
bool is_standard_;
|
||||
int bits_;
|
||||
};
|
||||
|
||||
#endif // DECODEDTEXT_H
|
||||
|
||||
@@ -23,6 +23,10 @@
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <QDebug>
|
||||
#include <QCache>
|
||||
|
||||
QMap<QString, quint32> LOOKUP_CACHE;
|
||||
|
||||
Codeword JSC::codeword(quint32 index, bool separate, quint32 bytesize, quint32 s, quint32 c){
|
||||
QList<Codeword> out;
|
||||
@@ -52,9 +56,19 @@ QList<CodewordPair> JSC::compress(QString text){
|
||||
const quint32 s = 7;
|
||||
const quint32 c = pow(2, 4) - s;
|
||||
|
||||
foreach(QString w, text.split(" ", QString::SkipEmptyParts)){
|
||||
QString space(" ");
|
||||
|
||||
foreach(QString w, text.split(" ", QString::KeepEmptyParts)){
|
||||
bool ok = false;
|
||||
|
||||
bool isSpaceCharacter = false;
|
||||
|
||||
// if this is an empty part, it should be a space.
|
||||
if(w.isEmpty()){
|
||||
w = space;
|
||||
isSpaceCharacter = true;
|
||||
}
|
||||
|
||||
while(!w.isEmpty()){
|
||||
// this does both prefix and full match lookup
|
||||
auto index = lookup(w, &ok);
|
||||
@@ -63,10 +77,11 @@ QList<CodewordPair> JSC::compress(QString text){
|
||||
}
|
||||
|
||||
auto t = JSC::map[index];
|
||||
w = QString(w.mid(t.size));
|
||||
w = QString(w).mid(t.size);
|
||||
|
||||
bool isLast = w.isEmpty();
|
||||
out.append({ codeword(index, isLast, b, s, c), (quint32)t.size + (isLast ? 1 : 0) /* for the space that follows */});
|
||||
bool shouldAppendSpace = isLast && !isSpaceCharacter;
|
||||
out.append({ codeword(index, shouldAppendSpace, b, s, c), (quint32)t.size + (shouldAppendSpace ? 1 : 0) /* for the space that follows */});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,17 +107,23 @@ QString JSC::decompress(Codeword const& bitvec){
|
||||
|
||||
QList<quint64> bytes;
|
||||
QList<int> separators;
|
||||
auto iter = bitvec.begin();
|
||||
while(iter != bitvec.end()){
|
||||
quint64 byte = Varicode::bitsToInt(iter, 4);
|
||||
iter += 4;
|
||||
|
||||
int i = 0;
|
||||
int count = bitvec.count();
|
||||
while(i < count){
|
||||
auto b = bitvec.mid(i, 4);
|
||||
if(b.length() != 4){
|
||||
break;
|
||||
}
|
||||
quint64 byte = Varicode::bitsToInt(b);
|
||||
bytes.append(byte);
|
||||
i += 4;
|
||||
|
||||
if(byte < s){
|
||||
if(*iter){
|
||||
if(count - i > 0 && bitvec.at(i)){
|
||||
separators.append(bytes.length()-1);
|
||||
}
|
||||
iter += 1;
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,9 +137,17 @@ QString JSC::decompress(Codeword const& bitvec){
|
||||
k++;
|
||||
}
|
||||
|
||||
if(start + k >= bytes.length()){
|
||||
break;
|
||||
}
|
||||
j = j*s + bytes[start + k] + base[k];
|
||||
|
||||
out.append(QString(JSC::map[j].str));
|
||||
if(j >= (int)JSC::size){
|
||||
break;
|
||||
}
|
||||
auto word = QString(JSC::map[j].str);
|
||||
|
||||
out.append(word);
|
||||
if(!separators.isEmpty() && separators.first() == start + k){
|
||||
out.append(" ");
|
||||
separators.removeFirst();
|
||||
@@ -131,7 +160,19 @@ QString JSC::decompress(Codeword const& bitvec){
|
||||
}
|
||||
|
||||
quint32 JSC::lookup(QString w, bool * ok){
|
||||
return lookup(w.toLatin1().data(), ok);
|
||||
if(LOOKUP_CACHE.contains(w)){
|
||||
if(ok) *ok = true;
|
||||
return LOOKUP_CACHE[w];
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
quint32 result = lookup(w.toLatin1().data(), &found);
|
||||
if(found){
|
||||
LOOKUP_CACHE[w] = result;
|
||||
}
|
||||
|
||||
if(ok) *ok = found;
|
||||
return result;
|
||||
}
|
||||
|
||||
quint32 JSC::lookup(char const* b, bool *ok){
|
||||
@@ -167,11 +208,6 @@ quint32 JSC::lookup(char const* b, bool *ok){
|
||||
|
||||
// now that we have the first index in the list, let's just iterate through the list, comparing words along the way
|
||||
for(quint32 i = index; i < index + count; i++){
|
||||
// if we're no longer a prefix match, end.
|
||||
if(b[0] != JSC::list[i].str[0]){
|
||||
break;
|
||||
}
|
||||
|
||||
quint32 len = JSC::list[i].size;
|
||||
if(strncmp(b, JSC::list[i].str, len) == 0){
|
||||
if(ok) *ok = true;
|
||||
|
||||
@@ -39,8 +39,8 @@ public:
|
||||
static const Tuple map[262144];
|
||||
static const Tuple list[262144];
|
||||
|
||||
static const quint32 prefixSize = 68;
|
||||
static const Tuple prefix[68];
|
||||
static const quint32 prefixSize = 69;
|
||||
static const Tuple prefix[69];
|
||||
};
|
||||
|
||||
#endif // JSC_H
|
||||
|
||||
+9
-8
@@ -29,7 +29,7 @@ const Tuple JSC::list[262144] = {
|
||||
{"_", 1, 48},
|
||||
{"^", 1, 64},
|
||||
{"]", 1, 59},
|
||||
{"\\", 1, 67},
|
||||
{" ", 1, 67},
|
||||
{"[", 1, 58},
|
||||
{"ZZZZ", 4, 91474},
|
||||
{"ZZZ", 3, 70901},
|
||||
@@ -180080,8 +180080,8 @@ const Tuple JSC::list[262144] = {
|
||||
{"FTAD", 4, 112460},
|
||||
{"FTAC", 4, 68872},
|
||||
{"FTAB", 4, 72752},
|
||||
{"FT8CALL", 7, 69},
|
||||
{"FT8", 3, 68},
|
||||
{"\\", 1, 69},
|
||||
{"FT8", 3, 68},
|
||||
{"FSYW", 4, 155790},
|
||||
{"FSYT", 4, 186523},
|
||||
{"FSYS", 4, 69541},
|
||||
@@ -256665,7 +256665,7 @@ const Tuple JSC::list[262144] = {
|
||||
{"ALLCOCK", 7, 255496},
|
||||
{"ALLCLASSIFIEDS", 14, 205858},
|
||||
{"ALLCHIN", 7, 102391},
|
||||
{"ALLCALL", 7, 81},
|
||||
{"@ALLCALL", 7, 81},
|
||||
{"ALLBUSINESS", 11, 110217},
|
||||
{"ALLBRITTON", 10, 248655},
|
||||
{"ALLBRIGHT", 9, 249916},
|
||||
@@ -262164,10 +262164,10 @@ const Tuple JSC::list[262144] = {
|
||||
{"$", 1, 51},
|
||||
{"#", 1, 53},
|
||||
{"\"", 1, 26},
|
||||
{"!", 1, 28},
|
||||
{"!", 1, 28},
|
||||
};
|
||||
|
||||
const Tuple JSC::prefix[68] = {
|
||||
const Tuple JSC::prefix[69] = {
|
||||
{"!", 1, 262143},
|
||||
{"\"", 1, 262142},
|
||||
{"#", 1, 262141},
|
||||
@@ -262204,7 +262204,8 @@ const Tuple JSC::prefix[68] = {
|
||||
{"B", 13306, 233869},
|
||||
{"C", 17608, 216261},
|
||||
{"D", 13749, 202512},
|
||||
{"E", 12403, 190109},
|
||||
{"E", 12403, 190109},
|
||||
{"\\", 1, 180059},
|
||||
{"F", 11252, 178857},
|
||||
{"G", 10672, 168185},
|
||||
{"H", 9060, 159125},
|
||||
@@ -262227,7 +262228,7 @@ const Tuple JSC::prefix[68] = {
|
||||
{"Y", 4348, 2264},
|
||||
{"Z", 2254, 10},
|
||||
{"[", 1, 9},
|
||||
{"\\", 1, 8},
|
||||
{" ", 1, 8},
|
||||
{"]", 1, 7},
|
||||
{"^", 1, 6},
|
||||
{"_", 1, 5},
|
||||
|
||||
+4
-4
@@ -88,9 +88,9 @@ const Tuple JSC::map[262144] = {
|
||||
{"^", 1, 64},
|
||||
{"`", 1, 65},
|
||||
{"~", 1, 66},
|
||||
{"\\", 1, 67},
|
||||
{"FT8", 3, 68},
|
||||
{"FT8CALL", 7, 69},
|
||||
{" ", 1, 67},
|
||||
{"FT8", 3, 68},
|
||||
{"\\", 1, 69},
|
||||
{"JS8", 3, 70},
|
||||
{"JS8CALL", 7, 71},
|
||||
{"JSQSO", 5, 72},
|
||||
@@ -102,7 +102,7 @@ const Tuple JSC::map[262144] = {
|
||||
{"589", 3, 78},
|
||||
{"579", 3, 79},
|
||||
{"569", 3, 80},
|
||||
{"ALLCALL", 7, 81},
|
||||
{"@ALLCALL", 7, 81},
|
||||
{"BEACON", 6, 82},
|
||||
{"CQCQCQ", 6, 83},
|
||||
{"CPY?", 4, 84},
|
||||
|
||||
+9
-61
@@ -60,25 +60,15 @@ subroutine multimode_decoder(ss,id2,params,nfsample)
|
||||
if(mod(params%nranera,2).eq.1) ntrials=3*10**(params%nranera/2)
|
||||
if(params%nranera.eq.0) ntrials=0
|
||||
|
||||
nfail=0
|
||||
10 if (params%nagain) then
|
||||
open(13,file=trim(temp_dir)//'/decoded.txt',status='unknown', &
|
||||
position='append',iostat=ios)
|
||||
else
|
||||
open(13,file=trim(temp_dir)//'/decoded.txt',status='unknown',iostat=ios)
|
||||
endif
|
||||
10 nfail=0
|
||||
if(params%nmode.eq.8) then
|
||||
inquire(file=trim(temp_dir)//'/houndcallers.txt',exist=ex)
|
||||
if(.not.ex) then
|
||||
c2fox=' '
|
||||
g2fox=' '
|
||||
nsnrfox=-99
|
||||
nfreqfox=-99
|
||||
n30z=0
|
||||
nwrap=0
|
||||
nfox=0
|
||||
endif
|
||||
open(19,file=trim(temp_dir)//'/houndcallers.txt',status='unknown')
|
||||
c2fox=' '
|
||||
g2fox=' '
|
||||
nsnrfox=-99
|
||||
nfreqfox=-99
|
||||
n30z=0
|
||||
nwrap=0
|
||||
nfox=0
|
||||
endif
|
||||
|
||||
if(ios.ne.0) then
|
||||
@@ -103,35 +93,6 @@ subroutine multimode_decoder(ss,id2,params,nfsample)
|
||||
n30min=minval(n30fox(1:nfox))
|
||||
n30max=maxval(n30fox(1:nfox))
|
||||
endif
|
||||
j=0
|
||||
rewind 19
|
||||
if(nfox.eq.0) then
|
||||
endfile 19
|
||||
rewind 19
|
||||
else
|
||||
do i=1,nfox
|
||||
n=n30fox(i)
|
||||
if(n30max-n30fox(i).le.4) then
|
||||
j=j+1
|
||||
c2fox(j)=c2fox(i)
|
||||
g2fox(j)=g2fox(i)
|
||||
nsnrfox(j)=nsnrfox(i)
|
||||
nfreqfox(j)=nfreqfox(i)
|
||||
n30fox(j)=n
|
||||
m=n30max-n
|
||||
if(len(trim(g2fox(j))).eq.4) then
|
||||
call azdist(mygrid,g2fox(j),0.d0,nAz,nEl,nDmiles,nDkm, &
|
||||
nHotAz,nHotABetter)
|
||||
else
|
||||
nDkm=9999
|
||||
endif
|
||||
write(19,1004) c2fox(j),g2fox(j),nsnrfox(j),nfreqfox(j),nDkm,m
|
||||
1004 format(a12,1x,a4,i5,i6,i7,i3)
|
||||
endif
|
||||
enddo
|
||||
nfox=j
|
||||
flush(19)
|
||||
endif
|
||||
go to 800
|
||||
endif
|
||||
|
||||
@@ -255,8 +216,6 @@ subroutine multimode_decoder(ss,id2,params,nfsample)
|
||||
write(*,1010) nsynced,ndecoded
|
||||
1010 format('<DecodeFinished>',2i4)
|
||||
call flush(6)
|
||||
close(13)
|
||||
close(19)
|
||||
if(params%nmode.eq.4 .or. params%nmode.eq.65) close(14)
|
||||
|
||||
return
|
||||
@@ -369,9 +328,6 @@ contains
|
||||
write(*,1009) params%nutc,snr,dt,freq,csync,decoded,nft
|
||||
1009 format(i4.4,i4,f5.1,i5,1x,a2,1x,a22,i2)
|
||||
endif
|
||||
write(13,1011) params%nutc,nint(sync),snr,dt,float(freq),drift, &
|
||||
decoded,nft
|
||||
1011 format(i4.4,i4,i5,f6.2,f8.0,i4,3x,a22,' QRA64',i3)
|
||||
go to 100
|
||||
endif
|
||||
|
||||
@@ -415,9 +371,6 @@ contains
|
||||
write(*,1010) params%nutc,snr,dt,freq,csync,decoded,cflags
|
||||
1010 format(i4.4,i4,f5.1,i5,1x,a2,1x,a22,1x,a3)
|
||||
endif
|
||||
write(13,1012) params%nutc,nint(sync),snr,dt,float(freq),drift, &
|
||||
decoded,ft,nsum,nsmo
|
||||
1012 format(i4.4,i4,i5,f6.2,f8.0,i4,3x,a22,' JT65',3i3)
|
||||
|
||||
100 call flush(6)
|
||||
|
||||
@@ -443,8 +396,6 @@ contains
|
||||
!$omp critical(decode_results)
|
||||
write(*,1000) params%nutc,snr,dt,nint(freq),decoded
|
||||
1000 format(i4.4,i4,f5.1,i5,1x,'@ ',1x,a22)
|
||||
write(13,1002) params%nutc,nint(sync),snr,dt,freq,drift,decoded
|
||||
1002 format(i4.4,i4,i5,f6.1,f8.0,i4,3x,a22,' JT9')
|
||||
call flush(6)
|
||||
!$omp end critical(decode_results)
|
||||
select type(this)
|
||||
@@ -503,8 +454,6 @@ contains
|
||||
1000 format(i6.6,i4,f5.1,i5,' ~ ',1x,a22,1x,a2)
|
||||
if(i0.gt.0) write(*,1001) params%nutc,snr,dt,nint(freq),decoded0
|
||||
1001 format(i6.6,i4,f5.1,i5,' ~ ',1x,a37)
|
||||
write(13,1002) params%nutc,nint(sync),snr,dt,freq,0,decoded0
|
||||
1002 format(i6.6,i4,i5,f6.1,f8.0,i4,3x,a37,' FT8')
|
||||
|
||||
i1=index(decoded0,' ')
|
||||
i2=i1 + index(decoded0(i1+1:),' ')
|
||||
@@ -538,8 +487,7 @@ contains
|
||||
endif
|
||||
|
||||
call flush(6)
|
||||
call flush(13)
|
||||
|
||||
|
||||
select type(this)
|
||||
type is (counting_ft8_decoder)
|
||||
this%decoded = this%decoded + 1
|
||||
|
||||
@@ -1,126 +0,0 @@
|
||||
Quick Start for DXpedition Mode
|
||||
-------------------------------
|
||||
|
||||
These notes are intended for operators already familiar with WSJT-X
|
||||
and FT8 mode. QSOs between the Dxpedition ("Fox") and other stations
|
||||
("Hounds") are completed with as little as one transmission per Hound,
|
||||
as in the following examples:
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Fox (300-600 Hz) Hounds
|
||||
----------------------------------------------------------------------------
|
||||
1. CQ KH1DX AJ10
|
||||
2. KH1DX K1ABC FN42, KH1DX W9XYZ EN37, ...
|
||||
3. K1ABC KH1DX -13
|
||||
4. KH1DX K1ABC R-11
|
||||
5. K1ABC RR73; W9XYZ <KH1DX> -17
|
||||
6. KH1DX W9XYZ R-16
|
||||
7. W9XYZ RR73; G4AAA <KH1DX> -09
|
||||
8. ...
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Everybody sets dial frequency to an agreed number and uses CAT control
|
||||
with Split Operation (either *Rig* or *Fake It*). Fox transmits up to
|
||||
5 signals simultaneously, at audio frequencies 300, 360, ... 540
|
||||
Hz. Hounds make initial calls (e.g., line 2 above) anywhere in the
|
||||
range 1000 - 4000 Hz. They send "R+rpt" 350 Hz above the frequency
|
||||
where Fox called them.
|
||||
|
||||
|
||||
INSTRUCTIONS FOR FOX
|
||||
--------------------
|
||||
|
||||
1. Start WSJT-X in FT8 mode. Select *Fox* on the *Settings ->
|
||||
Advanced tab*. On the main window, check *Tx even/1st*, *Auto Seq*,
|
||||
and *Hold Tx Freq*; uncheck *Call 1st*. Set *Tx 300 Hz* and select
|
||||
Tab 3.
|
||||
|
||||
2. In Fox mode the left window (called "Band Activity" in normal FT8
|
||||
mode) is labeled "Stations calling DXpedition <MyCall>". It will be
|
||||
filled with a sorted list of calling Hounds. You can sort by Call,
|
||||
Grid, S/N, Distance, or Random order by using the comboBox at top
|
||||
right of Tab 3. You can limit the displayed Hound callsigns to those
|
||||
no stronger than *Max dB*. Fox might use this feature to discourage
|
||||
Hounds from engaging in a QRO arms race.
|
||||
|
||||
3. *N Slots* sets the number of simultaneous Fox signals to be used.
|
||||
Fox carries out as many as *N Slots* QSOs simultaneously.
|
||||
|
||||
4. *Repeats* sets the maximum number of repeat transmissions of the
|
||||
same message. A QSO is aborted when this number would be exceeded.
|
||||
|
||||
5. The *CQ* comboBox on Tab 3 offers a selection of directed CQ
|
||||
messages. *Reset* clears the QSO queue.
|
||||
|
||||
6. The Fox operator's main task is to select Hounds to be called and
|
||||
worked. The text box on Tab 3 holds the "QSO queue": a list of Hound
|
||||
calls to be worked. Hit Enter to select the top callsign from the
|
||||
sorted list of callers (left window), or double-click on any
|
||||
particular call. Either actiion moves that Hound into the "QSO
|
||||
queue".
|
||||
|
||||
7. The right window displays decodes of signals below 1000 Hz.
|
||||
Normally these should include only Hound messages containing "R+rpt"
|
||||
and Fox's own transmissions.
|
||||
|
||||
8. To get things started, toggle *Enable Tx* to red. If a Hound call
|
||||
is available in the QSO queue, that station will be called. If the
|
||||
QSO queue is empty, Fox calls CQ.
|
||||
|
||||
9. If you're using Nslots = 2 or higher, your signal no longer has
|
||||
a constant envelope. To avoid producing intermod sidebands you need
|
||||
to ensure linearity in your Tx system. One way to get things about right
|
||||
is to use the WSJT-X *Tune* button to generate a pure tone. Reduce the
|
||||
Tx audio level until your power output decreases by 10% or so. Use this
|
||||
level for your Fox transmissions.
|
||||
|
||||
NOTE: If you are generating Nslots signals, the average power in each one
|
||||
will be 1/Nslots^2 of its normal value for single-signal transmissions.
|
||||
|
||||
Nslots Relative dB
|
||||
-------------------
|
||||
1 0
|
||||
2 -6
|
||||
3 -9.5
|
||||
4 -12
|
||||
5 -14
|
||||
|
||||
|
||||
The following features are not yet implemented for Fox:
|
||||
|
||||
1. Enforce all required settings
|
||||
2. Tx message timeout
|
||||
3. Manual abort of selected QSO
|
||||
4. All Tx and Rx messages to all.txt
|
||||
5. Additional sort criteria for Hound calls
|
||||
6. Selectable timeout for keeping Hounds in the sorted list
|
||||
7. Display number of active callers
|
||||
8. Display QSO rate
|
||||
|
||||
|
||||
INSTRUCTIONS FOR HOUND
|
||||
----------------------
|
||||
|
||||
1. Start WSJT-X in FT8 mode. Select *Hound* On the *Settings ->
|
||||
Advanced* tab. On the main window check *Auto Seq* and uncheck *Tx
|
||||
even/1st*, *Call 1st*, and *Hold Tx Freq*. Set *Tx nnnn Hz* to some
|
||||
frequency between 1000 and 4000 Hz, and select *Tab 1*. Enter Fox's
|
||||
callsign and locator in DX Call and DX Grid, select Tx1, and start
|
||||
*Monitor*.
|
||||
|
||||
2. When you have copied Fox, hit *Enable Tx* to call him. You may
|
||||
keep calling until he answers. You may wish to move your TxFreq
|
||||
around, hoping to find a clear calling frequency.
|
||||
|
||||
3. When you are called by Fox with a signal report, your next
|
||||
transmission will automatically be sent as Tx3 ("R+rpt"). When Fox
|
||||
receives that message he responds with "RR73", and your QSO is
|
||||
complete!
|
||||
|
||||
|
||||
The following features are not yet implemented for Hound:
|
||||
|
||||
1. Force all required settings
|
||||
2. React properly to directed CQs from Fox
|
||||
3. Disable Tx2, 4, 5, 6
|
||||
4. For Tx1, enforce TxFreq >= 1000 Hz
|
||||
@@ -16,7 +16,7 @@ subroutine chkcrc12a(decoded,nbadcrc)
|
||||
i1Dec8BitBytes(10)=iand(i1Dec8BitBytes(10),128+64+32)
|
||||
i1Dec8BitBytes(11)=0
|
||||
icrc12=crc12(c_loc(i1Dec8BitBytes),11) !CRC12 computed from 75 msg bits
|
||||
! icrc12=xor(icrc12, 41) ! TODO: jsherer - could change the crc here
|
||||
icrc12=xor(icrc12, 42) ! TODO: jsherer - could change the crc here
|
||||
|
||||
nbadcrc=1
|
||||
if(ncrc12.eq.icrc12) nbadcrc=0
|
||||
|
||||
@@ -22,9 +22,9 @@ subroutine extractmessage174(decoded,msgreceived,ncrcflag)
|
||||
i1Dec8BitBytes(10)=iand(i1Dec8BitBytes(10),128+64+32)
|
||||
i1Dec8BitBytes(11)=0
|
||||
icrc12=crc12(c_loc(i1Dec8BitBytes),11) !CRC12 computed from 75 msg bits
|
||||
! icrc12=xor(icrc12, 41) ! TODO: jsherer - could change the crc here
|
||||
icrc12=xor(icrc12, 42) ! TODO: jsherer - could change the crc here
|
||||
|
||||
if(ncrc12.eq.icrc12 .or. sum(decoded(57:87)).eq.0) then !### Kludge ###
|
||||
if(ncrc12.eq.icrc12) then ! .or. sum(decoded(57:87)).eq.0) then !### Kludge ###
|
||||
! CRC12 checks out --- unpack 72-bit message
|
||||
do ibyte=1,12
|
||||
itmp=0
|
||||
|
||||
+49
-49
@@ -48,50 +48,50 @@ subroutine foxgen()
|
||||
|
||||
do n=1,nslots
|
||||
i3b=i3bit(n)
|
||||
if(i3b.eq.0) then
|
||||
msg=cmsg(n)(1:22) !Standard FT8 message
|
||||
else
|
||||
i1=index(cmsg(n),' ') !Special Fox message
|
||||
i2=index(cmsg(n),';')
|
||||
i3=index(cmsg(n),'<')
|
||||
i4=index(cmsg(n),'>')
|
||||
msg=cmsg(n)(1:i1)//cmsg(n)(i2+1:i3-2)//' '
|
||||
read(cmsg(n)(i4+2:i4+4),*) irpt
|
||||
endif
|
||||
call genft8(msg,mygrid,bcontest,0,msgsent,msgbits,itone)
|
||||
!if(i3b.eq.0) then
|
||||
msg=cmsg(n)(1:12) !Standard FT8 message
|
||||
!else
|
||||
! i1=index(cmsg(n),' ') !Special Fox message
|
||||
! i2=index(cmsg(n),';')
|
||||
! i3=index(cmsg(n),'<')
|
||||
! i4=index(cmsg(n),'>')
|
||||
! msg=cmsg(n)(1:i1)//cmsg(n)(i2+1:i3-2)//' '
|
||||
! read(cmsg(n)(i4+2:i4+4),*) irpt
|
||||
!endif
|
||||
call genft8(msg,mygrid,bcontest,i3b,msgsent,msgbits,itone)
|
||||
! print*,'Foxgen:',n,cmsg(n),msgsent
|
||||
|
||||
if(i3b.eq.1) then
|
||||
icrc10=crc10(c_loc(mycall),12)
|
||||
nrpt=irpt+30
|
||||
write(cbits,1001) msgbits(1:56),icrc10,nrpt,i3b,0
|
||||
1001 format(56b1.1,b10.10,b6.6,b3.3,b12.12)
|
||||
read(cbits,1002) msgbits
|
||||
1002 format(87i1)
|
||||
|
||||
cb88=cbits//'0'
|
||||
read(cb88,1003) i1Msg8BitBytes(1:11)
|
||||
1003 format(11b8)
|
||||
icrc12=crc12(c_loc(i1Msg8BitBytes),11)
|
||||
! icrc12=xor(icrc12, 41) ! TODO: jsherer - could change the crc here
|
||||
|
||||
write(cbits,1001) msgbits(1:56),icrc10,nrpt,i3b,icrc12
|
||||
read(cbits,1002) msgbits
|
||||
|
||||
call encode174(msgbits,codeword) !Encode the test message
|
||||
|
||||
! Message structure: S7 D29 S7 D29 S7
|
||||
itone(1:7)=icos7
|
||||
itone(36+1:36+7)=icos7
|
||||
itone(NN-6:NN)=icos7
|
||||
k=7
|
||||
do j=1,ND
|
||||
i=3*j -2
|
||||
k=k+1
|
||||
if(j.eq.30) k=k+7
|
||||
itone(k)=codeword(i)*4 + codeword(i+1)*2 + codeword(i+2)
|
||||
enddo
|
||||
endif
|
||||
!! if(i3b.eq.1) then
|
||||
!! icrc10=crc10(c_loc(mycall),12)
|
||||
!! nrpt=irpt+30
|
||||
!! write(cbits,1001) msgbits(1:56),icrc10,nrpt,i3b,0
|
||||
!! 1001 format(56b1.1,b10.10,b6.6,b3.3,b12.12)
|
||||
!! read(cbits,1002) msgbits
|
||||
!! 1002 format(87i1)
|
||||
!!
|
||||
!! cb88=cbits//'0'
|
||||
!! read(cb88,1003) i1Msg8BitBytes(1:11)
|
||||
!! 1003 format(11b8)
|
||||
!! icrc12=crc12(c_loc(i1Msg8BitBytes),11)
|
||||
!! ! icrc12=xor(icrc12, 41) ! TODO: jsherer - could change the crc here
|
||||
!!
|
||||
!! write(cbits,1001) msgbits(1:56),icrc10,nrpt,i3b,icrc12
|
||||
!! read(cbits,1002) msgbits
|
||||
!!
|
||||
!! call encode174(msgbits,codeword) !Encode the test message
|
||||
!!
|
||||
!! ! Message structure: S7 D29 S7 D29 S7
|
||||
!! itone(1:7)=icos7
|
||||
!! itone(36+1:36+7)=icos7
|
||||
!! itone(NN-6:NN)=icos7
|
||||
!! k=7
|
||||
!! do j=1,ND
|
||||
!! i=3*j -2
|
||||
!! k=k+1
|
||||
!! if(j.eq.30) k=k+7
|
||||
!! itone(k)=codeword(i)*4 + codeword(i+1)*2 + codeword(i+2)
|
||||
!! enddo
|
||||
!! endif
|
||||
|
||||
! Make copies of itone() and msgbits() for ft8sim
|
||||
itone2=itone
|
||||
@@ -117,13 +117,13 @@ subroutine foxgen()
|
||||
! call plotspec(1,wave) !Plot the spectrum
|
||||
|
||||
! Apply compression
|
||||
! rms=sqrt(dot_product(wave,wave)/kz)
|
||||
! wave=wave/rms
|
||||
! do i=1,NWAVE
|
||||
! wave(i)=h1(wave(i))
|
||||
! enddo
|
||||
! peak2=maxval(abs(wave))
|
||||
! wave=wave/peak2
|
||||
rms=sqrt(dot_product(wave,wave)/kz)
|
||||
wave=wave/rms
|
||||
do i=1,NWAVE
|
||||
wave(i)=h1(wave(i))
|
||||
enddo
|
||||
peak2=maxval(abs(wave))
|
||||
wave=wave/peak2
|
||||
|
||||
! call plotspec(2,wave) !Plot the spectrum
|
||||
|
||||
|
||||
@@ -5,15 +5,23 @@ subroutine ft8_downsample(dd,newdat,f0,c1)
|
||||
parameter (NMAX=15*12000,NSPS=1920)
|
||||
parameter (NFFT1=192000,NFFT2=3200) !192000/60 = 3200
|
||||
|
||||
logical newdat
|
||||
logical newdat,first
|
||||
complex c1(0:NFFT2-1)
|
||||
complex cx(0:NFFT1/2)
|
||||
real dd(NMAX),x(NFFT1)
|
||||
real dd(NMAX),x(NFFT1),taper(0:100)
|
||||
equivalence (x,cx)
|
||||
save cx
|
||||
data first/.true./
|
||||
save cx,first,taper
|
||||
|
||||
if(first) then
|
||||
pi=4.0*atan(1.0)
|
||||
do i=0,100
|
||||
taper(i)=0.5*(1.0+cos(i*pi/100))
|
||||
enddo
|
||||
first=.false.
|
||||
endif
|
||||
if(newdat) then
|
||||
! Data in dd have changed, recompute the long FFT
|
||||
! Data in dd have changed, recompute the long FFT
|
||||
x(1:NMAX)=dd
|
||||
x(NMAX+1:NFFT1)=0. !Zero-pad the x array
|
||||
call four2a(cx,NFFT1,1,-1,0) !r2c FFT to freq domain
|
||||
@@ -23,9 +31,9 @@ subroutine ft8_downsample(dd,newdat,f0,c1)
|
||||
df=12000.0/NFFT1
|
||||
baud=12000.0/NSPS
|
||||
i0=nint(f0/df)
|
||||
ft=f0+8.0*baud
|
||||
ft=f0+8.5*baud
|
||||
it=min(nint(ft/df),NFFT1/2)
|
||||
fb=f0-1.0*baud
|
||||
fb=f0-1.5*baud
|
||||
ib=max(1,nint(fb/df))
|
||||
k=0
|
||||
c1=0.
|
||||
@@ -33,6 +41,8 @@ subroutine ft8_downsample(dd,newdat,f0,c1)
|
||||
c1(k)=cx(i)
|
||||
k=k+1
|
||||
enddo
|
||||
c1(0:100)=c1(0:100)*taper(100:0:-1)
|
||||
c1(k-1-100:k-1)=c1(k-1-100:k-1)*taper
|
||||
c1=cshift(c1,i0-ib)
|
||||
call four2a(c1,NFFT2,1,1,1) !c2c FFT back to time domain
|
||||
fac=1.0/sqrt(float(NFFT1)*NFFT2)
|
||||
|
||||
+4
-3
@@ -28,7 +28,7 @@ subroutine ft8b(dd0,newdat,nQSOProgress,nfqso,nftx,ndepth,lapon,lapcqonly, &
|
||||
integer nappasses(0:5) !Number of decoding passes to use for each QSO state
|
||||
integer naptypes(0:5,4) ! (nQSOProgress, decoding pass) maximum of 4 passes for now
|
||||
integer*1, target:: i1hiscall(12)
|
||||
complex cd0(3200)
|
||||
complex cd0(0:3199)
|
||||
complex ctwk(32)
|
||||
complex csymb(32)
|
||||
logical first,newdat,lsubtract,lapon,lapcqonly,nagain
|
||||
@@ -126,7 +126,8 @@ subroutine ft8b(dd0,newdat,nQSOProgress,nfqso,nftx,ndepth,lapon,lapcqonly, &
|
||||
do k=1,NN
|
||||
i1=ibest+(k-1)*32
|
||||
csymb=cmplx(0.0,0.0)
|
||||
if( i1.ge.1 .and. i1+31 .le. NP2 ) csymb=cd0(i1:i1+31)
|
||||
!if( i1.ge.1 .and. i1+31 .le. NP2 ) csymb=cd0(i1:i1+31)
|
||||
if( i1.ge.0 .and. i1+31 .le. NP2-1 ) csymb=cd0(i1:i1+31)
|
||||
call four2a(csymb,32,1,-1,1)
|
||||
s2(0:7,k)=abs(csymb(1:8))/1e3
|
||||
enddo
|
||||
@@ -181,7 +182,7 @@ subroutine ft8b(dd0,newdat,nQSOProgress,nfqso,nftx,ndepth,lapon,lapcqonly, &
|
||||
bmetap(i2)=r2
|
||||
bmetap(i1)=r1
|
||||
! Max log metric
|
||||
psl=log(ps)
|
||||
psl=log(ps+1e-32)
|
||||
r1=max(psl(1),psl(3),psl(5),psl(7))-max(psl(0),psl(2),psl(4),psl(6))
|
||||
r2=max(psl(2),psl(3),psl(6),psl(7))-max(psl(0),psl(1),psl(4),psl(5))
|
||||
r4=max(psl(4),psl(5),psl(6),psl(7))-max(psl(0),psl(1),psl(2),psl(3))
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@ subroutine genft8(msg,mygrid,bcontest,i3bit,msgsent,msgbits,itone)
|
||||
i1Msg8BitBytes(10)=iand(i1Msg8BitBytes(10),128+64+32)
|
||||
i1Msg8BitBytes(11)=0
|
||||
icrc12=crc12(c_loc(i1Msg8BitBytes),11)
|
||||
! icrc12=xor(icrc12, 41) ! TODO: jsherer - could change the crc here
|
||||
icrc12=xor(icrc12, 42) ! TODO: jsherer - could change the crc here
|
||||
|
||||
! For reference, here's how to check the CRC
|
||||
! i1Msg8BitBytes(10)=icrc12/256
|
||||
|
||||
@@ -65,7 +65,7 @@ write(*,*) "niter= ",max_iterations," s= ",s
|
||||
allocate ( codeword(N), decoded(K), message(K) )
|
||||
allocate ( rxdata(N), llr(N) )
|
||||
|
||||
msg="K1JT K9AN EN50"
|
||||
msg="0123456789012"
|
||||
! msg="G4WJS K9AN EN50"
|
||||
call packmsg(msg,i4Msg6BitWords,itype,.false.) !Pack into 12 6-bit bytes
|
||||
call unpackmsg(i4Msg6BitWords,msgsent,.false.,grid) !Unpack to get msgsent
|
||||
@@ -91,7 +91,7 @@ allocate ( rxdata(N), llr(N) )
|
||||
|
||||
i1Msg8BitBytes(10:11)=0
|
||||
checksum = crc12 (c_loc (i1Msg8BitBytes), 11)
|
||||
! checksum = xor(checksum, 41) ! TODO: jsherer - could change the crc here
|
||||
checksum = xor(checksum, 42) ! TODO: jsherer - could change the crc here
|
||||
! For reference, the next 3 lines show how to check the CRC
|
||||
i1Msg8BitBytes(10)=checksum/256
|
||||
i1Msg8BitBytes(11)=iand (checksum,255)
|
||||
|
||||
+12
-19
@@ -37,11 +37,6 @@ subroutine sync8(dd,nfa,nfb,syncmin,nfqso,s,candidate,ncand,sbase)
|
||||
savg=savg + s(1:NH1,j) !Average spectrum
|
||||
enddo
|
||||
call baseline(savg,nfa,nfb,sbase)
|
||||
! savg=savg/NHSYM
|
||||
! do i=1,NH1
|
||||
! write(51,3051) i*df,savg(i),db(savg(i))
|
||||
!3051 format(f10.3,e12.3,f12.3)
|
||||
! enddo
|
||||
|
||||
ia=max(1,nint(nfa/df))
|
||||
ib=nint(nfb/df)
|
||||
@@ -49,6 +44,9 @@ subroutine sync8(dd,nfa,nfb,syncmin,nfqso,s,candidate,ncand,sbase)
|
||||
nfos=NFFT1/NSPS ! # frequency bin oversampling factor
|
||||
jstrt=0.5/tstep
|
||||
|
||||
candidate0=0.
|
||||
k=0
|
||||
|
||||
do i=ia,ib
|
||||
do j=-JZ,+JZ
|
||||
ta=0.
|
||||
@@ -95,20 +93,18 @@ subroutine sync8(dd,nfa,nfb,syncmin,nfqso,s,candidate,ncand,sbase)
|
||||
iz=ib-ia+1
|
||||
call indexx(red(ia:ib),iz,indx)
|
||||
ibase=indx(nint(0.40*iz)) - 1 + ia
|
||||
if(ibase.lt.1) ibase=1
|
||||
if(ibase.gt.nh1) ibase=nh1
|
||||
base=red(ibase)
|
||||
red=red/base
|
||||
|
||||
candidate0=0.
|
||||
k=0
|
||||
do i=1,200
|
||||
ji=iz+1-1
|
||||
if(ji.eq.0) exit
|
||||
n=ia + indx(ji) - 1
|
||||
if(red(n).lt.syncmin) exit
|
||||
if(k.lt.200) k=k+1
|
||||
candidate0(1,k)=n*df
|
||||
candidate0(2,k)=(jpeak(n)-1)*tstep
|
||||
candidate0(3,k)=red(n)
|
||||
do i=1,min(200,iz)
|
||||
n=ia + indx(iz+1-i) - 1
|
||||
if(red(n).lt.syncmin.or.isnan(red(n)).or.k.eq.200) exit
|
||||
k=k+1
|
||||
candidate0(1,k)=n*df
|
||||
candidate0(2,k)=(jpeak(n)-1)*tstep
|
||||
candidate0(3,k)=red(n)
|
||||
enddo
|
||||
ncand=k
|
||||
|
||||
@@ -123,9 +119,6 @@ subroutine sync8(dd,nfa,nfb,syncmin,nfqso,s,candidate,ncand,sbase)
|
||||
if(candidate0(3,i).lt.candidate0(3,j)) candidate0(3,i)=0.
|
||||
endif
|
||||
enddo
|
||||
! write(*,3001) i,candidate0(1,i-1),candidate0(1,i),candidate0(3,i-1), &
|
||||
! candidate0(3,i)
|
||||
!3001 format(i2,4f8.1)
|
||||
endif
|
||||
enddo
|
||||
|
||||
|
||||
+9
-18
@@ -100,6 +100,7 @@ void ADIF::load()
|
||||
add (extractField (record, "CALL")
|
||||
, extractField (record, "BAND")
|
||||
, extractField (record, "MODE")
|
||||
, extractField (record, "SUBMODE")
|
||||
, extractField (record, "QSO_DATE"));
|
||||
}
|
||||
inputFile.close ();
|
||||
@@ -107,12 +108,13 @@ void ADIF::load()
|
||||
}
|
||||
|
||||
|
||||
void ADIF::add(QString const& call, QString const& band, QString const& mode, QString const& date)
|
||||
void ADIF::add(QString const& call, QString const& band, QString const& mode, QString const& submode, QString const& date)
|
||||
{
|
||||
QSO q;
|
||||
q.call = call;
|
||||
q.band = band;
|
||||
q.mode = mode;
|
||||
q.submode = submode;
|
||||
q.date = date;
|
||||
if (q.call.size ())
|
||||
{
|
||||
@@ -121,8 +123,8 @@ void ADIF::add(QString const& call, QString const& band, QString const& mode, QS
|
||||
}
|
||||
}
|
||||
|
||||
// return true if in the log same band and mode (where JT65 == JT9)
|
||||
bool ADIF::match(QString const& call, QString const& band, QString const& mode) const
|
||||
// return true if in the log same band
|
||||
bool ADIF::match(QString const& call, QString const& band) const
|
||||
{
|
||||
QList<QSO> qsos = _data.values(call);
|
||||
if (qsos.size()>0)
|
||||
@@ -134,20 +136,6 @@ bool ADIF::match(QString const& call, QString const& band, QString const& mode)
|
||||
|| (band=="")
|
||||
|| (q.band==""))
|
||||
{
|
||||
if (
|
||||
(
|
||||
((mode.compare("JT65",Qt::CaseInsensitive)==0) ||
|
||||
(mode.compare("JT9",Qt::CaseInsensitive)==0) ||
|
||||
(mode.compare("FT8",Qt::CaseInsensitive)==0))
|
||||
&&
|
||||
((q.mode.compare("JT65",Qt::CaseInsensitive)==0) ||
|
||||
(q.mode.compare("JT9",Qt::CaseInsensitive)==0) ||
|
||||
(q.mode.compare("FT8",Qt::CaseInsensitive)==0))
|
||||
)
|
||||
|| (mode.compare(q.mode,Qt::CaseInsensitive)==0)
|
||||
|| (mode=="")
|
||||
|| (q.mode=="")
|
||||
)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -174,7 +162,7 @@ int ADIF::getCount() const
|
||||
return _data.size();
|
||||
}
|
||||
|
||||
QByteArray ADIF::QSOToADIF(QString const& hisCall, QString const& hisGrid, QString const& mode
|
||||
QByteArray ADIF::QSOToADIF(QString const& hisCall, QString const& hisGrid, QString const& mode, QString const& submode
|
||||
, QString const& rptSent, QString const& rptRcvd, QDateTime const& dateTimeOn
|
||||
, QDateTime const& dateTimeOff, QString const& band, QString const& comments
|
||||
, QString const& name, QString const& strDialFreq, QString const& m_myCall
|
||||
@@ -184,6 +172,9 @@ QByteArray ADIF::QSOToADIF(QString const& hisCall, QString const& hisGrid, QStri
|
||||
t = "<call:" + QString::number(hisCall.length()) + ">" + hisCall;
|
||||
t += " <gridsquare:" + QString::number(hisGrid.length()) + ">" + hisGrid;
|
||||
t += " <mode:" + QString::number(mode.length()) + ">" + mode;
|
||||
if(!submode.isEmpty()){
|
||||
t += " <submode:" + QString::number(submode.length()) + ">" + submode;
|
||||
}
|
||||
t += " <rst_sent:" + QString::number(rptSent.length()) + ">" + rptSent;
|
||||
t += " <rst_rcvd:" + QString::number(rptRcvd.length()) + ">" + rptRcvd;
|
||||
t += " <qso_date:8>" + dateTimeOn.date().toString("yyyyMMdd");
|
||||
|
||||
+4
-4
@@ -23,15 +23,15 @@ class ADIF
|
||||
public:
|
||||
void init(QString const& filename);
|
||||
void load();
|
||||
void add(QString const& call, QString const& band, QString const& mode, QString const& date);
|
||||
bool match(QString const& call, QString const& band, QString const& mode) const;
|
||||
void add(QString const& call, QString const& band, QString const& mode, const QString &submode, QString const& date);
|
||||
bool match(QString const& call, QString const& band) const;
|
||||
QList<QString> getCallList() const;
|
||||
int getCount() const;
|
||||
|
||||
// open ADIF file and append the QSO details. Return true on success
|
||||
bool addQSOToFile(QByteArray const& ADIF_record);
|
||||
|
||||
QByteArray QSOToADIF(QString const& hisCall, QString const& hisGrid, QString const& mode, QString const& rptSent
|
||||
QByteArray QSOToADIF(QString const& hisCall, QString const& hisGrid, QString const& mode, QString const& submode, QString const& rptSent
|
||||
, QString const& rptRcvd, QDateTime const& dateTimeOn, QDateTime const& dateTimeOff
|
||||
, QString const& band, QString const& comments, QString const& name
|
||||
, QString const& strDialFreq, QString const& m_myCall, QString const& m_myGrid
|
||||
@@ -41,7 +41,7 @@ class ADIF
|
||||
private:
|
||||
struct QSO
|
||||
{
|
||||
QString call,band,mode,date;
|
||||
QString call,band,mode,submode,date;
|
||||
};
|
||||
|
||||
QMultiHash<QString, QSO> _data;
|
||||
|
||||
+7
-21
@@ -33,19 +33,6 @@ void LogBook::init()
|
||||
_log.load();
|
||||
|
||||
_setAlreadyWorkedFromLog();
|
||||
|
||||
/*
|
||||
int QSOcount = _log.getCount();
|
||||
int count = _worked.getWorkedCount();
|
||||
qDebug() << QSOcount << "QSOs and" << count << "countries worked in file" << logFilename;
|
||||
*/
|
||||
|
||||
// QString call = "ok1ct";
|
||||
// QString countryName;
|
||||
// bool callWorkedBefore,countryWorkedBefore;
|
||||
// match(/*in*/call, /*out*/ countryName,callWorkedBefore,countryWorkedBefore);
|
||||
// qDebug() << countryName;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -59,11 +46,14 @@ void LogBook::_setAlreadyWorkedFromLog()
|
||||
if (countryName.length() > 0)
|
||||
{
|
||||
_worked.setAsWorked(countryName);
|
||||
//qDebug() << countryName << " worked " << c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool LogBook::hasWorkedBefore(const QString &call, const QString &band){
|
||||
return _log.match(call, band);
|
||||
}
|
||||
|
||||
void LogBook::match(/*in*/const QString call,
|
||||
/*out*/ QString &countryName,
|
||||
bool &callWorkedBefore,
|
||||
@@ -71,11 +61,9 @@ void LogBook::match(/*in*/const QString call,
|
||||
{
|
||||
if (call.length() > 0)
|
||||
{
|
||||
QString currentMode = "JT9"; // JT65 == JT9 in ADIF::match()
|
||||
QString currentBand = ""; // match any band
|
||||
callWorkedBefore = _log.match(call,currentBand,currentMode);
|
||||
callWorkedBefore = _log.match(call,currentBand);
|
||||
countryName = _countries.find(call);
|
||||
// qDebug() << "B" << countryName;
|
||||
|
||||
if (countryName.length() > 0) // country was found
|
||||
countryWorkedBefore = _worked.getHasWorked(countryName);
|
||||
@@ -85,13 +73,11 @@ void LogBook::match(/*in*/const QString call,
|
||||
countryWorkedBefore = false;
|
||||
}
|
||||
}
|
||||
//qDebug() << "Logbook:" << call << ":" << countryName << "Cty B4:" << countryWorkedBefore << "call B4:" << callWorkedBefore;
|
||||
}
|
||||
|
||||
void LogBook::addAsWorked(const QString call, const QString band, const QString mode, const QString date)
|
||||
void LogBook::addAsWorked(const QString call, const QString band, const QString mode, const QString submode, const QString date)
|
||||
{
|
||||
//qDebug() << "adding " << call << " as worked";
|
||||
_log.add(call,band,mode,date);
|
||||
_log.add(call,band,mode,submode,date);
|
||||
QString countryName = _countries.find(call);
|
||||
if (countryName.length() > 0)
|
||||
_worked.setAsWorked(countryName);
|
||||
|
||||
+2
-1
@@ -20,11 +20,12 @@ class LogBook
|
||||
{
|
||||
public:
|
||||
void init();
|
||||
bool hasWorkedBefore(const QString &call, const QString &band);
|
||||
void match(/*in*/ const QString call,
|
||||
/*out*/ QString &countryName,
|
||||
bool &callWorkedBefore,
|
||||
bool &countryWorkedBefore) const;
|
||||
void addAsWorked(const QString call, const QString band, const QString mode, const QString date);
|
||||
void addAsWorked(const QString call, const QString band, const QString mode, const QString submode, const QString date);
|
||||
|
||||
private:
|
||||
CountryDat _countries;
|
||||
|
||||
+12
-8
@@ -95,12 +95,16 @@ void LogQSO::initLogQSO(QString const& hisCall, QString const& hisGrid, QString
|
||||
|
||||
void LogQSO::accept()
|
||||
{
|
||||
QString hisCall,hisGrid,mode,rptSent,rptRcvd,dateOn,dateOff,timeOn,timeOff,band,operator_call;
|
||||
QString hisCall,hisGrid,mode,submode,rptSent,rptRcvd,dateOn,dateOff,timeOn,timeOff,band,operator_call;
|
||||
QString comments,name;
|
||||
|
||||
hisCall=ui->call->text();
|
||||
hisGrid=ui->grid->text();
|
||||
mode=ui->mode->text();
|
||||
hisCall=ui->call->text().toUpper();
|
||||
hisGrid=ui->grid->text().toUpper();
|
||||
mode = ui->mode->text().toUpper();
|
||||
if(mode == "JS8"){
|
||||
mode="MFSK";
|
||||
submode="JS8";
|
||||
}
|
||||
rptSent=ui->sent->text();
|
||||
rptRcvd=ui->rcvd->text();
|
||||
m_dateTimeOn = ui->start_date_time->dateTime ();
|
||||
@@ -115,10 +119,10 @@ void LogQSO::accept()
|
||||
//Log this QSO to ADIF file "js8call_log.adi"
|
||||
QString filename = "js8call_log.adi"; // TODO allow user to set
|
||||
ADIF adifile;
|
||||
auto adifilePath = QDir {QStandardPaths::writableLocation (QStandardPaths::DataLocation)}.absoluteFilePath ("js8call_log.adi");
|
||||
auto adifilePath = QDir {QStandardPaths::writableLocation (QStandardPaths::DataLocation)}.absoluteFilePath (filename);
|
||||
adifile.init(adifilePath);
|
||||
|
||||
QByteArray ADIF {adifile.QSOToADIF (hisCall, hisGrid, mode, rptSent, rptRcvd, m_dateTimeOn, m_dateTimeOff, band
|
||||
QByteArray ADIF {adifile.QSOToADIF (hisCall, hisGrid, mode, submode, rptSent, rptRcvd, m_dateTimeOn, m_dateTimeOff, band
|
||||
, comments, name, strDialFreq, m_myCall, m_myGrid, m_txPower, operator_call)};
|
||||
if (!adifile.addQSOToFile (ADIF))
|
||||
{
|
||||
@@ -148,7 +152,7 @@ void LogQSO::accept()
|
||||
m_dateTimeOn.time().toString("hh:mm:ss,") +
|
||||
m_dateTimeOff.date().toString("yyyy-MM-dd,") +
|
||||
m_dateTimeOff.time().toString("hh:mm:ss,") + hisCall + "," +
|
||||
hisGrid + "," + strDialFreq + "," + mode +
|
||||
hisGrid + "," + strDialFreq + "," + (mode == "MFSK" ? "JS8" : mode) +
|
||||
"," + rptSent + "," + rptRcvd + "," + m_txPower +
|
||||
"," + comments + "," + name;
|
||||
QTextStream out(&f);
|
||||
@@ -157,7 +161,7 @@ void LogQSO::accept()
|
||||
}
|
||||
|
||||
//Clean up and finish logging
|
||||
Q_EMIT acceptQSO (m_dateTimeOff, hisCall, hisGrid, m_dialFreq, mode, rptSent, rptRcvd, m_txPower, comments, name,m_dateTimeOn, operator_call, m_myCall, m_myGrid, ADIF);
|
||||
Q_EMIT acceptQSO (m_dateTimeOff, hisCall, hisGrid, m_dialFreq, mode, submode, rptSent, rptRcvd, m_txPower, comments, name,m_dateTimeOn, operator_call, m_myCall, m_myGrid, ADIF);
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ public slots:
|
||||
|
||||
signals:
|
||||
void acceptQSO (QDateTime const& QSO_date_off, QString const& call, QString const& grid
|
||||
, Radio::Frequency dial_freq, QString const& mode
|
||||
, Radio::Frequency dial_freq, QString const& mode, QString const& submode
|
||||
, QString const& rpt_sent, QString const& rpt_received
|
||||
, QString const& tx_power, QString const& comments
|
||||
, QString const& name, QDateTime const& QSO_date_on, QString const& operator_call
|
||||
|
||||
@@ -152,6 +152,9 @@
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
|
||||
+1827
-1701
File diff suppressed because it is too large
Load Diff
+77
-37
@@ -120,8 +120,6 @@ public slots:
|
||||
void diskDat();
|
||||
void freezeDecode(int n);
|
||||
void guiUpdate();
|
||||
void doubleClickOnCall (Qt::KeyboardModifiers);
|
||||
void doubleClickOnCall2(Qt::KeyboardModifiers);
|
||||
void readFromStdout();
|
||||
void p1ReadFromStdout();
|
||||
void setXIT(int n, Frequency base = 0u);
|
||||
@@ -132,13 +130,14 @@ public slots:
|
||||
void msgAvgDecode2();
|
||||
void fastPick(int x0, int x1, int y);
|
||||
|
||||
void playSoundNotification(const QString &path);
|
||||
bool hasExistingMessageBuffer(int offset, bool drift, int *pPrevOffset);
|
||||
void logCallActivity(CallDetail d, bool spot=true);
|
||||
QString lookupCallInCompoundCache(QString const &call);
|
||||
void cacheActivity(QString key);
|
||||
void restoreActivity(QString key);
|
||||
void clearActivity();
|
||||
void createAllcallTableRow(QTableWidget *table, bool selected);
|
||||
void createAllcallTableRows(QTableWidget *table, const QString &selectedCall);
|
||||
void displayTextForFreq(QString text, int freq, QDateTime date, bool isTx, bool isNewLine, bool isLast);
|
||||
void writeNoticeTextToUI(QDateTime date, QString text);
|
||||
int writeMessageTextToUI(QDateTime date, QString text, int freq, bool bold, int block=-1);
|
||||
@@ -146,17 +145,19 @@ public slots:
|
||||
void prependMessageText(QString text);
|
||||
void addMessageText(QString text, bool clear=false, bool selectFirstPlaceholder=false);
|
||||
void enqueueMessage(int priority, QString message, int freq, Callback c);
|
||||
void enqueueBeacon(QString message);
|
||||
void enqueueHeartbeat(QString message);
|
||||
void resetMessage();
|
||||
void resetMessageUI();
|
||||
void restoreMessage();
|
||||
void initializeDummyData();
|
||||
bool ensureCallsignSet(bool alert=true);
|
||||
bool ensureSelcalCallsignSelected(bool alert=true);
|
||||
bool ensureKeyNotStuck(QString const& text);
|
||||
bool ensureNotIdle();
|
||||
void createMessage(QString const& text);
|
||||
void createMessageTransmitQueue(QString const& text);
|
||||
void resetMessageTransmitQueue();
|
||||
QString popMessageFrame();
|
||||
QPair<QString, int> popMessageFrame();
|
||||
protected:
|
||||
void keyPressEvent (QKeyEvent *) override;
|
||||
void closeEvent(QCloseEvent *) override;
|
||||
@@ -171,8 +172,16 @@ private slots:
|
||||
void on_tx4_editingFinished();
|
||||
void on_tx5_currentTextChanged (QString const&);
|
||||
void on_tx6_editingFinished();
|
||||
void on_menuControl_aboutToShow();
|
||||
void on_actionEnable_Spotting_toggled(bool checked);
|
||||
void on_actionEnable_Active_toggled(bool checked);
|
||||
void on_actionEnable_Auto_Reply_toggled(bool checked);
|
||||
void on_actionEnable_Selcall_toggled(bool checked);
|
||||
void on_menuWindow_aboutToShow();
|
||||
void on_actionShow_Fullscreen_triggered(bool checked);
|
||||
void on_actionShow_Frequency_Clock_triggered(bool checked);
|
||||
void on_actionShow_Band_Activity_triggered(bool checked);
|
||||
void on_actionShow_Band_Heartbeats_and_ACKs_triggered(bool checked);
|
||||
void on_actionShow_Call_Activity_triggered(bool checked);
|
||||
void on_actionShow_Waterfall_triggered(bool checked);
|
||||
void on_actionShow_Waterfall_Controls_triggered(bool checked);
|
||||
@@ -186,6 +195,7 @@ private slots:
|
||||
void on_actionAbout_triggered();
|
||||
void on_autoButton_clicked (bool);
|
||||
void on_labDialFreq_clicked();
|
||||
void resetPushButtonToggleText(QPushButton *btn);
|
||||
void on_monitorTxButton_clicked();
|
||||
void on_stopTxButton_clicked();
|
||||
void on_stopButton_clicked();
|
||||
@@ -211,9 +221,6 @@ private slots:
|
||||
void decode();
|
||||
void decodeBusy(bool b);
|
||||
void on_EraseButton_clicked();
|
||||
void band_activity_cleared ();
|
||||
void rx_frequency_activity_cleared ();
|
||||
void on_txFirstCheckBox_stateChanged(int arg1);
|
||||
void set_dateTimeQSO(int m_ntx);
|
||||
void set_ntx(int n);
|
||||
void on_txrb1_toggled(bool status);
|
||||
@@ -249,6 +256,7 @@ private slots:
|
||||
void on_actionSave_decoded_triggered();
|
||||
void on_actionQuickDecode_toggled (bool);
|
||||
void on_actionMediumDecode_toggled (bool);
|
||||
void on_actionDeepDecode_toggled (bool);
|
||||
void on_actionDeepestDecode_toggled (bool);
|
||||
void bumpFqso(int n);
|
||||
void on_actionErase_ALL_TXT_triggered();
|
||||
@@ -257,7 +265,6 @@ private slots:
|
||||
void startTx();
|
||||
void startTx2();
|
||||
void startP1();
|
||||
void continueTx();
|
||||
void stopTx();
|
||||
void stopTx2();
|
||||
void on_pbCallCQ_clicked();
|
||||
@@ -269,12 +276,21 @@ private slots:
|
||||
void on_rbGenMsg_clicked(bool checked);
|
||||
void on_rbFreeText_clicked(bool checked);
|
||||
void on_clearAction_triggered(QObject * sender);
|
||||
void buildHeartbeatMenu(QMenu *menu);
|
||||
void buildCQMenu(QMenu *menu);
|
||||
void buildRepeatMenu(QMenu *menu, QPushButton * button, int * interval);
|
||||
void sendHeartbeat();
|
||||
void on_hbMacroButton_toggled(bool checked);
|
||||
void on_hbMacroButton_clicked();
|
||||
void sendCQ(bool repeat=false);
|
||||
void on_cqMacroButton_toggled(bool checked);
|
||||
void on_cqMacroButton_clicked();
|
||||
void on_replyMacroButton_clicked();
|
||||
void on_snrMacroButton_clicked();
|
||||
void on_qthMacroButton_clicked();
|
||||
void on_qtcMacroButton_clicked();
|
||||
void setShowColumn(QString tableKey, QString columnKey, bool value);
|
||||
bool showColumn(QString tableKey, QString columnKey);
|
||||
bool showColumn(QString tableKey, QString columnKey, bool default_=true);
|
||||
void buildShowColumnsMenu(QMenu *menu, QString tableKey);
|
||||
void setSortBy(QString key, QString value);
|
||||
QString getSortBy(QString key, QString defaultValue);
|
||||
@@ -282,6 +298,8 @@ private slots:
|
||||
void buildBandActivitySortByMenu(QMenu * menu);
|
||||
void buildCallActivitySortByMenu(QMenu * menu);
|
||||
void buildQueryMenu(QMenu *, QString callsign);
|
||||
QMap<QString, QString> buildMacroValues();
|
||||
QString replaceMacros(QString const &text, QMap<QString, QString> values, bool prune);
|
||||
void buildSavedMessagesMenu(QMenu *menu);
|
||||
void buildRelayMenu(QMenu *menu);
|
||||
QAction* buildRelayAction(QString call);
|
||||
@@ -299,16 +317,12 @@ private slots:
|
||||
void on_nextFreeTextMsg_currentTextChanged (QString const&);
|
||||
void on_extFreeTextMsgEdit_currentTextChanged (QString const&);
|
||||
int currentFreqOffset();
|
||||
int countMessageFrames(QString const& text);
|
||||
QStringList buildMessageFrames(QString const& text);
|
||||
QList<QPair<QString, int>> buildMessageFrames(QString const& text);
|
||||
bool prepareNextMessageFrame();
|
||||
bool isFreqOffsetFree(int f, int bw);
|
||||
int findFreeFreqOffset(int fmin, int fmax, int bw);
|
||||
void scheduleBeacon(bool first=false);
|
||||
void pauseBeacon();
|
||||
void checkBeacon();
|
||||
void prepareBeacon();
|
||||
QString calculateDistance(QString const& grid, int *pDistance=nullptr);
|
||||
void checkRepeat();
|
||||
QString calculateDistance(QString const& grid, int *pDistance=nullptr, int *pAzimuth=nullptr);
|
||||
void on_driftSpinBox_valueChanged(int n);
|
||||
void on_driftSyncButton_clicked();
|
||||
void on_driftSyncEndButton_clicked();
|
||||
@@ -319,10 +333,9 @@ private slots:
|
||||
void on_tuneButton_clicked (bool);
|
||||
void on_pbR2T_clicked();
|
||||
void on_pbT2R_clicked();
|
||||
void on_beaconButton_clicked();
|
||||
void on_selcalButton_clicked();
|
||||
void on_turboButton_clicked();
|
||||
void acceptQSO (QDateTime const&, QString const& call, QString const& grid
|
||||
, Frequency dial_freq, QString const& mode
|
||||
, Frequency dial_freq, QString const& mode, QString const& submode
|
||||
, QString const& rpt_sent, QString const& rpt_received
|
||||
, QString const& tx_power, QString const& comments
|
||||
, QString const& name, QDateTime const& QSO_date_on, QString const& operator_call
|
||||
@@ -343,6 +356,14 @@ private slots:
|
||||
void stop_tuning ();
|
||||
void stopTuneATU();
|
||||
void auto_tx_mode(bool);
|
||||
void on_autoReplyButton_toggled(bool checked);
|
||||
void on_monitorButton_toggled(bool checked);
|
||||
void on_monitorTxButton_toggled(bool checked);
|
||||
void on_selcalButton_toggled(bool checked);
|
||||
void on_tuneButton_toggled(bool checked);
|
||||
void on_spotButton_toggled(bool checked);
|
||||
void on_activeButton_toggled(bool checked);
|
||||
|
||||
void on_actionMessage_averaging_triggered();
|
||||
void on_actionFox_Log_triggered();
|
||||
void on_actionInclude_averaging_toggled (bool);
|
||||
@@ -416,8 +437,7 @@ private:
|
||||
|
||||
private:
|
||||
void astroUpdate ();
|
||||
void writeAllTxt(QString message);
|
||||
void auto_sequence (DecodedText const& message, unsigned start_tolerance, unsigned stop_tolerance);
|
||||
void writeAllTxt(QString message, int bits);
|
||||
void hideMenus(bool b);
|
||||
|
||||
NetworkAccessManager m_network_manager;
|
||||
@@ -539,7 +559,6 @@ private:
|
||||
bool m_diskData;
|
||||
bool m_loopall;
|
||||
bool m_decoderBusy;
|
||||
bool m_txFirst;
|
||||
bool m_auto;
|
||||
bool m_restart;
|
||||
bool m_startAnother;
|
||||
@@ -556,6 +575,7 @@ private:
|
||||
bool m_sentFirst73;
|
||||
int m_currentMessageType;
|
||||
QString m_currentMessage;
|
||||
int m_currentMessageBits;
|
||||
int m_lastMessageType;
|
||||
QString m_lastMessageSent;
|
||||
bool m_bShMsgs;
|
||||
@@ -650,7 +670,7 @@ private:
|
||||
QTimer minuteTimer;
|
||||
QTimer splashTimer;
|
||||
QTimer p1Timer;
|
||||
QTimer beaconTimer;
|
||||
QTimer repeatTimer;
|
||||
|
||||
QString m_path;
|
||||
QString m_baseCall;
|
||||
@@ -691,6 +711,7 @@ private:
|
||||
QDateTime utcTimestamp;
|
||||
int snr;
|
||||
int bits;
|
||||
float tdrift;
|
||||
};
|
||||
|
||||
struct CommandDetail
|
||||
@@ -707,6 +728,8 @@ private:
|
||||
QString grid;
|
||||
QString text;
|
||||
QString extra;
|
||||
float tdrift;
|
||||
QString relayPath;
|
||||
};
|
||||
|
||||
struct ActivityDetail
|
||||
@@ -721,6 +744,8 @@ private:
|
||||
QString text;
|
||||
QDateTime utcTimestamp;
|
||||
int snr;
|
||||
bool shouldDisplay;
|
||||
float tdrift;
|
||||
};
|
||||
|
||||
struct MessageBuffer {
|
||||
@@ -729,6 +754,10 @@ private:
|
||||
QList<ActivityDetail> msgs;
|
||||
};
|
||||
|
||||
int m_bandActivityWidth;
|
||||
int m_callActivityWidth;
|
||||
int m_textActivityWidth;
|
||||
int m_waterfallHeight;
|
||||
bool m_bandActivityWasVisible;
|
||||
bool m_rxDirty;
|
||||
bool m_rxDisplayDirty;
|
||||
@@ -740,7 +769,8 @@ private:
|
||||
QString m_txTextDirtyLastSelectedCall;
|
||||
QString m_lastTxMessage;
|
||||
QDateTime m_lastTxTime;
|
||||
|
||||
int m_timeDeltaMsMMA;
|
||||
int m_timeDeltaMsMMA_N;
|
||||
|
||||
enum Priority {
|
||||
PriorityLow = 10,
|
||||
@@ -771,7 +801,7 @@ private:
|
||||
QMap<QString, QVariant> m_showColumnsCache; // table column:key -> show boolean
|
||||
QMap<QString, QVariant> m_sortCache; // table key -> sort by
|
||||
QPriorityQueue<PrioritizedMessage> m_txMessageQueue; // messages to be sent
|
||||
QQueue<QString> m_txFrameQueue; // frames to be sent
|
||||
QQueue<QPair<QString, int>> m_txFrameQueue; // frames to be sent
|
||||
QQueue<ActivityDetail> m_rxActivityQueue; // all rx activity queue
|
||||
QQueue<CommandDetail> m_rxCommandQueue; // command queue for processing commands
|
||||
QQueue<CallDetail> m_rxCallQueue; // call detail queue for spots to pskreporter
|
||||
@@ -784,14 +814,16 @@ private:
|
||||
QMap<int, QList<ActivityDetail>> m_bandActivity; // freq -> [(text, last timestamp), ...]
|
||||
QMap<int, MessageBuffer> m_messageBuffer; // freq -> (cmd, [frames, ...])
|
||||
QMap<QString, CallDetail> m_callActivity; // call -> (last freq, last timestamp)
|
||||
QQueue<QString> m_txBeaconQueue; // beacon frames to be sent
|
||||
QQueue<QString> m_txHeartbeatQueue; // ping frames to be sent
|
||||
QMap<QString, QDateTime> m_aprsCallCache;
|
||||
|
||||
QMap<QString, QList<CommandDetail>> m_rxCallsignCommandQueue; // call -> [cmd, ...]
|
||||
|
||||
QMap<QString, QMap<QString, CallDetail>> m_callActivityCache; // band -> call activity
|
||||
QMap<QString, QMap<int, QList<ActivityDetail>>> m_bandActivityCache; // band -> band activity
|
||||
QMap<QString, QString> m_rxTextCache; // band -> rx text
|
||||
|
||||
QSet<QString> m_callSeenBeacon; // call
|
||||
QSet<QString> m_callSeenHeartbeat; // call
|
||||
int m_previousFreq;
|
||||
bool m_shouldRestoreFreq;
|
||||
bool m_bandHopped;
|
||||
@@ -815,9 +847,11 @@ private:
|
||||
QQueue<QString> m_foxQSOinProgress; //QSOs in progress: Fox has sent a report
|
||||
QQueue<qint64> m_foxRateQueue;
|
||||
|
||||
bool m_nextBeaconQueued = false;
|
||||
bool m_nextBeaconPaused = false;
|
||||
QDateTime m_nextBeacon;
|
||||
bool m_hbHidden;
|
||||
int m_hbInterval;
|
||||
int m_cqInterval;
|
||||
QDateTime m_nextHeartbeat;
|
||||
QDateTime m_nextCQ;
|
||||
QDateTime m_dateTimeQSOOn;
|
||||
QDateTime m_dateTimeLastTX;
|
||||
|
||||
@@ -834,6 +868,7 @@ private:
|
||||
bool m_tx_when_ready;
|
||||
bool m_transmitting;
|
||||
bool m_tune;
|
||||
bool m_deadAirTone;
|
||||
bool m_tx_watchdog; // true when watchdog triggered
|
||||
bool m_block_pwr_tooltip;
|
||||
bool m_PwrBandSetOK;
|
||||
@@ -843,7 +878,6 @@ private:
|
||||
double m_toneSpacing;
|
||||
int m_firstDecode;
|
||||
QProgressDialog m_optimizingProgress;
|
||||
QTimer m_heartbeat;
|
||||
MessageClient * m_messageClient;
|
||||
PSK_Reporter *psk_Reporter;
|
||||
APRSISClient * m_aprsClient;
|
||||
@@ -860,8 +894,6 @@ private:
|
||||
void writeSettings();
|
||||
void createStatusBar();
|
||||
void updateStatusBar();
|
||||
void genStdMsgs(QString rpt, bool unconditional = false);
|
||||
void genCQMsg();
|
||||
void clearDX ();
|
||||
void lookup();
|
||||
void ba2msg(QByteArray ba, char* message);
|
||||
@@ -874,19 +906,18 @@ private:
|
||||
void rigFailure (QString const& reason);
|
||||
void pskSetLocal ();
|
||||
void aprsSetLocal ();
|
||||
void pskPost(DecodedText const& decodedtext);
|
||||
void pskLogReport(QString mode, int offset, int snr, QString callsign, QString grid);
|
||||
void aprsLogReport(int offset, int snr, QString callsign, QString grid);
|
||||
Radio::Frequency dialFrequency();
|
||||
void displayDialFrequency ();
|
||||
void transmitDisplay (bool);
|
||||
void processMessage(DecodedText const&, Qt::KeyboardModifiers = 0);
|
||||
void replyToCQ (QTime, qint32 snr, float delta_time, quint32 delta_frequency, QString const& mode, QString const& message_text, bool low_confidence, quint8 modifiers);
|
||||
void locationChange(QString const& location);
|
||||
void replayDecodes ();
|
||||
void postDecode (bool is_new, QString const& message);
|
||||
void displayTransmit();
|
||||
void updateButtonDisplay();
|
||||
void updateRepeatButtonDisplay();
|
||||
void updateTextDisplay();
|
||||
void updateFrameCountEstimate(int count);
|
||||
void updateTextStatsDisplay(QString text, int count);
|
||||
void updateTxButtonDisplay();
|
||||
@@ -900,6 +931,8 @@ private:
|
||||
void markOffsetDirected(int offset, bool isAllCall);
|
||||
void clearOffsetDirected(int offset);
|
||||
void processActivity(bool force=false);
|
||||
void observeTimeDeltaForAverage(float delta);
|
||||
void resetTimeDeltaAverage();
|
||||
void processRxActivity();
|
||||
void processCompoundActivity();
|
||||
void processBufferedActivity();
|
||||
@@ -932,6 +965,10 @@ private:
|
||||
, QString const& his_call
|
||||
, QString const& his_grid) const;
|
||||
void read_wav_file (QString const& fname);
|
||||
QDateTime nextTransmitCycle();
|
||||
void resetAutomaticIntervalTransmissions(bool stopCQ, bool stopHB);
|
||||
void resetCQTimer(bool stop);
|
||||
void resetHeartbeatTimer(bool stop);
|
||||
void decodeDone ();
|
||||
void subProcessFailed (QProcess *, int exit_code, QProcess::ExitStatus);
|
||||
void subProcessError (QProcess *, QProcess::ProcessError);
|
||||
@@ -942,6 +979,9 @@ private:
|
||||
void add_child_to_event_filter (QObject *);
|
||||
void remove_child_from_event_filter (QObject *);
|
||||
void setup_status_bar (bool vhf);
|
||||
|
||||
void resetIdleTimer();
|
||||
void incrementIdleTimer();
|
||||
void tx_watchdog (bool triggered);
|
||||
qint64 nWidgets(QString t);
|
||||
void displayWidgets(qint64 n);
|
||||
|
||||
+851
-661
File diff suppressed because it is too large
Load Diff
+32
-1
@@ -27,6 +27,7 @@ CPlotter::CPlotter(QWidget *parent) : //CPlotter Constructor
|
||||
m_plot2dGain {0},
|
||||
m_plot2dZero {0},
|
||||
m_nSubMode {0},
|
||||
m_turbo {false},
|
||||
m_Running {false},
|
||||
m_paintEventBusy {false},
|
||||
m_fftBinWidth {1500.0/2048.0},
|
||||
@@ -578,7 +579,7 @@ void CPlotter::DrawOverlay() //DrawOverlay()
|
||||
x1=XfromFreq(500);
|
||||
x2=XfromFreq(1000);
|
||||
if(x1<=m_w and x2>0) {
|
||||
painter0.setPen(penBlue); //Mark beacon range
|
||||
painter0.setPen(penBlue); //Mark ping range
|
||||
painter0.drawLine(x1+1,26,x2-2,26);
|
||||
painter0.drawLine(x1+1,28,x2-2,28);
|
||||
}
|
||||
@@ -587,6 +588,9 @@ void CPlotter::DrawOverlay() //DrawOverlay()
|
||||
|
||||
if(m_mode=="FT8"){
|
||||
int fwidth=XfromFreq(m_rxFreq+bw)-XfromFreq(m_rxFreq);
|
||||
#if TEST_FOX_WAVE_GEN
|
||||
int offset=XfromFreq(m_rxFreq+bw+10)-XfromFreq(m_rxFreq+bw);
|
||||
#endif
|
||||
QPainter overPainter(&m_DialOverlayPixmap);
|
||||
overPainter.initFrom(this);
|
||||
overPainter.setCompositionMode(QPainter::CompositionMode_Source);
|
||||
@@ -595,10 +599,22 @@ void CPlotter::DrawOverlay() //DrawOverlay()
|
||||
overPainter.setPen(thinRed);
|
||||
overPainter.drawLine(0, 30, 0, m_h);
|
||||
overPainter.drawLine(fwidth+1, 30, fwidth+1, m_h);
|
||||
#if TEST_FOX_WAVE_GEN
|
||||
if(m_turbo){
|
||||
overPainter.drawLine(offset+fwidth+1, 30, offset+fwidth+1, m_h);
|
||||
overPainter.drawLine(offset+2*fwidth+1, 30, offset+2*fwidth+1, m_h);
|
||||
}
|
||||
#endif
|
||||
|
||||
overPainter.setPen(penRed);
|
||||
overPainter.drawLine(0, 26, fwidth, 26);
|
||||
overPainter.drawLine(0, 28, fwidth, 28);
|
||||
#if TEST_FOX_WAVE_GEN
|
||||
if(m_turbo){
|
||||
overPainter.drawLine(offset+fwidth, 26, offset+2*fwidth, 26);
|
||||
overPainter.drawLine(offset+fwidth, 28, offset+2*fwidth, 28);
|
||||
}
|
||||
#endif
|
||||
|
||||
QPainter hoverPainter(&m_HoverOverlayPixmap);
|
||||
hoverPainter.initFrom(this);
|
||||
@@ -607,6 +623,12 @@ void CPlotter::DrawOverlay() //DrawOverlay()
|
||||
hoverPainter.setPen(QPen(Qt::white));
|
||||
hoverPainter.drawLine(0, 30, 0, m_h);
|
||||
hoverPainter.drawLine(fwidth+1, 30, fwidth+1, m_h);
|
||||
#if TEST_FOX_WAVE_GEN
|
||||
if(m_turbo){
|
||||
hoverPainter.drawLine(offset+fwidth+1, 30, offset+fwidth+1, m_h);
|
||||
hoverPainter.drawLine(offset+2*fwidth+1, 30, offset+2*fwidth+1, m_h);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if DRAW_FREQ_OVERLAY
|
||||
int f = FreqfromX(m_lastMouseX);
|
||||
@@ -865,6 +887,15 @@ void CPlotter::setDialFreq(double d)
|
||||
void CPlotter::setRxBand(QString band)
|
||||
{
|
||||
m_rxBand=band;
|
||||
DrawOverlay();
|
||||
update();
|
||||
}
|
||||
|
||||
void CPlotter::setTurbo(bool turbo)
|
||||
{
|
||||
m_turbo=turbo;
|
||||
DrawOverlay();
|
||||
update();
|
||||
}
|
||||
|
||||
void CPlotter::setFlatten(bool b1, bool b2)
|
||||
|
||||
@@ -81,6 +81,7 @@ public:
|
||||
void setFlatten(bool b1, bool b2);
|
||||
void setTol(int n);
|
||||
void setRxBand(QString band);
|
||||
void setTurbo(bool turbo);
|
||||
void setReference(bool b) {m_bReference = b;}
|
||||
bool Reference() const {return m_bReference;}
|
||||
void drawRed(int ia, int ib, float swide[]);
|
||||
@@ -147,6 +148,7 @@ private:
|
||||
QString m_rxBand;
|
||||
QString m_redFile;
|
||||
|
||||
bool m_turbo;
|
||||
bool m_Running;
|
||||
bool m_paintEventBusy;
|
||||
bool m_dataFromDisk;
|
||||
|
||||
+4
-2
@@ -33,6 +33,8 @@ QString version (bool include_patch)
|
||||
|
||||
QString program_title (QString const& revision)
|
||||
{
|
||||
QString id {"JS8Call de KN4CRD (v%1)"};
|
||||
return id.arg(QCoreApplication::applicationVersion ());
|
||||
QString id {"%1 DE KN4CRD (v%2)"};
|
||||
id = id.arg(QCoreApplication::applicationName());
|
||||
id = id.arg(QCoreApplication::applicationVersion ());
|
||||
return id;
|
||||
}
|
||||
|
||||
+448
-234
File diff suppressed because it is too large
Load Diff
+37
-24
@@ -12,6 +12,7 @@
|
||||
#include <QVector>
|
||||
#include <QThread>
|
||||
|
||||
|
||||
class Varicode
|
||||
{
|
||||
public:
|
||||
@@ -20,33 +21,38 @@ public:
|
||||
JS8Call = 0, // [000] <- any other frame of the message
|
||||
JS8CallFirst = 1, // [001] <- the first frame of a message
|
||||
JS8CallLast = 2, // [010] <- the last frame of a message
|
||||
JS8CallReserved = 4, // [100] <- a reserved flag for future use...
|
||||
JS8CallFlag = 4, // [100] <- flagged frame (no frame type header)
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
000 = heartbeat
|
||||
001 = compound
|
||||
010 = compound directed
|
||||
011 = directed
|
||||
1XX = data, with the X lsb bits dropped
|
||||
*/
|
||||
enum FrameType {
|
||||
FrameUnknown = 255, // [11111111] <- only used as a sentinel
|
||||
FrameBeacon = 0, // [000]
|
||||
FrameHeartbeat = 0, // [000]
|
||||
FrameCompound = 1, // [001]
|
||||
FrameCompoundDirected = 2, // [010]
|
||||
FrameDirected = 3, // [011]
|
||||
FrameReservedA = 4, // [100] <- Reserved for future use, likely an extension of one of these formats.
|
||||
FrameDataUncompressed = 5, // [101]
|
||||
FrameDataCompressed = 6, // [110]
|
||||
FrameReservedB = 7, // [111] <- Reserved for future use, likely binary data / other formats.
|
||||
FrameData = 4, // [10X] // but this only encodes the first 2 msb bits and drops the lsb
|
||||
FrameDataCompressed = 6, // [11X] // but this only encodes the first 2 msb bits and drops the lsb
|
||||
};
|
||||
|
||||
static const quint8 FrameTypeMax = 7;
|
||||
static const quint8 FrameTypeMax = 6;
|
||||
|
||||
static QString frameTypeString(quint8 type) {
|
||||
const char* FrameTypeStrings[] = {
|
||||
"FrameBeacon",
|
||||
"FrameHeartbeat",
|
||||
"FrameCompound",
|
||||
"FrameCompoundDirected",
|
||||
"FrameDirected",
|
||||
"FrameReservedA",
|
||||
"FrameDataUncompressed",
|
||||
"FrameData",
|
||||
"FrameUnknown", // 5
|
||||
"FrameDataCompressed",
|
||||
"FrameReservedB"
|
||||
};
|
||||
|
||||
if(type > FrameTypeMax){
|
||||
@@ -62,7 +68,9 @@ public:
|
||||
|
||||
static QMap<QString, QString> defaultHuffTable();
|
||||
static QString cqString(int number);
|
||||
static QString hbString(int number);
|
||||
static bool startsWithCQ(QString text);
|
||||
static bool startsWithHB(QString text);
|
||||
static QString formatSNR(int snr);
|
||||
static QString formatPWR(int dbm);
|
||||
|
||||
@@ -109,6 +117,9 @@ public:
|
||||
static quint32 packAlphaNumeric22(QString const& value, bool isFlag);
|
||||
static QString unpackAlphaNumeric22(quint32 packed, bool *isFlag);
|
||||
|
||||
static quint64 packAlphaNumeric50(QString const& value);
|
||||
static QString unpackAlphaNumeric50(quint64 packed);
|
||||
|
||||
static quint32 packCallsign(QString const& value);
|
||||
static QString unpackCallsign(quint32 value);
|
||||
|
||||
@@ -126,27 +137,29 @@ public:
|
||||
static bool isCommandAllowed(const QString &cmd);
|
||||
static bool isCommandBuffered(const QString &cmd);
|
||||
static int isCommandChecksumed(const QString &cmd);
|
||||
static bool isValidCallsign(const QString &callsign, bool *pIsCompound);
|
||||
static bool isCompoundCallsign(const QString &callsign);
|
||||
|
||||
static QString packBeaconMessage(QString const &text, QString const&callsign, int *n);
|
||||
static QStringList unpackBeaconMessage(const QString &text, quint8 *pType, bool *isAlt, quint8 *pBits3);
|
||||
static QString packHeartbeatMessage(QString const &text, QString const&callsign, int *n);
|
||||
static QStringList unpackHeartbeatMessage(const QString &text, quint8 *pType, bool *isAlt, quint8 *pBits3);
|
||||
|
||||
static QString packCompoundMessage(QString const &text, int *n);
|
||||
static QStringList unpackCompoundMessage(const QString &text, quint8 *pType, quint8 *pBits3);
|
||||
|
||||
static QString packCompoundFrame(const QString &baseCallsign, const QString &fix, bool isPrefix, quint8 type, quint16 num, quint8 bits3);
|
||||
static QString packCompoundFrame(const QString &callsign, quint8 type, quint16 num, quint8 bits3);
|
||||
static QStringList unpackCompoundFrame(const QString &text, quint8 *pType, quint16 *pNum, quint8 *pBits3);
|
||||
|
||||
static QString packDirectedMessage(QString const& text, QString const& callsign, QString *pTo, QString * pCmd, QString *pNum, int *n);
|
||||
static QString packDirectedMessage(QString const& text, QString const& mycall, QString *pTo, bool *pToCompound, QString * pCmd, QString *pNum, int *n);
|
||||
static QStringList unpackDirectedMessage(QString const& text, quint8 *pType);
|
||||
|
||||
static QString packDataMessage(QString const& text, int *n);
|
||||
static QString unpackDataMessage(QString const& text, quint8 *pType);
|
||||
static QString unpackDataMessage(QString const& text);
|
||||
|
||||
static QStringList buildMessageFrames(
|
||||
static QList<QPair<QString, int>> buildMessageFrames(
|
||||
QString const& mycall,
|
||||
QString const& basecall,
|
||||
//QString const& basecall,
|
||||
QString const& mygrid,
|
||||
bool compound,
|
||||
//bool compound,
|
||||
QString const& selectedCall,
|
||||
QString const& text
|
||||
);
|
||||
@@ -158,21 +171,21 @@ class BuildMessageFramesThread : public QThread
|
||||
Q_OBJECT
|
||||
public:
|
||||
BuildMessageFramesThread(QString const& mycall,
|
||||
QString const& basecall,
|
||||
//QString const& basecall,
|
||||
QString const& mygrid,
|
||||
bool compound,
|
||||
//bool compound,
|
||||
QString const& selectedCall,
|
||||
QString const& text,
|
||||
QObject *parent=nullptr);
|
||||
void run() override;
|
||||
signals:
|
||||
void resultReady(const QStringList s);
|
||||
void resultReady(QString, int);
|
||||
|
||||
private:
|
||||
QString m_mycall;
|
||||
QString m_basecall;
|
||||
//QString m_basecall;
|
||||
QString m_mygrid;
|
||||
bool m_compound;
|
||||
//bool m_compound;
|
||||
QString m_selectedCall;
|
||||
QString m_text;
|
||||
};
|
||||
|
||||
@@ -566,3 +566,7 @@ void WideGraph::setRedFile(QString fRed)
|
||||
{
|
||||
ui->widePlot->setRedFile(fRed);
|
||||
}
|
||||
|
||||
void WideGraph::setTurbo(bool turbo){
|
||||
ui->widePlot->setTurbo(turbo);
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ public:
|
||||
void drawRed(int ia, int ib);
|
||||
void setVHF(bool bVHF);
|
||||
void setRedFile(QString fRed);
|
||||
void setTurbo(bool turbo);
|
||||
|
||||
signals:
|
||||
void freezeDecode2(int n);
|
||||
|
||||
+2
-2
@@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1083</width>
|
||||
<height>337</height>
|
||||
<height>154</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@@ -43,7 +43,7 @@
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>400</width>
|
||||
<height>100</height>
|
||||
<height>10</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
|
||||
Reference in New Issue
Block a user