Merge tag 'wsjtx-2.0.0-rc6' into develop

WSJT-X v2.0.0 RC6 release
This commit is contained in:
Bill Somerville 2018-12-09 20:14:45 +00:00
commit 195b8d002a
118 changed files with 2336 additions and 2538 deletions

View File

@ -271,6 +271,8 @@ set (wsjt_qt_CXXSRCS
item_delegates/CallsignDelegate.cpp item_delegates/CallsignDelegate.cpp
item_delegates/MaidenheadLocatorDelegate.cpp item_delegates/MaidenheadLocatorDelegate.cpp
models/CabrilloLog.cpp models/CabrilloLog.cpp
logbook/AD1CCty.cpp
logbook/WorkedBefore.cpp
) )
set (wsjt_qtmm_CXXSRCS set (wsjt_qtmm_CXXSRCS
@ -288,8 +290,6 @@ set (jt9_CXXSRCS
set (wsjtx_CXXSRCS set (wsjtx_CXXSRCS
logbook/logbook.cpp logbook/logbook.cpp
logbook/WorkedBefore.cpp
logbook/AD1CCty.cpp
psk_reporter.cpp psk_reporter.cpp
Modulator.cpp Modulator.cpp
Detector.cpp Detector.cpp
@ -322,14 +322,12 @@ set (wsjtx_CXXSRCS
set (wsjt_CXXSRCS set (wsjt_CXXSRCS
lib/crc10.cpp lib/crc10.cpp
lib/crc12.cpp
lib/crc13.cpp lib/crc13.cpp
lib/crc14.cpp lib/crc14.cpp
) )
# deal with a GCC v6 UB error message # deal with a GCC v6 UB error message
set_source_files_properties ( set_source_files_properties (
lib/crc10.cpp lib/crc10.cpp
lib/crc12.cpp
lib/crc13.cpp lib/crc13.cpp
lib/crc14.cpp lib/crc14.cpp
PROPERTIES COMPILE_FLAGS -fpermissive) PROPERTIES COMPILE_FLAGS -fpermissive)
@ -384,13 +382,11 @@ set (wsjt_FSRCS
lib/ft8/baseline.f90 lib/ft8/baseline.f90
lib/bpdecode40.f90 lib/bpdecode40.f90
lib/bpdecode128_90.f90 lib/bpdecode128_90.f90
lib/ft8/bpdecode174.f90
lib/ft8/bpdecode174_91.f90 lib/ft8/bpdecode174_91.f90
lib/baddata.f90 lib/baddata.f90
lib/calibrate.f90 lib/calibrate.f90
lib/ccf2.f90 lib/ccf2.f90
lib/ccf65.f90 lib/ccf65.f90
lib/ft8/chkcrc12a.f90
lib/ft8/chkcrc13a.f90 lib/ft8/chkcrc13a.f90
lib/ft8/chkcrc14a.f90 lib/ft8/chkcrc14a.f90
lib/chkcall.f90 lib/chkcall.f90
@ -508,7 +504,6 @@ set (wsjt_FSRCS
lib/msk144sim.f90 lib/msk144sim.f90
lib/mskrtd.f90 lib/mskrtd.f90
lib/77bit/my_hash.f90 lib/77bit/my_hash.f90
lib/ft8/osd174.f90
lib/wsprd/osdwspr.f90 lib/wsprd/osdwspr.f90
lib/ft8/osd174_91.f90 lib/ft8/osd174_91.f90
lib/pctile.f90 lib/pctile.f90

View File

@ -182,6 +182,7 @@
#include "validators/CallsignValidator.hpp" #include "validators/CallsignValidator.hpp"
#include "LotWUsers.hpp" #include "LotWUsers.hpp"
#include "models/DecodeHighlightingModel.hpp" #include "models/DecodeHighlightingModel.hpp"
#include "logbook/logbook.h"
#include "ui_Configuration.h" #include "ui_Configuration.h"
#include "moc_Configuration.cpp" #include "moc_Configuration.cpp"
@ -199,16 +200,18 @@ namespace
QRegularExpression RTTY_roundup_exchange_re { QRegularExpression RTTY_roundup_exchange_re {
R"( R"(
( (
AL|AK|AZ|AR|CA|CO|CT|DE|FL|GA # states AL|AZ|AR|CA|CO|CT|DE|FL|GA # 48 contiguous states
|HI|ID|IL|IN|IA|KS|KY|LA|ME|MD |ID|IL|IN|IA|KS|KY|LA|ME|MD
|MA|MI|MN|MS|MO|MT|NE|NV|NH|NJ |MA|MI|MN|MS|MO|MT|NE|NV|NH|NJ
|NM|NY|NC|ND|OH|OK|OR|PA|RI|SC |NM|NY|NC|ND|OH|OK|OR|PA|RI|SC
|SD|TN|TX|UT|VT|VA|WA|WV|WI|WY |SD|TN|TX|UT|VT|VA|WA|WV|WI|WY
|NB|NS|QC|ON|MB|SK|AB|BC|NWT|NF # VE provinces |NB|NS|QC|ON|MB|SK|AB|BC|NWT|NF # VE provinces
|LB|NU|YT|PEI|DC |LB|NU|YT|PEI
|DC # District of Columbia
|DX # anyone else |DX # anyone else
) )
)", QRegularExpression::CaseInsensitiveOption | QRegularExpression::ExtendedPatternSyntaxOption}; )", QRegularExpression::CaseInsensitiveOption | QRegularExpression::ExtendedPatternSyntaxOption};
QRegularExpression field_day_exchange_re { QRegularExpression field_day_exchange_re {
R"( R"(
( (
@ -216,7 +219,7 @@ namespace
|[0-2]\d |[0-2]\d
|3[0-2] |3[0-2]
) )
[A-F]\ # class and space [A-F]\ * # class and optional space
( (
AB|AK|AL|AR|AZ|BC|CO|CT|DE|EB # ARRL/RAC section AB|AK|AL|AR|AZ|BC|CO|CT|DE|EB # ARRL/RAC section
|EMA|ENY|EPA|EWA|GA|GTA|IA|ID |EMA|ENY|EPA|EWA|GA|GTA|IA|ID
@ -395,6 +398,7 @@ public:
, QNetworkAccessManager * network_manager , QNetworkAccessManager * network_manager
, QDir const& temp_directory , QDir const& temp_directory
, QSettings * settings , QSettings * settings
, LogBook * logbook
, QWidget * parent); , QWidget * parent);
~impl (); ~impl ();
@ -480,11 +484,14 @@ private:
Q_SLOT void handle_transceiver_update (TransceiverState const&, unsigned sequence_number); Q_SLOT void handle_transceiver_update (TransceiverState const&, unsigned sequence_number);
Q_SLOT void handle_transceiver_failure (QString const& reason); Q_SLOT void handle_transceiver_failure (QString const& reason);
Q_SLOT void on_reset_highlighting_to_defaults_push_button_clicked (bool); Q_SLOT void on_reset_highlighting_to_defaults_push_button_clicked (bool);
Q_SLOT void on_rescan_log_push_button_clicked (bool);
Q_SLOT void on_LotW_CSV_fetch_push_button_clicked (bool); Q_SLOT void on_LotW_CSV_fetch_push_button_clicked (bool);
Q_SLOT void on_cbx2ToneSpacing_clicked(bool); Q_SLOT void on_cbx2ToneSpacing_clicked(bool);
Q_SLOT void on_cbx4ToneSpacing_clicked(bool); Q_SLOT void on_cbx4ToneSpacing_clicked(bool);
Q_SLOT void on_prompt_to_log_check_box_clicked(bool); Q_SLOT void on_prompt_to_log_check_box_clicked(bool);
Q_SLOT void on_cbAutoLog_clicked(bool); Q_SLOT void on_cbAutoLog_clicked(bool);
Q_SLOT void on_Field_Day_Exchange_textEdited (QString const&);
Q_SLOT void on_RTTY_Exchange_textEdited (QString const&);
// typenames used as arguments must match registered type names :( // typenames used as arguments must match registered type names :(
Q_SIGNAL void start_transceiver (unsigned seqeunce_number) const; Q_SIGNAL void start_transceiver (unsigned seqeunce_number) const;
@ -502,6 +509,7 @@ private:
QNetworkAccessManager * network_manager_; QNetworkAccessManager * network_manager_;
QSettings * settings_; QSettings * settings_;
LogBook * logbook_;
QDir doc_dir_; QDir doc_dir_;
QDir data_dir_; QDir data_dir_;
@ -638,8 +646,8 @@ private:
// delegate to implementation class // delegate to implementation class
Configuration::Configuration (QNetworkAccessManager * network_manager, QDir const& temp_directory, Configuration::Configuration (QNetworkAccessManager * network_manager, QDir const& temp_directory,
QSettings * settings, QWidget * parent) QSettings * settings, LogBook * logbook, QWidget * parent)
: m_ {this, network_manager, temp_directory, settings, parent} : m_ {this, network_manager, temp_directory, settings, logbook, parent}
{ {
} }
@ -905,13 +913,15 @@ namespace
} }
Configuration::impl::impl (Configuration * self, QNetworkAccessManager * network_manager Configuration::impl::impl (Configuration * self, QNetworkAccessManager * network_manager
, QDir const& temp_directory, QSettings * settings, QWidget * parent) , QDir const& temp_directory, QSettings * settings, LogBook * logbook
, QWidget * parent)
: QDialog {parent} : QDialog {parent}
, self_ {self} , self_ {self}
, transceiver_thread_ {nullptr} , transceiver_thread_ {nullptr}
, ui_ {new Ui::configuration_dialog} , ui_ {new Ui::configuration_dialog}
, network_manager_ {network_manager} , network_manager_ {network_manager}
, settings_ {settings} , settings_ {settings}
, logbook_ {logbook}
, doc_dir_ {doc_path ()} , doc_dir_ {doc_path ()}
, data_dir_ {data_path ()} , data_dir_ {data_path ()}
, temp_dir_ {temp_directory} , temp_dir_ {temp_directory}
@ -1005,8 +1015,8 @@ Configuration::impl::impl (Configuration * self, QNetworkAccessManager * network
ui_->callsign_line_edit->setValidator (new CallsignValidator {this}); ui_->callsign_line_edit->setValidator (new CallsignValidator {this});
ui_->grid_line_edit->setValidator (new MaidenheadLocatorValidator {this}); ui_->grid_line_edit->setValidator (new MaidenheadLocatorValidator {this});
ui_->add_macro_line_edit->setValidator (new QRegularExpressionValidator {message_alphabet, this}); ui_->add_macro_line_edit->setValidator (new QRegularExpressionValidator {message_alphabet, this});
ui_->Field_Day_Exchange->setValidator(new QRegularExpressionValidator {field_day_exchange_re}); ui_->Field_Day_Exchange->setValidator (new QRegularExpressionValidator {field_day_exchange_re, this});
ui_->RTTY_Exchange->setValidator(new QRegularExpressionValidator {RTTY_roundup_exchange_re}); ui_->RTTY_Exchange->setValidator (new QRegularExpressionValidator {RTTY_roundup_exchange_re, this});
ui_->udp_server_port_spin_box->setMinimum (1); ui_->udp_server_port_spin_box->setMinimum (1);
ui_->udp_server_port_spin_box->setMaximum (std::numeric_limits<port_type>::max ()); ui_->udp_server_port_spin_box->setMaximum (std::numeric_limits<port_type>::max ());
@ -1436,7 +1446,9 @@ void Configuration::impl::read_settings ()
stations_.station_list (settings_->value ("stations").value<StationList::Stations> ()); stations_.station_list (settings_->value ("stations").value<StationList::Stations> ());
decode_highlighing_model_.items (settings_->value ("DecodeHighlighting", QVariant::fromValue (DecodeHighlightingModel::default_items ())).value<DecodeHighlightingModel::HighlightItems> ()); auto highlight_items = settings_->value ("DecodeHighlighting", QVariant::fromValue (DecodeHighlightingModel::default_items ())).value<DecodeHighlightingModel::HighlightItems> ();
if (!highlight_items.size ()) highlight_items = DecodeHighlightingModel::default_items ();
decode_highlighing_model_.items (highlight_items);
highlight_by_mode_ = settings_->value("HighlightByMode", false).toBool (); highlight_by_mode_ = settings_->value("HighlightByMode", false).toBool ();
LotW_days_since_upload_ = settings_->value ("LotWDaysSinceLastUpload", 365).toInt (); LotW_days_since_upload_ = settings_->value ("LotWDaysSinceLastUpload", 365).toInt ();
lotw_users_.set_age_constraint (LotW_days_since_upload_); lotw_users_.set_age_constraint (LotW_days_since_upload_);
@ -2126,6 +2138,11 @@ void Configuration::impl::on_reset_highlighting_to_defaults_push_button_clicked
} }
} }
void Configuration::impl::on_rescan_log_push_button_clicked (bool /*clicked*/)
{
if (logbook_) logbook_->rescan ();
}
void Configuration::impl::on_LotW_CSV_fetch_push_button_clicked (bool /*checked*/) void Configuration::impl::on_LotW_CSV_fetch_push_button_clicked (bool /*checked*/)
{ {
lotw_users_.load (ui_->LotW_CSV_URL_line_edit->text (), true); lotw_users_.load (ui_->LotW_CSV_URL_line_edit->text (), true);
@ -2496,6 +2513,22 @@ void Configuration::impl::on_cbx4ToneSpacing_clicked(bool b)
if(b) ui_->cbx2ToneSpacing->setChecked(false); if(b) ui_->cbx2ToneSpacing->setChecked(false);
} }
void Configuration::impl::on_Field_Day_Exchange_textEdited (QString const& exchange)
{
auto text = exchange.simplified ().toUpper ();
auto class_pos = text.indexOf (QRegularExpression {R"([A-H])"});
if (class_pos >= 0 && text.size () >= class_pos + 2 && text.at (class_pos + 1) != QChar {' '})
{
text.insert (class_pos + 1, QChar {' '});
}
ui_->Field_Day_Exchange->setText (text);
}
void Configuration::impl::on_RTTY_Exchange_textEdited (QString const& exchange)
{
ui_->RTTY_Exchange->setText (exchange.toUpper ());
}
bool Configuration::impl::have_rig () bool Configuration::impl::have_rig ()
{ {
if (!open_rig ()) if (!open_rig ())

View File

@ -24,6 +24,7 @@ class QStringListModel;
class QHostAddress; class QHostAddress;
class LotWUsers; class LotWUsers;
class DecodeHighlightingModel; class DecodeHighlightingModel;
class LogBook;
// //
// Class Configuration // Class Configuration
@ -72,7 +73,7 @@ public:
Q_ENUM (Type2MsgGen) Q_ENUM (Type2MsgGen)
explicit Configuration (QNetworkAccessManager *, QDir const& temp_directory, QSettings * settings, explicit Configuration (QNetworkAccessManager *, QDir const& temp_directory, QSettings * settings,
QWidget * parent = nullptr); LogBook * logbook, QWidget * parent = nullptr);
~Configuration (); ~Configuration ();
void select_tab (int); void select_tab (int);

View File

@ -16,9 +16,6 @@
<layout class="QVBoxLayout" name="verticalLayout_2"> <layout class="QVBoxLayout" name="verticalLayout_2">
<item> <item>
<widget class="QTabWidget" name="configuration_tabs"> <widget class="QTabWidget" name="configuration_tabs">
<property name="toolTip">
<string>Select tab to change configuration parameters.</string>
</property>
<property name="currentIndex"> <property name="currentIndex">
<number>0</number> <number>0</number>
</property> </property>
@ -2197,7 +2194,7 @@ Right click for insert and delete options.</string>
<bool>true</bool> <bool>true</bool>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Enable or disable using the check boxes and right-click an item to change the foreground color, background color, or reset the item to default values. Drag and drop the items to change their priority, higher in the list is higher in priority.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Enable or disable using the check boxes and right-click an item to change or unset the foreground color, background color, or reset the item to default values. Drag and drop the items to change their priority, higher in the list is higher in priority.&lt;/p&gt;&lt;p&gt;Note that each foreground or background color may be either set or unset, unset means that it is not allocated for that item's type and lower priority items may apply.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="sizeAdjustPolicy"> <property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContents</enum> <enum>QAbstractScrollArea::AdjustToContents</enum>
@ -2233,8 +2230,8 @@ Right click for insert and delete options.</string>
</widget> </widget>
</item> </item>
<item> <item>
<layout class="QGridLayout" name="gridLayout_5"> <layout class="QHBoxLayout" name="horizontalLayout_15">
<item row="0" column="0"> <item>
<widget class="QCheckBox" name="highlight_by_mode_check_box"> <widget class="QCheckBox" name="highlight_by_mode_check_box">
<property name="toolTip"> <property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Check to indicate new DXCC entities, grid squares, and callsigns per mode.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Check to indicate new DXCC entities, grid squares, and callsigns per mode.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
@ -2244,6 +2241,29 @@ Right click for insert and delete options.</string>
</property> </property>
</widget> </widget>
</item> </item>
<item>
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="rescan_log_push_button">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Click to scan the wsjtx_log.adi ADIF file again for worked before information&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Rescan ADIF Log</string>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
</layout> </layout>
@ -2436,7 +2456,140 @@ Right click for insert and delete options.</string>
<property name="checked"> <property name="checked">
<bool>false</bool> <bool>false</bool>
</property> </property>
<layout class="QGridLayout" name="gridLayout_15" columnstretch="1,2,1,0,0"> <layout class="QGridLayout" name="gridLayout_15" columnstretch="1,0,0,0">
<item row="0" column="3">
<widget class="QRadioButton" name="rbHound">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;FT8 DXpedition mode: Hound operator calling the DX.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Hound</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<attribute name="buttonGroup">
<string notr="true">special_op_activity_button_group</string>
</attribute>
</widget>
</item>
<item row="1" column="0">
<widget class="QRadioButton" name="rbNA_VHF_Contest">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;North American VHF/UHF/Microwave contests and others in which a 4-character grid locator is the required exchange.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>NA VHF Contest</string>
</property>
<attribute name="buttonGroup">
<string notr="true">special_op_activity_button_group</string>
</attribute>
</widget>
</item>
<item row="0" column="0">
<widget class="QRadioButton" name="rbFox">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;FT8 DXpedition mode: Fox (DXpedition) operator.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Fox</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
<attribute name="buttonGroup">
<string notr="true">special_op_activity_button_group</string>
</attribute>
</widget>
</item>
<item row="2" column="0">
<widget class="QRadioButton" name="rbEU_VHF_Contest">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;European VHF+ contests requiring a signal report, serial number, and 6-character locator.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>EU VHF Contest</string>
</property>
<attribute name="buttonGroup">
<string notr="true">special_op_activity_button_group</string>
</attribute>
</widget>
</item>
<item row="2" column="3">
<layout class="QHBoxLayout" name="horizontalLayout_18" stretch="2,1,1">
<item>
<widget class="QRadioButton" name="rbRTTY_Roundup">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;ARRL RTTY Roundup and similar contests. Exchange is US state, Canadian province, or &amp;quot;DX&amp;quot;.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>ARRL RTTY Roundup</string>
</property>
<attribute name="buttonGroup">
<string notr="true">special_op_activity_button_group</string>
</attribute>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_10">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QFormLayout" name="formLayout_17">
<item row="0" column="0">
<widget class="QLabel" name="labRTTY">
<property name="text">
<string>RTTY RU Exch:</string>
</property>
<property name="buddy">
<cstring>RTTY_Exchange</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="RTTY_Exchange">
<property name="minimumSize">
<size>
<width>70</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;ARRL RTTY Roundup and similar contests. Exchange is US state, Canadian province, or &amp;quot;DX&amp;quot;.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>NJ</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item row="0" column="1" rowspan="3"> <item row="0" column="1" rowspan="3">
<spacer name="horizontalSpacer_11"> <spacer name="horizontalSpacer_11">
<property name="orientation"> <property name="orientation">
@ -2483,7 +2636,7 @@ Right click for insert and delete options.</string>
<item row="0" column="0"> <item row="0" column="0">
<widget class="QLabel" name="labFD"> <widget class="QLabel" name="labFD">
<property name="text"> <property name="text">
<string>Exch:</string> <string>FD Exch:</string>
</property> </property>
<property name="buddy"> <property name="buddy">
<cstring>Field_Day_Exchange</cstring> <cstring>Field_Day_Exchange</cstring>
@ -2513,152 +2666,6 @@ Right click for insert and delete options.</string>
</item> </item>
</layout> </layout>
</item> </item>
<item row="2" column="3">
<layout class="QHBoxLayout" name="horizontalLayout_18" stretch="2,1,1">
<item>
<widget class="QRadioButton" name="rbRTTY_Roundup">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;ARRL RTTY Roundup and similar contests. Exchange is US state, Canadian province, or &amp;quot;DX&amp;quot;.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>ARRL RTTY Roundup</string>
</property>
<attribute name="buttonGroup">
<string notr="true">special_op_activity_button_group</string>
</attribute>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_10">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QFormLayout" name="formLayout_17">
<item row="0" column="0">
<widget class="QLabel" name="labRTTY">
<property name="text">
<string>Exch:</string>
</property>
<property name="buddy">
<cstring>RTTY_Exchange</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="RTTY_Exchange">
<property name="minimumSize">
<size>
<width>70</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;ARRL RTTY Roundup and similar contests. Exchange is US state, Canadian province, or &amp;quot;DX&amp;quot;.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>NJ</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item row="0" column="0">
<widget class="QRadioButton" name="rbFox">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;FT8 DXpedition mode: Fox (DXpedition) operator.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Fox</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
<attribute name="buttonGroup">
<string notr="true">special_op_activity_button_group</string>
</attribute>
</widget>
</item>
<item row="2" column="0">
<widget class="QRadioButton" name="rbEU_VHF_Contest">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;European VHF+ contests requiring a signal report, serial number, and 6-character locator.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>EU VHF Contest</string>
</property>
<attribute name="buttonGroup">
<string notr="true">special_op_activity_button_group</string>
</attribute>
</widget>
</item>
<item row="1" column="0">
<widget class="QRadioButton" name="rbNA_VHF_Contest">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;North American VHF/UHF/Microwave contests and others in which a 4-character grid locator is the required exchange.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>NA VHF Contest</string>
</property>
<attribute name="buttonGroup">
<string notr="true">special_op_activity_button_group</string>
</attribute>
</widget>
</item>
<item row="0" column="4" rowspan="3">
<spacer name="horizontalSpacer_12">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="3">
<widget class="QRadioButton" name="rbHound">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;FT8 DXpedition mode: Hound operator calling the DX.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Hound</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<attribute name="buttonGroup">
<string notr="true">special_op_activity_button_group</string>
</attribute>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>
@ -2924,7 +2931,6 @@ Right click for insert and delete options.</string>
<tabstop>stations_table_view</tabstop> <tabstop>stations_table_view</tabstop>
<tabstop>highlighting_list_view</tabstop> <tabstop>highlighting_list_view</tabstop>
<tabstop>reset_highlighting_to_defaults_push_button</tabstop> <tabstop>reset_highlighting_to_defaults_push_button</tabstop>
<tabstop>highlight_by_mode_check_box</tabstop>
<tabstop>LotW_CSV_URL_line_edit</tabstop> <tabstop>LotW_CSV_URL_line_edit</tabstop>
<tabstop>LotW_CSV_fetch_push_button</tabstop> <tabstop>LotW_CSV_fetch_push_button</tabstop>
<tabstop>LotW_days_since_upload_spin_box</tabstop> <tabstop>LotW_days_since_upload_spin_box</tabstop>
@ -3012,13 +3018,13 @@ Right click for insert and delete options.</string>
</connection> </connection>
</connections> </connections>
<buttongroups> <buttongroups>
<buttongroup name="CAT_stop_bits_button_group"/>
<buttongroup name="TX_audio_source_button_group"/>
<buttongroup name="TX_mode_button_group"/>
<buttongroup name="split_mode_button_group"/>
<buttongroup name="CAT_handshake_button_group"/> <buttongroup name="CAT_handshake_button_group"/>
<buttongroup name="special_op_activity_button_group"/> <buttongroup name="split_mode_button_group"/>
<buttongroup name="PTT_method_button_group"/>
<buttongroup name="CAT_data_bits_button_group"/> <buttongroup name="CAT_data_bits_button_group"/>
<buttongroup name="PTT_method_button_group"/>
<buttongroup name="TX_mode_button_group"/>
<buttongroup name="CAT_stop_bits_button_group"/>
<buttongroup name="special_op_activity_button_group"/>
<buttongroup name="TX_audio_source_button_group"/>
</buttongroups> </buttongroups>
</ui> </ui>

View File

@ -1,8 +1,8 @@
Notes on WSJT-X Installation for Mac OS X Notes on WSJT-X Installation for Mac OS X
----------------------------------------- -----------------------------------------
Updated 16 July 2017 Updated 21 October 2018
-------------------- -----------------------
If you have already downloaded a previous version of WSJT-X then I suggest If you have already downloaded a previous version of WSJT-X then I suggest
you change the name in the Applications folder from WSJT-X to WSJT-X_previous you change the name in the Applications folder from WSJT-X to WSJT-X_previous
@ -68,6 +68,12 @@ under the WSJT-X Menu and fill in various station details on the General panel.
I recommend checking the 4 boxes under the Display heading and the first 4 boxes under I recommend checking the 4 boxes under the Display heading and the first 4 boxes under
the Behaviour heading. the Behaviour heading.
IMPORTANT: If you are using macOS 10.14 (Mojave) it is important to note that the default setting
for audio input is "block". In order to receive audio from WSJT-X you must visit
System Preferences > Security & Privacy > Privacy and, with WSJT-X launched, select "Microphone"
under Location Services and wsjtx should appear in the panel. Check the "Allow" box. You will
have to quit WSJT-X for this change to take effect.
Next visit the Audio panel and select the Audio Codec you use to communicate between Next visit the Audio panel and select the Audio Codec you use to communicate between
WSJT-X and your rig. There are so many audio interfaces available that it is not WSJT-X and your rig. There are so many audio interfaces available that it is not
possible to give detailed advice on selection. If you have difficulties contact me. possible to give detailed advice on selection. If you have difficulties contact me.
@ -86,7 +92,7 @@ be located in the device driver directory /dev. You should install your driver
and then re-launch WSJT-X. Return to the the Radio panel in Preferences and in and then re-launch WSJT-X. Return to the the Radio panel in Preferences and in
the "Serial port" panel select your driver from the list that is presented. If the "Serial port" panel select your driver from the list that is presented. If
for some reason your driver is not shown, then insert the full name for some reason your driver is not shown, then insert the full name
of your driver in the Serial Port panel. Such as: /dev/tty.PL2303-00002226 or of your driver in the Serial Port panel. Such as: /dev/cu.PL2303-00002226 or
whatever driver you have. The /dev/ prefix is mandatory. Set the relevant whatever driver you have. The /dev/ prefix is mandatory. Set the relevant
communication parameters as required by your transceiver and click "Test CAT" to communication parameters as required by your transceiver and click "Test CAT" to
check. check.

View File

@ -405,7 +405,7 @@ void MessageClient::status_update (Frequency f, QString const& mode, QString con
, qint32 rx_df, qint32 tx_df, QString const& de_call , qint32 rx_df, qint32 tx_df, QString const& de_call
, QString const& de_grid, QString const& dx_grid , QString const& de_grid, QString const& dx_grid
, bool watchdog_timeout, QString const& sub_mode , bool watchdog_timeout, QString const& sub_mode
, bool fast_mode) , bool fast_mode, quint8 special_op_mode)
{ {
if (m_->server_port_ && !m_->server_string_.isEmpty ()) if (m_->server_port_ && !m_->server_string_.isEmpty ())
{ {
@ -414,7 +414,7 @@ void MessageClient::status_update (Frequency f, QString const& mode, QString con
out << f << mode.toUtf8 () << dx_call.toUtf8 () << report.toUtf8 () << tx_mode.toUtf8 () out << f << mode.toUtf8 () << dx_call.toUtf8 () << report.toUtf8 () << tx_mode.toUtf8 ()
<< tx_enabled << transmitting << decoding << rx_df << tx_df << de_call.toUtf8 () << tx_enabled << transmitting << decoding << rx_df << tx_df << de_call.toUtf8 ()
<< de_grid.toUtf8 () << dx_grid.toUtf8 () << watchdog_timeout << sub_mode.toUtf8 () << de_grid.toUtf8 () << dx_grid.toUtf8 () << watchdog_timeout << sub_mode.toUtf8 ()
<< fast_mode; << fast_mode << special_op_mode;
m_->send_message (out, message); m_->send_message (out, message);
} }
} }
@ -462,7 +462,8 @@ void MessageClient::qso_logged (QDateTime time_off, QString const& dx_call, QStr
, QString const& report_received, QString const& tx_power , QString const& report_received, QString const& tx_power
, QString const& comments, QString const& name, QDateTime time_on , QString const& comments, QString const& name, QDateTime time_on
, QString const& operator_call, QString const& my_call , QString const& operator_call, QString const& my_call
, QString const& my_grid) , QString const& my_grid, QString const& exchange_sent
, QString const& exchange_rcvd)
{ {
if (m_->server_port_ && !m_->server_string_.isEmpty ()) if (m_->server_port_ && !m_->server_string_.isEmpty ())
{ {
@ -470,7 +471,8 @@ void MessageClient::qso_logged (QDateTime time_off, QString const& dx_call, QStr
NetworkMessage::Builder out {&message, NetworkMessage::QSOLogged, m_->id_, m_->schema_}; NetworkMessage::Builder out {&message, NetworkMessage::QSOLogged, m_->id_, m_->schema_};
out << time_off << dx_call.toUtf8 () << dx_grid.toUtf8 () << dial_frequency << mode.toUtf8 () out << time_off << dx_call.toUtf8 () << dx_grid.toUtf8 () << dial_frequency << mode.toUtf8 ()
<< report_sent.toUtf8 () << report_received.toUtf8 () << tx_power.toUtf8 () << comments.toUtf8 () << report_sent.toUtf8 () << report_received.toUtf8 () << tx_power.toUtf8 () << comments.toUtf8 ()
<< name.toUtf8 () << time_on << operator_call.toUtf8 () << my_call.toUtf8 () << my_grid.toUtf8 (); << name.toUtf8 () << time_on << operator_call.toUtf8 () << my_call.toUtf8 () << my_grid.toUtf8 ()
<< exchange_sent.toUtf8 () << exchange_rcvd.toUtf8 ();
m_->send_message (out, message); m_->send_message (out, message);
} }
} }

View File

@ -52,7 +52,7 @@ public:
, QString const& tx_mode, bool tx_enabled, bool transmitting, bool decoding , QString const& tx_mode, bool tx_enabled, bool transmitting, bool decoding
, qint32 rx_df, qint32 tx_df, QString const& de_call, QString const& de_grid , qint32 rx_df, qint32 tx_df, QString const& de_call, QString const& de_grid
, QString const& dx_grid, bool watchdog_timeout, QString const& sub_mode , QString const& dx_grid, bool watchdog_timeout, QString const& sub_mode
, bool fast_mode); , bool fast_mode, quint8 special_op_mode);
Q_SLOT void decode (bool is_new, QTime time, qint32 snr, float delta_time, quint32 delta_frequency Q_SLOT void decode (bool is_new, QTime time, qint32 snr, float delta_time, quint32 delta_frequency
, QString const& mode, QString const& message, bool low_confidence , QString const& mode, QString const& message, bool low_confidence
, bool off_air); , bool off_air);
@ -64,7 +64,8 @@ public:
, Frequency dial_frequency, QString const& mode, QString const& report_sent , Frequency dial_frequency, QString const& mode, QString const& report_sent
, QString const& report_received, QString const& tx_power, QString const& comments , QString const& report_received, QString const& tx_power, QString const& comments
, QString const& name, QDateTime time_on, QString const& operator_call , QString const& name, QDateTime time_on, QString const& operator_call
, QString const& my_call, QString const& my_grid); , QString const& my_call, QString const& my_grid
, QString const& exchange_sent, QString const& exchange_rcvd);
// ADIF_record argument should be valid ADIF excluding any <EOR> end // ADIF_record argument should be valid ADIF excluding any <EOR> end
// of record marker // of record marker

View File

@ -216,9 +216,10 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s
bool watchdog_timeout {false}; bool watchdog_timeout {false};
QByteArray sub_mode; QByteArray sub_mode;
bool fast_mode {false}; bool fast_mode {false};
quint8 special_op_mode {0};
in >> f >> mode >> dx_call >> report >> tx_mode >> tx_enabled >> transmitting >> decoding in >> f >> mode >> dx_call >> report >> tx_mode >> tx_enabled >> transmitting >> decoding
>> rx_df >> tx_df >> de_call >> de_grid >> dx_grid >> watchdog_timeout >> sub_mode >> rx_df >> tx_df >> de_call >> de_grid >> dx_grid >> watchdog_timeout >> sub_mode
>> fast_mode; >> fast_mode >> special_op_mode;
if (check_status (in) != Fail) if (check_status (in) != Fail)
{ {
Q_EMIT self_->status_update (id, f, QString::fromUtf8 (mode), QString::fromUtf8 (dx_call) Q_EMIT self_->status_update (id, f, QString::fromUtf8 (mode), QString::fromUtf8 (dx_call)
@ -226,7 +227,8 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s
, tx_enabled, transmitting, decoding, rx_df, tx_df , tx_enabled, transmitting, decoding, rx_df, tx_df
, QString::fromUtf8 (de_call), QString::fromUtf8 (de_grid) , QString::fromUtf8 (de_call), QString::fromUtf8 (de_grid)
, QString::fromUtf8 (dx_grid), watchdog_timeout , QString::fromUtf8 (dx_grid), watchdog_timeout
, QString::fromUtf8 (sub_mode), fast_mode); , QString::fromUtf8 (sub_mode), fast_mode
, special_op_mode);
} }
} }
break; break;
@ -294,8 +296,11 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s
QByteArray operator_call; QByteArray operator_call;
QByteArray my_call; QByteArray my_call;
QByteArray my_grid; QByteArray my_grid;
QByteArray exchange_sent;
QByteArray exchange_rcvd;
in >> time_off >> dx_call >> dx_grid >> dial_frequency >> mode >> report_sent >> report_received in >> time_off >> dx_call >> dx_grid >> dial_frequency >> mode >> report_sent >> report_received
>> tx_power >> comments >> name >> time_on >> operator_call >> my_call >> my_grid; >> tx_power >> comments >> name >> time_on >> operator_call >> my_call >> my_grid
>> exchange_sent >> exchange_rcvd;
if (check_status (in) != Fail) if (check_status (in) != Fail)
{ {
Q_EMIT self_->qso_logged (id, time_off, QString::fromUtf8 (dx_call), QString::fromUtf8 (dx_grid) Q_EMIT self_->qso_logged (id, time_off, QString::fromUtf8 (dx_call), QString::fromUtf8 (dx_grid)
@ -303,7 +308,8 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s
, QString::fromUtf8 (report_received), QString::fromUtf8 (tx_power) , QString::fromUtf8 (report_received), QString::fromUtf8 (tx_power)
, QString::fromUtf8 (comments), QString::fromUtf8 (name), time_on , QString::fromUtf8 (comments), QString::fromUtf8 (name), time_on
, QString::fromUtf8 (operator_call), QString::fromUtf8 (my_call) , QString::fromUtf8 (operator_call), QString::fromUtf8 (my_call)
, QString::fromUtf8 (my_grid)); , QString::fromUtf8 (my_grid), QString::fromUtf8 (exchange_sent)
, QString::fromUtf8 (exchange_rcvd));
} }
} }
break; break;

View File

@ -76,7 +76,8 @@ public:
, QString const& report, QString const& tx_mode, bool tx_enabled , QString const& report, QString const& tx_mode, bool tx_enabled
, bool transmitting, bool decoding, qint32 rx_df, qint32 tx_df , bool transmitting, bool decoding, qint32 rx_df, qint32 tx_df
, QString const& de_call, QString const& de_grid, QString const& dx_grid , QString const& de_call, QString const& de_grid, QString const& dx_grid
, bool watchdog_timeout, QString const& sub_mode, bool fast_mode); , bool watchdog_timeout, QString const& sub_mode, bool fast_mode
, quint8 special_op_mode);
Q_SIGNAL void client_closed (QString const& id); Q_SIGNAL void client_closed (QString const& id);
Q_SIGNAL void decode (bool is_new, QString const& id, QTime time, qint32 snr, float delta_time Q_SIGNAL void decode (bool is_new, QString const& id, QTime time, qint32 snr, float delta_time
, quint32 delta_frequency, QString const& mode, QString const& message , quint32 delta_frequency, QString const& mode, QString const& message
@ -88,7 +89,8 @@ public:
, Frequency dial_frequency, QString const& mode, QString const& report_sent , Frequency dial_frequency, QString const& mode, QString const& report_sent
, QString const& report_received, QString const& tx_power, QString const& comments , QString const& report_received, QString const& tx_power, QString const& comments
, QString const& name, QDateTime time_on, QString const& operator_call , QString const& name, QDateTime time_on, QString const& operator_call
, QString const& my_call, QString const& my_grid); , QString const& my_call, QString const& my_grid
, QString const& exchange_sent, QString const& exchange_rcvd);
Q_SIGNAL void clear_decodes (QString const& id); Q_SIGNAL void clear_decodes (QString const& id);
Q_SIGNAL void logged_ADIF (QString const& id, QByteArray const& ADIF); Q_SIGNAL void logged_ADIF (QString const& id, QByteArray const& ADIF);

