Merge branch 'hotfix-2.0.0-rc6'

This commit is contained in:
Bill Somerville 2018-12-09 20:12:41 +00:00
commit 7dd0dc9319
118 changed files with 2320 additions and 2536 deletions

View File

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

View File

@ -182,6 +182,7 @@
#include "validators/CallsignValidator.hpp"
#include "LotWUsers.hpp"
#include "models/DecodeHighlightingModel.hpp"
#include "logbook/logbook.h"
#include "ui_Configuration.h"
#include "moc_Configuration.cpp"
@ -199,16 +200,18 @@ namespace
QRegularExpression RTTY_roundup_exchange_re {
R"(
(
AL|AK|AZ|AR|CA|CO|CT|DE|FL|GA # states
|HI|ID|IL|IN|IA|KS|KY|LA|ME|MD
AL|AZ|AR|CA|CO|CT|DE|FL|GA # 48 contiguous states
|ID|IL|IN|IA|KS|KY|LA|ME|MD
|MA|MI|MN|MS|MO|MT|NE|NV|NH|NJ
|NM|NY|NC|ND|OH|OK|OR|PA|RI|SC
|SD|TN|TX|UT|VT|VA|WA|WV|WI|WY
|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
)
)", QRegularExpression::CaseInsensitiveOption | QRegularExpression::ExtendedPatternSyntaxOption};
QRegularExpression field_day_exchange_re {
R"(
(
@ -216,7 +219,7 @@ namespace
|[0-2]\d
|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
|EMA|ENY|EPA|EWA|GA|GTA|IA|ID
@ -395,6 +398,7 @@ public:
, QNetworkAccessManager * network_manager
, QDir const& temp_directory
, QSettings * settings
, LogBook * logbook
, QWidget * parent);
~impl ();
@ -480,11 +484,14 @@ private:
Q_SLOT void handle_transceiver_update (TransceiverState const&, unsigned sequence_number);
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_rescan_log_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_cbx4ToneSpacing_clicked(bool);
Q_SLOT void on_prompt_to_log_check_box_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 :(
Q_SIGNAL void start_transceiver (unsigned seqeunce_number) const;
@ -502,6 +509,7 @@ private:
QNetworkAccessManager * network_manager_;
QSettings * settings_;
LogBook * logbook_;
QDir doc_dir_;
QDir data_dir_;
@ -638,8 +646,8 @@ private:
// delegate to implementation class
Configuration::Configuration (QNetworkAccessManager * network_manager, QDir const& temp_directory,
QSettings * settings, QWidget * parent)
: m_ {this, network_manager, temp_directory, settings, parent}
QSettings * settings, LogBook * logbook, QWidget * parent)
: m_ {this, network_manager, temp_directory, settings, logbook, parent}
{
}
@ -905,13 +913,15 @@ namespace
}
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}
, self_ {self}
, transceiver_thread_ {nullptr}
, ui_ {new Ui::configuration_dialog}
, network_manager_ {network_manager}
, settings_ {settings}
, logbook_ {logbook}
, doc_dir_ {doc_path ()}
, data_dir_ {data_path ()}
, temp_dir_ {temp_directory}
@ -1005,8 +1015,8 @@ Configuration::impl::impl (Configuration * self, QNetworkAccessManager * network
ui_->callsign_line_edit->setValidator (new CallsignValidator {this});
ui_->grid_line_edit->setValidator (new MaidenheadLocatorValidator {this});
ui_->add_macro_line_edit->setValidator (new QRegularExpressionValidator {message_alphabet, this});
ui_->Field_Day_Exchange->setValidator(new QRegularExpressionValidator {field_day_exchange_re});
ui_->RTTY_Exchange->setValidator(new QRegularExpressionValidator {RTTY_roundup_exchange_re});
ui_->Field_Day_Exchange->setValidator (new QRegularExpressionValidator {field_day_exchange_re, this});
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->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> ());
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 ();
LotW_days_since_upload_ = settings_->value ("LotWDaysSinceLastUpload", 365).toInt ();
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*/)
{
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);
}
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 ()
{
if (!open_rig ())

View File

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

View File

@ -16,9 +16,6 @@
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QTabWidget" name="configuration_tabs">
<property name="toolTip">
<string>Select tab to change configuration parameters.</string>
</property>
<property name="currentIndex">
<number>0</number>
</property>
@ -2197,7 +2194,7 @@ Right click for insert and delete options.</string>
<bool>true</bool>
</property>
<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 name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContents</enum>
@ -2233,8 +2230,8 @@ Right click for insert and delete options.</string>
</widget>
</item>
<item>
<layout class="QGridLayout" name="gridLayout_5">
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_15">
<item>
<widget class="QCheckBox" name="highlight_by_mode_check_box">
<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>
@ -2244,6 +2241,29 @@ Right click for insert and delete options.</string>
</property>
</widget>
</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>
</item>
</layout>
@ -2436,7 +2456,140 @@ Right click for insert and delete options.</string>
<property name="checked">
<bool>false</bool>
</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">
<spacer name="horizontalSpacer_11">
<property name="orientation">
@ -2483,7 +2636,7 @@ Right click for insert and delete options.</string>
<item row="0" column="0">
<widget class="QLabel" name="labFD">
<property name="text">
<string>Exch:</string>
<string>FD Exch:</string>
</property>
<property name="buddy">
<cstring>Field_Day_Exchange</cstring>
@ -2513,152 +2666,6 @@ Right click for insert and delete options.</string>
</item>
</layout>
</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>
</widget>
</item>
@ -2924,7 +2931,6 @@ Right click for insert and delete options.</string>
<tabstop>stations_table_view</tabstop>
<tabstop>highlighting_list_view</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_fetch_push_button</tabstop>
<tabstop>LotW_days_since_upload_spin_box</tabstop>
@ -3012,13 +3018,13 @@ Right click for insert and delete options.</string>
</connection>
</connections>
<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="special_op_activity_button_group"/>
<buttongroup name="PTT_method_button_group"/>
<buttongroup name="split_mode_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>
</ui>

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
, QString const& de_grid, QString const& dx_grid
, 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 ())
{
@ -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 ()
<< tx_enabled << transmitting << decoding << rx_df << tx_df << de_call.toUtf8 ()
<< de_grid.toUtf8 () << dx_grid.toUtf8 () << watchdog_timeout << sub_mode.toUtf8 ()
<< fast_mode;
<< fast_mode << special_op_mode;
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& comments, QString const& name, QDateTime time_on
, 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 ())
{
@ -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_};
out << time_off << dx_call.toUtf8 () << dx_grid.toUtf8 () << dial_frequency << mode.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);
}
}

View File

@ -52,7 +52,7 @@ public:
, 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
, 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
, QString const& mode, QString const& message, bool low_confidence
, bool off_air);
@ -64,7 +64,8 @@ public:
, Frequency dial_frequency, QString const& mode, QString const& report_sent
, QString const& report_received, QString const& tx_power, QString const& comments
, 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
// of record marker

View File

