Merge branch 'release-2.5.0'

This commit is contained in:
Bill Somerville 2021-07-31 16:28:55 +01:00
commit 119fe4dd4b
No known key found for this signature in database
GPG Key ID: D864B06D1E81618F
58 changed files with 1278 additions and 1113 deletions

View File

@ -26,7 +26,7 @@ if (WIN32)
add_custom_command ( add_custom_command (
OUTPUT ${outfile}.h ${outfile}.cpp OUTPUT ${outfile}.h ${outfile}.cpp
COMMAND ${DUMPCPP_Executable} COMMAND ${DUMPCPP_Executable}
ARGS ${AX_SERVER_options} -o "${outfile}" "${infile}" ARGS ${ax_server_options} -o "${outfile}" "${infile}"
MAIN_DEPENDENCY ${infile} VERBATIM) MAIN_DEPENDENCY ${infile} VERBATIM)
list (APPEND ${outfiles} ${outfile}.cpp) list (APPEND ${outfiles} ${outfile}.cpp)
endforeach() endforeach()

View File

@ -71,7 +71,7 @@ message (STATUS "******************************************************")
include (set_build_type) include (set_build_type)
# RC 0 or omitted is a development build, GA is a General Availability release build # RC 0 or omitted is a development build, GA is a General Availability release build
set_build_type (RC 3) set_build_type (RC 4)
set (wsjtx_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}${BUILD_TYPE_REVISION}") set (wsjtx_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}${BUILD_TYPE_REVISION}")
# #

View File

@ -2735,6 +2735,7 @@ bool Configuration::impl::open_rig (bool force)
ui_->test_CAT_push_button->setStyleSheet ({}); ui_->test_CAT_push_button->setStyleSheet ({});
rig_active_ = true; rig_active_ = true;
LOG_TRACE ("emitting startup_transceiver");
Q_EMIT start_transceiver (++transceiver_command_number_); // start rig on its thread Q_EMIT start_transceiver (++transceiver_command_number_); // start rig on its thread
result = true; result = true;
} }
@ -2782,6 +2783,7 @@ void Configuration::impl::transceiver_frequency (Frequency f)
cached_rig_state_.frequency (apply_calibration (f + current_offset_)); cached_rig_state_.frequency (apply_calibration (f + current_offset_));
// qDebug () << "Configuration::impl::transceiver_frequency: n:" << transceiver_command_number_ + 1 << "f:" << f; // qDebug () << "Configuration::impl::transceiver_frequency: n:" << transceiver_command_number_ + 1 << "f:" << f;
LOG_TRACE ("emitting set_transceiver: requested state:" << cached_rig_state_);
Q_EMIT set_transceiver (cached_rig_state_, ++transceiver_command_number_); Q_EMIT set_transceiver (cached_rig_state_, ++transceiver_command_number_);
} }
@ -2808,6 +2810,7 @@ void Configuration::impl::transceiver_tx_frequency (Frequency f)
} }
// qDebug () << "Configuration::impl::transceiver_tx_frequency: n:" << transceiver_command_number_ + 1 << "f:" << f; // qDebug () << "Configuration::impl::transceiver_tx_frequency: n:" << transceiver_command_number_ + 1 << "f:" << f;
LOG_TRACE ("emitting set_transceiver: requested state:" << cached_rig_state_);
Q_EMIT set_transceiver (cached_rig_state_, ++transceiver_command_number_); Q_EMIT set_transceiver (cached_rig_state_, ++transceiver_command_number_);
} }
} }
@ -2817,6 +2820,7 @@ void Configuration::impl::transceiver_mode (MODE m)
cached_rig_state_.online (true); // we want the rig online cached_rig_state_.online (true); // we want the rig online
cached_rig_state_.mode (m); cached_rig_state_.mode (m);
// qDebug () << "Configuration::impl::transceiver_mode: n:" << transceiver_command_number_ + 1 << "m:" << m; // qDebug () << "Configuration::impl::transceiver_mode: n:" << transceiver_command_number_ + 1 << "m:" << m;
LOG_TRACE ("emitting set_transceiver: requested state:" << cached_rig_state_);
Q_EMIT set_transceiver (cached_rig_state_, ++transceiver_command_number_); Q_EMIT set_transceiver (cached_rig_state_, ++transceiver_command_number_);
} }
@ -2826,6 +2830,7 @@ void Configuration::impl::transceiver_ptt (bool on)
set_cached_mode (); set_cached_mode ();
cached_rig_state_.ptt (on); cached_rig_state_.ptt (on);
// qDebug () << "Configuration::impl::transceiver_ptt: n:" << transceiver_command_number_ + 1 << "on:" << on; // qDebug () << "Configuration::impl::transceiver_ptt: n:" << transceiver_command_number_ + 1 << "on:" << on;
LOG_TRACE ("emitting set_transceiver: requested state:" << cached_rig_state_);
Q_EMIT set_transceiver (cached_rig_state_, ++transceiver_command_number_); Q_EMIT set_transceiver (cached_rig_state_, ++transceiver_command_number_);
} }
@ -2909,6 +2914,7 @@ void Configuration::impl::close_rig ()
if (rig_active_) if (rig_active_)
{ {
ui_->test_CAT_push_button->setStyleSheet ("QPushButton {background-color: red;}"); ui_->test_CAT_push_button->setStyleSheet ("QPushButton {background-color: red;}");
LOG_TRACE ("emitting stop_transceiver");
Q_EMIT stop_transceiver (); Q_EMIT stop_transceiver ();
for (auto const& connection: rig_connections_) for (auto const& connection: rig_connections_)
{ {

View File

@ -6,7 +6,7 @@ you change the name in the Applications folder from WSJT-X to WSJT-X_previous
before proceeding. before proceeding.
I recommend that you follow the installation instructions especially if you I recommend that you follow the installation instructions especially if you
are moving from v2.2 to v2.3 or later, of WSJT-X or you have upgraded macOS. are moving from v2.3 to v2.4 or later, of WSJT-X or you have upgraded macOS.
Double-click on the wsjtx-...-Darwin.dmg file you have downloaded from K1JT's web-site. Double-click on the wsjtx-...-Darwin.dmg file you have downloaded from K1JT's web-site.
@ -25,7 +25,7 @@ change has been made by typing:
sysctl -a | grep sysv.shm sysctl -a | grep sysv.shm
If shmmax is not shown as 52428800 then contact me since WSJT-X will fail to load with If shmmax is not shown as 52428800 then contact me since WSJT-X might fail to load with
an error message: "Unable to create shared memory segment". an error message: "Unable to create shared memory segment".
You can now close the Terminal window. It will not be necessary to repeat this procedure You can now close the Terminal window. It will not be necessary to repeat this procedure
@ -72,7 +72,9 @@ Please email me if you have problems.
--- John G4KLA (g4kla@rmnjmn.co.uk) --- John G4KLA (g4kla@rmnjmn.co.uk)
Addendum: Information about com.wsjtx.sysctl.plist and multiple instances of WSJT-X. Additional Notes:
1. Information about com.wsjtx.sysctl.plist and multiple instances of WSJT-X
WSJT-X makes use of a block of memory which is shared between different parts of WSJT-X makes use of a block of memory which is shared between different parts of
the code. The normal allocation of shared memory on a Mac is insufficient and this the code. The normal allocation of shared memory on a Mac is insufficient and this
@ -87,7 +89,8 @@ simultaneously, the shmall parameter in the com.wsjtx.sysctl.plist file needs to
The shmall parameter determines the amount of shared memory which is allocated in 4096 byte pages The shmall parameter determines the amount of shared memory which is allocated in 4096 byte pages
with 50MB (52428800) required for each instance. The shmall parameter is calculated as: with 50MB (52428800) required for each instance. The shmall parameter is calculated as:
(n * 52428800)/4096 where 'n' is the number of instances required to run simultaneously. (n * 52428800)/4096 where 'n' is the number of instances required to run simultaneously.
Remember to reboot your Mac afterwards. Replace your new version of this file in /Library/LaunchDaemons and remember to reboot your
Mac afterwards.
Note that the shmmax parameter remains unchanged. This is the maximum amount of shared memory that Note that the shmmax parameter remains unchanged. This is the maximum amount of shared memory that
any one instance is allowed to request from the total shared memory allocation and should not any one instance is allowed to request from the total shared memory allocation and should not
@ -96,4 +99,15 @@ be changed.
If two instances of WSJT-X are running, it is likely that you might need additional If two instances of WSJT-X are running, it is likely that you might need additional
audio devices, from two rigs for example. Visit Audio MIDI Setup and create an Aggregate Device audio devices, from two rigs for example. Visit Audio MIDI Setup and create an Aggregate Device
which will allow you to specify more than one interface. I recommend you consult Apple's guide which will allow you to specify more than one interface. I recommend you consult Apple's guide
on combining multiple audio interfaces which is at https://support.apple.com/en-us/HT202000. on combining multiple audio interfaces which is at https://support.apple.com/en-us/HT202000.
2. Preventing WSJT-X from being put into 'sleep' mode (App Nap).
In normal circumstances an application which has not been directly accessed for a while can be
subject to App Nap which means it is suspended until such time as its windows are accessed. If
it is intended that WSJT-X should be submitting continued reports to, for example, PSK Reporter
then reporting will be interrupted. App Nap can be disabled as follows, but first quit WSJT-X:
Open a Terminal window and type: defaults write org.k1jt.wsjtx NSAppSleepDisable -bool YES
If you type: defaults read org.k1jt.wsjtx then the response will be: NSAppSleepDisable = 1;
Close the Terminal window and launch WSJT-X. (If you 'Hide' WSJT-X, this scheme will be suspended.)

20
NEWS
View File

@ -12,6 +12,26 @@
Copyright 2001 - 2021 by Joe Taylor, K1JT. Copyright 2001 - 2021 by Joe Taylor, K1JT.
Release: WSJT-X 2.5.0-rc4
Aug 2, 2021
-------------------------
Remember that the WSJT-X 2.5.0 package includes MAP65 3.0.0. Changes
in the package since WSJT-X 2.5.0-rc3 include the following
enhancements and defect repairs:
MAP65:
- Suppress display of duplicate decodes
- Increase the length of .tf2 & .iq files to 56 s
- Implements an early decoding pass at 52 s
WSJT-X:
- Repair a defect in CALL3.TXT lookups that incorrectly matched
partial calls
- Instructions in macOS ReadMe.txt to suppress App Nap energy saving
- Revised User Guide using FT8 mode for the basic tutorial
- Allow contest and FD operating in Q65 mode
Release: WSJT-X 2.5.0-rc3 Release: WSJT-X 2.5.0-rc3
Jul 5, 2021 Jul 5, 2021
------------------------- -------------------------

View File

@ -42,6 +42,15 @@ namespace Radio
value = v.toDouble (); value = v.toDouble ();
if (ok) *ok = true; if (ok) *ok = true;
} }
if (ok && !*ok)
{
return value;
}
return frequency (value, scale, ok);
}
Frequency frequency (double value, int scale, bool * ok)
{
value *= std::pow (10., scale); value *= std::pow (10., scale);
if (ok) if (ok)
{ {
@ -50,6 +59,10 @@ namespace Radio
value = 0.; value = 0.;
*ok = false; *ok = false;
} }
else
{
*ok = true;
}
} }
return std::llround (value); return std::llround (value);
} }
@ -66,6 +79,15 @@ namespace Radio
value = v.toDouble (); value = v.toDouble ();
if (ok) *ok = true; if (ok) *ok = true;
} }
if (ok && !*ok)
{
return value;
}
return frequency_delta (value, scale, ok);
}
FrequencyDelta frequency_delta (double value, int scale, bool * ok)
{
value *= std::pow (10., scale); value *= std::pow (10., scale);
if (ok) if (ok)
{ {
@ -75,6 +97,10 @@ namespace Radio
value = 0.; value = 0.;
*ok = false; *ok = false;
} }
else
{
*ok = true;
}
} }
return std::llround (value); return std::llround (value);
} }

View File

@ -34,10 +34,12 @@ namespace Radio
// QVariant argument is convertible to double and is assumed to // QVariant argument is convertible to double and is assumed to
// be scaled by (10 ** -scale). // be scaled by (10 ** -scale).
// //
Frequency UDP_EXPORT frequency (QVariant const&, int scale, Frequency UDP_EXPORT frequency (QVariant const&, int scale = 0,
bool * ok = nullptr, QLocale const& = QLocale ()); bool * ok = nullptr, QLocale const& = QLocale ());
FrequencyDelta UDP_EXPORT frequency_delta (QVariant const&, int scale, FrequencyDelta UDP_EXPORT frequency_delta (QVariant const&, int scale = 0,
bool * ok = nullptr, QLocale const& = QLocale ()); bool * ok = nullptr, QLocale const& = QLocale ());
Frequency UDP_EXPORT frequency (double, int scale = 0, bool * ok = nullptr);
FrequencyDelta UDP_EXPORT frequency_delta (double, int scale = 0, bool * ok = nullptr);
// //
// Frequency type formatting // Frequency type formatting

View File

@ -12,6 +12,27 @@
Copyright 2001 - 2021 by Joe Taylor, K1JT. Copyright 2001 - 2021 by Joe Taylor, K1JT.
Release: WSJT-X 2.5.0-rc4
Aug 2, 2021
-------------------------
Remember that the WSJT-X 2.5.0 package includes MAP65 3.0.0. Changes
in the package since WSJT-X 2.5.0-rc3 include the following
enhancements and defect repairs:
MAP65:
- Suppress display of duplicate decodes
- Increase the length of .tf2 & .iq files to 56 s
- Implement an early decoding pass at 52 s
- Clean up the output written to map65_rx.log
WSJT-X:
- Repair a defect in CALL3.TXT lookups that incorrectly matched
partial calls
- Instructions in macOS ReadMe.txt to suppress App Nap energy saving
- Revised User Guide using FT8 mode for the basic tutorial
- Allow contest and FD operating in Q65 mode
Release: WSJT-X 2.5.0-rc3 Release: WSJT-X 2.5.0-rc3
Jul 5, 2021 Jul 5, 2021
------------------------- -------------------------

View File

@ -1128,7 +1128,7 @@ void HamlibTransceiver::do_poll ()
{ {
m_->error_check (rig_get_freq (m_->rig_.data (), RIG_VFO_CURR, &f), tr ("getting current VFO frequency")); m_->error_check (rig_get_freq (m_->rig_.data (), RIG_VFO_CURR, &f), tr ("getting current VFO frequency"));
f = std::round (f); f = std::round (f);
CAT_TRACE ("rig_get_freq frequency=" << f); CAT_TRACE ("rig_get_freq frequency=" << Radio::frequency (f));
update_rx_frequency (f); update_rx_frequency (f);
} }

View File