View File

@ -124,6 +124,7 @@
* Tx Watchdog bool * Tx Watchdog bool
* Sub-mode utf8 * Sub-mode utf8
* Fast mode bool * Fast mode bool
* Special operation mode quint8
* *
* WSJT-X sends this status message when various internal state * WSJT-X sends this status message when various internal state
* changes to allow the server to track the relevant state of each * changes to allow the server to track the relevant state of each
@ -142,10 +143,22 @@
* At the start and end of decoding, * At the start and end of decoding,
* When the Rx DF changes, * When the Rx DF changes,
* When the Tx DF changes, * When the Tx DF changes,
* When the DE call or grid changes (currently when settings are exited), * When settings are exited,
* When the DX call or grid changes, * When the DX call or grid changes,
* When the Tx watchdog is set or reset. * When the Tx watchdog is set or reset.
* *
* The Special operation mode is an enumeration that indicates the
* setting selected in the WSJT-X "Settings->Advanced->Special
* operating activity" panel. The values are as follows:
*
* 0 -> NONE
* 1 -> NA VHF
* 2 -> EU VHF
* 3 -> FIELD DAY
* 4 -> RTTY RU
* 5 -> FOX
* 6 -> HOUND
*
* *
* Decode Out 2 quint32 * Decode Out 2 quint32
* Id (unique key) utf8 * Id (unique key) utf8
@ -240,6 +253,8 @@
* Operator call utf8 * Operator call utf8
* My call utf8 * My call utf8
* My grid utf8 * My grid utf8
* Exchange sent utf8
* Exchange received utf8
* *
* The QSO logged message is sent to the server(s) when the * The QSO logged message is sent to the server(s) when the
* WSJT-X user accepts the "Log QSO" dialog by clicking the "OK" * WSJT-X user accepts the "Log QSO" dialog by clicking the "OK"

View File

@ -136,12 +136,12 @@ namespace Radio
// the full call if no valid prefix (or prefix as a suffix) is specified // the full call if no valid prefix (or prefix as a suffix) is specified
QString effective_prefix (QString callsign) QString effective_prefix (QString callsign)
{ {
auto prefix = callsign.toUpper (); auto prefix = callsign;
auto slash_pos = callsign.indexOf ('/'); auto slash_pos = callsign.indexOf ('/');
if (slash_pos >= 0) if (slash_pos >= 0)
{ {
auto right_size = callsign.size () - slash_pos - 1; auto right_size = callsign.size () - slash_pos - 1;
if (right_size >= slash_pos) // naive call is longer than if (right_size >= slash_pos) // native call is longer than
// prefix/suffix algorithm // prefix/suffix algorithm
{ {
prefix = callsign.left (slash_pos); prefix = callsign.left (slash_pos);
@ -157,6 +157,6 @@ namespace Radio
} }
} }
} }
return prefix; return prefix.toUpper ();
} }
} }

View File

@ -12,6 +12,64 @@
Copyright 2001 - 2018 by Joe Taylor, K1JT. Copyright 2001 - 2018 by Joe Taylor, K1JT.
Release: WSJT-X 2.0
December 10, 2018
-----------------------
WSJT-X 2.0 is a major update that introduces new protocols for FT8 and
MSK144. The new protocols become the world-wide standards on December
10, 2018.
WSJT-X 2.0 cannot communicate in these modes with other stations using
WSJT-X v1.9.1 or earlier.
Please help by urging everyone to upgrade no later than January 1, 2019.
New features since WSJT-X v1.9.1:
1. Compound and nonstandard callsigns are automatically recognized and
handled using new message formats.
2. The new FT8 protocol provides optimized message formats for North
American VHF contests, European VHF contests, ARRL Field Day, and ARRL
RTTY Roundup. Similarly, the new MSK144 protocol provides optimized
message formats for North American VHF and European VHF contests.
Full support is provided for "/R" and "/P" calls in the relevant
contests.
3. The new protocols provide nearly equal (or better) sensitivity
compared to the old ones, and lower false decode rates.
4. New logging features are provided for contesting and for "Fox"
(DXpedition) mode. Logging is optionally integrated with N1MM Logger+
and WriteLog.
5. Color highlighting of decoded messages provides worked-before
status for callsigns, grid locators, DXCC entities, continents, CQ
Zones, and ITU zones on a “by band” and “by mode” basis, and for
stations that have uploaded their logs to Logbook of the World (LoTW)
within a specified time interval.
6. The WSPR decoder now achieves decodes down to S/N = -31 dB. For
the particular benefit of LF/MF users, an option "No own call decodes"
has been added.
7. The UDP messages sent to companion programs have been expanded and
improved.
Some details of changes since WSJT-X-rc5 include the following:
- Initial load of ADIF log in background
- Correct the UTC displayed in Fox/Contest log
- Faster entry and correct scrolling for Fox/Contest log
- Add contest exchanges and contest type to UDP logged QSO message
- Fix a bug that suppressed decodes with negative DT.
- AK and HI are DXCCs, not states, for RTTY Roundup
- Fix improper truncation of some non-FT8 messages in ALL.TXT
- Various minor bug fixes and code cleanup
- Update the WSJT-X User Guide to v2.0 (more to come...)
- Update cty.dat
Release: WSJT-X 2.0-rc5 Release: WSJT-X 2.0-rc5
November 26, 2018 November 26, 2018
----------------------- -----------------------
@ -36,6 +94,14 @@ Changes from WSJT-X 2.0-rc4 include the following:
- Fix a bug causing false AP decodes in JT65 VHF+ operation - Fix a bug causing false AP decodes in JT65 VHF+ operation
- Fix a bug that could switch unexpectedly from JT65 to JT9 mode - Fix a bug that could switch unexpectedly from JT65 to JT9 mode
PLEASE NOTE: As far as WSJT-X 2.0 (RC4, RC5, and GA releases) are
concerned, signals using the old FT8 protocol are undecodable
interference. This means that regenerated replicas cannot be
subtracted from received data, and consequently second- and third-pass
decodes may be impeded. Full performance of the 77-bit decoder will
not be realized until most signals on a crowded band are using the
new FT8 protocol.
Release: WSJT-X 2.0-rc4 Release: WSJT-X 2.0-rc4
November 12, 2018 November 12, 2018

View File

@ -72,7 +72,7 @@ namespace
} }
BeaconsModel::BeaconsModel (QObject * parent) BeaconsModel::BeaconsModel (QObject * parent)
: QStandardItemModel {0, sizeof (headings) / sizeof (headings[0]), parent} : QStandardItemModel {0, sizeof headings / sizeof headings[0], parent}
{ {
int column {0}; int column {0};
for (auto const& heading : headings) for (auto const& heading : headings)

View File

@ -244,15 +244,29 @@ void ClientWidget::update_status (QString const& id, Frequency f, QString const&
, QString const& report, QString const& tx_mode, bool tx_enabled , QString const& report, QString const& tx_mode, bool tx_enabled
, bool transmitting, bool decoding, qint32 rx_df, qint32 tx_df , bool transmitting, bool decoding, qint32 rx_df, qint32 tx_df
, QString const& de_call, QString const& de_grid, QString const& dx_grid , QString const& de_call, QString const& de_grid, QString const& dx_grid
, bool watchdog_timeout, QString const& sub_mode, bool fast_mode) , bool watchdog_timeout, QString const& sub_mode, bool fast_mode
, quint8 special_op_mode)
{ {
if (id == id_) if (id == id_)
{ {
fast_mode_ = fast_mode; fast_mode_ = fast_mode;
decodes_proxy_model_.de_call (de_call); decodes_proxy_model_.de_call (de_call);
decodes_proxy_model_.rx_df (rx_df); decodes_proxy_model_.rx_df (rx_df);
de_label_->setText (de_call.size () >= 0 ? QString {"DE: %1%2"}.arg (de_call) QString special;
.arg (de_grid.size () ? '(' + de_grid + ')' : QString {}) : QString {}); switch (special_op_mode)
{
case 1: special = "[NA VHF]"; break;
case 2: special = "[EU VHF]"; break;
case 3: special = "[FD]"; break;
case 4: special = "[RTTY RU]"; break;
case 5: special = "[Fox]"; break;
case 6: special = "[Hound]"; break;
default: break;
}
de_label_->setText (de_call.size () >= 0 ? QString {"DE: %1%2%3"}.arg (de_call)
.arg (de_grid.size () ? '(' + de_grid + ')' : QString {})
.arg (special)
: QString {});
mode_label_->setText (QString {"Mode: %1%2%3%4"} mode_label_->setText (QString {"Mode: %1%2%3%4"}
.arg (mode) .arg (mode)
.arg (sub_mode) .arg (sub_mode)

View File

@ -32,7 +32,8 @@ public:
, QString const& report, QString const& tx_mode, bool tx_enabled , QString const& report, QString const& tx_mode, bool tx_enabled
, bool transmitting, bool decoding, qint32 rx_df, qint32 tx_df , bool transmitting, bool decoding, qint32 rx_df, qint32 tx_df
, QString const& de_call, QString const& de_grid, QString const& dx_grid , QString const& de_call, QString const& de_grid, QString const& dx_grid
, bool watchdog_timeout, QString const& sub_mode, bool fast_mode); , bool watchdog_timeout, QString const& sub_mode, bool fast_mode
, quint8 special_op_mode);
Q_SLOT void decode_added (bool is_new, QString const& client_id, QTime, qint32 snr Q_SLOT void decode_added (bool is_new, QString const& client_id, QTime, qint32 snr
, float delta_time, quint32 delta_frequency, QString const& mode , float delta_time, quint32 delta_frequency, QString const& mode
, QString const& message, bool low_confidence, bool off_air); , QString const& message, bool low_confidence, bool off_air);

View File

@ -75,7 +75,7 @@ namespace
} }
DecodesModel::DecodesModel (QObject * parent) DecodesModel::DecodesModel (QObject * parent)
: QStandardItemModel {0, sizeof (headings) / sizeof (headings[0]), parent} : QStandardItemModel {0, sizeof headings / sizeof headings[0], parent}
{ {
int column {0}; int column {0};
for (auto const& heading : headings) for (auto const& heading : headings)

View File

@ -25,12 +25,14 @@ namespace
QT_TRANSLATE_NOOP ("MessageAggregatorMainWindow", "Operator"), QT_TRANSLATE_NOOP ("MessageAggregatorMainWindow", "Operator"),
QT_TRANSLATE_NOOP ("MessageAggregatorMainWindow", "My Call"), QT_TRANSLATE_NOOP ("MessageAggregatorMainWindow", "My Call"),
QT_TRANSLATE_NOOP ("MessageAggregatorMainWindow", "My Grid"), QT_TRANSLATE_NOOP ("MessageAggregatorMainWindow", "My Grid"),
QT_TRANSLATE_NOOP ("MessageAggregatorMainWindow", "Exchange Sent"),
QT_TRANSLATE_NOOP ("MessageAggregatorMainWindow", "Exchange Rcvd"),
QT_TRANSLATE_NOOP ("MessageAggregatorMainWindow", "Comments"), QT_TRANSLATE_NOOP ("MessageAggregatorMainWindow", "Comments"),
}; };
} }
MessageAggregatorMainWindow::MessageAggregatorMainWindow () MessageAggregatorMainWindow::MessageAggregatorMainWindow ()
: log_ {new QStandardItemModel {0, 14, this}} : log_ {new QStandardItemModel {0, sizeof headings / sizeof headings[0], this}}
, decodes_model_ {new DecodesModel {this}} , decodes_model_ {new DecodesModel {this}}
, beacons_model_ {new BeaconsModel {this}} , beacons_model_ {new BeaconsModel {this}}
, server_ {new MessageServer {this}} , server_ {new MessageServer {this}}
@ -209,7 +211,8 @@ void MessageAggregatorMainWindow::log_qso (QString const& /*id*/, QDateTime time
, QString const& report_sent, QString const& report_received , QString const& report_sent, QString const& report_received
, QString const& tx_power, QString const& comments , QString const& tx_power, QString const& comments
, QString const& name, QDateTime time_on, QString const& operator_call , QString const& name, QDateTime time_on, QString const& operator_call
, QString const& my_call, QString const& my_grid) , QString const& my_call, QString const& my_grid
, QString const& exchange_sent, QString const& exchange_rcvd)
{ {
QList<QStandardItem *> row; QList<QStandardItem *> row;
row << new QStandardItem {time_on.toString ("dd-MMM-yyyy hh:mm:ss")} row << new QStandardItem {time_on.toString ("dd-MMM-yyyy hh:mm:ss")}
@ -225,6 +228,8 @@ void MessageAggregatorMainWindow::log_qso (QString const& /*id*/, QDateTime time
<< new QStandardItem {operator_call} << new QStandardItem {operator_call}
<< new QStandardItem {my_call} << new QStandardItem {my_call}
<< new QStandardItem {my_grid} << new QStandardItem {my_grid}
<< new QStandardItem {exchange_sent}
<< new QStandardItem {exchange_rcvd}
<< new QStandardItem {comments}; << new QStandardItem {comments};
log_->appendRow (row); log_->appendRow (row);
log_table_view_->resizeColumnsToContents (); log_table_view_->resizeColumnsToContents ();

View File

@ -32,7 +32,8 @@ public:
, Frequency dial_frequency, QString const& mode, QString const& report_sent , Frequency dial_frequency, QString const& mode, QString const& report_sent
, QString const& report_received, QString const& tx_power, QString const& comments , QString const& report_received, QString const& tx_power, QString const& comments
, QString const& name, QDateTime time_on, QString const& operator_call , QString const& name, QDateTime time_on, QString const& operator_call
, QString const& my_call, QString const& my_grid); , QString const& my_call, QString const& my_grid
, QString const& exchange_sent, QString const& exchange_rcvd);
private: private:
void add_client (QString const& id, QString const& version, QString const& revision); void add_client (QString const& id, QString const& version, QString const& revision);

View File

@ -50,7 +50,8 @@ public:
, QString const& /*report*/, QString const& /*tx_mode*/, bool /*tx_enabled*/ , QString const& /*report*/, QString const& /*tx_mode*/, bool /*tx_enabled*/
, bool /*transmitting*/, bool /*decoding*/, qint32 /*rx_df*/, qint32 /*tx_df*/ , bool /*transmitting*/, bool /*decoding*/, qint32 /*rx_df*/, qint32 /*tx_df*/
, QString const& /*de_call*/, QString const& /*de_grid*/, QString const& /*dx_grid*/ , QString const& /*de_call*/, QString const& /*de_grid*/, QString const& /*dx_grid*/
, bool /* watchdog_timeout */, QString const& sub_mode, bool /*fast_mode*/) , bool /* watchdog_timeout */, QString const& sub_mode, bool /*fast_mode*/
, quint8 /*special_op_mode*/)
{ {
if (id == id_) if (id == id_)
{ {
@ -99,7 +100,8 @@ public:
, Frequency dial_frequency, QString const& mode, QString const& report_sent , Frequency dial_frequency, QString const& mode, QString const& report_sent
, QString const& report_received, QString const& tx_power , QString const& report_received, QString const& tx_power
, QString const& comments, QString const& name, QDateTime time_on , QString const& comments, QString const& name, QDateTime time_on
, QString const& operator_call, QString const& my_call, QString const& my_grid) , QString const& operator_call, QString const& my_call, QString const& my_grid
, QString const& exchange_sent, QString const& exchange_rcvd)
{ {
if (client_id == id_) if (client_id == id_)
{ {
@ -107,7 +109,8 @@ public:
<< "freq:" << dial_frequency << "mode:" << mode << "rpt_sent:" << report_sent << "freq:" << dial_frequency << "mode:" << mode << "rpt_sent:" << report_sent
<< "rpt_rcvd:" << report_received << "Tx_pwr:" << tx_power << "comments:" << comments << "rpt_rcvd:" << report_received << "Tx_pwr:" << tx_power << "comments:" << comments
<< "name:" << name << "operator_call:" << operator_call << "my_call:" << my_call << "name:" << name << "operator_call:" << operator_call << "my_call:" << my_call
<< "my_grid:" << my_grid; << "my_grid:" << my_grid << "exchange_sent:" << exchange_sent
<< "exchange_rcvd:" << exchange_rcvd;
std::cout << QByteArray {80, '-'}.data () << '\n'; std::cout << QByteArray {80, '-'}.data () << '\n';
std::cout << tr ("%1: Logged %2 grid: %3 power: %4 sent: %5 recd: %6 freq: %7 time_off: %8 op: %9 my_call: %10 my_grid: %11") std::cout << tr ("%1: Logged %2 grid: %3 power: %4 sent: %5 recd: %6 freq: %7 time_off: %8 op: %9 my_call: %10 my_grid: %11")
.arg (id_).arg (dx_call).arg (dx_grid).arg (tx_power).arg (report_sent).arg (report_received) .arg (id_).arg (dx_call).arg (dx_grid).arg (tx_power).arg (report_sent).arg (report_received)

1635
cty.dat

File diff suppressed because it is too large Load Diff

View File

@ -12,14 +12,14 @@ Example:
[displayed text] PSK Reporter [displayed text] PSK Reporter
Perform searches from the doc root directory: doc Perform searches from the doc root directory: doc
Search: grep -rl --exclude-dir="*\.svn" {pskreporter} . Search: grep -rl --exclude-dir="*\.git" {pskreporter} .
grep -rl --exclude-dir="*\.svn" PSK Reporter . grep -rl --exclude-dir="*\.git" PSK Reporter .
grep -rl --exclude-dir="*\.svn" {devsvn} . grep -rl --exclude-dir="*\.git" {devrepo} .
grep -rl --exclude-dir="*\.svn" {kvasd} . grep -rl --exclude-dir="*\.git" {kvasd} .
grep -rl --exclude-dir="*\.svn" {ntpsetup} . grep -rl --exclude-dir="*\.git" {ntpsetup} .
Include links.adoc: grep -rl --exclude-dir="*\.svn" pskreporter . Include links.adoc: grep -rl --exclude-dir="*\.git" pskreporter .
Exclude links.adoc: grep -rl --exclude-dir="*\.svn" {pskreporter} . Exclude links.adoc: grep -rl --exclude-dir="*\.git" {pskreporter} .
Note(s): Note(s):
a). Don't forget a space then "." at the end. a). Don't forget a space then "." at the end.
@ -54,8 +54,8 @@ d). Edit lines as needed. Keeping them in alphabetic order help see dupes.
:raspbian: http://physics.princeton.edu/pulsar/K1JT/wsjtx_{VERSION}_armhf.deb[wsjtx_{VERSION}_armhf.deb] :raspbian: http://physics.princeton.edu/pulsar/K1JT/wsjtx_{VERSION}_armhf.deb[wsjtx_{VERSION}_armhf.deb]
:debian: http://www.debian.org/[Debian] :debian: http://www.debian.org/[Debian]
:dev_guide: http://www.physics.princeton.edu/pulsar/K1JT/wsjtx-doc/wsjt-dev-guide.html[Dev-Guide] :dev_guide: http://www.physics.princeton.edu/pulsar/K1JT/wsjtx-doc/wsjt-dev-guide.html[Dev-Guide]
:devsvn1: http://sourceforge.net/p/wsjt/wsjt/HEAD/tree/[Devel-SVN] :devsvn: http://sourceforge.net/p/wsjt/wsjt/HEAD/tree/[Devel-SVN]
:devsvn: http://sourceforge.net/p/wsjt/wsjt/HEAD/tree/[SourceForge] :devrepo: https://sourceforge.net/p/wsjt/wsjtx/ci/master/tree/[SourceForge]
:dimension4: http://www.thinkman.com/dimension4/[Thinking Man Software] :dimension4: http://www.thinkman.com/dimension4/[Thinking Man Software]
:download: http://physics.princeton.edu/pulsar/K1JT/wsjtx.html[Download Page] :download: http://physics.princeton.edu/pulsar/K1JT/wsjtx.html[Download Page]
:dxatlas: http://www.dxatlas.com/[Afreet Software, Inc.] :dxatlas: http://www.dxatlas.com/[Afreet Software, Inc.]
@ -67,7 +67,7 @@ d). Edit lines as needed. Keeping them in alphabetic order help see dupes.
:fmt_group: https://groups.yahoo.com/neo/groups/FMT-nuts/info[FMT Group] :fmt_group: https://groups.yahoo.com/neo/groups/FMT-nuts/info[FMT Group]
:fmt_k5cm: http://www.k5cm.com/[FMT Event Info] :fmt_k5cm: http://www.k5cm.com/[FMT Event Info]
:fmt_wspr: http://www.physics.princeton.edu/pulsar/K1JT/FMT_User.pdf[Accurate Frequency Measurements with your WSPR Setup] :fmt_wspr: http://www.physics.princeton.edu/pulsar/K1JT/FMT_User.pdf[Accurate Frequency Measurements with your WSPR Setup]
:ft8_tips: http://www.physics.princeton.edu/pulsar/K1JT/FT8_Operating_Tips.pdf[here] :ft8_tips: http://www.g4ifb.com/FT8_Hinson_tips_for_HF_DXers.pdf[FT8 Operating Guide]
:ft8_DXped: http://physics.princeton.edu/pulsar/k1jt/FT8_DXpedition_Mode.pdf[FT8 DXpedition Mode] :ft8_DXped: http://physics.princeton.edu/pulsar/k1jt/FT8_DXpedition_Mode.pdf[FT8 DXpedition Mode]
:gnu_gpl: http://www.gnu.org/licenses/gpl-3.0.txt[GNU General Public License] :gnu_gpl: http://www.gnu.org/licenses/gpl-3.0.txt[GNU General Public License]
:homepage: http://physics.princeton.edu/pulsar/K1JT/[WSJT Home Page] :homepage: http://physics.princeton.edu/pulsar/K1JT/[WSJT Home Page]
@ -79,7 +79,9 @@ d). Edit lines as needed. Keeping them in alphabetic order help see dupes.
:log4om: http://www.log4om.com[Log4OM] :log4om: http://www.log4om.com[Log4OM]
:lunarEchoes: http://physics.princeton.edu/pulsar/K1JT/LunarEchoes_QEX.pdf[QEX] :lunarEchoes: http://physics.princeton.edu/pulsar/K1JT/LunarEchoes_QEX.pdf[QEX]
:msk144: http://physics.princeton.edu/pulsar/k1jt/MSK144_Protocol_QEX.pdf[QEX] :msk144: http://physics.princeton.edu/pulsar/k1jt/MSK144_Protocol_QEX.pdf[QEX]
:msvcpp_redist: https://www.microsoft.com/en-ph/download/details.aspx?id=40784[Microsoft VC++ 2013 Redistributable]
:msys_url: http://sourceforge.net/projects/mingwbuilds/files/external-binary-packages/[MSYS Download] :msys_url: http://sourceforge.net/projects/mingwbuilds/files/external-binary-packages/[MSYS Download]
:n1mm_logger: https://n1mm.hamdocs.com/tiki-index.php[N1MM Logger+]
:ntpsetup: http://www.satsignal.eu/ntp/setup.html[Network Time Protocol Setup] :ntpsetup: http://www.satsignal.eu/ntp/setup.html[Network Time Protocol Setup]
:osx_instructions: http://physics.princeton.edu/pulsar/K1JT/OSX_Readme[Mac OS X Install Instructions] :osx_instructions: http://physics.princeton.edu/pulsar/K1JT/OSX_Readme[Mac OS X Install Instructions]
:ppa: http://en.wikipedia.org/wiki/Personal_Package_Archive[PPA] :ppa: http://en.wikipedia.org/wiki/Personal_Package_Archive[PPA]
@ -88,6 +90,9 @@ d). Edit lines as needed. Keeping them in alphabetic order help see dupes.
:sourceforge: https://sourceforge.net/user/registration[SourceForge] :sourceforge: https://sourceforge.net/user/registration[SourceForge]
:sourceforge-jtsdk: https://sourceforge.net/projects/jtsdk[SourceForge JTSDK] :sourceforge-jtsdk: https://sourceforge.net/projects/jtsdk[SourceForge JTSDK]
:ubuntu_sdk: https://launchpad.net/~ubuntu-sdk-team/+archive/ppa[Ubuntu SDK Notice] :ubuntu_sdk: https://launchpad.net/~ubuntu-sdk-team/+archive/ppa[Ubuntu SDK Notice]
:win_openssl_packages: https://slproweb.com/products/Win32OpenSSL.html[Windows OpenSSL Packages]
:win32_openssl: https://slproweb.com/download/Win32OpenSSL_Light-1_0_2q.exe[Win32 OpenSSL Lite Package]
:writelog: https://writelog.com/[Writelog]
:wsjt_yahoo_group: https://groups.yahoo.com/neo/groups/wsjtgroup/info[WSJT Group] :wsjt_yahoo_group: https://groups.yahoo.com/neo/groups/wsjtgroup/info[WSJT Group]
:wsjtx: http://physics.princeton.edu/pulsar/K1JT/wsjtx.html[WSJT-X] :wsjtx: http://physics.princeton.edu/pulsar/K1JT/wsjtx.html[WSJT-X]
:wspr0_guide: http://www.physics.princeton.edu/pulsar/K1JT/WSPR0_Instructions.TXT[WSPR0 Guide] :wspr0_guide: http://www.physics.princeton.edu/pulsar/K1JT/WSPR0_Instructions.TXT[WSPR0 Guide]
@ -111,9 +116,9 @@ d). Edit lines as needed. Keeping them in alphabetic order help see dupes.
:svn: http://subversion.apache.org/packages.html#windows[Subversion] :svn: http://subversion.apache.org/packages.html#windows[Subversion]
:win32: http://physics.princeton.edu/pulsar/K1JT/wsjtx-{VERSION}-win32.exe[wsjtx-{VERSION}-win32.exe] :win32: http://physics.princeton.edu/pulsar/K1JT/wsjtx-{VERSION}-win32.exe[wsjtx-{VERSION}-win32.exe]
:wsjt-devel: https://lists.sourceforge.net/lists/listinfo/wsjt-devel[here] :wsjt-devel: https://lists.sourceforge.net/lists/listinfo/wsjt-devel[here]
:wsjt_svn: http://sourceforge.net/p/wsjt/wsjt/HEAD/tree/[WSJT Source Repository] :wsjt_repo: https://sourceforge.net/p/wsjt/wsjt_orig/ci/master/tree/[WSJT Source Repository]
:wspr_code: http://physics.princeton.edu/pulsar/K1JT/WSPRcode.exe[WSPRcode.exe] :wspr_code: http://physics.princeton.edu/pulsar/K1JT/WSPRcode.exe[WSPRcode.exe]
:wspr_svn: http://sourceforge.net/p/wsjt/wsjt/HEAD/tree/branches/wspr/[WSPR Source Repository] :wspr_svn: https://sourceforge.net/p/wsjt/wspr/ci/master/tree/[WSPR Source Repository]
// MAIL-TO links // MAIL-TO links
:alex_efros: mailto:powerman@powerman.name[Alex Efros] :alex_efros: mailto:powerman@powerman.name[Alex Efros]