@ -216,9 +216,10 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s
bool watchdog_timeout {false};
QByteArray sub_mode;
bool fast_mode {false};
quint8 special_op_mode {0};
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
>> fast_mode;
>> fast_mode >> special_op_mode;
if (check_status (in) != Fail)
{
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
, QString::fromUtf8 (de_call), QString::fromUtf8 (de_grid)
, QString::fromUtf8 (dx_grid), watchdog_timeout
, QString::fromUtf8 (sub_mode), fast_mode);
, QString::fromUtf8 (sub_mode), fast_mode
, special_op_mode);
}
}
break;
@ -294,8 +296,11 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s
QByteArray operator_call;
QByteArray my_call;
QByteArray my_grid;
QByteArray exchange_sent;
QByteArray exchange_rcvd;
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)
{
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 (comments), QString::fromUtf8 (name), time_on
, 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;

View File

@ -76,7 +76,8 @@ public:
, QString const& report, 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, 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 decode (bool is_new, QString const& id, QTime time, qint32 snr, float delta_time
, quint32 delta_frequency, QString const& mode, QString const& message
@ -88,7 +89,8 @@ public:
, Frequency dial_frequency, QString const& mode, QString const& report_sent
, QString const& report_received, QString const& tx_power, QString const& comments
, 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 logged_ADIF (QString const& id, QByteArray const& ADIF);

View File

@ -124,6 +124,7 @@
* Tx Watchdog bool
* Sub-mode utf8
* Fast mode bool
* Special operation mode quint8
*
* WSJT-X sends this status message when various internal state
* changes to allow the server to track the relevant state of each
@ -142,10 +143,22 @@
* At the start and end of decoding,
* When the Rx 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 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
* Id (unique key) utf8
@ -240,6 +253,8 @@
* Operator call utf8
* My call utf8
* My grid utf8
* Exchange sent utf8
* Exchange received utf8
*
* The QSO logged message is sent to the server(s) when the
* 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
QString effective_prefix (QString callsign)
{
auto prefix = callsign.toUpper ();
auto prefix = callsign;
auto slash_pos = callsign.indexOf ('/');
if (slash_pos >= 0)
{
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 = 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.
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
November 26, 2018
-----------------------

View File

@ -72,7 +72,7 @@ namespace
}
BeaconsModel::BeaconsModel (QObject * parent)
: QStandardItemModel {0, sizeof (headings) / sizeof (headings[0]), parent}
: QStandardItemModel {0, sizeof headings / sizeof headings[0], parent}
{
int column {0};
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
, bool transmitting, bool decoding, 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, bool fast_mode)
, bool watchdog_timeout, QString const& sub_mode, bool fast_mode
, quint8 special_op_mode)
{
if (id == id_)
{
fast_mode_ = fast_mode;
decodes_proxy_model_.de_call (de_call);
decodes_proxy_model_.rx_df (rx_df);
de_label_->setText (de_call.size () >= 0 ? QString {"DE: %1%2"}.arg (de_call)
.arg (de_grid.size () ? '(' + de_grid + ')' : QString {}) : QString {});
QString special;
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"}
.arg (mode)
.arg (sub_mode)

View File

@ -32,7 +32,8 @@ public:
, QString const& report, 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, 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
, float delta_time, quint32 delta_frequency, QString const& mode
, QString const& message, bool low_confidence, bool off_air);

View File

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

View File

@ -25,12 +25,14 @@ namespace
QT_TRANSLATE_NOOP ("MessageAggregatorMainWindow", "Operator"),
QT_TRANSLATE_NOOP ("MessageAggregatorMainWindow", "My Call"),
QT_TRANSLATE_NOOP ("MessageAggregatorMainWindow", "My Grid"),
QT_TRANSLATE_NOOP ("MessageAggregatorMainWindow", "Exchange Sent"),
QT_TRANSLATE_NOOP ("MessageAggregatorMainWindow", "Exchange Rcvd"),
QT_TRANSLATE_NOOP ("MessageAggregatorMainWindow", "Comments"),
};
}
MessageAggregatorMainWindow::MessageAggregatorMainWindow ()
: log_ {new QStandardItemModel {0, 14, this}}
: log_ {new QStandardItemModel {0, sizeof headings / sizeof headings[0], this}}
, decodes_model_ {new DecodesModel {this}}
, beacons_model_ {new BeaconsModel {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& tx_power, QString const& comments
, 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;
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 {my_call}
<< new QStandardItem {my_grid}
<< new QStandardItem {exchange_sent}
<< new QStandardItem {exchange_rcvd}
<< new QStandardItem {comments};
log_->appendRow (row);
log_table_view_->resizeColumnsToContents ();

View File

@ -32,7 +32,8 @@ public:
, Frequency dial_frequency, QString const& mode, QString const& report_sent
, QString const& report_received, QString const& tx_power, QString const& comments
, 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:
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*/
, bool /*transmitting*/, bool /*decoding*/, 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, bool /*fast_mode*/)
, bool /* watchdog_timeout */, QString const& sub_mode, bool /*fast_mode*/
, quint8 /*special_op_mode*/)
{
if (id == id_)
{
@ -99,7 +100,8 @@ public:
, Frequency dial_frequency, QString const& mode, QString const& report_sent
, QString const& report_received, QString const& tx_power
, 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_)
{
@ -107,7 +109,8 @@ public:
<< "freq:" << dial_frequency << "mode:" << mode << "rpt_sent:" << report_sent
<< "rpt_rcvd:" << report_received << "Tx_pwr:" << tx_power << "comments:" << comments
<< "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 << 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)

View File

@ -2,5 +2,5 @@
set (WSJTX_VERSION_MAJOR 2)
set (WSJTX_VERSION_MINOR 0)
set (WSJTX_VERSION_PATCH 0)
set (WSJTX_RC 5) # release candidate number, comment out or zero for development versions
set (WSJTX_RC 6) # release candidate number, comment out or zero for development versions
set (WSJTX_VERSION_IS_RELEASE 0) # set to 1 for final release build

1635
cty.dat

File diff suppressed because it is too large Load Diff

View File

@ -12,14 +12,14 @@ Example:
[displayed text] PSK Reporter
Perform searches from the doc root directory: doc
Search: grep -rl --exclude-dir="*\.svn" {pskreporter} .
grep -rl --exclude-dir="*\.svn" PSK Reporter .
grep -rl --exclude-dir="*\.svn" {devsvn} .
grep -rl --exclude-dir="*\.svn" {kvasd} .
grep -rl --exclude-dir="*\.svn" {ntpsetup} .
Search: grep -rl --exclude-dir="*\.git" {pskreporter} .
grep -rl --exclude-dir="*\.git" PSK Reporter .
grep -rl --exclude-dir="*\.git" {devrepo} .
grep -rl --exclude-dir="*\.git" {kvasd} .
grep -rl --exclude-dir="*\.git" {ntpsetup} .
Include links.adoc: grep -rl --exclude-dir="*\.svn" pskreporter .
Exclude links.adoc: grep -rl --exclude-dir="*\.svn" {pskreporter} .
Include links.adoc: grep -rl --exclude-dir="*\.git" pskreporter .
Exclude links.adoc: grep -rl --exclude-dir="*\.git" {pskreporter} .
Note(s):
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]
:debian: http://www.debian.org/[Debian]
: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/[SourceForge]
:devsvn: http://sourceforge.net/p/wsjt/wsjt/HEAD/tree/[Devel-SVN]
:devrepo: https://sourceforge.net/p/wsjt/wsjtx/ci/master/tree/[SourceForge]
:dimension4: http://www.thinkman.com/dimension4/[Thinking Man Software]
:download: http://physics.princeton.edu/pulsar/K1JT/wsjtx.html[Download Page]
: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_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]
: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]
: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]
@ -79,7 +79,9 @@ d). Edit lines as needed. Keeping them in alphabetic order help see dupes.
:log4om: http://www.log4om.com[Log4OM]
:lunarEchoes: http://physics.princeton.edu/pulsar/K1JT/LunarEchoes_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]
:n1mm_logger: https://n1mm.hamdocs.com/tiki-index.php[N1MM Logger+]
: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]
: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-jtsdk: https://sourceforge.net/projects/jtsdk[SourceForge JTSDK]
: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]
: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]
@ -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]
: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_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_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
: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
upper limit of -1 dB.
+
TIP: Consider reducing power if your QSO partner reports your
signal above -5 dB in one of the _WSJT-X_ slow modes. These are
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
been lost.
+
TIP: Many Icom rigs cannot be queried for split status, current VFO or
split transmit frequency. When using _WSJT-X_ with such radios you
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.
Double-clicking *Erase* clears both text windows.
+
TIP: Right-clicking on either text window brings up a context menu
with several options (including *Erase*) which operate on that window
alone.

View File