@ -96,11 +96,11 @@ void OmniRigTransceiver::register_transceivers (logger_type *,
}; };
} }
OmniRigTransceiver::OmniRigTransceiver (logger_type * logger, OmniRigTransceiver::OmniRigTransceiver (logger_type * the_logger,
std::unique_ptr<TransceiverBase> wrapped, std::unique_ptr<TransceiverBase> wrapped,
RigNumber n, TransceiverFactory::PTTMethod ptt_type, RigNumber n, TransceiverFactory::PTTMethod ptt_type,
QString const& ptt_port, QObject * parent) QString const& ptt_port, QObject * parent)
: TransceiverBase {logger, parent} : TransceiverBase {the_logger, parent}
, wrapped_ {std::move (wrapped)} , wrapped_ {std::move (wrapped)}
, use_for_ptt_ {TransceiverFactory::PTT_method_CAT == ptt_type || ("CAT" == ptt_port && (TransceiverFactory::PTT_method_RTS == ptt_type || TransceiverFactory::PTT_method_DTR == ptt_type))} , use_for_ptt_ {TransceiverFactory::PTT_method_CAT == ptt_type || ("CAT" == ptt_port && (TransceiverFactory::PTT_method_RTS == ptt_type || TransceiverFactory::PTT_method_DTR == ptt_type))}
, ptt_type_ {ptt_type} , ptt_type_ {ptt_type}
@ -111,173 +111,131 @@ OmniRigTransceiver::OmniRigTransceiver (logger_type * logger,
, reversed_ {false} , reversed_ {false}
{ {
CoInitializeEx (nullptr, 0 /*COINIT_APARTMENTTHREADED*/); // required because Qt only does this for GUI thread CoInitializeEx (nullptr, 0 /*COINIT_APARTMENTTHREADED*/); // required because Qt only does this for GUI thread
CAT_TRACE ("constructed");
} }
OmniRigTransceiver::~OmniRigTransceiver () OmniRigTransceiver::~OmniRigTransceiver ()
{ {
CAT_TRACE ("destroying");
CoUninitialize (); CoUninitialize ();
} }
// returns false on time out
bool OmniRigTransceiver::await_notification_with_timeout (int timeout)
{
QEventLoop el;
connect (this, &OmniRigTransceiver::notified, &el, [&el] () {el.exit (1);});
QTimer::singleShot (timeout, Qt::CoarseTimer, &el, [&el] () {el.exit (0);});
return 1 == el.exec (); // wait for notify or timer
}
int OmniRigTransceiver::do_start () int OmniRigTransceiver::do_start ()
{ {
CAT_TRACE ("starting"); CAT_TRACE ("starting");
try
if (wrapped_) wrapped_->start (0);
omni_rig_.reset (new OmniRig::OmniRigX {this});
if (omni_rig_->isNull ())
{ {
CAT_ERROR ("failed to start COM server"); if (wrapped_) wrapped_->start (0);
throw_qstring (tr ("Failed to start OmniRig COM server"));
}
// COM/OLE exceptions get signaled omni_rig_.reset (new OmniRig::OmniRigX {this});
connect (&*omni_rig_, SIGNAL (exception (int, QString, QString, QString)), this, SLOT (handle_COM_exception (int, QString, QString, QString))); if (omni_rig_->isNull ())
{
// IOmniRigXEvent interface signals CAT_ERROR ("failed to start COM server");
connect (&*omni_rig_, SIGNAL (VisibleChange ()), this, SLOT (handle_visible_change ())); throw_qstring (tr ("Failed to start OmniRig COM server"));
connect (&*omni_rig_, SIGNAL (RigTypeChange (int)), this, SLOT (handle_rig_type_change (int))); }
connect (&*omni_rig_, SIGNAL (StatusChange (int)), this, SLOT (handle_status_change (int)));
connect (&*omni_rig_, SIGNAL (ParamsChange (int, int)), this, SLOT (handle_params_change (int, int)));
connect (&*omni_rig_
, SIGNAL (CustomReply (int, QVariant const&, QVariant const&))
, this, SLOT (handle_custom_reply (int, QVariant const&, QVariant const&)));
CAT_INFO ("OmniRig s/w version: " << omni_rig_->SoftwareVersion ()
<< "i/f version: " << omni_rig_->InterfaceVersion ());
// fetch the interface of the RigX CoClass and instantiate a proxy object
switch (rig_number_)
{
case One: rig_.reset (new OmniRig::RigX (omni_rig_->Rig1 ())); break;
case Two: rig_.reset (new OmniRig::RigX (omni_rig_->Rig2 ())); break;
}
Q_ASSERT (rig_);
Q_ASSERT (!rig_->isNull ());
// COM/OLE exceptions get signaled
connect (&*rig_, SIGNAL (exception (int, QString, QString, QString)), this, SLOT (handle_COM_exception (int, QString, QString, QString)));
offline_timer_.reset (new QTimer); // instantiate here as
// constructor runs in wrong
// thread
offline_timer_->setSingleShot (true);
connect (offline_timer_.data (), &QTimer::timeout, [this] () {offline ("Rig went offline");});
if (use_for_ptt_ && (TransceiverFactory::PTT_method_DTR == ptt_type_ || TransceiverFactory::PTT_method_RTS == ptt_type_))
{
// fetch the interface for the serial port if we need it for PTT
port_.reset (new OmniRig::PortBits (rig_->PortBits ()));
Q_ASSERT (port_);
Q_ASSERT (!port_->isNull ());
// COM/OLE exceptions get signaled // COM/OLE exceptions get signaled
connect (&*port_, SIGNAL (exception (int, QString, QString, QString)), this, SLOT (handle_COM_exception (int, QString, QString, QString))); connect (&*omni_rig_, SIGNAL (exception (int, QString, QString, QString)), this, SLOT (handle_COM_exception (int, QString, QString, QString)));
CAT_TRACE ("OmniRig RTS state: " << port_->Rts ()); // IOmniRigXEvent interface signals
connect (&*omni_rig_, SIGNAL (VisibleChange ()), this, SLOT (handle_visible_change ()));
connect (&*omni_rig_, SIGNAL (RigTypeChange (int)), this, SLOT (handle_rig_type_change (int)));
connect (&*omni_rig_, SIGNAL (StatusChange (int)), this, SLOT (handle_status_change (int)));
connect (&*omni_rig_, SIGNAL (ParamsChange (int, int)), this, SLOT (handle_params_change (int, int)));
connect (&*omni_rig_
, SIGNAL (CustomReply (int, QVariant const&, QVariant const&))
, this, SLOT (handle_custom_reply (int, QVariant const&, QVariant const&)));
// remove locking because it doesn't seem to work properly CAT_INFO ("OmniRig s/w version: " << static_cast<quint16> (omni_rig_->SoftwareVersion () >> 16)
// if (!port_->Lock ()) // try to take exclusive use of the OmniRig serial port for PTT << '.' << static_cast<quint16> (omni_rig_->SoftwareVersion () & 0xffff)
// { << " i/f version: " << static_cast<int> (omni_rig_->InterfaceVersion () >> 8 & 0xff)
// CAT_WARNING ("Failed to get exclusive use of serial port for PTT from OmniRig"); << '.' << static_cast<int> (omni_rig_->InterfaceVersion () && 0xff));
// }
// start off so we don't accidentally key the radio // fetch the interface of the RigX CoClass and instantiate a proxy object
if (TransceiverFactory::PTT_method_DTR == ptt_type_) switch (rig_number_)
{ {
port_->SetDtr (false); case One: rig_.reset (new OmniRig::RigX (omni_rig_->Rig1 ())); break;
case Two: rig_.reset (new OmniRig::RigX (omni_rig_->Rig2 ())); break;
} }
else // RTS
{
port_->SetRts (false);
}
}
rig_type_ = rig_->RigType (); Q_ASSERT (rig_);
readable_params_ = rig_->ReadableParams (); Q_ASSERT (!rig_->isNull ());
writable_params_ = rig_->WriteableParams ();
CAT_INFO (QString {"OmniRig initial rig type: %1 readable params=0x%2 writable params=0x%3 for rig %4"} // COM/OLE exceptions get signaled
.arg (rig_type_) connect (&*rig_, SIGNAL (exception (int, QString, QString, QString)), this, SLOT (handle_COM_exception (int, QString, QString, QString)));
.arg (readable_params_, 8, 16, QChar ('0'))
.arg (writable_params_, 8, 16, QChar ('0')) offline_timer_.reset (new QTimer); // instantiate here as constructor runs in wrong thread
.arg (rig_number_)); offline_timer_->setSingleShot (true);
for (int i = 0; i < 5; ++i) connect (offline_timer_.data (), &QTimer::timeout, [this] () {offline ("Rig went offline");});
{
if (OmniRig::ST_ONLINE == rig_->Status ()) for (int i = 0; i < 5; ++i)
{ {
break; // leave some time for Omni-Rig to do its first poll
QThread::msleep (250);
if (OmniRig::ST_ONLINE == rig_->Status ())
{
break;
}
} }
await_notification_with_timeout (1000);
} if (OmniRig::ST_ONLINE != rig_->Status ())
if (OmniRig::ST_ONLINE != rig_->Status ()) {
{ CAT_ERROR ("rig not online");
throw_qstring ("OmniRig: " + rig_->StatusStr ()); throw_qstring ("OmniRig: " + rig_->StatusStr ());
} }
QThread::msleep (500); // leave some time for Omni-Rig to get
// the rig status for the 1st. time if (use_for_ptt_ && (TransceiverFactory::PTT_method_DTR == ptt_type_ || TransceiverFactory::PTT_method_RTS == ptt_type_))
auto f = rig_->GetRxFrequency (); {
for (int i = 0; (f == 0) && (i < 5); ++i) // fetch the interface for the serial port if we need it for PTT
{ port_.reset (new OmniRig::PortBits (rig_->PortBits ()));
await_notification_with_timeout (1000);
f = rig_->GetRxFrequency (); Q_ASSERT (port_);
} Q_ASSERT (!port_->isNull ());
update_rx_frequency (f);
int resolution {0}; // COM/OLE exceptions get signaled
if (OmniRig::PM_UNKNOWN == rig_->Vfo () connect (&*port_, SIGNAL (exception (int, QString, QString, QString)), this, SLOT (handle_COM_exception (int, QString, QString, QString)));
&& (writable_params_ & (OmniRig::PM_VFOA | OmniRig::PM_VFOB))
== (OmniRig::PM_VFOA | OmniRig::PM_VFOB)) CAT_TRACE ("OmniRig RTS state: " << port_->Rts ());
{
// start with VFO A (probably MAIN) on rigs that we // remove locking because it doesn't seem to work properly
// can't query VFO but can set explicitly // if (!port_->Lock ()) // try to take exclusive use of the OmniRig serial port for PTT
rig_->SetVfo (OmniRig::PM_VFOA); // {
} // CAT_WARNING ("Failed to get exclusive use of serial port for PTT from OmniRig");
f = state ().frequency (); // }
if (f % 10) return resolution; // 1Hz resolution
auto test_frequency = f - f % 100 + 55; // start off so we don't accidentally key the radio
if (OmniRig::PM_FREQ & writable_params_) if (TransceiverFactory::PTT_method_DTR == ptt_type_)
{ {
rig_->SetFreq (test_frequency); port_->SetDtr (false);
} }
else if (reversed_ && (OmniRig::PM_FREQB & writable_params_)) else // RTS
{ {
rig_->SetFreqB (test_frequency); port_->SetRts (false);
} }
else if (!reversed_ && (OmniRig::PM_FREQA & writable_params_)) }
{
rig_->SetFreqA (test_frequency); rig_type_ = rig_->RigType ();
} readable_params_ = rig_->ReadableParams ();
else writable_params_ = rig_->WriteableParams ();
{
throw_qstring (tr ("OmniRig: don't know how to set rig frequency")); CAT_INFO (QString {"OmniRig initial rig type: %1 readable params=0x%2 writable params=0x%3 for rig %4"}
} .arg (rig_type_)
if (!await_notification_with_timeout (1000)) .arg (readable_params_, 8, 16, QChar ('0'))
{ .arg (writable_params_, 8, 16, QChar ('0'))
CAT_ERROR ("do_start 1: wait timed out"); .arg (rig_number_));
throw_qstring (tr ("OmniRig: timeout waiting for update from rig")); update_rx_frequency (rig_->GetRxFrequency ());
} int resolution {0};
switch (rig_->GetRxFrequency () - test_frequency) if (OmniRig::PM_UNKNOWN == rig_->Vfo ()
{ && (writable_params_ & (OmniRig::PM_VFOA | OmniRig::PM_VFOB))
case -5: resolution = -1; break; // 10Hz truncated == (OmniRig::PM_VFOA | OmniRig::PM_VFOB))
case 5: resolution = 1; break; // 10Hz rounded {
case -15: resolution = -2; break; // 20Hz truncated // start with VFO A (probably MAIN) on rigs that we
case -55: resolution = -2; break; // 100Hz truncated // can't query VFO but can set explicitly
case 45: resolution = 2; break; // 100Hz rounded rig_->SetVfo (OmniRig::PM_VFOA);
} }
if (1 == resolution) // may be 20Hz rounded auto f = state ().frequency ();
{ if (f % 10) return resolution; // 1Hz resolution
test_frequency = f - f % 100 + 51; auto test_frequency = f - f % 100 + 55;
if (OmniRig::PM_FREQ & writable_params_) if (OmniRig::PM_FREQ & writable_params_)
{ {
rig_->SetFreq (test_frequency); rig_->SetFreq (test_frequency);
@ -290,34 +248,65 @@ int OmniRigTransceiver::do_start ()
{ {
rig_->SetFreqA (test_frequency); rig_->SetFreqA (test_frequency);
} }
if (!await_notification_with_timeout (2000)) else
{ {
CAT_ERROR ("do_start 2: wait timed out"); throw_qstring (tr ("OmniRig: don't know how to set rig frequency"));
throw_qstring (tr ("OmniRig: timeout waiting for update from rig"));
} }
if (9 == rig_->GetRxFrequency () - test_frequency) switch (rig_->GetRxFrequency () - test_frequency)
{ {
resolution = 2; // 20Hz rounded case -5: resolution = -1; break; // 10Hz truncated
case 5: resolution = 1; break; // 10Hz rounded
case -15: resolution = -2; break; // 20Hz truncated
case -55: resolution = -2; break; // 100Hz truncated
case 45: resolution = 2; break; // 100Hz rounded
} }
if (1 == resolution) // may be 20Hz rounded
{
test_frequency = f - f % 100 + 51;
if (OmniRig::PM_FREQ & writable_params_)
{
rig_->SetFreq (test_frequency);
}
else if (reversed_ && (OmniRig::PM_FREQB & writable_params_))
{
rig_->SetFreqB (test_frequency);
}
else if (!reversed_ && (OmniRig::PM_FREQA & writable_params_))
{
rig_->SetFreqA (test_frequency);
}
if (9 == rig_->GetRxFrequency () - test_frequency)
{
resolution = 2; // 20Hz rounded
}
}
if (OmniRig::PM_FREQ & writable_params_)
{
rig_->SetFreq (f);
}
else if (reversed_ && (OmniRig::PM_FREQB & writable_params_))
{
rig_->SetFreqB (f);
}
else if (!reversed_ && (OmniRig::PM_FREQA & writable_params_))
{
rig_->SetFreqA (f);
}
update_rx_frequency (f);
CAT_TRACE ("started");
return resolution;
} }
if (OmniRig::PM_FREQ & writable_params_) catch (...)
{ {
rig_->SetFreq (f); CAT_TRACE ("start threw exception");
throw;
} }
else if (reversed_ && (OmniRig::PM_FREQB & writable_params_))
{
rig_->SetFreqB (f);
}
else if (!reversed_ && (OmniRig::PM_FREQA & writable_params_))
{
rig_->SetFreqA (f);
}
update_rx_frequency (f);
return resolution;
} }
void OmniRigTransceiver::do_stop () void OmniRigTransceiver::do_stop ()
{ {
CAT_TRACE ("stopping");
QThread::msleep (200); // leave some time for pending QThread::msleep (200); // leave some time for pending
// commands at the server end // commands at the server end
@ -337,6 +326,7 @@ void OmniRigTransceiver::do_stop ()
{ {
rig_->clear (); rig_->clear ();
rig_.reset (); rig_.reset ();
CAT_TRACE ("rig_ reset");
} }
omni_rig_->clear (); omni_rig_->clear ();
omni_rig_.reset (); omni_rig_.reset ();
@ -396,7 +386,6 @@ void OmniRigTransceiver::handle_status_change (int rig_number)
else else
{ {
offline_timer_->stop (); // good to go again offline_timer_->stop (); // good to go again
Q_EMIT notified ();
} }
// else // else
// { // {
@ -467,7 +456,6 @@ void OmniRigTransceiver::handle_params_change (int rig_number, int params)
if (params & OmniRig::PM_FREQ) if (params & OmniRig::PM_FREQ)
{ {
CAT_TRACE ("FREQ");
need_frequency = true; need_frequency = true;
} }
if (params & OmniRig::PM_FREQA) if (params & OmniRig::PM_FREQA)
@ -653,7 +641,6 @@ void OmniRigTransceiver::handle_params_change (int rig_number, int params)
} }
CAT_TRACE ("OmniRig params change: state after:" << state ()); CAT_TRACE ("OmniRig params change: state after:" << state ());
} }
Q_EMIT notified ();
} }
void OmniRigTransceiver::handle_custom_reply (int rig_number, QVariant const& command, QVariant const& reply) void OmniRigTransceiver::handle_custom_reply (int rig_number, QVariant const& command, QVariant const& reply)
@ -710,7 +697,7 @@ void OmniRigTransceiver::do_ptt (bool on)
void OmniRigTransceiver::do_frequency (Frequency f, MODE m, bool /*no_ignore*/) void OmniRigTransceiver::do_frequency (Frequency f, MODE m, bool /*no_ignore*/)
{ {
CAT_TRACE (f << state ()); CAT_TRACE (f << ' ' << state ());
if (!rig_ || rig_->isNull ()) return; if (!rig_ || rig_->isNull ()) return;
if (UNK != m) if (UNK != m)
{ {
@ -739,7 +726,7 @@ void OmniRigTransceiver::do_frequency (Frequency f, MODE m, bool /*no_ignore*/)
void OmniRigTransceiver::do_tx_frequency (Frequency tx, MODE m, bool /*no_ignore*/) void OmniRigTransceiver::do_tx_frequency (Frequency tx, MODE m, bool /*no_ignore*/)
{ {
CAT_TRACE (tx << state ()); CAT_TRACE (tx << ' ' << state ());
if (!rig_ || rig_->isNull ()) return; if (!rig_ || rig_->isNull ()) return;
bool split {tx != 0}; bool split {tx != 0};
if (split) if (split)
@ -804,7 +791,7 @@ void OmniRigTransceiver::do_tx_frequency (Frequency tx, MODE m, bool /*no_ignore
void OmniRigTransceiver::do_mode (MODE mode) void OmniRigTransceiver::do_mode (MODE mode)
{ {
CAT_TRACE (mode << state ()); CAT_TRACE (mode << ' ' << state ());
if (!rig_ || rig_->isNull ()) return; if (!rig_ || rig_->isNull ()) return;
// TODO: G4WJS OmniRig doesn't seem to have any capability of tracking/setting VFO B mode // TODO: G4WJS OmniRig doesn't seem to have any capability of tracking/setting VFO B mode
auto mapped = map_mode (mode); auto mapped = map_mode (mode);

View File

@ -44,9 +44,6 @@ public:
void do_ptt (bool on) override; void do_ptt (bool on) override;
private: private:
bool await_notification_with_timeout (int timeout);
Q_SIGNAL void notified () const;
// Q_SLOT void timeout_check ();
Q_SLOT void handle_COM_exception (int, QString, QString, QString); Q_SLOT void handle_COM_exception (int, QString, QString, QString);
Q_SLOT void handle_visible_change (); Q_SLOT void handle_visible_change ();
Q_SLOT void handle_rig_type_change (int rig_number); Q_SLOT void handle_rig_type_change (int rig_number);

View File

@ -23,6 +23,12 @@ QDebug operator << (QDebug d, Transceiver::TransceiverState const& s)
} }
#endif #endif
std::ostream& operator << (std::ostream& os, Transceiver::MODE m)
{
auto const& mo = Transceiver::staticMetaObject; \
return os << mo.enumerator (mo.indexOfEnumerator ("MODE")).valueToKey (static_cast<int> (m)); \
}
std::ostream& operator << (std::ostream& os, Transceiver::TransceiverState const& s) std::ostream& operator << (std::ostream& os, Transceiver::TransceiverState const& s)
{ {
return os return os

View File

@ -169,6 +169,7 @@ Q_DECLARE_METATYPE (Transceiver::TransceiverState);
QDebug operator << (QDebug, Transceiver::TransceiverState const&); QDebug operator << (QDebug, Transceiver::TransceiverState const&);
#endif #endif
std::ostream& operator << (std::ostream&, Transceiver::MODE);
std::ostream& operator << (std::ostream&, Transceiver::TransceiverState const&); std::ostream& operator << (std::ostream&, Transceiver::TransceiverState const&);
ENUM_QDATASTREAM_OPS_DECL (Transceiver, MODE); ENUM_QDATASTREAM_OPS_DECL (Transceiver, MODE);

View File

@ -16,6 +16,8 @@ namespace
void TransceiverBase::start (unsigned sequence_number) noexcept void TransceiverBase::start (unsigned sequence_number) noexcept
{ {
CAT_TRACE ("#: " << sequence_number);
QString message; QString message;
try try
{ {
@ -26,10 +28,12 @@ void TransceiverBase::start (unsigned sequence_number) noexcept
} }
catch (std::exception const& e) catch (std::exception const& e)
{ {
CAT_TRACE ("#: " << sequence_number << " what: " << e.what ());
message = e.what (); message = e.what ();
} }
catch (...) catch (...)
{ {
CAT_TRACE ("#: " << sequence_number);
message = unexpected; message = unexpected;
} }
if (!message.isEmpty ()) if (!message.isEmpty ())
@ -41,7 +45,7 @@ void TransceiverBase::start (unsigned sequence_number) noexcept
void TransceiverBase::set (TransceiverState const& s, void TransceiverBase::set (TransceiverState const& s,
unsigned sequence_number) noexcept unsigned sequence_number) noexcept
{ {
CAT_TRACE ("#: " << sequence_number << " " << s); CAT_TRACE ("#: " << s);
QString message; QString message;
try try
@ -119,10 +123,12 @@ void TransceiverBase::set (TransceiverState const& s,
} }
catch (std::exception const& e) catch (std::exception const& e)
{ {
CAT_TRACE ("#: " << sequence_number << " what: " << e.what ());
message = e.what (); message = e.what ();
} }
catch (...) catch (...)
{ {
CAT_TRACE ("#: " << sequence_number << " " << sequence_number);
message = unexpected; message = unexpected;
} }
if (!message.isEmpty ()) if (!message.isEmpty ())
@ -133,6 +139,7 @@ void TransceiverBase::set (TransceiverState const& s,
void TransceiverBase::startup () void TransceiverBase::startup ()
{ {
CAT_TRACE ("startup");
QString message; QString message;
try try
{ {
@ -144,10 +151,12 @@ void TransceiverBase::startup ()
} }
catch (std::exception const& e) catch (std::exception const& e)
{ {
CAT_TRACE ("startup" << " what: " << e.what ());
message = e.what (); message = e.what ();
} }
catch (...) catch (...)
{ {
CAT_TRACE ("startup");
message = unexpected; message = unexpected;
} }
if (!message.isEmpty ()) if (!message.isEmpty ())
@ -158,6 +167,7 @@ void TransceiverBase::startup ()
void TransceiverBase::shutdown () void TransceiverBase::shutdown ()
{ {
CAT_TRACE ("shutdown");
may_update u {this}; may_update u {this};
if (requested_.online ()) if (requested_.online ())
{ {
@ -177,6 +187,7 @@ void TransceiverBase::shutdown ()
} }
catch (...) catch (...)
{ {
CAT_TRACE ("shutdown");
// don't care about exceptions // don't care about exceptions
} }
} }
@ -186,6 +197,7 @@ void TransceiverBase::shutdown ()
void TransceiverBase::stop () noexcept void TransceiverBase::stop () noexcept
{ {
CAT_TRACE ("stop");
QString message; QString message;
try try
{ {
@ -193,10 +205,12 @@ void TransceiverBase::stop () noexcept
} }
catch (std::exception const& e) catch (std::exception const& e)
{ {
CAT_TRACE ("stop" << " what: " << e.what ());
message = e.what (); message = e.what ();
} }
catch (...) catch (...)
{ {
CAT_TRACE ("stop");
message = unexpected; message = unexpected;
} }
if (!message.isEmpty ()) if (!message.isEmpty ())
@ -211,6 +225,7 @@ void TransceiverBase::stop () noexcept
void TransceiverBase::update_rx_frequency (Frequency rx) void TransceiverBase::update_rx_frequency (Frequency rx)
{ {
CAT_TRACE ("frequency: " << rx);
if (rx) if (rx)
{ {
actual_.frequency (rx); actual_.frequency (rx);
@ -220,28 +235,35 @@ void TransceiverBase::update_rx_frequency (Frequency rx)
void TransceiverBase::update_other_frequency (Frequency tx) void TransceiverBase::update_other_frequency (Frequency tx)
{ {
CAT_TRACE ("frequency: " << tx);
actual_.tx_frequency (tx); actual_.tx_frequency (tx);
} }
void TransceiverBase::update_split (bool state) void TransceiverBase::update_split (bool state)
{ {
CAT_TRACE ("state: " << state);
actual_.split (state); actual_.split (state);
} }
void TransceiverBase::update_mode (MODE m) void TransceiverBase::update_mode (MODE m)
{ {
CAT_TRACE ("mode: " << m);
actual_.mode (m); actual_.mode (m);
requested_.mode (m); // track rig changes requested_.mode (m); // track rig changes
} }
void TransceiverBase::update_PTT (bool state) void TransceiverBase::update_PTT (bool state)
{ {
CAT_TRACE ("state: " << state);
actual_.ptt (state); actual_.ptt (state);
} }
void TransceiverBase::update_complete (bool force_signal) void TransceiverBase::update_complete (bool force_signal)
{ {
if ((do_pre_update () && actual_ != last_) || force_signal) CAT_TRACE ("force signal: " << force_signal);
if ((do_pre_update ()
&& actual_ != last_)
|| force_signal)
{ {
Q_EMIT update (actual_, last_sequence_number_); Q_EMIT update (actual_, last_sequence_number_);
last_ = actual_; last_ = actual_;
@ -250,6 +272,7 @@ void TransceiverBase::update_complete (bool force_signal)
void TransceiverBase::offline (QString const& reason) void TransceiverBase::offline (QString const& reason)
{ {
CAT_TRACE ("reason: " << reason);
Q_EMIT failure (reason); Q_EMIT failure (reason);
try try
{ {
@ -257,6 +280,7 @@ void TransceiverBase::offline (QString const& reason)
} }
catch (...) catch (...)
{ {
CAT_TRACE ("reason: " << reason);
// don't care // don't care
} }
} }

1185
cty.dat

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,6 @@ JT4 11101000000011000011000000000000000000
JT4/VHF 11111001001011011011110000000000000000 JT4/VHF 11111001001011011011110000000000000000
JT9 11101000000011100001000000000000100000 JT9 11101000000011100001000000000000100000
JT9/VHF 11111010100011111001000000000000000000 JT9/VHF 11111010100011111001000000000000000000
JT9+JT65 11101000000111100001000000000000100000
JT65 11101000000011100001000000000000100000 JT65 11101000000011100001000000000000100000
JT65/VHF 11111001000011011010110001000000000000 JT65/VHF 11111001000011011010110001000000000000
Q65 11111101011011010011100000010000000011 Q65 11111101011011010011100000010000000011

View File

@ -49,12 +49,11 @@ set (UG_SRCS
system-requirements.adoc system-requirements.adoc
transceiver-setup.adoc transceiver-setup.adoc
tutorial-example1.adoc tutorial-example1.adoc
tutorial-example2.adoc
tutorial-example3.adoc tutorial-example3.adoc
tutorial-example4.adoc tutorial-example4.adoc
tutorial-example5.adoc tutorial-example5.adoc
tutorial-example6.adoc tutorial-example6.adoc
tutorial-main-window.adoc tutorial-download-samples.adoc
tutorial-wide-graph-settings.adoc tutorial-wide-graph-settings.adoc
utilities.adoc utilities.adoc
vhf-features.adoc vhf-features.adoc
@ -63,7 +62,6 @@ set (UG_SRCS
) )
set (UG_IMGS set (UG_IMGS
images/130610_2343-wav-80.png
images/AstroData_2.png images/AstroData_2.png
images/Astronomical_data.png images/Astronomical_data.png
images/auto-seq.png images/auto-seq.png
@ -72,7 +70,6 @@ set (UG_IMGS
images/colors.png images/colors.png
images/config-menu.png images/config-menu.png
images/decode-menu.png images/decode-menu.png
images/decodes.png
images/download_samples.png images/download_samples.png
images/echo_144.png images/echo_144.png
images/EME_Deep_0.png images/EME_Deep_0.png

View File

@ -1,11 +1,9 @@
// Status=edited // Status=edited
The following controls appear at the bottom of the Wide Graph window. The following controls appear at the bottom of the Wide Graph window.
Decoding occurs only in the displayed frequency range; otherwise, with Decoding occurs only in the displayed frequency range; otherwise,
the exceptions of *Start NNN Hz* and of *JT65 nnnn JT9* when operating controls on the Wide Graph window have no effect on the decoding
in JT9+JT65 mode, controls on the Wide Graph window have no effect on process.
the decoding process.
image::wide-graph-controls.png[align="center",alt="Wide Graph Controls"] image::wide-graph-controls.png[align="center",alt="Wide Graph Controls"]
- *Bins/Pixel* controls the displayed frequency resolution. Set this - *Bins/Pixel* controls the displayed frequency resolution. Set this
@ -13,11 +11,6 @@ value to 1 for the highest possible resolution, or to higher numbers
to compress the spectral display. Normal operation with a convenient to compress the spectral display. Normal operation with a convenient
window size works well at 2 to 8 bins per pixel. window size works well at 2 to 8 bins per pixel.
- *JT65 nnnn JT9* sets the dividing point (blue marker) for wide-band
decoding of JT65 and JT9 signals in *JT9+JT65* mode. The decoder
looks for JT65 signals everywhere, but JT9 signals only above this
frequency. This setting is stored separately for each band.
- *Start nnn Hz* sets the low-frequency starting point of the - *Start nnn Hz* sets the low-frequency starting point of the
waterfall frequency scale. waterfall frequency scale.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 171 KiB

View File

@ -1,5 +1,13 @@
=== Documentation Conventions === Documentation Conventions
We include screen shots that illustrate many of the settings and
features of _WSJT-X_. Keep in mind that _WSJT-X_ is a multi-platform
application: the detailed appearance of windows and user controls may
be significantly different in Windows, Linux, or macOS environments.
The underlying functionality is the same on all operating systems,
however. Where desirable we call special attention to important
platform differences.
In this manual the following icons call attention to particular types In this manual the following icons call attention to particular types
of information: of information:

View File

@ -39,7 +39,7 @@ image::RadioTab.png[align="center",alt="Radio Tab"]
+ +
NOTE: A special value of *USB* is available for custom USB devices 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 like those used by some SDR kits. This is not the same as the virtual
serial port provided by USB connected transceivers and CAT serial port provided by USB connected transceivers and CAT
interfaces, for those use the COM or serial port name that interfaces, for those use the COM or serial port name that
refers to them. refers to them.

View File

@ -0,0 +1,16 @@
// Status=review
[[DOWNLOAD_SAMPLES]]
=== Download Samples
The following steps will download sample audio Wave files that were originally recorded
by WSJT-X. These files can be read in and processed by WSJT-X to simulate realtime
operation.
- Select *Download samples...* from the *Help* menu.
- Download some or all of the available sample files using checkboxes
on the screen shown below. For this tutorial you will need at least
the FT8 files.
image::download_samples.png[width=400,align="center",alt="Download Samples"]

View File

@ -1,121 +0,0 @@
// Status=review
.Main Window:
- Select *JT9+JT65* on the *Mode* menu.
- Toggle the *Tx mode* button to read *Tx JT65 #*, and set the Tx and Rx
frequencies to 1718 Hz.
- Double-click on *Erase* to clear both text windows.
.Wide Graph Settings:
- *Bins/Pixel* = 7
- *JT65 .... JT9* = 2500
- Adjust the width of the Wide Graph window so that the upper
frequency limit is approximately 4000 Hz.
.Open a Wave File:
- Select *File | Open* and navigate to +...\save\samples\JT9+JT65\130610_2343.wav+.
The waterfall should look something like this:
//.130610_2343.wav Decode
[[X14]]
image::130610_2343-wav-80.png[align="left",alt="Wide Graph Decode 130610_2343"]
The position of the blue marker on the waterfall scale is
set by the spinner control *JT65 nnnn JT9*, where nnnn is an audio
frequency in Hz. In *JT9+JT65* mode the program will automatically
decode JT9 signals only above this frequency. JT65 signals will be
decoded over the full displayed frequency range.
JT9 signals appear in the *Cumulative* spectrum as nearly rectangular
shapes about 16 Hz wide. They have no clearly visible sync tone like
the one at the low-frequency edge of all JT65 signals. By convention
the nominal frequency of both JT9 and JT65 signals is taken to be that
of the lowest tone, at the left edge of its spectrum.
This sample file contains 17 decodable signals — nine in JT65 mode
(flagged with the character # in the decoded text windows), and eight
in JT9 mode (flagged with @). On multi-core computers the decoders
for JT9 and JT65 modes run simultaneously, so their results will be
interspersed. The *Band Activity* window contains all decodes (you
might need to scroll back in the window to see some of them). A
signal at the frequency specified by the green marker is given
decoding priority, and its message is displayed also in the *Rx
Frequency* window.
[[FigDecodes]]
image::decodes.png[align="center"]
- Confirm that mouse-click behavior is similar to that described
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
signal and the Rx and Tx frequency markers on the waterfall scale
resize themselves accordingly. When selecting a JT65 signal, click on
the sync tone at its left edge.
- Double-click on the waterfall near 815 Hz: a JT65 message
originating from W7VP will be decoded and appear in the *Rx Frequency*
window. Between the *UTC* and *Freq* columns on the decoded text line
you will find *dB*, the measured signal-to-noise ratio, and *DT*, the
signal's time offset in seconds relative to your computer clock.
[width="80%",align="center",cols="^10,2*^8,2*^10,54",options="header"]
|===
|UTC|dB|DT|Freq|Mode|Message
|+2343+|+-7+|+0.3+|+815+|+#+|+KK4DSD W7VP -16+
|===
- Double-click on the waterfall at 3196 Hz. The program will decode a
JT9 message from IZ0MIT:
[width="80%",align="center",cols="^10,2*^8,2*^10,54",options="header"]
|===
|UTC|dB|DT|Freq|Mode|Message
|+2343+|+-8+|+0.3+|+3196+|+@+|+WB8QPG IZ0MIT -11+
|===
- Scroll back in the *Band Activity* window and double-click on the
message `CQ DL7ACA JO40`. The program will set *Tx mode* to JT65 and
the Rx frequency to that of DL7ACA, 975 Hz. If you hold down the
*Ctrl* key, both Rx and Tx frequencies will be moved. If you had
checked *Double-click on call sets Tx Enable* on the *Setup* menu, the
program would configure itself to begin a transmission and start a QSO
with DL7ACA.
- Hold *Ctrl* down and double-click on the decoded JT65 message `CQ
TA4A KM37`. The program will set Tx mode to JT9 and the Rx and Tx
frequencies to 3567 Hz. The program is now configured properly for a
JT9 QSO with TA4A.
.Reopen the First Sample File:
- Select *File | Open* and navigate to `...\save\samples\130418_1742.wav`.
Taking full advantage of the wide-band, dual-mode capability of
_WSJT-X_ requires a receiver bandwidth of at least 4 kHz. These
data were recorded with a much narrower Rx bandwidth, roughly 200 to
2400 Hz. If you have no Rx filter wider than about 2.7 kHz, you will
be using data like this. For best viewing, adjust *Bins/Pixel* and the
width of the Wide Graph so that only the active part of the spectrum
shows, say 200 to 2400 Hz. Re-open the example file after any change of
*Bins/Pixel* or Wide Graph width, to refresh the waterfall.
The signals in this file are all JT9 signals. To decode them
automatically in *JT9+JT65* mode youll need to move the *JT65 nnnn JT9*
delimiter down to 1000 Hz or less.
.Waterfall Controls
Now is a good time to experiment with the *Start* control and the
sliders controlling gain and zero-point of the waterfall and spectrum
plots. *Start* determines the frequency displayed at the left side of
the waterfall scale. Sliders set the baseline level and gain for the
waterfall and the several types of spectra. Good starting values
should be close to mid-scale. You might want to uncheck *Flatten*
when adjusting the sliders. Re-open the wave file after each change,
to see the new results.

View File

@ -1,27 +1,92 @@
// Status=review // Status=review
.Main Window: .Main Window:
- Select *FT8* on the *Mode* menu. - Click the *Stop* button on the main window to halt any data acquisition.
- Select *FT8* from the *Mode* menu and *Deep* from the *Decode* menu.
- Double-click on *Erase* to clear both text windows. - Double-click on *Erase* to clear both text windows.
.Wide Graph Settings:
- *Bins/Pixel* = 5, *Start* = 100 Hz, *N Avg* = 2
- Adjust the width of the Wide Graph window so that the upper
frequency limit is approximately 3300 Hz.
.Open a Wave File: .Open a Wave File:
- Select *File | Open* and navigate to - Select *File | Open log directory* and navigate to
+...\save\samples\FT8\181201_180245.wav+. The waterfall and Band +...\save\samples\FT8\210703_133430.wav+. The waterfall and Band
Activity window should look something like the following screen shots. Activity/Rx Frequency windows should look something like the following screen shots:
(This recording was made during the "FT8 Roundup" contest, so most
transmissions happen to be using *RTTY Roundup* message formats.) - You may want to pretend you are K1JT
by entering that callsign temporarily as *My Call* on the
*Settings | General* tab. Your results should then be identical to
those shown in the screen shot below. Don't forget to change *My Call*
back to your own call when you are done!
[[X15]] [[X15]]
image::FT8_waterfall.png[align="left",alt="Wide Graph Decode 170709_135615"] image::FT8_waterfall.png[align="left",alt="Wide Graph Decode 210703_133430"]
image::ft8_decodes.png[align="left"] image::ft8_decodes.png[align="left"]
.Decoding Overview
Decoding takes place at the end of a receive sequence. With *Decode* set
to *Deep*, three decoding passes will be done and the *Decode* button on the
mainwindow will illuminate three times, once for each pass.
The first decoding attempt in each decoding pass is done at the selected Rx frequency,
indicated by the U-shaped green marker on the waterfall frequency
scale. All decodes appear in the left (*Band Activity*) window. The right
(*Rx Frequency*) text window displays any decodes obtained at the current
Rx frequency along with any decodes addressed to *My Call* (K1JT in this case).
The red marker on the waterfall scale indicates your
Tx frequency.
Twenty one FT8 signals are decoded from the example file. The number
of decodes is shown in a box at the bottom of the main window.
When this file was recorded HA5WA was finishing a QSO with K1JT, and
his 73 message is shown in red because it is addressed to *My Call* (in this case K1JT).
By default, lines containing `CQ`
are highlighted in green, and lines with *My Call* (K1JT)
in red. Notice that K1JT has two callers; HA0DU and EA3AGB.
[[X13]]
.Decoding Controls
To gain some feeling for controls frequently used when making QSOs,
try double-clicking with the mouse on the decoded text lines and on the
waterfall spectral display. You should be able to confirm the
following behavior:
- Double-click on one of the decoded *CQ* messages highlighted in
green. These actions produce the following results:
** Callsign and locator of the station calling CQ are copied to the *DX
Call* and *DX Grid* entry fields.
** Messages are generated for a standard minimal QSO.
** The *Tx even* box is checked or cleared appropriately, so that you
will transmit in the proper (odd or even) minutes.
** The Rx frequency marker is moved to the frequency of the CQing
station.
** You can modify the double-click behavior by holding down the
*Shift* key to move only the Tx frequency or the *Ctrl* key to move
both Rx and Tx frequencies. (On a Mac computer, use the *command* key
instead of *Ctrl*).
** In addition, if *Double-click on call sets Tx enable* is checked on the
*Settings | General* tab then *Enable Tx* will be activated
so that a transmission will start automatically at the proper time.
+
NOTE: You can prevent your Tx frequency from being changed by checking the
box *Hold Tx Freq*.
- Double-click on the decoded message `K1JT HA0DU KN07`, highlighted
in red. Results will be similar to those in the previous step. The Tx
frequency (red marker) is not moved unless *Shift* or *Ctrl* is held
down. Messages highlighted in red are usually in response to your own
CQ or from a tail-ender, and you probably want your Tx frequency to
stay where it was.
- Click with the mouse anywhere on the waterfall display. The green Rx - Click with the mouse anywhere on the waterfall display. The green Rx
frequency marker will jump to your selected frequency, and the Rx frequency marker will jump to your selected frequency, and the Rx
frequency control on the main window will be updated accordingly. frequency control on the main window will be updated accordingly.
@ -38,11 +103,12 @@ things just described and also invokes the decoder in a small range
around the Rx frequency. To decode a particular signal, double-click around the Rx frequency. To decode a particular signal, double-click
near the left edge of its waterfall trace. near the left edge of its waterfall trace.
- Now double-click on any of the lines of decoded text in the Band - Ctrl-double-click on a signal to set both Rx and Tx frequencies and
Activity window. Any line will show the same behavior, setting decode at the new frequency.
Rx frequency to that of the selected message and leaving Tx frequency
unchanged. To change both Rx and Tx frequencies, hold *Ctrl* down - Click *Erase* to clear the right window.
when double-clicking.
- Double-click *Erase* to clear both text windows.
TIP: To avoid QRM from competing callers, it is usually best TIP: To avoid QRM from competing callers, it is usually best
to answer a CQ on a different frequency from that of the CQing to answer a CQ on a different frequency from that of the CQing
@ -53,6 +119,11 @@ box *Hold Tx Freq*.
TIP: Keyboard shortcuts *Shift+F11* and *Shift+F12* provide an easy TIP: Keyboard shortcuts *Shift+F11* and *Shift+F12* provide an easy
way to move your Tx frequency down or up in 60 Hz steps. way to move your Tx frequency down or up in 60 Hz steps.
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
the spinner controls or use the mouse wheel.
TIP: An online {ft8_tips} by ZL2IFB offers many additional tips on TIP: An online {ft8_tips} by ZL2IFB offers many additional tips on
operating procedures. operating procedures.

View File

@ -1,25 +0,0 @@
// Status=review
- Click the *Stop* button on the main window to halt any data acquisition.
- Select *JT9* from the *Mode* menu and *Deep* from the *Decode* menu.
- 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
the spinner controls or use the mouse wheel.
[[DOWNLOAD_SAMPLES]]
=== Download Samples
- Select *Download samples...* from the *Help* menu.
- Download some or all of the available sample files using checkboxes
on the screen shown below. For this tutorial you will need at least
the JT9 and JT9+JT65 files.
image::download_samples.png[align="center",alt="Downlod Samples"]

View File

@ -1,13 +1,46 @@
// Status=review // Status=review
- *Bins/Pixel* = 4 The WSJT-X Wide Graph window displays the frequency spectrum of the received audio. Usually, the
- *Start* = 200 Hz upper portion of the window shows a waterfall plot of the frequency spectrum (a spectrogram) and
- *N Avg* = 5 a line plot of the current or average spectrum. Controls at the bottom of the window are used to
- *Palette* = Digipan set up the displayed audio frequency range, color palette, and scaling of the spectrum displays.
- *Flatten* = checked A control on the bottom right of the Wide Graph (displayed as *Spec nn%*) lets you control
- Select *Cumulative* for data display the vertical fraction of the window occupied by the spectrum line plot.
- *Gain* and *Zero* sliders for waterfall and spectrum set near midscale It is important to set appropriate lower and upper
- *Spec* = 25% audio frequency limits for the Wide Graph because these limits define the FT8 decoder's search window.
For this tutorial, the limits will be set to cover 100-3300 Hz:
- Set *Start* = 100 Hz.
- Set *Bins/Pixel* = 5. Smaller/larger values make the Wide Graph cover a smaller/larger
frequency range.
- Use the mouse to grab the left or right edge of the *Wide Graph*, and - Use the mouse to grab the left or right edge of the *Wide Graph*, and
adjust its width so that the upper frequency limit is about 2400 Hz. adjust its width so that the upper frequency limit is about 3300 Hz.
The *N Avg* setting controls how many spectra are averaged to produce each line in the spectrogram.
Smaller values make the spectrogram update more frequently, resulting in signals being more spread
out in the vertical (time) direction.
On the other hand, larger values make it easier to detect very weak signals:
- Set *N Avg* = 2.
The *Palette* setting controls the color scheme used for the spectrogram:
- Set *Palette* = Fldigi
When *Flatten* is checked, WSJT-X attempts to correct for slope or curvature in the receiver's
passband shape.
- *Flatten* = checked
The line plot can be set to display the current (un-averaged) spectrum or the cumulative (averaged)
spectrum:
- Select *Cumulative* for data display
- Set the *Gain* and *Zero* sliders for the waterfall and spectrum to near midscale
The *Spec nn%* setting determines what fraction of the vertical extent of the Wide Graph will
be used for the line plot of the spectrum. Setting *Spec* to 0 will eliminate the line plot and
a setting of 100 will eliminate the spectrogram and show only the line plot:
- Set *Spec* = 50%

View File

@ -141,31 +141,20 @@ include::transceiver-setup.adoc[]
== Basic Operating Tutorial == Basic Operating Tutorial
This section introduces the basic user controls and program behavior This section introduces the basic user controls and program behavior
of _WSJT-X_, with particular emphasis on the JT9, JT65, and FT8 modes. of _WSJT-X_, with particular emphasis on the FT8 mode.
We suggest that new users should go through the full HF-oriented We suggest that new users should go through the full HF-oriented
tutorial, preferably while at your radio. Note that as of late 2018, tutorial, preferably while at your radio.
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 Subsequent sections cover additional details on <<MAKE_QSOS,Making
QSOs>>, <<WSPR,WSPR mode>> and <<VHF_AND_UP,VHF+ Features>>. QSOs>>, <<WSPR,WSPR mode>> and <<VHF_AND_UP,VHF+ Features>>.
[[TUT_MAIN]] [[TUT_SAMPLES]]
=== Main Window Settings include::tutorial-download-samples.adoc[]
include::tutorial-main-window.adoc[]
[[TUT_WIDE_GRAPH]] [[TUT_WIDE_GRAPH]]
=== Wide Graph Settings === Wide Graph Settings
include::tutorial-wide-graph-settings.adoc[] include::tutorial-wide-graph-settings.adoc[]
[[TUT_EX1]]
=== JT9
include::tutorial-example1.adoc[]
[[TUT_EX2]]
=== JT9+JT65
include::tutorial-example2.adoc[]
[[TUT_EX3]] [[TUT_EX3]]
=== FT8 === FT8
include::tutorial-example3.adoc[] include::tutorial-example3.adoc[]

View File

@ -1118,7 +1118,7 @@ subroutine pack77_1(nwords,w,i3,n3,c77)
irpt=irpt+35 irpt=irpt+35
else if(c2.eq.'R+' .or. c2.eq.'R-') then else if(c2.eq.'R+' .or. c2.eq.'R-') then
ir=1 ir=1
read(w(nwords)(2:),*) irpt read(w(nwords)(2:),*,err=900) irpt
if(irpt.ge.-50 .and. irpt.le.-31) irpt=irpt+101 if(irpt.ge.-50 .and. irpt.le.-31) irpt=irpt+101
irpt=irpt+35 irpt=irpt+35
else if(trim(w(nwords)).eq.'RRR') then else if(trim(w(nwords)).eq.'RRR') then
@ -1274,6 +1274,7 @@ subroutine pack77_4(nwords,w,i3,n3,c77)
if(call_1(1:1).eq.'<') call_1=w(1)(2:len(trim(w(1)))-1) if(call_1(1:1).eq.'<') call_1=w(1)(2:len(trim(w(1)))-1)
call_2=w(2) call_2=w(2)
if(call_2(1:1).eq.'<') call_2=w(2)(2:len(trim(w(2)))-1) if(call_2(1:1).eq.'<') call_2=w(2)(2:len(trim(w(2)))-1)
if(call_1(1:1).ne.'<' .and. call_2(1:1).ne.'<') goto 900
call chkcall(call_1,bcall_1,ok1) call chkcall(call_1,bcall_1,ok1)
call chkcall(call_2,bcall_2,ok2) call chkcall(call_2,bcall_2,ok2)
icq=0 icq=0

View File

@ -55,7 +55,8 @@ subroutine jt9a()
if(.not.ok) call abort if(.not.ok) call abort
call flush(6) call flush(6)
call timer('decoder ',0) call timer('decoder ',0)
if(local_params%nmode.eq.8 .and. local_params%ndiskdat) then if(local_params%nmode.eq.8 .and. local_params%ndiskdat .and. &
.not. local_params%nagain) then
! Early decoding pass, FT8 only, when wsjtx reads from disk ! Early decoding pass, FT8 only, when wsjtx reads from disk
nearly=41 nearly=41
local_params%nzhsym=nearly local_params%nzhsym=nearly

View File

@ -157,12 +157,17 @@ subroutine q65_dec0(iavg,nutc,iwave,ntrperiod,nfqso,ntol,ndepth,lclearave, &
! Try list decoding via "Deep Likelihood". ! Try list decoding via "Deep Likelihood".
call timer('ccf_85 ',0) call timer('ccf_85 ',0)
! Try to synchronize using all 85 symbols ! Try to synchronize using all 85 symbols
call q65_ccf_85(s1,iz,jz,nfqso,ia,ia2,ipk,jpk,f0,xdt,imsg_best,ccf1) call q65_ccf_85(s1,iz,jz,nfqso,ia,ia2,ipk,jpk,f0,xdt,imsg_best, &
better,ccf1)
call timer('ccf_85 ',1) call timer('ccf_85 ',1)
call timer('list_dec',0) if(better.ge.1.10 .or. mode_q65.ge.8) then
call q65_dec_q3(s1,iz,jz,s3,LL,ipk,jpk,snr2,dat4,idec,decoded) call timer('list_dec',0)
call timer('list_dec',1) call q65_dec_q3(s1,iz,jz,s3,LL,ipk,jpk,snr2,dat4,idec,decoded)
call timer('list_dec',1)
! if(idec.ge.0) write(70,3070) idec,mode_q65,better,trim(decoded)
!3070 format(i3,i5,f8.2,2x,a)
endif
! If idec=3 we have a q3 decode. Continue to compute sync curve for plotting. ! If idec=3 we have a q3 decode. Continue to compute sync curve for plotting.
endif endif
@ -359,18 +364,21 @@ subroutine q65_dec_q012(s3,LL,snr2,dat4,idec,decoded)
100 return 100 return
end subroutine q65_dec_q012 end subroutine q65_dec_q012
subroutine q65_ccf_85(s1,iz,jz,nfqso,ia,ia2,ipk,jpk,f0,xdt,imsg_best,ccf1) subroutine q65_ccf_85(s1,iz,jz,nfqso,ia,ia2,ipk,jpk,f0,xdt,imsg_best, &
better,ccf1)
! Attempt synchronization using all 85 symbols, in advance of an ! Attempt synchronization using all 85 symbols, in advance of an
! attempt at q3 decoding. Return ccf1 for the "red sync curve". ! attempt at q3 decoding. Return ccf1 for the "red sync curve".
real s1(iz,jz) real s1(iz,jz)
real, allocatable :: ccf(:,:) !CCF(freq,lag) real, allocatable :: ccf(:,:) !CCF(freq,lag)
real, allocatable :: best(:) !best(imsg) -- for checking 2nd best
real ccf1(-ia2:ia2) real ccf1(-ia2:ia2)
integer ijpk(2) integer ijpk(2)
integer itone(85) integer itone(85)
allocate(ccf(-ia2:ia2,-53:214)) allocate(ccf(-ia2:ia2,-53:214))
allocate(best(ncw))
ipk=0 ipk=0
jpk=0 jpk=0
ccf_best=0. ccf_best=0.
@ -415,8 +423,15 @@ subroutine q65_ccf_85(s1,iz,jz,nfqso,ia,ia2,ipk,jpk,f0,xdt,imsg_best,ccf1)
imsg_best=imsg imsg_best=imsg
ccf1=ccf(:,jpk) ccf1=ccf(:,jpk)
endif endif
best(imsg)=ccfmax
enddo ! imsg enddo ! imsg
deallocate(ccf) deallocate(ccf)
better=0.
if(imsg_best.gt.0) then
best(imsg_best)=0.
better=ccf_best/maxval(best)
endif
return return
end subroutine q65_ccf_85 end subroutine q65_ccf_85

View File

@ -34,11 +34,14 @@ extern struct { //This is "common/datcom/..." in Fortran
int nfast; //No longer used int nfast; //No longer used
int nsave; //Number of s3(64,63) spectra saved int nsave; //Number of s3(64,63) spectra saved
int max_drift; //Maximum Q65 drift: units symbol_rate/TxT int max_drift; //Maximum Q65 drift: units symbol_rate/TxT
int nhsym; //Number of available JT65 half-symbols
char mycall[12]; char mycall[12];
char mygrid[6]; char mygrid[6];
char hiscall[12]; char hiscall[12];
char hisgrid[6]; char hisgrid[6];
char datetime[20]; char datetime[20];
int junk1; //Used to test extent of copy to shared memory
int junk2;
} datcom_; } datcom_;
} }

View File

@ -8,7 +8,7 @@ extern qint16 id[4*60*96000];
void getfile(QString fname, bool xpol, int dbDgrd) void getfile(QString fname, bool xpol, int dbDgrd)
{ {
int npts=2*52*96000; int npts=2*56*96000;
if(xpol) npts=2*npts; if(xpol) npts=2*npts;
// Degrade S/N by dbDgrd dB -- for tests only!! // Degrade S/N by dbDgrd dB -- for tests only!!
@ -56,7 +56,7 @@ void getfile(QString fname, bool xpol, int dbDgrd)
void savetf2(QString fname, bool xpol) void savetf2(QString fname, bool xpol)
{ {
int npts=2*52*96000; int npts=2*56*96000;
if(xpol) npts=2*npts; if(xpol) npts=2*npts;
qint16* buf=(qint16*)malloc(2*npts); qint16* buf=(qint16*)malloc(2*npts);

View File

@ -136,8 +136,8 @@ target_link_libraries (m65 m65impl ${FFTW3_LIBRARIES})
add_executable (mapsim mapsim.f90) add_executable (mapsim mapsim.f90)
target_link_libraries (mapsim m65impl ${FFTW3_LIBRARIES}) target_link_libraries (mapsim m65impl ${FFTW3_LIBRARIES})
add_executable (synctest synctest.f90) #add_executable (synctest synctest.f90)
target_link_libraries (synctest m65impl ${FFTW3_LIBRARIES}) #target_link_libraries (synctest m65impl ${FFTW3_LIBRARIES})
if (WIN32) if (WIN32)
install ( install (

View File

@ -6,18 +6,21 @@ subroutine decode0(dd,ss,savg,nstandalone)
real*4 dd(4,NSMAX),ss(4,322,NFFT),savg(4,NFFT) real*4 dd(4,NSMAX),ss(4,322,NFFT),savg(4,NFFT)
real*8 fcenter real*8 fcenter
integer hist(0:32768) integer hist(0:32768)
logical ldecoded
character mycall*12,hiscall*12,mygrid*6,hisgrid*6,datetime*20 character mycall*12,hiscall*12,mygrid*6,hisgrid*6,datetime*20
character mycall0*12,hiscall0*12,hisgrid0*6 character mycall0*12,hiscall0*12,hisgrid0*6
common/npar/fcenter,nutc,idphi,mousedf,mousefqso,nagain, & common/npar/fcenter,nutc,idphi,mousedf,mousefqso,nagain, &
ndepth,ndiskdat,neme,newdat,nfa,nfb,nfcal,nfshift, & ndepth,ndiskdat,neme,newdat,nfa,nfb,nfcal,nfshift, &
mcall3,nkeep,ntol,nxant,nrxlog,nfsample,nxpol,nmode, & mcall3,nkeep,ntol,nxant,nrxlog,nfsample,nxpol,nmode, &
nfast,nsave,max_drift,mycall,mygrid,hiscall,hisgrid,datetime nfast,nsave,max_drift,nhsym,mycall,mygrid,hiscall,hisgrid,datetime
common/early/nhsym1,nhsym2,ldecoded(32768)
data neme0/-99/,mcall3b/1/ data neme0/-99/,mcall3b/1/
save save
call sec0(0,tquick)
call timer('decode0 ',0) call timer('decode0 ',0)
if(newdat.ne.0) then if(newdat.ne.0) then
nz=52*96000 nz=96000*nhsym/5.3833
hist=0 hist=0
do i=1,nz do i=1,nz
j1=min(abs(dd(1,i)),32768.0) j1=min(abs(dd(1,i)),32768.0)
@ -36,7 +39,6 @@ subroutine decode0(dd,ss,savg,nstandalone)
enddo enddo
10 rmsdd=1.5*i 10 rmsdd=1.5*i
endif endif
nhsym=279
ndphi=0 ndphi=0
if(iand(nrxlog,8).ne.0) ndphi=1 if(iand(nrxlog,8).ne.0) ndphi=1
@ -52,12 +54,16 @@ subroutine decode0(dd,ss,savg,nstandalone)
call map65a(dd,ss,savg,newdat,nutc,fcenter,ntol,idphi,nfa,nfb, & call map65a(dd,ss,savg,newdat,nutc,fcenter,ntol,idphi,nfa,nfb, &
mousedf,mousefqso,nagain,ndecdone,nfshift,ndphi,max_drift, & mousedf,mousefqso,nagain,ndecdone,nfshift,ndphi,max_drift, &
nfcal,nkeep,mcall3b,nsum,nsave,nxant,mycall,mygrid, & nfcal,nkeep,mcall3b,nsum,nsave,nxant,mycall,mygrid, &
neme,ndepth,nstandalone,hiscall,hisgrid,nhsym,nfsample,nxpol,nmode) neme,ndepth,nstandalone,hiscall,hisgrid,nhsym,nfsample, &
ndiskdat,nxpol,nmode)
call timer('map65a ',1) call timer('map65a ',1)
call timer('decode0 ',1) call timer('decode0 ',1)
write(*,1010) nsum,nsave call sec0(1,tdec)
1010 format('<DecodeFinished>',2i4) if(nhsym.eq.nhsym1) write(*,1010) nsum,nsave,nstandalone,nhsym,tdec
1010 format('<EarlyFinished>',3i4,i6,f6.2)
if(nhsym.eq.nhsym2) write(*,1012) nsum,nsave,nstandalone,nhsym,tdec
1012 format('<DecodeFinished>',3i4,i6,f6.2)
flush(6) flush(6)
return return

View File

@ -3,14 +3,15 @@ subroutine display(nkeep,ftol)
parameter (MAXLINES=400,MX=400,MAXCALLS=500) parameter (MAXLINES=400,MX=400,MAXCALLS=500)
integer indx(MAXLINES),indx2(MX) integer indx(MAXLINES),indx2(MX)
character*83 line(MAXLINES),line2(MX),line3(MAXLINES) character*83 line(MAXLINES),line2(MX),line3(MAXLINES)
character out*52,cfreq0*3,livecq*58 character out*52,out0*52,cfreq0*3,livecq*58
character*6 callsign,callsign0 character*6 callsign,callsign0
character*12 freqcall(MAXCALLS) character*12 freqcall(MAXCALLS)
real freqkHz(MAXLINES) real freqkHz(MAXLINES)
integer utc(MAXLINES),utc2(MX),utcz integer utc(MAXLINES),utc2(MX),utcz
real*8 f0 real*8 f0
rewind 26 out0=' '
rewind(26)
do i=1,MAXLINES do i=1,MAXLINES
read(26,1010,end=10) line(i) read(26,1010,end=10) line(i)
@ -45,7 +46,7 @@ subroutine display(nkeep,ftol)
enddo enddo
20 i0=i 20 i0=i
nz=nz-i0+1 nz=nz-i0+1
rewind 26 rewind(26)
if(nz.lt.1) go to 999 if(nz.lt.1) go to 999
do i=1,nz do i=1,nz
j=i+i0-1 j=i+i0-1
@ -132,8 +133,14 @@ subroutine display(nkeep,ftol)
index(livecq,' QRT ').gt.0 .or. index(livecq,' CQV ').gt.0 .or. & index(livecq,' QRT ').gt.0 .or. index(livecq,' CQV ').gt.0 .or. &
index(livecq,' CQH ').gt.0) write(19,1029) livecq index(livecq,' CQH ').gt.0) write(19,1029) livecq
1029 format(a58) 1029 format(a58)
write(*,1030) out !Messages
1030 format('@',a52) ! Suppress listing duplicate (same time, same decoded message)
if(out(14:17).ne.out0(14:17) .or. out(26:50).ne.out0(26:50)) then
write(*,1030) out !Messages
1030 format('@',a52)
out0=out
endif
i1=index(out(26:),' ') i1=index(out(26:),' ')
callsign=out(i1+26:) callsign=out(i1+26:)
i2=index(callsign,' ') i2=index(callsign,' ')

View File

@ -26,21 +26,23 @@ program m65
use timer_module, only: timer use timer_module, only: timer
use timer_impl, only: init_timer, fini_timer use timer_impl, only: init_timer, fini_timer
include 'njunk.f90'
parameter (NFFT=32768) parameter (NFFT=32768)
parameter (NSMAX=60*96000) parameter (NSMAX=60*96000)
parameter (NREAD=2048) parameter (NREAD=2048)
integer*2 i2(NREAD) integer*2 i2(NREAD)
real*8 hsym real*8 hsym
real*4 ssz5a(NFFT) real*4 ssz5a(NFFT)
logical*1 lstrong(0:1023) logical*1 lstrong(0:1023),ldecoded,eof
real*8 fc0,fcenter real*8 fc0,fcenter
character*80 arg,infile character*80 arg,infile
character mycall*12,hiscall*12,mygrid*6,hisgrid*6,datetime*20 character mycall*12,hiscall*12,mygrid*6,hisgrid*6,datetime*20
common/datcom/dd(4,5760000),ss(4,322,NFFT),savg(4,NFFT),fc0,nutc0,junk(37) common/datcom/dd(4,5760000),ss(4,322,NFFT),savg(4,NFFT),fc0,nutc0,junk(NJUNK)
common/npar/fcenter,nutc,idphi,mousedf,mousefqso,nagain, & common/npar/fcenter,nutc,idphi,mousedf,mousefqso,nagain, &
ndepth,ndiskdat,neme,newdat,nfa,nfb,nfcal,nfshift, & ndepth,ndiskdat,neme,newdat,nfa,nfb,nfcal,nfshift, &
mcall3,nkeep,ntol,nxant,nrxlog,nfsample,nxpol,nmode, & mcall3,nkeep,ntol,nxant,nrxlog,nfsample,nxpol,nmode, &
nfast,nsave,max_drift,mycall,mygrid,hiscall,hisgrid,datetime nfast,nsave,max_drift,nhsym,mycall,mygrid,hiscall,hisgrid,datetime
common/early/nhsym1,nhsym2,ldecoded(32768)
nargs=iargc() nargs=iargc()
if(nargs.ne.1 .and. nargs.lt.5) then if(nargs.ne.1 .and. nargs.lt.5) then
@ -52,6 +54,9 @@ program m65
print*,' (Gets data from MAP65, via shared memory region.)' print*,' (Gets data from MAP65, via shared memory region.)'
go to 999 go to 999
endif endif
nstandalone=1
nhsym1=280
nhsym2=302
call getarg(1,arg) call getarg(1,arg)
if(arg(1:2).eq.'-s') then if(arg(1:2).eq.'-s') then
call m65a call m65a
@ -124,9 +129,12 @@ program m65
nch=2 nch=2
if(nxpol.eq.1) nch=4 if(nxpol.eq.1) nch=4
eof=.false.
do irec=1,9999999 do irec=1,9999999
read(10,end=10) i2 if(.not.eof) read(10,end=4) i2
go to 6
4 eof=.true.
6 if(eof) i2=0
do i=1,NREAD,nch do i=1,NREAD,nch
k=k+1 k=k+1
if(k.gt.60*96000) exit if(k.gt.60*96000) exit
@ -156,15 +164,18 @@ program m65
rejecty,pxdb,pydb,ssz5a,nkhz,ihsym,nzap,slimit,lstrong) rejecty,pxdb,pydb,ssz5a,nkhz,ihsym,nzap,slimit,lstrong)
call timer('symspec ',1) call timer('symspec ',1)
nhsym0=nhsym nhsym0=nhsym
nutc=nutc0
if(nhsym.eq.nhsym1) call decode0(dd,ss,savg,nstandalone)
if(nhsym.eq.nhsym2) then
call decode0(dd,ss,savg,nstandalone)
exit
endif
endif endif
enddo ! irec enddo ! irec
10 continue
if(iqadjust.ne.0) write(*,3002) rejectx,rejecty if(iqadjust.ne.0) write(*,3002) rejectx,rejecty
3002 format('Image rejection:',2f7.1,' dB') 3002 format('Image rejection:',2f7.1,' dB')
nutc=nutc0
nstandalone=1
call decode0(dd,ss,savg,nstandalone)
enddo ! ifile enddo ! ifile
call timer('m65 ',1) call timer('m65 ',1)
@ -175,5 +186,10 @@ program m65
print*,infile print*,infile
999 call fini_timer() 999 call fini_timer()
if(arg(1:2).eq.'-s') then
write(21,1999) datetime(:17)
1999 format('Subprocess m65 terminated normally at UTC ',a17)
close(21)
endif
end program m65 end program m65

View File

@ -1,5 +1,5 @@
subroutine m65a subroutine m65a
use timer_module, only: timer use timer_module, only: timer
use timer_impl, only: init_timer !, limtrace use timer_impl, only: init_timer !, limtrace
use, intrinsic :: iso_c_binding, only: C_NULL_CHAR use, intrinsic :: iso_c_binding, only: C_NULL_CHAR
@ -70,27 +70,35 @@ subroutine m65b(m65com,nbytes)
end subroutine m65b end subroutine m65b
subroutine m65c(dd,ss,savg,nparams0) subroutine m65c(dd,ss,savg,nparams0)
include 'njunk.f90'
real*4 dd(4,5760000),ss(4,322,32768),savg(4,32768) real*4 dd(4,5760000),ss(4,322,32768),savg(4,32768)
real*8 fcenter real*8 fcenter
integer nparams0(40),nparams(40) integer nparams0(NJUNK+2),nparams(NJUNK+2)
logical ldecoded
character*12 mycall,hiscall character*12 mycall,hiscall
character*6 mygrid,hisgrid character*6 mygrid,hisgrid
character*20 datetime character*20 datetime
common/npar/fcenter,nutc,idphi,mousedf,mousefqso,nagain, & common/npar/fcenter,nutc,idphi,mousedf,mousefqso,nagain, &
ndepth,ndiskdat,neme,newdat,nfa,nfb,nfcal,nfshift, & ndepth,ndiskdat,neme,newdat,nfa,nfb,nfcal,nfshift, &
mcall3,nkeep,ntol,nxant,nrxlog,nfsample,nxpol,nmode, & mcall3,nkeep,ntol,nxant,nrxlog,nfsample,nxpol,nmode, &
nfast,nsave,max_drift,mycall,mygrid,hiscall,hisgrid,datetime nfast,nsave,max_drift,nhsym,mycall,mygrid,hiscall,hisgrid, &
datetime,junk1,junk2
common/early/nhsym1,nhsym2,ldecoded(32768)
equivalence (nparams,fcenter) equivalence (nparams,fcenter)
nparams=nparams0 !Copy parameters into common/npar/ nparams=nparams0 !Copy parameters into common/npar/
npatience=1 npatience=1
if(iand(nrxlog,1).ne.0) then if(nhsym.eq.nhsym1 .and. iand(nrxlog,1).ne.0) then
write(21,1000) datetime(:17) write(21,1000) datetime(:17)
1000 format(/'UTC Date: 'a17/78('-')) 1000 format(/'UTC Date: 'a17/78('-'))
flush(21) flush(21)
endif endif
if(iand(nrxlog,2).ne.0) rewind 21 if(iand(nrxlog,2).ne.0) rewind(21)
if(iand(nrxlog,4).ne.0) rewind 26 if(iand(nrxlog,4).ne.0) then
if(nhsym.eq.nhsym1) rewind(26)
if(nhsym.eq.nhsym2) backspace(26)
endif
nstandalone=0 nstandalone=0
if(sum(nparams).ne.0) call decode0(dd,ss,savg,nstandalone) if(sum(nparams).ne.0) call decode0(dd,ss,savg,nstandalone)

View File

@ -1,7 +1,8 @@
subroutine map65a(dd,ss,savg,newdat,nutc,fcenter,ntol,idphi,nfa,nfb, & subroutine map65a(dd,ss,savg,newdat,nutc,fcenter,ntol,idphi,nfa,nfb, &
mousedf,mousefqso,nagain,ndecdone,nfshift,ndphi,max_drift, & mousedf,mousefqso,nagain,ndecdone,nfshift,ndphi,max_drift, &
nfcal,nkeep,mcall3b,nsum,nsave,nxant,mycall,mygrid, & nfcal,nkeep,mcall3b,nsum,nsave,nxant,mycall,mygrid, &
neme,ndepth,nstandalone,hiscall,hisgrid,nhsym,nfsample,nxpol,nmode) neme,ndepth,nstandalone,hiscall,hisgrid,nhsym,nfsample, &
ndiskdat,nxpol,nmode)
! Processes timf2 data from Linrad to find and decode JT65 signals. ! Processes timf2 data from Linrad to find and decode JT65 signals.
@ -24,6 +25,7 @@ subroutine map65a(dd,ss,savg,newdat,nutc,fcenter,ntol,idphi,nfa,nfb, &
logical done(MAXMSG) logical done(MAXMSG)
logical xpol,bq65,q65b_called logical xpol,bq65,q65b_called
logical candec(MAX_CANDIDATES) logical candec(MAX_CANDIDATES)
logical ldecoded
character decoded*22,blank*22,cmode*2 character decoded*22,blank*22,cmode*2
real short(3,NFFT) !SNR dt ipol for potential shorthands real short(3,NFFT) !SNR dt ipol for potential shorthands
real qphi(12) real qphi(12)
@ -31,35 +33,44 @@ subroutine map65a(dd,ss,savg,newdat,nutc,fcenter,ntol,idphi,nfa,nfb, &
common/c3com/ mcall3a common/c3com/ mcall3a
common/testcom/ifreq common/testcom/ifreq
common/early/nhsym1,nhsym2,ldecoded(32768)
data blank/' '/,cm/'#'/ data blank/' '/,cm/'#'/
data shmsg0/'ATT','RO ','RRR','73 '/ data shmsg0/'ATT','RO ','RRR','73 '/
data nfile/0/,nutc0/-999/,nid/0/,ip000/1/,ip001/1/,mousefqso0/-999/ data nfile/0/,nutc0/-999/,nid/0/,ip000/1/,ip001/1/,mousefqso0/-999/
save save
call sec0(0,tquick) ! Clean start for Q65 at early decode
if(nhsym.eq.nhsym1 .or. nagain.ne.0) ldecoded=.false.
nkhz_center=nint(1000.0*(fcenter-int(fcenter))) nkhz_center=nint(1000.0*(fcenter-int(fcenter)))
mfa=nfa-nkhz_center+48 mfa=nfa-nkhz_center+48
mfb=nfb-nkhz_center+48 mfb=nfb-nkhz_center+48
mode65=mod(nmode,10) mode65=mod(nmode,10)
if(mode65.eq.3) mode65=4 if(mode65.eq.3) mode65=4
mode_q65=nmode/10 mode_q65=nmode/10
xpol=(nxpol.ne.0)
nts_jt65=2**(mode65-1) !JT65 tone separation factor nts_jt65=2**(mode65-1) !JT65 tone separation factor
nts_q65=2**(mode_q65) !Q65 tone separation factor nts_q65=2**(mode_q65-1) !Q65 tone separation factor
xpol=(nxpol.ne.0)
! No second decode for JT65?
! if(nhsym.eq.nhsym2 .and. (nstandalone.eq.1 .or. ndiskdat.eq.0)) mode65=0
if(nhsym.eq.nhsym2 .and. nagain.eq.0) mode65=0
! print*,'=a',nhsym,nagain,mode65
if(nagain.eq.0) then if(nagain.eq.0) then
call timer('get_cand',0) call timer('get_cand',0)
call get_candidates(ss,savg,xpol,mfa,mfb,nts_jt65,nts_q65,cand,ncand) call get_candidates(ss,savg,xpol,nhsym,mfa,mfb,nts_jt65,nts_q65,cand,ncand)
call timer('get_cand',1) call timer('get_cand',1)
candec=.false. candec=.false.
endif endif
!### !###
! do k=1,ncand ! do k=1,ncand
! freq=cand(k)%f+nkhz_center-48.0-1.27046 ! freq=cand(k)%f+nkhz_center-48.0-1.27046
! write(70,3010) nutc,k,cand(k)%snr,cand(k)%f,freq,cand(k)%xdt, & ! ipk=cand(k)%indx
! cand(k)%ipol,cand(k)%iflip ! write(*,3010) nutc,k,db(cand(k)%snr),freq,cand(k)%xdt, &
!3010 format(i4.4,i5,f10.1,3f10.3,2i3) ! cand(k)%ipol,cand(k)%iflip,ipk,ldecoded(ipk)
!3010 format('=a',i5.4,i5,f8.2,f10.3,f8.2,2i3,i6,L4)
! enddo ! enddo
!### !###
@ -111,7 +122,9 @@ subroutine map65a(dd,ss,savg,newdat,nutc,fcenter,ntol,idphi,nfa,nfb, &
short=0. !Zero the whole short array short=0. !Zero the whole short array
jpz=1 jpz=1
if(xpol) jpz=4 if(xpol) jpz=4
if(mode65.eq.0) go to 50
! First steps for JT65 decoding
do i=ia,ib !Search over freq range do i=ia,ib !Search over freq range
freq=0.001*(i-16385)*df freq=0.001*(i-16385)*df
! Find the local base level for each polarization; update every 10 bins. ! Find the local base level for each polarization; update every 10 bins.
@ -278,8 +291,9 @@ subroutine map65a(dd,ss,savg,newdat,nutc,fcenter,ntol,idphi,nfa,nfb, &
endif endif
enddo !i=ia,ib enddo !i=ia,ib
if(nqd.eq.1) then 50 if(nqd.eq.1) then
nwrite=0 nwrite=0
if(mode65.eq.0) km=0
do k=1,km do k=1,km
decoded=msg(k) decoded=msg(k)
if(decoded.ne.' ') then if(decoded.ne.' ') then
@ -350,7 +364,7 @@ subroutine map65a(dd,ss,savg,newdat,nutc,fcenter,ntol,idphi,nfa,nfb, &
call timer('q65b ',0) call timer('q65b ',0)
call q65b(nutc,nqd,nxant,fcenter,nfcal,nfsample,ikhz,mousedf, & call q65b(nutc,nqd,nxant,fcenter,nfcal,nfsample,ikhz,mousedf, &
ntol,xpol,mycall,mygrid, hiscall,hisgrid,mode_q65,f0,fqso, & ntol,xpol,mycall,mygrid, hiscall,hisgrid,mode_q65,f0,fqso, &
newdat,nagain,max_drift,idec) newdat,nagain,max_drift,nhsym,idec)
call timer('q65b ',1) call timer('q65b ',1)
if(idec.ge.0) candec(icand)=.true. if(idec.ge.0) candec(icand)=.true.
enddo enddo
@ -361,7 +375,7 @@ subroutine map65a(dd,ss,savg,newdat,nutc,fcenter,ntol,idphi,nfa,nfb, &
call timer('q65b ',0) call timer('q65b ',0)
call q65b(nutc,nqd,nxant,fcenter,nfcal,nfsample,ikhz,mousedf, & call q65b(nutc,nqd,nxant,fcenter,nfcal,nfsample,ikhz,mousedf, &
ntol,xpol,mycall,mygrid,hiscall,hisgrid,mode_q65,f0,fqso, & ntol,xpol,mycall,mygrid,hiscall,hisgrid,mode_q65,f0,fqso, &
newdat,nagain,max_drift,idec) newdat,nagain,max_drift,nhsym,idec)
call timer('q65b ',1) call timer('q65b ',1)
endif endif
endif endif
@ -379,15 +393,17 @@ subroutine map65a(dd,ss,savg,newdat,nutc,fcenter,ntol,idphi,nfa,nfb, &
if(ndphi.eq.1 .and.iloop.eq.12) call getdphi(qphi) if(ndphi.eq.1 .and.iloop.eq.12) call getdphi(qphi)
if(nqd.eq.1) then if(nqd.eq.1) then
write(*,1013) nsum,nsave call sec0(1,tdec)
1013 format('<QuickDecodeDone>',2i4) write(*,1013) nsum,nsave,nstandalone,nhsym,tdec
1013 format('<QuickDecodeDone>',3i4,i6,f6.2)
flush(6) flush(6)
call sec0(1,tquick)
open(16,file='tquick.dat',status='unknown',access='append') open(16,file='tquick.dat',status='unknown',access='append')
write(16,1016) nutc,tquick write(16,1016) nutc,tdec
1016 format(i4.4,f7.1) 1016 format(i4.4,f7.1)
close(16) close(16)
endif endif
call sec0(1,tsec0)
if(nhsym.eq.nhsym1 .and. tsec0.gt.3.0) go to 700
if(nqd.eq.1 .and. nagain.eq.1) go to 900 if(nqd.eq.1 .and. nagain.eq.1) go to 900
if(nqd.eq.0 .and. bq65) then if(nqd.eq.0 .and. bq65) then
@ -403,21 +419,19 @@ subroutine map65a(dd,ss,savg,newdat,nutc,fcenter,ntol,idphi,nfa,nfb, &
call timer('q65b ',0) call timer('q65b ',0)
call q65b(nutc,nqd,nxant,fcenter,nfcal,nfsample,ikhz,mousedf,ntol, & call q65b(nutc,nqd,nxant,fcenter,nfcal,nfsample,ikhz,mousedf,ntol, &
xpol,mycall,mygrid,hiscall,hisgrid,mode_q65,f0,fqso,newdat, & xpol,mycall,mygrid,hiscall,hisgrid,mode_q65,f0,fqso,newdat, &
nagain,max_drift,idec) nagain,max_drift,nhsym,idec)
call timer('q65b ',1) call timer('q65b ',1)
if(idec.ge.0) candec(icand)=.true. if(idec.ge.0) candec(icand)=.true.
enddo ! icand enddo ! icand
endif endif
call sec0(1,tsec0)
enddo ! nqd enddo ! nqd
! Trim the list and produce a sorted index and sizes of groups. ! Trim the list and produce a sorted index and sizes of groups.
! (Should trimlist remove all but best SNR for given UTC and message content?) ! (Should trimlist remove all but best SNR for given UTC and message content?)
call trimlist(sig,km,ftol,indx,nsiz,nz) 700 call trimlist(sig,km,ftol,indx,nsiz,nz)
done(1:km)=.false.
do i=1,km
done(i)=.false.
enddo
j=0 j=0
ilatest=-1 ilatest=-1
do n=1,nz do n=1,nz
@ -490,11 +504,8 @@ subroutine map65a(dd,ss,savg,newdat,nutc,fcenter,ntol,idphi,nfa,nfb, &
write(21,1100) f0,ndf,dt,npol,nsync2,nutc,decoded,cp, & write(21,1100) f0,ndf,dt,npol,nsync2,nutc,decoded,cp, &
cmode(1:1),cmode(2:2) cmode(1:1),cmode(2:2)
1100 format(f8.3,i5,f5.1,2i4,i5.4,2x,a22,2x,a1,3x,a1,1x,a1) 1100 format(f8.3,i5,f5.1,2i4,i5.4,2x,a22,2x,a1,3x,a1,1x,a1)
! write(21,1014) f0,ndf,ndf0,ndf1,ndf2,dt,npol,nsync1, &
! nutc,decoded,cp,cmode
endif endif
endif endif
j=j+nsiz(n) j=j+nsiz(n)
enddo !i=1,km enddo !i=1,km

1
map65/libm65/njunk.f90 Normal file
View File

@ -0,0 +1 @@
parameter(NJUNK=40)

View File

@ -1,6 +1,6 @@
subroutine q65b(nutc,nqd,nxant,fcenter,nfcal,nfsample,ikhz,mousedf,ntol,xpol, & subroutine q65b(nutc,nqd,nxant,fcenter,nfcal,nfsample,ikhz,mousedf,ntol,xpol, &
mycall0,mygrid,hiscall0,hisgrid,mode_q65,f0,fqso,newdat,nagain, & mycall0,mygrid,hiscall0,hisgrid,mode_q65,f0,fqso,newdat,nagain, &
max_drift,idec) max_drift,nhsym,idec)
! This routine provides an interface between MAP65 and the Q65 decoder ! This routine provides an interface between MAP65 and the Q65 decoder
! in WSJT-X. All arguments are input data obtained from the MAP65 GUI. ! in WSJT-X. All arguments are input data obtained from the MAP65 GUI.
@ -22,17 +22,20 @@ subroutine q65b(nutc,nqd,nxant,fcenter,nfcal,nfsample,ikhz,mousedf,ntol,xpol, &
integer*2 iwave(60*12000) integer*2 iwave(60*12000)
complex ca(MAXFFT1),cb(MAXFFT1) !FFTs of raw x,y data complex ca(MAXFFT1),cb(MAXFFT1) !FFTs of raw x,y data
complex cx(0:MAXFFT2-1),cy(0:MAXFFT2-1),cz(0:MAXFFT2) complex cx(0:MAXFFT2-1),cy(0:MAXFFT2-1),cz(0:MAXFFT2)
logical xpol logical xpol,ldecoded
integer ipk1(1) integer ipk1(1)
real*8 fcenter,freq0,freq1 real*8 fcenter,freq0,freq1
character*12 mycall0,hiscall0 character*12 mycall0,hiscall0
character*12 mycall,hiscall character*12 mycall,hiscall
character*6 mygrid,hisgrid character*6 mygrid,hisgrid
character*4 grid4 character*4 grid4
character*28 msg00
character*80 line character*80 line
character*80 wsjtx_dir character*80 wsjtx_dir
character*1 cp,cmode*2 character*1 cp,cmode*2
common/cacb/ca,cb common/cacb/ca,cb
common/early/nhsym1,nhsym2,ldecoded(32768)
data nutc00/-1/,msg00/' '/
save save
open(9,file='wsjtx_dir.txt',status='old') open(9,file='wsjtx_dir.txt',status='old')
@ -50,8 +53,8 @@ subroutine q65b(nutc,nqd,nxant,fcenter,nfcal,nfsample,ikhz,mousedf,ntol,xpol, &
ib=nint(ifreq+ntol/df3) ib=nint(ifreq+ntol/df3)
ipk1=maxloc(sync(ia:ib)%ccfmax) ipk1=maxloc(sync(ia:ib)%ccfmax)
ipk=ia+ipk1(1)-1 ipk=ia+ipk1(1)-1
if(ldecoded(ipk)) go to 900
snr1=sync(ipk)%ccfmax snr1=sync(ipk)%ccfmax
ipol=1 ipol=1
if(xpol) ipol=sync(ipk)%ipol if(xpol) ipol=sync(ipk)%ipol
@ -141,6 +144,7 @@ subroutine q65b(nutc,nqd,nxant,fcenter,nfcal,nfsample,ikhz,mousedf,ntol,xpol, &
freq0=MHz + 0.001d0*ikhz freq0=MHz + 0.001d0*ikhz
if(nsnr0.gt.-99) then if(nsnr0.gt.-99) then
ldecoded(ipk)=.true.
nq65df=nint(1000*(0.001*k0*df+nkhz_center-48.0+1.000-1.27046-ikhz))-nfcal nq65df=nint(1000*(0.001*k0*df+nkhz_center-48.0+1.000-1.27046-ikhz))-nfcal
nq65df=nq65df + nfreq0 - 1000 nq65df=nq65df + nfreq0 - 1000
npol=nint(poldeg) npol=nint(poldeg)
@ -163,7 +167,6 @@ subroutine q65b(nutc,nqd,nxant,fcenter,nfcal,nfsample,ikhz,mousedf,ntol,xpol, &
endif endif
! Write to lu 26, for Messages and Band Map windows ! Write to lu 26, for Messages and Band Map windows
cmode=': ' cmode=': '
cmode(2:2)=char(ichar('A') + mode_q65-1) cmode(2:2)=char(ichar('A') + mode_q65-1)
freq1=freq0 + 0.001d0*(ikhz1-ikhz) freq1=freq0 + 0.001d0*(ikhz1-ikhz)
@ -171,9 +174,14 @@ subroutine q65b(nutc,nqd,nxant,fcenter,nfcal,nfsample,ikhz,mousedf,ntol,xpol, &
':',cp,cmode ':',cp,cmode
1014 format(f8.3,i5,3i3,f5.1,i4,i3,i4,i5.4,4x,a22,1x,2a1,2x,a2) 1014 format(f8.3,i5,3i3,f5.1,i4,i3,i4,i5.4,4x,a22,1x,2a1,2x,a2)
! Suppress writing duplicates (same time, same decoded message) to map65_rx.log
if(nutc.ne.nutc00 .or. msg0(1:28).ne.msg00) then
! Write to file map65_rx.log: ! Write to file map65_rx.log:
write(21,1110) freq1,ndf,xdt0,npol,nsnr0,nutc,msg0(1:28),cq0 write(21,1110) freq1,ndf,xdt0,npol,nsnr0,nutc,msg0(1:28),cq0
1110 format(f8.3,i5,f5.1,2i4,i5.4,2x,a28,': A',2x,a3) 1110 format(f8.3,i5,f5.1,2i4,i5.4,2x,a28,': A',2x,a3)
nutc00=nutc
msg00=msg0(1:28)
endif
endif endif
900 close(13) 900 close(13)

View File

@ -2,6 +2,7 @@ subroutine recvpkt(nsam,nblock2,userx_no,k,buf4,buf8,buf16)
! Reformat timf2 data from Linrad and stuff data into r*4 array dd(). ! Reformat timf2 data from Linrad and stuff data into r*4 array dd().
include 'njunk.f90'
parameter (NSMAX=60*96000) !Total sample intervals per minute parameter (NSMAX=60*96000) !Total sample intervals per minute
parameter (NFFT=32768) parameter (NFFT=32768)
integer*1 userx_no integer*1 userx_no
@ -11,7 +12,8 @@ subroutine recvpkt(nsam,nblock2,userx_no,k,buf4,buf8,buf16)
integer*2 jd(4),kd(2),nblock2 integer*2 jd(4),kd(2),nblock2
real*4 xd(4),yd(2) real*4 xd(4),yd(2)
real*8 fcenter real*8 fcenter
common/datcom/dd(4,5760000),ss(4,322,NFFT),savg(4,NFFT),fcenter,nutc,junk(36) common/datcom/dd(4,5760000),ss(4,322,NFFT),savg(4,NFFT),fcenter,nutc, &
junk(NJUNK)
equivalence (kd,d4) equivalence (kd,d4)
equivalence (jd,d8,yd) equivalence (jd,d8,yd)
equivalence (xd,c16) equivalence (xd,c16)

View File

@ -18,11 +18,13 @@ subroutine symspec(k,nxpol,ndiskdat,nb,nbslider,idphi,nfsample, &
! ihsym index number of this half-symbol (1-322) ! ihsym index number of this half-symbol (1-322)
! nzap number of samples zero'ed by noise blanker ! nzap number of samples zero'ed by noise blanker
include 'njunk.f90'
parameter (NSMAX=60*96000) !Total sample intervals per minute parameter (NSMAX=60*96000) !Total sample intervals per minute
parameter (NFFT=32768) !Length of FFTs parameter (NFFT=32768) !Length of FFTs
real*8 ts,hsym real*8 ts,hsym
real*8 fcenter real*8 fcenter
common/datcom/dd(4,5760000),ss(4,322,NFFT),savg(4,NFFT),fcenter,nutc,junk(36) common/datcom/dd(4,5760000),ss(4,322,NFFT),savg(4,NFFT),fcenter,nutc, &
junk(NJUNK)
real*4 ssz5a(NFFT),w(NFFT),w2a(NFFT),w2b(NFFT) real*4 ssz5a(NFFT),w(NFFT),w2a(NFFT),w2b(NFFT)
complex z,zfac complex z,zfac
complex zsumx,zsumy complex zsumx,zsumy

View File

@ -41,7 +41,7 @@ program synctest
call timer('synctest',0) call timer('synctest',0)
call timer('get_cand',0) call timer('get_cand',0)
call get_candidates(ss,savg,.true.,nfa,nfb,nts_jt65,nts_q65,cand,ncand) call get_candidates(ss,savg,302,.true.,nfa,nfb,nts_jt65,nts_q65,cand,ncand)
call timer('get_cand',1) call timer('get_cand',1)
do k=1,ncand do k=1,ncand

View File

@ -7,6 +7,7 @@ module wideband_sync
real :: pol !Polarization angle, degrees real :: pol !Polarization angle, degrees
integer :: ipol !Polarization angle, 1 to 4 ==> 0, 45, 90, 135 deg integer :: ipol !Polarization angle, 1 to 4 ==> 0, 45, 90, 135 deg
integer :: iflip !Sync type: JT65 = +/- 1, Q65 = 0 integer :: iflip !Sync type: JT65 = +/- 1, Q65 = 0
integer :: indx
end type candidate end type candidate
type sync_dat type sync_dat
real :: ccfmax real :: ccfmax
@ -25,25 +26,21 @@ module wideband_sync
contains contains
subroutine get_candidates(ss,savg,xpol,nfa,nfb,nts_jt65,nts_q65,cand,ncand) subroutine get_candidates(ss,savg,xpol,jz,nfa,nfb,nts_jt65,nts_q65,cand,ncand)
! Search symbol spectra ss() over frequency range nfa to nfb (in kHz) for ! Search symbol spectra ss() over frequency range nfa to nfb (in kHz) for
! JT65 and Q65 sync patterns. The nts_* variables are the submode tone ! JT65 and Q65 sync patterns. The nts_* variables are the submode tone
! spacings: 1 2 4 8 16 for A B C D E. Birdies are detected and ! spacings: 1 2 4 8 16 for A B C D E. Birdies are detected and
! excised. Candidates are returned in the structure array cand(). ! excised. Candidates are returned in the structure array cand().
parameter (MAX_PEAKS=300) parameter (MAX_PEAKS=100)
real ss(4,322,NFFT),savg(4,NFFT) real ss(4,322,NFFT),savg(4,NFFT)
real pavg(-20:20) real pavg(-20:20)
integer indx(NFFT) integer indx(NFFT)
logical xpol,skip logical xpol,skip,ldecoded
type(candidate) :: cand(MAX_CANDIDATES) type(candidate) :: cand(MAX_CANDIDATES)
common/early/nhsym1,nhsym2,ldecoded(32768)
do j=322,1,-1 !Find end of data in ss()
if(sum(ss(1,j,1:NFFT)).gt.0.0) exit
enddo
jz=j
call wb_sync(ss,savg,xpol,jz,nfa,nfb) call wb_sync(ss,savg,xpol,jz,nfa,nfb)
tstep=2048.0/11025.0 !0.185760 s: 0.5*tsym_jt65, 0.3096*tsym_q65 tstep=2048.0/11025.0 !0.185760 s: 0.5*tsym_jt65, 0.3096*tsym_q65
@ -87,11 +84,11 @@ subroutine get_candidates(ss,savg,xpol,nfa,nfb,nts_jt65,nts_q65,cand,ncand)
diffhz=1000.0*(f0-cand(m)%f) diffhz=1000.0*(f0-cand(m)%f)
bw=nts_q65*110.0 bw=nts_q65*110.0
if(cand(m)%iflip.ne.0) bw=nts_jt65*178.0 if(cand(m)%iflip.ne.0) bw=nts_jt65*178.0
if(diffhz.gt.-20.0 .and. diffhz.lt.bw+20.0) skip=.true. if(diffhz.gt.-0.03*bw .and. diffhz.lt.1.03*bw) skip=.true.
! write(*,3301) i,k,m,f0,cand(m)%f,diffhz,snr1,skip
!3301 format('=',3i5,f10.1,3f10.3,L3)
enddo enddo
if(skip) cycle if(skip) cycle
! write(*,3301) i,k,m,f0,diffhz,bw,db(snr1)
!3301 format('=A',3i5,f8.3,2f8.0,f8.2)
k=k+1 k=k+1
cand(k)%snr=snr1 cand(k)%snr=snr1
cand(k)%f=f0 cand(k)%f=f0
@ -99,6 +96,7 @@ subroutine get_candidates(ss,savg,xpol,nfa,nfb,nts_jt65,nts_q65,cand,ncand)
cand(k)%pol=sync(n)%pol cand(k)%pol=sync(n)%pol
cand(k)%ipol=sync(n)%ipol cand(k)%ipol=sync(n)%ipol
cand(k)%iflip=nint(flip) cand(k)%iflip=nint(flip)
cand(k)%indx=n
if(k.ge.MAX_CANDIDATES) exit if(k.ge.MAX_CANDIDATES) exit
enddo enddo
ncand=k ncand=k

View File

@ -19,7 +19,7 @@ int main(int argc, char *argv[])
QApplication a {argc, argv}; QApplication a {argc, argv};
// Override programs executable basename as application name. // Override programs executable basename as application name.
a.setApplicationName ("MAP65"); a.setApplicationName ("MAP65");
a.setApplicationVersion ("3.0.0-rc3"); a.setApplicationVersion ("3.0.0-rc4");
// switch off as we share an Info.plist file with WSJT-X // switch off as we share an Info.plist file with WSJT-X
a.setAttribute (Qt::AA_DontUseNativeMenuBar); a.setAttribute (Qt::AA_DontUseNativeMenuBar);
MainWindow w; MainWindow w;

View File

@ -520,6 +520,7 @@ void MainWindow::dataSink(int k)
static int nkhz; static int nkhz;
static int nfsample=96000; static int nfsample=96000;
static int nxpol=0; static int nxpol=0;
static int iRxState=0;
static float fgreen; static float fgreen;
static int ndiskdat; static int ndiskdat;
static int nb; static int nb;
@ -530,7 +531,6 @@ void MainWindow::dataSink(int k)
static float rejecty; static float rejecty;
static float slimit; static float slimit;
if(m_diskData) { if(m_diskData) {
ndiskdat=1; ndiskdat=1;
datcom_.ndiskdat=1; datcom_.ndiskdat=1;
@ -620,10 +620,23 @@ void MainWindow::dataSink(int k)
n=0; n=0;
} }
// if(ihsym == 280) { //For JT65, decode at t=52 s (also for old *.tf2/*.iq disk files) if(ihsym<280) iRxState=0;
if(ihsym == 302) { //For Q65, decode at t=56 s
if(iRxState==0 and ihsym>=280) { //Early decode, t=52 s
iRxState=1;
datcom_.newdat=1; datcom_.newdat=1;
datcom_.nagain=0; datcom_.nagain=0;
datcom_.nhsym=ihsym;
QDateTime t = QDateTime::currentDateTimeUtc();
m_dateTime=t.toString("yyyy-MMM-dd hh:mm");
decode(); //Start the decoder
}
if(iRxState<=1 and ihsym>=302) { //Decode at t=56 s (for Q65 and data from disk)
iRxState=2;
datcom_.newdat=1;
datcom_.nagain=0;
datcom_.nhsym=ihsym;
QDateTime t = QDateTime::currentDateTimeUtc(); QDateTime t = QDateTime::currentDateTimeUtc();
m_dateTime=t.toString("yyyy-MMM-dd hh:mm"); m_dateTime=t.toString("yyyy-MMM-dd hh:mm");
decode(); //Start the decoder decode(); //Start the decoder
@ -636,6 +649,7 @@ void MainWindow::dataSink(int k)
watcher2->setFuture(*future2); watcher2->setFuture(*future2);
} }
} }
soundInThread.m_dataSinkBusy=false; soundInThread.m_dataSinkBusy=false;
} }
@ -1107,15 +1121,14 @@ void MainWindow::diskDat() //diskDat()
m_diskData=true; m_diskData=true;
datcom_.newdat=1; datcom_.newdat=1;
// if(g_pWideGraph->m_bForceCenterFreq) datcom_.fcenter=g_pWideGraph->m_dForceCenterFreq;
// qDebug() << "aa" << datcom_.fcenter << g_pWideGraph->m_dForceCenterFreq
// << g_pWideGraph->m_bForceCenterFreq;
if(m_fs96000) hsym=2048.0*96000.0/11025.0; //Samples per JT65 half-symbol if(m_fs96000) hsym=2048.0*96000.0/11025.0; //Samples per JT65 half-symbol
if(!m_fs96000) hsym=2048.0*95238.1/11025.0; if(!m_fs96000) hsym=2048.0*95238.1/11025.0;
for(int i=0; i<304; i++) { // Do the half-symbol FFTs for(int i=0; i<304; i++) { // Do the half-symbol FFTs
int k = i*hsym + 2048.5; int k = i*hsym + 2048.5;
dataSink(k); dataSink(k);
while(m_decoderBusy) {
qApp->processEvents();
}
if(i%10 == 0) qApp->processEvents(); //Keep the GUI responsive if(i%10 == 0) qApp->processEvents(); //Keep the GUI responsive
} }
} }
@ -1248,6 +1261,9 @@ void MainWindow::freezeDecode(int n) //freezeDecode()
void MainWindow::decode() //decode() void MainWindow::decode() //decode()
{ {
ui->DecodeButton->setStyleSheet(m_pbdecoding_style1); ui->DecodeButton->setStyleSheet(m_pbdecoding_style1);
// QFile f("mockRTfiles.txt");
// if(datcom_.nagain==0 && (!m_diskData) && !f.exists()) {
if(datcom_.nagain==0 && (!m_diskData)) { if(datcom_.nagain==0 && (!m_diskData)) {
qint64 ms = QDateTime::currentMSecsSinceEpoch() % 86400000; qint64 ms = QDateTime::currentMSecsSinceEpoch() % 86400000;
int imin=ms/60000; int imin=ms/60000;
@ -1282,7 +1298,7 @@ void MainWindow::decode() //decode()
datcom_.ntol=m_tol; datcom_.ntol=m_tol;
datcom_.nxant=0; datcom_.nxant=0;
if(m_xpolx) datcom_.nxant=1; if(m_xpolx) datcom_.nxant=1;
if(datcom_.nutc < m_nutc0) m_map65RxLog |= 1; //Date and Time to all65.txt if(datcom_.nutc < m_nutc0) m_map65RxLog |= 1; //Date and Time to map65_rx.log
m_nutc0=datcom_.nutc; m_nutc0=datcom_.nutc;
datcom_.map65RxLog=m_map65RxLog; datcom_.map65RxLog=m_map65RxLog;
datcom_.nfsample=96000; datcom_.nfsample=96000;
@ -1303,7 +1319,9 @@ void MainWindow::decode() //decode()
memcpy(datcom_.mygrid, mgrid.toLatin1(), 6); memcpy(datcom_.mygrid, mgrid.toLatin1(), 6);
memcpy(datcom_.hiscall, hcall.toLatin1(), 12); memcpy(datcom_.hiscall, hcall.toLatin1(), 12);
memcpy(datcom_.hisgrid, hgrid.toLatin1(), 6); memcpy(datcom_.hisgrid, hgrid.toLatin1(), 6);
memcpy(datcom_.datetime, m_dateTime.toLatin1(), 20); memcpy(datcom_.datetime, m_dateTime.toLatin1(), 17);
datcom_.junk1=1234;
datcom_.junk2=5678;
//newdat=1 ==> this is new data, must do the big FFT //newdat=1 ==> this is new data, must do the big FFT
//nagain=1 ==> decode only at fQSO +/- Tol //nagain=1 ==> decode only at fQSO +/- Tol
@ -1317,9 +1335,10 @@ void MainWindow::decode() //decode()
from += noffset; from += noffset;
size -= noffset; size -= noffset;
} }
memcpy(to, from, qMin(mem_m65.size(), size)); memcpy(to, from, qMin(mem_m65.size(), size-8));
datcom_.nagain=0; datcom_.nagain=0;
datcom_.ndiskdat=0; datcom_.ndiskdat=0;
m_map65RxLog=0;
m_call3Modified=false; m_call3Modified=false;
QFile lockFile(m_appDir + "/.lock"); // Allow m65 to start QFile lockFile(m_appDir + "/.lock"); // Allow m65 to start
@ -1371,7 +1390,8 @@ void MainWindow::readFromStdout() //readFromStdout
lab7->setText (QString {"Avg: %1"}.arg (m_nsum)); lab7->setText (QString {"Avg: %1"}.arg (m_nsum));
if(m_modeQ65>0) m_wide_graph_window->setDecodeFinished(); if(m_modeQ65>0) m_wide_graph_window->setDecodeFinished();
} }
if(t.indexOf("<DecodeFinished>") >= 0) {
if((t.indexOf("<EarlyFinished>") >= 0) or (t.indexOf("<DecodeFinished>") >= 0)) {
if(m_widebandDecode) { if(m_widebandDecode) {
m_messages_window->setText(m_messagesText,m_bandmapText); m_messages_window->setText(m_messagesText,m_bandmapText);
m_band_map_window->setText(m_bandmapText); m_band_map_window->setText(m_bandmapText);
@ -1379,10 +1399,12 @@ void MainWindow::readFromStdout() //readFromStdout
} }
QFile lockFile(m_appDir + "/.lock"); QFile lockFile(m_appDir + "/.lock");
lockFile.open(QIODevice::ReadWrite); lockFile.open(QIODevice::ReadWrite);
if(t.indexOf("<DecodeFinished>") >= 0) {
m_map65RxLog=0;
m_startAnother=m_loopall;
}
ui->DecodeButton->setStyleSheet(""); ui->DecodeButton->setStyleSheet("");
decodeBusy(false); decodeBusy(false);
m_map65RxLog=0;
m_startAnother=m_loopall;
return; return;
} }
@ -1531,11 +1553,13 @@ void MainWindow::guiUpdate()
msgsent[22]=0; msgsent[22]=0;
if(m_restart) { if(m_restart) {
QString t=" Tx " + m_modeTx + " ";
t=t.left(11);
QFile f("map65_tx.log"); QFile f("map65_tx.log");
f.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append); f.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append);
QTextStream out(&f); QTextStream out(&f);
out << QDateTime::currentDateTimeUtc().toString("yyyy-MMM-dd hh:mm") out << QDateTime::currentDateTimeUtc().toString("yyyy-MMM-dd hh:mm")
<< " Tx message: " << QString::fromLatin1(msgsent) << t << QString::fromLatin1(msgsent)
#if QT_VERSION >= QT_VERSION_CHECK (5, 15, 0) #if QT_VERSION >= QT_VERSION_CHECK (5, 15, 0)
<< Qt::endl << Qt::endl
#else #else
@ -1560,11 +1584,13 @@ void MainWindow::guiUpdate()
m_transmitting=true; m_transmitting=true;
m_wide_graph_window->enableSetRxHardware(false); m_wide_graph_window->enableSetRxHardware(false);
QString t=" Tx " + m_modeTx + " ";
t=t.left(11);
QFile f("map65_tx.log"); QFile f("map65_tx.log");
f.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append); f.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append);
QTextStream out(&f); QTextStream out(&f);
out << QDateTime::currentDateTimeUtc().toString("yyyy-MMM-dd hh:mm") out << QDateTime::currentDateTimeUtc().toString("yyyy-MMM-dd hh:mm")
<< " Tx message: " << QString::fromLatin1(msgsent) << t << QString::fromLatin1(msgsent)
#if QT_VERSION >= QT_VERSION_CHECK (5, 15, 0) #if QT_VERSION >= QT_VERSION_CHECK (5, 15, 0)
<< Qt::endl << Qt::endl
#else #else

View File

@ -1,6 +1,6 @@
set (SAMPLE_FILES set (SAMPLE_FILES
FT4/000000_000002.wav FT4/000000_000002.wav
FT8/181201_180245.wav FT8/210703_133430.wav
FST4+FST4W/210115_0058.wav FST4+FST4W/210115_0058.wav
FST4+FST4W/201230_0300.wav FST4+FST4W/201230_0300.wav
MSK144/181211_120500.wav MSK144/181211_120500.wav
@ -17,7 +17,6 @@ set (SAMPLE_FILES
JT65/JT65B/000000_0005.wav JT65/JT65B/000000_0005.wav
JT65/JT65B/000000_0006.wav JT65/JT65B/000000_0006.wav
JT65/JT65B/000000_0007.wav JT65/JT65B/000000_0007.wav
JT9+JT65/130610_2343.wav
JT9/130418_1742.wav JT9/130418_1742.wav
MSK144/181211_120500.wav MSK144/181211_120500.wav
MSK144/181211_120800.wav MSK144/181211_120800.wav

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -453,10 +453,6 @@ void DisplayText::displayDecodedText(DecodedText const& decodedText, QString con
// if enabled add the DXCC entity and B4 status to the end of the // if enabled add the DXCC entity and B4 status to the end of the
// preformated text line t1 // preformated text line t1
auto currentMode = mode; auto currentMode = mode;
if ("JT9+JT65" == mode)
{
currentMode = decodedText.isJT65 () ? "JT65" : "JT9";
}
message = appendWorkedB4 (message, decodedText.CQersCall(), dxGrid, &bg, &fg message = appendWorkedB4 (message, decodedText.CQersCall(), dxGrid, &bg, &fg
, logBook, currentBand, currentMode, extra); , logBook, currentBand, currentMode, extra);
} }

View File

@ -1028,9 +1028,9 @@ void MainWindow::not_GA_warning_message ()
MessageBox::critical_message (this, MessageBox::critical_message (this,
"This is a pre-release version of WSJT-X 2.5.0 made\n" "This is a pre-release version of WSJT-X 2.5.0 made\n"
"available for testing purposes. By design it will\n" "available for testing purposes. By design it will\n"
"be nonfunctional after Aug 31, 2021."); "be nonfunctional after Sept 30, 2021.");
auto now = QDateTime::currentDateTimeUtc (); auto now = QDateTime::currentDateTimeUtc ();
if (now >= QDateTime {{2021, 8, 31}, {23, 59, 59, 999}, Qt::UTC}) { if (now >= QDateTime {{2021, 9, 30}, {23, 59, 59, 999}, Qt::UTC}) {
Q_EMIT finished (); Q_EMIT finished ();
} }
} }
@ -4942,12 +4942,13 @@ void MainWindow::processMessage (DecodedText const& message, Qt::KeyboardModifie
return; return;
} }
bool bContestOK=(m_mode=="FT4" or m_mode=="FT8" or m_mode=="Q65" or m_mode=="MSK144");
if(message_words.size () > 3 // enough fields for a normal message if(message_words.size () > 3 // enough fields for a normal message
&& (message_words.at(1).contains(m_baseCall) || "DE" == message_words.at(1)) && (message_words.at(1).contains(m_baseCall) || "DE" == message_words.at(1))
&& (message_words.at(2).contains(qso_partner_base_call) or m_bDoubleClicked && (message_words.at(2).contains(qso_partner_base_call) or m_bDoubleClicked
or bEU_VHF_w2 or (m_QSOProgress==CALLING))) { or bEU_VHF_w2 or (m_QSOProgress==CALLING))) {
if(message_words.at(3).contains(grid_regexp) and SpecOp::EU_VHF!=m_config.special_op_id()) { if(message_words.at(3).contains(grid_regexp) and SpecOp::EU_VHF!=m_config.special_op_id()) {
if(SpecOp::NA_VHF==m_config.special_op_id() or SpecOp::WW_DIGI==m_config.special_op_id()){ if((SpecOp::NA_VHF==m_config.special_op_id() or SpecOp::WW_DIGI==m_config.special_op_id()) and bContestOK){
setTxMsg(3); setTxMsg(3);
m_QSOProgress=ROGER_REPORT; m_QSOProgress=ROGER_REPORT;
} else { } else {
@ -5604,8 +5605,8 @@ void MainWindow::lookup()
break; break;
} }
QString t=QString(c); QString t=QString(c);
if(t.indexOf(hisCall)==0) { int i1=t.indexOf(",");
int i1=t.indexOf(","); if(t.left(i1)==hisCall) {
QString hisgrid=t.mid(i1+1,6); QString hisgrid=t.mid(i1+1,6);
i1=hisgrid.indexOf(","); i1=hisgrid.indexOf(",");
if(i1>0) { if(i1>0) {
@ -6454,13 +6455,21 @@ void MainWindow::on_actionQ65_triggered()
ui->lh_decodes_headings_label->setText("UTC dB DT Freq " + tr ("Message")); ui->lh_decodes_headings_label->setText("UTC dB DT Freq " + tr ("Message"));
ui->rh_decodes_headings_label->setText("UTC dB DT Freq " + tr ("Message")); ui->rh_decodes_headings_label->setText("UTC dB DT Freq " + tr ("Message"));
statusChanged(); statusChanged();
if(SpecOp::NONE < m_config.special_op_id()) {
ui->labDXped->setVisible(true); if (SpecOp::NONE < m_config.special_op_id () && SpecOp::FOX > m_config.special_op_id ()) {
ui->labDXped->setText("Contest ?"); QString t0="";
} else { if(SpecOp::NA_VHF==m_config.special_op_id()) t0="NA VHF";
ui->labDXped->setVisible(false); if(SpecOp::EU_VHF==m_config.special_op_id()) t0="EU VHF";
ui->labDXped->setText(""); if(SpecOp::FIELD_DAY==m_config.special_op_id()) t0="Field Day";
if(t0=="") {
ui->labDXped->setVisible(false);
} else {
ui->labDXped->setVisible(true);
ui->labDXped->setText(t0);
}
on_contest_log_action_triggered();
} }
} }
void MainWindow::on_actionMSK144_triggered() void MainWindow::on_actionMSK144_triggered()

View File

@ -530,9 +530,8 @@ void CPlotter::DrawOverlay() //DrawOverlay()
int yh=5; int yh=5;
int yTxTop=12; int yTxTop=12;
int yRxBottom=yTxTop + 2*yh + 4; int yRxBottom=yTxTop + 2*yh + 4;
if(m_mode=="JT9" or m_mode=="JT65" or m_mode=="JT9+JT65" if(m_mode=="JT9" or m_mode=="JT65" or m_mode=="Q65" or m_mode=="FT8"
or m_mode=="Q65" or m_mode=="FT8" or m_mode=="FT4" or m_mode=="FT4" or m_mode.startsWith("FST4")) {
or m_mode.startsWith("FST4")) {
if(m_mode=="FST4" and !m_bSingleDecode) { if(m_mode=="FST4" and !m_bSingleDecode) {
x1=XfromFreq(m_nfa); x1=XfromFreq(m_nfa);
@ -580,9 +579,8 @@ void CPlotter::DrawOverlay() //DrawOverlay()
} }
} }
if(m_mode=="JT9" or m_mode=="JT65" or m_mode=="JT9+JT65" or if(m_mode=="JT9" or m_mode=="JT65" or m_mode.mid(0,4)=="WSPR" or m_mode=="Q65"
m_mode.mid(0,4)=="WSPR" or m_mode=="Q65" or m_mode=="FT8" or m_mode=="FT8" or m_mode=="FT4" or m_mode.startsWith("FST4")) {
or m_mode=="FT4" or m_mode.startsWith("FST4")) {
painter0.setPen(penRed); painter0.setPen(penRed);
x1=XfromFreq(m_txFreq); x1=XfromFreq(m_txFreq);
x2=XfromFreq(m_txFreq+bw); x2=XfromFreq(m_txFreq+bw);
@ -597,15 +595,6 @@ void CPlotter::DrawOverlay() //DrawOverlay()
painter0.drawLine(x2,yTxTop,x2,yTxTop+yh); painter0.drawLine(x2,yTxTop,x2,yTxTop+yh);
} }
if(m_mode=="JT9+JT65") {
QPen pen2(Qt::blue, 3); //Mark the JT65 | JT9 divider
painter0.setPen(pen2);
x1=XfromFreq(m_fMin);
if(x1<2) x1=2;
x2=x1+30;
painter0.drawLine(x1,8,x1,28);
}
if(m_dialFreq>10.13 and m_dialFreq< 10.15 and m_mode.mid(0,4)!="WSPR") { if(m_dialFreq>10.13 and m_dialFreq< 10.15 and m_mode.mid(0,4)!="WSPR") {
float f1=1.0e6*(10.1401 - m_dialFreq); float f1=1.0e6*(10.1401 - m_dialFreq);
float f2=f1+200.0; float f2=f1+200.0;

View File

@ -292,7 +292,7 @@ void WideGraph::setTxFreq(int n) //setTxFreq
void WideGraph::setMode(QString mode) //setMode void WideGraph::setMode(QString mode) //setMode
{ {
m_mode=mode; m_mode=mode;
ui->fSplitSpinBox->setEnabled(m_mode=="JT9+JT65" or m_mode.startsWith("FST4")); ui->fSplitSpinBox->setEnabled(m_mode.startsWith("FST4"));
ui->widePlot->setMode(mode); ui->widePlot->setMode(mode);
ui->widePlot->DrawOverlay(); ui->widePlot->DrawOverlay();
ui->widePlot->update(); ui->widePlot->update();
@ -363,7 +363,7 @@ void WideGraph::setRxBand (QString const& band)
else else
{ {
ui->fSplitSpinBox->setValue (m_fMinPerBand.value (band, 2500).toUInt ()); ui->fSplitSpinBox->setValue (m_fMinPerBand.value (band, 2500).toUInt ());
ui->fSplitSpinBox->setEnabled (m_mode=="JT9+JT65" or m_mode.startsWith("FST4")); ui->fSplitSpinBox->setEnabled (m_mode.startsWith("FST4"));
} }
ui->widePlot->setRxBand(band); ui->widePlot->setRxBand(band);
setRxRange (); setRxRange ();