View File

@ -36,6 +36,8 @@ inserted automatically. Typical reports for the various modes fall in
the range 30 to +20 dB. Remember that JT65 reports saturate at an the range 30 to +20 dB. Remember that JT65 reports saturate at an
upper limit of -1 dB. upper limit of -1 dB.
+
TIP: Consider reducing power if your QSO partner reports your TIP: Consider reducing power if your QSO partner reports your
signal above -5 dB in one of the _WSJT-X_ slow modes. These are signal above -5 dB in one of the _WSJT-X_ slow modes. These are
supposed to be weak signal modes! supposed to be weak signal modes!

View File

@ -28,6 +28,8 @@ if the rig is detected to be in *Split* mode. The circle becomes red
if you have requested CAT control but communication with the radio has if you have requested CAT control but communication with the radio has
been lost. been lost.
+
TIP: Many Icom rigs cannot be queried for split status, current VFO or TIP: Many Icom rigs cannot be queried for split status, current VFO or
split transmit frequency. When using _WSJT-X_ with such radios you split transmit frequency. When using _WSJT-X_ with such radios you
should not change the current VFO, split status or dial frequency should not change the current VFO, split status or dial frequency

View File

@ -36,6 +36,8 @@ the original frequency.
* *Erase* clears the right-hand decoded text window. * *Erase* clears the right-hand decoded text window.
Double-clicking *Erase* clears both text windows. Double-clicking *Erase* clears both text windows.
+
TIP: Right-clicking on either text window brings up a context menu TIP: Right-clicking on either text window brings up a context menu
with several options (including *Erase*) which operate on that window with several options (including *Erase*) which operate on that window
alone. alone.

View File

@ -56,6 +56,8 @@ spaces) in the *Free Msg* box.
pre-stored macro. Pressing *Enter* on a modified message here pre-stored macro. Pressing *Enter* on a modified message here
automatically adds that message to the table of stored macros. automatically adds that message to the table of stored macros.
+
TIP: During a transmission the actual message being sent always TIP: During a transmission the actual message being sent always
appears in the first box of the status bar (bottom left of the main appears in the first box of the status bar (bottom left of the main
screen). screen).

View File

@ -21,3 +21,5 @@ the elapsed fraction of a Tx or Rx sequence. Finally, if the Watchdog
lower right-hand corner displays the number of minutes remaining lower right-hand corner displays the number of minutes remaining
before timeout. before timeout.
TIP: Temporary status messages may occasionally be displayed here for
a few seconds when background processing completes.

View File

@ -37,3 +37,11 @@ current band, as well as other options.
logging applications Aether, MacLoggerDX, RUMlog or RUMlogNG. It logging applications Aether, MacLoggerDX, RUMlog or RUMlogNG. It
checks QSO and QSL status of the call and DXCC entity, as well as many checks QSO and QSL status of the call and DXCC entity, as well as many
other features. other features.
* {n1mm_logger} is a free full feature contest logging application. It
is only available for Windows. _WSJT-X_ can send logged QSO
information to it via a network connection.
* {writelog} is a non-free full feature contest logging
application. It is only available for Windows. _WSJT-X_ can send
logged QSO information to it via a network connection.

View File

@ -8,9 +8,9 @@ false decodes.
For example: when you decide to answer a CQ, you already know your own For example: when you decide to answer a CQ, you already know your own
callsign and that of your potential QSO partner. The software callsign and that of your potential QSO partner. The software
therefore "`knows`" what to expect for 57 of the 72 message bits (28 therefore "`knows`" what might be expected for at least 57 message
bits for each of two callsigns, 1 bit for message type) in the next bits (28 for each of two callsigns, 1 or more for message type) in the
received message. The decoder's task can thus be reduced to next received message. The decoder's task can thus be reduced to
determining the remaining 15 bits of the message and ensuring that the determining the remaining 15 bits of the message and ensuring that the
resulting solution is reliable. resulting solution is reliable.

View File

@ -47,7 +47,27 @@ location for each instance of _WSJT-X_.
wsjtx --rig-name=TS2000 wsjtx --rig-name=TS2000
wsjtx --rig-name=FT847 wsjtx --rig-name=FT847
Rig control through _OmniRig_ seems to fail when I click *Test CAT*. What can I do about it?:: I am getting a "Network Error - SSL/TLS support not installed" message. What should I do?::
You need to install suitable _OpenSSL_ libraries - see <<OPENSSL,Instructions to install _OpenSSL_>>.
I occasionally get Rig Control Errors if I adjust my Icom rig's VFO. What's wrong?::
By default most Icom transceivers have *CI-V Tranceive Mode" enabled,
this will cause unsolicited CAT traffic from the rig that disrupts CAT
control by a PC. Disable this option in the rig's menu.
I want to control my transceiver with another application as well as _WSJT-X_, is that possible?::
This only possible to do reliably via some kind of rig control server,
that server must be able to accept both _WSJT-X_ and the other
application(s) as clients. Using a dumb serial port splitter like the
VSPE tool is not supported, it may work but it is not reliable due to
unmanaged CAT control collisions. Applications like the _Hamlib Rig
Control Server (rigctld)_, _{omnirig}_, and _{dxlsuite} Commander_ are
potentially suitable and _WSJT-X_ can act as a client to them all.
Rig control through _OmniRig_ seems to fail when I click *Test CAT*. What can I do about it?::
_Omni-Rig_ apparently has a bug that appears when you click *Test _Omni-Rig_ apparently has a bug that appears when you click *Test
CAT*. Forget using *Test CAT* and just click *OK*. _Omni-Rig_ then CAT*. Forget using *Test CAT* and just click *OK*. _Omni-Rig_ then

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.9 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@ -1,10 +1,10 @@
// Status=review // Status=review
Source code for _WSJT-X_ is available from a public repository at Source code for _WSJT-X_ is available from a public repository at
{devsvn}. To compile the program you will need to install at least the {devrepo}. To compile the program you will need to install at least the
following packages: following packages:
- Subversion 1.8 or later - Git
- Qt 5.2 or later - Qt 5.2 or later
- g++ 4.8 or later - g++ 4.8 or later
- gfortran 4.8 or later - gfortran 4.8 or later
@ -14,13 +14,15 @@ following packages:
Source code for _WSJT-X_ v{VERSION} can be downloaded with the command: Source code for _WSJT-X_ v{VERSION} can be downloaded with the command:
===== =====
svn co svn://svn.code.sf.net/p/wsjt/wsjt/tags/wsjtx-{VERSION} git clone git://git.code.sf.net/p/wsjt/wsjtx
cd wsjtx
git checkout wsjtx-{VERSION}
===== =====
and for the current development branch, and for the current development branch,
===== =====
svn co svn://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx git clone git://git.code.sf.net/p/wsjt/wsjtx
===== =====
If you are interested in contributing to the development and If you are interested in contributing to the development and

View File

@ -2,6 +2,16 @@
Debian, Ubuntu, and other Debian-based systems including Raspbian: Debian, Ubuntu, and other Debian-based systems including Raspbian:
NOTE: The project team release binary installer packages for Linux
when a new _WSJT-X_ release is announced, note that these are built to
target one contemporary version of a Linux distribution. Although
these may work on newer Linux versions or even different
distributions, it is unlikely that they will work on older
versions. Check the notes provided with the release for details of the
targeted Linux distributions and versions. If the binary package is
not compatible with your Linux distribution or version you must build
the application from sources.
* 32-bit: {debian32} * 32-bit: {debian32}
- To install: - To install:
+ +
@ -33,9 +43,9 @@ sudo dpkg -P wsjtx
You may also need to execute the following command in a terminal: You may also need to execute the following command in a terminal:
[example] [example]
sudo apt install libqt5multimedia5-plugins libqt5serialport5 libfftw3-single3 sudo apt install libqt5multimedia5-plugins libqt5serialport5 libqt5sql5-sqlite libfftw3-single3
Fedora, Red Hat, and other rpm-based systems: Fedora, CentOS, Red Hat, and other rpm-based systems:
* 32-bit: {fedora32} * 32-bit: {fedora32}
- To install: - To install:

View File

@ -6,7 +6,7 @@ installation notes.
If you have already installed a previous version, you can retain it by If you have already installed a previous version, you can retain it by
changing its name in the *Applications* folder (say, from _WSJT-X_ to changing its name in the *Applications* folder (say, from _WSJT-X_ to
_WSJT-X_1.8_). You can then proceed to the installation phase. _WSJT-X_1.9_). You can then proceed to the installation phase.
Take note also of the following: Take note also of the following:

View File

@ -3,32 +3,70 @@
Download and execute the package file {win32}, following these Download and execute the package file {win32}, following these
instructions: instructions:
- Install _WSJT-X_ into its own directory, for example `C:\WSJTX` or * Install _WSJT-X_ into its own directory, for example `C:\WSJTX` or `
`C:\WSJT\WSJTX`, rather than the conventional location C:\WSJT\WSJTX`, rather than the conventional location `C:\Program
`C:\Program Files\WSJTX`. Files (x86)\WSJTX`.
- All program files relating to _WSJT-X_ will be stored in the chosen * All program files relating to _WSJT-X_ will be stored in the chosen
installation directory and its subdirectories. installation directory and its subdirectories.
* Logs and other writeable files will normally be found in the
directory +
- Logs and other writeable files will normally be found in the
directory +
`C:\Users\<username>\AppData\Local\WSJT-X`. `C:\Users\<username>\AppData\Local\WSJT-X`.
TIP: Your computer may be configured so that this directory is TIP: Your computer may be configured so that this directory is
"`invisible`". It's there, however, and accessible. An alternative "`invisible`". It's there, however, and accessible. An
(shortcut) directory name is `%LOCALAPPDATA%\WSJT-X\`. alternative (shortcut) directory name is
`"%LocalAppData%\WSJT-X\"`.
- The built-in Windows facility for time synchronization is usually * The built-in Windows facility for time synchronization is usually
not adequate. We recommend the program _Meinberg NTP_ (see {ntpsetup} not adequate. We recommend the program _Meinberg NTP_ (see
for downloading and installation instructions) or _Dimension 4_ from {ntpsetup} for downloading and installation instructions) or
{dimension4}. _Dimension 4_ from {dimension4}. Recent versions of Windows 10 are
now shipped with a more capable Internet time synchronization
service that is suitable if configured appropriately.
- _WSJT-X_ expects your sound card to do its raw sampling at 48000 Hz. [[OPENSSL]]
To ensure that this will be so when running under recent versions of
Windows, open the system's *Sound* control panel and select in turn the
*Recording* and *Playback* tabs. Click on *Properties*, then
*Advanced*, and select *16 bit, 48000 Hz (DVD Quality)*.
- You can uninstall _WSJT-X_ by clicking its *Uninstall* link in the * image:LoTW_TLS_error.png[_WSJT-X_ LoTW download TLS error, role="right"]
Windows *Start* menu, or by using *Uninstall a Program* on the From this version onward _WSJT-X_ requires the _OpenSSL_ libraries
Windows Control Panel. to be installed. Suitable libraries may already be installed on your
system, if they are not you will see this error shortly after
startup. To fix this you need to install the _OpenSSL_ libraries.
** You can download a suitable _OpenSSL_ package for from
{win_openssl_packages}, you need the latest *Win32 v1.0.2 Lite*
version (Note it is the Win32 package even if you are using a
64-bit Windows operating system) which at the time of writing was
{win32_openssl}.
** Install the package and accept the default options, including the
option to copy the _OpenSSL_ DLLs to the Windows system directory
(this is important). +
NOTE: If you still get the same network error after installing the
_OpenSSL_ libraries then you also need to install the
{msvcpp_redist} component. From the download page select
`vcredist_x86.exe` and run it to install.
TIP: If you cannot install the _OpenSSL_ libraries or do not have an
Internet connection on the computer used to run
_WSJT-X_&nbsp;{VERSION_MAJOR}.{VERSION_MINOR}, you can download
the _LoTW_ file manually. Go to
https://lotw.arrl.org/lotw-user-activity.csv in a web browser,
download the file, then move it to the _WSJT-X_ log files
directory. This directory can be opened by selecting
*File&nbsp;|&nbsp;Open&nbsp;log&nbsp;directory*.
* _WSJT-X_ expects your sound card to do its raw sampling at 48000 Hz.
To ensure that this will be so when running under recent versions of
Windows, open the system's *Sound* control panel and select in turn
the *Recording* and *Playback* tabs. Click on *Properties*, then
*Advanced*, and select *16 bit, 48000 Hz (DVD Quality)*. Switch of
all audio enhancement features for these devices.
* You can uninstall _WSJT-X_ by clicking its *Uninstall* link in the
Windows *Start* menu, or by using *Uninstall a Program* on the
Windows Control Panel Programs and Features option or in Settings
Apps on Windows 10.

View File

@ -7,29 +7,30 @@ K1**JT**,`" while the suffix "`-X`" indicates that _WSJT-X_ started as
an extended and experimental branch of the program an extended and experimental branch of the program
_WSJT_. _WSJT_.
_WSJT-X_ Version 1.9 offers nine different protocols or modes: *FT8*, _WSJT-X_ Version {VERSION_MAJOR}.{VERSION_MINOR} offers nine different
*JT4*, *JT9*, *JT65*, *QRA64*, *ISCAT*, *MSK144*, *WSPR*, and *Echo*. protocols or modes: *FT8*, *JT4*, *JT9*, *JT65*, *QRA64*, *ISCAT*,
The first five are designed for making reliable QSOs under extreme *MSK144*, *WSPR*, and *Echo*. The first five are designed for making
weak-signal conditions. They use nearly identical message structure reliable QSOs under extreme weak-signal conditions. They use nearly
and source encoding. JT65 and QRA64 were designed for EME identical message structure and source encoding. JT65 and QRA64 were
("`moonbounce`") on the VHF/UHF bands and have also proven very designed for EME ("`moonbounce`") on the VHF/UHF bands and have also
effective for worldwide QRP communication on the HF bands. QRA64 has proven very effective for worldwide QRP communication on the HF bands.
a number of advantages over JT65, including better performance on the QRA64 has a number of advantages over JT65, including better
very weakest signals. We imagine that over time it may replace JT65 performance on the very weakest signals. We imagine that over time it
for EME use. JT9 was originally designed for the LF, MF, and lower HF may replace JT65 for EME use. JT9 was originally designed for the LF,
bands. Its submode JT9A is 2 dB more sensitive than JT65 while using MF, and lower HF bands. Its submode JT9A is 2 dB more sensitive than
less than 10% of the bandwidth. JT4 offers a wide variety of tone JT65 while using less than 10% of the bandwidth. JT4 offers a wide
spacings and has proven highly effective for EME on microwave bands up variety of tone spacings and has proven highly effective for EME on
to 24 GHz. These four "`slow`" modes use one-minute timed sequences microwave bands up to 24 GHz. These four "`slow`" modes use
of alternating transmission and reception, so a minimal QSO takes four one-minute timed sequences of alternating transmission and reception,
to six minutes — two or three transmissions by each station, one so a minimal QSO takes four to six minutes — two or three
sending in odd UTC minutes and the other even. FT8 is operationally transmissions by each station, one sending in odd UTC minutes and the
similar but four times faster (15-second T/R sequences) and less other even. FT8 is operationally similar but four times faster
sensitive by a few dB. On the HF bands, world-wide QSOs are possible (15-second T/R sequences) and less sensitive by a few dB. On the HF
with any of these modes using power levels of a few watts (or even bands, world-wide QSOs are possible with any of these modes using
milliwatts) and compromise antennas. On VHF bands and higher, QSOs power levels of a few watts (or even milliwatts) and compromise
are possible (by EME and other propagation types) at signal levels 10 antennas. On VHF bands and higher, QSOs are possible (by EME and
to 15 dB below those required for CW. other propagation types) at signal levels 10 to 15 dB below those
required for CW.
*ISCAT*, *MSK144*, and optionally submodes *JT9E-H* are "`fast`" *ISCAT*, *MSK144*, and optionally submodes *JT9E-H* are "`fast`"
protocols designed to take advantage of brief signal enhancements from protocols designed to take advantage of brief signal enhancements from
@ -47,7 +48,7 @@ format with hashed callsigns.
potential propagation paths using low-power transmissions. WSPR potential propagation paths using low-power transmissions. WSPR
messages normally carry the transmitting stations callsign, grid messages normally carry the transmitting stations callsign, grid
locator, and transmitter power in dBm, and they can be decoded at locator, and transmitter power in dBm, and they can be decoded at
signal-to-noise ratios as low as -28 dB in a 2500 Hz bandwidth. WSPR signal-to-noise ratios as low as -31 dB in a 2500 Hz bandwidth. WSPR
users with internet access can automatically upload reception users with internet access can automatically upload reception
reports to a central database called {wsprnet} that provides a mapping reports to a central database called {wsprnet} that provides a mapping
facility, archival storage, and many other features. facility, archival storage, and many other features.

View File

@ -18,17 +18,8 @@ this option is checked _WSJT-X_ appends some additional information to
all CQ messages displayed in the _Band Activity_ window. The name of all CQ messages displayed in the _Band Activity_ window. The name of
the DXCC entity is shown, abbreviated if necessary. Your "`worked the DXCC entity is shown, abbreviated if necessary. Your "`worked
before`" status for this callsign (according to log file before`" status for this callsign (according to log file
`wsjtx_log.adi`) is flagged with a single character and a change of `wsjtx_log.adi`) is indicated by highlighting colors, if that option
background color, as follows: has been selected.
[horizontal]
!:: Default color bright purple: New DXCC entity
~:: Light pink: You have already worked this DXCC entity but not
this station
:: Green: You have previously worked the calling station
In this respect the program does not distinguish between modes, but it
does differentiate between bands.
_WSJT-X_ includes a built-in `cty.dat` file containing DXCC prefix _WSJT-X_ includes a built-in `cty.dat` file containing DXCC prefix
information. Updated files can be downloaded from the {cty_dat} web information. Updated files can be downloaded from the {cty_dat} web
@ -45,3 +36,5 @@ before status* off and then on again will cause _WSJT-X_ to re-read
the log file. Very large log files may cause _WSJT-X_ to slow down the log file. Very large log files may cause _WSJT-X_ to slow down
when searching for calls. when searching for calls.
Additional features are provided for *Contest* and *Fox* logging.
(more to come, here ...)

View File

@ -19,7 +19,10 @@ one callsign) followed by the transmitting stations grid locator, a
signal report, R plus a signal report, or the final acknowledgements signal report, R plus a signal report, or the final acknowledgements
RRR or 73. These messages are compressed and encoded in a highly RRR or 73. These messages are compressed and encoded in a highly
efficient and reliable way. In uncompressed form (as displayed efficient and reliable way. In uncompressed form (as displayed
on-screen) they may contain as many as 22 characters. on-screen) they may contain as many as 22 characters. Some operators
prefer ro send RR73 rather than RRR. This is workable because RR73 is
encoded as a valid grid locator, one unlikely ever to be occupied by
an amateur station.
*Signal reports* are specified as signal-to-noise ratio (S/N) in dB, *Signal reports* are specified as signal-to-noise ratio (S/N) in dB,
using a standard reference noise bandwidth of 2500 Hz. Thus, in the using a standard reference noise bandwidth of 2500 Hz. Thus, in the
@ -76,36 +79,92 @@ NOTE: When *Auto-Seq* is enabled the program de-activates *Enable Tx*
at the end of each QSO. It is not intended that _WSJT-X_ should make at the end of each QSO. It is not intended that _WSJT-X_ should make
fully automated QSOs. fully automated QSOs.
=== VHF Contest Mode === Contest Messages
A special *NA VHF Contest* mode can be activated for FT8 and MSK144. The new FT8 and MSK144 protocols support special messages optimized
To use it you must activate *File | Settings | General | Enable for *NA VHF* and *EU VHF* contests. FT8 also supports messages for
VHF/UHF/Microwave features* and then check the box *NA VHF Contest* on *ARRL Field Day* and the *ARRL RTTY Roundup*. The decoders recognize
the main window. This mode is configured especially for contests in and decode these messages at any time. Configure the program to
which four-character grid locators are the required exchange. When automatically generate the required message types by selecting a
*NA VHF Contest* mode is active, the standard QSO sequence looks like supported operating activity on the *Settings | Advanced* tab. Model
this: QSOs then proceed as follows, for each event type:
*NA VHF Contest*
CQ K1ABC FN42 CQ K1ABC FN42
K1ABC W9XYZ EN37 K1ABC W9XYZ EN37
W9XYZ K1ABC R FN42 W9XYZ K1ABC R FN42
K1ABC W9XYZ RRR K1ABC W9XYZ RRR
W9XYZ K1ABC 73 W9XYZ K1ABC 73
In contest circumstances K1ABC might choose to call CQ again rather Either callsign (or both) may have /R appended. You can use RR73 in
than sending 73 for his third transmission. place of RRR, and the final 73 is optional.
IMPORTANT: Do not use VHF Contest Mode on an HF band or in conditions
where worldwide propagation is available. See *EU VHF Contest*
<<PROTOCOL_OVERVIEW,Protocol Specifications>> for further details.
CQ TEST G4ABC IO91
G4ABC PA9XYZ JO22
PA9XYZ 570123 IO91NP
G4ABC R 580071 JO22DB
PA9XYZ G4ABC RR73
Either callsign (or both) may have /P appended.
*ARRL Field Day*
CQ FD K1ABC FN42
K1ABC W9XYZ 6A WI
W9XYZ K1ABC R 2B EMA
K1ABC W9XYZ RR73
*ARRL RTTY Roundup*
CQ RU K1ABC FN42
K1ABC W9XYZ 579 WI
W9XYZ K1ABC R 589 MA
K1ABC W9XYZ RR73
[[COMP-CALL]] [[COMP-CALL]]
=== Compound Callsigns === Compound Callsigns
Compound callsigns such as xx/K1ABC or K1ABC/x are handled in *FT8 and MSK144*
one of two possible ways:
.Messages containing Type 1 compound callsigns Compound callsigns like xx/K1ABC or K1ABC/x and nonstandard callsigns
like YW18FIFA are supported for normal QSOs but not for the special
contest-style messages. Model QSOs look something like this:
CQ PJ4/K1ABC
<PJ4/K1ABC> W9XYZ
W9XYZ <PJ4/K1ABC> +03
<PJ4/K1ABC> W9XYZ R-08
<W9XYZ> PJ4/K1ABC RRR
PJ4/K1ABC <W9XYZ> 73
The compound or nonstandard callsigns are automatically recognized and
handled using special message formats. One such callsign and one
standard callsign may appear in most messages, provided that one of
them is enclosed in < > angle brackets. If the message includes a
grid locator or numerical signal report, the brackets must enclose the
compound or nonstandard callsign; otherwise the brackets may be around
either call.
Angle brackets imply that the enclosed callsign is not transmitted in
full, but rather as a hash code using a smaller number of bits.
Receiving stations will display the full nonstandard callsign if it
has been received in full in the recent past. Otherwise it will be
displayed as < . . . >. These restrictions are honored automatically
by the algorithm that generates default messages for minimal QSOs.
Except for the special cases involving /P or /R used in VHF
contesting, _WSJT-X {VERSION_MAJOR}.{VERSION_MINOR}_ offers no support
for two nonstandard callsigns to work each other.
*JT4, JT9, JT65, and QRA64*
In the 72-bit modes, compound callsigns are handled in one of two
possible ways:
.Type 1 compound callsigns
A list of about 350 of the most common prefixes and suffixes can be A list of about 350 of the most common prefixes and suffixes can be
displayed from the *Help* menu. A single compound callsign involving displayed from the *Help* menu. A single compound callsign involving
@ -139,7 +198,7 @@ Notice that the full compound callsign is sent and received in the
first two transmissions. After that, the operators omit the add-on first two transmissions. After that, the operators omit the add-on
prefix or suffix and use the standard structured messages. prefix or suffix and use the standard structured messages.
.Type 2 Compound-Callsign Messages .Type 2 Compound callsigns
Prefixes and suffixes _not_ found in the displayable short list are Prefixes and suffixes _not_ found in the displayable short list are
handled by using *Type 2* compound callsigns. In this case the handled by using *Type 2* compound callsigns. In this case the