@ -56,6 +56,8 @@ spaces) in the *Free Msg* box.
pre-stored macro. Pressing *Enter* on a modified message here
automatically adds that message to the table of stored macros.
+
TIP: During a transmission the actual message being sent always
appears in the first box of the status bar (bottom left of the main
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
before timeout.
TIP: Temporary status messages may occasionally be displayed here for
a few seconds when background processing completes.

View File

@ -36,4 +36,12 @@ current band, as well as other options.
* {jtbridge}, by SM0THU, is available for OS X. It works together with
logging applications Aether, MacLoggerDX, RUMlog or RUMlogNG. It
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
callsign and that of your potential QSO partner. The software
therefore "`knows`" what to expect for 57 of the 72 message bits (28
bits for each of two callsigns, 1 bit for message type) in the next
received message. The decoder's task can thus be reduced to
therefore "`knows`" what might be expected for at least 57 message
bits (28 for each of two callsigns, 1 or more for message type) in the
next received message. The decoder's task can thus be reduced to
determining the remaining 15 bits of the message and ensuring that the
resulting solution is reliable.

View File

@ -47,7 +47,27 @@ location for each instance of _WSJT-X_.
wsjtx --rig-name=TS2000
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
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
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:
- Subversion 1.8 or later
- Git
- Qt 5.2 or later
- g++ 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:
=====
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,
=====
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

View File

@ -2,6 +2,16 @@
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}
- To install:
+
@ -33,9 +43,9 @@ sudo dpkg -P wsjtx
You may also need to execute the following command in a terminal:
[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}
- To install:

View File

@ -6,7 +6,7 @@ installation notes.
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
_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:

View File