View File

@ -20,6 +20,8 @@ tab, delete any default frequencies for *FreqCal* mode that are not
relevant for your location. You may want to replace some of them with relevant for your location. You may want to replace some of them with
reliably known frequencies receivable at your location. reliably known frequencies receivable at your location.
+
TIP: We find major-city AM broadcast stations generally serve well as TIP: We find major-city AM broadcast stations generally serve well as
frequency calibrators at the low frequency end of the spectrum. In frequency calibrators at the low frequency end of the spectrum. In
North America we also use the standard time-and-frequency broadcasts North America we also use the standard time-and-frequency broadcasts

View File

@ -1,33 +1,41 @@
=== New in Version 1.9 === New in Version {VERSION}
For quick reference, here's a short list of features and capabilities For quick reference, here's a short list of features and capabilities
added to _WSJT-X_ since Version 1.8.0: added to _WSJT-X_ since Version 1.9.1:
- New *FT8 DXpedition Mode* to facilitate high QSO rates in pileup - New FT8 and MSK144 protocols with 77-bit payloads permit these enhancements:
situations
- Decoding improvements for JT65 mode, including _a priori_ (AP) * Optimized contest messages for NA VHF, EU VHF, Field Day, RTTY Roundup
decoding when VHF/UHF/Microwave features are enabled
- Optional Auto-Sequencing in JT4, JT9, and JT65 when VHF/UHF/Microwave features are enabled * Full support for "/R" and "/P" calls in relevant contests
- Better suppression of low-confidence false decodes generated by AP * New logging features for contesting
decoding in FT8 mode
- Improved decoding performance for WSPR mode, especially effective at LF and MF * Integration with {n1mm_logger} and {writelog} for contesting
- Minor adjustments to auto-sequencing behavior * Improved support for compound and nonstandard callsigns
- More flexible Doppler control features for EME * Nearly equal (or better) sensitivity compared to old protocols
- Improved waterfall sensitivity for very weak signals * Lower false decode rates
- Automatic real-time forwarding of logged information to _N1MM Logger+_ - Improved color highlighting of received messages
- Improved WSPR sensitivity
- Expanded and improved UDP messages sent to companion programs - Expanded and improved UDP messages sent to companion programs
- Bug fixes and other minor tweaks to user interface - Bug fixes and other minor tweaks to user interface
IMPORTANT: Note that for FT8 and MSK144 there is no backward
compatibility with WSJT-X 1.9.1 and earlier. Everyone using these
modes should upgrade to WSJT-X 2.0 by January 1, 2019.
IMPORTANT: _WSJT-X_ Version 2.0 drops support for Apple Mac OS X 10.9
(Mavericks). It is possible to build from source for this operating
system version but the DMG installer package requires 10.10 or later.
=== Documentation Conventions === Documentation Conventions
In this manual the following icons call attention to particular types In this manual the following icons call attention to particular types
@ -45,12 +53,12 @@ consequences.
=== How You Can Contribute === How You Can Contribute
_WSJT-X_ is part of an open-source project released under the _WSJT-X_ is part of an open-source project released under the
{gnu_gpl} (GPL). If you have programming or documentation skills or {gnu_gpl} (GPLv3). If you have programming or documentation skills or
would like to contribute to the project in other ways, please make would like to contribute to the project in other ways, please make
your interests known to the development team. The project's your interests known to the development team. The project's
source-code repository can be found at {devsvn}, and most source-code repository can be found at {devrepo}, and communication
communication among the developers takes place on the email reflector among the developers takes place on the email reflector {devmail}.
{devmail}. Bug reports and suggestions for new features, improvements Bug reports and suggestions for new features, improvements to the
to the _WSJT-X_ User Guide, etc., may also be sent to the _WSJT-X_ User Guide, etc., may also be sent to the {wsjt_yahoo_group}
{wsjt_yahoo_group} email reflector. You must join the relevant group email reflector. You must join the relevant group before posting to
before posting to either email list. either email list.

View File

@ -2,18 +2,20 @@
=== Overview === Overview
All QSO modes except ISCAT use structured messages that compress All QSO modes except ISCAT use structured messages that compress
user-readable information into fixed-length packets of 72 bits. Each user-readable information into fixed-length packets. JT4, JT9, JT65,
message consists of two 28-bit fields normally used for callsigns and and QRA64 use 72-bit payloads. Standard messages consist of two
a 15-bit field for a grid locator, report, acknowledgment, or 73. An 28-bit fields normally used for callsigns and a 15-bit field for a
additional bit flags a message containing arbitrary alphanumeric text, grid locator, report, acknowledgment, or 73. An additional bit flags
up to 13 characters. Special cases allow other information such as a message containing arbitrary free text, up to 13 characters.
add-on callsign prefixes (e.g., ZA/K1ABC) or suffixes (e.g., K1ABC/P) Special cases allow other information such as add-on callsign prefixes
to be encoded. The basic aim is to compress the most common messages (e.g., ZA/K1ABC) or suffixes (e.g., K1ABC/P) to be encoded. The basic
used for minimally valid QSOs into a fixed 72-bit length. The aim is to compress the most common messages used for minimally valid
information payload in FT8 includes 3 additional bits (75 bits total). QSOs into a fixed 72-bit length.
One of the added bits is used to flag special messages used by the
DXpedition station in FT8 DXpedition Mode. Uses for the remaining two The information payload for FT8 and MSK144 contains 77 bits. The 5
bits are yet to be defined. additional bits are used to flag special message types used for FT8
DXpedition Mode, contesting, nonstandard callsigns, and a few other
special types.
A standard amateur callsign consists of a one- or two-character A standard amateur callsign consists of a one- or two-character
prefix, at least one of which must be a letter, followed by a digit prefix, at least one of which must be a letter, followed by a digit
@ -42,22 +44,16 @@ additional information is sent in place of the grid locator or by
encoding additional information into some of the 6 million available encoding additional information into some of the 6 million available
slots mentioned above. slots mentioned above.
As a convenience for sending directed CQ messages, the compression As a convenience for sending directed CQ messages, the 72-bit
algorithm supports messages starting with `CQ AA` through `CQ ZZ`. compression algorithm supports messages starting with `CQ AA` through
These message fragments are encoded internally as if they were the `CQ ZZ`. These message fragments are encoded internally as if they
callsigns `E9AA` through `E9ZZ`. Upon reception they are converted were the callsigns `E9AA` through `E9ZZ`. Upon reception they are
back to the form `CQ AA` through `CQ ZZ`, for display to the user. converted back to the form `CQ AA` through `CQ ZZ`, for display to the
user.
The FT8 and MSK144 modes support a special feature allowing convenient The new FT8 and MSK144 protocols use a different lossless compression
transmission and acknowledgment of four-character grid locators, the algorithm with features to generate and recognize the special messages
required exchanges in most North American VHF contests. With this used for contesting and the like. (More to come, here ...)
Contest Mode enabled, _WSJT-X_ supports messages of the form `W9XYZ
K1ABC R FN42` by converting the grid locator to that of its
diametrically opposite point on Earth. The receiving program
recognizes a locator implying a distance greater than 10,000 km, does
the reverse transformation, and inserts the implied "`R`". Obviously,
this mode should not be used on the HF bands or under other
circumstances where world-wide propagation is possible.
To be useful on channels with low signal-to-noise ratio, this kind of To be useful on channels with low signal-to-noise ratio, this kind of
lossless message compression requires use of a strong forward error lossless message compression requires use of a strong forward error
@ -75,9 +71,9 @@ _WSJT-X_ modes have continuous phase and constant envelope.
==== FT8 ==== FT8
Forward error correction (FEC) in FT8 uses a low-density parity check Forward error correction (FEC) in FT8 uses a low-density parity check
(LDPC) code with 75 information bits, a 12-bit cyclic redundancy check (LDPC) code with 77 information bits, a 14-bit cyclic redundancy check
(CRC), and 87 parity bits making a 174-bit codeword. It is thus (CRC), and 83 parity bits making a 174-bit codeword. It is thus
called an LDPC (174,87) code. Synchronization uses 7×7 Costas arrays called an LDPC (174,91) code. Synchronization uses 7×7 Costas arrays
at the beginning, middle, and end of each transmission. Modulation is at the beginning, middle, and end of each transmission. Modulation is
8-tone frequency-shift keying (8-FSK) at 12000/1920 = 6.25 baud. Each 8-tone frequency-shift keying (8-FSK) at 12000/1920 = 6.25 baud. Each
transmitted symbol carries three bits, so the total number of channel transmitted symbol carries three bits, so the total number of channel
@ -231,7 +227,7 @@ which the probability of decoding is 50% or higher.
|=============================================================================== |===============================================================================
|Mode |FEC Type |(n,k) | Q|Modulation type|Keying rate (Baud)|Bandwidth (Hz) |Mode |FEC Type |(n,k) | Q|Modulation type|Keying rate (Baud)|Bandwidth (Hz)
|Sync Energy|Tx Duration (s)|S/N Threshold (dB) |Sync Energy|Tx Duration (s)|S/N Threshold (dB)
|FT8 |LDPC, r=1/2|(174,87)| 8| 8-FSK| 6.25 | 50.0 | 0.27| 12.6 | -21 |FT8 |LDPC, r=1/2|(174,91)| 8| 8-FSK| 6.25 | 50.0 | 0.27| 12.6 | -21
|JT4A |K=32, r=1/2|(206,72)| 2| 4-FSK| 4.375| 17.5 | 0.50| 47.1 | -23 |JT4A |K=32, r=1/2|(206,72)| 2| 4-FSK| 4.375| 17.5 | 0.50| 47.1 | -23
|JT9A |K=32, r=1/2|(206,72)| 8| 9-FSK| 1.736| 15.6 | 0.19| 49.0 | -27 |JT9A |K=32, r=1/2|(206,72)| 8| 9-FSK| 1.736| 15.6 | 0.19| 49.0 | -27
|JT65A |Reed Solomon|(63,12) |64|65-FSK| 2.692| 177.6 | 0.50| 46.8 | -25 |JT65A |Reed Solomon|(63,12) |64|65-FSK| 2.692| 177.6 | 0.50| 46.8 | -25
@ -329,13 +325,13 @@ For details see Table 4, below.
==== MSK144 ==== MSK144
Standard MSK144 messages are structured in the same way as those in Standard MSK144 messages are structured in the same way as in FT8,
the slow modes, with 72 bits of user information. Forward error with 77 bits of user information. Forward error correction is
correction is implemented by first augmenting the 72 message bits with implemented by first augmenting the 77 message bits with a 13-bit
an 8-bit cyclic redundancy check (CRC) calculated from the message cyclic redundancy check (CRC) calculated from the message bits. The
bits. The CRC is used to detect and eliminate most false decodes at CRC is used to detect and eliminate most false decodes at the
the receiver. The resulting 80-bit augmented message is mapped to a receiver. The resulting 90-bit augmented message is mapped to a
128-bit codeword using a (128,80) binary low-density-parity-check 128-bit codeword using a (128,90) binary low-density-parity-check
(LDPC) code designed by K9AN specifically for this purpose. Two 8-bit (LDPC) code designed by K9AN specifically for this purpose. Two 8-bit
synchronizing sequences are added to make a message frame 144 bits synchronizing sequences are added to make a message frame 144 bits
long. Modulation is Offset Quadrature Phase-Shift Keying (OQPSK) at long. Modulation is Offset Quadrature Phase-Shift Keying (OQPSK) at
@ -379,6 +375,6 @@ and your QSO partner ± 200 Hz.
|JT9F |K=32, r=1/2|(206,72)| 8| 9-FSK| 50.0 | 450 | 0.19| 1.700 |JT9F |K=32, r=1/2|(206,72)| 8| 9-FSK| 50.0 | 450 | 0.19| 1.700
|JT9G |K=32, r=1/2|(206,72)| 8| 9-FSK|100.0 | 900 | 0.19| 0.850 |JT9G |K=32, r=1/2|(206,72)| 8| 9-FSK|100.0 | 900 | 0.19| 0.850
|JT9H |K=32, r=1/2|(206,72)| 8| 9-FSK|200.0 | 1800 | 0.19| 0.425 |JT9H |K=32, r=1/2|(206,72)| 8| 9-FSK|200.0 | 1800 | 0.19| 0.425
|MSK144 |LDPC |(128,80)| 2| OQPSK| 2000 | 2400 | 0.11| 0.072 |MSK144 |LDPC |(128,90)| 2| OQPSK| 2000 | 2400 | 0.11| 0.072
|MSK144 Sh|LDPC |(32,16) | 2| OQPSK| 2000 | 2400 | 0.20| 0.020 |MSK144 Sh|LDPC |(32,16) | 2| OQPSK| 2000 | 2400 | 0.20| 0.020
|===================================================================== |=====================================================================

View File

@ -27,6 +27,8 @@ receiver's effective noise bandwidth.
a larger delay between execution of a command to enable PTT and onset a larger delay between execution of a command to enable PTT and onset
of Tx audio. of Tx audio.
+
IMPORTANT: For the health of your T/R relays and external IMPORTANT: For the health of your T/R relays and external
preamplifier, we strongly recommend using a hardware sequencer and preamplifier, we strongly recommend using a hardware sequencer and
testing to make sure that sequencing is correct. testing to make sure that sequencing is correct.
@ -36,9 +38,16 @@ with twice or four times the normal tone spacing. This feature is
intended for use with specialized LF/MF transmitters that divide intended for use with specialized LF/MF transmitters that divide
generated frequencies by 2 or 4 as part of the transmission process. generated frequencies by 2 or 4 as part of the transmission process.
_FT8 DXpedition Mode_ _Special Operating Activity: Generation of FT8 and MSk144 messages_
- Check this box and select the type of activity to enable
auto-generation of special message formats for contesting and
DXpeditions. For *ARRL Field Day*, enter your operating Class and
ARRL/RAC section; for *ARRL RTTY Roundup*, enter your state or province.
Use “DX” for section or state if you are not in the US or Canada. In
the RTTY Roundup, Stations in Alaska and Hawaii should enter “DX”.
- Check *Fox* if you are a DXpedition station operating in FT8 - Check *Fox* if you are a DXpedition station operating in FT8
DXpedition Mode. Check *Hound* if you wish to make QSOs with such a DXpedition Mode. Check *Hound* if you wish to make QSOs with such a
Fox. Be sure to read the operating instructions for {ft8_DXped}. Fox. Be sure to read the operating instructions for {ft8_DXped}.

View File

@ -4,18 +4,21 @@ image::settings-audio.png[align="center",alt="_WSJT-X_ Audio Configuration Scree
Select the *Audio* tab to configure your sound system. Select the *Audio* tab to configure your sound system.
- _Soundcard_: Select the audio devices to be used for *Input* and * _Soundcard_: Select the audio devices to be used for *Input* and
*Output*. Usually the *Mono* settings will suffice, but in special *Output*. Usually the *Mono* settings will suffice, but in special
cases you can choose *Left*, *Right*, or *Both* stereo channels. cases you can choose *Left*, *Right*, or *Both* stereo channels.
- Be sure that your audio device is configured to sample at 48000 Hz, ** Be sure that your audio device is configured to sample at 48000 Hz,
16 bits. 16 bits.
+
IMPORTANT: If you select the audio output device that is also your IMPORTANT: If you select the audio output device that is also your
computer's default audio device, be sure to turn off all system sounds computer's default audio device, be sure to turn off all system sounds
to prevent inadvertently transmitting them over the air. to prevent inadvertently transmitting them over the air.
+
NOTE: Windows Vista and later may configure audio devices using NOTE: Windows Vista and later may configure audio devices using
the Texas Instruments PCM2900 series CODEC for microphone input rather the Texas Instruments PCM2900 series CODEC for microphone input rather
line input. (This chip is used in many radios with built-in USB line input. (This chip is used in many radios with built-in USB
@ -23,18 +26,20 @@ CODECs, as well as various other audio interfaces.) If you are using
such a device, be sure to set the mic level in the Recording Device such a device, be sure to set the mic level in the Recording Device
Properties to 0 dB. Properties to 0 dB.
- _Save Directory_: _WSJT-X_ can save its received audio sequences as +
* _Save Directory_: _WSJT-X_ can save its received audio sequences as
`.wav` files. A default directory for these files is provided; you `.wav` files. A default directory for these files is provided; you
can select another location if desired. can select another location if desired.
- _AzEl Directory_: A file named `azel.dat` will appear in the * _AzEl Directory_: A file named `azel.dat` will appear in the
specified directory. The file contains information usable by another specified directory. The file contains information usable by another
program for automatic tracking of the Sun or Moon, as well as program for automatic tracking of the Sun or Moon, as well as
calculated Doppler shift for the specified EME path. The file is calculated Doppler shift for the specified EME path. The file is
updated once per second whenever the <<ASTRODATA,Astronomical Data>> updated once per second whenever the <<ASTRODATA,Astronomical Data>>
window is displayed. window is displayed.
- _Remember power settings by band_: Checking either of these will * _Remember power settings by band_: Checking either of these will
cause _WSJT-X_ to remember the *Pwr* slider setting for that operation cause _WSJT-X_ to remember the *Pwr* slider setting for that operation
on a band-by-band basis. For example, when *Tune* is checked here and on a band-by-band basis. For example, when *Tune* is checked here and
you click the *Tune* button on the main window, the power slider will you click the *Tune* button on the main window, the power slider will

View File

@ -1,5 +1,47 @@
image::colors.png[align="center",alt="Colors Screen"] image::colors.png[align="center",alt="Colors Screen"]
_WSJT-X_ uses colors to highlight decoded messages containing .Decode Highlighting
information of particular interest. Click on one of the buttons to
select your preferred colors for any message category. * _WSJT-X_ uses colors to highlight decoded CQ messages of particular
interest. Check the box *Show DXCC, grid, and worked-before status*
on the *Settings | General* tab, and any boxes of interest to you on
the *Colors* tab. You can drag any line up or down to raise or
lower its logical priority. Right-click any line to set a new
foreground or background color. Foreground and background colors
are applied separately, and careful choices of foreground,
background, and priority can provide two indications of
worked-before status.
* Press the *Reset Highlighting* button to reset all of the color
settings to default values.
* Check *Highlight by Mode* if you wish worked before status to be per
<<INTRO,mode>>.
* Worked before status is calculated from your _WSJT-X_ ADIF
<<LOGGING, Logging>> file, you may replace ADIF log file with one
exported from your station logging application, *Rescan ADIF Log*
rebuilds the _WSJT-X_ worked before indexes using the current ADIF
log file.
+
TIP: The _WSJT-X_ ADIF file records must contain the "CALL" field.
The "BAND", and "MODE", and "GRIDSQUARE" fields are optional
depending on your DXing objectives. DXCC entity, continent, CQ,
and ITU Zone data for call prefixes and certain well known
overrides are derived from the cty.dat database which is bundled
with _WSJT-X_ (See <<LOGGING,Logging>> for details).
.Logbook of The World User Validation
Stations who are known to have uploaded their logs to the ARRL LoTW
QSL matching service can be highlighted. The data used to determine
this is available on line.
* *Fetch Now* will download a fresh dataset from the *Users CSV file
URL*. The LoTW team normally update this data weekly.
* Adjust *Age of of last upload less than* to set the period within
which a station must have uploaded their log to LoTW to trigger
highlighting.

View File

@ -4,9 +4,9 @@
image::settings-frequencies.png[align="center",alt="Frequency Screen"] image::settings-frequencies.png[align="center",alt="Frequency Screen"]
_Working Frequencies_: By default the *Working Frequencies* table _Working Frequencies_: By default the *Working Frequencies* table
contains a list of frequencies conventionally used for modes JT4, JT9, contains a list of frequencies conventionally used for modes FT8, JT4,
JT65, MSK144, WSPR, and Echo. Conventions may change with time or JT9, JT65, MSK144, WSPR, and Echo. Conventions may change with time
by user preference; you can modify the frequency table as desired. or by user preference; you can modify the frequency table as desired.
- To change an existing entry, double-click to edit it, type a desired - To change an existing entry, double-click to edit it, type a desired
frequency in MHz or select from the drop down list of options, then frequency in MHz or select from the drop down list of options, then

View File

@ -17,6 +17,6 @@ NOTE: If you are using a callsign with an add-on prefix or
suffix, or wish to work a station using such a call, be sure to read suffix, or wish to work a station using such a call, be sure to read
the section <<COMP-CALL,Compound Callsigns>>. the section <<COMP-CALL,Compound Callsigns>>.
NOTE: Enabling VHF/UHF/Microwave features necessarily disables the NOTE: Checking *Enable VHF/UHF/Microwave features* necessarily
wideband multi-decode capability of JT65. In most circumstances you disables the wideband multi-decode capability of JT65. In most
should turn this feature off when operating at HF. circumstances you should turn this feature off when operating at HF.

View File

@ -6,66 +6,91 @@ _WSJT-X_ offers CAT (Computer Aided Transceiver) control of relevant
features of most modern transceivers. To configure the program for features of most modern transceivers. To configure the program for
your radio, select the *Radio* tab. your radio, select the *Radio* tab.
- Select your radio type from the drop-down list labeled *Rig*, or * Select your radio type from the drop-down list labeled *Rig*, or
*None* if you do not wish to use CAT control. *None* if you do not wish to use CAT control.
- Alternatively, if you have configured your station for control by ** Alternatively, if you have configured your station for control by
*DX Lab Suite Commander*, *Ham Radio Deluxe*, *Hamlib NET rigctl*, or *DX Lab Suite Commander*, *Flrig*, *Ham Radio Deluxe*, *Hamlib NET
*Omni-Rig*, you may select one of those program names from the *Rig* rigctl*, or *Omni-Rig*, you may select one of those program names
list. In these cases the entry field immediately under _CAT Control_ from the *Rig* list. In these cases the entry field immediately
will be relabeled as *Network Server*. Leave this field blank to under _CAT Control_ will be relabeled as *Network Server*. Leave
access the default instance of your control program, running on the this field blank to access the default instance of your control
same computer. If the control program runs on a different computer program, running on the same computer. If the control program runs
and/or port, specify it here. Hover the mouse pointer over the entry on a different computer and/or port, specify it here. Hover the
field to see the required formatting details. mouse pointer over the entry field to see the required formatting
details.
- Select *Omni-Rig Rig 1* or *Omni-Rig Rig 2* to connect to an ** Select *Omni-Rig Rig 1* or *Omni-Rig Rig 2* to connect to an
_Omni-Rig_ server running on the same computer. Note that _Omni-Rig_ _Omni-Rig_ server installed on the same computer. _Omni-Rig_ will
is available only under Windows. be started automatically by _WSJT-X_.
- Set *Poll Interval* to the desired interval for _WSJT-X_ to query +
your radio. For most radios a small number (say, 1 3 s) is
suitable.
- _CAT Control_: To have _WSJT-X_ control the radio directly rather NOTE: _Omni-Rig_ is available only under Windows.
than though another program, make the following settings:
* Select the *Serial Port* used to communicate with your radio. * Set *Poll Interval* to the desired interval for _WSJT-X_ to query
your radio. For most radios a small number (say, 1 3 s) is
suitable.
* _Serial Port Parameters_: Set values for *Baud Rate*, *Data Bits*, * _CAT Control_: To have _WSJT-X_ control the radio directly rather
*Stop Bits*, and *Handshake* method. Consult your radio's user guide than though another program, make the following settings:
for the proper parameter values.
* _Force Control Lines_: A few station setups require the CAT serial ** Select the *Serial Port* or *Network Server* including the service
ports *RTS* and/or *DTR* control lines to be forced high or port number used to communicate with your radio.
low. Check these boxes only if you are sure they are needed (for
example, to power the radio serial interface).
- _PTT Method_: select *VOX*, *CAT*, *DTR*, or *RTS* as the desired +
method for T/R switching. If your choice is *DTR* or *RTS*, select
the desired serial port (which may be the same one as used for
CAT control).
- _Transmit Audio Source_: some radios permit you to choose the NOTE: A special value of *USB* is available for custom USB devices
connector that will accept Tx audio. If this choice is enabled, like those used by some SDR kits. This is not the same a virtual
select *Rear/Data* or *Front/Mic*. serial port provided by USB connected transcivers and CAT
interfaces, for those use the COM or serial port name that
refers to them.
- _Mode_: _WSJT-X_ uses upper sideband mode for both transmitting and ** _Serial Port Parameters_: Set values for *Baud Rate*, *Data Bits*,
receiving. Select *USB*, or choose *Data/Pkt* if your radio offers *Stop Bits*, and *Handshake* method. Consult your radio's user
such an option and uses it to enable the rear-panel audio line input. *guide for the proper parameter values.
Some radios also offer wider and/or flatter passbands when set to
*Data/Pkt* mode. Select *None* if you do not want _WSJT-X_ to change
the radio's Mode setting.
- _Split Operation_: Significant advantages result from using *Split* +
mode (separate VFOs for Rx and Tx) if your radio supports it. If it
does not, _WSJT-X_ can emulate such behavior. Either method will NOTE: CAT interfaces that require handshaking will be non-responsive
result in a cleaner transmitted signal, by keeping the Tx audio always until the correct *Handshake* setting is applied.
in the range 1500 to 2000 Hz so that audio harmonics cannot pass
through the Tx sideband filter. Select *Rig* to use the radio's Split ** _Force Control Lines_: A few station setups require the CAT serial
mode, or *Fake It* to have _WSJT-X_ adjust the VFO frequency as ports *RTS* and/or *DTR* control lines to be forced high or
needed, when T/R switching occurs. Choose *None* if you do not low. Check these boxes *only* if you are sure they are needed (for
wish to use split operation. example, to power the radio serial interface).
* _PTT Method_: select *VOX*, *CAT*, *DTR*, or *RTS* as the desired
method for T/R switching. If your choice is *DTR* or *RTS*, select
the desired serial port (which may be the same one as used for CAT
control).
+
NOTE: When using a proxy application for rig control, *CAT* is usually
the correct option for _PTT Method_ assuming the proxy
application is capable of keying your transceiver idependently.
* _Transmit Audio Source_: some radios permit you to choose the
connector that will accept Tx audio. If this choice is enabled,
select *Rear/Data* or *Front/Mic*.
* _Mode_: _WSJT-X_ uses upper sideband mode for both transmitting and
receiving. Select *USB*, or choose *Data/Pkt* if your radio offers
such an option and uses it to enable the rear-panel audio line
input. Some radios also offer wider and/or flatter passbands when
set to *Data/Pkt* mode. Select *None* if you do not want _WSJT-X_
to change the radio's Mode setting.
* _Split Operation_: Significant advantages result from using *Split*
mode (separate VFOs for Rx and Tx) if your radio supports it. If it
does not, _WSJT-X_ can emulate such behavior. Either method will
result in a cleaner transmitted signal, by keeping the Tx audio
always in the range 1500 to 2000 Hz so that audio harmonics cannot
pass through the Tx sideband filter. Select *Rig* to use the
radio's Split mode, or *Fake It* to have _WSJT-X_ adjust the VFO
frequency as needed, when T/R switching occurs. Choose *None* if
you do not wish to use split operation.
When all required settings have been made, click *Test CAT* to test When all required settings have been made, click *Test CAT* to test
communication between _WSJT-X_ and your radio. The button should turn communication between _WSJT-X_ and your radio. The button should turn

View File

@ -2,53 +2,63 @@
.Receiver Noise Level .Receiver Noise Level
- If it is not already highlighted in green, click the *Monitor* - If it is not already highlighted in green, click the *Monitor*
button to start normal receive operation. button to start normal receive operation.
- Be sure your transceiver is set to *USB* (or *USB Data*) mode. - Be sure your transceiver is set to *USB* (or *USB Data*) mode.
- Use the receiver gain controls and/or the computer's audio mixer - Use the receiver gain controls and/or the computer's audio mixer
controls to set the background noise level (scale at lower left of controls to set the background noise level (scale at lower left of
main window) to around 30 dB when no signals are present. It is main window) to around 30 dB when no signals are present. It is
usually best to turn AGC off or reduce the RF gain control to minimize usually best to turn AGC off or reduce the RF gain control to
AGC action. minimize AGC action.
+
TIP: The PC audio mixer normally has two sliders, one for each
application attached which should be set to maximum (0dB FS) as
it cannot help with distortion from overly high or low input
levels from your receiver and another *Master* level which is
analogue attenuator on the sound card before the Analogue to
Digital Converter (ADC). The *Master* level can be used to adjust
the signal level received by _WSJT-X_.
.Bandwidth and Frequency Setting .Bandwidth and Frequency Setting
- If your transceiver offers more than one bandwidth setting in USB - If your transceiver offers more than one bandwidth setting in USB
mode, it may be advantageous to choose the widest one possible, up to mode, it may be advantageous to choose the widest one possible, up
about 5 kHz. This choice has the desirable effect of allowing the to about 5 kHz. This choice has the desirable effect of allowing
*Wide Graph* (waterfall and 2D spectrum) to display the conventional the *Wide Graph* (waterfall and 2D spectrum) to display the
JT65 and JT9 sub-bands simultaneously on most HF bands. Further conventional JT65 and JT9 sub-bands simultaneously on most HF bands.
details are provided in the <<TUTORIAL,Basic Operating Tutorial>>. A Further details are provided in the <<TUTORIAL,Basic Operating
wider displayed bandwidth may also be helpful at VHF and above, where Tutorial>>. A wider displayed bandwidth may also be helpful at VHF
FT8, JT4, JT65, and QRA64 signals may be found over much wider ranges and above, where FT8, JT4, JT65, and QRA64 signals may be found over
of frequencies. much wider ranges of frequencies.
- If you have only a standard SSB filter you wont be able to display - If you have only a standard SSB filter you wont be able to display
more than about 2.7 kHz bandwidth. Depending on the exact dial more than about 2.7 kHz bandwidth. Depending on the exact dial
frequency setting, on HF bands you can display the full sub-band frequency setting, on HF bands you can display the full sub-band
generally used for one mode. generally used for one mode.
- Of course, you might prefer to concentrate on one mode at a time, - Of course, you might prefer to concentrate on one mode at a time,
setting your dial frequency to (say) 14.074 for FT8, 14.076 for JT65, setting your dial frequency to (say) 14.074 for FT8, 14.076 for
or 14.078 for JT9. Present conventions have the nominal JT9 dial JT65, or 14.078 for JT9. Present conventions have the nominal JT9
frequency 2 kHz higher than the JT65 dial frequency on most bands, and dial frequency 2 kHz higher than the JT65 dial frequency on most
the FT8 frequency 2 kHz lower. bands, and the FT8 frequency 2 kHz lower.
.Transmitter Audio Level .Transmitter Audio Level
* Click the *Tune* button on the main screen to switch the * Click the *Tune* button on the main screen to switch the radio into
radio into transmit mode and generate a steady audio tone. transmit mode and generate a steady audio tone.
* Listen to the generated audio tone using your radios *Monitor* * Listen to the generated audio tone using your radios *Monitor*
facility. The transmitted tone should be perfectly smooth, with no facility. The transmitted tone should be perfectly smooth, with no
clicks or glitches. Make sure that this is true even when you clicks or glitches. Make sure that this is true even when you
simultaneously use the computer to do other tasks such as email, web simultaneously use the computer to do other tasks such as email, web
browsing, etc. browsing, etc..
* Adjust the *Pwr* slider (at right edge of main window) downward from * Adjust the *Pwr* slider (at right edge of main window) downward from
its maximum until the RF output from your transmitter falls slightly. its maximum until the RF output from your transmitter falls
This is generally a good level for audio drive. slightly. This is generally a good level for audio drive.
* Toggle the *Tune* button once more or click *Halt Tx* to stop your * Toggle the *Tune* button once more or click *Halt Tx* to stop your
test transmission. test transmission.

View File

@ -64,6 +64,8 @@ so that a transmission will start automatically at the proper time.
*Shift* key to move only the Tx frequency or the *Ctrl* key to move *Shift* key to move only the Tx frequency or the *Ctrl* key to move
both Rx and Tx frequencies. both Rx and Tx frequencies.
+
NOTE: You can prevent your Tx frequency from being changed by checking the NOTE: You can prevent your Tx frequency from being changed by checking the
box *Hold Tx Freq*. box *Hold Tx Freq*.

View File

@ -50,6 +50,8 @@ image::decodes.png[align="center"]
earlier, in <<TUT_EX1,Example 1>>. _WSJT-X_ automatically determines earlier, in <<TUT_EX1,Example 1>>. _WSJT-X_ automatically determines
the mode of each JT9 or JT65 message. the mode of each JT9 or JT65 message.
+
TIP: When you double-click on a signal in the waterfall it will be TIP: When you double-click on a signal in the waterfall it will be
properly decoded even if on the "`wrong`" side of the *JT65 nnnn JT9* properly decoded even if on the "`wrong`" side of the *JT65 nnnn JT9*
marker. The Tx mode automatically switches to that of the decoded marker. The Tx mode automatically switches to that of the decoded

View File

@ -43,16 +43,17 @@ frequency to that of the selected message and leaving Tx frequency
unchanged. To change both Rx and Tx frequencies, hold *Ctrl* down unchanged. To change both Rx and Tx frequencies, hold *Ctrl* down
when double-clicking. when double-clicking.
NOTE: To avoid QRM from competing callers, it is frequently desirable TIP: To avoid QRM from competing callers, it is frequently desirable
to answer a CQ on a different frequency from that of the CQing to answer a CQ on a different frequency from that of the CQing
station. The same is true when you tail-end another QSO. Choose a Tx station. The same is true when you tail-end another QSO. Choose a Tx
frequency that appears to be not in use. frequency that appears to be not in use. You might want to check the
box *Hold Tx Freq*.
NOTE: Keyboard shortcuts *Shift+F11* and *Shift+F12* provide an easy TIP: Keyboard shortcuts *Shift+F11* and *Shift+F12* provide an easy
way to move your Tx frequency down or up in 60 Hz steps. way to move your Tx frequency down or up in 60 Hz steps.
NOTE: Further helpful tips on FT8 operating procedures are available TIP: An online {ft8_tips} by ZL2IFB offers many helpful tips on
{ft8_tips}. Thanks to ZL2IFB! operating procedures.
.FT8 DXpedition Mode: .FT8 DXpedition Mode:

View File

@ -6,6 +6,8 @@
- Set the audio frequencies to *Tx 1224 Hz* and *Rx 1224 Hz*. - Set the audio frequencies to *Tx 1224 Hz* and *Rx 1224 Hz*.
+
TIP: Sliders and spinner controls respond to *Arrow* key presses TIP: Sliders and spinner controls respond to *Arrow* key presses
and *Page Up/Down* key presses, with the *Page* keys moving the and *Page Up/Down* key presses, with the *Page* keys moving the
controls in larger steps. You can also type numbers directly into controls in larger steps. You can also type numbers directly into

View File

@ -1,5 +1,6 @@
_WSJT-X_ v1.9 suppports a number of features designed for use _WSJT-X_ v{VERSION_MAJOR}.{VERSION_MINOR} suppports a number of
on the VHF and higher bands. These features include: features designed for use on the VHF and higher bands. These features
include:
- *FT8*, a mode designed for making fast QSOs with weak, fading - *FT8*, a mode designed for making fast QSOs with weak, fading
signals signals
@ -276,6 +277,8 @@ this number is well below 100% you may increase the decoding depth
from *Fast* to *Normal* or *Deep*, and increase *F Tol* from 100 to from *Fast* to *Normal* or *Deep*, and increase *F Tol* from 100 to
200 Hz. 200 Hz.
+
NOTE: Most modern multi-core computers can easily handle the optimum NOTE: Most modern multi-core computers can easily handle the optimum
parameters *Deep* and *F Tol 200*. Older and slower machines may not parameters *Deep* and *F Tol 200*. Older and slower machines may not
be able to keep up at these settings; at the *Fast* and *Normal* be able to keep up at these settings; at the *Fast* and *Normal*
@ -303,6 +306,7 @@ enclosed in <> angle brackets, as in the following model QSO
<W9XYZ K1ABC> RRR <W9XYZ K1ABC> RRR
<K1ABC W9XYZ> 73 <K1ABC W9XYZ> 73
+
NOTE: There is little or no advantage to using MSK144 *Sh* NOTE: There is little or no advantage to using MSK144 *Sh*
messages at 50 or 70 MHz. At these frequencies, most pings are long messages at 50 or 70 MHz. At these frequencies, most pings are long

View File

@ -1,5 +1,5 @@
// This is a comment line, anything with // is ignored at process time. // This is a comment line, anything with // is ignored at process time.
= _WSJT-X_ User Guide = _WSJT-X {VERSION_MAJOR}.{VERSION_MINOR}_ User Guide
Joseph H Taylor, Jr, K1JT Joseph H Taylor, Jr, K1JT
:revnumber: {VERSION} :revnumber: {VERSION}
// For web-pages, adding :badges: is ok, but is a security issue for // For web-pages, adding :badges: is ok, but is a security issue for
@ -113,9 +113,12 @@ include::transceiver-setup.adoc[]
This section introduces the basic user controls and program behavior This section introduces the basic user controls and program behavior
of _WSJT-X_, with particular emphasis on the JT9, JT65, and FT8 modes. of _WSJT-X_, with particular emphasis on the JT9, JT65, and FT8 modes.
We suggest that new users should go through the full HF-oriented We suggest that new users should go through the full HF-oriented
tutorial, preferably while at your radio. Subsequent sections cover tutorial, preferably while at your radio. Note that as of late 2018,
additional details on <<MAKE_QSOS,Making QSOs>>, <<WSPR,WSPR mode>> digital usage on the HF bands has mostly moved from JT65 and JT9 to FT8. So
and <<VHF_AND_UP,VHF+ Features>>. you may wish to pay particular attention to *FT8*, in Section 6.6.
Subsequent sections cover additional details on <<MAKE_QSOS,Making
QSOs>>, <<WSPR,WSPR mode>> and <<VHF_AND_UP,VHF+ Features>>.
[[TUT_MAIN]] [[TUT_MAIN]]
=== Main Window Settings === Main Window Settings

View File

@ -11,6 +11,8 @@ desired size.
- Select an active WSPR frequency (for example, 10.1387 or 14.0956 MHz). - Select an active WSPR frequency (for example, 10.1387 or 14.0956 MHz).
+
IMPORTANT: If you will transmit in the 60 m band, be sure to choose a IMPORTANT: If you will transmit in the 60 m band, be sure to choose a
frequency that conforms with your local regulations. frequency that conforms with your local regulations.

View File

@ -28,3 +28,4 @@ void CallsignDelegate::setModelData (QWidget * editor, QAbstractItemModel * mode
{ {
model->setData (index, static_cast<QLineEdit *> (editor)->text (), Qt::EditRole); model->setData (index, static_cast<QLineEdit *> (editor)->text (), Qt::EditRole);
} }

View File

@ -1,8 +1,10 @@
#ifndef DATE_TIME_AS_SECS_SINCE_EPOCH_DELEGATE_HPP_ #ifndef DATE_TIME_AS_SECS_SINCE_EPOCH_DELEGATE_HPP_
#define DATE_TIME_AS_SECS_SINCE_EPOCH_DELEGATE_HPP_ #define DATE_TIME_AS_SECS_SINCE_EPOCH_DELEGATE_HPP_
#include <memory>
#include <QStyledItemDelegate> #include <QStyledItemDelegate>
#include <QVariant> #include <QVariant>
#include <QLocale>
#include <QDateTime> #include <QDateTime>
#include <QAbstractItemModel> #include <QAbstractItemModel>
#include <QDateTimeEdit> #include <QDateTimeEdit>
@ -33,12 +35,17 @@ public:
QString displayText (QVariant const& value, QLocale const& locale) const override QString displayText (QVariant const& value, QLocale const& locale) const override
{ {
return locale.toString (to_date_time (value), QLocale::ShortFormat); return locale.toString (to_date_time (value), locale.dateFormat (QLocale::ShortFormat) + " hh:mm:ss");
} }
QWidget * createEditor (QWidget * parent, QStyleOptionViewItem const& /*option*/, QModelIndex const& /*index*/) const override QWidget * createEditor (QWidget * parent, QStyleOptionViewItem const& /*option*/, QModelIndex const& /*index*/) const override
{ {
return new QDateTimeEdit {parent}; std::unique_ptr<QDateTimeEdit> editor {new QDateTimeEdit {parent}};
editor->setDisplayFormat (parent->locale ().dateFormat (QLocale::ShortFormat) + " hh:mm:ss");
editor->setTimeSpec (Qt::UTC); // needed because it ignores time
// spec of the QDateTime that it is
// set from
return editor.release ();
} }
void setEditorData (QWidget * editor, QModelIndex const& index) const override void setEditorData (QWidget * editor, QModelIndex const& index) const override

View File

@ -34,22 +34,6 @@ module crc
integer (c_int), value :: length integer (c_int), value :: length
end function crc13_check end function crc13_check
function crc12 (data, length) bind (C, name="crc12")
use, intrinsic :: iso_c_binding, only: c_short, c_ptr, c_int
implicit none
integer (c_short) :: crc12
type (c_ptr), value :: data
integer (c_int), value :: length
end function crc12
function crc12_check (data, length) bind (C, name="crc12_check")
use, intrinsic :: iso_c_binding, only: c_bool, c_ptr, c_int
implicit none
logical (c_bool) :: crc12_check
type (c_ptr), value :: data
integer (c_int), value :: length
end function crc12_check
function crc10 (data, length) bind (C, name="crc10") function crc10 (data, length) bind (C, name="crc10")
use, intrinsic :: iso_c_binding, only: c_short, c_ptr, c_int use, intrinsic :: iso_c_binding, only: c_short, c_ptr, c_int
implicit none implicit none

View File

@ -1,31 +0,0 @@
#include <boost/crc.hpp>
#include <boost/config.hpp>
extern "C"
{
short crc12 (unsigned char const * data, int length);
bool crc12_check (unsigned char const * data, int length);
}
#define POLY 0xc06
#ifdef BOOST_NO_CXX11_CONSTEXPR
#define TRUNCATED_POLYNOMIAL POLY
#else
namespace
{
unsigned long constexpr TRUNCATED_POLYNOMIAL = POLY;
}
#endif
// assumes CRC is last 16 bits of the data and is set to zero
// caller should assign the returned CRC into the message in big endian byte order
short crc12 (unsigned char const * data, int length)
{
return boost::augmented_crc<12, TRUNCATED_POLYNOMIAL> (data, length);
}
bool crc12_check (unsigned char const * data, int length)
{
return !boost::augmented_crc<12, TRUNCATED_POLYNOMIAL> (data, length);
}

View File

@ -470,8 +470,8 @@ contains
real, intent(in) :: dt real, intent(in) :: dt
real, intent(in) :: freq real, intent(in) :: freq
character(len=37), intent(in) :: decoded character(len=37), intent(in) :: decoded
character c1*12,c2*12,g2*4,w*4,ctmp*12 character c1*12,c2*12,g2*4,w*4
integer i0,i1,i2,i3,i4,i5,i6,n30,nwrap integer i0,i1,i2,i3,i4,i5,n30,nwrap
integer, intent(in) :: nap integer, intent(in) :: nap
real, intent(in) :: qual real, intent(in) :: qual
character*2 annot character*2 annot

View File

@ -1,16 +1,16 @@
subroutine fmtmsg(msg,iz) subroutine fmtmsg(msg,iz)
character*22 msg character*(*) msg
! Convert all letters to upper case ! Convert all letters to upper case
iz=22 iz=len(msg)
do i=1,22 do i=1,iz
if(msg(i:i).ge.'a' .and. msg(i:i).le.'z') & if(msg(i:i).ge.'a' .and. msg(i:i).le.'z') &
msg(i:i)= char(ichar(msg(i:i))+ichar('A')-ichar('a')) msg(i:i)= char(ichar(msg(i:i))+ichar('A')-ichar('a'))
if(msg(i:i).ne.' ') iz=i if(msg(i:i).ne.' ') iz=i
enddo enddo
do iter=1,5 !Collapse multiple blanks into one do iter=1,37 !Collapse multiple blanks into one
ib2=index(msg(1:iz),' ') ib2=index(msg(1:iz),' ')
if(ib2.lt.1) go to 100 if(ib2.lt.1) go to 100
msg=msg(1:ib2)//msg(ib2+2:) msg=msg(1:ib2)//msg(ib2+2:)

View File

@ -1,401 +0,0 @@
subroutine bpdecode174(llr,apmask,maxiterations,decoded,cw,nharderror,iter)
!
! A log-domain belief propagation decoder for the (174,87) code.
!
integer, parameter:: N=174, K=87, M=N-K
integer*1 codeword(N),cw(N),apmask(N)
integer colorder(N)
integer*1 decoded(K)
integer Nm(7,M) ! 5, 6, or 7 bits per check
integer Mn(3,N) ! 3 checks per bit
integer synd(M)
real tov(3,N)
real toc(7,M)
real tanhtoc(7,M)
real zn(N)
real llr(N)
real Tmn
integer nrw(M)
data colorder/ &
0, 1, 2, 3, 30, 4, 5, 6, 7, 8, 9, 10, 11, 32, 12, 40, 13, 14, 15, 16,&
17, 18, 37, 45, 29, 19, 20, 21, 41, 22, 42, 31, 33, 34, 44, 35, 47, 51, 50, 43,&
36, 52, 63, 46, 25, 55, 27, 24, 23, 53, 39, 49, 59, 38, 48, 61, 60, 57, 28, 62,&
56, 58, 65, 66, 26, 70, 64, 69, 68, 67, 74, 71, 54, 76, 72, 75, 78, 77, 80, 79,&
73, 83, 84, 81, 82, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,&
100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,&
120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,&
140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,&
160,161,162,163,164,165,166,167,168,169,170,171,172,173/
data Mn/ &
1, 25, 69, &
2, 5, 73, &
3, 32, 68, &
4, 51, 61, &
6, 63, 70, &
7, 33, 79, &
8, 50, 86, &
9, 37, 43, &
10, 41, 65, &
11, 14, 64, &
12, 75, 77, &
13, 23, 81, &
15, 16, 82, &
17, 56, 66, &
18, 53, 60, &
19, 31, 52, &
20, 67, 84, &
21, 29, 72, &
22, 24, 44, &
26, 35, 76, &
27, 36, 38, &
28, 40, 42, &
30, 54, 55, &
34, 49, 87, &
39, 57, 58, &
45, 74, 83, &
46, 62, 80, &
47, 48, 85, &
59, 71, 78, &
1, 50, 53, &
2, 47, 84, &
3, 25, 79, &
4, 6, 14, &
5, 7, 80, &
8, 34, 55, &
9, 36, 69, &
10, 43, 83, &
11, 23, 74, &
12, 17, 44, &
13, 57, 76, &
15, 27, 56, &
16, 28, 29, &
18, 19, 59, &
20, 40, 63, &
21, 35, 52, &
22, 54, 64, &
24, 62, 78, &
26, 32, 77, &
30, 72, 85, &
31, 65, 87, &
33, 39, 51, &
37, 48, 75, &
38, 70, 71, &
41, 42, 68, &
45, 67, 86, &
46, 81, 82, &
49, 66, 73, &
58, 60, 66, &
61, 65, 85, &
1, 14, 21, &
2, 13, 59, &
3, 67, 82, &
4, 32, 73, &
5, 36, 54, &
6, 43, 46, &
7, 28, 75, &
8, 33, 71, &
9, 49, 76, &
10, 58, 64, &
11, 48, 68, &
12, 19, 45, &
15, 50, 61, &
16, 22, 26, &
17, 72, 80, &
18, 40, 55, &
20, 35, 51, &
23, 25, 34, &
24, 63, 87, &
27, 39, 74, &
29, 78, 83, &
30, 70, 77, &
31, 69, 84, &
22, 37, 86, &
38, 41, 81, &
42, 44, 57, &
47, 53, 62, &
52, 56, 79, &
60, 75, 81, &
1, 39, 77, &
2, 16, 41, &
3, 31, 54, &
4, 36, 78, &
5, 45, 65, &
6, 57, 85, &
7, 14, 49, &
8, 21, 46, &
9, 15, 72, &
10, 20, 62, &
11, 17, 71, &
12, 34, 47, &
13, 68, 86, &
18, 23, 43, &
19, 64, 73, &
24, 48, 79, &
25, 70, 83, &
26, 80, 87, &
27, 32, 40, &
28, 56, 69, &
29, 63, 66, &
30, 42, 50, &
33, 37, 82, &
35, 60, 74, &
38, 55, 84, &
44, 52, 61, &
51, 53, 72, &
58, 59, 67, &
47, 56, 76, &
1, 19, 37, &
2, 61, 75, &
3, 8, 66, &
4, 60, 84, &
5, 34, 39, &
6, 26, 53, &
7, 32, 57, &
9, 52, 67, &
10, 12, 15, &
11, 51, 69, &
13, 14, 65, &
16, 31, 43, &
17, 20, 36, &
18, 80, 86, &
21, 48, 59, &
22, 40, 46, &
23, 33, 62, &
24, 30, 74, &
25, 42, 64, &
27, 49, 85, &
28, 38, 73, &
29, 44, 81, &
35, 68, 70, &
41, 63, 76, &
45, 49, 71, &
50, 58, 87, &
48, 54, 83, &
13, 55, 79, &
77, 78, 82, &
1, 2, 24, &
3, 6, 75, &
4, 56, 87, &
5, 44, 53, &
7, 50, 83, &
8, 10, 28, &
9, 55, 62, &
11, 29, 67, &
12, 33, 40, &
14, 16, 20, &
15, 35, 73, &
17, 31, 39, &
18, 36, 57, &
19, 46, 76, &
21, 42, 84, &
22, 34, 59, &
23, 26, 61, &
25, 60, 65, &
27, 64, 80, &
30, 37, 66, &
32, 45, 72, &
38, 51, 86, &
41, 77, 79, &
43, 56, 68, &
47, 74, 82, &
40, 52, 78, &
54, 61, 71, &
46, 58, 69/
data Nm/ &
1, 30, 60, 89, 118, 147, 0, &
2, 31, 61, 90, 119, 147, 0, &
3, 32, 62, 91, 120, 148, 0, &
4, 33, 63, 92, 121, 149, 0, &
2, 34, 64, 93, 122, 150, 0, &
5, 33, 65, 94, 123, 148, 0, &
6, 34, 66, 95, 124, 151, 0, &
7, 35, 67, 96, 120, 152, 0, &
8, 36, 68, 97, 125, 153, 0, &
9, 37, 69, 98, 126, 152, 0, &
10, 38, 70, 99, 127, 154, 0, &
11, 39, 71, 100, 126, 155, 0, &
12, 40, 61, 101, 128, 145, 0, &
10, 33, 60, 95, 128, 156, 0, &
13, 41, 72, 97, 126, 157, 0, &
13, 42, 73, 90, 129, 156, 0, &
14, 39, 74, 99, 130, 158, 0, &
15, 43, 75, 102, 131, 159, 0, &
16, 43, 71, 103, 118, 160, 0, &
17, 44, 76, 98, 130, 156, 0, &
18, 45, 60, 96, 132, 161, 0, &
19, 46, 73, 83, 133, 162, 0, &
12, 38, 77, 102, 134, 163, 0, &
19, 47, 78, 104, 135, 147, 0, &
1, 32, 77, 105, 136, 164, 0, &
20, 48, 73, 106, 123, 163, 0, &
21, 41, 79, 107, 137, 165, 0, &
22, 42, 66, 108, 138, 152, 0, &
18, 42, 80, 109, 139, 154, 0, &
23, 49, 81, 110, 135, 166, 0, &
16, 50, 82, 91, 129, 158, 0, &
3, 48, 63, 107, 124, 167, 0, &
6, 51, 67, 111, 134, 155, 0, &
24, 35, 77, 100, 122, 162, 0, &
20, 45, 76, 112, 140, 157, 0, &
21, 36, 64, 92, 130, 159, 0, &
8, 52, 83, 111, 118, 166, 0, &
21, 53, 84, 113, 138, 168, 0, &
25, 51, 79, 89, 122, 158, 0, &
22, 44, 75, 107, 133, 155, 172, &
9, 54, 84, 90, 141, 169, 0, &
22, 54, 85, 110, 136, 161, 0, &
8, 37, 65, 102, 129, 170, 0, &
19, 39, 85, 114, 139, 150, 0, &
26, 55, 71, 93, 142, 167, 0, &
27, 56, 65, 96, 133, 160, 174, &
28, 31, 86, 100, 117, 171, 0, &
28, 52, 70, 104, 132, 144, 0, &
24, 57, 68, 95, 137, 142, 0, &
7, 30, 72, 110, 143, 151, 0, &
4, 51, 76, 115, 127, 168, 0, &
16, 45, 87, 114, 125, 172, 0, &
15, 30, 86, 115, 123, 150, 0, &
23, 46, 64, 91, 144, 173, 0, &
23, 35, 75, 113, 145, 153, 0, &
14, 41, 87, 108, 117, 149, 170, &
25, 40, 85, 94, 124, 159, 0, &
25, 58, 69, 116, 143, 174, 0, &
29, 43, 61, 116, 132, 162, 0, &
15, 58, 88, 112, 121, 164, 0, &
4, 59, 72, 114, 119, 163, 173, &
27, 47, 86, 98, 134, 153, 0, &
5, 44, 78, 109, 141, 0, 0, &
10, 46, 69, 103, 136, 165, 0, &
9, 50, 59, 93, 128, 164, 0, &
14, 57, 58, 109, 120, 166, 0, &
17, 55, 62, 116, 125, 154, 0, &
3, 54, 70, 101, 140, 170, 0, &
1, 36, 82, 108, 127, 174, 0, &
5, 53, 81, 105, 140, 0, 0, &
29, 53, 67, 99, 142, 173, 0, &
18, 49, 74, 97, 115, 167, 0, &
2, 57, 63, 103, 138, 157, 0, &
26, 38, 79, 112, 135, 171, 0, &
11, 52, 66, 88, 119, 148, 0, &
20, 40, 68, 117, 141, 160, 0, &
11, 48, 81, 89, 146, 169, 0, &
29, 47, 80, 92, 146, 172, 0, &
6, 32, 87, 104, 145, 169, 0, &
27, 34, 74, 106, 131, 165, 0, &
12, 56, 84, 88, 139, 0, 0, &
13, 56, 62, 111, 146, 171, 0, &
26, 37, 80, 105, 144, 151, 0, &
17, 31, 82, 113, 121, 161, 0, &
28, 49, 59, 94, 137, 0, 0, &
7, 55, 83, 101, 131, 168, 0, &
24, 50, 78, 106, 143, 149, 0/
data nrw/ &
6,6,6,6,6,6,6,6,6,6, &
6,6,6,6,6,6,6,6,6,6, &
6,6,6,6,6,6,6,6,6,6, &
6,6,6,6,6,6,6,6,6,7, &
6,6,6,6,6,7,6,6,6,6, &
6,6,6,6,6,7,6,6,6,6, &
7,6,5,6,6,6,6,6,6,5, &
6,6,6,6,6,6,6,6,6,6, &
5,6,6,6,5,6,6/
ncw=3
decoded=0
toc=0
tov=0
tanhtoc=0
! initialize messages to checks
do j=1,M
do i=1,nrw(j)
toc(i,j)=llr((Nm(i,j)))
enddo
enddo
ncnt=0
do iter=0,maxiterations
! Update bit log likelihood ratios (tov=0 in iteration 0).
do i=1,N
if( apmask(i) .ne. 1 ) then
zn(i)=llr(i)+sum(tov(1:ncw,i))
else
zn(i)=llr(i)
endif
enddo
! Check to see if we have a codeword (check before we do any iteration).
cw=0
where( zn .gt. 0. ) cw=1
ncheck=0
do i=1,M
synd(i)=sum(cw(Nm(1:nrw(i),i)))
if( mod(synd(i),2) .ne. 0 ) ncheck=ncheck+1
! if( mod(synd(i),2) .ne. 0 ) write(*,*) 'check ',i,' unsatisfied'
enddo
! write(*,*) 'number of unsatisfied parity checks ',ncheck
if( ncheck .eq. 0 ) then ! we have a codeword - reorder the columns and return it
codeword=cw(colorder+1)
decoded=codeword(M+1:N)
nerr=0
do i=1,N
if( (2*cw(i)-1)*llr(i) .lt. 0.0 ) nerr=nerr+1
enddo
nharderror=nerr
return
endif
if( iter.gt.0 ) then ! this code block implements an early stopping criterion
! if( iter.gt.10000 ) then ! this code block implements an early stopping criterion
nd=ncheck-nclast
if( nd .lt. 0 ) then ! # of unsatisfied parity checks decreased
ncnt=0 ! reset counter
else
ncnt=ncnt+1
endif
! write(*,*) iter,ncheck,nd,ncnt
if( ncnt .ge. 5 .and. iter .ge. 10 .and. ncheck .gt. 15) then
nharderror=-1
return
endif
endif
nclast=ncheck
! Send messages from bits to check nodes
do j=1,M
do i=1,nrw(j)
ibj=Nm(i,j)
toc(i,j)=zn(ibj)
do kk=1,ncw ! subtract off what the bit had received from the check
if( Mn(kk,ibj) .eq. j ) then
toc(i,j)=toc(i,j)-tov(kk,ibj)
endif
enddo
enddo
enddo
! send messages from check nodes to variable nodes
do i=1,M
tanhtoc(1:7,i)=tanh(-toc(1:7,i)/2)
enddo
do j=1,N
do i=1,ncw
ichk=Mn(i,j) ! Mn(:,j) are the checks that include bit j
Tmn=product(tanhtoc(1:nrw(ichk),ichk),mask=Nm(1:nrw(ichk),ichk).ne.j)
call platanh(-Tmn,y)
! y=atanh(-Tmn)
tov(i,j)=2*y
enddo
enddo
enddo
nharderror=-1
return
end subroutine bpdecode174

View File

@ -1,24 +0,0 @@
subroutine chkcrc12a(decoded,nbadcrc)
use crc
integer*1 decoded(87)
integer*1, target:: i1Dec8BitBytes(11)
character*87 cbits
! Write decoded bits into cbits: 75-bit message plus 12-bit CRC
write(cbits,1000) decoded
1000 format(87i1)
read(cbits,1001) i1Dec8BitBytes
1001 format(11b8)
read(cbits,1002) ncrc12 !Received CRC12
1002 format(75x,b12)
i1Dec8BitBytes(10)=iand(i1Dec8BitBytes(10),128+64+32)
i1Dec8BitBytes(11)=0
icrc12=crc12(c_loc(i1Dec8BitBytes),11) !CRC12 computed from 75 msg bits
nbadcrc=1
if(ncrc12.eq.icrc12) nbadcrc=0
return
end subroutine chkcrc12a

View File

@ -20,7 +20,6 @@ subroutine foxgen()
character*37 msg,msgsent character*37 msg,msgsent
integer itone(79) integer itone(79)
integer*1 msgbits(77),msgbits2 integer*1 msgbits(77),msgbits2
integer*1, target:: i1Msg8BitBytes(11)
integer*1, target:: mycall integer*1, target:: mycall
real x(NFFT) real x(NFFT)
real*8 dt,twopi,f0,fstep,dfreq,phi,dphi real*8 dt,twopi,f0,fstep,dfreq,phi,dphi

View File

@ -1,5 +1,5 @@
! LDPC (174,87) code ! LDPC (174,91) code
parameter (KK=87) !Information bits (75 + CRC12) parameter (KK=91) !Information bits (77 + CRC14)
parameter (ND=58) !Data symbols parameter (ND=58) !Data symbols
parameter (NS=21) !Sync symbols (3 @ Costas 7x7) parameter (NS=21) !Sync symbols (3 @ Costas 7x7)
parameter (NN=NS+ND) !Total channel symbols (79) parameter (NN=NS+ND) !Total channel symbols (79)

View File

@ -4,7 +4,6 @@ subroutine ft8apset(mycall12,hiscall12,apsym)
character*37 msg character*37 msg
character*12 mycall12,hiscall12,hiscall character*12 mycall12,hiscall12,hiscall
integer apsym(58) integer apsym(58)
integer*1 msgbits(77)
logical nohiscall logical nohiscall
if(len(trim(mycall12)).eq.0) then if(len(trim(mycall12)).eq.0) then
@ -30,10 +29,10 @@ subroutine ft8apset(mycall12,hiscall12,apsym)
apsym(1)=99 apsym(1)=99
apsym(30)=99 apsym(30)=99
return return
endif endif
read(c77,'(58i1)',err=1) apsym(1:58) read(c77,'(58i1)',err=1) apsym(1:58)
apsym=2*apsym-1
if(nohiscall) apsym(30)=99 if(nohiscall) apsym(30)=99
return return

View File

@ -7,30 +7,25 @@ subroutine ft8b(dd0,newdat,nQSOProgress,nfqso,nftx,ndepth,lapon,lapcqonly, &
use packjt77 use packjt77
include 'ft8_params.f90' include 'ft8_params.f90'
parameter(NP2=2812) parameter(NP2=2812)
character*37 msg37,msgsent37 character*37 msg37
character*12 mycall12,hiscall12,hiscall12_0 character*12 mycall12,hiscall12,hiscall12_0
character*77 c77 character*77 c77
character*6 mycall6,hiscall6,c1,c2
character*13 c13 character*13 c13
character*87 cbits
real a(5) real a(5)
real s8(0:7,NN) real s8(0:7,NN)
real s2(0:511),s2l(0:511) real s2(0:511),s2l(0:511)
real bmeta(174),bmetb(174),bmetc(174) real bmeta(174),bmetb(174),bmetc(174)
real bmetal(174),bmetbl(174),bmetcl(174)
real llra(174),llrb(174),llrc(174),llrd(174) !Soft symbols real llra(174),llrb(174),llrc(174),llrd(174) !Soft symbols
real llral(174),llrbl(174),llrcl(174) !Soft symbols
real dd0(15*12000) real dd0(15*12000)
integer*1 message77(77),apmask(174),cw(174) integer*1 message77(77),apmask(174),cw(174)
integer apsym(58) integer apsym(58)
integer mcq(29),mcqru(29),mcqfd(29),mcqtest(29),mcqhund(29) integer mcq(29),mcqru(29),mcqfd(29),mcqtest(29)
integer mrrr(19),m73(19),mrr73(19) integer mrrr(19),m73(19),mrr73(19)
integer itone(NN) integer itone(NN)
integer icos7(0:6),ip(1) integer icos7(0:6),ip(1)
integer nappasses(0:5) !Number of decoding passes to use for each QSO state 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 naptypes(0:5,4) ! (nQSOProgress, decoding pass) maximum of 4 passes for now
integer ncontest,ncontest0 integer ncontest,ncontest0
integer*1, target:: i1hiscall(12)
logical one(0:511,0:8) logical one(0:511,0:8)
integer graymap(0:7) integer graymap(0:7)
complex cd0(0:3199) complex cd0(0:3199)
@ -43,7 +38,6 @@ subroutine ft8b(dd0,newdat,nQSOProgress,nfqso,nftx,ndepth,lapon,lapcqonly, &
data mcqru/0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1,1,0,0,1,1,0,0/ data mcqru/0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1,1,0,0,1,1,0,0/
data mcqfd/0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,1,0,0,0,1,0/ data mcqfd/0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,1,0,0,0,1,0/
data mcqtest/0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,1,0,1,0,1,1,1,1,1,1,0,0,1,0/ data mcqtest/0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,1,0,1,0,1,1,1,1,1,1,0,0,1,0/
data mcqhund/0,0,0,0,0,0,0,0,0,0,1,0,1,0,1,0,1,0,0,0,0,1,0,0,1,1,1,0,0/
data mrrr/0,1,1,1,1,1,1,0,1,0,0,1,0,0,1,0,0,0,1/ data mrrr/0,1,1,1,1,1,1,0,1,0,0,1,0,0,1,0,0,0,1/
data m73/0,1,1,1,1,1,1,0,1,0,0,1,0,1,0,0,0,0,1/ data m73/0,1,1,1,1,1,1,0,1,0,0,1,0,1,0,0,0,0,1/
data mrr73/0,1,1,1,1,1,1,0,0,1,1,1,0,1,0,1,0,0,1/ data mrr73/0,1,1,1,1,1,1,0,0,1,1,1,0,1,0,1,0,0,1/
@ -57,7 +51,6 @@ subroutine ft8b(dd0,newdat,nQSOProgress,nfqso,nftx,ndepth,lapon,lapcqonly, &
mcqfd=2*mcqfd-1 mcqfd=2*mcqfd-1
mcqru=2*mcqru-1 mcqru=2*mcqru-1
mcqtest=2*mcqtest-1 mcqtest=2*mcqtest-1
mcqhund=2*mcqhund-1
mrrr=2*mrrr-1 mrrr=2*mrrr-1
m73=2*m73-1 m73=2*m73-1
mrr73=2*mrr73-1 mrr73=2*mrr73-1
@ -205,37 +198,26 @@ subroutine ft8b(dd0,newdat,nQSOProgress,nfqso,nftx,ndepth,lapon,lapcqonly, &
do ib=0,ibmax do ib=0,ibmax
bm=maxval(s2(0:nt-1),one(0:nt-1,ibmax-ib)) - & bm=maxval(s2(0:nt-1),one(0:nt-1,ibmax-ib)) - &
maxval(s2(0:nt-1),.not.one(0:nt-1,ibmax-ib)) maxval(s2(0:nt-1),.not.one(0:nt-1,ibmax-ib))
! bml=maxval(s2l(0:nt-1),one(0:nt-1,ibmax-ib)) - &
! maxval(s2l(0:nt-1),.not.one(0:nt-1,ibmax-ib))
if(i32+ib .gt.174) cycle if(i32+ib .gt.174) cycle
if(nsym.eq.1) then if(nsym.eq.1) then
bmeta(i32+ib)=bm bmeta(i32+ib)=bm
! bmetal(i32+ib)=bml
elseif(nsym.eq.2) then elseif(nsym.eq.2) then
bmetb(i32+ib)=bm bmetb(i32+ib)=bm
! bmetbl(i32+ib)=bml
elseif(nsym.eq.3) then elseif(nsym.eq.3) then
bmetc(i32+ib)=bm bmetc(i32+ib)=bm
! bmetcl(i32+ib)=bml
endif endif
enddo enddo
enddo enddo
enddo enddo
enddo enddo
call normalizebmet(bmeta,174) call normalizebmet(bmeta,174)
! call normalizebmet(bmetal,174)
call normalizebmet(bmetb,174) call normalizebmet(bmetb,174)
! call normalizebmet(bmetbl,174)
call normalizebmet(bmetc,174) call normalizebmet(bmetc,174)
! call normalizebmet(bmetcl,174)
scalefac=2.83 scalefac=2.83
llra=scalefac*bmeta llra=scalefac*bmeta
! llral=scalefac*bmetal
llrb=scalefac*bmetb llrb=scalefac*bmetb
! llrbl=scalefac*bmetbl
llrc=scalefac*bmetc llrc=scalefac*bmetc
! llrcl=scalefac*bmetcl
apmag=maxval(abs(llra))*1.01 apmag=maxval(abs(llra))*1.01
@ -290,7 +272,6 @@ subroutine ft8b(dd0,newdat,nQSOProgress,nfqso,nftx,ndepth,lapon,lapcqonly, &
if(ncontest.eq.6.and.f1.gt.950.0) cycle ! Hounds use AP only for signals below 950 Hz if(ncontest.eq.6.and.f1.gt.950.0) cycle ! Hounds use AP only for signals below 950 Hz
if(iaptype.ge.2 .and. apsym(1).gt.1) cycle ! No, or nonstandard, mycall if(iaptype.ge.2 .and. apsym(1).gt.1) cycle ! No, or nonstandard, mycall
if(iaptype.ge.3 .and. apsym(30).gt.1) cycle ! No, or nonstandard, dxcall if(iaptype.ge.3 .and. apsym(30).gt.1) cycle ! No, or nonstandard, dxcall
apsym=2*apsym-1 ! Change from [0,1] to antipodal
if(iaptype.eq.1) then ! CQ or CQ RU or CQ TEST or CQ FD if(iaptype.eq.1) then ! CQ or CQ RU or CQ TEST or CQ FD
apmask=0 apmask=0
@ -300,7 +281,7 @@ subroutine ft8b(dd0,newdat,nQSOProgress,nfqso,nftx,ndepth,lapon,lapcqonly, &
if(ncontest.eq.2) llrd(1:29)=apmag*mcqtest(1:29) if(ncontest.eq.2) llrd(1:29)=apmag*mcqtest(1:29)
if(ncontest.eq.3) llrd(1:29)=apmag*mcqfd(1:29) if(ncontest.eq.3) llrd(1:29)=apmag*mcqfd(1:29)
if(ncontest.eq.4) llrd(1:29)=apmag*mcqru(1:29) if(ncontest.eq.4) llrd(1:29)=apmag*mcqru(1:29)
if(ncontest.eq.6) llrd(1:29)=apmag*mcqhund(1:29) if(ncontest.eq.6) llrd(1:29)=apmag*mcq(1:29)
apmask(75:77)=1 apmask(75:77)=1
llrd(75:76)=apmag*(-1) llrd(75:76)=apmag*(-1)
llrd(77)=apmag*(+1) llrd(77)=apmag*(+1)

View File

@ -8,14 +8,11 @@ program ft8code
include 'ft8_testmsg.f90' include 'ft8_testmsg.f90'
parameter (NWAVE=NN*NSPS) parameter (NWAVE=NN*NSPS)
character*77 c77
character*37 msg,msgsent character*37 msg,msgsent
character*9 comment character*9 comment
character bad*1,msgtype*16 character bad*1,msgtype*18
character*91 cbits
integer itone(NN) integer itone(NN)
integer*1 msgbits(77) integer*1 msgbits(77)
logical unpk77_success
! Get command-line argument(s) ! Get command-line argument(s)
nargs=iargc() nargs=iargc()
@ -69,10 +66,10 @@ program ft8code
if(msg.ne.msgsent) bad="*" if(msg.ne.msgsent) bad="*"
if(n3.ge.0) then if(n3.ge.0) then
write(*,1020) imsg,msg,msgsent,bad,i3,n3,msgtype,comment write(*,1020) imsg,msg,msgsent,bad,i3,n3,msgtype,comment
1020 format(i2,'.',1x,a37,1x,a37,1x,a1,2x,i1,'.',i1,1x,a16,1x,a9) 1020 format(i2,'.',1x,a37,1x,a37,1x,a1,2x,i1,'.',i1,1x,a18,1x,a9)
else else
write(*,1022) imsg,msg,msgsent,bad,i3,msgtype,comment write(*,1022) imsg,msg,msgsent,bad,i3,msgtype,comment
1022 format(i2,'.',1x,a37,1x,a37,1x,a1,2x,i1,'.',1x,1x,a16,1x,a9) 1022 format(i2,'.',1x,a37,1x,a37,1x,a1,2x,i1,'.',1x,1x,a18,1x,a9)
endif endif
enddo enddo

View File

@ -9,7 +9,7 @@ program ft8sim
parameter (NWAVE=NN*NSPS) parameter (NWAVE=NN*NSPS)
type(hdr) h !Header for .wav file type(hdr) h !Header for .wav file
character arg*12,fname*17 character arg*12,fname*17
character msg37*37,msgsent37*37,msg40*40 character msg37*37,msgsent37*37
character c77*77 character c77*77
complex c0(0:NMAX-1) complex c0(0:NMAX-1)
complex c(0:NMAX-1) complex c(0:NMAX-1)
@ -108,7 +108,6 @@ program ft8sim
ib=k ib=k
wave=real(c) wave=real(c)
peak=maxval(abs(wave(ia:ib))) peak=maxval(abs(wave(ia:ib)))
rms=sqrt(dot_product(wave(ia:ib),wave(ia:ib))/NWAVE)
nslots=1 nslots=1
if(width.gt.0.0) call filt8(f0,nslots,width,wave) if(width.gt.0.0) call filt8(f0,nslots,width,wave)
@ -119,10 +118,16 @@ program ft8sim
enddo enddo
endif endif
fac=32767.0 gain=100.0
rms=100.0 if(snrdb.lt.90.0) then
if(snrdb.ge.90.0) iwave(1:NMAX)=nint(fac*wave) wave=gain*wave
if(snrdb.lt.90.0) iwave(1:NMAX)=nint(rms*wave) else
datpk=maxval(abs(wave))
fac=32766.9/datpk
wave=fac*wave
endif
if(any(abs(wave).gt.32767.0)) print*,"Warning - data will be clipped."
iwave=nint(wave)
h=default_header(12000,NMAX) h=default_header(12000,NMAX)
write(fname,1102) ifile write(fname,1102) ifile

View File

@ -19,8 +19,11 @@ subroutine genft8(msg,i3,n3,msgsent,msgbits,itone)
call pack77(msg,i3,n3,c77) call pack77(msg,i3,n3,c77)
call unpack77(c77,msgsent,unpk77_success) call unpack77(c77,msgsent,unpk77_success)
read(c77,'(77i1)',err=1) msgbits read(c77,'(77i1)',err=1) msgbits
go to 2 if(unpk77_success) go to 2
1 write(81,*) msg,c77 ; flush(81) 1 msgbits=0
itone=0
msgsent='*** bad message *** '
go to 900
entry get_tones_from_77bits(msgbits,itone) entry get_tones_from_77bits(msgbits,itone)
@ -39,5 +42,5 @@ entry get_tones_from_77bits(msgbits,itone)
itone(k)=graymap(indx) itone(k)=graymap(indx)
enddo enddo
return 900 return
end subroutine genft8 end subroutine genft8

View File

@ -1,365 +0,0 @@
subroutine osd174(llr,apmask,ndeep,decoded,cw,nhardmin,dmin)
!
! An ordered-statistics decoder for the (174,87) code.
!
include "ldpc_174_87_params.f90"
integer*1 apmask(N),apmaskr(N)
integer*1 gen(K,N)
integer*1 genmrb(K,N),g2(N,K)
integer*1 temp(K),m0(K),me(K),mi(K),misub(K),e2sub(N-K),e2(N-K),ui(N-K)
integer*1 r2pat(N-K)
integer indices(N),nxor(N)
integer*1 cw(N),ce(N),c0(N),hdec(N)
integer*1 decoded(K)
integer indx(N)
real llr(N),rx(N),absrx(N)
logical first,reset
data first/.true./
save first,gen
if( first ) then ! fill the generator matrix
gen=0
do i=1,M
do j=1,22
read(g(i)(j:j),"(Z1)") istr
do jj=1, 4
irow=(j-1)*4+jj
if( btest(istr,4-jj) ) gen(irow,i)=1
enddo
enddo
enddo
do irow=1,K
gen(irow,M+irow)=1
enddo
first=.false.
endif
! Re-order received vector to place systematic msg bits at the end.
rx=llr(colorder+1)
apmaskr=apmask(colorder+1)
! Hard decisions on the received word.
hdec=0
where(rx .ge. 0) hdec=1
! Use magnitude of received symbols as a measure of reliability.
absrx=abs(rx)
call indexx(absrx,N,indx)
! Re-order the columns of the generator matrix in order of decreasing reliability.
do i=1,N
genmrb(1:K,i)=gen(1:K,indx(N+1-i))
indices(i)=indx(N+1-i)
enddo
! Do gaussian elimination to create a generator matrix with the most reliable
! received bits in positions 1:K in order of decreasing reliability (more or less).
do id=1,K ! diagonal element indices
do icol=id,K+20 ! The 20 is ad hoc - beware
iflag=0
if( genmrb(id,icol) .eq. 1 ) then
iflag=1
if( icol .ne. id ) then ! reorder column
temp(1:K)=genmrb(1:K,id)
genmrb(1:K,id)=genmrb(1:K,icol)
genmrb(1:K,icol)=temp(1:K)
itmp=indices(id)
indices(id)=indices(icol)
indices(icol)=itmp
endif
do ii=1,K
if( ii .ne. id .and. genmrb(ii,id) .eq. 1 ) then
genmrb(ii,1:N)=ieor(genmrb(ii,1:N),genmrb(id,1:N))
endif
enddo
exit
endif
enddo
enddo
g2=transpose(genmrb)
! The hard decisions for the K MRB bits define the order 0 message, m0.
! Encode m0 using the modified generator matrix to find the "order 0" codeword.
! Flip various combinations of bits in m0 and re-encode to generate a list of
! codewords. Return the member of the list that has the smallest Euclidean
! distance to the received word.
hdec=hdec(indices) ! hard decisions from received symbols
m0=hdec(1:K) ! zero'th order message
absrx=absrx(indices)
rx=rx(indices)
apmaskr=apmaskr(indices)
call mrbencode(m0,c0,g2,N,K)
nxor=ieor(c0,hdec)
nhardmin=sum(nxor)
dmin=sum(nxor*absrx)
cw=c0
ntotal=0
nrejected=0
if(ndeep.eq.0) goto 998 ! norder=0
if(ndeep.gt.5) ndeep=5
if( ndeep.eq. 1) then
nord=1
npre1=0
npre2=0
nt=40
ntheta=12
elseif(ndeep.eq.2) then
nord=1
npre1=1
npre2=0
nt=40
ntheta=12
elseif(ndeep.eq.3) then
nord=1
npre1=1
npre2=1
nt=40
ntheta=12
ntau=14
elseif(ndeep.eq.4) then
nord=2
npre1=1
npre2=0
nt=40
ntheta=12
ntau=19
elseif(ndeep.eq.5) then
nord=2
npre1=1
npre2=1
nt=40
ntheta=12
ntau=19
endif
do iorder=1,nord
misub(1:K-iorder)=0
misub(K-iorder+1:K)=1
iflag=K-iorder+1
do while(iflag .ge.0)
if(iorder.eq.nord .and. npre1.eq.0) then
iend=iflag
else
iend=1
endif
do n1=iflag,iend,-1
mi=misub
mi(n1)=1
if(any(iand(apmaskr(1:K),mi).eq.1)) cycle
ntotal=ntotal+1
me=ieor(m0,mi)
if(n1.eq.iflag) then
call mrbencode(me,ce,g2,N,K)
e2sub=ieor(ce(K+1:N),hdec(K+1:N))
e2=e2sub
nd1Kpt=sum(e2sub(1:nt))+1
d1=sum(ieor(me(1:K),hdec(1:K))*absrx(1:K))
else
e2=ieor(e2sub,g2(K+1:N,n1))
nd1Kpt=sum(e2(1:nt))+2
endif
if(nd1Kpt .le. ntheta) then
call mrbencode(me,ce,g2,N,K)
nxor=ieor(ce,hdec)
if(n1.eq.iflag) then
dd=d1+sum(e2sub*absrx(K+1:N))
else
dd=d1+ieor(ce(n1),hdec(n1))*absrx(n1)+sum(e2*absrx(K+1:N))
endif
if( dd .lt. dmin ) then
dmin=dd
cw=ce
nhardmin=sum(nxor)
nd1Kptbest=nd1Kpt
endif
else
nrejected=nrejected+1
endif
enddo
! Get the next test error pattern, iflag will go negative
! when the last pattern with weight iorder has been generated.
call nextpat(misub,k,iorder,iflag)
enddo
enddo
if(npre2.eq.1) then
reset=.true.
ntotal=0
do i1=K,1,-1
do i2=i1-1,1,-1
ntotal=ntotal+1
mi(1:ntau)=ieor(g2(K+1:K+ntau,i1),g2(K+1:K+ntau,i2))
call boxit(reset,mi(1:ntau),ntau,ntotal,i1,i2)
enddo
enddo
ncount2=0
ntotal2=0
reset=.true.
! Now run through again and do the second pre-processing rule
misub(1:K-nord)=0
misub(K-nord+1:K)=1
iflag=K-nord+1
do while(iflag .ge.0)
me=ieor(m0,misub)
call mrbencode(me,ce,g2,N,K)
e2sub=ieor(ce(K+1:N),hdec(K+1:N))
do i2=0,ntau
ntotal2=ntotal2+1
ui=0
if(i2.gt.0) ui(i2)=1
r2pat=ieor(e2sub,ui)
778 continue
call fetchit(reset,r2pat(1:ntau),ntau,in1,in2)
if(in1.gt.0.and.in2.gt.0) then
ncount2=ncount2+1
mi=misub
mi(in1)=1
mi(in2)=1
if(sum(mi).lt.nord+npre1+npre2.or.any(iand(apmaskr(1:K),mi).eq.1)) cycle
me=ieor(m0,mi)
call mrbencode(me,ce,g2,N,K)
nxor=ieor(ce,hdec)
dd=sum(nxor*absrx)
if( dd .lt. dmin ) then
dmin=dd
cw=ce
nhardmin=sum(nxor)
endif
goto 778
endif
enddo
call nextpat(misub,K,nord,iflag)
enddo
endif
998 continue
! Re-order the codeword to place message bits at the end.
cw(indices)=cw
hdec(indices)=hdec
decoded=cw(M+1:N)
cw(colorder+1)=cw ! put the codeword back into received-word order
return
end subroutine osd174
subroutine mrbencode(me,codeword,g2,N,K)
integer*1 me(K),codeword(N),g2(N,K)
! fast encoding for low-weight test patterns
codeword=0
do i=1,K
if( me(i) .eq. 1 ) then
codeword=ieor(codeword,g2(1:N,i))
endif
enddo
return
end subroutine mrbencode
subroutine nextpat(mi,k,iorder,iflag)
integer*1 mi(k),ms(k)
! generate the next test error pattern
ind=-1
do i=1,k-1
if( mi(i).eq.0 .and. mi(i+1).eq.1) ind=i
enddo
if( ind .lt. 0 ) then ! no more patterns of this order
iflag=ind
return
endif
ms=0
ms(1:ind-1)=mi(1:ind-1)
ms(ind)=1
ms(ind+1)=0
if( ind+1 .lt. k ) then
nz=iorder-sum(ms)
ms(k-nz+1:k)=1
endif
mi=ms
do i=1,k ! iflag will point to the lowest-index 1 in mi
if(mi(i).eq.1) then
iflag=i
exit
endif
enddo
return
end subroutine nextpat
subroutine boxit(reset,e2,ntau,npindex,i1,i2)
integer*1 e2(1:ntau)
integer indexes(4000,2),fp(0:525000),np(4000)
logical reset
common/boxes/indexes,fp,np
if(reset) then
patterns=-1
fp=-1
np=-1
sc=-1
indexes=-1
reset=.false.
endif
indexes(npindex,1)=i1
indexes(npindex,2)=i2
ipat=0
do i=1,ntau
if(e2(i).eq.1) then
ipat=ipat+ishft(1,ntau-i)
endif
enddo
ip=fp(ipat) ! see what's currently stored in fp(ipat)
if(ip.eq.-1) then
fp(ipat)=npindex
else
do while (np(ip).ne.-1)
ip=np(ip)
enddo
np(ip)=npindex
endif
return
end subroutine boxit
subroutine fetchit(reset,e2,ntau,i1,i2)
integer indexes(4000,2),fp(0:525000),np(4000)
integer lastpat
integer*1 e2(ntau)
logical reset
common/boxes/indexes,fp,np
save lastpat,inext
if(reset) then
lastpat=-1
reset=.false.
endif
ipat=0
do i=1,ntau
if(e2(i).eq.1) then
ipat=ipat+ishft(1,ntau-i)
endif
enddo
index=fp(ipat)
if(lastpat.ne.ipat .and. index.gt.0) then ! return first set of indices
i1=indexes(index,1)
i2=indexes(index,2)
inext=np(index)
elseif(lastpat.eq.ipat .and. inext.gt.0) then
i1=indexes(inext,1)
i2=indexes(inext,2)
inext=np(inext)
else
i1=-1
i2=-1
inext=-1
endif
lastpat=ipat
return
end subroutine fetchit

View File

@ -44,7 +44,6 @@ subroutine sync8(dd,nfa,nfb,syncmin,nfqso,maxcand,s,candidate, &
nssy=NSPS/NSTEP ! # steps per symbol nssy=NSPS/NSTEP ! # steps per symbol
nfos=NFFT1/NSPS ! # frequency bin oversampling factor nfos=NFFT1/NSPS ! # frequency bin oversampling factor
jstrt=0.5/tstep jstrt=0.5/tstep
candidate0=0. candidate0=0.
k=0 k=0
@ -133,7 +132,8 @@ subroutine sync8(dd,nfa,nfb,syncmin,nfqso,maxcand,s,candidate, &
j=indx(i) j=indx(i)
! if( candidate0(3,j) .ge. syncmin .and. candidate0(2,j).ge.-1.5 ) then ! if( candidate0(3,j) .ge. syncmin .and. candidate0(2,j).ge.-1.5 ) then
if( candidate0(3,j) .ge. syncmin ) then if( candidate0(3,j) .ge. syncmin ) then
candidate(1:3,k)=abs(candidate0(1:3,j)) candidate(2:3,k)=candidate0(2:3,j)
candidate(1,k)=abs(candidate0(1,j))
k=k+1 k=k+1
endif endif
enddo enddo

View File

@ -52,7 +52,7 @@ contains
character*12 mycall12,hiscall12,mycall12_0 character*12 mycall12,hiscall12,mycall12_0
character*6 hisgrid6 character*6 hisgrid6
integer*2 iwave(15*12000) integer*2 iwave(15*12000)
integer apsym1(KK),apsym2(58) integer apsym2(58)
character datetime*13,msg37*37 character datetime*13,msg37*37
! character message*22 ! character message*22
character*37 allmessages(100) character*37 allmessages(100)

View File

@ -21,12 +21,13 @@ program jt65sim
character msg*22,fname*11,csubmode*1,c,optarg*500,numbuf*32 character msg*22,fname*11,csubmode*1,c,optarg*500,numbuf*32
! character call1*5,call2*5 ! character call1*5,call2*5
logical :: display_help=.false.,seed_prngs=.true. logical :: display_help=.false.,seed_prngs=.true.
type (option) :: long_options(12) = [ & type (option) :: long_options(13) = [ &
option ('help',.false.,'h','Display this help message',''), & option ('help',.false.,'h','Display this help message',''), &
option ('sub-mode',.true.,'m','sub mode, default MODE=A','MODE'), & option ('sub-mode',.true.,'m','sub mode, default MODE=A','MODE'), &
option ('num-sigs',.true.,'n','number of signals per file, default SIGNALS=10','SIGNALS'), & option ('num-sigs',.true.,'n','number of signals per file, default SIGNALS=10','SIGNALS'), &
option ('f0',.true.,'F','base frequency offset, default F0=1500.0','F0'), & option ('f0',.true.,'F','base frequency offset, default F0=1500.0','F0'), &
option ('doppler-spread',.true.,'d','Doppler spread, default SPREAD=0.0','SPREAD'), & option ('doppler-spread',.true.,'d','Doppler spread, default SPREAD=0.0','SPREAD'), &
option ('drift per min',.true.,'D','Frequency drift (Hz/min), default DRIFT=0.0','DRIFT'), &
option ('time-offset',.true.,'t','Time delta, default SECONDS=0.0','SECONDS'), & option ('time-offset',.true.,'t','Time delta, default SECONDS=0.0','SECONDS'), &
option ('num-files',.true.,'f','Number of files to generate, default FILES=1','FILES'), & option ('num-files',.true.,'f','Number of files to generate, default FILES=1','FILES'), &
option ('no-prng-seed',.false.,'p','Do not seed PRNGs (use for reproducible tests)',''), & option ('no-prng-seed',.false.,'p','Do not seed PRNGs (use for reproducible tests)',''), &
@ -50,6 +51,7 @@ program jt65sim
nsigs=10 nsigs=10
bf0=1500. bf0=1500.
fspread=0. fspread=0.
drift=0.
xdt=0. xdt=0.
snrdb=0. snrdb=0.
nfiles=1 nfiles=1
@ -58,7 +60,7 @@ program jt65sim
msg="K1ABC W9XYZ EN37" msg="K1ABC W9XYZ EN37"
do do
call getopt('hm:n:F:d:t:f:ps:SG:M:',long_options,c,optarg,narglen,nstat,noffset,nremain,.true.) call getopt('hm:n:F:d:D:t:f:ps:SG:M:',long_options,c,optarg,narglen,nstat,noffset,nremain,.true.)
if( nstat .ne. 0 ) then if( nstat .ne. 0 ) then
exit exit
end if end if
@ -76,6 +78,8 @@ program jt65sim
read (optarg(:narglen), *,err=10) bf0 read (optarg(:narglen), *,err=10) bf0
case ('d') case ('d')
read (optarg(:narglen), *,err=10) fspread read (optarg(:narglen), *,err=10) fspread
case ('D')
read (optarg(:narglen), *,err=10) drift
case ('t') case ('t')
read (optarg(:narglen), *) numbuf read (optarg(:narglen), *) numbuf
if (numbuf(1:1) == '\') then !'\' if (numbuf(1:1) == '\') then !'\'
@ -105,7 +109,6 @@ program jt65sim
end if end if
case ('M') case ('M')
read (optarg(:narglen), '(A)',err=10) msg read (optarg(:narglen), '(A)',err=10) msg
write(*,*) msg
end select end select
cycle cycle
10 display_help=.true. 10 display_help=.true.
@ -190,6 +193,21 @@ program jt65sim
endif endif
enddo enddo
if(len(trim(msg)).eq.2.or.len(trim(msg)).eq.3) then
nshorthand=0
if(msg(1:2).eq.'RO') nshorthand=2
if(msg(1:3).eq.'RRR') nshorthand=3
if(msg(1:2).eq.'73') nshorthand=4
if(nshorthand.gt.0) then
ntoggle=0
do i=1,nsym,2
itone(i)=ntoggle*10*nshorthand
if(i+1.le.126) itone(i+1)=ntoggle*10*nshorthand
ntoggle=mod(ntoggle+1,2)
enddo
endif
endif
bandwidth_ratio=2500.0/(fsample/2.0) bandwidth_ratio=2500.0/(fsample/2.0)
sig=sqrt(2*bandwidth_ratio)*10.0**(0.05*xsnr) sig=sqrt(2*bandwidth_ratio)*10.0**(0.05*xsnr)
if(xsnr.gt.90.0) sig=1.0 if(xsnr.gt.90.0) sig=1.0
@ -203,11 +221,8 @@ program jt65sim
do i=1,npts !Add this signal into cdat() do i=1,npts !Add this signal into cdat()
isym=floor(i/sps)+1 isym=floor(i/sps)+1
if(isym.gt.nsym) exit if(isym.gt.nsym) exit
if(isym.ne.isym0) then freq=f0 + (drift/60.0)*(i-npts/2)*dt + itone(isym)*baud*mode65
freq=f0 + itone(isym)*baud*mode65 dphi=twopi*freq*dt
dphi=twopi*freq*dt
isym0=isym
endif
phi=phi + dphi phi=phi + dphi
if(phi.gt.twopi) phi=phi-twopi if(phi.gt.twopi) phi=phi-twopi
xphi=phi xphi=phi
@ -282,9 +297,9 @@ program jt65sim
endif endif
dat=aimag(cdat) + xnoise !Add the generated noise dat(1:npts)=aimag(cdat(1:npts)) + xnoise(1:npts) !Add the generated noise
if(snrdb.lt.90.0) then if(snrdb.lt.90.0) then
dat=rms*dat(1:npts) dat(1:npts)=rms*dat(1:npts)
else else
datpk=maxval(abs(dat(1:npts))) datpk=maxval(abs(dat(1:npts)))
fac=32766.9/datpk fac=32766.9/datpk

View File

@ -5,7 +5,7 @@ program msk144code
use packjt77 use packjt77
character*77 c77 character*77 c77
character msg*37,msgsent*37,decoded,bad*1,msgtype*16 character msg*37,msgsent*37,decoded,bad*1,msgtype*18
integer*4 i4tone(144) integer*4 i4tone(144)
include 'msk144_testmsg.f90' include 'msk144_testmsg.f90'
@ -61,13 +61,13 @@ program msk144code
if(msg.ne.msgsent) bad="*" if(msg.ne.msgsent) bad="*"
if(i3.eq.0.and.n3.ge.0) then if(i3.eq.0.and.n3.ge.0) then
write(*,1020) imsg,msg,msgsent,bad,i3,n3,msgtype write(*,1020) imsg,msg,msgsent,bad,i3,n3,msgtype
1020 format(i2,'.',1x,a37,1x,a37,1x,a1,2x,i1,'.',i1,1x,a16) 1020 format(i2,'.',1x,a37,1x,a37,1x,a1,2x,i1,'.',i1,1x,a18)
elseif(i3.ge.1) then elseif(i3.ge.1) then
write(*,1022) imsg,msg,msgsent,bad,i3,msgtype write(*,1022) imsg,msg,msgsent,bad,i3,msgtype
1022 format(i2,'.',1x,a37,1x,a37,1x,a1,2x,i1,'.',1x,1x,a16) 1022 format(i2,'.',1x,a37,1x,a37,1x,a1,2x,i1,'.',1x,1x,a18)
elseif(i3.lt.0) then elseif(i3.lt.0) then
write(*,1024) imsg,msg,msgsent,bad,msgtype write(*,1024) imsg,msg,msgsent,bad,msgtype
1024 format(i2,'.',1x,a37,1x,a37,1x,a1,6x,a16) 1024 format(i2,'.',1x,a37,1x,a37,1x,a1,6x,a18)
endif endif
enddo enddo

View File

@ -100,7 +100,7 @@ subroutine msk144decodeframe(c,softbits,msgreceived,nsuccess)
if( nharderror .ge. 0 .and. nharderror .lt. 18 ) then if( nharderror .ge. 0 .and. nharderror .lt. 18 ) then
nsuccess=1 nsuccess=1
write(c77,'(77i1)') decoded77 write(c77,'(77i1)') decoded77
read(c77(72:77),'(2b3)'),n3,i3 read(c77(72:77),'(2b3)') n3,i3
if( (i3.eq.0.and.(n3.eq.1 .or. n3.eq.3 .or. n3.eq.4 .or. n3.gt.5)) .or. i3.eq.3 .or. i3.gt.4 ) then if( (i3.eq.0.and.(n3.eq.1 .or. n3.eq.3 .or. n3.eq.4 .or. n3.gt.5)) .or. i3.eq.3 .or. i3.gt.4 ) then
nsuccess=0 nsuccess=0
else else

View File

@ -5,7 +5,6 @@ program msk144sim
real pings(0:NMAX-1) real pings(0:NMAX-1)
real waveform(0:NMAX-1) real waveform(0:NMAX-1)
character arg*8,msg*37,msgsent*37,fname*40 character arg*8,msg*37,msgsent*37,fname*40
character*77 c77
real wave(0:NMAX-1) !Simulated received waveform real wave(0:NMAX-1) !Simulated received waveform
real*8 twopi,freq,phi,dphi0,dphi1,dphi real*8 twopi,freq,phi,dphi0,dphi1,dphi
type(hdr) h !Header for .wav file type(hdr) h !Header for .wav file

View File

@ -29,7 +29,7 @@ subroutine sync4(dat,jz,ntol,nfqso,mode,mode4,minwidth,dtx,dfx,snrx, &
df=0.5*11025.0/nfft df=0.5*11025.0/nfft
ftop=nfqso + 7*mode4*df ftop=nfqso + 7*mode4*df
if(ftop.gt.11025.0/4.0) then if(ftop.gt.11025.0/4.0) then
print*,'*** Rx Freq is set too high for this submode ***' print*,'*** Rx Freq is set too high for this sybmode ***'
go to 900 go to 900
endif endif
@ -139,11 +139,8 @@ subroutine sync4(dat,jz,ntol,nfqso,mode,mode4,minwidth,dtx,dfx,snrx, &
ns=ns+1 ns=ns+1
endif endif
enddo enddo
rms=0.1 rms=sqrt(sq/ns)
snrx=-26.0 snrx=10.0*log10(ccfred(ipk1a)/rms) - 41.2
if(ns.gt.0) rms=sqrt(sq/ns)
if(ccfred(ipk1a).gt.0.0) snrx=10.0*log10(ccfred(ipk1a)/rms) - 41.2
if(snrx.gt.50.0) snrx=50.0
900 return 900 return
end subroutine sync4 end subroutine sync4

View File

@ -159,8 +159,9 @@ public:
{ {
} }
Record fixup (QString const& call, prefix const& p) const Record fixup (QString call, prefix const& p) const
{ {
call = call.toUpper ();
using entity_by_id = entities_type::index<id>::type; using entity_by_id = entities_type::index<id>::type;
entity_by_id::iterator e; // iterator into entity set entity_by_id::iterator e; // iterator into entity set

View File

@ -1,22 +1,29 @@
#include "WorkedBefore.hpp" #include "WorkedBefore.hpp"
#include <functional> #include <functional>
#include <stdexcept>
#include <boost/functional/hash.hpp> #include <boost/functional/hash.hpp>
#include <boost/multi_index_container.hpp> #include <boost/multi_index_container.hpp>
#include <boost/multi_index/hashed_index.hpp> #include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/ordered_index.hpp> #include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/key_extractors.hpp> #include <boost/multi_index/key_extractors.hpp>
#include <QtConcurrent/QtConcurrentRun>
#include <QFuture>
#include <QFutureWatcher>
#include <QChar> #include <QChar>
#include <QString> #include <QString>
#include <QByteArray> #include <QByteArray>
#include <QStandardPaths> #include <QStandardPaths>
#include <QDir> #include <QDir>
#include <QFileInfo>
#include <QFile> #include <QFile>
#include <QTextStream> #include <QTextStream>
#include <QDebug>
#include "qt_helpers.hpp" #include "qt_helpers.hpp"
#include "pimpl_impl.hpp" #include "pimpl_impl.hpp"
#include "moc_WorkedBefore.cpp"
using namespace boost::multi_index; using namespace boost::multi_index;
// hash function for QString members in hashed indexes // hash function for QString members in hashed indexes
@ -214,6 +221,20 @@ namespace
{ {
auto const logFileName = "wsjtx_log.adi"; auto const logFileName = "wsjtx_log.adi";
// Expception class suitable for using with QtConcurrent across
// thread boundaries
class LoaderException final
: public QException
{
public:
LoaderException (std::exception const& e) : error_ {e.what ()} {}
QString error () const {return error_;}
void raise () const override {throw *this;}
LoaderException * clone () const override {return new LoaderException {*this};}
private:
QString error_;
};
QString extractField (QString const& record, QString const& fieldName) QString extractField (QString const& record, QString const& fieldName)
{ {
int fieldNameIndex = record.indexOf ('<' + fieldName + ':', 0, Qt::CaseInsensitive); int fieldNameIndex = record.indexOf ('<' + fieldName + ':', 0, Qt::CaseInsensitive);
@ -228,8 +249,12 @@ namespace
if (dataTypeIndex > closingBracketIndex) if (dataTypeIndex > closingBracketIndex)
dataTypeIndex = -1; // second : was found but it was beyond the closing > dataTypeIndex = -1; // second : was found but it was beyond the closing >
} }
else
{
throw LoaderException (std::runtime_error {"Invalid ADIF field " + fieldName.toStdString () + ": " + record.toStdString ()});
}
if ((closingBracketIndex > fieldNameIndex) && (fieldLengthIndex > fieldNameIndex) && (fieldLengthIndex< closingBracketIndex)) if (closingBracketIndex > fieldNameIndex && fieldLengthIndex > fieldNameIndex && fieldLengthIndex < closingBracketIndex)
{ {
int fieldLengthCharCount = closingBracketIndex - fieldLengthIndex -1; int fieldLengthCharCount = closingBracketIndex - fieldLengthIndex -1;
if (dataTypeIndex >= 0) if (dataTypeIndex >= 0)
@ -241,8 +266,93 @@ namespace
return record.mid(closingBracketIndex+1,fieldLength); return record.mid(closingBracketIndex+1,fieldLength);
} }
} }
else
{
throw LoaderException (std::runtime_error {"Malformed ADIF field " + fieldName.toStdString () + ": " + record.toStdString ()});
}
} }
return ""; return QString {};
}
worked_before_database_type loader (QString const& path, AD1CCty const * prefixes)
{
worked_before_database_type worked;
QFile inputFile {path};
if (inputFile.exists ())
{
if (inputFile.open (QFile::ReadOnly))
{
QTextStream in {&inputFile};
QString buffer;
bool pre_read {false};
int end_position {-1};
// skip optional header record
do
{
buffer += in.readLine () + '\n';
if (buffer.startsWith (QChar {'<'})) // denotes no header
{
pre_read = true;
}
else
{
end_position = buffer.indexOf ("<EOH>", 0, Qt::CaseInsensitive);
}
}
while (!in.atEnd () && !pre_read && end_position < 0);
if (!pre_read) // found header
{
if (end_position < 0)
{
throw LoaderException (std::runtime_error {"Invalid ADIF header"});
}
buffer.remove (0, end_position + 5);
}
while (!in.atEnd ())
{
end_position = buffer.indexOf ("<EOR>", 0, Qt::CaseInsensitive);
do
{
if (!in.atEnd () && end_position < 0)
{
buffer += in.readLine () + '\n';
}
}
while ((end_position = buffer.indexOf ("<EOR>", 0, Qt::CaseInsensitive)) < 0 && !in.atEnd ());
if (end_position < 0)
{
throw LoaderException (std::runtime_error {"Invalid ADIF record starting at: " + buffer.left (40).toStdString ()});
}
auto record = buffer.left (end_position + 5).trimmed ();
auto next_record = buffer.indexOf (QChar {'<'}, end_position + 5);
buffer.remove (0, next_record >=0 ? next_record : buffer.size ());
record = record.mid (record.indexOf (QChar {'<'}));
auto call = extractField (record, "CALL");
if (call.size ())
{
auto const& entity = prefixes->lookup (call);
worked.emplace (call.toUpper ()
, extractField (record, "GRIDSQUARE").left (4).toUpper () // not interested in 6-digit grids
, extractField (record, "BAND").toUpper ()
, extractField (record, "MODE").toUpper ()
, entity.entity_name
, entity.continent
, entity.CQ_zone
, entity.ITU_zone);
}
else
{
throw LoaderException (std::runtime_error {"Invalid ADIF record with no CALL: " + record.toStdString ()});
}
}
}
else
{
throw LoaderException (std::runtime_error {"Error opening ADIF log file for read: " + inputFile.errorString ().toStdString ()});
}
}
return worked;
} }
} }
@ -254,70 +364,41 @@ public:
{ {
} }
void reload ()
{
async_loader_ = QtConcurrent::run (loader, path_, &prefixes_);
loader_watcher_.setFuture (async_loader_);
}
QString path_; QString path_;
AD1CCty prefixes_; AD1CCty prefixes_;
QFutureWatcher<worked_before_database_type> loader_watcher_;
QFuture<worked_before_database_type> async_loader_;
worked_before_database_type worked_; worked_before_database_type worked_;
}; };
WorkedBefore::WorkedBefore () WorkedBefore::WorkedBefore ()
{ {
QFile inputFile {m_->path_}; connect (&m_->loader_watcher_, &QFutureWatcher<worked_before_database_type>::finished, [this] () {
if (inputFile.open (QFile::ReadOnly)) QString error;
{ size_t n {0};
QTextStream in {&inputFile}; try
QString buffer; {
bool pre_read {false}; m_->worked_ = m_->loader_watcher_.result ();
int end_position {-1}; n = m_->worked_.size ();
}
catch (LoaderException const& e)
{
error = e.error ();
}
Q_EMIT finished_loading (n, error);
});
reload ();
}
// skip optional header record void WorkedBefore::reload ()
do {
{ m_->reload ();
buffer += in.readLine () + '\n';
if (buffer.startsWith (QChar {'<'})) // denotes no header
{
pre_read = true;
}
else
{
end_position = buffer.indexOf ("<EOH>", 0, Qt::CaseInsensitive);
}
}
while (!in.atEnd () && !pre_read && end_position < 0);
if (!pre_read) // found header
{
buffer.remove (0, end_position + 5);
}
while (buffer.size () || !in.atEnd ())
{
do
{
end_position = buffer.indexOf ("<EOR>", 0, Qt::CaseInsensitive);
if (!in.atEnd () && end_position < 0)
{
buffer += in.readLine () + '\n';
}
}
while (!in.atEnd () && end_position < 0);
int record_length {end_position >= 0 ? end_position + 5 : -1};
auto record = buffer.left (record_length).trimmed ();
auto next_record = buffer.indexOf (QChar {'<'}, record_length);
buffer.remove (0, next_record >=0 ? next_record : buffer.size ());
record = record.mid (record.indexOf (QChar {'<'}));
auto call = extractField (record, "CALL");
if (call.size ())
{
auto const& entity = m_->prefixes_.lookup (call);
m_->worked_.emplace (call
, extractField (record, "GRIDSQUARE").left (4) // not interested in 6-digit grids
, extractField (record, "BAND")
, extractField (record, "MODE")
, entity.entity_name
, entity.continent
, entity.CQ_zone
, entity.ITU_zone);
}
}
}
} }
WorkedBefore::~WorkedBefore () WorkedBefore::~WorkedBefore ()
@ -357,8 +438,8 @@ bool WorkedBefore::add (QString const& call
} }
out << ADIF_record << " <eor>" << endl; out << ADIF_record << " <eor>" << endl;
} }
m_->worked_.emplace (call, grid, band, mode, entity.entity_name m_->worked_.emplace (call.toUpper (), grid.left (4).toUpper (), band.toUpper (), mode.toUpper ()
, entity.continent, entity.CQ_zone, entity.ITU_zone); , entity.entity_name, entity.continent, entity.CQ_zone, entity.ITU_zone);
} }
return true; return true;
} }
@ -372,7 +453,7 @@ bool WorkedBefore::country_worked (QString const& country, QString const& mode,
return return
country.size () country.size ()
&& m_->worked_.get<entity_mode_band> ().end () && m_->worked_.get<entity_mode_band> ().end ()
!= m_->worked_.get<entity_mode_band> ().find (std::make_tuple (country, mode, band)); != m_->worked_.get<entity_mode_band> ().find (std::make_tuple (country, mode.toUpper (), band.toUpper ()));
} }
else else
{ {
@ -380,7 +461,7 @@ bool WorkedBefore::country_worked (QString const& country, QString const& mode,
return return
country.size () country.size ()
&& m_->worked_.get<entity_mode_band> ().end () && m_->worked_.get<entity_mode_band> ().end ()
!= m_->worked_.get<entity_mode_band> ().find (std::make_tuple (country, mode)); != m_->worked_.get<entity_mode_band> ().find (std::make_tuple (country, mode.toUpper ()));
} }
} }
else else
@ -390,7 +471,7 @@ bool WorkedBefore::country_worked (QString const& country, QString const& mode,
return return
country.size () country.size ()
&& m_->worked_.get<entity_band> ().end () && m_->worked_.get<entity_band> ().end ()
!= m_->worked_.get<entity_band> ().find (std::make_tuple (country, band)); != m_->worked_.get<entity_band> ().find (std::make_tuple (country, band.toUpper ()));
} }
else else
{ {
@ -410,13 +491,13 @@ bool WorkedBefore::grid_worked (QString const& grid, QString const& mode, QStrin
if (band.size ()) if (band.size ())
{ {
return m_->worked_.get<grid_mode_band> ().end () return m_->worked_.get<grid_mode_band> ().end ()
!= m_->worked_.get<grid_mode_band> ().find (std::make_tuple (grid, mode, band)); != m_->worked_.get<grid_mode_band> ().find (std::make_tuple (grid.left (4).toUpper (), mode.toUpper (), band.toUpper ()));
} }
else else
{ {
// partial key lookup // partial key lookup
return m_->worked_.get<grid_mode_band> ().end () return m_->worked_.get<grid_mode_band> ().end ()
!= m_->worked_.get<grid_mode_band> ().find (std::make_tuple (grid, mode)); != m_->worked_.get<grid_mode_band> ().find (std::make_tuple (grid.left (4).toUpper (), mode.toUpper ()));
} }
} }
else else
@ -424,13 +505,13 @@ bool WorkedBefore::grid_worked (QString const& grid, QString const& mode, QStrin
if (band.size ()) if (band.size ())
{ {
return m_->worked_.get<grid_band> ().end () return m_->worked_.get<grid_band> ().end ()
!= m_->worked_.get<grid_band> ().find (std::make_tuple (grid, band)); != m_->worked_.get<grid_band> ().find (std::make_tuple (grid.left (4).toUpper (), band.toUpper ()));
} }
else else
{ {
// partial key lookup // partial key lookup
return m_->worked_.get<grid_band> ().end () return m_->worked_.get<grid_band> ().end ()
!= m_->worked_.get<grid_band> ().find (grid); != m_->worked_.get<grid_band> ().find (grid.left (4).toUpper ());
} }
} }
} }
@ -442,13 +523,13 @@ bool WorkedBefore::call_worked (QString const& call, QString const& mode, QStrin
if (band.size ()) if (band.size ())
{ {
return m_->worked_.get<call_mode_band> ().end () return m_->worked_.get<call_mode_band> ().end ()
!= m_->worked_.get<call_mode_band> ().find (std::make_tuple (call, mode, band)); != m_->worked_.get<call_mode_band> ().find (std::make_tuple (call.toUpper (), mode.toUpper (), band.toUpper ()));
} }
else else
{ {
// partial key lookup // partial key lookup
return m_->worked_.get<call_mode_band> ().end () return m_->worked_.get<call_mode_band> ().end ()
!= m_->worked_.get<call_mode_band> ().find (std::make_tuple (call, mode)); != m_->worked_.get<call_mode_band> ().find (std::make_tuple (call.toUpper (), mode.toUpper ()));
} }
} }
else else
@ -456,13 +537,13 @@ bool WorkedBefore::call_worked (QString const& call, QString const& mode, QStrin
if (band.size ()) if (band.size ())
{ {
return m_->worked_.get<call_band> ().end () return m_->worked_.get<call_band> ().end ()
!= m_->worked_.get<call_band> ().find (std::make_tuple (call, band)); != m_->worked_.get<call_band> ().find (std::make_tuple (call.toUpper (), band.toUpper ()));
} }
else else
{ {
// partial key lookup // partial key lookup
return m_->worked_.get<call_band> ().end () return m_->worked_.get<call_band> ().end ()
!= m_->worked_.get<call_band> ().find (std::make_tuple (call)); != m_->worked_.get<call_band> ().find (std::make_tuple (call.toUpper ()));
} }
} }
} }
@ -474,13 +555,13 @@ bool WorkedBefore::continent_worked (Continent continent, QString const& mode, Q
if (band.size ()) if (band.size ())
{ {
return m_->worked_.get<continent_mode_band> ().end () return m_->worked_.get<continent_mode_band> ().end ()
!= m_->worked_.get<continent_mode_band> ().find (std::make_tuple (continent, mode, band)); != m_->worked_.get<continent_mode_band> ().find (std::make_tuple (continent, mode.toUpper (), band.toUpper ()));
} }
else else
{ {
// partial key lookup // partial key lookup
return m_->worked_.get<continent_mode_band> ().end () return m_->worked_.get<continent_mode_band> ().end ()
!= m_->worked_.get<continent_mode_band> ().find (std::make_tuple (continent, mode)); != m_->worked_.get<continent_mode_band> ().find (std::make_tuple (continent, mode.toUpper ()));
} }
} }
else else
@ -488,7 +569,7 @@ bool WorkedBefore::continent_worked (Continent continent, QString const& mode, Q
if (band.size ()) if (band.size ())
{ {
return m_->worked_.get<continent_band> ().end () return m_->worked_.get<continent_band> ().end ()
!= m_->worked_.get<continent_band> ().find (std::make_tuple (continent, band)); != m_->worked_.get<continent_band> ().find (std::make_tuple (continent, band.toUpper ()));
} }
else else
{ {
@ -506,13 +587,13 @@ bool WorkedBefore::CQ_zone_worked (int CQ_zone, QString const& mode, QString con
if (band.size ()) if (band.size ())
{ {
return m_->worked_.get<CQ_zone_mode_band> ().end () return m_->worked_.get<CQ_zone_mode_band> ().end ()
!= m_->worked_.get<CQ_zone_mode_band> ().find (std::make_tuple (CQ_zone, mode, band)); != m_->worked_.get<CQ_zone_mode_band> ().find (std::make_tuple (CQ_zone, mode.toUpper (), band.toUpper ()));
} }
else else
{ {
// partial key lookup // partial key lookup
return m_->worked_.get<CQ_zone_mode_band> ().end () return m_->worked_.get<CQ_zone_mode_band> ().end ()
!= m_->worked_.get<CQ_zone_mode_band> ().find (std::make_tuple (CQ_zone, mode)); != m_->worked_.get<CQ_zone_mode_band> ().find (std::make_tuple (CQ_zone, mode.toUpper ()));
} }
} }
else else
@ -520,7 +601,7 @@ bool WorkedBefore::CQ_zone_worked (int CQ_zone, QString const& mode, QString con
if (band.size ()) if (band.size ())
{ {
return m_->worked_.get<CQ_zone_band> ().end () return m_->worked_.get<CQ_zone_band> ().end ()
!= m_->worked_.get<CQ_zone_band> ().find (std::make_tuple (CQ_zone, band)); != m_->worked_.get<CQ_zone_band> ().find (std::make_tuple (CQ_zone, band.toUpper ()));
} }
else else
{ {
@ -538,13 +619,13 @@ bool WorkedBefore::ITU_zone_worked (int ITU_zone, QString const& mode, QString c
if (band.size ()) if (band.size ())
{ {
return m_->worked_.get<ITU_zone_mode_band> ().end () return m_->worked_.get<ITU_zone_mode_band> ().end ()
!= m_->worked_.get<ITU_zone_mode_band> ().find (std::make_tuple (ITU_zone, mode, band)); != m_->worked_.get<ITU_zone_mode_band> ().find (std::make_tuple (ITU_zone, mode.toUpper (), band.toUpper ()));
} }
else else
{ {
// partial key lookup // partial key lookup
return m_->worked_.get<ITU_zone_mode_band> ().end () return m_->worked_.get<ITU_zone_mode_band> ().end ()
!= m_->worked_.get<ITU_zone_mode_band> ().find (std::make_tuple (ITU_zone, mode)); != m_->worked_.get<ITU_zone_mode_band> ().find (std::make_tuple (ITU_zone, mode.toUpper ()));
} }
} }
else else
@ -552,7 +633,7 @@ bool WorkedBefore::ITU_zone_worked (int ITU_zone, QString const& mode, QString c
if (band.size ()) if (band.size ())
{ {
return m_->worked_.get<ITU_zone_band> ().end () return m_->worked_.get<ITU_zone_band> ().end ()
!= m_->worked_.get<ITU_zone_band> ().find (std::make_tuple (ITU_zone, band)); != m_->worked_.get<ITU_zone_band> ().find (std::make_tuple (ITU_zone, band.toUpper ()));
} }
else else
{ {

View File

@ -1,7 +1,7 @@
#ifndef WORKWED_BEFORE_HPP_ #ifndef WORKWED_BEFORE_HPP_
#define WORKWED_BEFORE_HPP_ #define WORKWED_BEFORE_HPP_
#include <boost/core/noncopyable.hpp> #include <QObject>
#include "AD1CCty.hpp" #include "AD1CCty.hpp"
#include "pimpl_h.hpp" #include "pimpl_h.hpp"
@ -10,21 +10,25 @@ class QString;
class QByteArray; class QByteArray;
class WorkedBefore final class WorkedBefore final
: private boost::noncopyable : public QObject
{ {
Q_OBJECT
public: public:
using Continent = AD1CCty::Continent; using Continent = AD1CCty::Continent;
explicit WorkedBefore (); explicit WorkedBefore ();
~WorkedBefore (); ~WorkedBefore ();
Q_SLOT void reload ();
Q_SLOT bool add (QString const& call
, QString const& grid
, QString const& band
, QString const& mode
, QByteArray const& ADIF_record);
QString const& path () const; QString const& path () const;
AD1CCty const& countries () const; AD1CCty const& countries () const;
bool add (QString const& call
, QString const& grid
, QString const& band
, QString const& mode
, QByteArray const& ADIF_record);
bool country_worked (QString const& call, QString const& mode, QString const& band) const; bool country_worked (QString const& call, QString const& mode, QString const& band) const;
bool grid_worked (QString const& grid, QString const& mode, QString const& band) const; bool grid_worked (QString const& grid, QString const& mode, QString const& band) const;
bool call_worked (QString const& call, QString const& mode, QString const& band) const; bool call_worked (QString const& call, QString const& mode, QString const& band) const;
@ -32,6 +36,8 @@ public:
bool CQ_zone_worked (int CQ_zone, QString const& mode, QString const& band) const; bool CQ_zone_worked (int CQ_zone, QString const& mode, QString const& band) const;
bool ITU_zone_worked (int ITU_zone, QString const& mode, QString const& band) const; bool ITU_zone_worked (int ITU_zone, QString const& mode, QString const& band) const;
Q_SIGNAL void finished_loading (int worked_before_record_count, QString const& error) const;
private: private:
class impl; class impl;
pimpl<impl> m_; pimpl<impl> m_;

View File

@ -1,13 +1,15 @@
#include "logbook.h" #include "logbook.h"
#include <QDateTime> #include <QDateTime>
#include <QDebug>
#include "Configuration.hpp" #include "Configuration.hpp"
#include "AD1CCty.hpp" #include "AD1CCty.hpp"
#include "moc_logbook.cpp"
LogBook::LogBook (Configuration const * configuration) LogBook::LogBook (Configuration const * configuration)
: config_ {configuration} : config_ {configuration}
{ {
connect (&worked_before_, &WorkedBefore::finished_loading, this, &LogBook::finished_loading);
} }
void LogBook::match (QString const& call, QString const& mode, QString const& grid, void LogBook::match (QString const& call, QString const& mode, QString const& grid,
@ -52,6 +54,11 @@ bool LogBook::add (QString const& call
return worked_before_.add (call, grid, band, mode, ADIF_record); return worked_before_.add (call, grid, band, mode, ADIF_record);
} }
void LogBook::rescan ()
{
worked_before_.reload ();
}
QByteArray LogBook::QSOToADIF (QString const& hisCall, QString const& hisGrid, QString const& mode, QByteArray LogBook::QSOToADIF (QString const& hisCall, QString const& hisGrid, QString const& mode,
QString const& rptSent, QString const& rptRcvd, QDateTime const& dateTimeOn, QString const& rptSent, QString const& rptRcvd, QDateTime const& dateTimeOn,
QDateTime const& dateTimeOff, QString const& band, QString const& comments, QDateTime const& dateTimeOff, QString const& band, QString const& comments,

View File

@ -1,12 +1,12 @@
// -*- Mode: C++ -*-
/* /*
* From an ADIF file and cty.dat, get a call's DXCC entity and its worked before status * From an ADIF file and cty.dat, get a call's DXCC entity and its worked before status
* VK3ACF July 2013
*/ */
#ifndef LOG_BOOK_H_ #ifndef LOG_BOOK_H_
#define LOG_BOOK_H_ #define LOG_BOOK_H_
#include <boost/core/noncopyable.hpp> #include <QObject>
#include <QString> #include <QString>
#include "WorkedBefore.hpp" #include "WorkedBefore.hpp"
@ -16,9 +16,11 @@ class QByteArray;
class QDateTime; class QDateTime;
class LogBook final class LogBook final
: private boost::noncopyable : public QObject
{ {
public: Q_OBJECT
public:
LogBook (Configuration const *); LogBook (Configuration const *);
QString const& path () const {return worked_before_.path ();} QString const& path () const {return worked_before_.path ();}
bool add (QString const& call bool add (QString const& call
@ -27,6 +29,7 @@ class LogBook final
, QString const& mode , QString const& mode
, QByteArray const& ADIF_record); , QByteArray const& ADIF_record);
AD1CCty const& countries () const {return worked_before_.countries ();} AD1CCty const& countries () const {return worked_before_.countries ();}
void rescan ();
void match (QString const& call, QString const& mode, QString const& grid, void match (QString const& call, QString const& mode, QString const& grid,
AD1CCty::Record const&, bool& callB4, bool& countryB4, AD1CCty::Record const&, bool& callB4, bool& countryB4,
bool &gridB4, bool &continentB4, bool& CQZoneB4, bool& ITUZoneB4, bool &gridB4, bool &continentB4, bool& CQZoneB4, bool& ITUZoneB4,
@ -38,7 +41,9 @@ class LogBook final
QString const& m_myGrid, QString const& m_txPower, QString const& operator_call, QString const& m_myGrid, QString const& m_txPower, QString const& operator_call,
QString const& xSent, QString const& xRcvd); QString const& xSent, QString const& xRcvd);
private: Q_SIGNAL void finished_loading (int worked_before_record_count, QString const& error) const;
private:
Configuration const * config_; Configuration const * config_;
WorkedBefore worked_before_; WorkedBefore worked_before_;
}; };

View File

@ -6,6 +6,8 @@
#include <locale.h> #include <locale.h>
#include <fftw3.h> #include <fftw3.h>
#include <QSharedMemory>
#include <QTemporaryFile>
#include <QDateTime> #include <QDateTime>
#include <QApplication> #include <QApplication>
#include <QRegularExpression> #include <QRegularExpression>
@ -21,6 +23,7 @@
#include <QCommandLineParser> #include <QCommandLineParser>
#include <QCommandLineOption> #include <QCommandLineOption>
#include <QSqlDatabase> #include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError> #include <QSqlError>
#include "revision_utils.hpp" #include "revision_utils.hpp"
@ -288,6 +291,12 @@ int main(int argc, char *argv[])
throw std::runtime_error {("Database Error: " + db.lastError ().text ()).toStdString ()}; throw std::runtime_error {("Database Error: " + db.lastError ().text ()).toStdString ()};
} }
// better performance traded for a risk of d/b corruption
// on system crash or application crash
// db.exec ("PRAGMA synchronous=OFF"); // system crash risk
// db.exec ("PRAGMA journal_mode=MEMORY"); // application crash risk
db.exec ("PRAGMA locking_mode=EXCLUSIVE");
int result; int result;
do do
{ {

View File

@ -10,7 +10,6 @@
#include <QSqlError> #include <QSqlError>
#include <QSqlQuery> #include <QSqlQuery>
#include <QDataStream> #include <QDataStream>
#include <QDebug>
#include "Configuration.hpp" #include "Configuration.hpp"
#include "Bands.hpp" #include "Bands.hpp"
#include "qt_db_helpers.hpp" #include "qt_db_helpers.hpp"
@ -52,7 +51,7 @@ CabrilloLog::impl::impl (Configuration const * configuration)
SQL_error_check (export_query_, &QSqlQuery::prepare, SQL_error_check (export_query_, &QSqlQuery::prepare,
"SELECT frequency, \"when\", exchange_sent, call, exchange_rcvd FROM cabrillo_log ORDER BY \"when\""); "SELECT frequency, \"when\", exchange_sent, call, exchange_rcvd FROM cabrillo_log ORDER BY \"when\"");
setEditStrategy (QSqlTableModel::OnRowChange); setEditStrategy (QSqlTableModel::OnFieldChange);
setTable ("cabrillo_log"); setTable ("cabrillo_log");
setHeaderData (fieldIndex ("frequency"), Qt::Horizontal, tr ("Freq(kHz)")); setHeaderData (fieldIndex ("frequency"), Qt::Horizontal, tr ("Freq(kHz)"));
setHeaderData (fieldIndex ("when"), Qt::Horizontal, tr ("Date & Time(UTC)")); setHeaderData (fieldIndex ("when"), Qt::Horizontal, tr ("Date & Time(UTC)"));
@ -60,6 +59,12 @@ CabrilloLog::impl::impl (Configuration const * configuration)
setHeaderData (fieldIndex ("exchange_sent"), Qt::Horizontal, tr ("Sent")); setHeaderData (fieldIndex ("exchange_sent"), Qt::Horizontal, tr ("Sent"));
setHeaderData (fieldIndex ("exchange_rcvd"), Qt::Horizontal, tr ("Rcvd")); setHeaderData (fieldIndex ("exchange_rcvd"), Qt::Horizontal, tr ("Rcvd"));
setHeaderData (fieldIndex ("band"), Qt::Horizontal, tr ("Band")); setHeaderData (fieldIndex ("band"), Qt::Horizontal, tr ("Band"));
// This descending order by time is important, it makes the view
// place the latest row at the top, without this the model/view
// interactions are both sluggish and unhelpful.
setSort (fieldIndex ("when"), Qt::DescendingOrder);
SQL_error_check (*this, &QSqlTableModel::select); SQL_error_check (*this, &QSqlTableModel::select);
} }
@ -110,11 +115,15 @@ bool CabrilloLog::add_QSO (Frequency frequency, QDateTime const& when, QString c
set_value_maybe_null (record, "exchange_sent", exchange_sent); set_value_maybe_null (record, "exchange_sent", exchange_sent);
set_value_maybe_null (record, "exchange_rcvd", exchange_received); set_value_maybe_null (record, "exchange_rcvd", exchange_received);
set_value_maybe_null (record, "band", m_->configuration_->bands ()->find (frequency)); set_value_maybe_null (record, "band", m_->configuration_->bands ()->find (frequency));
auto ok = m_->insertRecord (-1, record); if (m_->isDirty ())
if (ok)
{ {
m_->select (); // to refresh views m_->revert (); // discard any uncommitted changes
} }
m_->setEditStrategy (QSqlTableModel::OnManualSubmit);
ConditionalTransaction transaction {*m_};
auto ok = m_->insertRecord (-1, record);
transaction.submit ();
m_->setEditStrategy (QSqlTableModel::OnFieldChange);
return ok; return ok;
} }
@ -136,7 +145,7 @@ void CabrilloLog::reset ()
SQL_error_check (*m_, &QSqlTableModel::removeRows, 0, m_->rowCount (), QModelIndex {}); SQL_error_check (*m_, &QSqlTableModel::removeRows, 0, m_->rowCount (), QModelIndex {});
transaction.submit (); transaction.submit ();
m_->select (); // to refresh views m_->select (); // to refresh views
m_->setEditStrategy (QSqlTableModel::OnRowChange); m_->setEditStrategy (QSqlTableModel::OnFieldChange);
} }
} }

View File

@ -4,7 +4,8 @@
#include <QVariant> #include <QVariant>
#include <QList> #include <QList>
#include <QBrush> #include <QBrush>
#include <QFont> #include <QColor>
#include <QFont>
#include <QMap> #include <QMap>
#include <QVector> #include <QVector>
#include <QDataStream> #include <QDataStream>
@ -160,7 +161,10 @@ QVariant DecodeHighlightingModel::data (const QModelIndex& index, int role) cons
result = item.enabled_ ? Qt::Checked : Qt::Unchecked; result = item.enabled_ ? Qt::Checked : Qt::Unchecked;
break; break;
case Qt::DisplayRole: case Qt::DisplayRole:
result = highlight_name (item.type_); return QString {"%1 [f/g:%2, b/g:%3]"}
.arg (highlight_name (item.type_))
.arg (item.foreground_.style () != Qt::NoBrush ? QString {"#%1"}.arg (item.foreground_.color ().rgb () & 0xffffff, 6, 16, QChar {'0'}) : QString {"unset"})
.arg (item.background_.style () != Qt::NoBrush ? QString {"#%1"}.arg (item.background_.color ().rgb () & 0xffffff, 6, 16, QChar {'0'}) : QString {"unset"});
break; break;
case Qt::ForegroundRole: case Qt::ForegroundRole:
if (Qt::NoBrush != item.foreground_.style ()) if (Qt::NoBrush != item.foreground_.style ())

View File

@ -43,7 +43,7 @@ FoxLog::impl::impl ()
SQL_error_check (dupe_query_, &QSqlQuery::prepare, SQL_error_check (dupe_query_, &QSqlQuery::prepare,
"SELECT COUNT(*) FROM fox_log WHERE call = :call AND band = :band"); "SELECT COUNT(*) FROM fox_log WHERE call = :call AND band = :band");
setEditStrategy (QSqlTableModel::OnRowChange); setEditStrategy (QSqlTableModel::OnFieldChange);
setTable ("fox_log"); setTable ("fox_log");
setHeaderData (fieldIndex ("when"), Qt::Horizontal, tr ("Date & Time(UTC)")); setHeaderData (fieldIndex ("when"), Qt::Horizontal, tr ("Date & Time(UTC)"));
setHeaderData (fieldIndex ("call"), Qt::Horizontal, tr ("Call")); setHeaderData (fieldIndex ("call"), Qt::Horizontal, tr ("Call"));
@ -51,6 +51,12 @@ FoxLog::impl::impl ()
setHeaderData (fieldIndex ("report_sent"), Qt::Horizontal, tr ("Sent")); setHeaderData (fieldIndex ("report_sent"), Qt::Horizontal, tr ("Sent"));
setHeaderData (fieldIndex ("report_rcvd"), Qt::Horizontal, tr ("Rcvd")); setHeaderData (fieldIndex ("report_rcvd"), Qt::Horizontal, tr ("Rcvd"));
setHeaderData (fieldIndex ("band"), Qt::Horizontal, tr ("Band")); setHeaderData (fieldIndex ("band"), Qt::Horizontal, tr ("Band"));
// This descending order by time is important, it makes the view
// place the latest row at the top, without this the model/view
// interactions are both sluggish and unhelpful.
setSort (fieldIndex ("when"), Qt::DescendingOrder);
SQL_error_check (*this, &QSqlTableModel::select); SQL_error_check (*this, &QSqlTableModel::select);
} }
@ -100,11 +106,18 @@ bool FoxLog::add_QSO (QDateTime const& when, QString const& call, QString const&
set_value_maybe_null (record, "report_sent", report_sent); set_value_maybe_null (record, "report_sent", report_sent);
set_value_maybe_null (record, "report_rcvd", report_received); set_value_maybe_null (record, "report_rcvd", report_received);
set_value_maybe_null (record, "band", band); set_value_maybe_null (record, "band", band);
if (m_->isDirty ())
{
m_->revert (); // discard any uncommitted changes
}
m_->setEditStrategy (QSqlTableModel::OnManualSubmit);
ConditionalTransaction transaction {*m_};
auto ok = m_->insertRecord (-1, record); auto ok = m_->insertRecord (-1, record);
if (ok) if (ok)
{ {
m_->select (); // to refresh views ok = transaction.submit (false);
} }
m_->setEditStrategy (QSqlTableModel::OnFieldChange);
return ok; return ok;
} }
@ -126,6 +139,6 @@ void FoxLog::reset ()
SQL_error_check (*m_, &QSqlTableModel::removeRows, 0, m_->rowCount (), QModelIndex {}); SQL_error_check (*m_, &QSqlTableModel::removeRows, 0, m_->rowCount (), QModelIndex {});
transaction.submit (); transaction.submit ();
m_->select (); // to refresh views m_->select (); // to refresh views
m_->setEditStrategy (QSqlTableModel::OnRowChange); m_->setEditStrategy (QSqlTableModel::OnFieldChange);
} }
} }