@ -3,32 +3,70 @@
Download and execute the package file {win32}, following these
instructions:
- Install _WSJT-X_ into its own directory, for example `C:\WSJTX` or
`C:\WSJT\WSJTX`, rather than the conventional location
`C:\Program Files\WSJTX`.
* Install _WSJT-X_ into its own directory, for example `C:\WSJTX` or `
C:\WSJT\WSJTX`, rather than the conventional location `C:\Program
Files (x86)\WSJTX`.
- All program files relating to _WSJT-X_ will be stored in the chosen
installation directory and its subdirectories.
* All program files relating to _WSJT-X_ will be stored in the chosen
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`.
TIP: Your computer may be configured so that this directory is
"`invisible`". It's there, however, and accessible. An alternative
(shortcut) directory name is `%LOCALAPPDATA%\WSJT-X\`.
"`invisible`". It's there, however, and accessible. An
alternative (shortcut) directory name is
`"%LocalAppData%\WSJT-X\"`.
- The built-in Windows facility for time synchronization is usually
not adequate. We recommend the program _Meinberg NTP_ (see {ntpsetup}
for downloading and installation instructions) or _Dimension 4_ from
{dimension4}.
* The built-in Windows facility for time synchronization is usually
not adequate. We recommend the program _Meinberg NTP_ (see
{ntpsetup} for downloading and installation instructions) or
_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.
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)*.
[[OPENSSL]]
- 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.
* image:LoTW_TLS_error.png[_WSJT-X_ LoTW download TLS error, role="right"]
From this version onward _WSJT-X_ requires the _OpenSSL_ libraries
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
_WSJT_.
_WSJT-X_ Version 1.9 offers nine different protocols or modes: *FT8*,
*JT4*, *JT9*, *JT65*, *QRA64*, *ISCAT*, *MSK144*, *WSPR*, and *Echo*.
The first five are designed for making reliable QSOs under extreme
weak-signal conditions. They use nearly identical message structure
and source encoding. JT65 and QRA64 were designed for EME
("`moonbounce`") on the VHF/UHF bands and have also proven very
effective for worldwide QRP communication on the HF bands. QRA64 has
a number of advantages over JT65, including better performance on the
very weakest signals. We imagine that over time it may replace JT65
for EME use. JT9 was originally designed for the LF, MF, and lower HF
bands. Its submode JT9A is 2 dB more sensitive than JT65 while using
less than 10% of the bandwidth. JT4 offers a wide variety of tone
spacings and has proven highly effective for EME on microwave bands up
to 24 GHz. These four "`slow`" modes use one-minute timed sequences
of alternating transmission and reception, so a minimal QSO takes four
to six minutes — two or three transmissions by each station, one
sending in odd UTC minutes and the other even. FT8 is operationally
similar but four times faster (15-second T/R sequences) and less
sensitive by a few dB. On the HF bands, world-wide QSOs are possible
with any of these modes using power levels of a few watts (or even
milliwatts) and compromise antennas. On VHF bands and higher, QSOs
are possible (by EME and other propagation types) at signal levels 10
to 15 dB below those required for CW.
_WSJT-X_ Version {VERSION_MAJOR}.{VERSION_MINOR} offers nine different
protocols or modes: *FT8*, *JT4*, *JT9*, *JT65*, *QRA64*, *ISCAT*,
*MSK144*, *WSPR*, and *Echo*. The first five are designed for making
reliable QSOs under extreme weak-signal conditions. They use nearly
identical message structure and source encoding. JT65 and QRA64 were
designed for EME ("`moonbounce`") on the VHF/UHF bands and have also
proven very effective for worldwide QRP communication on the HF bands.
QRA64 has a number of advantages over JT65, including better
performance on the very weakest signals. We imagine that over time it
may replace JT65 for EME use. JT9 was originally designed for the LF,
MF, and lower HF bands. Its submode JT9A is 2 dB more sensitive than
JT65 while using less than 10% of the bandwidth. JT4 offers a wide
variety of tone spacings and has proven highly effective for EME on
microwave bands up to 24 GHz. These four "`slow`" modes use
one-minute timed sequences of alternating transmission and reception,
so a minimal QSO takes four to six minutes — two or three
transmissions by each station, one sending in odd UTC minutes and the
other even. FT8 is operationally similar but four times faster
(15-second T/R sequences) and less sensitive by a few dB. On the HF
bands, world-wide QSOs are possible with any of these modes using
power levels of a few watts (or even milliwatts) and compromise
antennas. On VHF bands and higher, QSOs are possible (by EME and
other propagation types) at signal levels 10 to 15 dB below those
required for CW.
*ISCAT*, *MSK144*, and optionally submodes *JT9E-H* are "`fast`"
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
messages normally carry the transmitting stations callsign, grid
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
reports to a central database called {wsprnet} that provides a mapping
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
the DXCC entity is shown, abbreviated if necessary. Your "`worked
before`" status for this callsign (according to log file
`wsjtx_log.adi`) is flagged with a single character and a change of
background color, as follows:
[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.
`wsjtx_log.adi`) is indicated by highlighting colors, if that option
has been selected.
_WSJT-X_ includes a built-in `cty.dat` file containing DXCC prefix
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
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
RRR or 73. These messages are compressed and encoded in a highly
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,
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
fully automated QSOs.
=== VHF Contest Mode
=== Contest Messages
A special *NA VHF Contest* mode can be activated for FT8 and MSK144.
To use it you must activate *File | Settings | General | Enable
VHF/UHF/Microwave features* and then check the box *NA VHF Contest* on
the main window. This mode is configured especially for contests in
which four-character grid locators are the required exchange. When
*NA VHF Contest* mode is active, the standard QSO sequence looks like
this:
The new FT8 and MSK144 protocols support special messages optimized
for *NA VHF* and *EU VHF* contests. FT8 also supports messages for
*ARRL Field Day* and the *ARRL RTTY Roundup*. The decoders recognize
and decode these messages at any time. Configure the program to
automatically generate the required message types by selecting a
supported operating activity on the *Settings | Advanced* tab. Model
QSOs then proceed as follows, for each event type:
*NA VHF Contest*
CQ K1ABC FN42
K1ABC W9XYZ EN37
K1ABC W9XYZ EN37
W9XYZ K1ABC R FN42
K1ABC W9XYZ RRR
K1ABC W9XYZ RRR
W9XYZ K1ABC 73
In contest circumstances K1ABC might choose to call CQ again rather
than sending 73 for his third transmission.
Either callsign (or both) may have /R appended. You can use RR73 in
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
<<PROTOCOL_OVERVIEW,Protocol Specifications>> for further details.
*EU VHF Contest*
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]]
=== Compound Callsigns
Compound callsigns such as xx/K1ABC or K1ABC/x are handled in
one of two possible ways:
*FT8 and MSK144*
.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
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
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
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
reliably known frequencies receivable at your location.
+
TIP: We find major-city AM broadcast stations generally serve well as
frequency calibrators at the low frequency end of the spectrum. In
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
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
situations
- New FT8 and MSK144 protocols with 77-bit payloads permit these enhancements:
- Decoding improvements for JT65 mode, including _a priori_ (AP)
decoding when VHF/UHF/Microwave features are enabled
* Optimized contest messages for NA VHF, EU VHF, Field Day, RTTY Roundup
- 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
decoding in FT8 mode
* New logging features for contesting
- 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
- 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
In this manual the following icons call attention to particular types
@ -45,12 +53,12 @@ consequences.
=== How You Can Contribute
_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
your interests known to the development team. The project's
source-code repository can be found at {devsvn}, and most
communication among the developers takes place on the email reflector
{devmail}. Bug reports and suggestions for new features, improvements
to the _WSJT-X_ User Guide, etc., may also be sent to the
{wsjt_yahoo_group} email reflector. You must join the relevant group
before posting to either email list.
source-code repository can be found at {devrepo}, and communication
among the developers takes place on the email reflector {devmail}.
Bug reports and suggestions for new features, improvements to the
_WSJT-X_ User Guide, etc., may also be sent to the {wsjt_yahoo_group}
email reflector. You must join the relevant group before posting to
either email list.

View File

@ -2,18 +2,20 @@
=== Overview
All QSO modes except ISCAT use structured messages that compress
user-readable information into fixed-length packets of 72 bits. Each
message consists of two 28-bit fields normally used for callsigns and
a 15-bit field for a grid locator, report, acknowledgment, or 73. An
additional bit flags a message containing arbitrary alphanumeric text,
up to 13 characters. Special cases allow other information such as
add-on callsign prefixes (e.g., ZA/K1ABC) or suffixes (e.g., K1ABC/P)
to be encoded. The basic aim is to compress the most common messages
used for minimally valid QSOs into a fixed 72-bit length. The
information payload in FT8 includes 3 additional bits (75 bits total).
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
bits are yet to be defined.
user-readable information into fixed-length packets. JT4, JT9, JT65,
and QRA64 use 72-bit payloads. Standard messages consist of two
28-bit fields normally used for callsigns and a 15-bit field for a
grid locator, report, acknowledgment, or 73. An additional bit flags
a message containing arbitrary free text, up to 13 characters.
Special cases allow other information such as add-on callsign prefixes
(e.g., ZA/K1ABC) or suffixes (e.g., K1ABC/P) to be encoded. The basic
aim is to compress the most common messages used for minimally valid
QSOs into a fixed 72-bit length.
The information payload for FT8 and MSK144 contains 77 bits. The 5
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
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
slots mentioned above.
As a convenience for sending directed CQ messages, the compression
algorithm supports messages starting with `CQ AA` through `CQ ZZ`.
These message fragments are encoded internally as if they were the
callsigns `E9AA` through `E9ZZ`. Upon reception they are converted
back to the form `CQ AA` through `CQ ZZ`, for display to the user.
As a convenience for sending directed CQ messages, the 72-bit
compression algorithm supports messages starting with `CQ AA` through
`CQ ZZ`. These message fragments are encoded internally as if they
were the callsigns `E9AA` through `E9ZZ`. Upon reception they are
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
transmission and acknowledgment of four-character grid locators, the
required exchanges in most North American VHF contests. With this
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.
The new FT8 and MSK144 protocols use a different lossless compression
algorithm with features to generate and recognize the special messages
used for contesting and the like. (More to come, here ...)
To be useful on channels with low signal-to-noise ratio, this kind of
lossless message compression requires use of a strong forward error
@ -75,9 +71,9 @@ _WSJT-X_ modes have continuous phase and constant envelope.
==== FT8
Forward error correction (FEC) in FT8 uses a low-density parity check
(LDPC) code with 75 information bits, a 12-bit cyclic redundancy check
(CRC), and 87 parity bits making a 174-bit codeword. It is thus
called an LDPC (174,87) code. Synchronization uses 7×7 Costas arrays
(LDPC) code with 77 information bits, a 14-bit cyclic redundancy check
(CRC), and 83 parity bits making a 174-bit codeword. It is thus
called an LDPC (174,91) code. Synchronization uses 7×7 Costas arrays
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
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)
|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
|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
@ -329,13 +325,13 @@ For details see Table 4, below.
==== MSK144
Standard MSK144 messages are structured in the same way as those in
the slow modes, with 72 bits of user information. Forward error
correction is implemented by first augmenting the 72 message bits with
an 8-bit cyclic redundancy check (CRC) calculated from the message
bits. The CRC is used to detect and eliminate most false decodes at
the receiver. The resulting 80-bit augmented message is mapped to a
128-bit codeword using a (128,80) binary low-density-parity-check
Standard MSK144 messages are structured in the same way as in FT8,
with 77 bits of user information. Forward error correction is
implemented by first augmenting the 77 message bits with a 13-bit
cyclic redundancy check (CRC) calculated from the message bits. The
CRC is used to detect and eliminate most false decodes at the
receiver. The resulting 90-bit augmented message is mapped to a
128-bit codeword using a (128,90) binary low-density-parity-check
(LDPC) code designed by K9AN specifically for this purpose. Two 8-bit
synchronizing sequences are added to make a message frame 144 bits
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
|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
|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
|=====================================================================

View File

@ -27,6 +27,8 @@ receiver's effective noise bandwidth.
a larger delay between execution of a command to enable PTT and onset
of Tx audio.
+
IMPORTANT: For the health of your T/R relays and external
preamplifier, we strongly recommend using a hardware sequencer and
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
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
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.
- _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
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.
+
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
to prevent inadvertently transmitting them over the air.
+
NOTE: Windows Vista and later may configure audio devices using
the Texas Instruments PCM2900 series CODEC for microphone input rather
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
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
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
program for automatic tracking of the Sun or Moon, as well as
calculated Doppler shift for the specified EME path. The file is
updated once per second whenever the <<ASTRODATA,Astronomical Data>>
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
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

View File

@ -1,5 +1,47 @@
image::colors.png[align="center",alt="Colors Screen"]
_WSJT-X_ uses colors to highlight decoded messages containing
information of particular interest. Click on one of the buttons to
select your preferred colors for any message category.
.Decode Highlighting
* _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"]
_Working Frequencies_: By default the *Working Frequencies* table
contains a list of frequencies conventionally used for modes JT4, JT9,
JT65, MSK144, WSPR, and Echo. Conventions may change with time or
by user preference; you can modify the frequency table as desired.
contains a list of frequencies conventionally used for modes FT8, JT4,
JT9, JT65, MSK144, WSPR, and Echo. Conventions may change with time
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
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
the section <<COMP-CALL,Compound Callsigns>>.
NOTE: Enabling VHF/UHF/Microwave features necessarily disables the
wideband multi-decode capability of JT65. In most circumstances you
should turn this feature off when operating at HF.
NOTE: Checking *Enable VHF/UHF/Microwave features* necessarily
disables the wideband multi-decode capability of JT65. In most
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
your radio, select the *Radio* tab.
- Select your radio type from the drop-down list labeled *Rig*, or
*None* if you do not wish to use CAT control.
* Select your radio type from the drop-down list labeled *Rig*, or
*None* if you do not wish to use CAT control.
- Alternatively, if you have configured your station for control by
*DX Lab Suite Commander*, *Ham Radio Deluxe*, *Hamlib NET rigctl*, or
*Omni-Rig*, you may select one of those program names from the *Rig*
list. In these cases the entry field immediately under _CAT Control_
will be relabeled as *Network Server*. Leave this field blank to
access the default instance of your control program, running on the
same computer. If the control program runs on a different computer
and/or port, specify it here. Hover the mouse pointer over the entry
field to see the required formatting details.
** Alternatively, if you have configured your station for control by
*DX Lab Suite Commander*, *Flrig*, *Ham Radio Deluxe*, *Hamlib NET
rigctl*, or *Omni-Rig*, you may select one of those program names
from the *Rig* list. In these cases the entry field immediately
under _CAT Control_ will be relabeled as *Network Server*. Leave
this field blank to access the default instance of your control
program, running on the same computer. If the control program runs
on a different computer and/or port, specify it here. Hover the
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
_Omni-Rig_ server running on the same computer. Note that _Omni-Rig_
is available only under Windows.
** Select *Omni-Rig Rig 1* or *Omni-Rig Rig 2* to connect to an
_Omni-Rig_ server installed on the same computer. _Omni-Rig_ will
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
than though another program, make the following settings:
NOTE: _Omni-Rig_ is available only under Windows.
* 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*,
*Stop Bits*, and *Handshake* method. Consult your radio's user guide
for the proper parameter values.
* _CAT Control_: To have _WSJT-X_ control the radio directly rather
than though another program, make the following settings:
* _Force Control Lines_: A few station setups require the CAT serial
ports *RTS* and/or *DTR* control lines to be forced high or
low. Check these boxes only if you are sure they are needed (for
example, to power the radio serial interface).
** Select the *Serial Port* or *Network Server* including the service
port number used to communicate with your radio.
- _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
connector that will accept Tx audio. If this choice is enabled,
select *Rear/Data* or *Front/Mic*.
NOTE: A special value of *USB* is available for custom USB devices
like those used by some SDR kits. This is not the same a virtual
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
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.
** _Serial Port Parameters_: Set values for *Baud Rate*, *Data Bits*,
*Stop Bits*, and *Handshake* method. Consult your radio's user
*guide for the proper parameter values.
- _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.
+
NOTE: CAT interfaces that require handshaking will be non-responsive
until the correct *Handshake* setting is applied.
** _Force Control Lines_: A few station setups require the CAT serial
ports *RTS* and/or *DTR* control lines to be forced high or
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).
+
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
communication between _WSJT-X_ and your radio. The button should turn

View File

@ -2,53 +2,63 @@
.Receiver Noise Level
- 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.
- Use the receiver gain controls and/or the computer's audio mixer
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
usually best to turn AGC off or reduce the RF gain control to minimize
AGC action.
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
usually best to turn AGC off or reduce the RF gain control to
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
- If your transceiver offers more than one bandwidth setting in USB
mode, it may be advantageous to choose the widest one possible, up to
about 5 kHz. This choice has the desirable effect of allowing the
*Wide Graph* (waterfall and 2D spectrum) to display the conventional
JT65 and JT9 sub-bands simultaneously on most HF bands. Further
details are provided in the <<TUTORIAL,Basic Operating Tutorial>>. A
wider displayed bandwidth may also be helpful at VHF and above, where
FT8, JT4, JT65, and QRA64 signals may be found over much wider ranges
of frequencies.
mode, it may be advantageous to choose the widest one possible, up
to about 5 kHz. This choice has the desirable effect of allowing
the *Wide Graph* (waterfall and 2D spectrum) to display the
conventional JT65 and JT9 sub-bands simultaneously on most HF bands.
Further details are provided in the <<TUTORIAL,Basic Operating
Tutorial>>. A wider displayed bandwidth may also be helpful at VHF
and above, where FT8, JT4, JT65, and QRA64 signals may be found over
much wider ranges of frequencies.
- 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
frequency setting, on HF bands you can display the full sub-band
generally used for one mode.
more than about 2.7 kHz bandwidth. Depending on the exact dial
frequency setting, on HF bands you can display the full sub-band
generally used for one mode.
- 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,
or 14.078 for JT9. Present conventions have the nominal JT9 dial
frequency 2 kHz higher than the JT65 dial frequency on most bands, and
the FT8 frequency 2 kHz lower.
setting your dial frequency to (say) 14.074 for FT8, 14.076 for
JT65, or 14.078 for JT9. Present conventions have the nominal JT9
dial frequency 2 kHz higher than the JT65 dial frequency on most
bands, and the FT8 frequency 2 kHz lower.
.Transmitter Audio Level
* Click the *Tune* button on the main screen to switch the
radio into transmit mode and generate a steady audio tone.
* Click the *Tune* button on the main screen to switch the radio into
transmit mode and generate a steady audio tone.
* Listen to the generated audio tone using your radios *Monitor*
facility. The transmitted tone should be perfectly smooth, with no
clicks or glitches. Make sure that this is true even when you
simultaneously use the computer to do other tasks such as email, web
browsing, etc.
facility. The transmitted tone should be perfectly smooth, with no
clicks or glitches. Make sure that this is true even when you
simultaneously use the computer to do other tasks such as email, web
browsing, etc..
* Adjust the *Pwr* slider (at right edge of main window) downward from
its maximum until the RF output from your transmitter falls slightly.
This is generally a good level for audio drive.
its maximum until the RF output from your transmitter falls
slightly. This is generally a good level for audio drive.
* 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
both Rx and Tx frequencies.
+
NOTE: You can prevent your Tx frequency from being changed by checking the
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
the mode of each JT9 or JT65 message.
+
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*
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
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
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.
NOTE: Further helpful tips on FT8 operating procedures are available
{ft8_tips}. Thanks to ZL2IFB!
TIP: An online {ft8_tips} by ZL2IFB offers many helpful tips on
operating procedures.
.FT8 DXpedition Mode:

View File

@ -6,6 +6,8 @@
- Set the audio frequencies to *Tx 1224 Hz* and *Rx 1224 Hz*.
+
TIP: Sliders and spinner controls respond to *Arrow* key presses
and *Page Up/Down* key presses, with the *Page* keys moving the
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
on the VHF and higher bands. These features include:
_WSJT-X_ v{VERSION_MAJOR}.{VERSION_MINOR} suppports a number of
features designed for use on the VHF and higher bands. These features
include:
- *FT8*, a mode designed for making fast QSOs with weak, fading
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
200 Hz.
+
NOTE: Most modern multi-core computers can easily handle the optimum
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*
@ -303,6 +306,7 @@ enclosed in <> angle brackets, as in the following model QSO
<W9XYZ K1ABC> RRR
<K1ABC W9XYZ> 73
+
NOTE: There is little or no advantage to using MSK144 *Sh*
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.
= _WSJT-X_ User Guide
= _WSJT-X {VERSION_MAJOR}.{VERSION_MINOR}_ User Guide
Joseph H Taylor, Jr, K1JT
:revnumber: {VERSION}
// 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
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
tutorial, preferably while at your radio. Subsequent sections cover
additional details on <<MAKE_QSOS,Making QSOs>>, <<WSPR,WSPR mode>>
and <<VHF_AND_UP,VHF+ Features>>.
tutorial, preferably while at your radio. Note that as of late 2018,
digital usage on the HF bands has mostly moved from JT65 and JT9 to FT8. So
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]]
=== Main Window Settings

View File

@ -11,6 +11,8 @@ desired size.
- 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
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);
}

View File

@ -1,8 +1,10 @@
#ifndef DATE_TIME_AS_SECS_SINCE_EPOCH_DELEGATE_HPP_
#define DATE_TIME_AS_SECS_SINCE_EPOCH_DELEGATE_HPP_
#include <memory>
#include <QStyledItemDelegate>
#include <QVariant>
#include <QLocale>
#include <QDateTime>
#include <QAbstractItemModel>
#include <QDateTimeEdit>
@ -33,12 +35,17 @@ public:
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
{
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

View File

@ -34,22 +34,6 @@ module crc
integer (c_int), value :: length
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")
use, intrinsic :: iso_c_binding, only: c_short, c_ptr, c_int
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) :: freq
character(len=37), intent(in) :: decoded
character c1*12,c2*12,g2*4,w*4,ctmp*12
integer i0,i1,i2,i3,i4,i5,i6,n30,nwrap
character c1*12,c2*12,g2*4,w*4
integer i0,i1,i2,i3,i4,i5,n30,nwrap
integer, intent(in) :: nap
real, intent(in) :: qual
character*2 annot

View File

@ -1,16 +1,16 @@
subroutine fmtmsg(msg,iz)
character*22 msg
character*(*) msg
! Convert all letters to upper case
iz=22
do i=1,22
iz=len(msg)
do i=1,iz
if(msg(i:i).ge.'a' .and. msg(i:i).le.'z') &
msg(i:i)= char(ichar(msg(i:i))+ichar('A')-ichar('a'))
if(msg(i:i).ne.' ') iz=i
enddo
do iter=1,5 !Collapse multiple blanks into one
do iter=1,37 !Collapse multiple blanks into one
ib2=index(msg(1:iz),' ')
if(ib2.lt.1) go to 100
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
integer itone(79)
integer*1 msgbits(77),msgbits2
integer*1, target:: i1Msg8BitBytes(11)
integer*1, target:: mycall
real x(NFFT)
real*8 dt,twopi,f0,fstep,dfreq,phi,dphi

View File

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

View File

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

View File

@ -7,30 +7,25 @@ subroutine ft8b(dd0,newdat,nQSOProgress,nfqso,nftx,ndepth,lapon,lapcqonly, &
use packjt77
include 'ft8_params.f90'
parameter(NP2=2812)
character*37 msg37,msgsent37
character*37 msg37
character*12 mycall12,hiscall12,hiscall12_0
character*77 c77
character*6 mycall6,hiscall6,c1,c2
character*13 c13
character*87 cbits
real a(5)
real s8(0:7,NN)
real s2(0:511),s2l(0:511)
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 llral(174),llrbl(174),llrcl(174) !Soft symbols
real dd0(15*12000)
integer*1 message77(77),apmask(174),cw(174)
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 itone(NN)
integer icos7(0:6),ip(1)
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 ncontest,ncontest0
integer*1, target:: i1hiscall(12)
logical one(0:511,0:8)
integer graymap(0:7)
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 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 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 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/
@ -57,7 +51,6 @@ subroutine ft8b(dd0,newdat,nQSOProgress,nfqso,nftx,ndepth,lapon,lapcqonly, &
mcqfd=2*mcqfd-1
mcqru=2*mcqru-1
mcqtest=2*mcqtest-1
mcqhund=2*mcqhund-1
mrrr=2*mrrr-1
m73=2*m73-1
mrr73=2*mrr73-1
@ -205,37 +198,26 @@ subroutine ft8b(dd0,newdat,nQSOProgress,nfqso,nftx,ndepth,lapon,lapcqonly, &
do ib=0,ibmax
bm=maxval(s2(0:nt-1),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(nsym.eq.1) then
bmeta(i32+ib)=bm
! bmetal(i32+ib)=bml
elseif(nsym.eq.2) then
bmetb(i32+ib)=bm
! bmetbl(i32+ib)=bml
elseif(nsym.eq.3) then
bmetc(i32+ib)=bm
! bmetcl(i32+ib)=bml
endif
enddo
enddo
enddo
enddo
call normalizebmet(bmeta,174)
! call normalizebmet(bmetal,174)
call normalizebmet(bmetb,174)
! call normalizebmet(bmetbl,174)
call normalizebmet(bmetc,174)
! call normalizebmet(bmetcl,174)
scalefac=2.83
llra=scalefac*bmeta
! llral=scalefac*bmetal
llrb=scalefac*bmetb
! llrbl=scalefac*bmetbl
llrc=scalefac*bmetc
! llrcl=scalefac*bmetcl
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(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
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
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.3) llrd(1:29)=apmag*mcqfd(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
llrd(75:76)=apmag*(-1)
llrd(77)=apmag*(+1)

View File

@ -8,14 +8,11 @@ program ft8code
include 'ft8_testmsg.f90'
parameter (NWAVE=NN*NSPS)
character*77 c77
character*37 msg,msgsent
character*9 comment
character bad*1,msgtype*16
character*91 cbits
character bad*1,msgtype*18
integer itone(NN)
integer*1 msgbits(77)
logical unpk77_success
! Get command-line argument(s)
nargs=iargc()
@ -69,10 +66,10 @@ program ft8code
if(msg.ne.msgsent) bad="*"
if(n3.ge.0) then
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
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
enddo

View File

@ -9,7 +9,7 @@ program ft8sim
parameter (NWAVE=NN*NSPS)
type(hdr) h !Header for .wav file
character arg*12,fname*17
character msg37*37,msgsent37*37,msg40*40
character msg37*37,msgsent37*37
character c77*77
complex c0(0:NMAX-1)
complex c(0:NMAX-1)
@ -108,7 +108,6 @@ program ft8sim
ib=k
wave=real(c)
peak=maxval(abs(wave(ia:ib)))
rms=sqrt(dot_product(wave(ia:ib),wave(ia:ib))/NWAVE)
nslots=1
if(width.gt.0.0) call filt8(f0,nslots,width,wave)
@ -119,10 +118,16 @@ program ft8sim
enddo
endif
fac=32767.0
rms=100.0
if(snrdb.ge.90.0) iwave(1:NMAX)=nint(fac*wave)
if(snrdb.lt.90.0) iwave(1:NMAX)=nint(rms*wave)
gain=100.0
if(snrdb.lt.90.0) then
wave=gain*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)
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 unpack77(c77,msgsent,unpk77_success)
read(c77,'(77i1)',err=1) msgbits
go to 2
1 write(81,*) msg,c77 ; flush(81)
if(unpk77_success) go to 2
1 msgbits=0
itone=0
msgsent='*** bad message *** '
go to 900
entry get_tones_from_77bits(msgbits,itone)
@ -39,5 +42,5 @@ entry get_tones_from_77bits(msgbits,itone)
itone(k)=graymap(indx)
enddo
return
900 return
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
nfos=NFFT1/NSPS ! # frequency bin oversampling factor
jstrt=0.5/tstep
candidate0=0.
k=0
@ -133,7 +132,8 @@ subroutine sync8(dd,nfa,nfb,syncmin,nfqso,maxcand,s,candidate, &
j=indx(i)
! if( candidate0(3,j) .ge. syncmin .and. candidate0(2,j).ge.-1.5 ) 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
endif
enddo

View File

@ -52,7 +52,7 @@ contains
character*12 mycall12,hiscall12,mycall12_0
character*6 hisgrid6
integer*2 iwave(15*12000)
integer apsym1(KK),apsym2(58)
integer apsym2(58)
character datetime*13,msg37*37
! character message*22
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 call1*5,call2*5
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 ('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 ('f0',.true.,'F','base frequency offset, default F0=1500.0','F0'), &
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 ('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)',''), &
@ -50,6 +51,7 @@ program jt65sim
nsigs=10
bf0=1500.
fspread=0.
drift=0.
xdt=0.
snrdb=0.
nfiles=1
@ -58,7 +60,7 @@ program jt65sim
msg="K1ABC W9XYZ EN37"
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
exit
end if
@ -76,6 +78,8 @@ program jt65sim
read (optarg(:narglen), *,err=10) bf0
case ('d')
read (optarg(:narglen), *,err=10) fspread
case ('D')
read (optarg(:narglen), *,err=10) drift
case ('t')
read (optarg(:narglen), *) numbuf
if (numbuf(1:1) == '\') then !'\'
@ -105,7 +109,6 @@ program jt65sim
end if
case ('M')
read (optarg(:narglen), '(A)',err=10) msg
write(*,*) msg
end select
cycle
10 display_help=.true.
@ -190,6 +193,21 @@ program jt65sim
endif
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)
sig=sqrt(2*bandwidth_ratio)*10.0**(0.05*xsnr)
if(xsnr.gt.90.0) sig=1.0
@ -203,11 +221,8 @@ program jt65sim
do i=1,npts !Add this signal into cdat()
isym=floor(i/sps)+1
if(isym.gt.nsym) exit
if(isym.ne.isym0) then
freq=f0 + itone(isym)*baud*mode65
dphi=twopi*freq*dt
isym0=isym
endif
freq=f0 + (drift/60.0)*(i-npts/2)*dt + itone(isym)*baud*mode65
dphi=twopi*freq*dt
phi=phi + dphi
if(phi.gt.twopi) phi=phi-twopi
xphi=phi
@ -282,9 +297,9 @@ program jt65sim
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
dat=rms*dat(1:npts)
dat(1:npts)=rms*dat(1:npts)
else
datpk=maxval(abs(dat(1:npts)))
fac=32766.9/datpk

View File

@ -5,7 +5,7 @@ program msk144code
use packjt77
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)
include 'msk144_testmsg.f90'
@ -61,13 +61,13 @@ program msk144code
if(msg.ne.msgsent) bad="*"
if(i3.eq.0.and.n3.ge.0) then
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
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
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
enddo

View File

@ -100,7 +100,7 @@ subroutine msk144decodeframe(c,softbits,msgreceived,nsuccess)
if( nharderror .ge. 0 .and. nharderror .lt. 18 ) then
nsuccess=1
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
nsuccess=0
else

View File

@ -5,7 +5,6 @@ program msk144sim
real pings(0:NMAX-1)
real waveform(0:NMAX-1)
character arg*8,msg*37,msgsent*37,fname*40
character*77 c77
real wave(0:NMAX-1) !Simulated received waveform
real*8 twopi,freq,phi,dphi0,dphi1,dphi
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
ftop=nfqso + 7*mode4*df
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
endif
@ -139,11 +139,8 @@ subroutine sync4(dat,jz,ntol,nfqso,mode,mode4,minwidth,dtx,dfx,snrx, &
ns=ns+1
endif
enddo
rms=0.1
snrx=-26.0
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
rms=sqrt(sq/ns)
snrx=10.0*log10(ccfred(ipk1a)/rms) - 41.2
900 return
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;
entity_by_id::iterator e; // iterator into entity set

View File

@ -1,22 +1,29 @@
#include "WorkedBefore.hpp"
#include <functional>
#include <stdexcept>
#include <boost/functional/hash.hpp>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/key_extractors.hpp>
#include <QtConcurrent/QtConcurrentRun>
#include <QFuture>
#include <QFutureWatcher>
#include <QChar>
#include <QString>
#include <QByteArray>
#include <QStandardPaths>
#include <QDir>
#include <QFileInfo>
#include <QFile>
#include <QTextStream>
#include <QDebug>
#include "qt_helpers.hpp"
#include "pimpl_impl.hpp"
#include "moc_WorkedBefore.cpp"
using namespace boost::multi_index;
// hash function for QString members in hashed indexes
@ -214,6 +221,20 @@ namespace
{
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)
{
int fieldNameIndex = record.indexOf ('<' + fieldName + ':', 0, Qt::CaseInsensitive);
@ -228,8 +249,12 @@ namespace
if (dataTypeIndex > closingBracketIndex)
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;
if (dataTypeIndex >= 0)
@ -241,8 +266,93 @@ namespace
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_;
AD1CCty prefixes_;
QFutureWatcher<worked_before_database_type> loader_watcher_;
QFuture<worked_before_database_type> async_loader_;
worked_before_database_type worked_;
};
WorkedBefore::WorkedBefore ()
{
QFile inputFile {m_->path_};
if (inputFile.open (QFile::ReadOnly))
{
QTextStream in {&inputFile};
QString buffer;
bool pre_read {false};
int end_position {-1};
connect (&m_->loader_watcher_, &QFutureWatcher<worked_before_database_type>::finished, [this] () {
QString error;
size_t n {0};
try
{
m_->worked_ = m_->loader_watcher_.result ();
n = m_->worked_.size ();
}
catch (LoaderException const& e)
{
error = e.error ();
}
Q_EMIT finished_loading (n, error);
});
reload ();
}
// 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
{
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);
}
}
}
void WorkedBefore::reload ()
{
m_->reload ();
}
WorkedBefore::~WorkedBefore ()
@ -357,8 +438,8 @@ bool WorkedBefore::add (QString const& call
}
out << ADIF_record << " <eor>" << endl;
}
m_->worked_.emplace (call, grid, band, mode, entity.entity_name
, entity.continent, entity.CQ_zone, entity.ITU_zone);
m_->worked_.emplace (call.toUpper (), grid.left (4).toUpper (), band.toUpper (), mode.toUpper ()
, entity.entity_name, entity.continent, entity.CQ_zone, entity.ITU_zone);
}
return true;
}
@ -372,7 +453,7 @@ bool WorkedBefore::country_worked (QString const& country, QString const& mode,
return
country.size ()
&& 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
{
@ -380,7 +461,7 @@ bool WorkedBefore::country_worked (QString const& country, QString const& mode,
return
country.size ()
&& 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
@ -390,7 +471,7 @@ bool WorkedBefore::country_worked (QString const& country, QString const& mode,
return
country.size ()
&& 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
{
@ -410,13 +491,13 @@ bool WorkedBefore::grid_worked (QString const& grid, QString const& mode, QStrin
if (band.size ())
{
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
{
// partial key lookup
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
@ -424,13 +505,13 @@ bool WorkedBefore::grid_worked (QString const& grid, QString const& mode, QStrin
if (band.size ())
{
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
{
// partial key lookup
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 ())
{
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
{
// partial key lookup
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
@ -456,13 +537,13 @@ bool WorkedBefore::call_worked (QString const& call, QString const& mode, QStrin
if (band.size ())
{
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
{
// partial key lookup
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 ())
{
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
{
// partial key lookup
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
@ -488,7 +569,7 @@ bool WorkedBefore::continent_worked (Continent continent, QString const& mode, Q
if (band.size ())
{
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
{
@ -506,13 +587,13 @@ bool WorkedBefore::CQ_zone_worked (int CQ_zone, QString const& mode, QString con
if (band.size ())
{
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
{
// partial key lookup
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
@ -520,7 +601,7 @@ bool WorkedBefore::CQ_zone_worked (int CQ_zone, QString const& mode, QString con
if (band.size ())
{
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
{
@ -538,13 +619,13 @@ bool WorkedBefore::ITU_zone_worked (int ITU_zone, QString const& mode, QString c
if (band.size ())
{
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
{
// partial key lookup
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
@ -552,7 +633,7 @@ bool WorkedBefore::ITU_zone_worked (int ITU_zone, QString const& mode, QString c
if (band.size ())
{
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
{

View File

@ -1,7 +1,7 @@
#ifndef WORKWED_BEFORE_HPP_
#define WORKWED_BEFORE_HPP_
#include <boost/core/noncopyable.hpp>
#include <QObject>
#include "AD1CCty.hpp"
#include "pimpl_h.hpp"
@ -10,21 +10,25 @@ class QString;
class QByteArray;
class WorkedBefore final
: private boost::noncopyable
: public QObject
{
Q_OBJECT
public:
using Continent = AD1CCty::Continent;
explicit 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;
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 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;
@ -32,6 +36,8 @@ public:
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;
Q_SIGNAL void finished_loading (int worked_before_record_count, QString const& error) const;
private:
class impl;
pimpl<impl> m_;

View File

@ -1,13 +1,15 @@
#include "logbook.h"
#include <QDateTime>
#include <QDebug>
#include "Configuration.hpp"
#include "AD1CCty.hpp"
#include "moc_logbook.cpp"
LogBook::LogBook (Configuration const * 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,
@ -52,6 +54,11 @@ bool LogBook::add (QString const& call
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,
QString const& rptSent, QString const& rptRcvd, QDateTime const& dateTimeOn,
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
* VK3ACF July 2013
*/
#ifndef LOG_BOOK_H_
#define LOG_BOOK_H_
#include <boost/core/noncopyable.hpp>
#include <QObject>
#include <QString>
#include "WorkedBefore.hpp"
@ -16,9 +16,11 @@ class QByteArray;
class QDateTime;
class LogBook final
: private boost::noncopyable
: public QObject
{
public:
Q_OBJECT
public:
LogBook (Configuration const *);
QString const& path () const {return worked_before_.path ();}
bool add (QString const& call
@ -27,6 +29,7 @@ class LogBook final
, QString const& mode
, QByteArray const& ADIF_record);
AD1CCty const& countries () const {return worked_before_.countries ();}
void rescan ();
void match (QString const& call, QString const& mode, QString const& grid,
AD1CCty::Record const&, bool& callB4, bool& countryB4,
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& xSent, QString const& xRcvd);
private:
Q_SIGNAL void finished_loading (int worked_before_record_count, QString const& error) const;
private:
Configuration const * config_;
WorkedBefore worked_before_;
};

View File

@ -6,6 +6,8 @@
#include <locale.h>
#include <fftw3.h>
#include <QSharedMemory>
#include <QTemporaryFile>
#include <QDateTime>
#include <QApplication>
#include <QRegularExpression>
@ -21,6 +23,7 @@
#include <QCommandLineParser>
#include <QCommandLineOption>
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include "revision_utils.hpp"
@ -288,6 +291,12 @@ int main(int argc, char *argv[])
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;
do
{

View File

@ -10,7 +10,6 @@
#include <QSqlError>
#include <QSqlQuery>
#include <QDataStream>
#include <QDebug>
#include "Configuration.hpp"
#include "Bands.hpp"
#include "qt_db_helpers.hpp"
@ -52,7 +51,7 @@ CabrilloLog::impl::impl (Configuration const * configuration)
SQL_error_check (export_query_, &QSqlQuery::prepare,
"SELECT frequency, \"when\", exchange_sent, call, exchange_rcvd FROM cabrillo_log ORDER BY \"when\"");
setEditStrategy (QSqlTableModel::OnRowChange);
setEditStrategy (QSqlTableModel::OnFieldChange);
setTable ("cabrillo_log");
setHeaderData (fieldIndex ("frequency"), Qt::Horizontal, tr ("Freq(kHz)"));
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_rcvd"), Qt::Horizontal, tr ("Rcvd"));
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);
}
@ -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_rcvd", exchange_received);
set_value_maybe_null (record, "band", m_->configuration_->bands ()->find (frequency));
auto ok = m_->insertRecord (-1, record);
if (ok)
if (m_->isDirty ())
{
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;
}
@ -136,7 +145,7 @@ void CabrilloLog::reset ()
SQL_error_check (*m_, &QSqlTableModel::removeRows, 0, m_->rowCount (), QModelIndex {});
transaction.submit ();
m_->select (); // to refresh views
m_->setEditStrategy (QSqlTableModel::OnRowChange);
m_->setEditStrategy (QSqlTableModel::OnFieldChange);
}
}

View File

@ -4,7 +4,8 @@
#include <QVariant>
#include <QList>
#include <QBrush>
#include <QFont>
#include <QColor>
#include <QFont>
#include <QMap>
#include <QVector>
#include <QDataStream>
@ -160,7 +161,10 @@ QVariant DecodeHighlightingModel::data (const QModelIndex& index, int role) cons
result = item.enabled_ ? Qt::Checked : Qt::Unchecked;
break;
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;
case Qt::ForegroundRole:
if (Qt::NoBrush != item.foreground_.style ())

View File

@ -43,7 +43,7 @@ FoxLog::impl::impl ()
SQL_error_check (dupe_query_, &QSqlQuery::prepare,
"SELECT COUNT(*) FROM fox_log WHERE call = :call AND band = :band");
setEditStrategy (QSqlTableModel::OnRowChange);
setEditStrategy (QSqlTableModel::OnFieldChange);
setTable ("fox_log");
setHeaderData (fieldIndex ("when"), Qt::Horizontal, tr ("Date & Time(UTC)"));
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_rcvd"), Qt::Horizontal, tr ("Rcvd"));
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);
}
@ -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_rcvd", report_received);
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);
if (ok)
{
m_->select (); // to refresh views
ok = transaction.submit (false);
}
m_->setEditStrategy (QSqlTableModel::OnFieldChange);
return ok;
}
@ -126,6 +139,6 @@ void FoxLog::reset ()
SQL_error_check (*m_, &QSqlTableModel::removeRows, 0, m_->rowCount (), QModelIndex {});
transaction.submit ();
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}
, m_ {this, settings_key, settings, configuration}
{
// ensure view scrolls to latest new row
connect (&m_->model_, &QAbstractItemModel::rowsInserted, [this] (QModelIndex const& /*parent*/, int /*first*/, int /*last*/) {
if (m_->log_view_) m_->log_view_->scrollToBottom ();
});
// this attempt to scroll to the last new record doesn't work, some
// sort of issue with model indexes and optimized DB fetches. For
// 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 ()
@ -102,23 +115,27 @@ void AbstractLogWindow::set_log_view (QTableView * log_view)
SettingsGroup g {m_->settings_, m_->settings_key_};
restoreGeometry (m_->settings_->value ("window/geometry").toByteArray ());
m_->log_view_ = log_view;
m_->log_view_->setContextMenuPolicy (Qt::ActionsContextMenu);
m_->log_view_->setAlternatingRowColors (true);
m_->log_view_->setSelectionBehavior (QAbstractItemView::SelectRows);
m_->log_view_->setSelectionMode (QAbstractItemView::ExtendedSelection);
m_->model_.setSourceModel (m_->log_view_->model ());
m_->log_view_->setModel (&m_->model_);
m_->log_view_->setColumnHidden (0, true);
set_log_view_font (m_->configuration_->decoded_text_font ());
log_view->setSortingEnabled (true);
log_view->setContextMenuPolicy (Qt::ActionsContextMenu);
log_view->setAlternatingRowColors (true);
log_view->setSelectionBehavior (QAbstractItemView::SelectRows);
log_view->setSelectionMode (QAbstractItemView::ExtendedSelection);
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 ();
horizontal_header->setResizeContentsPrecision (0); // visible region only
horizontal_header->setSectionResizeMode (QHeaderView::ResizeToContents);
horizontal_header->setSectionsMovable (true);
m_->log_view_->verticalHeader ()->setSectionResizeMode (QHeaderView::ResizeToContents);
set_log_view_font (m_->configuration_->decoded_text_font ());
m_->log_view_->scrollToBottom ();
auto vertical_header = log_view->horizontalHeader ();
vertical_header->setResizeContentsPrecision (0); // visible region only
vertical_header->setSectionResizeMode (QHeaderView::ResizeToContents);
// actions
auto delete_action = new QAction {tr ("&Delete ..."), m_->log_view_};
m_->log_view_->insertAction (nullptr, delete_action);
auto delete_action = new QAction {tr ("&Delete ..."), log_view};
log_view->insertAction (nullptr, delete_action);
connect (delete_action, &QAction::triggered, [this] (bool /*checked*/) {
m_->delete_QSOs ();
});
@ -126,8 +143,8 @@ void AbstractLogWindow::set_log_view (QTableView * log_view)
void AbstractLogWindow::set_log_view_font (QFont const& font)
{
// m_->log_view_->setFont (font);
// m_->log_view_->horizontalHeader ()->setFont (font);
// m_->log_view_->verticalHeader ()->setFont (font);
m_->log_view_->setFont (font);
m_->log_view_->horizontalHeader ()->setFont (font);
m_->log_view_->verticalHeader ()->setFont (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);
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 (6, new ForeignKeyDelegate {configuration->bands (), m_->log_model_, 0, 6, this});
m_->ui_.log_table_view->horizontalHeader ()->moveSection (6, 1); // band to first column
m_->ui_.log_table_view->setItemDelegateForColumn (6, new ForeignKeyDelegate {configuration->bands (), 0, this});
auto h_header = m_->ui_.log_table_view->horizontalHeader ();
h_header->moveSection (6, 1); // band to first column
}
CabrilloLogWindow::~CabrilloLogWindow ()

View File

@ -6,31 +6,12 @@
#include "models/DecodeHighlightingModel.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)
: QListView {parent}
{
addAction (&m_->fg_colour_action_);
addAction (&m_->bg_colour_action_);
addAction (&m_->defaults_action_);
connect (&m_->fg_colour_action_, &QAction::triggered, [this] (bool /*checked*/) {
auto * fg_colour_action = new QAction {tr ("&Foreground color ..."), this};
addAction (fg_colour_action);
connect (fg_colour_action, &QAction::triggered, [this] (bool /*checked*/) {
auto const& index = currentIndex ();
auto colour = QColorDialog::getColor (model ()->data (index, Qt::ForegroundRole).value<QBrush> ().color ()
, this
@ -38,10 +19,19 @@ DecodeHighlightingListView::DecodeHighlightingListView (QWidget * parent)
.arg (model ()->data (index).toString ()));
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 colour = QColorDialog::getColor (model ()->data (index, Qt::BackgroundRole).value<QBrush> ().color ()
, this
@ -49,10 +39,19 @@ DecodeHighlightingListView::DecodeHighlightingListView (QWidget * parent)
.arg (model ()->data (index).toString ()));
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 ();
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);
@ -60,10 +59,6 @@ DecodeHighlightingListView::DecodeHighlightingListView (QWidget * parent)
});
}
DecodeHighlightingListView::~DecodeHighlightingListView ()
{
}
QSize DecodeHighlightingListView::sizeHint () const
{
auto item_height = sizeHintForRow (0);

View File

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