View File

@ -84,10 +84,23 @@ AbstractLogWindow::AbstractLogWindow (QString const& settings_key, QSettings * s
: QWidget {parent} : QWidget {parent}
, m_ {this, settings_key, settings, configuration} , m_ {this, settings_key, settings, configuration}
{ {
// ensure view scrolls to latest new row // this attempt to scroll to the last new record doesn't work, some
connect (&m_->model_, &QAbstractItemModel::rowsInserted, [this] (QModelIndex const& /*parent*/, int /*first*/, int /*last*/) { // sort of issue with model indexes and optimized DB fetches. For
if (m_->log_view_) m_->log_view_->scrollToBottom (); // now sorting by the same column and direction as the underlying DB
}); // select and that DB select being in descending order so new rows
// at the end appear at view row 0 gets the job done
// // ensure view scrolls to latest new row
// connect (&m_->model_, &QAbstractItemModel::rowsInserted, this, [this] (QModelIndex const& parent, int first, int last) {
// // note col 0 is hidden so use col 1
// // queued connection required otherwise row may not be available
// // in time
// auto index = m_->model_.index (last, 1, parent);
// if (m_->log_view_)
// {
// m_->log_view_->scrollTo (index);
// }
// }, Qt::QueuedConnection);
} }
AbstractLogWindow::~AbstractLogWindow () AbstractLogWindow::~AbstractLogWindow ()
@ -102,23 +115,27 @@ void AbstractLogWindow::set_log_view (QTableView * log_view)
SettingsGroup g {m_->settings_, m_->settings_key_}; SettingsGroup g {m_->settings_, m_->settings_key_};
restoreGeometry (m_->settings_->value ("window/geometry").toByteArray ()); restoreGeometry (m_->settings_->value ("window/geometry").toByteArray ());
m_->log_view_ = log_view; m_->log_view_ = log_view;
m_->log_view_->setContextMenuPolicy (Qt::ActionsContextMenu); set_log_view_font (m_->configuration_->decoded_text_font ());
m_->log_view_->setAlternatingRowColors (true); log_view->setSortingEnabled (true);
m_->log_view_->setSelectionBehavior (QAbstractItemView::SelectRows); log_view->setContextMenuPolicy (Qt::ActionsContextMenu);
m_->log_view_->setSelectionMode (QAbstractItemView::ExtendedSelection); log_view->setAlternatingRowColors (true);
m_->model_.setSourceModel (m_->log_view_->model ()); log_view->setSelectionBehavior (QAbstractItemView::SelectRows);
m_->log_view_->setModel (&m_->model_); log_view->setSelectionMode (QAbstractItemView::ExtendedSelection);
m_->log_view_->setColumnHidden (0, true); log_view->setVerticalScrollMode (QAbstractItemView::ScrollPerPixel);
m_->model_.setSourceModel (log_view->model ());
log_view->setModel (&m_->model_);
log_view->setColumnHidden (0, true);
auto horizontal_header = log_view->horizontalHeader (); auto horizontal_header = log_view->horizontalHeader ();
horizontal_header->setResizeContentsPrecision (0); // visible region only
horizontal_header->setSectionResizeMode (QHeaderView::ResizeToContents); horizontal_header->setSectionResizeMode (QHeaderView::ResizeToContents);
horizontal_header->setSectionsMovable (true); horizontal_header->setSectionsMovable (true);
m_->log_view_->verticalHeader ()->setSectionResizeMode (QHeaderView::ResizeToContents); auto vertical_header = log_view->horizontalHeader ();
set_log_view_font (m_->configuration_->decoded_text_font ()); vertical_header->setResizeContentsPrecision (0); // visible region only
m_->log_view_->scrollToBottom (); vertical_header->setSectionResizeMode (QHeaderView::ResizeToContents);
// actions // actions
auto delete_action = new QAction {tr ("&Delete ..."), m_->log_view_}; auto delete_action = new QAction {tr ("&Delete ..."), log_view};
m_->log_view_->insertAction (nullptr, delete_action); log_view->insertAction (nullptr, delete_action);
connect (delete_action, &QAction::triggered, [this] (bool /*checked*/) { connect (delete_action, &QAction::triggered, [this] (bool /*checked*/) {
m_->delete_QSOs (); m_->delete_QSOs ();
}); });
@ -126,8 +143,8 @@ void AbstractLogWindow::set_log_view (QTableView * log_view)
void AbstractLogWindow::set_log_view_font (QFont const& font) void AbstractLogWindow::set_log_view_font (QFont const& font)
{ {
// m_->log_view_->setFont (font); m_->log_view_->setFont (font);
// m_->log_view_->horizontalHeader ()->setFont (font); m_->log_view_->horizontalHeader ()->setFont (font);
// m_->log_view_->verticalHeader ()->setFont (font); m_->log_view_->verticalHeader ()->setFont (font);
m_->model_.set_font (font); m_->model_.set_font (font);
} }

View File

@ -66,8 +66,9 @@ CabrilloLogWindow::CabrilloLogWindow (QSettings * settings, Configuration const
set_log_view (m_->ui_.log_table_view); set_log_view (m_->ui_.log_table_view);
m_->ui_.log_table_view->setItemDelegateForColumn (2, new DateTimeAsSecsSinceEpochDelegate {this}); m_->ui_.log_table_view->setItemDelegateForColumn (2, new DateTimeAsSecsSinceEpochDelegate {this});
m_->ui_.log_table_view->setItemDelegateForColumn (3, new CallsignDelegate {this}); m_->ui_.log_table_view->setItemDelegateForColumn (3, new CallsignDelegate {this});
m_->ui_.log_table_view->setItemDelegateForColumn (6, new ForeignKeyDelegate {configuration->bands (), m_->log_model_, 0, 6, this}); m_->ui_.log_table_view->setItemDelegateForColumn (6, new ForeignKeyDelegate {configuration->bands (), 0, this});
m_->ui_.log_table_view->horizontalHeader ()->moveSection (6, 1); // band to first column auto h_header = m_->ui_.log_table_view->horizontalHeader ();
h_header->moveSection (6, 1); // band to first column
} }
CabrilloLogWindow::~CabrilloLogWindow () CabrilloLogWindow::~CabrilloLogWindow ()

View File

@ -6,31 +6,12 @@
#include "models/DecodeHighlightingModel.hpp" #include "models/DecodeHighlightingModel.hpp"
#include "MessageBox.hpp" #include "MessageBox.hpp"
#include "pimpl_impl.hpp"
class DecodeHighlightingListView::impl final
{
public:
impl ()
: fg_colour_action_ {tr ("&Foreground color ..."), nullptr}
, bg_colour_action_ {tr ("&Background color ..."), nullptr}
, defaults_action_ {tr ("&Reset this item to defaults"), nullptr}
{
}
DecodeHighlightingListView * self_;
QAction fg_colour_action_;
QAction bg_colour_action_;
QAction defaults_action_;
};
DecodeHighlightingListView::DecodeHighlightingListView (QWidget * parent) DecodeHighlightingListView::DecodeHighlightingListView (QWidget * parent)
: QListView {parent} : QListView {parent}
{ {
addAction (&m_->fg_colour_action_); auto * fg_colour_action = new QAction {tr ("&Foreground color ..."), this};
addAction (&m_->bg_colour_action_); addAction (fg_colour_action);
addAction (&m_->defaults_action_); connect (fg_colour_action, &QAction::triggered, [this] (bool /*checked*/) {
connect (&m_->fg_colour_action_, &QAction::triggered, [this] (bool /*checked*/) {
auto const& index = currentIndex (); auto const& index = currentIndex ();
auto colour = QColorDialog::getColor (model ()->data (index, Qt::ForegroundRole).value<QBrush> ().color () auto colour = QColorDialog::getColor (model ()->data (index, Qt::ForegroundRole).value<QBrush> ().color ()
, this , this
@ -38,10 +19,19 @@ DecodeHighlightingListView::DecodeHighlightingListView (QWidget * parent)
.arg (model ()->data (index).toString ())); .arg (model ()->data (index).toString ()));
if (colour.isValid ()) if (colour.isValid ())
{ {
model ()->setData (index, colour, Qt::ForegroundRole); model ()->setData (index, QBrush {colour}, Qt::ForegroundRole);
} }
}); });
connect (&m_->bg_colour_action_, &QAction::triggered, [this] (bool /*checked*/) {
auto * unset_fg_colour_action = new QAction {tr ("&Unset foreground color"), this};
addAction (unset_fg_colour_action);
connect (unset_fg_colour_action, &QAction::triggered, [this] (bool /*checked*/) {
model ()->setData (currentIndex (), QBrush {}, Qt::ForegroundRole);
});
auto * bg_colour_action = new QAction {tr ("&Background color ..."), this};
addAction (bg_colour_action);
connect (bg_colour_action, &QAction::triggered, [this] (bool /*checked*/) {
auto const& index = currentIndex (); auto const& index = currentIndex ();
auto colour = QColorDialog::getColor (model ()->data (index, Qt::BackgroundRole).value<QBrush> ().color () auto colour = QColorDialog::getColor (model ()->data (index, Qt::BackgroundRole).value<QBrush> ().color ()
, this , this
@ -49,10 +39,19 @@ DecodeHighlightingListView::DecodeHighlightingListView (QWidget * parent)
.arg (model ()->data (index).toString ())); .arg (model ()->data (index).toString ()));
if (colour.isValid ()) if (colour.isValid ())
{ {
model ()->setData (index, colour, Qt::BackgroundRole); model ()->setData (index, QBrush {colour}, Qt::BackgroundRole);
} }
}); });
connect (&m_->defaults_action_, &QAction::triggered, [this] (bool /*checked*/) {
auto * unset_bg_colour_action = new QAction {tr ("U&nset background color"), this};
addAction (unset_bg_colour_action);
connect (unset_bg_colour_action, &QAction::triggered, [this] (bool /*checked*/) {
model ()->setData (currentIndex (), QBrush {}, Qt::BackgroundRole);
});
auto * defaults_action = new QAction {tr ("&Reset this item to defaults"), this};
addAction (defaults_action);
connect (defaults_action, &QAction::triggered, [this] (bool /*checked*/) {
auto const& index = currentIndex (); auto const& index = currentIndex ();
model ()->setData (index, model ()->data (index, DecodeHighlightingModel::EnabledDefaultRole).toBool () ? Qt::Checked : Qt::Unchecked, Qt::CheckStateRole); model ()->setData (index, model ()->data (index, DecodeHighlightingModel::EnabledDefaultRole).toBool () ? Qt::Checked : Qt::Unchecked, Qt::CheckStateRole);
model ()->setData (index, model ()->data (index, DecodeHighlightingModel::ForegroundDefaultRole), Qt::ForegroundRole); model ()->setData (index, model ()->data (index, DecodeHighlightingModel::ForegroundDefaultRole), Qt::ForegroundRole);
@ -60,10 +59,6 @@ DecodeHighlightingListView::DecodeHighlightingListView (QWidget * parent)
}); });
} }
DecodeHighlightingListView::~DecodeHighlightingListView ()
{
}
QSize DecodeHighlightingListView::sizeHint () const QSize DecodeHighlightingListView::sizeHint () const
{ {
auto item_height = sizeHintForRow (0); auto item_height = sizeHintForRow (0);

View File

@ -3,8 +3,6 @@
#include <QListView> #include <QListView>
#include "pimpl_h.hpp"
class QWidget; class QWidget;
// Class Decode Highlighting List View // Class Decode Highlighting List View
@ -20,13 +18,9 @@ class DecodeHighlightingListView final
{ {
public: public:
explicit DecodeHighlightingListView (QWidget * parent = nullptr); explicit DecodeHighlightingListView (QWidget * parent = nullptr);
~DecodeHighlightingListView ();
private: private:
QSize sizeHint () const override; QSize sizeHint () const override;
class impl;
pimpl<impl> m_;
}; };
#endif #endif

View File

@ -43,7 +43,7 @@ FoxLogWindow::FoxLogWindow (QSettings * settings, Configuration const * configur
m_->ui_.log_table_view->setItemDelegateForColumn (1, new DateTimeAsSecsSinceEpochDelegate {this}); m_->ui_.log_table_view->setItemDelegateForColumn (1, new DateTimeAsSecsSinceEpochDelegate {this});
m_->ui_.log_table_view->setItemDelegateForColumn (2, new CallsignDelegate {this}); m_->ui_.log_table_view->setItemDelegateForColumn (2, new CallsignDelegate {this});
m_->ui_.log_table_view->setItemDelegateForColumn (3, new MaidenheadLocatorDelegate {this}); m_->ui_.log_table_view->setItemDelegateForColumn (3, new MaidenheadLocatorDelegate {this});
m_->ui_.log_table_view->setItemDelegateForColumn (6, new ForeignKeyDelegate {configuration->bands (), m_->log_model_, 0, 6, this}); m_->ui_.log_table_view->setItemDelegateForColumn (6, new ForeignKeyDelegate {configuration->bands (), 0, this});
m_->ui_.log_table_view->horizontalHeader ()->moveSection (6, 1); // move band to first column m_->ui_.log_table_view->horizontalHeader ()->moveSection (6, 1); // move band to first column
m_->ui_.rate_label->setNum (0); m_->ui_.rate_label->setNum (0);
m_->ui_.queued_label->setNum (0); m_->ui_.queued_label->setNum (0);

Some files were not shown because too many files have changed in this diff Show More